123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.U2D.IK;
-
- namespace UnityEditor.U2D.IK
- {
- internal class IKGizmos : ScriptableSingleton<IKGizmos>
- {
- private static readonly int kTargetHashCode = "IkTarget".GetHashCode();
- private Color enabledColor = Color.green;
- private Color disabledColor = Color.grey;
- private const float kCircleHandleRadius = 0.1f;
- private const float kNodeRadius = 0.05f;
- private const float kDottedLineLength = 5f;
- private const float kFadeStart = 0.75f;
- private const float kFadeEnd = 1.75f;
- private Dictionary<IKChain2D, Vector3> m_ChainPositionOverrides = new Dictionary<IKChain2D, Vector3>();
- public bool isDragging { get; private set; }
-
- public void DoSolversGUI(IKManager2D manager)
- {
- var solvers = manager.solvers;
- for (var s = 0; s < solvers.Count; s++)
- {
- var solver = solvers[s];
- if (solver == null || !solver.isValid || !solver.isActiveAndEnabled)
- continue;
-
- var solverData = manager.GetSolverEditorData(solver);
- if (!solverData.showGizmo)
- return;
-
- DrawSolver(solver, solverData.color);
-
- var allChainsHaveTargets = solver.allChainsHaveTargets;
-
- for (var c = 0; c < solver.chainCount; ++c)
- {
- var chain = solver.GetChain(c);
- if (chain == null)
- continue;
-
- if (allChainsHaveTargets)
- {
- if (!IsTargetTransformSelected(chain))
- DoTargetGUI(solver, chain);
- }
- else if (chain.target == null)
- DoIkPoseGUI(solver, chain);
- }
-
- if (GUIUtility.hotControl == 0)
- isDragging = false;
- }
- }
-
- private void DoTargetGUI(Solver2D solver, IKChain2D chain)
- {
- int controlId = GUIUtility.GetControlID(kTargetHashCode, FocusType.Passive);
-
- var color = FadeFromChain(Color.white, chain);
-
- if (!isDragging && (color.a == 0f || !IsVisible(chain.target.position)))
- return;
-
- EditorGUI.BeginChangeCheck();
-
- Handles.color = color;
- 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);
-
- if (EditorGUI.EndChangeCheck())
- {
- if(!isDragging)
- {
- isDragging = true;
- IKEditorManager.instance.RegisterUndo(solver, "Move Target");
- }
-
- Undo.RecordObject(chain.target, "Move Target");
-
- chain.target.position = newPosition;
- }
- }
-
- private void DoIkPoseGUI(Solver2D solver, IKChain2D chain)
- {
- int controlId = GUIUtility.GetControlID(kTargetHashCode, FocusType.Passive);
-
- var color = FadeFromChain(Color.white, chain);
-
- if (!isDragging && (color.a == 0f || !IsVisible(chain.effector.position)))
- return;
-
- if (HandleUtility.nearestControl == controlId && Event.current.type == EventType.MouseDown && Event.current.button == 0)
- StoreSolverPositionOverrides(solver);
-
- EditorGUI.BeginChangeCheck();
-
- Handles.color = color;
- 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);
-
- if (EditorGUI.EndChangeCheck())
- {
- if(!isDragging)
- isDragging = true;
-
- IKEditorManager.instance.Record(solver, "IK Pose");
-
- SetSolverPositionOverrides();
- IKEditorManager.instance.SetChainPositionOverride(chain, newPosition);
- IKEditorManager.instance.UpdateSolverImmediate(solver, true);
- }
- }
-
- private void StoreSolverPositionOverrides(Solver2D solver)
- {
- Debug.Assert(solver.allChainsHaveTargets == false);
-
- m_ChainPositionOverrides.Clear();
-
- IKManager2D manager = IKEditorManager.instance.FindManager(solver);
- foreach (Solver2D l_solver in manager.solvers)
- {
- if(l_solver == null || l_solver.allChainsHaveTargets)
- continue;
-
- for (int i = 0; i < l_solver.chainCount; ++i)
- {
- var chain = l_solver.GetChain(i);
- if (chain.effector != null)
- m_ChainPositionOverrides[chain] = chain.effector.position;
- }
- }
- }
-
- private void SetSolverPositionOverrides()
- {
- foreach (var pair in m_ChainPositionOverrides)
- IKEditorManager.instance.SetChainPositionOverride(pair.Key, pair.Value);
- }
-
- private bool IsTargetTransformSelected(IKChain2D chain)
- {
- Debug.Assert(chain.target != null);
-
- return Selection.Contains(chain.target.gameObject);
- }
-
- private void DrawSolver(Solver2D solver, Color color)
- {
- if (Event.current.type != EventType.Repaint)
- return;
-
- for (int i = 0; i < solver.chainCount; ++i)
- {
- var chain = solver.GetChain(i);
- if (chain != null)
- DrawChain(chain, color, solver.allChainsHaveTargets);
- }
- }
-
- private void DrawChain(IKChain2D chain, Color solverColor, bool solverHasTargets)
- {
- Handles.matrix = Matrix4x4.identity;
- Color color = FadeFromChain(solverColor, chain);
-
- if (color.a == 0f)
- return;
-
- Transform currentTransform = chain.effector;
- for (int i = 0; i < chain.transformCount - 1; ++i)
- {
- var parentPosition = currentTransform.parent.position;
- var position = currentTransform.position;
- Vector3 projectedLocalPosition = Vector3.Project(currentTransform.localPosition, Vector3.right);
- Vector3 projectedEndPoint = currentTransform.parent.position + currentTransform.parent.TransformVector(projectedLocalPosition);
- var visible = IsVisible(projectedEndPoint) || IsVisible(position);
-
- if (visible && currentTransform.localPosition.sqrMagnitude != projectedLocalPosition.sqrMagnitude)
- {
- Color red = Color.red;
- red.a = color.a;
- Handles.color = red;
- Handles.DrawDottedLine(projectedEndPoint, position, kDottedLineLength);
- }
-
- visible = IsVisible(parentPosition) || IsVisible(projectedEndPoint);
-
- Handles.color = color;
- if (visible)
- Handles.DrawDottedLine(parentPosition, projectedEndPoint, kDottedLineLength);
-
- currentTransform = currentTransform.parent;
- }
-
- Handles.color = color;
- currentTransform = chain.effector;
- for (int i = 0; i < chain.transformCount; ++i)
- {
- var position = currentTransform.position;
- var size = HandleUtility.GetHandleSize(position);
-
- if (IsVisible(position))
- Handles.DrawSolidDisc(position, currentTransform.forward, kNodeRadius * size);
-
- currentTransform = currentTransform.parent;
- }
-
- Handles.color = Color.white;
- }
-
- private Color FadeFromChain(Color color, IKChain2D chain)
- {
- var size = HandleUtility.GetHandleSize(chain.effector.position);
- var scaleFactor = 1f;
- var lengths = chain.lengths;
- foreach (var length in lengths)
- scaleFactor = Mathf.Max(scaleFactor, length);
-
- return FadeFromSize(color, size, kFadeStart * scaleFactor, kFadeEnd * scaleFactor);
- }
-
- private Color FadeFromSize(Color color, float size, float fadeStart, float fadeEnd)
- {
- float alpha = Mathf.Lerp(1f, 0f, (size - fadeStart) / (fadeEnd - fadeStart));
- color.a = alpha;
- return color;
- }
-
- private bool IsVisible(Vector3 position)
- {
- var screenPos = HandleUtility.GUIPointToScreenPixelCoordinate(HandleUtility.WorldToGUIPoint(position));
- if (screenPos.x < 0f || screenPos.x > Camera.current.pixelWidth || screenPos.y < 0f || screenPos.y > Camera.current.pixelHeight)
- return false;
-
- return true;
- }
- }
- }
|