A game about forced loneliness, made by TACStudios
1using System; 2using System.Linq; 3using UnityEngine.Assertions; 4 5namespace UnityEngine.Rendering 6{ 7 /// <summary> 8 /// Debug UI Class 9 /// </summary> 10 public partial class DebugUI 11 { 12 /// <summary> 13 /// A column of checkboxes for enabling and disabling flags. 14 /// </summary> 15 [Flags] 16 public enum Flags 17 { 18 /// <summary> 19 /// None. 20 /// </summary> 21 None = 0, 22 /// <summary> 23 /// This widget is Editor only. 24 /// </summary> 25 EditorOnly = 1 << 1, 26 /// <summary> 27 /// This widget is Runtime only. 28 /// </summary> 29 RuntimeOnly = 1 << 2, 30 /// <summary> 31 /// This widget will force the Debug Editor Window refresh. 32 /// </summary> 33 EditorForceUpdate = 1 << 3, 34 /// <summary> 35 /// This widget will appear in the section "Frequently Used" 36 /// </summary> 37 FrequentlyUsed = 1 << 4 38 39 } 40 41 /// <summary> 42 /// Base class for all debug UI widgets. 43 /// </summary> 44 public abstract class Widget 45 { 46 // Set to null until it's added to a panel, be careful 47 /// <summary> 48 /// Panels containing the widget. 49 /// </summary> 50 protected Panel m_Panel; 51 52 /// <summary> 53 /// Panels containing the widget. 54 /// </summary> 55 public virtual Panel panel 56 { 57 get { return m_Panel; } 58 internal set { m_Panel = value; } 59 } 60 61 /// <summary> 62 /// Parent container. 63 /// </summary> 64 protected IContainer m_Parent; 65 66 /// <summary> 67 /// Parent container. 68 /// </summary> 69 public virtual IContainer parent 70 { 71 get { return m_Parent; } 72 internal set { m_Parent = value; } 73 } 74 75 /// <summary> 76 /// Flags for the widget. 77 /// </summary> 78 public Flags flags { get; set; } 79 80 /// <summary> 81 /// Display name. 82 /// </summary> 83 public string displayName { get; set; } 84 85 /// <summary> 86 /// Tooltip. 87 /// </summary> 88 public string tooltip { get; set; } 89 90 /// <summary> 91 /// Path of the widget. 92 /// </summary> 93 public string queryPath { get; private set; } 94 95 /// <summary> 96 /// True if the widget is Editor only. 97 /// </summary> 98 public bool isEditorOnly => flags.HasFlag(Flags.EditorOnly); 99 100 /// <summary> 101 /// True if the widget is Runtime only. 102 /// </summary> 103 public bool isRuntimeOnly => flags.HasFlag(Flags.RuntimeOnly); 104 105 /// <summary> 106 /// True if the widget is inactive in the editor (i.e. widget is runtime only and the application is not 'Playing'). 107 /// </summary> 108 public bool isInactiveInEditor => (isRuntimeOnly && !Application.isPlaying); 109 110 /// <summary> 111 /// Optional delegate that can be used to conditionally hide widgets at runtime (e.g. due to state of other widgets). 112 /// </summary> 113 public Func<bool> isHiddenCallback; 114 115 /// <summary> 116 /// If <see cref="isHiddenCallback">shouldHideDelegate</see> has been set and returns true, the widget is hidden from the UI. 117 /// </summary> 118 public bool isHidden => isHiddenCallback?.Invoke() ?? false; 119 120 internal virtual void GenerateQueryPath() 121 { 122 queryPath = displayName.Trim(); 123 124 if (m_Parent != null) 125 queryPath = m_Parent.queryPath + " -> " + queryPath; 126 } 127 128 /// <summary> 129 /// Returns the hash code of the widget. 130 /// </summary> 131 /// <returns>The hash code of the widget.</returns> 132 public override int GetHashCode() 133 { 134 return queryPath.GetHashCode() ^ isHidden.GetHashCode(); 135 } 136 137 /// <summary> 138 /// Helper struct to allow more compact initialization of widgets. 139 /// </summary> 140 public struct NameAndTooltip 141 { 142 /// <summary> 143 /// The name 144 /// </summary> 145 public string name; 146 /// <summary> 147 /// The tooltip 148 /// </summary> 149 public string tooltip; 150 } 151 152 /// <summary> 153 /// Helper setter to allow more compact initialization of widgets. 154 /// </summary> 155 public NameAndTooltip nameAndTooltip 156 { 157 set 158 { 159 displayName = value.name; 160 tooltip = value.tooltip; 161 } 162 } 163 } 164 165 /// <summary> 166 /// Interface for widgets that can contain other widgets. 167 /// </summary> 168 public interface IContainer 169 { 170 /// <summary> 171 /// List of children of the container. 172 /// </summary> 173 ObservableList<Widget> children { get; } 174 175 /// <summary> 176 /// Display name of the container. 177 /// </summary> 178 string displayName { get; set; } 179 180 /// <summary> 181 /// Path of the container. 182 /// </summary> 183 string queryPath { get; } 184 } 185 186 /// <summary> 187 /// Any widget that implements this will be considered for serialization (only if the setter is set and thus is not read-only) 188 /// </summary> 189 public interface IValueField 190 { 191 /// <summary> 192 /// Return the value of the field. 193 /// </summary> 194 /// <returns>Value of the field.</returns> 195 object GetValue(); 196 197 /// <summary> 198 /// Set the value of the field. 199 /// </summary> 200 /// <param name="value">Input value.</param> 201 void SetValue(object value); 202 203 /// <summary> 204 /// Function used to validate the value when setting it. 205 /// </summary> 206 /// <param name="value">Input value.</param> 207 /// <returns>Validated value.</returns> 208 object ValidateValue(object value); 209 } 210 211 // Miscellaneous 212 /// <summary> 213 /// Button widget. 214 /// </summary> 215 public class Button : Widget 216 { 217 /// <summary> 218 /// Action performed by the button. 219 /// </summary> 220 public Action action { get; set; } 221 } 222 223 /// <summary> 224 /// A field that displays a read-only value. 225 /// </summary> 226 public class Value : Widget 227 { 228 /// <summary> 229 /// Getter for the Value. 230 /// </summary> 231 public Func<object> getter { get; set; } 232 233 /// <summary> 234 /// Refresh rate for the read-only value (runtime only) 235 /// </summary> 236 public float refreshRate = 0.1f; 237 238 /// <summary> 239 /// Optional C# numeric format string, using following syntax: "{0[:numericFormatString]}" 240 /// See https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings 241 /// and https://docs.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting 242 /// Example: 123.45678 with formatString "{0:F2} ms" --> "123.45 ms". 243 /// </summary> 244 public string formatString = null; 245 246 /// <summary> 247 /// Constructor. 248 /// </summary> 249 public Value() 250 { 251 displayName = ""; 252 } 253 254 /// <summary> 255 /// Returns the value of the widget. 256 /// </summary> 257 /// <returns>The value of the widget.</returns> 258 public virtual object GetValue() 259 { 260 Assert.IsNotNull(getter); 261 return getter(); 262 } 263 264 /// <summary> 265 /// Returns the formatted value string for display purposes. 266 /// </summary> 267 /// <param name="value">Value to be formatted.</param> 268 /// <returns>The formatted value string.</returns> 269 public virtual string FormatString(object value) 270 { 271 return string.IsNullOrEmpty(formatString) ? $"{value}" : string.Format(formatString, value); 272 } 273 } 274 275 /// <summary> 276 /// A progress bar that displays values between 0% and 100%. 277 /// </summary> 278 public class ProgressBarValue : Value 279 { 280 /// <summary> 281 /// Minimum value. 282 /// </summary> 283 public float min = 0f; 284 /// <summary> 285 /// Maximum value. 286 /// </summary> 287 public float max = 1f; 288 289 /// <summary> 290 /// Get the current progress string, remapped to [0, 1] range, representing the progress between min and max. 291 /// </summary> 292 /// <param name="value">Value to be formatted.</param> 293 /// <returns>Formatted progress percentage string between 0% and 100%.</returns> 294 public override string FormatString(object value) 295 { 296 static float Remap01(float v, float x0, float y0) => (v - x0) / (y0 - x0); 297 298 float clamped = Mathf.Clamp((float)value, min, max); 299 float percentage = Remap01(clamped, min, max); 300 return $"{percentage:P1}"; 301 } 302 } 303 304 /// <summary> 305 /// An array of read-only values that Unity displays in a horizontal row. 306 /// </summary> 307 public class ValueTuple : Widget 308 { 309 /// <summary> 310 /// Number of elements in the tuple. 311 /// </summary> 312 public int numElements 313 { 314 get 315 { 316 Assert.IsTrue(values.Length > 0); 317 return values.Length; 318 } 319 } 320 321 /// <summary> 322 /// Value widgets. 323 /// </summary> 324 public Value[] values; 325 326 /// <summary> 327 /// Refresh rate for the read-only values (runtime only) 328 /// </summary> 329 public float refreshRate => values.FirstOrDefault()?.refreshRate ?? 0.1f; 330 331 /// <summary> 332 /// The currently pinned element index, or -1 if none are pinned. 333 /// </summary> 334 public int pinnedElementIndex = -1; 335 } 336 } 337}