123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.U2D;
- using UnityEngine.U2D.Animation;
- using UnityEngine.U2D.Common;
- namespace UnityEditor.U2D.Animation
- {
- //Make sure Bone Gizmo registers callbacks before anyone else
- [InitializeOnLoad]
- internal class BoneGizmoInitializer
- {
- static BoneGizmoInitializer()
- {
- BoneGizmo.instance.Initialize();
- }
- }
- internal class BoneGizmo : ScriptableSingleton<BoneGizmo>
- {
- private BoneGizmoController m_BoneGizmoController;
- internal BoneGizmoController boneGizmoController { get { return m_BoneGizmoController; } }
- internal void Initialize()
- {
- m_BoneGizmoController = new BoneGizmoController(new SkeletonView(new GUIWrapper()), new UnityEngineUndo(), new BoneGizmoToggle());
- RegisterCallbacks();
- }
- internal void ClearSpriteBoneCache()
- {
- boneGizmoController.ClearSpriteBoneCache();
- }
- private void RegisterCallbacks()
- {
- Selection.selectionChanged += OnSelectionChanged;
- SceneView.duringSceneGui += OnSceneGUI;
- AssemblyReloadEvents.afterAssemblyReload += OnAfterAssemblyReload;
- EditorApplication.playModeStateChanged += PlayModeStateChanged;
- }
- private void OnSceneGUI(SceneView sceneView)
- {
- boneGizmoController.OnGUI();
- }
- private void OnSelectionChanged()
- {
- boneGizmoController.OnSelectionChanged();
- }
- private void OnAfterAssemblyReload()
- {
- boneGizmoController.OnSelectionChanged();
- }
- private void PlayModeStateChanged(PlayModeStateChange stateChange)
- {
- if (stateChange == PlayModeStateChange.EnteredPlayMode ||
- stateChange == PlayModeStateChange.EnteredEditMode)
- boneGizmoController.OnSelectionChanged();
- }
- }
- internal class BoneGizmoController
- {
- private Dictionary<Sprite, UnityEngine.U2D.SpriteBone[]> m_SpriteBones = new Dictionary<Sprite, UnityEngine.U2D.SpriteBone[]>();
- private Dictionary<Transform, Vector2> m_BoneData = new Dictionary<Transform, Vector2>();
- private HashSet<SpriteSkin> m_SkinComponents = new HashSet<SpriteSkin>();
- private HashSet<Transform> m_CachedBones = new HashSet<Transform>();
- private HashSet<Transform> m_SelectionRoots = new HashSet<Transform>();
- private ISkeletonView view;
- private IUndo m_Undo;
- private Tool m_PreviousTool = Tool.None;
- private IBoneGizmoToggle m_BoneGizmoToggle;
-
- internal IBoneGizmoToggle boneGizmoToggle { get { return m_BoneGizmoToggle; } set { m_BoneGizmoToggle = value; } }
- public Transform hoveredBone
- {
- get { return GetBone(view.hoveredBoneID); }
- }
- public Transform hoveredTail
- {
- get { return GetBone(view.hoveredTailID); }
- }
- public Transform hoveredBody
- {
- get { return GetBone(view.hoveredBodyID); }
- }
- public Transform hoveredJoint
- {
- get { return GetBone(view.hoveredJointID); }
- }
- public Transform hotBone
- {
- get { return GetBone(view.hotBoneID); }
- }
- private Transform GetBone(int instanceID)
- {
- return EditorUtility.InstanceIDToObject(instanceID) as Transform;
- }
- public BoneGizmoController(ISkeletonView view, IUndo undo, IBoneGizmoToggle toggle)
- {
- this.view = view;
- view.mode = SkeletonMode.EditPose;
- view.InvalidID = 0;
- m_Undo = undo;
- m_BoneGizmoToggle = toggle;
- }
- internal void OnSelectionChanged()
- {
- m_SelectionRoots.Clear();
- foreach (var selectedTransform in Selection.transforms)
- {
- var prefabRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(selectedTransform.gameObject);
- var animator = default(Animator);
- if (prefabRoot != null)
- m_SelectionRoots.Add(prefabRoot.transform);
- else if ((animator = selectedTransform.GetComponentInParent<Animator>()) != null)
- m_SelectionRoots.Add(animator.transform);
- else
- m_SelectionRoots.Add(selectedTransform.root);
- }
- if (m_PreviousTool == Tool.None && Selection.activeTransform != null && m_BoneData.ContainsKey(Selection.activeTransform))
- {
- m_PreviousTool = UnityEditor.Tools.current;
- UnityEditor.Tools.current = Tool.None;
- }
- if (m_PreviousTool != Tool.None && (Selection.activeTransform == null || !m_BoneData.ContainsKey(Selection.activeTransform)))
- {
- if (UnityEditor.Tools.current == Tool.None)
- UnityEditor.Tools.current = m_PreviousTool;
- m_PreviousTool = Tool.None;
- }
- FindSkinComponents();
- }
- internal void OnGUI()
- {
- m_BoneGizmoToggle.OnGUI();
- if (!m_BoneGizmoToggle.enableGizmos)
- return;
-
- PrepareBones();
- DoBoneGUI();
- }
- internal void FindSkinComponents()
- {
- m_SkinComponents.Clear();
-
- foreach (var root in m_SelectionRoots)
- {
- var components = root.GetComponentsInChildren<SpriteSkin>(false);
- foreach (var component in components)
- m_SkinComponents.Add(component);
- }
- SceneView.RepaintAll();
- }
- internal void ClearSpriteBoneCache()
- {
- m_SpriteBones.Clear();
- }
- private void PrepareBones()
- {
- if (!view.CanLayout())
- return;
- if (view.IsActionHot(SkeletonAction.None))
- m_CachedBones.Clear();
- m_BoneData.Clear();
- foreach (var skinComponent in m_SkinComponents)
- {
- if (skinComponent == null)
- continue;
- PrepareBones(skinComponent);
- }
- }
- private UnityEngine.U2D.SpriteBone[] GetSpriteBones(SpriteSkin spriteSkin)
- {
- Debug.Assert(spriteSkin.isValid);
- var sprite = spriteSkin.spriteRenderer.sprite;
- UnityEngine.U2D.SpriteBone[] spriteBones;
- if (!m_SpriteBones.TryGetValue(sprite, out spriteBones))
- {
- spriteBones = sprite.GetBones();
- m_SpriteBones[sprite] = sprite.GetBones();
- }
-
- return spriteBones;
- }
- private void PrepareBones(SpriteSkin spriteSkin)
- {
- Debug.Assert(spriteSkin != null);
- Debug.Assert(view.CanLayout());
- if (!spriteSkin.isActiveAndEnabled || !spriteSkin.isValid || !spriteSkin.spriteRenderer.enabled)
- return;
- var sprite = spriteSkin.spriteRenderer.sprite;
- var boneTransforms = spriteSkin.boneTransforms;
- var spriteBones = GetSpriteBones(spriteSkin);
- var alpha = 1f;
- if (spriteBones == null)
- return;
-
- for (int i = 0; i < boneTransforms.Length; ++i)
- {
- var boneTransform = boneTransforms[i];
- if (boneTransform == null || m_BoneData.ContainsKey(boneTransform))
- continue;
- var bone = spriteBones[i];
- if (view.IsActionHot(SkeletonAction.None))
- m_CachedBones.Add(boneTransform);
- m_BoneData.Add(boneTransform, new Vector2(bone.length, alpha));
- }
- }
- private void DoBoneGUI()
- {
- view.BeginLayout();
- if (view.CanLayout())
- LayoutBones();
- view.EndLayout();
- HandleSelectBone();
- HandleRotateBone();
- HandleMoveBone();
- DrawBones();
- DrawCursors();
- }
- private void LayoutBones()
- {
- foreach (var bone in m_CachedBones)
- {
- if (bone == null)
- continue;
- Vector2 value;
- if (!m_BoneData.TryGetValue(bone, out value))
- continue;
- var length = value.x;
- if (bone != hotBone)
- view.LayoutBone(bone.GetInstanceID(), bone.position, bone.position + bone.GetScaledRight() * length, bone.forward, bone.up, bone.right, false);
- }
- }
- private void HandleSelectBone()
- {
- int instanceID;
- bool additive;
- if (view.DoSelectBone(out instanceID, out additive))
- {
- var bone = GetBone(instanceID);
- if (!additive)
- {
- if (!Selection.Contains(bone.gameObject))
- Selection.activeTransform = bone;
- }
- else
- {
- var objectList = new List<Object>(Selection.objects);
- if(objectList.Contains(bone.gameObject))
- objectList.Remove(bone.gameObject);
- else
- objectList.Add(bone.gameObject);
- Selection.objects = objectList.ToArray();
- }
- }
- }
- private void HandleRotateBone()
- {
- var pivot = hoveredBone;
- if (view.IsActionHot(SkeletonAction.RotateBone))
- pivot = hotBone;
- if (pivot == null)
- return;
- FindPivotTransform(pivot, out pivot);
- if (pivot == null)
- return;
- float deltaAngle;
- if (view.DoRotateBone(pivot.position, pivot.forward, out deltaAngle))
- SetBoneRotation(deltaAngle);
- }
- private void HandleMoveBone()
- {
- Vector3 deltaPosition;
- if (view.DoMoveBone(out deltaPosition))
- SetBonePosition(deltaPosition);
- }
- private bool FindPivotTransform(Transform transform, out Transform selectedTransform)
- {
- selectedTransform = transform;
- var selectedRoots = Selection.transforms;
- foreach(var selectedRoot in selectedRoots)
- {
- if(transform.IsDescendentOf(selectedRoot))
- {
- selectedTransform = selectedRoot;
- return true;
- }
- }
- return false;
- }
- private void SetBonePosition(Vector3 deltaPosition)
- {
- foreach (var selectedTransform in Selection.transforms)
- {
- if(!m_BoneData.ContainsKey(selectedTransform))
- continue;
-
- var boneTransform = selectedTransform;
-
- m_Undo.RecordObject(boneTransform, TextContent.moveBone);
- boneTransform.position += deltaPosition;
- }
- }
- private void SetBoneRotation(float deltaAngle)
- {
- foreach(var selectedGameObject in Selection.gameObjects)
- {
- if(!m_BoneData.ContainsKey(selectedGameObject.transform))
- continue;
-
- var boneTransform = selectedGameObject.transform;
-
- m_Undo.RecordObject(boneTransform, TextContent.rotateBone);
- boneTransform.Rotate(boneTransform.forward, deltaAngle, Space.World);
- InternalEngineBridge.SetLocalEulerHint(boneTransform);
- }
- }
- private void DrawBones()
- {
- if (!view.IsRepainting())
- return;
- var selectedOutlineColor = SelectionOutlineSettings.outlineColor;
- var selectedOutlineSize = SelectionOutlineSettings.selectedBoneOutlineSize;
- var defaultOutlineColor = Color.black.AlphaMultiplied(0.5f);
- //Draw bone outlines
- foreach (var boneData in m_BoneData)
- {
- var bone = boneData.Key;
- if (bone == null)
- continue;
- var value = boneData.Value;
- var length = value.x;
- var alpha = value.y;
- if (alpha == 0f || !bone.gameObject.activeInHierarchy)
- continue;
- var color = defaultOutlineColor;
- var outlineSize = 1.25f;
- var isSelected = Selection.Contains(bone.gameObject);
- var isHovered = hoveredBody == bone && view.IsActionHot(SkeletonAction.None);
- if (isSelected)
- {
- color = selectedOutlineColor;
- outlineSize = selectedOutlineSize * 0.5f + 1f;
- }
- else if (isHovered)
- color = Handles.preselectionColor;
- DrawBoneOutline(bone, length, color, outlineSize);
- }
- //Draw bones
- foreach (var boneData in m_BoneData)
- {
- var bone = boneData.Key;
- if (bone == null)
- continue;
- var value = boneData.Value;
- var length = value.x;
- var alpha = value.y;
- if (alpha == 0f || !bone.gameObject.activeInHierarchy)
- continue;
- DrawBone(bone, length, Color.white);
- }
- }
- private void DrawBone(Transform bone, float length, Color color)
- {
- var isSelected = Selection.Contains(bone.gameObject);
- var isJointHovered = view.IsActionHot(SkeletonAction.None) && hoveredJoint == bone;
- var isTailHovered = view.IsActionHot(SkeletonAction.None) && hoveredTail == bone;
- view.DrawBone(bone.position, bone.GetScaledRight(), bone.forward, length, color, false, isSelected, isJointHovered, isTailHovered, bone == hotBone);
- }
- private void DrawBoneOutline(Transform bone, float length, Color color, float outlineScale)
- {
- view.DrawBoneOutline(bone.position, bone.GetScaledRight(), bone.forward, length, color, outlineScale);
- }
- private void DrawCursors()
- {
- if (!view.IsRepainting())
- return;
- view.DrawCursors(true);
- }
- private bool HasParentBone(Transform transform)
- {
- Debug.Assert(transform != null);
- return transform.parent != null && m_BoneData.ContainsKey(transform.parent);
- }
- }
- }
|