暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

PostNormalizedVectorDrawer.cs 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using UnityEditor;
  5. using UnityEngine;
  6. using UnityObject = UnityEngine.Object;
  7. namespace Unity.Mathematics.Editor
  8. {
  9. [CustomPropertyDrawer(typeof(PostNormalizeAttribute))]
  10. class PostNormalizedVectorDrawer : PrimitiveVectorDrawer
  11. {
  12. static class Content
  13. {
  14. public static readonly string tooltip =
  15. L10n.Tr("Values you enter will be post-normalized. You will see the normalized result if you change selection and view the values again.");
  16. }
  17. class VectorPropertyGUIData
  18. {
  19. const int k_MaxElements = 4;
  20. public readonly bool Valid;
  21. // parent property
  22. readonly SerializedProperty m_VectorProperty;
  23. // relative paths of element child properties
  24. readonly IReadOnlyList<string> m_ElementPaths;
  25. // the number of element child properties
  26. readonly int m_NumElements;
  27. // per child property; value is null if there are multiple different values
  28. readonly double?[] m_PreNormalizedValues;
  29. // per target; used to revert actual values for each object after displaying pre-normalized values
  30. readonly Dictionary<SerializedProperty, double4> m_PostNormalizedValues = new Dictionary<SerializedProperty, double4>();
  31. public VectorPropertyGUIData(SerializedProperty property)
  32. {
  33. m_VectorProperty = property;
  34. var parentPath = m_VectorProperty.propertyPath;
  35. var i = 0;
  36. var elementPaths = new List<string>(k_MaxElements);
  37. var iterator = m_VectorProperty.Copy();
  38. while (iterator.Next(true) && iterator.propertyPath.StartsWith(parentPath))
  39. {
  40. if (i >= k_MaxElements || iterator.propertyType != SerializedPropertyType.Float)
  41. return;
  42. elementPaths.Add(iterator.propertyPath.Substring(parentPath.Length + 1));
  43. i++;
  44. }
  45. Valid = true;
  46. m_NumElements = elementPaths.Count;
  47. m_ElementPaths = elementPaths;
  48. m_PreNormalizedValues = elementPaths.Select(p => (double?)null).ToArray();
  49. UpdatePreNormalizedValues();
  50. UpdatePostNormalizedValues();
  51. }
  52. void UpdatePostNormalizedValues()
  53. {
  54. m_PostNormalizedValues.Clear();
  55. foreach (var target in m_VectorProperty.serializedObject.targetObjects)
  56. {
  57. var postNormalizedValue = new double4();
  58. var parentProperty = new SerializedObject(target).FindProperty(m_VectorProperty.propertyPath);
  59. for (var i = 0; i < m_NumElements; ++i)
  60. postNormalizedValue[i] = parentProperty.FindPropertyRelative(m_ElementPaths[i]).doubleValue;
  61. m_PostNormalizedValues[parentProperty] = postNormalizedValue;
  62. }
  63. }
  64. public void UpdatePreNormalizedValues()
  65. {
  66. for (var i = 0; i < m_NumElements; ++i)
  67. {
  68. var p = m_VectorProperty.FindPropertyRelative(m_ElementPaths[i]);
  69. m_PreNormalizedValues[i] = p.hasMultipleDifferentValues ? (double?)null : p.doubleValue;
  70. }
  71. }
  72. public void ApplyPreNormalizedValues()
  73. {
  74. m_VectorProperty.serializedObject.ApplyModifiedProperties();
  75. for (var i = 0; i < m_NumElements; ++i)
  76. {
  77. if (m_PreNormalizedValues[i] != null)
  78. m_VectorProperty.FindPropertyRelative(m_ElementPaths[i]).doubleValue = m_PreNormalizedValues[i].Value;
  79. }
  80. }
  81. public void UnapplyPreNormalizedValues()
  82. {
  83. foreach (var target in m_PostNormalizedValues)
  84. {
  85. target.Key.serializedObject.Update();
  86. for (var i = 0; i < m_NumElements; ++i)
  87. {
  88. target.Key.FindPropertyRelative(m_ElementPaths[i]).doubleValue = target.Value[i];
  89. target.Key.serializedObject.ApplyModifiedProperties();
  90. }
  91. }
  92. m_VectorProperty.serializedObject.Update();
  93. }
  94. public void PostNormalize(Func<double4, double4> normalize)
  95. {
  96. m_VectorProperty.serializedObject.ApplyModifiedProperties();
  97. foreach (var target in m_PostNormalizedValues)
  98. {
  99. target.Key.serializedObject.Update();
  100. var postNormalizedValue = new double4();
  101. for (var i = 0; i < m_NumElements; ++i)
  102. postNormalizedValue[i] = target.Key.FindPropertyRelative(m_ElementPaths[i]).doubleValue;
  103. postNormalizedValue = normalize(normalize(postNormalizedValue));
  104. for (var i = 0; i < m_NumElements; ++i)
  105. target.Key.FindPropertyRelative(m_ElementPaths[i]).doubleValue = postNormalizedValue[i];
  106. target.Key.serializedObject.ApplyModifiedProperties();
  107. }
  108. UpdatePostNormalizedValues();
  109. m_VectorProperty.serializedObject.Update();
  110. }
  111. public void RebuildIfDirty()
  112. {
  113. foreach (var target in m_PostNormalizedValues)
  114. {
  115. target.Key.serializedObject.Update();
  116. for (var i = 0; i < m_NumElements; ++i)
  117. {
  118. var serialized = target.Key.FindPropertyRelative(m_ElementPaths[i]).doubleValue;
  119. if (target.Value[i] != serialized)
  120. {
  121. UpdatePreNormalizedValues();
  122. UpdatePostNormalizedValues();
  123. return;
  124. }
  125. }
  126. }
  127. }
  128. }
  129. Dictionary<string, VectorPropertyGUIData> m_GUIDataPerPropertyPath = new Dictionary<string, VectorPropertyGUIData>();
  130. protected virtual SerializedProperty GetVectorProperty(SerializedProperty property)
  131. {
  132. return property;
  133. }
  134. protected virtual double4 Normalize(double4 value)
  135. {
  136. return math.normalizesafe(value);
  137. }
  138. VectorPropertyGUIData GetGUIData(SerializedProperty property)
  139. {
  140. VectorPropertyGUIData guiData;
  141. if (!m_GUIDataPerPropertyPath.TryGetValue(property.propertyPath, out guiData))
  142. {
  143. guiData = new VectorPropertyGUIData(GetVectorProperty(property));
  144. m_GUIDataPerPropertyPath[property.propertyPath] = guiData;
  145. }
  146. return guiData;
  147. }
  148. public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
  149. {
  150. return GetGUIData(property).Valid ? base.GetPropertyHeight(property, label) : EditorGUIUtility.singleLineHeight;
  151. }
  152. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
  153. {
  154. var guiData = GetGUIData(property);
  155. if (!guiData.Valid)
  156. {
  157. EditorGUI.HelpBox(
  158. EditorGUI.PrefixLabel(position, label),
  159. L10n.Tr($"{typeof(PostNormalizeAttribute).Name} only works with decimal vector types."),
  160. MessageType.None
  161. );
  162. return;
  163. }
  164. if (string.IsNullOrEmpty(label.tooltip))
  165. label.tooltip = Content.tooltip;
  166. guiData.RebuildIfDirty();
  167. guiData.ApplyPreNormalizedValues();
  168. EditorGUI.BeginChangeCheck();
  169. base.OnGUI(position, property, label);
  170. if (EditorGUI.EndChangeCheck())
  171. {
  172. guiData.UpdatePreNormalizedValues();
  173. guiData.PostNormalize(Normalize);
  174. }
  175. else
  176. {
  177. guiData.UnapplyPreNormalizedValues();
  178. }
  179. }
  180. }
  181. }