]> Untitled Git - wolf-seeking-sheep.git/blob - addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd
Adding import files
[wolf-seeking-sheep.git] / addons / dialogic / Modules / Variable / variables_editor / variable_tree.gd
1 @tool
2 extends Tree
3
4 enum TreeButtons {ADD_FOLDER, ADD_VARIABLE, DUPLICATE_FOLDER, DELETE, CHANGE_TYPE}
5
6 @onready var editor: DialogicEditor = find_parent("VariablesEditor")
7
8
9 #region INITIAL SETUP
10
11 func _ready() -> void:
12         set_column_title(0, "Name")
13         set_column_title(1, "")
14         set_column_title(2, "Default Value")
15         set_column_expand(1, false)
16         set_column_expand_ratio(2, 2)
17         set_column_title_alignment(0, 0)
18         set_column_title_alignment(2, 0)
19
20         %ChangeTypePopup.self_modulate = get_theme_color("dark_color_3", "Editor")
21         %ChangeTypePopup.theme.set_stylebox('pressed', 'Button', get_theme_stylebox("LaunchPadMovieMode", "EditorStyles"))
22         %ChangeTypePopup.theme.set_stylebox('hover', 'Button', get_theme_stylebox("LaunchPadMovieMode", "EditorStyles"))
23         for child in %ChangeTypePopup/HBox.get_children():
24                 child.toggled.connect(_on_type_pressed.bind(child.get_index()+1))
25                 child.icon = get_theme_icon(["String", "float", "int", "bool"][child.get_index()], "EditorIcons")
26
27         %RightClickMenu.set_item_icon(0, get_theme_icon("ActionCopy", "EditorIcons"))
28 #endregion
29
30
31 #region POPULATING THE TREE
32
33 func load_info(dict:Dictionary, parent:TreeItem = null, is_new:=false) -> void:
34         if parent == null:
35                 clear()
36                 parent = add_folder_item("VAR", null)
37
38         var sorted_keys := dict.keys()
39         sorted_keys.sort()
40         for key in sorted_keys:
41                 if typeof(dict[key]) != TYPE_DICTIONARY:
42                         var item := add_variable_item(key, dict[key], parent)
43                         if is_new:
44                                 item.set_meta("new", true)
45
46         for key in sorted_keys:
47                 if typeof(dict[key]) == TYPE_DICTIONARY:
48                         var folder := add_folder_item(key, parent)
49                         if is_new:
50                                 folder.set_meta("new", true)
51                         load_info(dict[key], folder, is_new)
52
53
54
55 func add_variable_item(name:String, value:Variant, parent:TreeItem) -> TreeItem:
56         var item := create_item(parent)
57         item.set_meta("type", "VARIABLE")
58
59         item.set_text(0, name)
60         item.set_editable(0, true)
61         item.set_metadata(0, name)
62         item.set_icon(0, load(DialogicUtil.get_module_path('Variable').path_join("variable.svg")))
63         var folder_color: Color = parent.get_meta('color', Color.DARK_GOLDENROD)
64         item.set_custom_bg_color(0, folder_color.lerp(get_theme_color("background", "Editor"), 0.8))
65
66         item.add_button(1, get_theme_icon("String", "EditorIcons"), TreeButtons.CHANGE_TYPE)
67         adjust_variable_type(item, DialogicUtil.get_variable_value_type(value), value)
68         item.set_editable(2, true)
69         item.add_button(2, get_theme_icon("Remove", "EditorIcons"), TreeButtons.DELETE)
70
71         item.set_meta('prev_path', get_item_path(item))
72         return item
73
74
75 func add_folder_item(name:String, parent:TreeItem) -> TreeItem:
76         var item := create_item(parent)
77         item.set_icon(0, get_theme_icon("Folder", "EditorIcons"))
78         item.set_text(0, name)
79         item.set_editable(0, item != get_root())
80
81         var folder_color: Color
82         if parent == null:
83                 folder_color = Color(0.33000001311302, 0.15179999172688, 0.15179999172688)
84         else:
85                 folder_color = parent.get_meta('color')
86         folder_color.h = wrap(folder_color.h+0.15*(item.get_index()+1), 0, 1)
87         item.set_custom_bg_color(0, folder_color)
88         item.set_custom_bg_color(1, folder_color)
89         item.set_custom_bg_color(2, folder_color)
90         item.set_meta('color', folder_color)
91         item.add_button(2, load(self.get_script().get_path().get_base_dir().get_base_dir() + "/add-variable.svg"), TreeButtons.ADD_VARIABLE)
92         item.add_button(2, load("res://addons/dialogic/Editor/Images/Pieces/add-folder.svg"), TreeButtons.ADD_FOLDER)
93         item.add_button(2, get_theme_icon("Duplicate", "EditorIcons"), TreeButtons.DUPLICATE_FOLDER, item == get_root())
94         item.add_button(2, get_theme_icon("Remove", "EditorIcons"), TreeButtons.DELETE, item == get_root())
95         item.set_meta("type", "FOLDER")
96         return item
97
98
99 #endregion
100
101
102 #region EDITING THE TREE
103
104 func set_variable_item_type(item:TreeItem, type:int) -> void:
105         item.set_meta('value_type', type)
106         item.set_button(1, 0, get_theme_icon(["Variant", "String", "float", "int", "bool"][type], "EditorIcons"))
107
108
109 func get_variable_item_default(item:TreeItem) -> Variant:
110         match int(item.get_meta('value_type', DialogicUtil.VarTypes.STRING)):
111                 DialogicUtil.VarTypes.STRING:
112                         return item.get_text(2)
113                 DialogicUtil.VarTypes.FLOAT:
114                         return item.get_range(2)
115                 DialogicUtil.VarTypes.INT:
116                         return int(item.get_range(2))
117                 DialogicUtil.VarTypes.BOOL:
118                         return item.is_checked(2)
119         return ""
120
121
122 func _on_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void:
123         match id:
124                 TreeButtons.ADD_FOLDER:
125                         var new_item := add_folder_item("Folder", item)
126                         new_item.select(0)
127                         new_item.set_meta("new", true)
128                         await get_tree().process_frame
129                         edit_selected()
130                 TreeButtons.ADD_VARIABLE:
131                         var new_item := add_variable_item("Var", "", item)
132                         new_item.select(0)
133                         new_item.set_meta("new", true)
134                         await get_tree().process_frame
135                         edit_selected()
136                 TreeButtons.DELETE:
137                         item.free()
138                 TreeButtons.DUPLICATE_FOLDER:
139                         load_info({item.get_text(0)+"(copy)":get_info(item)}, item.get_parent(), true)
140                 TreeButtons.CHANGE_TYPE:
141                         %ChangeTypePopup.show()
142                         %ChangeTypePopup.set_meta('item', item)
143                         %ChangeTypePopup.position = get_local_mouse_position()+Vector2(-%ChangeTypePopup.size.x/2, 10)
144                         for child in %ChangeTypePopup/HBox.get_children():
145                                 child.set_pressed_no_signal(false)
146                         %ChangeTypePopup/HBox.get_child(int(item.get_meta('value_type', DialogicUtil.VarTypes.STRING)-1)).set_pressed_no_signal(true)
147
148
149 func _on_type_pressed(pressed:bool, type:int) -> void:
150         %ChangeTypePopup.hide()
151         var item: Variant = %ChangeTypePopup.get_meta('item')
152         adjust_variable_type(item, type, item.get_metadata(2))
153
154
155 func _on_item_edited() -> void:
156         var item := get_edited()
157         match item.get_meta('type'):
158                 "VARIABLE":
159                         match get_edited_column():
160                                 0:
161                                         if item.get_text(0).is_empty():
162                                                 item.set_text(0, item.get_metadata(0))
163
164                                         else:
165                                                 if item.get_text(0) != item.get_metadata(0):
166                                                         item.set_metadata(0, item.get_text(0))
167                                                         report_name_changes(item)
168
169                                 2:
170                                         item.set_metadata(2, get_variable_item_default(item))
171                 "FOLDER":
172                         report_name_changes(item)
173
174
175 func adjust_variable_type(item:TreeItem, type:int, prev_value:Variant) -> void:
176         set_variable_item_type(item, type)
177         match type:
178                 DialogicUtil.VarTypes.STRING:
179                         item.set_metadata(2, str(prev_value))
180                         item.set_cell_mode(2, TreeItem.CELL_MODE_STRING)
181                         item.set_text(2, str(prev_value))
182                 DialogicUtil.VarTypes.FLOAT:
183                         item.set_metadata(2, float(prev_value))
184                         item.set_cell_mode(2, TreeItem.CELL_MODE_RANGE)
185                         item.set_range_config(2, -9999, 9999, 0.001, false)
186                         item.set_range(2, float(prev_value))
187                 DialogicUtil.VarTypes.INT:
188                         item.set_metadata(2, int(prev_value))
189                         item.set_cell_mode(2, TreeItem.CELL_MODE_RANGE)
190                         item.set_range_config(2, -9999, 9999, 1, false)
191                         item.set_range(2, int(prev_value))
192                 DialogicUtil.VarTypes.BOOL:
193                         item.set_metadata(2, prev_value and true)
194                         item.set_cell_mode(2, TreeItem.CELL_MODE_CHECK)
195                         item.set_checked(2, prev_value and true)
196
197
198 func _input(event):
199         if !%ChangeTypePopup.visible:
200                 return
201         if event is InputEventMouseButton and event.pressed:
202                 if not %ChangeTypePopup.get_global_rect().has_point(get_global_mouse_position()):
203                         %ChangeTypePopup.hide()
204
205 #endregion
206
207
208 func filter(filter_term:String, item:TreeItem = null) -> bool:
209         if item == null:
210                 item = get_root()
211
212         var any := false
213         for child in item.get_children():
214                 match child.get_meta('type'):
215                         "VARIABLE":
216                                 child.visible = filter_term.is_empty() or filter_term.to_lower() in child.get_text(0).to_lower()
217
218                         "FOLDER":
219                                 child.visible = filter(filter_term, child)
220                 if child.visible:
221                         any = true
222         return any
223
224
225 ## Parses the tree and returns a dictionary representing it.
226 func get_info(item:TreeItem = null) -> Dictionary:
227         if item == null:
228                 item = get_root()
229                 if item == null:
230                         return {}
231
232         var dict := {}
233
234         for child in item.get_children():
235                 match child.get_meta('type'):
236                         "VARIABLE":
237                                 dict[child.get_text(0)] = child.get_metadata(2)
238                         "FOLDER":
239                                 dict[child.get_text(0)] = get_info(child)
240
241         return dict
242
243
244 #region DRAG AND DROP
245 ################################################################################
246
247 func _get_drag_data(position:Vector2) -> Variant:
248         drop_mode_flags = DROP_MODE_INBETWEEN
249         var preview := Label.new()
250         preview.text = "     "+get_selected().get_text(0)
251         preview.add_theme_stylebox_override('normal', get_theme_stylebox("Background", "EditorStyles"))
252         set_drag_preview(preview)
253
254         return get_selected()
255
256
257 func _can_drop_data(position:Vector2, data:Variant) -> bool:
258         return data is TreeItem
259
260
261 func _drop_data(position:Vector2, item:Variant) -> void:
262         var to_item := get_item_at_position(position)
263
264         if !to_item:
265                 return
266
267         var drop_section := get_drop_section_at_position(position)
268         var parent: TreeItem = null
269         if (drop_section == 1 and to_item.get_meta('type') == "FOLDER") or to_item == get_root():
270                 parent = to_item
271         else:
272                 parent = to_item.get_parent()
273
274         ## Test for inheritance-recursion
275         var test_item := to_item
276         while true:
277                 if test_item == item:
278                         return
279                 test_item = test_item.get_parent()
280                 if test_item == get_root():
281                         break
282
283         var new_item: TreeItem = null
284         match item.get_meta('type'):
285                 "VARIABLE":
286                         new_item = add_variable_item(item.get_text(0), item.get_metadata(2), parent)
287                         new_item.set_meta('prev_path', get_item_path(item))
288                         if item.get_meta("new", false):
289                                 new_item.set_meta("new", true)
290                 "FOLDER":
291                         new_item = add_folder_item(item.get_text(0), parent)
292                         load_info(get_info(item), new_item)
293                         if item.get_meta("new", false):
294                                 new_item.set_meta("new", true)
295
296         # If this was dropped on a variable (or the root node)
297         if to_item != parent:
298                 if drop_section == -1:
299                         new_item.move_before(to_item)
300                 else:
301                         new_item.move_after(to_item)
302
303         report_name_changes(new_item)
304
305         item.free()
306
307 #endregion
308
309
310 #region NAME CHANGES
311 ################################################################################
312
313 func report_name_changes(item:TreeItem) -> void:
314
315         match item.get_meta('type'):
316                 "VARIABLE":
317                         if item.get_meta("new", false):
318                                 return
319                         var new_path := get_item_path(item)
320                         editor.variable_renamed(item.get_meta('prev_path'), new_path)
321                         item.set_meta('prev_path', new_path)
322                 "FOLDER":
323                         for child in item.get_children():
324                                 report_name_changes(child)
325
326
327 func get_item_path(item:TreeItem) -> String:
328         var path := item.get_text(0)
329         while item.get_parent() != get_root():
330                 item = item.get_parent()
331                 path = item.get_text(0)+"."+path
332         return path
333
334 #endregion
335
336
337 func _on_gui_input(event: InputEvent) -> void:
338         if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_MASK_RIGHT and event.pressed:
339                 var item := get_item_at_position(get_local_mouse_position())
340                 if item and item != get_root():
341                         %RightClickMenu.popup_on_parent(Rect2(get_global_mouse_position(), Vector2()))
342                         %RightClickMenu.set_item_text(0, 'Copy "' + get_item_path(item) + '"')
343                         %RightClickMenu.set_meta("item", item)
344                         %RightClickMenu.size = Vector2()
345
346
347 func _on_right_click_menu_id_pressed(id: int) -> void:
348         if %RightClickMenu.get_meta("item", null) == null:
349                 return
350         match id:
351                 0:
352                         DisplayServer.clipboard_set(get_item_path(%RightClickMenu.get_meta("item")))