TransitionCollectionDrawer.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using TheraBytes.BetterUi.Editor.ThirdParty;
  8. using UnityEditor;
  9. using UnityEditorInternal;
  10. using UnityEngine;
  11. namespace TheraBytes.BetterUi.Editor
  12. {
  13. #if ODIN_INSPECTOR
  14. [Sirenix.OdinInspector.Editor.DrawerPriority(0, 0, 1)]
  15. #endif
  16. [CustomPropertyDrawer(typeof(List<Transitions>))]
  17. public class TransitionCollectionDrawer : PropertyDrawer
  18. {
  19. string[] stateNames;
  20. SerializedProperty listProperty;
  21. ReorderableListControl listEditor;
  22. IReorderableListAdaptor adaptor;
  23. public TransitionCollectionDrawer() { }
  24. public TransitionCollectionDrawer(Type containerObjectType,
  25. string fieldName = "betterTransitions",
  26. BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance)
  27. {
  28. var fieldInfo = containerObjectType.GetField(fieldName, bindingFlags);
  29. TryReadStateNames(fieldInfo);
  30. }
  31. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  32. {
  33. TryReadStateNames(base.fieldInfo);
  34. Draw(() => property);
  35. }
  36. public void Draw(Func<SerializedProperty> getProperty)
  37. {
  38. if(this.listProperty == null)
  39. {
  40. this.listProperty = getProperty();
  41. }
  42. if (adaptor == null)
  43. {
  44. adaptor = new SerializedPropertyAdaptor(listProperty);
  45. }
  46. if(stateNames == null)
  47. {
  48. var msg = string.Format(
  49. "No [TransitionStates(...)] or [DefaultTransitionStates] attribute defined for field <b>{0}</b>",
  50. listProperty.displayName);
  51. EditorGUILayout.HelpBox(msg, MessageType.Error);
  52. return;
  53. }
  54. if (listEditor == null)
  55. {
  56. listEditor = new ReorderableListControl(ReorderableListFlags.ShowSizeField);
  57. listEditor.ItemInserted += ItemInserted;
  58. }
  59. ReorderableListGUI.Title(listProperty.displayName);
  60. listEditor.Draw(adaptor);
  61. listProperty.serializedObject.ApplyModifiedProperties();
  62. }
  63. private bool TryReadStateNames(FieldInfo fieldInfo)
  64. {
  65. if (stateNames != null)
  66. return true;
  67. var attribute = fieldInfo.GetCustomAttributes(typeof(TransitionStatesAttribute), true)
  68. .FirstOrDefault() as TransitionStatesAttribute;
  69. if (attribute == null)
  70. return false;
  71. stateNames = attribute.States;
  72. return true;
  73. }
  74. private void ItemInserted(object sender, ItemInsertedEventArgs args)
  75. {
  76. var p = listProperty.GetArrayElementAtIndex(args.ItemIndex);
  77. var namesProp = p.FindPropertyRelative("stateNames");
  78. // unity copies the previous content.
  79. // so we need to fill the array only the first time.
  80. if (namesProp.arraySize >= stateNames.Length)
  81. return;
  82. for (int i = 0; i < stateNames.Length; i++)
  83. {
  84. namesProp.InsertArrayElementAtIndex(i);
  85. namesProp.serializedObject.ApplyModifiedPropertiesWithoutUndo();
  86. string name = stateNames[i];
  87. var elem = namesProp.GetArrayElementAtIndex(i);
  88. elem.stringValue = name;
  89. }
  90. namesProp.serializedObject.ApplyModifiedPropertiesWithoutUndo();
  91. }
  92. }
  93. }