Editor Scripting Confusion

Hi Guys,

I’m trying to keep the data of a List in a EditorWindow between plays, and it doesn’t seem to be working. I’ve followed https://blogs.unity3d.com/2012/10/25/unity-serialization/, but to no avail. Here is my code:

public class ArtistTools : EditorWindow
{
    #region Setups
    private AnimBool m_ShowSelectionOptions;

    private string[] m_Toolbars = new string[]
    {
        "General",
        "Asset Bundles"
    };

    [SerializeField]
    private class GameObjectLabel
    {
        public int Id;
        public string Message = "no message";
        public Texture2D Image;

        public GameObjectLabel(int id, string msg, Texture2D image)
        {
            Id = id;
            Message = msg;
            Image = image;
        }
    }
   
    private string m_AssetGroupName = "AssetBundleName";
    private string m_GameObjectLabel = "no message";
    private int m_ToolbarIndex = 0;
    private bool m_CrunchTextures = true;
    private bool m_ShowSlectionOptions = false;
    private bool m_Passed = true;
    private static bool m_ShowLabel = true;
    private static Texture2D m_GreenTick, m_RedCross;
   
    [SerializeField]
    private static List<GameObjectLabel> gameObjectLabels = new List<GameObjectLabel>(); // Thing I want to keep between plays
   
    private void OnEnable()
    {
        hideFlags = HideFlags.HideAndDontSave;

        m_GreenTick = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Runtime/green-tick.png") as Texture2D;
        m_RedCross = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Runtime/red-cross.png") as Texture2D;

        Selection.selectionChanged += CheckSelection;
        Repaint();
    }
    [MenuItem("Window/Artist Tools")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(ArtistTools), false, "Artist Tools");
    }
    #endregion

    private void OnGUI()
    {
        Texture2D logo = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Runtime/logo.png") as Texture2D;
        GUILayout.BeginVertical();
        GUILayout.Label(logo, GUILayout.MaxHeight(55));
        GUILayout.EndVertical();

       m_ToolbarIndex = GUILayout.Toolbar(m_ToolbarIndex, m_Toolbars);

        switch (m_ToolbarIndex)
        {
            case 0:
                {
                    GeneralView();
                    break;
                }
            case 1:
                {
                    AssetBundleView();
                    break;
                }
            case 2:
                {
                    break;
                }
            default:
                {
                    AssetBundleView();
                    break;
                }
        }
    }
    private void GeneralView()
    {
        GUIStyle someStyle = new GUIStyle();
        someStyle.border = new RectOffset(1, 1, 1, 1);
        GUILayout.BeginArea(new Rect(0, Screen.height - 130, Screen.width, 100));
        GUILayout.Label("Label Tools", EditorStyles.boldLabel);
       
        if (m_ShowLabel = GUILayout.Toggle(m_ShowLabel, new GUIContent("Active Labels", "Toggles visibility on labels in the scene.")))
        {
            Repaint();
            SceneView.RepaintAll();

            GUILayout.Space(10);

            if (m_ShowSlectionOptions)
            {
                GameObjectLabel label = gameObjectLabels.Find(go => go.Id == Selection.gameObjects[0].GetInstanceID());

                if (label != null)
                {
                    label.Message = EditorGUILayout.TextField("GameObject Label", label.Message);
                    m_Passed = GUILayout.Toggle(label.Image == m_GreenTick ? true : false, new GUIContent("Passed"));
                    label.Image = m_Passed ? m_GreenTick : m_RedCross;
                    m_GameObjectLabel = label.Message;

                    if (GUILayout.Button(new GUIContent("Remove Label")))
                    {
                        gameObjectLabels.Remove(label);
                    }
                }
                else
                {
                    m_GameObjectLabel = EditorGUILayout.TextField("GameObject Label", m_GameObjectLabel);
                    m_Passed = GUILayout.Toggle(m_Passed, new GUIContent("Passed"));

                    if (GUILayout.Button(new GUIContent("Add Label")))
                    {
                        gameObjectLabels.Add(new GameObjectLabel(Selection.gameObjects[0].GetInstanceID(), m_GameObjectLabel, m_Passed ? m_GreenTick : m_RedCross));
                    }
                }
            }
        }
       
        GUILayout.EndArea();
        GUILayout.Space(10);
    }
    [DrawGizmo(GizmoType.InSelectionHierarchy | GizmoType.NotInSelectionHierarchy)]
    private static void AddLabel(Transform transform, GizmoType gizmoType)
    {
        if (m_ShowLabel)
        {
            if(transform != null)
            {
                GameObjectLabel label = gameObjectLabels.Find(go => go.Id == transform.gameObject.GetInstanceID());

                if (label != null)
                {
                    GUIStyle labelStyle = new GUIStyle();
                    labelStyle.normal.textColor = Color.black;
                    labelStyle.alignment = TextAnchor.UpperLeft;
                    labelStyle.imagePosition = ImagePosition.ImageLeft;
                    Vector3 offset = transform.position + new Vector3(0, 1f, 0);

                    Handles.BeginGUI();
                    Handles.Label(offset, "GameObject: " + transform.gameObject.name, labelStyle);
                    Handles.Label(offset + new Vector3(0, -0.4f, 0), "Message: " + label.Message, labelStyle);
                    Handles.Label(offset + new Vector3(0, -0.5f, 0), label.Image);
                    Handles.EndGUI();
                }
            }
        }
    }

Does anyone know what I’m doing wrong? Must I use a ScriptableObject for this somewhere?

If the method you are talking about is OnGUI, than whatever script it is contained in, must be on a scene. The method itself doesn’t have to be referenced/used by any other object as it is one of the unity’s special methods/callbacks/messages. Or did you mean some other method?

Hi radwan,

The method in question is:

  • [DrawGizmo(GizmoType.InSelectionHierarchy | GizmoType.NotInSelectionHierarchy)]
  • private static void AddLabel(Transform transform, GizmoType gizmoType)

but I actually found the issue there and re-worded the question, lol. The reason that method is called is because DrawGizmo as a static function automatically draws objects in the scene I think, dis-regarding whether the method’s been called.

Great! Looks like that’s the idea behind this attribute