using System; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEngine; using UnityObject = UnityEngine.Object; public static class MyExtensions { #if UNITY_EDITOR // Gets value from SerializedProperty - even if value is nested public static object GetValue(this UnityEditor.SerializedProperty property) { object obj = property.serializedObject.targetObject; FieldInfo field = null; foreach (var path in property.propertyPath.Split('.')) { var type = obj.GetType(); field = type.GetField(path); obj = field.GetValue(obj); } return obj; } // Sets value from SerializedProperty - even if value is nested public static void SetValue(this UnityEditor.SerializedProperty property, object val) { object obj = property.serializedObject.targetObject; List> list = new List>(); FieldInfo field = null; foreach (var path in property.propertyPath.Split('.')) { var type = obj.GetType(); field = type.GetField(path); list.Add(new KeyValuePair(field, obj)); obj = field.GetValue(obj); } // Now set values of all objects, from child to parent for (int i = list.Count - 1; i >= 0; --i) { list[i].Key.SetValue(list[i].Value, val); // New 'val' object will be parent of current 'val' object val = list[i].Value; } } #endif // UNITY_EDITOR } public abstract class DictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property, label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property, label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); EditorUtility.SetDirty(property.serializedObject.targetObject); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); EditorUtility.SetDirty(property.serializedObject.targetObject); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); EditorUtility.SetDirty(property.serializedObject.targetObject); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; EditorUtility.SetDirty(property.serializedObject.targetObject); break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); EditorUtility.SetDirty(property.serializedObject.targetObject); break; } property.serializedObject.Update(); property.serializedObject.ApplyModifiedProperties(); } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { var target = property.serializedObject.targetObject; _Dictionary = fieldInfo.GetValue(target) as SerializableDictionary; if (_Dictionary == null) { _Dictionary = new SerializableDictionary(); fieldInfo.SetValue(target, _Dictionary); } _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); Debug.Log("Type is not supported: " + type); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class LootingPointsDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("LootingPointsData").FindPropertyRelative("allLootingPoints"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("LootingPointsData").FindPropertyRelative("allLootingPoints"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class ItemsInWorldDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("ItemsInWorldData").FindPropertyRelative("allItemsInWorld"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("ItemsInWorldData").FindPropertyRelative("allItemsInWorld"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class CreatedItemsInWorldDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("CreatedItemsInWorldData").FindPropertyRelative("allCreatedItemsInWorld"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("CreatedItemsInWorldData").FindPropertyRelative("allCreatedItemsInWorld"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class DoorDataDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("DoorData").FindPropertyRelative("allDoors"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("DoorData").FindPropertyRelative("allDoors"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class AIDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("AIData").FindPropertyRelative("aiDictionary"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("AIData").FindPropertyRelative("aiDictionary"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class AICellDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("AIData").FindPropertyRelative("aiCellDictionary"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("AIData").FindPropertyRelative("aiCellDictionary"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } public abstract class QuestIDQuestDataDictionaryDrawer : PropertyDrawer { private SerializableDictionary _Dictionary; private bool _Foldout; private const float kButtonWidth = 18f; public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("QuestsData").FindPropertyRelative("allQuests"), label); if (_Foldout) return (_Dictionary.Count + 1) * 17f; return 17f; } public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { CheckInitialize(property.serializedObject.FindProperty("saveFile").FindPropertyRelative("QuestsData").FindPropertyRelative("allQuests"), label); position.height = 17f; var foldoutRect = position; foldoutRect.width -= 2 * kButtonWidth; EditorGUI.BeginChangeCheck(); _Foldout = EditorGUI.Foldout(foldoutRect, _Foldout, label, true); if (EditorGUI.EndChangeCheck()) EditorPrefs.SetBool(label.text, _Foldout); var buttonRect = position; buttonRect.x = position.width - kButtonWidth + position.x; buttonRect.width = kButtonWidth + 2; if (GUI.Button(buttonRect, new GUIContent("+", "Add item"), EditorStyles.miniButton)) { AddNewItem(); } buttonRect.x -= kButtonWidth; if (GUI.Button(buttonRect, new GUIContent("X", "Clear dictionary"), EditorStyles.miniButtonRight)) { ClearDictionary(); } if (!_Foldout) return; foreach (var item in _Dictionary) { var key = item.Key; var value = item.Value; position.y += 17f; var keyRect = position; keyRect.width /= 2; keyRect.width -= 4; EditorGUI.BeginChangeCheck(); var newKey = DoField(keyRect, typeof(TK), key); if (EditorGUI.EndChangeCheck()) { try { _Dictionary.Remove(key); _Dictionary.Add(newKey, value); } catch (Exception e) { Debug.Log(e.Message); } break; } var valueRect = position; valueRect.x = position.width / 2 + 15; valueRect.width = keyRect.width - kButtonWidth; EditorGUI.BeginChangeCheck(); value = DoField(valueRect, typeof(TV), value); if (EditorGUI.EndChangeCheck()) { _Dictionary[key] = value; break; } var removeRect = valueRect; removeRect.x = valueRect.xMax + 2; removeRect.width = kButtonWidth; if (GUI.Button(removeRect, new GUIContent("x", "Remove item"), EditorStyles.miniButtonRight)) { RemoveItem(key); break; } } } private void RemoveItem(TK key) { _Dictionary.Remove(key); } private void CheckInitialize(SerializedProperty property, GUIContent label) { if (_Dictionary == null) { _Dictionary = property.GetValue() as SerializableDictionary; Debug.Log(_Dictionary); _Foldout = EditorPrefs.GetBool(label.text); } } private static readonly Dictionary> _Fields = new Dictionary>() { { typeof(int), (rect, value) => EditorGUI.IntField(rect, (int)value) }, { typeof(float), (rect, value) => EditorGUI.FloatField(rect, (float)value) }, { typeof(string), (rect, value) => EditorGUI.TextField(rect, (string)value) }, { typeof(bool), (rect, value) => EditorGUI.Toggle(rect, (bool)value) }, { typeof(Vector2), (rect, value) => EditorGUI.Vector2Field(rect, GUIContent.none, (Vector2)value) }, { typeof(Vector3), (rect, value) => EditorGUI.Vector3Field(rect, GUIContent.none, (Vector3)value) }, { typeof(Bounds), (rect, value) => EditorGUI.BoundsField(rect, (Bounds)value) }, { typeof(Rect), (rect, value) => EditorGUI.RectField(rect, (Rect)value) }, }; private static T DoField(Rect rect, Type type, T value) { Func field; if (_Fields.TryGetValue(type, out field)) return (T)field(rect, value); if (type.IsEnum) return (T)(object)EditorGUI.EnumPopup(rect, (Enum)(object)value); if (typeof(UnityObject).IsAssignableFrom(type)) return (T)(object)EditorGUI.ObjectField(rect, (UnityObject)(object)value, type, true); return value; } private void ClearDictionary() { _Dictionary.Clear(); } private void AddNewItem() { TK key; if (typeof(TK) == typeof(string)) key = (TK)(object)""; else key = default(TK); var value = default(TV); try { _Dictionary.Add(key, value); } catch (Exception e) { Debug.Log(e.Message); } } } [CustomPropertyDrawer(typeof(RPGCreationKit.PersistentReferences.PersistentReferencesDictionary))] public class MyDictionaryDrawer1 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.ItemsDatabaseDictionary))] public class MyDictionaryDrawer2 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.IconsDatabaseDictionary))] public class MyDictionaryDrawer3 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.FactionsDatabaseDictionary))] public class MyDictionaryDrawer4 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.WorldspacesDatabaseDictionary))] public class MyDictionaryDrawer5 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.QuestsDatabaseDictionary))] public class MyDictionaryDrawer6 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.LootingPointsDictionary))] public class MyDictionaryDrawer7 : LootingPointsDictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.ItemsInWorldDictionary))] public class MyDictionaryDrawer8 : ItemsInWorldDictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.CreatedItemsInWorldDictionary))] public class MyDictionaryDrawer9 : CreatedItemsInWorldDictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.DoorsDataDictionary))] public class MyDictionaryDrawer10: DoorDataDictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.AIDatabaseFileDictionary))] public class MyDictionaryDrawer11 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.CellsSystem.AIInWorldDictionary))] public class MyDictionaryDrawer12 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.DialoguesDatabaseDictionary))] public class MyDictionaryDrawer13 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.BehavioursDatabaseDictionary))] public class MyDictionaryDrawer14 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.AIDictionary))] public class MyDictionaryDrawer15 : AIDictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.AICellDictionary))] public class MyDictionaryDrawer16 : AICellDictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.CellsSystem.AllDoorsDictionary))] public class MyDictionaryDrawer17 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.PersistentReferences.CellsDoorsDictionary))] public class MyDictionaryDrawer18 : DictionaryDrawer { } /* [CustomPropertyDrawer(typeof(RPGCreationKit.SaveSystem.QuestIDQuestDataDictionary))] public class MyDictionaryDrawer19 : QuestIDQuestDataDictionaryDrawer { } */ [CustomPropertyDrawer(typeof(RPGCreationKit.CellsSystem.MutablesInWorldDictionary))] public class MyDictionaryDrawer20 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.CellsSystem.AllActionPointsDictionary))] public class MyDictionaryDrawer21 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.RacesDatabaseDictionary))] public class MyDictionaryDrawer22 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.CellsSystem.TargetableTransformInWorldDictionary))] public class MyDictionaryDrawer23 : DictionaryDrawer { } [CustomPropertyDrawer(typeof(RPGCreationKit.CellsSystem.AIPathInWorldDictionary))] public class MyDictionaryDrawer24 : DictionaryDrawer { }