170 lines
3.9 KiB
C#
170 lines
3.9 KiB
C#
//----------------------------------------------
|
|
// NGUI: Next-Gen UI kit
|
|
// Copyright © 2011-2015 Tasharen Entertainment
|
|
//----------------------------------------------
|
|
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// Utility class that makes it easy to perform snapping while dragging widgets.
|
|
/// </summary>
|
|
|
|
public static class NGUISnap
|
|
{
|
|
const float SNAP_THRESHOLD = 10f;
|
|
|
|
static BetterList<Vector3> mSnapCenter = new BetterList<Vector3>();
|
|
static BetterList<Vector3> mSnapCorners = new BetterList<Vector3>();
|
|
|
|
static int mSnapping = -1;
|
|
|
|
/// <summary>
|
|
/// Whether widgets will snap to edges of other widgets when dragged around.
|
|
/// </summary>
|
|
|
|
static public bool allow
|
|
{
|
|
get
|
|
{
|
|
if (mSnapping == -1)
|
|
{
|
|
mSnapping = UnityEditor.EditorPrefs.GetInt("NGUI Snap", 1);
|
|
}
|
|
return (mSnapping == 1);
|
|
}
|
|
set
|
|
{
|
|
int val = value ? 1 : 0;
|
|
|
|
if (mSnapping != val)
|
|
{
|
|
mSnapping = val;
|
|
UnityEditor.EditorPrefs.SetInt("NGUI Handles", mSnapping);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recalculate all snapping edges.
|
|
/// </summary>
|
|
|
|
static public void Recalculate (Object obj)
|
|
{
|
|
mSnapCenter.Clear();
|
|
mSnapCorners.Clear();
|
|
|
|
if (obj is UIWidget)
|
|
{
|
|
UIWidget w = obj as UIWidget;
|
|
Recalculate(w.cachedTransform);
|
|
}
|
|
else if (obj is UIPanel)
|
|
{
|
|
UIPanel p = obj as UIPanel;
|
|
Recalculate(p.cachedTransform);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recalculate all snapping edges.
|
|
/// </summary>
|
|
|
|
static void Recalculate (Transform t)
|
|
{
|
|
// If the transform is rotated, ignore it
|
|
if (Vector3.Dot(t.localRotation * Vector3.up, Vector3.up) < 0.999f) return;
|
|
|
|
Transform parent = t.parent;
|
|
|
|
if (parent != null)
|
|
{
|
|
Add(t, parent);
|
|
|
|
for (int i = 0; i < parent.childCount; ++i)
|
|
{
|
|
Transform child = parent.GetChild(i);
|
|
if (child != t) Add(t, child);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified transform's edges to the lists.
|
|
/// </summary>
|
|
|
|
static void Add (Transform root, Transform child)
|
|
{
|
|
UIWidget w = child.GetComponent<UIWidget>();
|
|
if (w != null) Add(root, child, w.localCorners);
|
|
|
|
UIPanel p = child.GetComponent<UIPanel>();
|
|
if (p != null) Add(root, child, p.localCorners);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified transform's edges to the list.
|
|
/// </summary>
|
|
|
|
static void Add (Transform root, Transform child, Vector3[] local)
|
|
{
|
|
// If the transform is rotated, ignore it
|
|
if (Vector3.Dot(child.localRotation * Vector3.forward, Vector3.forward) < 0.999f) return;
|
|
|
|
// Make the coordinates relative to 'mine' transform
|
|
if (root != child)
|
|
{
|
|
for (int i = 0; i < 4; ++i)
|
|
{
|
|
local[i] = root.InverseTransformPoint(child.TransformPoint(local[i]));
|
|
}
|
|
}
|
|
|
|
Vector3 pos = root.localPosition;
|
|
mSnapCenter.Add(pos + (local[0] + local[2]) * 0.5f);
|
|
mSnapCorners.Add(pos + local[0]);
|
|
mSnapCorners.Add(pos + local[2]);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Snap the X coordinate using the previously calculated snapping edges.
|
|
/// </summary>
|
|
|
|
static public Vector3 Snap (Vector3 pos, Vector3[] local, bool snapToEdges)
|
|
{
|
|
if (snapToEdges && allow)
|
|
{
|
|
Vector3 center = pos + (local[0] + local[2]) * 0.5f;
|
|
Vector3 bl = pos + local[0];
|
|
Vector3 tr = pos + local[2];
|
|
Vector2 best = new Vector2(float.MaxValue, float.MaxValue);
|
|
|
|
for (int i = 0; i < mSnapCenter.size; ++i)
|
|
ChooseBest(ref best, mSnapCenter[i] - center);
|
|
|
|
for (int i = 0; i < mSnapCorners.size; ++i)
|
|
{
|
|
ChooseBest(ref best, mSnapCorners[i] - bl);
|
|
ChooseBest(ref best, mSnapCorners[i] - tr);
|
|
}
|
|
|
|
if (Mathf.Abs(best.x) < SNAP_THRESHOLD) pos.x += best.x;
|
|
if (Mathf.Abs(best.y) < SNAP_THRESHOLD) pos.y += best.y;
|
|
}
|
|
|
|
pos.x = Mathf.Round(pos.x);
|
|
pos.y = Mathf.Round(pos.y);
|
|
pos.z = Mathf.Round(pos.z);
|
|
return pos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Choose the closest edge.
|
|
/// </summary>
|
|
|
|
static void ChooseBest (ref Vector2 best, Vector3 diff)
|
|
{
|
|
if (Mathf.Abs(best.x) > Mathf.Abs(diff.x)) best.x = diff.x;
|
|
if (Mathf.Abs(best.y) > Mathf.Abs(diff.y)) best.y = diff.y;
|
|
}
|
|
}
|