暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.U2D.IK;
  5. namespace UnityEditor.U2D.IK
  6. {
  7. internal class IKGizmos : ScriptableSingleton<IKGizmos>
  8. {
  9. private static readonly int kTargetHashCode = "IkTarget".GetHashCode();
  10. private Color enabledColor = Color.green;
  11. private Color disabledColor = Color.grey;
  12. private const float kCircleHandleRadius = 0.1f;
  13. private const float kNodeRadius = 0.05f;
  14. private const float kDottedLineLength = 5f;
  15. private const float kFadeStart = 0.75f;
  16. private const float kFadeEnd = 1.75f;
  17. private Dictionary<IKChain2D, Vector3> m_ChainPositionOverrides = new Dictionary<IKChain2D, Vector3>();
  18. public bool isDragging { get; private set; }
  19. public void DoSolverGUI(Solver2D solver)
  20. {
  21. if (solver == null || !solver.isValid)
  22. return;
  23. IKManager2D manager = IKEditorManager.instance.FindManager(solver);
  24. if (!solver.isActiveAndEnabled || manager == null || !manager.isActiveAndEnabled)
  25. return;
  26. var solverData = manager.GetSolverEditorData(solver);
  27. if (!solverData.showGizmo)
  28. return;
  29. DrawSolver(solver, solverData);
  30. var allChainsHaveTargets = solver.allChainsHaveTargets;
  31. for (int i = 0; i < solver.chainCount; ++i)
  32. {
  33. var chain = solver.GetChain(i);
  34. if (chain == null)
  35. continue;
  36. if (allChainsHaveTargets)
  37. {
  38. if (!IsTargetTransformSelected(chain))
  39. DoTargetGUI(solver, chain);
  40. }
  41. else if(chain.target == null)
  42. DoIkPoseGUI(solver, chain);
  43. }
  44. if(GUIUtility.hotControl == 0)
  45. isDragging = false;
  46. }
  47. private void DoTargetGUI(Solver2D solver, IKChain2D chain)
  48. {
  49. int controlId = GUIUtility.GetControlID(kTargetHashCode, FocusType.Passive);
  50. var color = FadeFromChain(Color.white, chain);
  51. if (!isDragging && (color.a == 0f || !IsVisible(chain.target.position)))
  52. return;
  53. EditorGUI.BeginChangeCheck();
  54. Handles.color = color;
  55. var newPosition = Handles.Slider2D(controlId, chain.target.position, chain.target.forward, chain.target.up, chain.target.right, HandleUtility.GetHandleSize(chain.effector.position) * kCircleHandleRadius, Handles.CircleHandleCap, Vector2.zero);
  56. if (EditorGUI.EndChangeCheck())
  57. {
  58. if(!isDragging)
  59. {
  60. isDragging = true;
  61. IKEditorManager.instance.RegisterUndo(solver, "Move Target");
  62. }
  63. Undo.RecordObject(chain.target, "Move Target");
  64. chain.target.position = newPosition;
  65. }
  66. }
  67. private void DoIkPoseGUI(Solver2D solver, IKChain2D chain)
  68. {
  69. int controlId = GUIUtility.GetControlID(kTargetHashCode, FocusType.Passive);
  70. var color = FadeFromChain(Color.white, chain);
  71. if (!isDragging && (color.a == 0f || !IsVisible(chain.effector.position)))
  72. return;
  73. if (HandleUtility.nearestControl == controlId && Event.current.type == EventType.MouseDown && Event.current.button == 0)
  74. StoreSolverPositionOverrides(solver);
  75. EditorGUI.BeginChangeCheck();
  76. Handles.color = color;
  77. Vector3 newPosition = Handles.Slider2D(controlId, chain.effector.position, chain.effector.forward, chain.effector.up, chain.effector.right, HandleUtility.GetHandleSize(chain.effector.position) * kCircleHandleRadius, Handles.CircleHandleCap, Vector2.zero);
  78. if (EditorGUI.EndChangeCheck())
  79. {
  80. if(!isDragging)
  81. isDragging = true;
  82. IKEditorManager.instance.Record(solver, "IK Pose");
  83. SetSolverPositionOverrides();
  84. IKEditorManager.instance.SetChainPositionOverride(chain, newPosition);
  85. IKEditorManager.instance.UpdateSolverImmediate(solver, true);
  86. }
  87. }
  88. private void StoreSolverPositionOverrides(Solver2D solver)
  89. {
  90. Debug.Assert(solver.allChainsHaveTargets == false);
  91. m_ChainPositionOverrides.Clear();
  92. IKManager2D manager = IKEditorManager.instance.FindManager(solver);
  93. foreach (Solver2D l_solver in manager.solvers)
  94. {
  95. if(l_solver == null || l_solver.allChainsHaveTargets)
  96. continue;
  97. for (int i = 0; i < l_solver.chainCount; ++i)
  98. {
  99. var chain = l_solver.GetChain(i);
  100. if (chain.effector != null)
  101. m_ChainPositionOverrides[chain] = chain.effector.position;
  102. }
  103. }
  104. }
  105. private void SetSolverPositionOverrides()
  106. {
  107. foreach (var pair in m_ChainPositionOverrides)
  108. IKEditorManager.instance.SetChainPositionOverride(pair.Key, pair.Value);
  109. }
  110. private bool IsTargetTransformSelected(IKChain2D chain)
  111. {
  112. Debug.Assert(chain.target != null);
  113. return Selection.Contains(chain.target.gameObject);
  114. }
  115. private void DrawSolver(Solver2D solver, IKManager2D.SolverEditorData editorData)
  116. {
  117. if (Event.current.type != EventType.Repaint)
  118. return;
  119. for (int i = 0; i < solver.chainCount; ++i)
  120. {
  121. var chain = solver.GetChain(i);
  122. if (chain != null)
  123. DrawChain(chain, editorData.color, solver.allChainsHaveTargets);
  124. }
  125. }
  126. private void DrawChain(IKChain2D chain, Color solverColor, bool solverHasTargets)
  127. {
  128. Handles.matrix = Matrix4x4.identity;
  129. Color color = FadeFromChain(solverColor, chain);
  130. if (color.a == 0f)
  131. return;
  132. Transform currentTransform = chain.effector;
  133. for (int i = 0; i < chain.transformCount - 1; ++i)
  134. {
  135. var parentPosition = currentTransform.parent.position;
  136. var position = currentTransform.position;
  137. Vector3 projectedLocalPosition = Vector3.Project(currentTransform.localPosition, Vector3.right);
  138. Vector3 projectedEndPoint = currentTransform.parent.position + currentTransform.parent.TransformVector(projectedLocalPosition);
  139. var visible = IsVisible(projectedEndPoint) || IsVisible(position);
  140. if (visible && currentTransform.localPosition.sqrMagnitude != projectedLocalPosition.sqrMagnitude)
  141. {
  142. Color red = Color.red;
  143. red.a = color.a;
  144. Handles.color = red;
  145. Handles.DrawDottedLine(projectedEndPoint, position, kDottedLineLength);
  146. }
  147. visible = IsVisible(parentPosition) || IsVisible(projectedEndPoint);
  148. Handles.color = color;
  149. if (visible)
  150. Handles.DrawDottedLine(parentPosition, projectedEndPoint, kDottedLineLength);
  151. currentTransform = currentTransform.parent;
  152. }
  153. Handles.color = color;
  154. currentTransform = chain.effector;
  155. for (int i = 0; i < chain.transformCount; ++i)
  156. {
  157. var position = currentTransform.position;
  158. var size = HandleUtility.GetHandleSize(position);
  159. if (IsVisible(position))
  160. Handles.DrawSolidDisc(position, currentTransform.forward, kNodeRadius * size);
  161. currentTransform = currentTransform.parent;
  162. }
  163. Handles.color = Color.white;
  164. }
  165. private Color FadeFromChain(Color color, IKChain2D chain)
  166. {
  167. var size = HandleUtility.GetHandleSize(chain.effector.position);
  168. var scaleFactor = 1f;
  169. var lengths = chain.lengths;
  170. foreach (var length in lengths)
  171. scaleFactor = Mathf.Max(scaleFactor, length);
  172. return FadeFromSize(color, size, kFadeStart * scaleFactor, kFadeEnd * scaleFactor);
  173. }
  174. private Color FadeFromSize(Color color, float size, float fadeStart, float fadeEnd)
  175. {
  176. float alpha = Mathf.Lerp(1f, 0f, (size - fadeStart) / (fadeEnd - fadeStart));
  177. color.a = alpha;
  178. return color;
  179. }
  180. private bool IsVisible(Vector3 position)
  181. {
  182. var screenPos = HandleUtility.GUIPointToScreenPixelCoordinate(HandleUtility.WorldToGUIPoint(position));
  183. if (screenPos.x < 0f || screenPos.x > Camera.current.pixelWidth || screenPos.y < 0f || screenPos.y > Camera.current.pixelHeight)
  184. return false;
  185. return true;
  186. }
  187. }
  188. }