123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- using System.Collections.Generic;
- using System.Linq;
- using UnityEditor.SceneManagement;
- using UnityEngine;
- using UnityEngine.U2D.Common;
- using UnityEngine.U2D.IK;
- using UnityEngine.U2D.Animation;
-
- namespace UnityEditor.U2D.IK
- {
- [DefaultExecutionOrder(UpdateOrder.ikUpdateOrder - 1)]
- internal class IKEditorManager : ScriptableObject
- {
- static IKEditorManager s_Instance;
-
- readonly HashSet<IKManager2D> m_DirtyManagers = new HashSet<IKManager2D>();
- readonly HashSet<IKManager2D> m_IKManagers = new HashSet<IKManager2D>();
- readonly Dictionary<IKChain2D, Vector3> m_ChainPositionOverrides = new Dictionary<IKChain2D, Vector3>();
- readonly List<Vector3> m_TargetPositions = new List<Vector3>();
-
- GameObject m_Helper;
- GameObject[] m_SelectedGameobjects;
-
- internal bool isDraggingATool { get; private set; }
-
- bool m_Initialized;
-
- [InitializeOnLoadMethod]
- static void CreateInstance()
- {
- if (s_Instance != null)
- return;
-
- var ikManagers = Resources.FindObjectsOfTypeAll<IKEditorManager>();
- if (ikManagers.Length > 0)
- s_Instance = ikManagers[0];
- else
- s_Instance = ScriptableObject.CreateInstance<IKEditorManager>();
- s_Instance.hideFlags = HideFlags.HideAndDontSave;
- }
-
- public static IKEditorManager instance
- {
- get
- {
- if (s_Instance == null)
- CreateInstance();
- return s_Instance;
- }
- }
-
- void OnEnable()
- {
- if (s_Instance == null)
- s_Instance = this;
-
- IKManager2D.onEnabledEditor += AddIKManager2D;
- IKManager2D.onDisabledEditor += RemoveIKManager2D;
- }
-
- void OnDisable()
- {
- IKManager2D.onEnabledEditor -= AddIKManager2D;
- IKManager2D.onDisabledEditor -= RemoveIKManager2D;
-
- Dispose();
- }
-
- public void Initialize()
- {
- var currentStage = StageUtility.GetCurrentStageHandle();
- var managers = currentStage.FindComponentsOfType<IKManager2D>().Where(x => x.gameObject.scene.isLoaded).ToArray();
- foreach (var ikManager2D in managers)
- m_IKManagers.Add(ikManager2D);
-
- RegisterCallbacks();
-
- m_Initialized = true;
- }
-
- void Dispose()
- {
- UnregisterCallbacks();
- Clear();
-
- m_Initialized = false;
- }
-
- void AddIKManager2D(IKManager2D manager)
- {
- if (manager == null)
- return;
-
- if (!m_Initialized)
- Initialize();
-
- m_IKManagers.Add(manager);
- }
-
- void RemoveIKManager2D(IKManager2D manager)
- {
- m_IKManagers.Remove(manager);
-
- if (m_IKManagers.Count == 0)
- Dispose();
- }
-
- private void RegisterCallbacks()
- {
- #if UNITY_2019_1_OR_NEWER
- SceneView.duringSceneGui += OnSceneGUI;
- #else
- SceneView.onSceneGUIDelegate += OnSceneGUI;
- #endif
- Selection.selectionChanged += OnSelectionChanged;
- }
-
- private void UnregisterCallbacks()
- {
- #if UNITY_2019_1_OR_NEWER
- SceneView.duringSceneGui -= OnSceneGUI;
- #else
- SceneView.onSceneGUIDelegate -= OnSceneGUI;
- #endif
- Selection.selectionChanged -= OnSelectionChanged;
- }
-
- private bool m_EnableGizmos;
- private bool m_CurrentEnableGizmoState;
-
- void OnDrawGizmos()
- {
- m_EnableGizmos = true;
- IKManager2D.onDrawGizmos.RemoveListener(OnDrawGizmos);
- }
-
- public void CheckGizmoToggle()
- {
- //Ignore events other than Repaint
- if (Event.current.type != EventType.Repaint)
- return;
-
- if (m_CurrentEnableGizmoState != m_EnableGizmos)
- SceneView.RepaintAll();
-
- m_CurrentEnableGizmoState = m_EnableGizmos;
-
- //Assume the Gizmo toggle is disabled and listen to the event again
- m_EnableGizmos = false;
- IKManager2D.onDrawGizmos.RemoveListener(OnDrawGizmos);
- IKManager2D.onDrawGizmos.AddListener(OnDrawGizmos);
- }
-
- private void OnSelectionChanged()
- {
- m_SelectedGameobjects = null;
- }
-
- void Clear()
- {
- m_IKManagers.Clear();
- m_DirtyManagers.Clear();
- m_ChainPositionOverrides.Clear();
- }
-
- public IKManager2D FindManager(Solver2D solver)
- {
- foreach (IKManager2D manager in m_IKManagers)
- {
- if (manager == null)
- continue;
-
- foreach (Solver2D s in manager.solvers)
- {
- if (s == null)
- continue;
-
- if (s == solver)
- return manager;
- }
- }
-
- return null;
- }
-
- public void Record(Solver2D solver, string undoName)
- {
- var manager = FindManager(solver);
-
- DoUndo(manager, undoName, true);
- }
-
- public void RegisterUndo(Solver2D solver, string undoName)
- {
- var manager = FindManager(solver);
-
- DoUndo(manager, undoName, false);
- }
-
- public void Record(IKManager2D manager, string undoName)
- {
- DoUndo(manager, undoName, true);
- }
-
- public void RegisterUndo(IKManager2D manager, string undoName)
- {
- DoUndo(manager, undoName, false);
- }
-
- private void DoUndo(IKManager2D manager, string undoName, bool record)
- {
- if (manager == null)
- return;
- foreach (var solver in manager.solvers)
- {
- if (solver == null || !solver.isActiveAndEnabled)
- continue;
-
- if (!solver.isValid)
- solver.Initialize();
-
- if (!solver.isValid)
- continue;
-
- for (int i = 0; i < solver.chainCount; ++i)
- {
- var chain = solver.GetChain(i);
-
- if (record)
- {
- foreach(var t in chain.transforms)
- Undo.RecordObject(t, undoName);
-
- if(chain.target)
- Undo.RecordObject(chain.target, undoName);
- }
- else
- {
- foreach(var t in chain.transforms)
- Undo.RegisterCompleteObjectUndo(t, undoName);
-
- if(chain.target)
- Undo.RegisterCompleteObjectUndo(chain.target, undoName);
- }
- }
- }
- }
-
- public void UpdateManagerImmediate(IKManager2D manager, bool recordRootLoops)
- {
- SetManagerDirty(manager);
- UpdateDirtyManagers(recordRootLoops);
- }
-
- public void UpdateSolverImmediate(Solver2D solver, bool recordRootLoops)
- {
- SetSolverDirty(solver);
- UpdateDirtyManagers(recordRootLoops);
- }
-
- public void SetChainPositionOverride(IKChain2D chain, Vector3 position)
- {
- m_ChainPositionOverrides[chain] = position;
- }
-
- private bool IsViewToolActive()
- {
- int button = Event.current.button;
- return Tools.current == Tool.View || Event.current.alt || (button == 1) || (button == 2);
- }
-
- private bool IsDraggingATool()
- {
- //If a tool has used EventType.MouseDrag, we won't be able to detect it. Instead we check for delta magnitude
- return GUIUtility.hotControl != 0 && Event.current.button == 0 && Event.current.delta.sqrMagnitude > 0f && !IsViewToolActive();
- }
-
- private void OnSceneGUI(SceneView sceneView)
- {
- CheckGizmoToggle();
- if (!m_CurrentEnableGizmoState)
- return;
-
- if (m_SelectedGameobjects == null)
- m_SelectedGameobjects = Selection.gameObjects;
-
- foreach (var ikManager2D in m_IKManagers)
- {
- if (ikManager2D != null && ikManager2D.isActiveAndEnabled)
- IKGizmos.instance.DoSolversGUI(ikManager2D);
- }
-
- if (!IKGizmos.instance.isDragging && IsDraggingATool())
- {
- //We expect the object to be selected while dragged
- foreach (var gameObject in m_SelectedGameobjects)
- {
- if (gameObject != null && gameObject.transform != null)
- SetDirtySolversAffectedByTransform(gameObject.transform);
- }
-
- if(m_DirtyManagers.Count > 0 && !isDraggingATool)
- {
- isDraggingATool = true;
- Undo.SetCurrentGroupName("IK Update");
-
- RegisterUndoForDirtyManagers();
- }
- }
-
- if(GUIUtility.hotControl == 0)
- isDraggingATool = false;
- }
-
- private void SetSolverDirty(Solver2D solver)
- {
- if (solver && solver.isValid && solver.isActiveAndEnabled)
- SetManagerDirty(FindManager(solver));
- }
-
- private void SetManagerDirty(IKManager2D manager)
- {
- if (manager && manager.isActiveAndEnabled)
- m_DirtyManagers.Add(manager);
- }
-
- private void SetDirtySolversAffectedByTransform(Transform transform)
- {
- foreach (var manager in m_IKManagers)
- {
- if (manager != null && manager.isActiveAndEnabled)
- {
- var dirty = false;
- var solvers = manager.solvers;
- for (var s = 0; s < solvers.Count; s++)
- {
- if(dirty)
- break;
-
- var solver = solvers[s];
- if (solver != null && solver.isValid)
- {
- for (var c = 0; c < solver.chainCount; ++c)
- {
- var chain = solver.GetChain(c);
-
- if(chain.target == null)
- continue;
-
- if (!(IKUtility.IsDescendentOf(chain.target, transform) && IKUtility.IsDescendentOf(chain.rootTransform, transform)) &&
- (chain.target == transform || IKUtility.IsDescendentOf(chain.target, transform) || IKUtility.IsDescendentOf(chain.effector, transform)))
- {
- SetManagerDirty(manager);
- dirty = true;
- break;
- }
- }
- }
- }
- }
- }
- }
-
- private void RegisterUndoForDirtyManagers()
- {
- foreach (var manager in m_DirtyManagers)
- RegisterUndo(manager, Undo.GetCurrentGroupName());
- }
-
- private void UpdateDirtyManagers(bool recordRootLoops)
- {
- foreach (var manager in m_DirtyManagers)
- {
- if (manager == null || !manager.isActiveAndEnabled)
- continue;
-
- foreach (var solver in manager.solvers)
- {
- if (solver == null || !solver.isActiveAndEnabled)
- continue;
-
- if (!solver.isValid)
- solver.Initialize();
-
- if (!solver.isValid)
- continue;
-
- if(solver.allChainsHaveTargets)
- solver.UpdateIK(manager.weight);
- else if(PrepareTargetOverrides(solver))
- solver.UpdateIK(m_TargetPositions, manager.weight);
-
- for (int i = 0; i < solver.chainCount; ++i)
- {
- var chain = solver.GetChain(i);
-
- if (recordRootLoops)
- InternalEngineBridge.SetLocalEulerHint(chain.rootTransform);
-
- if(solver.constrainRotation && chain.target != null)
- InternalEngineBridge.SetLocalEulerHint(chain.effector);
- }
- }
- }
-
- m_DirtyManagers.Clear();
- m_ChainPositionOverrides.Clear();
- }
-
- private bool PrepareTargetOverrides(Solver2D solver)
- {
- m_TargetPositions.Clear();
-
- for (int i = 0; i < solver.chainCount; ++i)
- {
- var chain = solver.GetChain(i);
-
- Vector3 positionOverride;
- if (!m_ChainPositionOverrides.TryGetValue(chain, out positionOverride))
- {
- m_TargetPositions.Clear();
- return false;
- }
-
- m_TargetPositions.Add(positionOverride);
- }
-
- return true;
- }
- }
- }
|