暫無描述
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.

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