A game about forced loneliness, made by TACStudios
at master 926 lines 39 kB view raw
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using UnityEngine; 5using UnityEngine.Rendering; 6 7namespace UnityEditor.Rendering 8{ 9 /// <summary> 10 /// Builtin Drawer for Value Debug Items. 11 /// </summary> 12 [DebugUIDrawer(typeof(DebugUI.Value))] 13 public sealed class DebugUIDrawerValue : DebugUIWidgetDrawer<DebugUI.Value> 14 { 15 /// <summary> 16 /// Does the field of the given type 17 /// </summary> 18 /// <param name="rect">The rect to draw the field</param> 19 /// <param name="label">The label for the field</param> 20 /// <param name="field">The widget</param> 21 protected override void DoGUI(Rect rect, GUIContent label, DebugUI.Value field) 22 { 23 EditorGUI.LabelField(rect, label, EditorGUIUtility.TrTextContent(field.FormatString(field.GetValue()))); 24 } 25 } 26 27 /// <summary> 28 /// Builtin Drawer for ValueTuple Debug Items. 29 /// </summary> 30 [DebugUIDrawer(typeof(DebugUI.ValueTuple))] 31 public sealed class DebugUIDrawerValueTuple : DebugUIWidgetDrawer<DebugUI.ValueTuple> 32 { 33 /// <summary> 34 /// Does the field of the given type 35 /// </summary> 36 /// <param name="rect">The rect to draw the field</param> 37 /// <param name="label">The label for the field</param> 38 /// <param name="field">The widget</param> 39 protected override void DoGUI(Rect rect, GUIContent label, DebugUI.ValueTuple field) 40 { 41 EditorGUI.PrefixLabel(rect, label); 42 43 // Following layout should match DebugUIDrawerFoldout to make column labels align 44 Rect drawRect = GUILayoutUtility.GetLastRect(); 45 46 int indent = EditorGUI.indentLevel; 47 EditorGUI.indentLevel = 0; //be at left of rects 48 for (int i = 0; i < field.numElements; i++) 49 { 50 var columnRect = drawRect; 51 columnRect.x += EditorGUIUtility.labelWidth + i * DebugWindow.Styles.foldoutColumnWidth; 52 columnRect.width = DebugWindow.Styles.foldoutColumnWidth; 53 var value = field.values[i].GetValue(); 54 55 var style = EditorStyles.label; 56 if (Convert.ToSingle(value) == 0) 57 style = DebugWindow.Styles.labelWithZeroValueStyle; 58 59 EditorGUI.LabelField(columnRect, field.values[i].FormatString(value), style); 60 } 61 EditorGUI.indentLevel = indent; 62 } 63 } 64 65 /// <summary> 66 /// Builtin Drawer for ProgressBarValue Debug Items. 67 /// </summary> 68 [DebugUIDrawer(typeof(DebugUI.ProgressBarValue))] 69 public sealed class DebugUIDrawerProgressBarValue : DebugUIWidgetDrawer<DebugUI.ProgressBarValue> 70 { 71 /// <summary> 72 /// Does the field of the given type 73 /// </summary> 74 /// <param name="rect">The rect to draw the field</param> 75 /// <param name="label">The label for the field</param> 76 /// <param name="field">The widget</param> 77 protected override void DoGUI(Rect rect, GUIContent label, DebugUI.ProgressBarValue field) 78 { 79 var progressBarRect = EditorGUI.PrefixLabel(rect, label); 80 float value = (float)field.GetValue(); 81 EditorGUI.ProgressBar(progressBarRect, value, field.FormatString(value)); 82 } 83 } 84 85 /// <summary> 86 /// Builtin Drawer for Button Debug Items. 87 /// </summary> 88 [DebugUIDrawer(typeof(DebugUI.Button))] 89 public sealed class DebugUIDrawerButton : DebugUIWidgetDrawer<DebugUI.Button> 90 { 91 /// <summary> 92 /// Does the field of the given type 93 /// </summary> 94 /// <param name="rect">The rect to draw the field</param> 95 /// <param name="label">The label for the field</param> 96 /// <param name="field">The widget</param> 97 protected override void DoGUI(Rect rect, GUIContent label, DebugUI.Button field) 98 { 99 rect = EditorGUI.IndentedRect(rect); 100 if (GUI.Button(rect, label, EditorStyles.miniButton)) 101 { 102 if (field.action != null) 103 field.action(); 104 } 105 } 106 } 107 108 /// <summary> 109 /// Builtin Drawer for Boolean Debug Items. 110 /// </summary> 111 [DebugUIDrawer(typeof(DebugUI.BoolField))] 112 public sealed class DebugUIDrawerBoolField : DebugUIFieldDrawer<bool, DebugUI.BoolField, DebugStateBool> 113 { 114 /// <summary> 115 /// Does the field of the given type 116 /// </summary> 117 /// <param name="rect">The rect to draw the field</param> 118 /// <param name="label">The label for the field</param> 119 /// <param name="field">The field</param> 120 /// <param name="state">The state</param> 121 /// <returns>The value</returns> 122 protected override bool DoGUI(Rect rect, GUIContent label, DebugUI.BoolField field, DebugStateBool state) 123 { 124 return EditorGUI.Toggle(rect, label, field.GetValue()); 125 } 126 } 127 128 /// <summary> 129 /// Builtin Drawer for History Boolean Debug Items. 130 /// </summary> 131 [DebugUIDrawer(typeof(DebugUI.HistoryBoolField))] 132 public sealed class DebugUIDrawerHistoryBoolField : DebugUIFieldDrawer<bool, DebugUI.HistoryBoolField, DebugStateBool> 133 { 134 /// <summary> 135 /// Does the field of the given type 136 /// </summary> 137 /// <param name="rect">The rect to draw the field</param> 138 /// <param name="label">The label for the field</param> 139 /// <param name="field">The field</param> 140 /// <param name="state">The state</param> 141 /// <returns>The current value from the UI</returns> 142 protected override bool DoGUI(Rect rect, GUIContent label, DebugUI.HistoryBoolField field, DebugStateBool state) 143 { 144 var labelRect = rect; 145 labelRect.width = EditorGUIUtility.labelWidth; 146 const int oneValueWidth = 70; 147 var valueRects = new Rect[field.historyDepth + 1]; 148 for (int i = 0; i < field.historyDepth + 1; i++) 149 { 150 valueRects[i] = rect; 151 valueRects[i].x += EditorGUIUtility.labelWidth + i * oneValueWidth; 152 valueRects[i].width = oneValueWidth; 153 } 154 EditorGUI.LabelField(labelRect, label); 155 int indent = EditorGUI.indentLevel; 156 EditorGUI.indentLevel = 0; //be at left of rects 157 bool value = EditorGUI.Toggle(valueRects[0], field.GetValue()); 158 using (new EditorGUI.DisabledScope(true)) 159 { 160 for (int i = 0; i < field.historyDepth; i++) 161 EditorGUI.Toggle(valueRects[i + 1], field.GetHistoryValue(i)); 162 } 163 EditorGUI.indentLevel = indent; 164 return value; 165 } 166 } 167 168 /// <summary> 169 /// Builtin Drawer for Integer Debug Items. 170 /// </summary> 171 [DebugUIDrawer(typeof(DebugUI.IntField))] 172 public sealed class DebugUIDrawerIntField : DebugUIFieldDrawer<int, DebugUI.IntField, DebugStateInt> 173 { 174 /// <summary> 175 /// Does the field of the given type 176 /// </summary> 177 /// <param name="rect">The rect to draw the field</param> 178 /// <param name="label">The label for the field</param> 179 /// <param name="field">The field</param> 180 /// <param name="state">The state</param> 181 /// <returns>The current value from the UI</returns> 182 protected override int DoGUI(Rect rect, GUIContent label, DebugUI.IntField field, DebugStateInt state) 183 { 184 return field.min != null && field.max != null 185 ? EditorGUI.IntSlider(rect, label, field.GetValue(), field.min(), field.max()) 186 : EditorGUI.IntField(rect, label, field.GetValue()); 187 } 188 } 189 190 /// <summary> 191 /// Builtin Drawer for Unsigned Integer Debug Items. 192 /// </summary> 193 [DebugUIDrawer(typeof(DebugUI.UIntField))] 194 public sealed class DebugUIDrawerUIntField : DebugUIFieldDrawer<uint, DebugUI.UIntField, DebugStateUInt> 195 { 196 /// <summary> 197 /// Does the field of the given type 198 /// </summary> 199 /// <param name="rect">The rect to draw the field</param> 200 /// <param name="label">The label for the field</param> 201 /// <param name="field">The field</param> 202 /// <param name="state">The state</param> 203 /// <returns>The current value from the UI</returns> 204 protected override uint DoGUI(Rect rect, GUIContent label, DebugUI.UIntField field, DebugStateUInt state) 205 { 206 // No UIntField so we need to max to 0 ourselves or the value will wrap around 207 int tmp = field.min != null && field.max != null 208 ? EditorGUI.IntSlider(rect, label, Mathf.Max(0, (int)field.GetValue()), Mathf.Max(0, (int)field.min()), Mathf.Max(0, (int)field.max())) 209 : EditorGUI.IntField(rect, label, Mathf.Max(0, (int)field.GetValue())); 210 211 return (uint)Mathf.Max(0, tmp); 212 } 213 } 214 215 /// <summary> 216 /// Builtin Drawer for Float Debug Items. 217 /// </summary> 218 [DebugUIDrawer(typeof(DebugUI.FloatField))] 219 public sealed class DebugUIDrawerFloatField : DebugUIFieldDrawer<float, DebugUI.FloatField, DebugStateFloat> 220 { 221 /// <summary> 222 /// Does the field of the given type 223 /// </summary> 224 /// <param name="rect">The rect to draw the field</param> 225 /// <param name="label">The label for the field</param> 226 /// <param name="field">The field</param> 227 /// <param name="state">The state</param> 228 /// <returns>The current value from the UI</returns> 229 protected override float DoGUI(Rect rect, GUIContent label, DebugUI.FloatField field, DebugStateFloat state) 230 { 231 return field.min != null && field.max != null 232 ? EditorGUI.Slider(rect, label, field.GetValue(), field.min(), field.max()) 233 : EditorGUI.FloatField(rect, label, field.GetValue()); 234 } 235 } 236 237 /// <summary> 238 /// Builtin Drawer for Enum Debug Items. 239 /// </summary> 240 [DebugUIDrawer(typeof(DebugUI.EnumField))] 241 public sealed class DebugUIDrawerEnumField : DebugUIFieldDrawer<int, DebugUI.EnumField, DebugStateEnum> 242 { 243 /// <summary> 244 /// Does the field of the given type 245 /// </summary> 246 /// <param name="rect">The rect to draw the field</param> 247 /// <param name="label">The label for the field</param> 248 /// <param name="field">The field</param> 249 /// <param name="state">The state</param> 250 /// <returns>The current value from the UI</returns> 251 protected override int DoGUI(Rect rect, GUIContent label, DebugUI.EnumField field, DebugStateEnum state) 252 { 253 int index = Mathf.Max(0, field.currentIndex); // Fallback just in case, we may be handling sub/sectioned enums here 254 int value = field.GetValue(); 255 256 if (field.enumNames == null || field.enumValues == null) 257 { 258 EditorGUI.LabelField(rect, label, "Can't draw an empty enumeration."); 259 } 260 else if (field.enumNames.Length != field.enumValues.Length) 261 { 262 EditorGUI.LabelField(rect, label, "Invalid data"); 263 } 264 else 265 { 266 index = EditorGUI.IntPopup(rect, label, index, field.enumNames, field.indexes); 267 value = field.enumValues[index]; 268 } 269 270 return value; 271 } 272 } 273 274 /// <summary> 275 /// Builtin Drawer for Object Popup Fields Items. 276 /// </summary> 277 [DebugUIDrawer(typeof(DebugUI.ObjectPopupField))] 278 public sealed class DebugUIDrawerObjectPopupField : DebugUIFieldDrawer<UnityEngine.Object, DebugUI.ObjectPopupField, DebugStateObject> 279 { 280 /// <summary> 281 /// Does the field of the given type 282 /// </summary> 283 /// <param name="rect">The rect to draw the field</param> 284 /// <param name="label">The label for the field</param> 285 /// <param name="field">The field</param> 286 /// <param name="state">The state</param> 287 /// <returns>The current value from the UI</returns> 288 protected override UnityEngine.Object DoGUI(Rect rect, GUIContent label, DebugUI.ObjectPopupField field, DebugStateObject state) 289 { 290 var selectedValue = field.GetValue(); 291 292 rect = EditorGUI.PrefixLabel(rect, label); 293 294 var elements = field.getObjects(); 295 if (elements?.Any() ?? false) 296 { 297 var elementsArrayNames = elements.Select(e => e.name).ToArray(); 298 var elementsArrayIndices = Enumerable.Range(0, elementsArrayNames.Length).ToArray(); 299 var selectedIndex = selectedValue != null ? Array.IndexOf(elementsArrayNames, selectedValue.name) : 0; 300 var newSelectedIndex = EditorGUI.IntPopup(rect, selectedIndex, elementsArrayNames, elementsArrayIndices); 301 if (selectedIndex != newSelectedIndex) 302 selectedValue = elements.ElementAt(newSelectedIndex); 303 } 304 else 305 { 306 EditorGUI.LabelField(rect, "Can't draw an empty enumeration."); 307 } 308 309 return selectedValue; 310 } 311 } 312 313 /// <summary> 314 /// Builtin Drawer for History Enum Debug Items. 315 /// </summary> 316 [DebugUIDrawer(typeof(DebugUI.HistoryEnumField))] 317 public sealed class DebugUIDrawerHistoryEnumField : DebugUIFieldDrawer<int, DebugUI.HistoryEnumField, DebugStateEnum> 318 { 319 /// <summary> 320 /// Does the field of the given type 321 /// </summary> 322 /// <param name="rect">The rect to draw the field</param> 323 /// <param name="label">The label for the field</param> 324 /// <param name="field">The field</param> 325 /// <param name="state">The state</param> 326 /// <returns>The current value from the UI</returns> 327 protected override int DoGUI(Rect rect, GUIContent label, DebugUI.HistoryEnumField field, DebugStateEnum state) 328 { 329 int index = -1; 330 int value = field.GetValue(); 331 if (field.enumNames == null || field.enumValues == null) 332 { 333 EditorGUILayout.LabelField("Can't draw an empty enumeration."); 334 } 335 else 336 { 337 index = field.currentIndex; 338 339 // Fallback just in case, we may be handling sub/sectionned enums here 340 if (index < 0) 341 index = 0; 342 343 var labelRect = rect; 344 labelRect.width = EditorGUIUtility.labelWidth; 345 const int oneValueWidth = 70; 346 var valueRects = new Rect[field.historyDepth + 1]; 347 for (int i = 0; i < field.historyDepth + 1; i++) 348 { 349 valueRects[i] = rect; 350 valueRects[i].x += EditorGUIUtility.labelWidth + i * oneValueWidth; 351 valueRects[i].width = oneValueWidth; 352 } 353 EditorGUI.LabelField(labelRect, label); 354 int indent = EditorGUI.indentLevel; 355 EditorGUI.indentLevel = 0; //be at left of rects 356 index = EditorGUI.IntPopup(valueRects[0], index, field.enumNames, field.indexes); 357 value = field.enumValues[index]; 358 using (new EditorGUI.DisabledScope(true)) 359 { 360 for (int i = 0; i < field.historyDepth; i++) 361 EditorGUI.IntPopup(valueRects[i + 1], field.GetHistoryValue(i), field.enumNames, field.indexes); 362 } 363 EditorGUI.indentLevel = indent; 364 365 value = field.enumValues[index]; 366 } 367 368 return value; 369 } 370 } 371 372 /// <summary> 373 /// Builtin Drawer for Bitfield Debug Items. 374 /// </summary> 375 [DebugUIDrawer(typeof(DebugUI.BitField))] 376 public sealed class DebugUIDrawerBitField : DebugUIFieldDrawer<Enum, DebugUI.BitField, DebugStateFlags> 377 { 378 /// <summary> 379 /// Does the field of the given type 380 /// </summary> 381 /// <param name="rect">The rect to draw the field</param> 382 /// <param name="label">The label for the field</param> 383 /// <param name="field">The field</param> 384 /// <param name="state">The state</param> 385 /// <returns>The current value from the UI</returns> 386 protected override Enum DoGUI(Rect rect, GUIContent label, DebugUI.BitField field, DebugStateFlags state) 387 { 388 Enum value = field.GetValue(); 389 390 // Skip first element (with value 0) because EditorGUI.MaskField adds a 'Nothing' field anyway 391 var enumNames = new string[field.enumNames.Length - 1]; 392 for (int i = 0; i < enumNames.Length; i++) 393 enumNames[i] = field.enumNames[i + 1].text; 394 var index = EditorGUI.MaskField(rect, label, (int)Convert.ToInt32(value), enumNames); 395 value = Enum.Parse(value.GetType(), index.ToString()) as Enum; 396 397 return value; 398 } 399 } 400 401 402 /// <summary> 403 /// Builtin Drawer for Maskfield Debug Items. 404 /// </summary> 405 [DebugUIDrawer(typeof(DebugUI.MaskField))] 406 public sealed class DebugUIDrawerMaskField : DebugUIFieldDrawer<uint, DebugUI.MaskField, DebugStateUInt> 407 { 408 /// <summary> 409 /// Does the field of the given type 410 /// </summary> 411 /// <param name="rect">The rect to draw the field</param> 412 /// <param name="label">The label for the field</param> 413 /// <param name="field">The field</param> 414 /// <param name="state">The state</param> 415 /// <returns>The current value from the UI</returns> 416 protected override uint DoGUI(Rect rect, GUIContent label, DebugUI.MaskField field, DebugStateUInt state) 417 { 418 uint value = field.GetValue(); 419 420 var enumNames = new string[field.enumNames.Length]; 421 for (int i = 0; i < enumNames.Length; i++) 422 enumNames[i] = field.enumNames[i].text; 423 var mask = EditorGUI.MaskField(rect, label, (int)value, enumNames); 424 425 return (uint)mask; 426 } 427 } 428 429 /// <summary> 430 /// Builtin Drawer for Foldout Debug Items. 431 /// </summary> 432 [DebugUIDrawer(typeof(DebugUI.Foldout))] 433 public sealed class DebugUIDrawerFoldout : DebugUIDrawer 434 { 435 const int k_HeaderVerticalMargin = 2; 436 static void DisplayColumns(Rect drawRect, List<GUIContent> rowContents) 437 { 438 drawRect.x += EditorGUIUtility.labelWidth; 439 drawRect.width = DebugWindow.Styles.foldoutColumnWidth; 440 441 int indent = EditorGUI.indentLevel; 442 EditorGUI.indentLevel = 0; //be at left of rects 443 for (int i = 0; i < rowContents.Count; i++) 444 { 445 EditorGUI.LabelField(drawRect, rowContents[i], EditorStyles.miniBoldLabel); 446 447 // Offset the rect to the next possible column 448 drawRect.x += DebugWindow.Styles.foldoutColumnWidth; 449 } 450 EditorGUI.indentLevel = indent; 451 } 452 453 /// <summary> 454 /// Implement this to execute processing before UI rendering. 455 /// </summary> 456 /// <param name="widget">Widget that is going to be rendered.</param> 457 /// <param name="state">Debug State associated with the Debug Item.</param> 458 public override void Begin(DebugUI.Widget widget, DebugState state) 459 { 460 var w = Cast<DebugUI.Foldout>(widget); 461 var s = Cast<DebugStateBool>(state); 462 463 var title = EditorGUIUtility.TrTextContent(w.displayName, w.tooltip); 464 465 Action<GenericMenu> fillContextMenuAction = null; 466 467 if (w.contextMenuItems != null) 468 { 469 fillContextMenuAction = menu => 470 { 471 foreach (var item in w.contextMenuItems) 472 { 473 menu.AddItem(EditorGUIUtility.TrTextContent(item.displayName), false, () => item.action.Invoke()); 474 } 475 }; 476 } 477 478 bool previousValue = (bool)w.GetValue(); 479 bool value = CoreEditorUtils.DrawHeaderFoldout(title, previousValue, isTitleHeader: w.isHeader, customMenuContextAction: fillContextMenuAction); 480 if (previousValue != value) 481 Apply(w, s, value); 482 483 EditorGUI.indentLevel++; 484 } 485 486 /// <summary> 487 /// OnGUI implementation for Foldout DebugUIDrawer. 488 /// </summary> 489 /// <param name="widget">DebugUI Widget.</param> 490 /// <param name="state">Debug State associated with the Debug Item.</param> 491 /// <returns>The state of the widget.</returns> 492 public override bool OnGUI(DebugUI.Widget widget, DebugState state) 493 { 494 var w = Cast<DebugUI.Foldout>(widget); 495 if (w.opened && w.columnLabels != null) 496 { 497 var drawRect = PrepareControlRect(EditorGUIUtility.singleLineHeight); 498 drawRect.x = 0; 499 DisplayColumns(drawRect, w.rowContents); 500 } 501 return w.opened; 502 } 503 504 /// <summary> 505 /// End implementation for Foldout DebugUIDrawer. 506 /// </summary> 507 /// <param name="widget">DebugUI Widget.</param> 508 /// <param name="state">Debug State associated with the Debug Item.</param> 509 public override void End(DebugUI.Widget widget, DebugState state) 510 { 511 EditorGUI.indentLevel--; 512 var w = Cast<DebugUI.Foldout>(widget); 513 if (w.isHeader) 514 GUILayout.Space(k_HeaderVerticalMargin); 515 } 516 } 517 518 /// <summary> 519 /// Builtin Drawer for Color Debug Items. 520 /// </summary> 521 [DebugUIDrawer(typeof(DebugUI.ColorField))] 522 public sealed class DebugUIDrawerColorField : DebugUIFieldDrawer<Color, DebugUI.ColorField, DebugStateColor> 523 { 524 /// <summary> 525 /// Does the field of the given type 526 /// </summary> 527 /// <param name="rect">The rect to draw the field</param> 528 /// <param name="label">The label for the field</param> 529 /// <param name="field">The field</param> 530 /// <param name="state">The state</param> 531 /// <returns>The current value from the UI</returns> 532 protected override Color DoGUI(Rect rect, GUIContent label, DebugUI.ColorField field, DebugStateColor state) 533 { 534 return EditorGUI.ColorField(rect, label, field.GetValue(), field.showPicker, field.showAlpha, field.hdr); 535 } 536 } 537 538 /// <summary> 539 /// Builtin Drawer for Vector2 Debug Items. 540 /// </summary> 541 [DebugUIDrawer(typeof(DebugUI.Vector2Field))] 542 public sealed class DebugUIDrawerVector2Field : DebugUIFieldDrawer<Vector2, DebugUI.Vector2Field, DebugStateVector2> 543 { 544 /// <summary> 545 /// Does the field of the given type 546 /// </summary> 547 /// <param name="rect">The rect to draw the field</param> 548 /// <param name="label">The label for the field</param> 549 /// <param name="field">The field</param> 550 /// <param name="state">The state</param> 551 /// <returns>The current value from the UI</returns> 552 protected override Vector2 DoGUI(Rect rect, GUIContent label, DebugUI.Vector2Field field, DebugStateVector2 state) 553 { 554 return EditorGUILayout.Vector2Field(label, field.GetValue()); 555 } 556 } 557 558 /// <summary> 559 /// Builtin Drawer for Vector3 Debug Items. 560 /// </summary> 561 [DebugUIDrawer(typeof(DebugUI.Vector3Field))] 562 public sealed class DebugUIDrawerVector3Field : DebugUIFieldDrawer<Vector3, DebugUI.Vector3Field, DebugStateVector3> 563 { 564 /// <summary> 565 /// Does the field of the given type 566 /// </summary> 567 /// <param name="rect">The rect to draw the field</param> 568 /// <param name="label">The label for the field</param> 569 /// <param name="field">The field</param> 570 /// <param name="state">The state</param> 571 /// <returns>The current value from the UI</returns> 572 protected override Vector3 DoGUI(Rect rect, GUIContent label, DebugUI.Vector3Field field, DebugStateVector3 state) 573 { 574 return EditorGUILayout.Vector3Field(label, field.GetValue()); 575 } 576 } 577 578 /// <summary> 579 /// Builtin Drawer for Vector4 Debug Items. 580 /// </summary> 581 [DebugUIDrawer(typeof(DebugUI.Vector4Field))] 582 public sealed class DebugUIDrawerVector4Field : DebugUIFieldDrawer<Vector4, DebugUI.Vector4Field, DebugStateVector4> 583 { 584 /// <summary> 585 /// Does the field of the given type 586 /// </summary> 587 /// <param name="rect">The rect to draw the field</param> 588 /// <param name="label">The label for the field</param> 589 /// <param name="field">The field</param> 590 /// <param name="state">The state</param> 591 /// <returns>The current value from the UI</returns> 592 protected override Vector4 DoGUI(Rect rect, GUIContent label, DebugUI.Vector4Field field, DebugStateVector4 state) 593 { 594 return EditorGUILayout.Vector4Field(label, field.GetValue()); 595 } 596 } 597 598 /// <summary> 599 /// Builtin Drawer for <see cref="DebugUI.ObjectField"/> items. 600 /// </summary> 601 [DebugUIDrawer(typeof(DebugUI.ObjectField))] 602 public sealed class DebugUIDrawerObjectField : DebugUIFieldDrawer<UnityEngine.Object, DebugUI.ObjectField, DebugStateObject> 603 { 604 /// <summary> 605 /// Does the field of the given type 606 /// </summary> 607 /// <param name="rect">The rect to draw the field</param> 608 /// <param name="label">The label for the field</param> 609 /// <param name="field">The field</param> 610 /// <param name="state">The state</param> 611 /// <returns>The current value from the UI</returns> 612 protected override UnityEngine.Object DoGUI(Rect rect, GUIContent label, DebugUI.ObjectField field, DebugStateObject state) 613 { 614 return EditorGUI.ObjectField(rect, label, field.GetValue(), field.type, true); 615 } 616 } 617 618 /// <summary> 619 /// Builtin Drawer for <see cref="DebugUI.ObjectListField"/> Items. 620 /// </summary> 621 [DebugUIDrawer(typeof(DebugUI.ObjectListField))] 622 public sealed class DebugUIDrawerObjectListField : DebugUIDrawer 623 { 624 /// <summary> 625 /// Implement this to execute UI rendering. 626 /// </summary> 627 /// <param name="widget">Widget that is going to be rendered.</param> 628 /// <param name="state">Debug State associated with the Debug Item.</param> 629 /// <returns>Returns the state of the widget.</returns> 630 public override bool OnGUI(DebugUI.Widget widget, DebugState state) 631 { 632 var w = Cast<DebugUI.ObjectListField>(widget); 633 var objects = w.GetValue(); 634 635 float height = Math.Max(objects != null ? objects.Length : 0, 1) * DebugWindow.Styles.singleRowHeight; 636 var rect = PrepareControlRect(height); 637 638 rect = EditorGUI.PrefixLabel(rect, EditorGUIUtility.TrTextContent(widget.displayName)); 639 640 EditorGUI.BeginChangeCheck(); 641 DoObjectList(rect, w, objects); 642 if (EditorGUI.EndChangeCheck()) 643 Apply(w, state, objects); 644 645 return true; 646 } 647 648 internal static void DoObjectList(Rect rect, DebugUI.ObjectListField widget, UnityEngine.Object[] objects) 649 { 650 if (objects == null || objects.Length == 0) 651 { 652 EditorGUI.LabelField(rect, GUIContent.none, EditorGUIUtility.TrTextContent("Empty")); 653 return; 654 } 655 656 rect.height = EditorGUIUtility.singleLineHeight; 657 for (int i = 0; i < objects.Length; i++) 658 { 659 objects[i] = EditorGUI.ObjectField(rect, GUIContent.none, objects[i], widget.type, true); 660 rect.y += DebugWindow.Styles.singleRowHeight; 661 } 662 } 663 } 664 665 /// <summary> 666 /// Builtin Drawer for MessageBox Items. 667 /// </summary> 668 [DebugUIDrawer(typeof(DebugUI.MessageBox))] 669 public sealed class DebugUIDrawerMessageBox : DebugUIDrawer 670 { 671 /// <summary> 672 /// Implement this to execute UI rendering. 673 /// </summary> 674 /// <param name="widget">Widget that is going to be rendered.</param> 675 /// <param name="state">Debug State associated with the Debug Item.</param> 676 /// <returns>Returns the state of the widget.</returns> 677 public override bool OnGUI(DebugUI.Widget widget, DebugState state) 678 { 679 var w = Cast<DebugUI.MessageBox>(widget); 680 681 var type = w.style switch 682 { 683 DebugUI.MessageBox.Style.Info => MessageType.Info, 684 DebugUI.MessageBox.Style.Warning => MessageType.Warning, 685 DebugUI.MessageBox.Style.Error => MessageType.Error, 686 _ => MessageType.None 687 }; 688 689 EditorGUILayout.HelpBox(w.message, type); 690 691 return true; 692 } 693 } 694 695 /// <summary> 696 /// Builtin Drawer for Container Debug Items. 697 /// </summary> 698 [DebugUIDrawer(typeof(DebugUI.Container))] 699 public sealed class DebugUIDrawerContainer : DebugUIDrawer 700 { 701 /// <summary> 702 /// Implement this to execute processing before UI rendering. 703 /// </summary> 704 /// <param name="widget">Widget that is going to be rendered.</param> 705 /// <param name="state">Debug State associated with the Debug Item.</param> 706 public override void Begin(DebugUI.Widget widget, DebugState state) 707 { 708 var w = Cast<DebugUI.Container>(widget); 709 if (!w.hideDisplayName) 710 EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent(widget.displayName, widget.tooltip), EditorStyles.boldLabel); 711 712 EditorGUI.indentLevel++; 713 } 714 715 /// <summary> 716 /// Implement this to execute processing after UI rendering. 717 /// </summary> 718 /// <param name="widget">Widget that is going to be rendered.</param> 719 /// <param name="state">Debug State associated with the Debug Item.</param> 720 public override void End(DebugUI.Widget widget, DebugState state) 721 { 722 EditorGUI.indentLevel--; 723 } 724 } 725 726 /// <summary> 727 /// Builtin Drawer for Horizontal Box Debug Items. 728 /// </summary> 729 [DebugUIDrawer(typeof(DebugUI.HBox))] 730 public sealed class DebugUIDrawerHBox : DebugUIDrawer 731 { 732 /// <summary> 733 /// Implement this to execute processing before UI rendering. 734 /// </summary> 735 /// <param name="widget">Widget that is going to be rendered.</param> 736 /// <param name="state">Debug State associated with the Debug Item.</param> 737 public override void Begin(DebugUI.Widget widget, DebugState state) 738 { 739 EditorGUILayout.BeginHorizontal(); 740 } 741 /// <summary> 742 /// Implement this to execute processing after UI rendering. 743 /// </summary> 744 /// <param name="widget">Widget that is going to be rendered.</param> 745 /// <param name="state">Debug State associated with the Debug Item.</param> 746 public override void End(DebugUI.Widget widget, DebugState state) 747 { 748 EditorGUILayout.EndHorizontal(); 749 } 750 } 751 752 /// <summary> 753 /// Builtin Drawer for Vertical Box Debug Items. 754 /// </summary> 755 [DebugUIDrawer(typeof(DebugUI.VBox))] 756 public sealed class DebugUIDrawerVBox : DebugUIDrawer 757 { 758 /// <summary> 759 /// Implement this to execute processing before UI rendering. 760 /// </summary> 761 /// <param name="widget">Widget that is going to be rendered.</param> 762 /// <param name="state">Debug State associated with the Debug Item.</param> 763 public override void Begin(DebugUI.Widget widget, DebugState state) 764 { 765 EditorGUILayout.BeginVertical(); 766 } 767 768 /// <summary> 769 /// Implement this to execute processing after UI rendering. 770 /// </summary> 771 /// <param name="widget">Widget that is going to be rendered.</param> 772 /// <param name="state">Debug State associated with the Debug Item.</param> 773 public override void End(DebugUI.Widget widget, DebugState state) 774 { 775 EditorGUILayout.EndVertical(); 776 } 777 } 778 779 /// <summary> 780 /// Builtin Drawer for Table Debug Items. 781 /// </summary> 782 [DebugUIDrawer(typeof(DebugUI.Table))] 783 public sealed class DebugUIDrawerTable : DebugUIDrawer 784 { 785 /// <summary> 786 /// Implement this to execute UI rendering. 787 /// </summary> 788 /// <param name="widget">Widget that is going to be rendered.</param> 789 /// <param name="state">Debug State associated with the Debug Item.</param> 790 /// <returns>Returns the state of the widget.</returns> 791 public override bool OnGUI(DebugUI.Widget widget, DebugState state) 792 { 793 const float k_ScrollBarHeight = 15; 794 795 var w = Cast<DebugUI.Table>(widget); 796 var header = w.Header; 797 var visible = header.state.visibleColumns; 798 799 float contentHeight = 0.0f; 800 foreach (DebugUI.Table.Row row in w.children) 801 contentHeight += row != null ? GetRowHeight(row, visible) : EditorGUIUtility.singleLineHeight; 802 803 // Put some space before the array 804 PrepareControlRect(EditorGUIUtility.singleLineHeight * 0.5f); 805 806 // Draw an outline around the table 807 var rect = EditorGUI.IndentedRect(PrepareControlRect(header.height + contentHeight + k_ScrollBarHeight)); 808 rect = DrawOutline(rect); 809 810 // Compute rects 811 var headerRect = new Rect(rect.x, rect.y, rect.width, header.height); 812 var contentRect = new Rect(rect.x, headerRect.yMax, rect.width, rect.height - headerRect.height); 813 var viewRect = new Rect(contentRect.x, contentRect.y, header.state.widthOfAllVisibleColumns, contentRect.height); 814 var rowRect = contentRect; 815 viewRect.height -= k_ScrollBarHeight; 816 817 // Show header 818 header.OnGUI(headerRect, Mathf.Max(w.scroll.x, 0f)); 819 820 // Show array content 821 w.scroll = GUI.BeginScrollView(contentRect, w.scroll, viewRect); 822 { 823 var columns = header.state.columns; 824 for (int r = 0; r < w.children.Count; r++) 825 { 826 var row = Cast<DebugUI.Container>(w.children[r]); 827 rowRect.x = contentRect.x; 828 rowRect.width = columns[0].width; 829 rowRect.height = (row is DebugUI.Table.Row tableRow) ? GetRowHeight(tableRow, visible) : EditorGUIUtility.singleLineHeight; 830 831 rowRect.xMin += 2; 832 rowRect.xMax -= 2; 833 EditorGUI.LabelField(rowRect, GUIContent.none, EditorGUIUtility.TrTextContent(row.displayName), DebugWindow.Styles.centeredLeft); 834 rowRect.xMin -= 2; 835 rowRect.xMax += 2; 836 837 using (new EditorGUI.DisabledScope(w.isReadOnly)) 838 { 839 for (int c = 1; c < visible.Length; c++) 840 { 841 rowRect.x += rowRect.width; 842 rowRect.width = columns[visible[c]].width; 843 if (!row.isHidden) 844 DisplayChild(rowRect, row.children[visible[c] - 1]); 845 } 846 rowRect.y += rowRect.height; 847 } 848 } 849 } 850 GUI.EndScrollView(false); 851 852 return false; 853 } 854 855 internal float GetRowHeight(DebugUI.Table.Row row, int[] visibleColumns) 856 { 857 float height = EditorGUIUtility.singleLineHeight; 858 for (int c = 1; c < visibleColumns.Length; c++) 859 { 860 var child = row.children[visibleColumns[c] - 1] as DebugUI.ObjectListField; 861 if (child == null || child.GetValue() == null) 862 continue; 863 height = Mathf.Max(height, child.GetValue().Length * DebugWindow.Styles.singleRowHeight); 864 } 865 return height; 866 } 867 868 internal Rect DrawOutline(Rect rect) 869 { 870 if (Event.current.type != EventType.Repaint) 871 return rect; 872 873 float size = 1.0f; 874 var color = EditorGUIUtility.isProSkin ? new Color(0.12f, 0.12f, 0.12f, 1.333f) : new Color(0.6f, 0.6f, 0.6f, 1.333f); 875 876 Color orgColor = GUI.color; 877 GUI.color = GUI.color * color; 878 GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width, size), EditorGUIUtility.whiteTexture); 879 GUI.DrawTexture(new Rect(rect.x, rect.yMax - size, rect.width, size), EditorGUIUtility.whiteTexture); 880 GUI.DrawTexture(new Rect(rect.x, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture); 881 GUI.DrawTexture(new Rect(rect.xMax - size, rect.y + 1, size, rect.height - 2 * size), EditorGUIUtility.whiteTexture); 882 883 GUI.color = orgColor; 884 return new Rect(rect.x + size, rect.y + size, rect.width - 2 * size, rect.height - 2 * size); 885 } 886 887 internal void DisplayChild(Rect rect, DebugUI.Widget child) 888 { 889 rect.xMin += 2; 890 rect.xMax -= 2; 891 892 if (child.isHidden) 893 { 894 EditorGUI.LabelField(rect, "-"); 895 } 896 else 897 { 898 if (child.GetType() == typeof(DebugUI.Value)) 899 { 900 var widget = Cast<DebugUI.Value>(child); 901 EditorGUI.LabelField(rect, GUIContent.none, EditorGUIUtility.TrTextContent(widget.GetValue().ToString())); 902 } 903 else if (child.GetType() == typeof(DebugUI.ColorField)) 904 { 905 var widget = Cast<DebugUI.ColorField>(child); 906 EditorGUI.ColorField(rect, GUIContent.none, widget.GetValue(), false, widget.showAlpha, widget.hdr); 907 } 908 else if (child.GetType() == typeof(DebugUI.BoolField)) 909 { 910 var widget = Cast<DebugUI.BoolField>(child); 911 EditorGUI.Toggle(rect, GUIContent.none, widget.GetValue()); 912 } 913 else if (child.GetType() == typeof(DebugUI.ObjectField)) 914 { 915 var widget = Cast<DebugUI.ObjectField>(child); 916 EditorGUI.ObjectField(rect, GUIContent.none, widget.GetValue(), widget.type, true); 917 } 918 else if (child.GetType() == typeof(DebugUI.ObjectListField)) 919 { 920 var widget = Cast<DebugUI.ObjectListField>(child); 921 DebugUIDrawerObjectListField.DoObjectList(rect, widget, widget.GetValue()); 922 } 923 } 924 } 925 } 926}