UnityEditor items editor question

Hello,
My question may be simple but for me it’s a bit hard and i think that any answer can help with this.
The question [questions] is how can i improve this script? As you can see i’ve wrote all Item subclasses and fields within those subclasses but it’s really annoying to write those lines over and over again. I know that in C# i could use something like AppDomain.GetAssemblies() and then loop through all classes to check if IsSubclassOf( Item ).
I’ve tried that and it didnt work so maybe you have some other options. Thank you for your time spent in here and for help.

Regards,
M.Rogalski

ItemsEditorConfiguration.cs :

using UnityEngine;
using System;

namespace InterArts.ItemsEditor
{
    public enum ITEM_TYPES : uint { Weapon, Shield, Armour, Legs, Boots, Helmet, Food, Potion, Quest }

    public static class ItemsEditorConfiguration
    {
        private const string G_IA_EDITOR_PATH = "/Resources/Items";
        private const string G_IA_XML_PATH = "/Items.xml";
        private const string G_IA_SPRITES_PATH = "/Sprites";
        private const string G_IA_RESOURCE_PATH = "Items";

        private const int G_IA_LIST_WIDTH = 300;
        private const int G_IA_FIELDS_WIDTH = 500;
        private const int G_IA_TYPE_COLUMNS = 5;

        private static string[] G_IA_TYPES = Enum.GetNames(typeof(ITEM_TYPES));
        private static string G_IA_XML_FILE = G_IA_RESOURCE_PATH + "/Items";

        public static string s_ResourcesMain
        {
            get{ return G_IA_RESOURCE_PATH; }
        }

        public static string s_ResourcesSprites
        {
            get{ return G_IA_RESOURCE_PATH + G_IA_SPRITES_PATH; }
        }

        public static int s_ListWidth
        {
            get{ return G_IA_LIST_WIDTH; }
        }

        public static int s_FieldsWidth
        {
            get{ return G_IA_FIELDS_WIDTH; }
        }

        public static int s_TypeColumns
        {
            get{ return G_IA_TYPE_COLUMNS; }
        }

        public static string s_SpritesPath
        {
            get{ return s_MainPath + G_IA_SPRITES_PATH; }
        }

        public static string[] s_Types
        {
            get{ return G_IA_TYPES; }
            private set{ G_IA_TYPES = value; }
        }

        public static TextAsset s_XmlFile
        {
            get{ return (TextAsset)Resources.Load (G_IA_XML_FILE); }
        }

        public static string s_MainPath
        {
            get{ return Application.dataPath + G_IA_EDITOR_PATH; }
        }

        public static string s_XmlPath
        {
            get{ return s_MainPath + G_IA_XML_PATH; }
        }
    }
}

ItemsEditor.cs :

using UnityEditor;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using System.Text;
using System;
using InterArts.ItemsEditor;
using EDITOR_CONFIG = InterArts.ItemsEditor.ItemsEditorConfiguration;

public class ItemsEditor : EditorWindow
{
    private int m_SelectedType = 0;
    private int m_SelectedItem = 0;

    private string[] m_ItemsList = new string[]{""};

    private string m_ItemName = "item name";
    private string m_ItemDescription = "item description";
    private Texture2D m_ItemSprite = new Texture2D(1,1);
    private int m_ItemWeight = 0;
    private bool m_ItemStackable = false;

    private int m_WeaponAttack = 0;

    private ItemsCollection m_ItemsCollection;

    private Vector2 m_ItemsListScroll = Vector2.zero;
    private Vector2 m_EditorScroll = Vector2.zero;

    [MenuItem("InterArts/Items editor")]
    public static void Init()
    {
        EditorWindow.GetWindow(typeof(ItemsEditor));
        if(!Directory.Exists(EDITOR_CONFIG.s_MainPath))
            Directory.CreateDirectory(EDITOR_CONFIG.s_MainPath);

        if(!Directory.Exists(EDITOR_CONFIG.s_SpritesPath))
            Directory.CreateDirectory(EDITOR_CONFIG.s_SpritesPath);
    }

    public void OnGUI()
    {
        if(m_ItemsCollection == null)
            LoadItems ();
        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();

        EditorGUILayout.LabelField("IA :: Items Editor [ v 0.0.2a ]", EditorStyles.boldLabel);

        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));

        EditorGUILayout.BeginVertical(GUILayout.Width(EDITOR_CONFIG.s_ListWidth));

        EditorGUILayout.LabelField("Items database", EditorStyles.boldLabel);
        m_ItemsListScroll = EditorGUILayout.BeginScrollView(m_ItemsListScroll, false, false);
        m_SelectedItem = GUILayout.SelectionGrid(m_SelectedItem, m_ItemsList, 1, EditorStyles.radioButton);
        EditorGUILayout.EndScrollView();

        GUILayout.Space(10);
        if(GUILayout.Button("RefreshItemsNames items list"))
            LoadItems();

        EditorGUILayout.BeginHorizontal();
        if(GUILayout.Button(" << "))
        {
            if(m_SelectedItem - 1 >= 0)
                m_SelectedItem = GUILayout.SelectionGrid(m_SelectedItem - 1, m_ItemsList, 1, EditorStyles.radioButton);
        }

        if(GUILayout.Button("Add"))
            AddEmptyItem();

        if(GUILayout.Button("Edit"))
            EditItem(m_SelectedItem);

        if(GUILayout.Button("Delete"))
            DeleteItem(m_SelectedItem);

        if(GUILayout.Button(" >> "))
        {
            if(m_SelectedItem + 1 < m_ItemsCollection.ItemsDatabase.Count)
                m_SelectedItem = GUILayout.SelectionGrid(m_SelectedItem + 1, m_ItemsList, 1, EditorStyles.radioButton);
        }
        EditorGUILayout.EndHorizontal();

        if(GUILayout.Button("Save items list"))
            SaveItems();

        EditorGUILayout.EndVertical();

        GUILayout.Space(20);

        EditorGUILayout.BeginVertical();
        GUILayout.Label("Item editor window", EditorStyles.boldLabel);
        m_EditorScroll = EditorGUILayout.BeginScrollView(m_EditorScroll, false, false);
        EditorGUILayout.BeginHorizontal();
        m_SelectedType = GUILayout.SelectionGrid(m_SelectedType, EDITOR_CONFIG.s_Types, EDITOR_CONFIG.s_TypeColumns, EditorStyles.radioButton);
        EditorGUILayout.EndHorizontal();

        GUILayout.Space(10);

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Item name: ");
        m_ItemName = EditorGUILayout.TextField(m_ItemName, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Item description: ");
        m_ItemDescription = EditorGUILayout.TextArea(m_ItemDescription, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Item sprite: ");
        m_ItemSprite = EditorGUILayout.ObjectField(m_ItemSprite, typeof(Texture2D), false, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth)) as Texture2D;
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Item weight: ");
        m_ItemWeight = EditorGUILayout.IntField(m_ItemWeight, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Stackable: ");
        m_ItemStackable = EditorGUILayout.Toggle(m_ItemStackable, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        EditorGUILayout.EndHorizontal();

        DrawEditor(m_SelectedType);

        if(GUILayout.Button("Save changes", GUILayout.ExpandWidth(true)))
            ChangeItem(m_SelectedItem);

        EditorGUILayout.EndScrollView();
        EditorGUILayout.EndVertical();

        EditorGUILayout.EndHorizontal();

        GUILayout.Space(10);
    }

    private void ChangeItem(int i)
    {
        string filename = m_ItemsCollection.ItemsDatabase[m_SelectedItem].m_ID + "__" + m_ItemName;
        string oldName = m_ItemSprite.name;
        m_ItemSprite.name = filename;
        AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(m_ItemSprite), Application.dataPath + "/Resources/Items/Sprites/");

        if(EDITOR_CONFIG.s_Types[m_SelectedType].Equals(Enum.GetName(typeof(ITEM_TYPES), ITEM_TYPES.Weapon)))
        {
            Weapon it = new Weapon(m_ItemsCollection.ItemsDatabase[i].m_ID, m_ItemName, m_ItemDescription, "Items/Sprites/" + filename, m_ItemWeight, m_ItemStackable, m_WeaponAttack);
            m_ItemsCollection.ItemsDatabase[i] = it;
        }

        SaveItems();
        m_ItemSprite.name = oldName;
    }

    private void EditItem(int i)
    {
        m_ItemName = GUILayout.TextField(m_ItemsCollection.ItemsDatabase[i].m_Name, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        m_ItemDescription = GUILayout.TextArea(m_ItemsCollection.ItemsDatabase[i].m_Description, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        m_ItemSprite = EditorGUILayout.ObjectField(m_ItemsCollection.ItemsDatabase[i].m_Sprite, typeof(Texture2D), false, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth)) as Texture2D;

        if(m_ItemsCollection.ItemsDatabase[i] is Weapon)
            m_SelectedType = 0;
    }

    private void DeleteItem(int i)
    {
        if(m_ItemsCollection.ItemsDatabase[i] != null)
            m_ItemsCollection.ItemsDatabase.RemoveAt(i);

        RefreshItemsNames();
    }

    private void AddEmptyItem()
    {
        Item i = new Item(m_ItemsCollection.ItemsDatabase.Count, "Unnamed", "", "", 0, false);
        m_ItemsCollection.ItemsDatabase.Add(i);
        m_SelectedItem = m_ItemsCollection.ItemsDatabase.Count - 1;
        RefreshItemsNames();
    }

    private void DrawEditor(int s)
    {
        EditorGUILayout.BeginHorizontal();

        if(EDITOR_CONFIG.s_Types[m_SelectedType].Equals(Enum.GetName(typeof(ITEM_TYPES), ITEM_TYPES.Weapon)))
        {   
            EditorGUILayout.LabelField("Weapon attack:");
            m_WeaponAttack = EditorGUILayout.IntField(m_WeaponAttack, GUILayout.Width(EDITOR_CONFIG.s_FieldsWidth));
        }

        EditorGUILayout.EndHorizontal();
    }

    private void RefreshItemsNames()
    {
        if(m_ItemsCollection.ItemsDatabase.Count == 0)
        {
            m_ItemsList = new string[1] { "There are no items yet." };
            return;
        }
        m_ItemsList = new string[m_ItemsCollection.ItemsDatabase.Count];
        for(int i = 0; i < m_ItemsCollection.ItemsDatabase.Count; i++)
        {
            string str = "{0} :: {1}";
            m_ItemsList[i] = string.Format(str, m_ItemsCollection.ItemsDatabase[i].m_ID, m_ItemsCollection.ItemsDatabase[i].m_Name);
        }
    }

    private void LoadItems()
    {
        Debug.Log ("Loading Items.xml file...");
        AssetDatabase.Refresh();
        m_ItemsCollection = new ItemsCollection();
        if(File.Exists(EDITOR_CONFIG.s_XmlPath))
        {
            XmlSerializer _XmlSerializer = new XmlSerializer(typeof(ItemsCollection));
            using (TextReader _Stream = new StringReader(EDITOR_CONFIG.s_XmlFile.text))
                m_ItemsCollection = (ItemsCollection)_XmlSerializer.Deserialize(_Stream);
        }
        RefreshItemsNames();
        Debug.Log ("Items.xml loaded!");
    }

    private void SaveItems()
    {
        Debug.Log ("Saving Items.xml file...");

        XmlSerializer _XmlSerializer = new XmlSerializer(typeof(ItemsCollection));
        using (StreamWriter _Stream = new StreamWriter(EDITOR_CONFIG.s_XmlPath, false))
            _XmlSerializer.Serialize(_Stream, m_ItemsCollection);

        RefreshItemsNames ();
        AssetDatabase.Refresh();
        Debug.Log ("Items.xml saved!");
    }
}

This?

            List<Type> types = new List<Type>();
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                foreach (Type type in assembly.GetTypes())
                {
                    if (typeof(Item).IsAssignableFrom(type))
                        types.Add(type);
                }
            }
1 Like

I dont know but i’t throws some errors yesterday and now it’s working. Thank you for this solution.

And if anyone would like to test this editor i’ll post it in the asset store and google drive:
https://drive.google.com/file/d/0B_3K9HN-LHbHU29KWjExU29xWTA/edit?usp=sharing

Again thank you for this post :slight_smile: