Custom Inspector for a list of custom class members.
I am trying to make an in-editor content creator for my strategy game. I thought it was the easiest way to do it rather then type XML or hardcode class instances; output it as XML and save. But unfortunately I ran into inability to edit list members' appearance and limit values to an extent I need.
My goal is to prevent MaxElevation and MaxHumidity from having lower values then MinElevation and MinHumidity respectively in each member. (From there I can draw analogy to apply to more tricky parts of other content generators)
My MonoBehaviour (do not mind the methods of BiomM) :
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using System;
 
 public class BiomsListGenerator : MonoBehaviour
 {
     public List<BiomM> bioms;
 
     public void Load ()
     {
         bioms = new List<BiomM> ();
         foreach (string key in DataHub.Bioms.Keys) {
             bioms.Add (BiomM.BiomToBiomM (key, DataHub.Bioms [key]));
         }
     }
 
     public void Save ()
     {
         List<BiomContainer.BiomSaveFormat> biomsSF = new List<BiomContainer.BiomSaveFormat> ();
         foreach (BiomM biom in bioms) {
             biomsSF.Add (BiomM.BiomMToBiom (biom));
         }
         BiomContainer.Save (biomsSF);
     }
 }
 
  //All you need to know are the properties of that class.
 
 [System.Serializable]
 public class BiomM
 {
 
     public string name;
 
     public string officialName;
 
     [Range (0f, 1000f)]
     public float minElevation;
 
     [Range (0f, 1000f)]
     public float maxElevation;
 
     [Range (0f, 1000f)]
     public float minHumidity;
 
     [Range (0f, 1000f)]
     public float maxHumidity;
 
     public bool primary;
 
     public GameObject modelPrefab;
 
     public GameObject guiPrifab;
 
     public BiomM (string name, string officialName, float minElevation, float minHumidity, float maxElevation, float maxHumidity, bool primary, GameObject modelPrefabName, GameObject guiPrifabName)
     {
         this.name = name;
         this.officialName = officialName;
         this.minElevation = minElevation;
         this.minHumidity = minHumidity;
         this.maxElevation = maxElevation;
         this.maxHumidity = maxHumidity;
         this.primary = primary;
         this.modelPrefab = modelPrefabName;
         this.guiPrifab = guiPrifabName;
     }
     public static BiomContainer.BiomSaveFormat BiomMToBiom (BiomM bm)
     {
         string s1 = "";
         string s2 = "";
         try {
             s1 = bm.modelPrefab.name;
         } catch {
         }
         try {
             s2 = bm.guiPrifab.name;
         } catch {
         }
         return new BiomContainer.BiomSaveFormat (bm.name, new Biom (bm.officialName, bm.minElevation / 1000, bm.minHumidity / 1000, bm.maxElevation / 1000, bm.maxHumidity / 1000, bm.primary, s1, s2));
     }
 
     public static BiomM BiomToBiomM (string name, Biom biom)
     {
         return new BiomM (
             name,
             biom.officialName,
             biom.minElevation * 1000,
             biom.minHumidity * 1000,
             biom.maxElevation * 1000,
             biom.maxHumidity * 1000,
             biom.primary,
             Resources.Load (BiomContainer.modelPrefabFolderPath + biom.modelPrefabName) as GameObject,
             Resources.Load (BiomContainer.guiPrefabFolderPath + biom.guiPrifabName) as GameObject
         );
     }
 
 
     public static BiomM BiomToBiomM (BiomContainer.BiomSaveFormat b)
     {
         return BiomToBiomM (b.key,b.biom);
     }
 }
 
 
               My Editor Script:
 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 
 [CustomEditor (typeof(BiomsListGenerator))]
 public class  BiomsListGeneratorEditor: Editor
 {
 
 
     public override void OnInspectorGUI ()
     {
 
         BiomsListGenerator blg = (BiomsListGenerator)target;
 
         DrawDefaultInspector (); //what should replace this?
 
         if (GUILayout.Button ("Load")) {
             blg.Load ();
         }
         if (GUILayout.Button ("Save")) {
             blg.Save ();
         }
     }
 }
 
              Answer by Adam-Mechtley · Oct 10, 2016 at 07:57 AM
Could you achieve this using a PropertyDrawer for the BioM type?
Yes! Thank you very much! I just overlooked that class because I focused too much on word "Editor". Solution is below if you are interested.
Answer by Daniil-Besedin · Oct 10, 2016 at 03:38 PM
Here is the end result for those who are interested (new Editor Script):
 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 using System.Collections.Generic;
 
 [CustomEditor (typeof(BiomsListGenerator))]
 public class  BiomsListGeneratorEditor: Editor
 {
 
     public Dictionary<int,bool> dictionary = new Dictionary<int, bool> ();
 
     public override void OnInspectorGUI ()
     {
         
         BiomsListGenerator blg = (BiomsListGenerator)target;
         serializedObject.Update ();
         SerializedProperty myIterator = serializedObject.FindProperty ("bioms");
         for (int i = 0; i < short.MaxValue; i++) {
             if (!dictionary.ContainsKey (i)) {
                 dictionary [i] = false;
             }
             if (i >= 3) {
                 dictionary [i] = EditorGUILayout.Foldout (dictionary [i], myIterator.FindPropertyRelative ("officialName").stringValue);
             }
             if (dictionary [i] && i >= 3) {
                 EditorGUILayout.PropertyField (myIterator);
                 EditorGUILayout.BeginHorizontal ();
                 if (GUILayout.Button ("Copy")) {
                     serializedObject.FindProperty ("bioms").InsertArrayElementAtIndex (i - 3);
                 }
                 if (GUILayout.Button ("Delete")) {
                     serializedObject.FindProperty ("bioms").DeleteArrayElementAtIndex (i - 3);
                 }
                 EditorGUILayout.EndHorizontal ();
                 EditorGUILayout.Space ();
                 EditorGUILayout.Space ();
             }
             if (!myIterator.Next (i < 3)) {
                 break;
             }
         }
         serializedObject.ApplyModifiedProperties ();
 
         if (GUILayout.Button ("Load")) {
             blg.Load ();
         }
         if (GUILayout.Button ("Save")) {
             blg.Save ();
         }
     }
 }
 
 
 [CustomPropertyDrawer (typeof(BiomM))]
 public class BiomMpd : PropertyDrawer
 {
 
     public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
     {
         float minElevation = property.FindPropertyRelative ("minElevation").floatValue;
         float maxElevation = property.FindPropertyRelative ("maxElevation").floatValue;
 
         float minHumidity = property.FindPropertyRelative ("minHumidity").floatValue;
         float maxHumidity = property.FindPropertyRelative ("maxHumidity").floatValue;
 
         property.FindPropertyRelative ("name").stringValue = EditorGUI.TextField (position, "Unique Name", property.FindPropertyRelative ("name").stringValue);
         property.FindPropertyRelative ("officialName").stringValue = EditorGUILayout.TextField ("Displayed Name", property.FindPropertyRelative ("officialName").stringValue);
 
         EditorGUILayout.BeginHorizontal ();
         minElevation = EditorGUILayout.FloatField (minElevation);
         EditorGUILayout.PrefixLabel ("Elevation");
         maxElevation = EditorGUILayout.FloatField (maxElevation);
         EditorGUILayout.EndHorizontal ();
 
         EditorGUILayout.MinMaxSlider (ref minElevation, ref  maxElevation, 0f, 1000f);
 
         EditorGUILayout.BeginHorizontal ();
         minHumidity = EditorGUILayout.FloatField (minHumidity);
         EditorGUILayout.PrefixLabel ("Humidity");
         maxHumidity = EditorGUILayout.FloatField (maxHumidity);
         EditorGUILayout.EndHorizontal ();
         EditorGUILayout.MinMaxSlider (ref minHumidity, ref  maxHumidity, 0f, 1000f);
 
         property.FindPropertyRelative ("primary").boolValue = EditorGUILayout.ToggleLeft (" Essential at the start of the game.", property.FindPropertyRelative ("primary").boolValue);
 
         property.FindPropertyRelative ("modelPrefab").objectReferenceValue = EditorGUILayout.ObjectField (
             new GUIContent ("In-Game Model Prefab", "Must be located in Assets/Resources/" + BiomContainer.modelPrefabFolderPath),
             property.FindPropertyRelative ("modelPrefab").objectReferenceValue, typeof(GameObject), false);
         property.FindPropertyRelative ("guiPrifab").objectReferenceValue = EditorGUILayout.ObjectField (
             new GUIContent ("GUI Representation Prefab", "Must be located in Assets/Resources/" + BiomContainer.guiPrefabFolderPath),
             property.FindPropertyRelative ("guiPrifab").objectReferenceValue, typeof(GameObject), false);
 
         property.FindPropertyRelative ("minElevation").floatValue = minElevation;
         property.FindPropertyRelative ("maxElevation").floatValue = maxElevation;
 
         property.FindPropertyRelative ("minHumidity").floatValue = minHumidity;
         property.FindPropertyRelative ("maxHumidity").floatValue = maxHumidity;
     }
 }
 
              Your answer
 
             Follow this Question
Related Questions
How to remove an item from a list of custom variables 1 Answer
Custom inspector. Pick one bool from a list. 1 Answer
c# foreach does not work 1 Answer
Custom Inspector changes not updating target in Edit Mode 1 Answer
InvalidOperationException: Operation is not valid due to the current state of the object 1 Answer