Rasagar/Library/PackageCache/com.unity.2d.sprite/Editor/SpriteEditor/SpriteEditorHandles.cs
2024-08-26 23:07:20 +03:00

361 lines
16 KiB
C#

using UnityEngine;
using UnityEvent = UnityEngine.Event;
namespace UnityEditor.U2D.Sprites
{
internal static class SpriteEditorHandles
{
private static Vector2 s_CurrentMousePosition;
private static Vector2 s_DragStartScreenPosition;
private static Vector2 s_DragScreenOffset;
static internal Vector2 PointSlider(Vector2 pos, MouseCursor cursor, GUIStyle dragDot, GUIStyle dragDotActive)
{
int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard);
Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
Rect handleScreenPos = new Rect(
screenVal.x - dragDot.fixedWidth * .5f,
screenVal.y - dragDot.fixedHeight * .5f,
dragDot.fixedWidth,
dragDot.fixedHeight
);
var evt = UnityEvent.current;
switch (evt.GetTypeForControl(id))
{
case EventType.Repaint:
if (GUIUtility.hotControl == id)
dragDotActive.Draw(handleScreenPos, GUIContent.none, id);
else
dragDot.Draw(handleScreenPos, GUIContent.none, id);
break;
}
return ScaleSlider(pos, cursor, handleScreenPos);
}
static internal Vector2 ScaleSlider(Vector2 pos, MouseCursor cursor, Rect cursorRect)
{
int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard);
return ScaleSlider(id, pos, cursor, cursorRect);
}
static private Vector2 ScaleSlider(int id, Vector2 pos, MouseCursor cursor, Rect cursorRect)
{
Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
var evt = UnityEvent.current;
switch (evt.GetTypeForControl(id))
{
case EventType.MouseDown:
// am I closest to the thingy?
if (evt.button == 0 &&
cursorRect.Contains(UnityEvent.current.mousePosition) &&
!evt.alt)
{
GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
s_CurrentMousePosition = evt.mousePosition;
s_DragStartScreenPosition = evt.mousePosition;
s_DragScreenOffset = s_CurrentMousePosition - screenVal;
evt.Use();
EditorGUIUtility.SetWantsMouseJumping(1);
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
s_CurrentMousePosition += evt.delta;
Vector2 oldPos = pos;
pos = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition);
if (!Mathf.Approximately((oldPos - pos).magnitude, 0f))
GUI.changed = true;
evt.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
{
GUIUtility.hotControl = 0;
evt.Use();
EditorGUIUtility.SetWantsMouseJumping(0);
}
break;
case EventType.KeyDown:
if (GUIUtility.hotControl == id)
{
if (evt.keyCode == KeyCode.Escape)
{
pos = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset);
GUIUtility.hotControl = 0;
GUI.changed = true;
evt.Use();
}
}
break;
case EventType.Repaint:
if (GUIUtility.hotControl == 0 || GUIUtility.hotControl == id)
EditorGUIUtility.AddCursorRect(cursorRect, cursor, id);
break;
}
return pos;
}
static internal Vector2 PivotSlider(Rect sprite, Vector2 pos, GUIStyle pivotDot, GUIStyle pivotDotActive)
{
int id = GUIUtility.GetControlID("Slider1D".GetHashCode(), FocusType.Keyboard);
// Convert from normalized space to texture space
pos = new Vector2(sprite.xMin + sprite.width * pos.x, sprite.yMin + sprite.height * pos.y);
Vector2 screenVal = Handles.matrix.MultiplyPoint(pos);
Rect handleScreenPos = new Rect(
screenVal.x - pivotDot.fixedWidth * .5f,
screenVal.y - pivotDot.fixedHeight * .5f,
pivotDotActive.fixedWidth,
pivotDotActive.fixedHeight
);
var evt = UnityEvent.current;
switch (evt.GetTypeForControl(id))
{
case EventType.MouseDown:
// am I closest to the thingy?
if (evt.button == 0 && handleScreenPos.Contains(UnityEvent.current.mousePosition) && !evt.alt)
{
GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
s_CurrentMousePosition = evt.mousePosition;
s_DragStartScreenPosition = evt.mousePosition;
Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos);
s_DragScreenOffset = s_CurrentMousePosition - rectScreenCenter;
evt.Use();
EditorGUIUtility.SetWantsMouseJumping(1);
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
s_CurrentMousePosition += evt.delta;
Vector2 oldPos = pos;
Vector3 scrPos = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition - s_DragScreenOffset);
pos = new Vector2(scrPos.x, scrPos.y);
if (!Mathf.Approximately((oldPos - pos).magnitude, 0f))
GUI.changed = true;
evt.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
{
GUIUtility.hotControl = 0;
evt.Use();
EditorGUIUtility.SetWantsMouseJumping(0);
}
break;
case EventType.KeyDown:
if (GUIUtility.hotControl == id)
{
if (evt.keyCode == KeyCode.Escape)
{
pos = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset);
GUIUtility.hotControl = 0;
GUI.changed = true;
evt.Use();
}
}
break;
case EventType.Repaint:
EditorGUIUtility.AddCursorRect(handleScreenPos, MouseCursor.Arrow, id);
if (GUIUtility.hotControl == id)
pivotDotActive.Draw(handleScreenPos, GUIContent.none, id);
else
pivotDot.Draw(handleScreenPos, GUIContent.none, id);
break;
}
// Convert from texture space back to normalized space
pos = new Vector2((pos.x - sprite.xMin) / sprite.width, (pos.y - sprite.yMin) / sprite.height);
return pos;
}
static internal Rect SliderRect(Rect pos)
{
int id = GUIUtility.GetControlID("SliderRect".GetHashCode(), FocusType.Keyboard);
var evt = UnityEvent.current;
// SpriteEditorWindow is telling us we got selected and so we fake a mousedown on our Repaint event to get "one-click dragging" going on
if (SpriteEditorWindow.s_OneClickDragStarted && evt.type == EventType.Repaint)
{
HandleSliderRectMouseDown(id, evt, pos);
SpriteEditorWindow.s_OneClickDragStarted = false;
}
switch (evt.GetTypeForControl(id))
{
case EventType.MouseDown:
// am I closest to the thingy?
if (evt.button == 0 && pos.Contains(Handles.inverseMatrix.MultiplyPoint(UnityEvent.current.mousePosition)) && !evt.alt)
{
HandleSliderRectMouseDown(id, evt, pos);
evt.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
s_CurrentMousePosition += evt.delta;
Vector2 oldCenter = pos.center;
pos.center = Handles.inverseMatrix.MultiplyPoint(s_CurrentMousePosition - s_DragScreenOffset);
if (!Mathf.Approximately((oldCenter - pos.center).magnitude, 0f))
GUI.changed = true;
evt.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id && (evt.button == 0 || evt.button == 2))
{
GUIUtility.hotControl = 0;
evt.Use();
EditorGUIUtility.SetWantsMouseJumping(0);
}
break;
case EventType.KeyDown:
if (GUIUtility.hotControl == id)
{
if (evt.keyCode == KeyCode.Escape)
{
pos.center = Handles.inverseMatrix.MultiplyPoint(s_DragStartScreenPosition - s_DragScreenOffset);
GUIUtility.hotControl = 0;
GUI.changed = true;
evt.Use();
}
}
break;
case EventType.Repaint:
Vector2 topleft = Handles.inverseMatrix.MultiplyPoint(new Vector2(pos.xMin, pos.yMin));
Vector2 bottomright = Handles.inverseMatrix.MultiplyPoint(new Vector2(pos.xMax, pos.yMax));
EditorGUIUtility.AddCursorRect(new Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y), MouseCursor.Arrow, id);
break;
}
return pos;
}
static internal void HandleSliderRectMouseDown(int id, UnityEvent evt, Rect pos)
{
GUIUtility.hotControl = GUIUtility.keyboardControl = id; // Grab mouse focus
s_CurrentMousePosition = evt.mousePosition;
s_DragStartScreenPosition = evt.mousePosition;
Vector2 rectScreenCenter = Handles.matrix.MultiplyPoint(pos.center);
s_DragScreenOffset = s_CurrentMousePosition - rectScreenCenter;
EditorGUIUtility.SetWantsMouseJumping(1);
}
static int s_RectSelectionID = GUIUtility.GetPermanentControlID();
static internal Rect RectCreator(Rect textureArea, GUIStyle rectStyle)
{
var evt = UnityEvent.current;
Vector2 mousePos = evt.mousePosition;
int id = s_RectSelectionID;
Rect result = new Rect();
switch (evt.GetTypeForControl(id))
{
case EventType.MouseDown:
if (evt.button == 0)
{
GUIUtility.hotControl = id;
// Make sure that the starting position is clamped to inside texture area
s_DragStartScreenPosition = Handles.inverseMatrix.MultiplyPoint(mousePos);
s_DragStartScreenPosition.x = Mathf.Min(Mathf.Max(s_DragStartScreenPosition.x, textureArea.xMin), textureArea.xMax);
s_DragStartScreenPosition.y = Mathf.Min(Mathf.Max(s_DragStartScreenPosition.y, textureArea.yMin), textureArea.yMax);
evt.Use();
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
evt.Use();
}
break;
case EventType.Repaint:
{
var startDragPoint = Handles.matrix.MultiplyPoint(s_DragStartScreenPosition);
if (GUIUtility.hotControl == id && ValidRect(startDragPoint, mousePos))
{
// TODO: use rectstyle
//rectStyle.Draw (GetCurrentRect (true, textureWidth, textureHeight, s_DragStartScreenPosition, s_CurrentMousePosition), GUIContent.none, false, false, false, false);
SpriteEditorUtility.BeginLines(Color.green * 1.5f);
SpriteEditorUtility.DrawBox(GetCurrentRect(false, textureArea, startDragPoint, mousePos));
SpriteEditorUtility.EndLines();
}
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id && evt.button == 0)
{
var startDragPoint = Handles.matrix.MultiplyPoint(s_DragStartScreenPosition);
if (ValidRect(startDragPoint, mousePos))
{
result = GetCurrentRect(false, textureArea, startDragPoint, mousePos);
GUI.changed = true;
evt.Use();
}
GUIUtility.hotControl = 0;
}
break;
case EventType.KeyDown:
if (GUIUtility.hotControl == id)
{
if (evt.keyCode == KeyCode.Escape)
{
GUIUtility.hotControl = 0;
GUI.changed = true;
evt.Use();
}
}
break;
}
return result;
}
static internal Rect RectCreator(float textureWidth, float textureHeight, GUIStyle rectStyle)
{
return RectCreator(new Rect(0, 0, textureWidth, textureHeight), rectStyle);
}
static private bool ValidRect(Vector2 startPoint, Vector2 endPoint)
{
return Mathf.Abs((endPoint - startPoint).x) > 5f && Mathf.Abs((endPoint - startPoint).y) > 5f;
}
static private Rect GetCurrentRect(bool screenSpace, Rect clampArea, Vector2 startPoint, Vector2 endPoint)
{
Rect r = EditorGUIExt.FromToRect(Handles.inverseMatrix.MultiplyPoint(startPoint), Handles.inverseMatrix.MultiplyPoint(endPoint));
r = SpriteEditorUtility.ClampedRect(SpriteEditorUtility.RoundToInt(r), clampArea, false);
if (screenSpace)
{
Vector2 topleft = Handles.matrix.MultiplyPoint(new Vector2(r.xMin, r.yMin));
Vector2 bottomright = Handles.matrix.MultiplyPoint(new Vector2(r.xMax, r.yMax));
r = new Rect(topleft.x, topleft.y, bottomright.x - topleft.x, bottomright.y - topleft.y);
}
return r;
}
}
}