DummyInvokableDrawer.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. #if UNITY_EDITOR
  3. using UnityEditor;
  4. using UnityEngine;
  5. namespace Animancer.Editor
  6. {
  7. /// <summary>[Editor-Only] [Internal]
  8. /// A utility for drawing empty [<see cref="SerializeReference"/>] <see cref="IInvokable"/> fields.
  9. /// </summary>
  10. /// <remarks>
  11. /// Used to draw empty slots in <see cref="AnimancerEvent.Sequence.Serializable.Callbacks"/>
  12. /// which don't actually have a <see cref="SerializedProperty"/> of their own because
  13. /// the array is compacted to trim any <c>null</c> items from the end.
  14. /// </remarks>
  15. /// https://kybernetik.com.au/animancer/api/Animancer.Editor/DummyInvokableDrawer
  16. internal class DummyInvokableDrawer : ScriptableObject
  17. {
  18. /************************************************************************************************************************/
  19. [SerializeReference, Polymorphic]
  20. private IInvokable[] _Invokable;
  21. /************************************************************************************************************************/
  22. private static SerializedProperty _InvokableProperty;
  23. /// <summary>[Editor-Only] A static dummy <see cref="IInvokable"/>.</summary>
  24. private static SerializedProperty InvokableProperty
  25. {
  26. get
  27. {
  28. if (_InvokableProperty == null)
  29. {
  30. var instance = CreateInstance<DummyInvokableDrawer>();
  31. instance.hideFlags = HideFlags.HideInHierarchy | HideFlags.DontSave;
  32. var serializedObject = new SerializedObject(instance);
  33. _InvokableProperty = serializedObject.FindProperty(nameof(_Invokable));
  34. AssemblyReloadEvents.beforeAssemblyReload += () =>
  35. {
  36. serializedObject.Dispose();
  37. DestroyImmediate(instance);
  38. };
  39. }
  40. return _InvokableProperty;
  41. }
  42. }
  43. /************************************************************************************************************************/
  44. /// <summary>[Editor-Only] The GUI height required by <see cref="DoGUI"/>.</summary>
  45. public static float Height
  46. => AnimancerGUI.LineHeight;
  47. /************************************************************************************************************************/
  48. private static int _LastControlID;
  49. private static int _PropertyIndex;
  50. /// <summary>[Editor-Only] Draws the <see cref="InvokableProperty"/> GUI.</summary>
  51. public static bool DoGUI(
  52. ref Rect area,
  53. GUIContent label,
  54. SerializedProperty property,
  55. out object invokable)
  56. {
  57. var controlID = GUIUtility.GetControlID(FocusType.Passive);
  58. if (_LastControlID >= controlID)
  59. _PropertyIndex = 0;
  60. _LastControlID = controlID;
  61. var invokablesProperty = InvokableProperty;
  62. if (invokablesProperty.arraySize <= _PropertyIndex)
  63. invokablesProperty.arraySize = _PropertyIndex + 1;
  64. var invokableProperty = invokablesProperty.GetArrayElementAtIndex(_PropertyIndex);
  65. invokableProperty.prefabOverride = property.prefabOverride;
  66. _PropertyIndex++;
  67. label = EditorGUI.BeginProperty(area, label, property);
  68. EditorGUI.PropertyField(area, invokableProperty, label, false);
  69. EditorGUI.EndProperty();
  70. invokable = invokableProperty.managedReferenceValue;
  71. if (invokable == null)
  72. return false;
  73. invokableProperty.managedReferenceValue = null;
  74. return true;
  75. }
  76. /************************************************************************************************************************/
  77. }
  78. }
  79. #endif