Custom Editor Window for a Built-In Array?

I would like to build a custom editor window for a built-in array. A built-in array works fine for what I’m doing, but as it’s displaying a class, this can be difficult to downright annoying to edit in the dropdowns in the inspector.

I’ve started working with extending EditorWindow, but I’m having a difficult time grabbing the array from the scene, and then writing back to it.

With this basic code I can make a window and access the information from the array:

class InventoryItemEditor extends EditorWindow {
    static var myInventoryObject : GameObject;
    static var myInventory : InventoryItem[];
    var myIndex : int = 1;
    var field01 : String;
    var field02 : Texture2D;
    var field03 : SlotType;
    @MenuItem ("Window/Inventory Editor")
    static function Init () {
        // Get existing open window or if none, make a new one:
        var window : InventoryItemEditor = EditorWindow.GetWindow (InventoryItemEditor);
        myInventoryObject = GameObject.Find("InventoryManager");
        myInventory = GameObject.Find("InventoryManager").GetComponent(ItemList).items;
    }
    
    function OnGUI () {
        GUILayout.Label ("Base Settings", EditorStyles.boldLabel);
            myIndex = EditorGUILayout.IntField ("Item Number", myIndex);
            if (myIndex > myInventory.Length)
            	myIndex = myInventory.Length;
            if (myIndex < 1)
            	myIndex = 1;
            field01 = EditorGUILayout.TextField ("Item Name", myInventory[myIndex-1].itemName as String);
            field02 = EditorGUILayout.ObjectField ("Item Icon", myInventory[myIndex-1].itemIcon, Texture2D);
            field03 = EditorGUILayout.EnumPopup ("Slot Type", myInventory[myIndex-1].slotType);
            EditorUtility.SetDirty(myInventoryObject);
    }
}

What I want to do with this code is create one “page” per slot in the array, for ease of viewing, editing and understanding the contents of each slot.

At this point where I THINK I’m having trouble is with:
static var myInventory : InventoryItem[ ];

This isn’t acting like a reference. When I change a value in field01, the changes are not written to the array. Essentially the data is constantly being reverted, rather than this window updating the array. If I don’t make “myInventory” static, then I get the error: “Assets/Editor/InventoryItemEditor.js(11,9): BCE0020: An instance of type ‘InventoryItemEditor’ is required to access non static member ‘myInventory’.”.

And I must make this field static, or it won’t compile. I believe this could also be related to dealing with an instance in a scene from an editor window - but clearly the inspector can do it, so why can’t I?

Eventually I’d also like to have the ability to resize the array, etc., but I can get to that later. I see GUI buttons for next and back that increment or decrement the index and checks against string/names to make sure they are unique.

Any hints and suggestions about how to grab this array in edit time and be able to muscle it around?

Is there a better approach than an editor window?

I found: EditorUtility.SetDirty(myInventoryObject);, which I’ve added to the code above, but nope, didn’t do what I wanted. This editor window is displaying correctly, but not saving changes to the array, and the fields are reverting back to what the array contains when I leave a field.

Got it:

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

public class InventoryItemEditor : EditorWindow {
	InventoryItem[] myInventory;
	int myIndex = 1;
	
    [MenuItem ("Window/Inventory Editor")]
	static void  Init (){
		// Get existing open window or if none, make a new one:
		EditorWindow.GetWindow (typeof (InventoryItemEditor));
	}
	
	void  OnEnable (){
		myInventory = GameObject.Find("InventoryManager").GetComponent<ItemList>().items;
	}

	void  OnGUI (){
		GUILayout.Label ("Inventory Item Editor", EditorStyles.boldLabel);
		
		if (myIndex > myInventory.Length)
			myIndex = myInventory.Length;
		if (myIndex < 1)
			myIndex = 1;
		
		myIndex = EditorGUILayout.IntField (myIndex);
		myInventory[myIndex-1].itemName = EditorGUILayout.TextField ("Item Name", myInventory[myIndex-1].itemName as string);
		myInventory[myIndex-1].itemIcon = (Texture2D)EditorGUILayout.ObjectField ("Item Icon", myInventory[myIndex-1].itemIcon, typeof (Texture2D));
		myInventory[myIndex-1].slotType = EditorGUILayout.EnumPopup ("Slot Type", myInventory[myIndex-1].slotType);
	}
}

4 years ago dude… He wasn’t a member back then, he is now.

I certainly don’t know everything, that’s for sure. I’m asking things all the time!

But… yeah, that was a while ago.

1 Like