1
\$\begingroup\$

I searched for hours on google and Unity Documentation & forums for information or tutorials on how to do this, but I can't find anything.

I'm trying to write an editor script who'll allow me to edit a zone in the scene view.

I found a way to do it and it works, BUT I really find this solution not aesthetic at all, here's how it looked :

With arrows

And that's my code to achieve that :

[CustomEditor(typeof(CameraZone))]
public class CameraZoneEditor : Editor
{

    void OnSceneGUI()
    {
        var zone = (CameraZone)target;

        Handles.DrawSolidRectangleWithOutline(new Rect(zone.transform.position, zone.size), zone.editorColor, Color.black);
        Handles.color = Color.white;

        var center = zone.transform.position + ((Vector3)zone.size / 2);

        var handlesPos = new [] {
            new Vector3(center.x + zone.size.x / 2, center.y, center.z),
            new Vector3(center.x - zone.size.x / 2, center.y, center.z),
            new Vector3(center.x, center.y + zone.size.y / 2, center.z),
            new Vector3(center.x, center.y - zone.size.y / 2, center.z)
        };

        var posRight = Handles.Slider(handlesPos[0], Vector2.right);
        var posLeft = Handles.Slider(handlesPos[1], Vector2.left);
        var posUp = Handles.Slider(handlesPos[2], Vector2.up);
        var posDown = Handles.Slider(handlesPos[3], Vector2.down);

        var rect = new Rect(posLeft.x, posDown.y, posRight.x, posUp.y);
        zone.size = rect.size;
    }

}

This is working just how I want it to (except that the bottom and left arrows are not resizing the zone but that's not a problem for now).

Now to make it more beautiful, I wanted to replace the arrows with simple cubes, I've seen that I can do that with Handles.CubeHandleCap delegates so I made some to test it. It looks exactly how I want them to but I'm unable to resize the zone now, when I try to drag it it just unselect the GameObject.

Here's how it looks now :

With cubes

And here's the code I wrote to do that :

[CustomEditor(typeof(CameraZone))]
public class CameraZoneEditor : Editor
{

    void OnSceneGUI()
    {
        var zone = (CameraZone)target;

        Handles.DrawSolidRectangleWithOutline(new Rect(zone.transform.position, zone.size), zone.editorColor, Color.black);
        Handles.color = Color.white;

        var center = zone.transform.position + ((Vector3)zone.size / 2);

        var handlesPos = new [] {
            new Vector3(center.x + zone.size.x / 2, center.y, center.z),
            new Vector3(center.x - zone.size.x / 2, center.y, center.z),
            new Vector3(center.x, center.y + zone.size.y / 2, center.z),
            new Vector3(center.x, center.y - zone.size.y / 2, center.z)
        };

        Handles.CapFunction rightFunc = (id, position, rotation, size, type) => Handles.CubeHandleCap(0, handlesPos[0], Quaternion.identity, 0.2f, EventType.Repaint);
        Handles.CapFunction leftFunc = (id, position, rotation, size, type) => Handles.CubeHandleCap(0, handlesPos[1], Quaternion.identity, 0.2f, EventType.Repaint);
        Handles.CapFunction upFunc = (id, position, rotation, size, type) => Handles.CubeHandleCap(0, handlesPos[2], Quaternion.identity, 0.2f, EventType.Repaint);
        Handles.CapFunction downFunc = (id, position, rotation, size, type) => Handles.CubeHandleCap(0, handlesPos[3], Quaternion.identity, 0.2f, EventType.Repaint);

        var posRight = Handles.Slider(handlesPos[0], Vector2.right, 0.2f, rightFunc, 0.1f);
        var posLeft = Handles.Slider(handlesPos[1], Vector2.left, 0.2f, leftFunc, 0.1f);
        var posUp = Handles.Slider(handlesPos[2], Vector2.up, 0.2f, upFunc, 0.1f);
        var posDown = Handles.Slider(handlesPos[3], Vector2.down, 0.2f, downFunc, 0.1f);

        var rect = new Rect(posLeft.x, posDown.y, posRight.x, posUp.y);
        zone.size = rect.size;
    }

}
\$\endgroup\$

1 Answer 1

1
+50
\$\begingroup\$

Use FreeMoveHandle to draw custom shaped handles. Here you go.

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(CameraZone))]
public class CameraZoneEditor : Editor
{

    void OnSceneGUI()
    {
        var zone = (CameraZone)target;

        var center = zone.transform.position;

        Handles.DrawSolidRectangleWithOutline(new Rect(zone.transform.position - ((Vector3)zone.size / 2), zone.size), zone.editorColor, Color.black);
        Handles.color = Color.white;

        var handlesPos = new [] {
            new Vector3(center.x + zone.size.x / 2, center.y, center.z),
            new Vector3(center.x - zone.size.x / 2, center.y, center.z),
            new Vector3(center.x, center.y + zone.size.y / 2, center.z),
            new Vector3(center.x, center.y - zone.size.y / 2, center.z)
        };

        float size = HandleUtility.GetHandleSize(zone.transform.position) * 0.2f;
        Vector3 snap = Vector3.one * 0.5f;

        EditorGUI.BeginChangeCheck();
        Vector3 hPos0 = Handles.FreeMoveHandle(handlesPos[0], Quaternion.identity, size, snap, Handles.CubeHandleCap);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(zone, "Changed Scale");
            float offset = (hPos0.x - handlesPos [0].x)/2f;
            zone.transform.position += new Vector3 (offset, 0, 0);      
            zone.size = new Vector2 (hPos0.x - handlesPos [1].x, handlesPos [2].y - handlesPos [3].y);
        }

        EditorGUI.BeginChangeCheck();
        Vector3 hPos1 = Handles.FreeMoveHandle(handlesPos[1], Quaternion.identity, size, snap, Handles.CubeHandleCap);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(zone, "Changed Scale");
            float offset = (hPos1.x - handlesPos [1].x)/2f;
            zone.transform.position += new Vector3 (offset, 0, 0);
            zone.size = new Vector2 (handlesPos [0].x - hPos1.x, handlesPos [2].y - handlesPos [3].y);

        }
        EditorGUI.BeginChangeCheck();
        Vector3 hPos2 = Handles.FreeMoveHandle(handlesPos[2], Quaternion.identity, size, snap, Handles.CubeHandleCap);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(zone, "Changed Scale");
            float offset = (hPos2.y - handlesPos [2].y)/2f;
            zone.transform.position += new Vector3 (0, offset, 0);
            zone.size = new Vector2 (handlesPos [0].x - handlesPos [1].x, hPos2.y - handlesPos [3].y);
        }
        EditorGUI.BeginChangeCheck();
        Vector3 hPos3= Handles.FreeMoveHandle(handlesPos[3], Quaternion.identity, size, snap, Handles.CubeHandleCap);
        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(zone, "Changed Scale");
            float offset = (hPos3.y - handlesPos[3].y)/2f;
            zone.transform.position += new Vector3 (0, offset, 0);
            zone.size = new Vector2 (handlesPos [0].x - handlesPos [1].x, handlesPos [2].y - hPos3.y);
        }


    }
}
\$\endgroup\$
4
  • \$\begingroup\$ Perfect ! Thank you very much it works like a charm. Strange thing I couldn't find any documentation or example on this tho. \$\endgroup\$ Commented Mar 28, 2018 at 4:41
  • \$\begingroup\$ Happy to help! The documentation is there, but yeah it is kinda hard to get to through relevant searches. \$\endgroup\$
    – Aj_
    Commented Mar 28, 2018 at 13:23
  • \$\begingroup\$ Yes the documentation is there but it looks like this is such an underused feature of Unity that nobody took care of making a guide on this. \$\endgroup\$ Commented Mar 28, 2018 at 13:24
  • \$\begingroup\$ Agree. Even I was having lot of troubles back when I was trying to implement something similar. \$\endgroup\$
    – Aj_
    Commented Mar 28, 2018 at 13:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .