Preface: I’m trying to create a custom attribute that draws moveable gizmos from an array or list of points (Vector2 or Vector3)
The dream would be to have something like:
[MoveablePoints]
public List<Vector2> examplePointSetList;
[MoveablePoints]
public Vector2[ ] examplePointSetArray;
…however, I don’t know how achievable something like that is. I’m not familiar with attributes.
So far, I have this helper script that I use to move points around manually while debugging.
(an older version can be seen here):
public class MovablePoints : MonoBehaviour
{
[Range(.01f, 1f)] public float selectionRadius = .05f;
public bool selectionActive = true;
public class MovablePoint
{
public Vector2 point;
public MovablePoint(float x, float y)
{
this.point = new Vector2(x, y);
}
public MovablePoint(Vector2 point)
{
this.point = point;
}
}
public class Point
{
public Vector2 position;
public Vector2 offset;
public Color color;
public bool isMoving;
public MovablePoint movablePoint;
public Vector2 posRef;
public Point(ref Vector2 position, MovablePoint movablePoint)
{
this.position = position;
this.movablePoint = movablePoint;
}
public bool IsPointInRange(Vector2 mosPos, float selectionRadius)
{
float dx = Mathf.Abs(position.x - mosPos.x);
float dy = Mathf.Abs(position.y - mosPos.y);
if (dx > selectionRadius)
return false;
if (dy > selectionRadius)
return false;
if (dx + dy <= selectionRadius)
return true;
if (Mathf.Pow(dx, 2) + Mathf.Pow(dy, 2) <= Mathf.Pow(selectionRadius, 2))
return true;
return false;
}
}
public List<Point> points = new List<Point>();
private Vector2 clickedPos;
private void Update()
{
Vector2 mosPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if (Input.GetMouseButtonDown(0))
{
clickedPos = mosPos;
foreach (Point point in points)
{
//if (IsPointInRange(point.position, mosPos) && !point.isMoving)
if (point.IsPointInRange(mosPos, selectionRadius))
{
point.isMoving = true;
point.offset = point.position - clickedPos;
}
}
}
if (Input.GetMouseButton(0))
{
foreach (Point point in points)
{
if (point.isMoving)
{
point.position = mosPos + point.offset;
point.movablePoint.point = mosPos + point.offset;
}
}
}
if (Input.GetMouseButtonUp(0))
{
foreach (Point point in points)
{
point.offset = Vector2.zero;
point.isMoving = false;
}
}
}
void OnDrawGizmos()
{
if (selectionActive)
{
Color selectionColor = Color.white;
selectionColor.a = 0.65f;
Handles.color = selectionColor;
if (Input.GetAxis("Mouse ScrollWheel") > 0f && selectionRadius < 1)
selectionRadius += .01f;
if (Input.GetAxis("Mouse ScrollWheel") < 0f && selectionRadius > 0)
selectionRadius -= .01f;
Vector2 mosPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Handles.DrawWireDisc(mosPos, new Vector3(0, 0, 1), selectionRadius);
foreach (Point point in points)
{
bool IsUnderSelectedArea = point.IsPointInRange(mosPos, selectionRadius);
if (point.isMoving)
Gizmos.color = Color.green;
else if (IsUnderSelectedArea)
Gizmos.color = Color.red;
else
Gizmos.color = Color.white;
Gizmos.DrawSphere(point.position, 0.05f);
}
}
}
}
Currently, it’s pretty jank as I’ve been experimenting with custom classes to store references to value types. This system is rather undesirable, and not very streamlined or intuitive.