ParametizedAnimancerStateDrawer.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2018-2024 Kybernetik //
  2. #if UNITY_EDITOR && UNITY_IMGUI
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. using UnityEngine;
  6. namespace Animancer.Editor
  7. {
  8. /// <summary>[Editor-Only] Draws the Inspector GUI for an <see cref="AnimancerState"/>.</summary>
  9. /// https://kybernetik.com.au/animancer/api/Animancer.Editor/ParametizedAnimancerStateDrawer_1
  10. [CustomGUI(typeof(ManualMixerState))]
  11. public class ParametizedAnimancerStateDrawer<T> : AnimancerStateDrawer<T>
  12. where T : AnimancerState, IParametizedState
  13. {
  14. /************************************************************************************************************************/
  15. /// <inheritdoc/>
  16. protected override void DoDetailsGUI()
  17. {
  18. base.DoDetailsGUI();
  19. if (!IsExpanded)
  20. return;
  21. EditorGUI.indentLevel++;
  22. var parameters = ListPool.Acquire<StateParameterDetails>();
  23. Value.GetParameters(parameters);
  24. DoParametersGUI(parameters);
  25. ListPool.Release(parameters);
  26. EditorGUI.indentLevel--;
  27. }
  28. /************************************************************************************************************************/
  29. /// <summary>Draws fields for all `parameters`.</summary>
  30. private void DoParametersGUI(List<StateParameterDetails> parameters)
  31. {
  32. if (parameters.Count == 0)
  33. return;
  34. var labelWidth = EditorGUIUtility.labelWidth;
  35. EditorGUIUtility.labelWidth -= AnimancerGUI.IndentSize;
  36. EditorGUI.BeginChangeCheck();
  37. for (int i = 0; i < parameters.Count; i++)
  38. parameters[i] = DoParameterGUI(i, parameters[i]);
  39. EditorGUIUtility.labelWidth = labelWidth;
  40. if (EditorGUI.EndChangeCheck())
  41. Value.SetParameters(parameters);
  42. }
  43. /************************************************************************************************************************/
  44. /// <summary>Draws fields for the `parameter`.</summary>
  45. private StateParameterDetails DoParameterGUI(int index, StateParameterDetails parameter)
  46. {
  47. var area = AnimancerGUI.LayoutSingleLineRect(AnimancerGUI.SpacingMode.Before);
  48. var indentLevel = EditorGUI.indentLevel;
  49. var labelWidth = EditorGUIUtility.labelWidth;
  50. var label = parameter.label;
  51. if (parameter.SupportsBinding && Value.Graph.HasParameters)
  52. {
  53. area = EditorGUI.IndentedRect(area);
  54. EditorGUI.indentLevel = 0;
  55. parameter = DoBindingGUI(ref area, index, parameter, ref label);
  56. }
  57. else
  58. {
  59. EditorGUIUtility.labelWidth += AnimancerGUI.IndentSize;
  60. }
  61. switch (parameter.type)
  62. {
  63. case AnimatorControllerParameterType.Float:
  64. parameter.value = EditorGUI.FloatField(area, label, (float)parameter.value);
  65. break;
  66. case AnimatorControllerParameterType.Int:
  67. parameter.value = EditorGUI.IntField(area, label, (int)parameter.value);
  68. break;
  69. case AnimatorControllerParameterType.Bool:
  70. parameter.value = EditorGUI.Toggle(area, label, (bool)parameter.value);
  71. break;
  72. case AnimatorControllerParameterType.Trigger:
  73. parameter.value = EditorGUI.Toggle(area, label, (bool)parameter.value, EditorStyles.radioButton);
  74. break;
  75. default:
  76. EditorGUI.LabelField(area, label, "Unsupported Type: " + parameter.type);
  77. break;
  78. }
  79. EditorGUI.indentLevel = indentLevel;
  80. EditorGUIUtility.labelWidth = labelWidth;
  81. return parameter;
  82. }
  83. /************************************************************************************************************************/
  84. /// <summary>Draws a dropdown for the `parameter`'s name binding.</summary>
  85. private StateParameterDetails DoBindingGUI(
  86. ref Rect area,
  87. int index,
  88. StateParameterDetails parameter,
  89. ref string fieldLabel)
  90. {
  91. if (!parameter.SupportsBinding)
  92. return parameter;
  93. var spacing = AnimancerGUI.StandardSpacing;
  94. float width;
  95. if (string.IsNullOrEmpty(parameter.name))
  96. {
  97. width = area.height + spacing;
  98. EditorGUIUtility.labelWidth -= width + AnimancerGUI.IndentSize + spacing;
  99. }
  100. else
  101. {
  102. width = EditorGUIUtility.labelWidth - AnimancerGUI.IndentSize;
  103. fieldLabel = "";
  104. }
  105. var labelArea = AnimancerGUI.StealFromLeft(
  106. ref area,
  107. width,
  108. spacing);
  109. using (var label = PooledGUIContent.Acquire(parameter.name))
  110. {
  111. if (EditorGUI.DropdownButton(labelArea, label, FocusType.Passive))
  112. ShowBindingSelectionMenu(labelArea, index, parameter.name);
  113. }
  114. return parameter;
  115. }
  116. /************************************************************************************************************************/
  117. /// <summary>Shows a context menu for selecting the parameter binding.</summary>
  118. private void ShowBindingSelectionMenu(Rect area, int index, string currentName)
  119. {
  120. var menu = new GenericMenu();
  121. menu.AddItem(
  122. new("None"),
  123. string.IsNullOrEmpty(currentName),
  124. () => SetParameterName(index, null));
  125. menu.AddSeparator("");
  126. foreach (var parameter in Value.Graph.Parameters)
  127. {
  128. if (parameter.ValueType != typeof(float))
  129. continue;
  130. var name = parameter.Key;
  131. menu.AddItem(
  132. new(name),
  133. name == currentName,
  134. () => SetParameterName(index, name));
  135. }
  136. menu.DropDown(area);
  137. }
  138. /************************************************************************************************************************/
  139. /// <summary>Sets the name binding of the specified parameter.</summary>
  140. private void SetParameterName(int index, string name)
  141. {
  142. var parameters = ListPool.Acquire<StateParameterDetails>();
  143. Value.GetParameters(parameters);
  144. var modify = parameters[index];
  145. modify.name = name;
  146. parameters[index] = modify;
  147. Value.SetParameters(parameters);
  148. ListPool.Release(parameters);
  149. }
  150. /************************************************************************************************************************/
  151. }
  152. }
  153. #endif