Created
May 14, 2025 02:58
-
-
Save simonwittber/38db5d079b41246d7e043dae00f8a2e5 to your computer and use it in GitHub Desktop.
Handle for resizing rects in Unity.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEditor; | |
using UnityEngine; | |
public class RectBoundsHandle | |
{ | |
public float HandleSize = 10f; | |
public float CornerGrabRadius = 12f; | |
public Color FillColor = new Color(0, 1, 1, 0.1f); | |
public Color OutlineColor = Color.cyan; | |
public Color HandleColor = Color.blue; | |
// internal state | |
Corner _activeCorner = Corner.None; | |
private Vector2 _initialPosition; | |
private Vector2 _dragOffset; | |
enum Corner | |
{ | |
None = -1, | |
TopLeft, | |
TopRight, | |
BottomRight, | |
BottomLeft, | |
Top, | |
Right, | |
Bottom, | |
Left, | |
Center | |
} | |
public Rect DrawHandle(Rect rect) | |
{ | |
var rectCopy = rect; | |
var e = Event.current; | |
// Draw fill + outline | |
Handles.DrawSolidRectangleWithOutline(rect, FillColor, OutlineColor); | |
var corners = new[] | |
{ | |
(Corner.TopLeft, MouseCursor.ResizeUpLeft, new Vector2(rect.xMin, rect.yMin)), // top-left | |
(Corner.TopRight, MouseCursor.ResizeUpRight, new Vector2(rect.xMax, rect.yMin)), // top-right | |
(Corner.BottomRight, MouseCursor.ResizeUpLeft, new Vector2(rect.xMax, rect.yMax)), // bottom-right | |
(Corner.BottomLeft, MouseCursor.ResizeUpRight, new Vector2(rect.xMin, rect.yMax)), // bottom-left | |
(Corner.Top, MouseCursor.ResizeVertical, new Vector2(rect.center.x, rect.yMin)), // top | |
(Corner.Right, MouseCursor.ResizeHorizontal, new Vector2(rect.xMax, rect.center.y)), // right | |
(Corner.Bottom, MouseCursor.ResizeVertical, new Vector2(rect.center.x, rect.yMax)), // bottom | |
(Corner.Left, MouseCursor.ResizeHorizontal, new Vector2(rect.xMin, rect.center.y)), // left | |
(Corner.Center, MouseCursor.MoveArrow, new Vector2(rect.center.x, rect.center.y)) // center | |
}; | |
foreach(var (corner, cursor, cpos) in corners) | |
{ | |
var hr = new Rect(cpos.x - HandleSize / 2, cpos.y - HandleSize / 2, HandleSize, HandleSize); | |
Handles.color = HandleColor; | |
Handles.DrawSolidDisc(cpos, Vector3.forward, HandleSize / 2); | |
Handles.color = Color.white; | |
EditorGUIUtility.AddCursorRect(hr, cursor); | |
} | |
switch (e.type) | |
{ | |
case EventType.MouseDown when e.button == 0: | |
// see if we hit a corner | |
foreach(var (corner, cursor, cpos) in corners) | |
{ | |
if (Vector2.Distance(e.mousePosition, cpos) < CornerGrabRadius / 2) | |
{ | |
_activeCorner = corner; | |
_initialPosition = cpos; | |
_dragOffset = cpos - e.mousePosition; | |
e.Use(); | |
return rect; | |
} | |
} | |
break; | |
case EventType.MouseDrag when e.button == 0: | |
var delta = e.mousePosition - _initialPosition; | |
if (_activeCorner >= 0) | |
{ | |
// resize from that corner | |
var newCornerPos = (_initialPosition + _dragOffset) + delta; | |
switch (_activeCorner) | |
{ | |
case Corner.TopLeft: | |
rect.xMin = newCornerPos.x; | |
rect.yMin = newCornerPos.y; | |
break; | |
case Corner.TopRight: | |
rect.xMax = newCornerPos.x; | |
rect.yMin = newCornerPos.y; | |
break; | |
case Corner.BottomRight: | |
rect.xMax = newCornerPos.x; | |
rect.yMax = newCornerPos.y; | |
break; | |
case Corner.BottomLeft: | |
rect.xMin = newCornerPos.x; | |
rect.yMax = newCornerPos.y; | |
break; | |
case Corner.Top: | |
rect.yMin = newCornerPos.y; | |
break; | |
case Corner.Right: | |
rect.xMax = newCornerPos.x; | |
break; | |
case Corner.Bottom: | |
rect.yMax = newCornerPos.y; | |
break; | |
case Corner.Left: | |
rect.xMin = newCornerPos.x; | |
break; | |
case Corner.Center: | |
rect.center = newCornerPos; | |
break; | |
} | |
e.Use(); | |
} | |
break; | |
case EventType.MouseUp when e.button == 0: | |
_activeCorner = Corner.None; | |
break; | |
} | |
return rect; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment