123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598 |
- using UnityEngine;
- using System;
- namespace UnityEditor.U2D.Animation
- {
- internal class SkeletonView : ISkeletonView
- {
- private const float kPickingRadius = 5f;
- internal const string kDeleteCommandName = "Delete";
- internal const string kSoftDeleteCommandName = "SoftDelete";
- private static readonly int kBodyHashCode = "Body".GetHashCode();
- private static readonly int kJointHashCode = "Joint".GetHashCode();
- private static readonly int kTailHashCode = "Tail".GetHashCode();
- private static readonly int kCreateBoneHashCode = "CreateBone".GetHashCode();
- public int InvalidID { get; set; }
- public SkeletonMode mode { get; set; }
- public int defaultControlID { get; set; }
- public int hoveredBoneID { get { return m_HoveredBoneID; } }
- public int hoveredJointID { get { return m_HoveredJointID; } }
- public int hoveredBodyID { get { return m_HoveredBodyID; } }
- public int hoveredTailID { get { return m_HoveredTailID; } }
- public int hotBoneID { get { return m_HotBoneID; } }
- private IGUIWrapper m_GUIWrapper;
- private int m_RotateControlID = -1;
- private int m_MoveControlID = -1;
- private int m_FreeMoveControlID = -1;
- private int m_MoveJointControlID = -1;
- private int m_MoveEndPositionControlID = -1;
- private int m_ChangeLengthControlID = -1;
- private int m_CreateBoneControlID = -1;
- private int m_HoveredBoneID = 0;
- private int m_PrevHoveredBoneID = 0;
- private int m_HoveredBodyID = 0;
- private int m_HoveredJointID = 0;
- private int m_HoveredTailID = 0;
- private int m_HotBoneID = 0;
- private int m_HoveredBodyControlID = -1;
- private int m_HoveredJointControlID = -1;
- private int m_HoveredTailControlID = -1;
- private float m_NearestDistance;
- private float m_NearestBodyDistance;
- private float m_NearestJointDistance;
- private float m_NearestTailDistance;
- private int m_NearestBodyId = 0;
- private int m_NearestJointId = 0;
- private int m_NearestTailId = 0;
- private SliderData m_HoveredSliderData = SliderData.zero;
- private SliderData m_HotSliderData = SliderData.zero;
- public SkeletonView(IGUIWrapper gw)
- {
- m_GUIWrapper = gw;
- }
- public void BeginLayout()
- {
- m_HoveredBodyControlID = m_GUIWrapper.GetControlID(kBodyHashCode, FocusType.Passive);
- m_HoveredJointControlID = m_GUIWrapper.GetControlID(kJointHashCode, FocusType.Passive);
- m_HoveredTailControlID = m_GUIWrapper.GetControlID(kTailHashCode, FocusType.Passive);
- m_CreateBoneControlID = m_GUIWrapper.GetControlID(kCreateBoneHashCode, FocusType.Passive);
- if (m_GUIWrapper.eventType == EventType.Layout)
- {
- m_PrevHoveredBoneID = m_HoveredBoneID;
- m_NearestDistance = float.MaxValue;
- m_NearestBodyDistance = float.MaxValue;
- m_NearestJointDistance = float.MaxValue;
- m_NearestTailDistance = float.MaxValue;
- m_NearestBodyId = InvalidID;
- m_NearestJointId = InvalidID;
- m_NearestTailId = InvalidID;
- m_HoveredBoneID = InvalidID;
- m_HoveredBodyID = InvalidID;
- m_HoveredJointID = InvalidID;
- m_HoveredTailID = InvalidID;
- m_HoveredSliderData = SliderData.zero;
- if (m_GUIWrapper.IsControlHot(0))
- {
- m_RotateControlID = -1;
- m_MoveControlID = -1;
- m_FreeMoveControlID = -1;
- m_MoveJointControlID = -1;
- m_MoveEndPositionControlID = -1;
- m_ChangeLengthControlID = -1;
- m_HotBoneID = InvalidID;
- }
- }
- }
- public void EndLayout()
- {
- m_GUIWrapper.LayoutControl(m_HoveredBodyControlID, m_NearestBodyDistance * 0.25f);
- m_GUIWrapper.LayoutControl(m_HoveredJointControlID, m_NearestJointDistance);
- m_GUIWrapper.LayoutControl(m_HoveredTailControlID, m_NearestTailDistance);
- if (m_GUIWrapper.IsControlNearest(m_HoveredBodyControlID))
- {
- m_HoveredBoneID = m_NearestBodyId;
- m_HoveredBodyID = m_NearestBodyId;
- }
- if (m_GUIWrapper.IsControlNearest(m_HoveredJointControlID))
- {
- m_HoveredBoneID = m_NearestJointId;
- m_HoveredJointID = m_NearestJointId;
- }
- if (m_GUIWrapper.IsControlNearest(m_HoveredTailControlID))
- {
- m_HoveredBoneID = m_NearestTailId;
- m_HoveredTailID = m_NearestTailId;
- }
- if ((m_GUIWrapper.eventType == EventType.Layout && m_PrevHoveredBoneID != m_HoveredBoneID) || m_GUIWrapper.eventType == EventType.MouseMove)
- m_GUIWrapper.Repaint();
- }
- public bool CanLayout()
- {
- return m_GUIWrapper.eventType == EventType.Layout;
- }
- public void LayoutBone(int id, Vector3 position, Vector3 endPosition, Vector3 forward, Vector3 up, Vector3 right, bool isChainEnd)
- {
- if (mode == SkeletonMode.Disabled)
- return;
- var sliderData = new SliderData()
- {
- position = GetMouseWorldPosition(forward, position),
- forward = forward,
- up = up,
- right = right
- };
- {
- var distance = m_GUIWrapper.DistanceToSegmentClamp(position, endPosition);
- if (distance <= m_NearestDistance)
- {
- m_NearestDistance = distance;
- m_NearestBodyDistance = distance;
- m_NearestBodyId = id;
- m_HoveredSliderData = sliderData;
- }
- }
- {
- var distance = m_GUIWrapper.DistanceToCircle(position, GetBoneRadiusForPicking(position) * 2f);
- if (distance <= m_NearestDistance)
- {
- m_NearestDistance = distance;
- m_NearestJointDistance = distance;
- m_NearestJointId = id;
- m_HoveredSliderData = sliderData;
- }
- }
- if (isChainEnd &&
- (IsCapable(SkeletonAction.ChangeLength) ||
- IsCapable(SkeletonAction.MoveEndPosition) ||
- IsCapable(SkeletonAction.CreateBone)))
- {
- var distance = m_GUIWrapper.DistanceToCircle(endPosition, GetBoneRadiusForPicking(endPosition));
- if (distance <= m_NearestDistance)
- {
- m_NearestDistance = distance;
- m_NearestTailDistance = distance;
- m_NearestTailId = id;
- m_HoveredSliderData = sliderData;
- }
- }
- }
- public Vector3 GetMouseWorldPosition(Vector3 planeNormal, Vector3 planePosition)
- {
- return m_GUIWrapper.GUIToWorld(m_GUIWrapper.mousePosition, planeNormal, planePosition);
- }
- private float GetBoneRadiusForPicking(Vector3 position)
- {
- if (m_GUIWrapper.HasCurrentCamera())
- return 0.1f * m_GUIWrapper.GetHandleSize(position);
- return kPickingRadius;
- }
- public bool DoSelectBone(out int id, out bool additive)
- {
- id = 0;
- additive = false;
- if (IsActionTriggering(SkeletonAction.Select))
- {
- id = m_HoveredBoneID;
- additive = m_GUIWrapper.isActionKeyDown;
- if (mode == SkeletonMode.Selection)
- {
- m_GUIWrapper.UseCurrentEvent();
- m_GUIWrapper.SetGuiChanged(true);
- }
- return true;
- }
- return false;
- }
- public bool DoRotateBone(Vector3 pivot, Vector3 normal, out float deltaAngle)
- {
- deltaAngle = 0f;
- Vector3 oldPosition = m_HotSliderData.position;
- Vector3 newPosition;
- if (DoSliderAction(SkeletonAction.RotateBone, m_HoveredBodyControlID, ref m_RotateControlID, out newPosition))
- {
- deltaAngle = Vector3.SignedAngle(oldPosition - pivot, (Vector3)newPosition - pivot, normal);
- return true;
- }
- return false;
- }
- public bool DoMoveBone(out Vector3 deltaPosition)
- {
- deltaPosition = Vector3.zero;
- Vector3 oldPosition = m_HotSliderData.position;
- Vector3 newPosition;
- if (DoSliderAction(SkeletonAction.MoveBone, m_HoveredJointControlID, ref m_MoveControlID, out newPosition))
- {
- deltaPosition = newPosition - oldPosition;
- return true;
- }
- return false;
- }
- public bool DoFreeMoveBone(out Vector3 deltaPosition)
- {
- deltaPosition = Vector3.zero;
- Vector3 oldPosition = m_HotSliderData.position;
- Vector3 newPosition;
- if (DoSliderAction(SkeletonAction.FreeMoveBone, m_HoveredBodyControlID, ref m_FreeMoveControlID, out newPosition))
- {
- deltaPosition = newPosition - oldPosition;
- return true;
- }
- return false;
- }
- public bool DoMoveJoint(out Vector3 deltaPosition)
- {
- deltaPosition = Vector3.zero;
- Vector3 oldPosition = m_HotSliderData.position;
- Vector3 newPosition;
- if (DoSliderAction(SkeletonAction.MoveJoint, m_HoveredJointControlID, ref m_MoveJointControlID, out newPosition))
- {
- deltaPosition = newPosition - oldPosition;
- return true;
- }
- return false;
- }
- public bool DoMoveEndPosition(out Vector3 endPosition)
- {
- return DoSliderAction(SkeletonAction.MoveEndPosition, m_HoveredTailControlID, ref m_MoveEndPositionControlID, out endPosition);
- }
- public bool DoChangeLength(out Vector3 endPosition)
- {
- return DoSliderAction(SkeletonAction.ChangeLength, m_HoveredTailControlID, ref m_ChangeLengthControlID, out endPosition);
- }
- private bool DoSliderAction(SkeletonAction action, int controlID, ref int actionControlID, out Vector3 newPosition)
- {
- newPosition = m_HoveredSliderData.position;
- if (IsActionTriggering(action))
- {
- actionControlID = controlID;
- m_HotSliderData = m_HoveredSliderData;
- m_HotBoneID = hoveredBoneID;
- }
- if (m_GUIWrapper.DoSlider(actionControlID, m_HotSliderData, out newPosition))
- {
- m_HotSliderData.position = newPosition;
- return true;
- }
- return false;
- }
- public bool DoCreateBoneStart(out Vector3 position)
- {
- position = GetMouseWorldPosition(m_HoveredSliderData.forward, m_HoveredSliderData.position);
- if (CanCreateBone())
- m_GUIWrapper.LayoutControl(m_CreateBoneControlID, 0f);
- if (IsActionActive(SkeletonAction.CreateBone))
- ConsumeMouseMoveEvents();
- if (IsActionTriggering(SkeletonAction.CreateBone))
- {
- m_HotBoneID = hoveredBoneID;
- m_GUIWrapper.SetMultiStepControlHot(m_CreateBoneControlID);
- m_GUIWrapper.UseCurrentEvent();
- return true;
- }
- return false;
- }
- public bool CanCreateBone()
- {
- return mode == SkeletonMode.CreateBone && (m_GUIWrapper.IsControlNearest(defaultControlID) || m_GUIWrapper.IsControlNearest(m_HoveredTailControlID));
- }
- public bool DoCreateBone(out Vector3 position)
- {
- position = GetMouseWorldPosition(m_HoveredSliderData.forward, m_HoveredSliderData.position);
- if (IsActionHot(SkeletonAction.CreateBone))
- ConsumeMouseMoveEvents();
- if (IsActionFinishing(SkeletonAction.CreateBone))
- {
- m_GUIWrapper.UseCurrentEvent();
- m_GUIWrapper.SetGuiChanged(true);
- return true;
- }
- return false;
- }
- public bool DoSplitBone(out int id, out Vector3 position)
- {
- id = m_HoveredBodyID;
- position = GetMouseWorldPosition(m_HoveredSliderData.forward, m_HoveredSliderData.position);
- if (IsActionActive(SkeletonAction.SplitBone))
- ConsumeMouseMoveEvents();
- if (IsActionTriggering(SkeletonAction.SplitBone))
- {
- m_GUIWrapper.UseCurrentEvent();
- m_GUIWrapper.SetGuiChanged(true);
- return true;
- }
- return false;
- }
- public bool DoRemoveBone()
- {
- if (IsActionTriggering(SkeletonAction.Remove))
- {
- m_GUIWrapper.UseCurrentEvent();
- m_GUIWrapper.SetGuiChanged(true);
- return true;
- }
- return false;
- }
- public bool DoCancelMultistepAction(bool force)
- {
- if (force)
- {
- m_GUIWrapper.SetMultiStepControlHot(0);
- return true;
- }
- if ((!m_GUIWrapper.IsMultiStepControlHot(0) && (m_GUIWrapper.IsMouseDown(1) || m_GUIWrapper.IsKeyDown(KeyCode.Escape))))
- {
- m_GUIWrapper.SetMultiStepControlHot(0);
- m_GUIWrapper.UseCurrentEvent();
- return true;
- }
- return false;
- }
- public bool IsActionActive(SkeletonAction action)
- {
- if (m_GUIWrapper.isAltDown || !m_GUIWrapper.IsControlHot(0) || !m_GUIWrapper.IsMultiStepControlHot(0))
- return false;
- if (action == SkeletonAction.None)
- return m_GUIWrapper.IsControlNearest(defaultControlID);
- if (!IsCapable(action))
- return false;
- if (action == SkeletonAction.RotateBone)
- return m_GUIWrapper.IsControlNearest(m_HoveredBodyControlID);
- if (action == SkeletonAction.ChangeLength)
- return m_GUIWrapper.IsControlNearest(m_HoveredTailControlID) && !m_GUIWrapper.isShiftDown;
- if (action == SkeletonAction.MoveJoint)
- return m_GUIWrapper.IsControlNearest(m_HoveredJointControlID);
- if (action == SkeletonAction.MoveEndPosition)
- return m_GUIWrapper.IsControlNearest(m_HoveredTailControlID) && !m_GUIWrapper.isShiftDown;
- if (action == SkeletonAction.FreeMoveBone)
- return m_GUIWrapper.IsControlNearest(m_HoveredBodyControlID);
- if (action == SkeletonAction.MoveBone)
- return m_GUIWrapper.IsControlNearest(m_HoveredJointControlID);
- bool canCreateBone = IsCapable(SkeletonAction.CreateBone) && m_GUIWrapper.IsControlNearest(m_CreateBoneControlID);
- bool canSplitBone = IsCapable(SkeletonAction.SplitBone) && m_GUIWrapper.IsControlNearest(m_HoveredBodyControlID);
- if (action == SkeletonAction.CreateBone)
- return canCreateBone;
- if (action == SkeletonAction.SplitBone)
- return canSplitBone;
- if (action == SkeletonAction.Select)
- return (m_GUIWrapper.IsControlNearest(m_HoveredBodyControlID) && !canSplitBone) ||
- m_GUIWrapper.IsControlNearest(m_HoveredJointControlID) ||
- (m_GUIWrapper.IsControlNearest(m_HoveredTailControlID) && !canCreateBone);
- if (action == SkeletonAction.Remove)
- return true;
- return false;
- }
- public bool IsActionHot(SkeletonAction action)
- {
- if (action == SkeletonAction.None)
- return m_GUIWrapper.IsControlHot(0) && m_GUIWrapper.IsMultiStepControlHot(0);
- if (action == SkeletonAction.RotateBone)
- return m_GUIWrapper.IsControlHot(m_RotateControlID);
- if (action == SkeletonAction.MoveBone)
- return m_GUIWrapper.IsControlHot(m_MoveControlID);
- if (action == SkeletonAction.FreeMoveBone)
- return m_GUIWrapper.IsControlHot(m_FreeMoveControlID);
- if (action == SkeletonAction.MoveJoint)
- return m_GUIWrapper.IsControlHot(m_MoveJointControlID);
- if (action == SkeletonAction.MoveEndPosition)
- return m_GUIWrapper.IsControlHot(m_MoveEndPositionControlID);
- if (action == SkeletonAction.ChangeLength)
- return m_GUIWrapper.IsControlHot(m_ChangeLengthControlID);
- if (action == SkeletonAction.CreateBone)
- return m_GUIWrapper.IsMultiStepControlHot(m_CreateBoneControlID) && !m_GUIWrapper.isAltDown;
- return false;
- }
- public bool IsActionTriggering(SkeletonAction action)
- {
- if (!IsActionActive(action))
- return false;
- if (action == SkeletonAction.Remove)
- {
- if ((m_GUIWrapper.eventType == EventType.ValidateCommand || m_GUIWrapper.eventType == EventType.ExecuteCommand)
- && (m_GUIWrapper.commandName == kSoftDeleteCommandName || m_GUIWrapper.commandName == kDeleteCommandName))
- {
- if (m_GUIWrapper.eventType == EventType.ExecuteCommand)
- return true;
- m_GUIWrapper.UseCurrentEvent();
- }
- return false;
- }
- return m_GUIWrapper.IsMouseDown(0);
- }
- public bool IsActionFinishing(SkeletonAction action)
- {
- if (!IsActionHot(action) || !IsCapable(action))
- return false;
- if (m_GUIWrapper.IsEventOutsideWindow())
- return true;
- if (action == SkeletonAction.CreateBone)
- return m_GUIWrapper.IsMouseDown(0);
- return m_GUIWrapper.IsMouseUp(0);
- }
- public bool IsRepainting()
- {
- return m_GUIWrapper.IsRepainting();
- }
- public void DrawBone(Vector3 position, Vector3 right, Vector3 forward, float length, Color color, bool isChained, bool isSelected, bool isJointHovered, bool isTailHovered, bool isHot)
- {
- var endPosition = position + right * length;
- var rotation = Quaternion.LookRotation(forward, Vector3.Cross(right, forward));
- var boneBodyColor = color;
- var boneJointColor = new Color(0f, 0f, 0f, 0.75f * color.a);
- var tailColor = new Color(0f, 0f, 0f, 0.75f * color.a);
- var hoveredColor = Handles.preselectionColor;
- var selectedColor = Handles.selectedColor;
- var drawRectCap = false;
- if (isJointHovered)
- boneJointColor = hoveredColor;
- if (isHot && (IsActionHot(SkeletonAction.MoveBone) || IsActionHot(SkeletonAction.MoveJoint)))
- boneJointColor = selectedColor;
- if (mode == SkeletonMode.EditPose || mode == SkeletonMode.CreateBone)
- {
- if (isJointHovered || isSelected)
- drawRectCap = true;
- }
- else if (mode == SkeletonMode.EditJoints || mode == SkeletonMode.SplitBone)
- {
- rotation = Quaternion.identity;
- drawRectCap = true;
- }
- if (drawRectCap)
- Handles.RectangleHandleCap(0, position, rotation, BoneDrawingUtility.GetBoneRadius(position), EventType.Repaint);
- BoneDrawingUtility.DrawBone(position, endPosition, forward, boneBodyColor);
- BoneDrawingUtility.DrawBoneNode(position, forward, boneJointColor);
- if (!isChained &&
- (IsCapable(SkeletonAction.ChangeLength) ||
- IsCapable(SkeletonAction.MoveEndPosition)))
- {
- if (isTailHovered)
- tailColor = hoveredColor;
- if (isHot && (IsActionHot(SkeletonAction.ChangeLength) || IsActionHot(SkeletonAction.MoveEndPosition)))
- tailColor = selectedColor;
- BoneDrawingUtility.DrawBoneNode(endPosition, forward, tailColor);
- }
- }
- public void DrawBoneParentLink(Vector3 parentPosition, Vector3 position, Vector3 forward, Color color)
- {
- BoneDrawingUtility.DrawBone(position, parentPosition, forward, color);
- }
- public void DrawBoneOutline(Vector3 position, Vector3 right, Vector3 forward, float length, Color color, float outlineScale)
- {
- BoneDrawingUtility.DrawBoneOutline(position, position + right * length, forward, color, outlineScale);
- }
- public void DrawCursors(bool canBeActive)
- {
- var mouseScreenRect = new Rect(m_GUIWrapper.mousePosition.x - 100f, m_GUIWrapper.mousePosition.y - 100f, 200f, 200f);
- var isRotateHot = IsActionHot(SkeletonAction.RotateBone);
- if ((canBeActive && IsActionActive(SkeletonAction.RotateBone)) || isRotateHot)
- EditorGUIUtility.AddCursorRect(mouseScreenRect, MouseCursor.RotateArrow);
- if ((canBeActive && IsActionActive(SkeletonAction.MoveBone)) || IsActionHot(SkeletonAction.MoveBone) ||
- (canBeActive && IsActionActive(SkeletonAction.FreeMoveBone)) || IsActionHot(SkeletonAction.FreeMoveBone) ||
- (canBeActive && IsActionActive(SkeletonAction.MoveJoint)) || IsActionHot(SkeletonAction.MoveJoint) ||
- (canBeActive && IsActionActive(SkeletonAction.MoveEndPosition)) || IsActionHot(SkeletonAction.MoveEndPosition))
- EditorGUIUtility.AddCursorRect(mouseScreenRect, MouseCursor.MoveArrow);
- }
- private void ConsumeMouseMoveEvents()
- {
- if (m_GUIWrapper.eventType == EventType.MouseMove || (m_GUIWrapper.eventType == EventType.MouseDrag && m_GUIWrapper.mouseButton == 0))
- m_GUIWrapper.UseCurrentEvent();
- }
- private bool IsCapable(SkeletonAction action)
- {
- return ((int)mode & (int)action) != 0;
- }
- }
- }
|