0
\$\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
+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\$
  • \$\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\$ – Antoine Thiry Mar 28 '18 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_ Mar 28 '18 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\$ – Antoine Thiry Mar 28 '18 at 13:24
  • \$\begingroup\$ Agree. Even I was having lot of troubles back when I was trying to implement something similar. \$\endgroup\$ – Aj_ Mar 28 '18 at 13:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.