Buttons Placed After Field Not Working Properly?

Ok, weird one.
I’m trying to extend the default transform controls to give me a more streamlined approach to working… not going well.

So, in the snippet below I can reset the position by clicking the “R” reset button (sets localPosition to 0,0,0), and “C” seems to work, but “V” doesn’t do anything at all. Unless I delete the Vector3 field entirely, then it does stuff, just not the right stuff (it seems to function like “R” and pushes the object back to 0,0,0).

using (new EditorGUILayout.HorizontalScope())
                {
                    if(GUILayout.Button("R", this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");
                      
                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localPosition = new Vector3(0, 0, 0);
                        }
                    }

                    //Position
                    EditorGUI.BeginChangeCheck();
                    localPosition = EditorGUILayout.Vector3Field("Position", _transform.localPosition);
                    if(EditorGUI.EndChangeCheck())
                    {

                    }

                    if(GUILayout.Button("C", this.btnSmall))
                    {
                        _clipboard = _transform.localPosition;
                    }

                    if(GUILayout.Button("V", this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");

                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localPosition = _clipboard;
                        }
                    }
                }

I have absolutely no idea what’s going on here and have been swapping between staring at this code and staring at the web for answers for the better part of a couple hours now to no avail. So I thought I’d ask the experts.

Any ideas what I’m doing wrong?

Edit: _transform is set as “_transform = target as Transform” at the top of OnInspectorGUI.

This looks like a copy/paste type situation, if I read your C and V correctly.

That makes me think, what is _clipboard? If it isn’t static, then it might be a different instance of that Vector3 by the time you get to the new object. You could experiment with setting it static (after all you only have one global ‘clipboard’ generally speaking), or else use Debug.Log() to print the values going into it / coming out of it.

I was trying to create a unique (non system-wide) clipboard, just for the transforms.
I’ve never really done this and although I’ve done a couple small editor windows before I’ve never really modified/replaced any existing features before, so I think I’m making quite a few mistakes here.
Here’s the full script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using UnityEngine.SocialPlatforms;

[CustomEditor(typeof(Transform))]
[CanEditMultipleObjects]
public class ArcaneTransformExtension : Editor
{
    //Built-in editor
    Editor defaultEditor;

    private Transform _transform;
    private Vector3 _clipboard;

    bool localSpace = true;
    bool worldSpace = false;

    GUIStyle btnSmall;
    GUIStyle btnNorm;

    bool posLock = false;
    bool rotLock = false;
    bool scaLock = false;

    void OnEnable()
    {
        //Called when inspector is created
        defaultEditor = Editor.CreateEditor(targets, Type.GetType("UnityEditor.TransformInspector, UnityEditor"));
        _transform = target as Transform;
    }

    void OnDisable()
    {
        //Prevents memory leakage
        MethodInfo disableMethod = defaultEditor.GetType().GetMethod("OnDisable", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

        if(disableMethod != null)
        {
            disableMethod.Invoke(defaultEditor, null);
        }

        DestroyImmediate(defaultEditor);
    }

    public override void OnInspectorGUI()
    {
        _transform = target as Transform;

        Vector3 localPosition = new Vector3();
        Vector3 localRotation = new Vector3();
        Vector3 localScale = new Vector3();

        btnSmall = new GUIStyle("ShurikenModuleTitle");
        //btnSmall = new GUIStyle(EditorStyles.toolbarButton);
        btnSmall.fixedHeight = 20;
        btnSmall.fixedWidth = 20;
        btnSmall.padding = new RectOffset(-10, 0, 0, 0);
        btnSmall.margin = new RectOffset(0, 4, 2, 0);

        btnNorm = new GUIStyle("ShurikenModuleTitle");
        btnNorm.margin = new RectOffset(0, 0, 4, 0);

        GUIStyle labelSmall = new GUIStyle("label");
        labelSmall.fixedWidth = EditorGUIUtility.currentViewWidth - 67;

        GUIStyle padlockBool = new GUIStyle("IN LockButton");

        GUIStyle arcIcon = new GUIStyle();
        arcIcon.fixedHeight = 20;
        arcIcon.fixedWidth = 20;
        arcIcon.margin = new RectOffset(16, 0, 3, 0);

        //If Arcane Transform Extension is enabled
        if (EditorPrefs.GetBool("arcaneTransformExtension") == true)
        {
            OnHeaderGUI();

            if (GUILayout.Button("Disable Arcane Transform Extension", this.btnNorm))
            {
                EditorPrefs.SetBool("arcaneTransformExtension", false);
                Repaint();
            }

            localSpace = Foldout("Local Space", localSpace);
            if (localSpace)
            {
                //defaultEditor.OnInspectorGUI();
                using (new EditorGUILayout.HorizontalScope())
                {
                    //GUILayout.Box(EditorGUIUtility.FindTexture("Prefab Icon"), arcIcon);
                    GUILayout.Box(EditorGUIUtility.FindTexture("d_ToolHandleLocal"), arcIcon);
                    GUILayout.Label("Local Position", labelSmall);
                    posLock = EditorGUILayout.Toggle(posLock, padlockBool);
                }
                using (new EditorGUILayout.HorizontalScope())
                {
                    GUI.enabled = !posLock;

                    if(GUILayout.Button(new GUIContent("R", "Set object position to zero"), this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");
                       
                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localPosition = new Vector3(0, 0, 0);
                        }
                    }

                    //Position
                    EditorGUI.BeginChangeCheck();
                    localPosition = EditorGUILayout.Vector3Field("", _transform.localPosition);
                    if(EditorGUI.EndChangeCheck())
                    {

                    }

                    if(GUILayout.Button(new GUIContent("C", "Copy object position to clipboard"), this.btnSmall))
                    {
                        _clipboard = _transform.localPosition;
                    }

                    if(GUILayout.Button(new GUIContent("V", "Paste clipboard into object position"), this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");

                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localPosition = _clipboard;
                        }
                    }

                    GUI.enabled = true;
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    GUILayout.Box(EditorGUIUtility.FindTexture("d_ToolHandleLocal"), arcIcon);
                    GUILayout.Label("Local Rotation", labelSmall);
                    rotLock = EditorGUILayout.Toggle(rotLock, padlockBool);
                }
                using (new EditorGUILayout.HorizontalScope())
                {
                    GUI.enabled = !rotLock;

                    if (GUILayout.Button(new GUIContent("R", "Set object rotation to zero"), this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");

                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localEulerAngles = new Vector3(0, 0, 0);
                        }
                    }

                    //Rotation
                    EditorGUI.BeginChangeCheck();
                    localRotation = EditorGUILayout.Vector3Field("", _transform.localEulerAngles);
                    if (EditorGUI.EndChangeCheck())
                    {
                       
                    }

                    if (GUILayout.Button(new GUIContent("C", "Copy object rotation to clipboard"), this.btnSmall))
                    {
                        _clipboard = _transform.localEulerAngles;
                    }

                    if (GUILayout.Button(new GUIContent("V", "Paste clipboard into object rotation"), this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");

                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localEulerAngles = _clipboard;
                        }
                    }

                    GUI.enabled = true;
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    GUILayout.Box(EditorGUIUtility.FindTexture("d_ToolHandleGlobal"), arcIcon);
                    GUILayout.Label("Local Scale", labelSmall);
                    scaLock = EditorGUILayout.Toggle(scaLock, padlockBool);
                }
               
                using (new EditorGUILayout.HorizontalScope())
                {
                    GUI.enabled = !scaLock;

                    if (GUILayout.Button(new GUIContent("R", "Set object scale to one"), this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");
                       
                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localScale = new Vector3(1, 1, 1);
                        }
                    }

                    //Scale
                    EditorGUI.BeginChangeCheck();
                    localScale = EditorGUILayout.Vector3Field("", _transform.localScale);
                    if(EditorGUI.EndChangeCheck())
                    {
                       
                    }

                    if (GUILayout.Button(new GUIContent("C", "Copy object scale to clipboard"), this.btnSmall))
                    {
                        _clipboard = _transform.localScale;
                    }

                    if (GUILayout.Button(new GUIContent("V", "Paste clipboard into object scale"), this.btnSmall))
                    {
                        Undo.RecordObject(_transform, "Transform Changed");
                       
                        foreach (Transform tform in Selection.transforms)
                        {
                            tform.localScale = _clipboard;
                        }
                    }

                    GUI.enabled = true;
                }

                if(GUI.changed)
                {
                    Undo.RecordObject(_transform, "Transform Changed");
                    _transform.localPosition = localPosition;
                    _transform.localEulerAngles = localRotation;
                    _transform.localScale = localScale;
                }
            }

            //EditorGUILayout.Space();

            worldSpace = Foldout("World Space", worldSpace);
            if (worldSpace)
            {

            }
        }
        else //Use default Editor
        {
            if (GUILayout.Button("Enable Arcane Transform Extension", this.btnNorm))
            {
                EditorPrefs.SetBool("arcaneTransformExtension", true);
                Repaint();
            }
            defaultEditor.OnInspectorGUI();
        }
    }

    public static bool Foldout(string title, bool display)
    {
        var style = new GUIStyle("ShurikenModuleTitle");
        style.font = new GUIStyle(EditorStyles.label).font;
        style.border = new RectOffset(15, 7, 4, 4);
        style.fixedHeight = 22;
        style.contentOffset = new Vector2(20f, -2f);

        var rect = GUILayoutUtility.GetRect(16f, 22f, style);
        GUI.Box(rect, title, style);

        var e = Event.current;

        var toggleRect = new Rect(rect.x + 4f, rect.y + 2f, 13f, 13f);
        if (e.type == EventType.Repaint)
        {
            EditorStyles.foldout.Draw(toggleRect, false, false, display, false);
        }

        if (e.type == EventType.MouseDown && rect.Contains(e.mousePosition))
        {
            display = !display;
            e.Use();
        }

        return display;
    }

    protected override void OnHeaderGUI()
    {
        Color proColor = (Color)new Color32(56, 56, 56, 255);
        Color noProColor = (Color)new Color32(194, 194, 194, 255);
        //base.OnHeaderGUI();
        var rect = EditorGUILayout.GetControlRect(false, 0f);
        rect.height = EditorGUIUtility.singleLineHeight;
        rect.y -= rect.height;
        rect.x = 48;
        rect.xMax -= rect.x * 2f;

        EditorGUI.DrawRect(rect, EditorGUIUtility.isProSkin ? proColor : noProColor);

        string header = "Arcane Transform";

        EditorGUI.LabelField(rect, header, EditorStyles.boldLabel);
    }
}