2 using System.Collections.Generic;
7 namespace droid.Runtime.Utilities.ScriptableObjects.SerialisableDictionary {
8 public abstract class SerializableKeyValueTemplate<TK, TV> : ScriptableObject {
13 public abstract class SerializableDictionaryDrawer<TK, TV> : PropertyDrawer {
14 Dictionary<int, Dictionary<int, SerializedProperty>> _indexed_property_dicts =
15 new Dictionary<int, Dictionary<int, SerializedProperty>>();
17 Dictionary<int, SerializedProperty> _keys_props =
new Dictionary<int, SerializedProperty>();
19 Dictionary<int, SerializedProperty> _template_key_prop =
new Dictionary<int, SerializedProperty>();
21 Dictionary<int, SerializedProperty> _template_value_prop =
new Dictionary<int, SerializedProperty>();
23 Dictionary<int, SerializedProperty> _values_props =
new Dictionary<int, SerializedProperty>();
25 protected abstract SerializableKeyValueTemplate<TK, TV> GetTemplate();
27 protected T GetGenericTemplate<T>() where T : SerializableKeyValueTemplate<TK, TV> {
28 return ScriptableObject.CreateInstance<T>();
31 public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
32 EditorGUI.BeginProperty(position, label, property);
34 var first_line = position;
35 first_line.height = EditorGUIUtility.singleLineHeight;
36 EditorGUI.PropertyField(first_line, property);
38 if (property.isExpanded) {
39 var second_line = first_line;
40 second_line.y += EditorGUIUtility.singleLineHeight;
42 EditorGUIUtility.labelWidth = 50f;
45 second_line.width -= 15f;
47 var second_line_key = second_line;
49 var button_width = 60f;
50 second_line_key.width -= button_width;
51 second_line_key.width /= 2f;
53 var second_line_value = second_line_key;
54 second_line_value.x += second_line_value.width;
55 if (this.GetTemplateValueProp(property).hasVisibleChildren) {
57 second_line_value.x += 15;
58 second_line_value.width -= 15;
61 var second_line_button = second_line_value;
62 second_line_button.x += second_line_value.width;
63 second_line_button.width = button_width;
65 var k_height = EditorGUI.GetPropertyHeight(this.GetTemplateKeyProp(property));
66 var v_height = EditorGUI.GetPropertyHeight(this.GetTemplateValueProp(property));
67 var extra_height = Mathf.Max(k_height, v_height);
69 second_line_key.height = k_height;
70 second_line_value.height = v_height;
72 EditorGUI.PropertyField(second_line_key, this.GetTemplateKeyProp(property),
true);
73 EditorGUI.PropertyField(second_line_value, this.GetTemplateValueProp(property),
true);
75 var keys_prop = this.GetKeysProp(property);
76 var values_prop = this.GetValuesProp(property);
78 var num_lines = keys_prop.arraySize;
80 if (GUI.Button(second_line_button,
"Assign")) {
81 var assignment =
false;
82 for (var i = 0; i < num_lines; i++)
85 if (SerializedPropertyExtension.EqualBasics(
this.GetIndexedItemProp(keys_prop, i),
86 this.GetTemplateKeyProp(property))) {
87 SerializedPropertyExtension.CopyBasics(this.GetTemplateValueProp(property),
88 this.GetIndexedItemProp(values_prop, i));
96 keys_prop.arraySize += 1;
97 values_prop.arraySize += 1;
98 SerializedPropertyExtension.CopyBasics(this.GetTemplateKeyProp(property),
99 this.GetIndexedItemProp(keys_prop, num_lines));
100 SerializedPropertyExtension.CopyBasics(this.GetTemplateValueProp(property),
101 this.GetIndexedItemProp(values_prop, num_lines));
105 for (var i = 0; i < num_lines; i++) {
106 second_line_key.y += extra_height;
107 second_line_value.y += extra_height;
108 second_line_button.y += extra_height;
110 k_height = EditorGUI.GetPropertyHeight(this.GetIndexedItemProp(keys_prop, i));
111 v_height = EditorGUI.GetPropertyHeight(this.GetIndexedItemProp(values_prop, i));
112 extra_height = Mathf.Max(k_height, v_height);
114 second_line_key.height = k_height;
115 second_line_value.height = v_height;
117 EditorGUI.PropertyField(second_line_key, this.GetIndexedItemProp(keys_prop, i),
true);
118 EditorGUI.PropertyField(second_line_value, this.GetIndexedItemProp(values_prop, i),
true);
120 if (GUI.Button(second_line_button,
"Remove")) {
121 keys_prop.DeleteArrayElementAtIndex(i);
122 values_prop.DeleteArrayElementAtIndex(i);
127 EditorGUI.EndProperty();
130 public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
131 if (!property.isExpanded) {
132 return EditorGUIUtility.singleLineHeight;
135 var total = EditorGUIUtility.singleLineHeight;
137 var k_height = EditorGUI.GetPropertyHeight(this.GetTemplateKeyProp(property));
138 var v_height = EditorGUI.GetPropertyHeight(this.GetTemplateValueProp(property));
139 total += Mathf.Max(k_height, v_height);
141 var keys_prop = this.GetKeysProp(property);
142 var values_prop = this.GetValuesProp(property);
143 var num_lines = keys_prop.arraySize;
144 for (var i = 0; i < num_lines; i++) {
145 k_height = EditorGUI.GetPropertyHeight(this.GetIndexedItemProp(keys_prop, i));
146 v_height = EditorGUI.GetPropertyHeight(this.GetIndexedItemProp(values_prop, i));
147 total += Mathf.Max(k_height, v_height);
153 SerializedProperty GetTemplateKeyProp(SerializedProperty main_prop) {
154 return this.GetTemplateProp(this._template_key_prop, main_prop);
157 SerializedProperty GetTemplateValueProp(SerializedProperty main_prop) {
158 return this.GetTemplateProp(this._template_value_prop, main_prop);
161 SerializedProperty GetTemplateProp(Dictionary<int, SerializedProperty> source,
162 SerializedProperty main_prop) {
163 if (!source.TryGetValue(main_prop.GetObjectCode(), out var p)) {
164 var template_object = this.GetTemplate();
165 var template_serialized_object =
new SerializedObject(template_object);
166 var k_prop = template_serialized_object.FindProperty(
"key");
167 var v_prop = template_serialized_object.FindProperty(
"value");
168 this._template_key_prop[main_prop.GetObjectCode()] = k_prop;
169 this._template_value_prop[main_prop.GetObjectCode()] = v_prop;
170 p = source == this._template_key_prop ? k_prop : v_prop;
176 SerializedProperty GetKeysProp(SerializedProperty main_prop) {
177 return this.GetCachedProp(main_prop,
"keys", this._keys_props);
180 SerializedProperty GetValuesProp(SerializedProperty main_prop) {
181 return this.GetCachedProp(main_prop,
"values", this._values_props);
184 SerializedProperty GetCachedProp(SerializedProperty main_prop,
185 string relative_property_name,
186 Dictionary<int, SerializedProperty> source) {
187 var object_code = main_prop.GetObjectCode();
188 if (!source.TryGetValue(object_code, out var p)) {
189 source[object_code] = p = main_prop.FindPropertyRelative(relative_property_name);
195 SerializedProperty GetIndexedItemProp(SerializedProperty array_prop,
int index) {
196 if (!this._indexed_property_dicts.TryGetValue(array_prop.GetObjectCode(), out var d)) {
197 this._indexed_property_dicts[array_prop.GetObjectCode()] =
198 d =
new Dictionary<int, SerializedProperty>();
201 if (!d.TryGetValue(index, out var result)) {
202 d[index] = result = array_prop.FindPropertyRelative($
"Array.data[{index}]");