Skip to content

Instantly share code, notes, and snippets.

@Monsoonexe
Last active March 5, 2024 15:32
Show Gist options
  • Save Monsoonexe/9c6749d6b561a40fba8dcd8221a8ca37 to your computer and use it in GitHub Desktop.
Save Monsoonexe/9c6749d6b561a40fba8dcd8221a8ca37 to your computer and use it in GitHub Desktop.
Drag component for windows in Unity
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace SmolderSoft.Gists
{
/// <summary>
/// Add this component to a Graphic to allow dragging. Keeps within the bounds of the screen.
/// </summary>
public class DraggableWindow : MonoBehaviour, IDragHandler, IBeginDragHandler
{
public bool resetToOriginalPositionOnShow = true;
private RectTransform windowRectTransform;
private Vector2 offset;
public Vector2 OriginalPosition { get; private set; }
#region Unity Messages
private void Awake()
{
windowRectTransform = GetComponent<RectTransform>();
OriginalPosition = windowRectTransform.anchoredPosition;
}
private void OnEnable()
{
if (resetToOriginalPositionOnShow)
windowRectTransform.anchoredPosition = OriginalPosition;
}
#endregion Unity Messages
public void OnBeginDrag(PointerEventData eventData)
{
// don't start dragging if something like a button was pressed
if (eventData.pointerPress && eventData.pointerPress.TryGetComponent<Selectable>(out _))
return;
// Calculate the initial offset from the window's position to the mouse position
offset = windowRectTransform.position.ToVector2() - eventData.position;
}
public void OnDrag(PointerEventData eventData)
{
// Calculate the clamped position based on the screen bounds
Rect bounds = windowRectTransform.rect.Scale(0.9f);
Vector2 clampedPosition = eventData.position + offset;
// modify lower bounds so window can be moved off screen up to the title bar
float lowerBounds = -bounds.height * 0.3f;
// horizontal bounds such that window never leaves viewport
clampedPosition.x = QuickMath.Clamp(clampedPosition.x, -bounds.xMin, Screen.width - bounds.xMax);
// vertical bounds such that the title bar never leaves viewport
clampedPosition.y = QuickMath.Clamp(clampedPosition.y, lowerBounds, Screen.height - bounds.yMax);
// Update the window's position based on the clamped position
windowRectTransform.position = clampedPosition;
}
}
public static class Rect_Extensions
{
/// <summary>
/// Creates a new rect scaled by <paramref name="scaleFactor"/>.
/// </summary>
public static Rect Scale(this Rect originalRect, float scaleFactor)
{
// Calculate the new dimensions
float newWidth = originalRect.width * scaleFactor;
float newHeight = originalRect.height * scaleFactor;
// Calculate the new position to keep the Rect centered
float newX = originalRect.x + (originalRect.width - newWidth) / 2;
float newY = originalRect.y + (originalRect.height - newHeight) / 2;
// Create the new Rect
return new Rect(newX, newY, newWidth, newHeight);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment