4 ## Editor that handles the editing of styles and their layers.
7 var styles: Array[DialogicStyle] = []
8 var current_style : DialogicStyle = null
9 var default_style := ""
11 var premade_style_parts := {}
13 @onready var StyleList: ItemList = %StyleList
15 #region EDITOR MANAGEMENT
16 ################################################################################
18 func _get_title() -> String:
22 func _get_icon() -> Texture:
23 return load(DialogicUtil.get_module_path('StyleEditor').path_join("styles_icon.svg"))
26 func _register() -> void:
27 editors_manager.register_simple_editor(self)
28 alternative_text = "Change the look of the dialog in your game"
31 func _open(_extra_info:Variant = null) -> void:
35 func _close() -> void:
43 func _ready() -> void:
49 #region STYLE MANAGEMENT
50 ################################################################################
52 func collect_styles() -> void:
53 for indexer in DialogicUtil.get_indexers():
54 for layout in indexer._get_layout_parts():
55 premade_style_parts[layout['path']] = layout
57 var style_list: Array = ProjectSettings.get_setting('dialogic/layout/style_list', [])
58 for style in style_list:
59 if ResourceLoader.exists(style):
61 styles.append(ResourceLoader.load(style, "DialogicStyle"))
63 print("[Dialogic] Failed to open style '", style, "'. Some dependency might be broken.")
65 print("[Dialogic] Failed to open style '", style, "'. Might have been moved or deleted.")
67 default_style = ProjectSettings.get_setting('dialogic/layout/default_style', 'Default')
70 func save_style_list() -> void:
71 ProjectSettings.set_setting('dialogic/layout/style_list', styles.map(func(style:DialogicStyle): return style.resource_path))
72 ProjectSettings.set_setting('dialogic/layout/default_style', default_style)
73 ProjectSettings.save()
76 func save_style() -> void:
77 if current_style == null:
80 ResourceSaver.save(current_style)
83 func add_style(file_path:String, style:DialogicStyle, inherits:DialogicStyle= null) -> void:
84 style.resource_path = file_path
85 style.inherits = inherits
87 if style.layer_list.is_empty() and style.inherits_anything():
88 for id in style.get_layer_inherited_list():
89 style.add_layer('', {}, id)
91 ResourceSaver.save(style, file_path)
96 default_style = style.resource_path
103 func delete_style(style:DialogicStyle) -> void:
104 for other_style in styles:
105 if other_style.inherits == style:
106 other_style.realize_inheritance()
107 push_warning('[Dialogic] Style "',other_style.name,'" had to be realized because it inherited "', style.name,'" which was deleted!')
109 if style.resource_path == default_style:
115 func delete_style_by_name(style_name:String) -> void:
117 if style.name == style_name:
122 func realize_style() -> void:
123 current_style.realize_inheritance()
125 select_style(current_style)
129 #region USER INTERFACE
130 ################################################################################
132 func setup_ui() -> void:
133 %AddButton.icon = get_theme_icon("Add", "EditorIcons")
134 %DuplicateButton.icon = get_theme_icon("Duplicate", "EditorIcons")
135 %InheritanceButton.icon = get_theme_icon("GuiDropdown", "EditorIcons")
136 %RemoveButton.icon = get_theme_icon("Remove", "EditorIcons")
138 %EditNameButton.icon = get_theme_icon("Edit", "EditorIcons")
139 %TestStyleButton.icon = get_theme_icon("PlayCustom", "EditorIcons")
140 %MakeDefaultButton.icon = get_theme_icon("Favorites", "EditorIcons")
142 StyleList.item_selected.connect(_on_stylelist_selected)
143 %AddButton.get_popup().index_pressed.connect(_on_AddStyleMenu_selected)
144 %AddButton.about_to_popup.connect(_on_AddStyleMenu_about_to_popup)
145 %InheritanceButton.get_popup().index_pressed.connect(_on_inheritance_index_pressed)
146 StyleList.set_drag_forwarding(_on_stylelist_drag, _on_stylelist_can_drop, _on_style_list_drop)
150 func load_style_list() -> void:
151 var latest: String = DialogicUtil.get_editor_setting('latest_layout_style', 'Default')
156 # TODO remove when going Beta
157 style.update_from_pre_alpha16()
158 StyleList.add_item(style.name, get_theme_icon("PopupMenu", "EditorIcons"))
159 StyleList.set_item_tooltip(idx, style.resource_path)
160 StyleList.set_item_metadata(idx, style)
162 if style.resource_path == default_style:
163 StyleList.set_item_icon_modulate(idx, get_theme_color("warning_color", "Editor"))
164 if style.resource_path.begins_with("res://addons/dialogic"):
165 StyleList.set_item_icon_modulate(idx, get_theme_color("property_color_z", "Editor"))
166 StyleList.set_item_tooltip(idx, "This is a default style. Only edit it if you know what you are doing!")
167 StyleList.set_item_custom_bg_color(idx, get_theme_color("property_color_z", "Editor").lerp(get_theme_color("dark_color_3", "Editor"), 0.8))
168 if style.name == latest:
169 StyleList.select(idx)
177 elif !StyleList.is_anything_selected():
179 load_style(StyleList.get_item_metadata(0))
182 func _on_stylelist_selected(index:int) -> void:
183 load_style(StyleList.get_item_metadata(index))
186 func select_style(style:DialogicStyle) -> void:
187 DialogicUtil.set_editor_setting('latest_layout_style', style.name)
188 for idx in range(StyleList.item_count):
189 if StyleList.get_item_metadata(idx) == style:
190 StyleList.select(idx)
194 func load_style(style:DialogicStyle) -> void:
195 if current_style != null:
196 current_style.changed.disconnect(save_style)
198 current_style = style
199 if current_style == null:
201 current_style.changed.connect(save_style)
203 %LayoutStyleName.text = style.name
204 if style.resource_path == default_style:
205 %MakeDefaultButton.tooltip_text = "Is Default"
206 %MakeDefaultButton.disabled = true
208 %MakeDefaultButton.tooltip_text = "Make Default"
209 %MakeDefaultButton.disabled = false
211 %StyleEditor.load_style(style)
213 %InheritanceButton.visible = style.inherits_anything()
214 if %InheritanceButton.visible:
215 %InheritanceButton.text = "Inherits " + style.inherits.name
218 DialogicUtil.set_editor_setting('latest_layout_style', style.name)
224 func _on_AddStyleMenu_about_to_popup() -> void:
225 %AddButton.get_popup().set_item_disabled(3, not StyleList.is_anything_selected())
228 func _on_AddStyleMenu_selected(index:int) -> void:
231 %StyleBrowserWindow.popup_centered_ratio(0.6)
232 %StyleBrowser.current_type = 1
233 %StyleBrowser.load_parts()
234 var picked_info: Dictionary = await %StyleBrowserWindow.get_picked_info()
235 if not picked_info.has('style_path'):
238 if not ResourceLoader.exists(picked_info.style_path):
241 var new_style: DialogicStyle = load(picked_info.style_path).clone()
243 find_parent('EditorView').godot_file_dialog(
244 add_style_undoable.bind(new_style),
246 EditorFileDialog.FILE_MODE_SAVE_FILE,
247 "Select folder for new style")
250 if StyleList.get_selected_items().is_empty():
252 find_parent('EditorView').godot_file_dialog(
253 add_style_undoable.bind(DialogicStyle.new(), current_style),
255 EditorFileDialog.FILE_MODE_SAVE_FILE,
256 "Select folder for new style")
259 find_parent('EditorView').godot_file_dialog(
260 add_style_undoable.bind(DialogicStyle.new()),
262 EditorFileDialog.FILE_MODE_SAVE_FILE,
263 "Select folder for new style")
266 func add_style_undoable(file_path:String, style:DialogicStyle, inherits:DialogicStyle = null) -> void:
267 style.name = _get_new_name(file_path.get_file().trim_suffix('.'+file_path.get_extension()))
268 var undo_redo: EditorUndoRedoManager = DialogicUtil.get_dialogic_plugin().get_undo_redo()
269 undo_redo.create_action('Add Style', UndoRedo.MERGE_ALL)
270 undo_redo.add_do_method(self, "add_style", file_path, style, inherits)
271 undo_redo.add_do_method(self, "load_style_list")
272 undo_redo.add_undo_method(self, "delete_style", style)
273 undo_redo.add_undo_method(self, "load_style_list")
274 undo_redo.commit_action()
275 DialogicUtil.set_editor_setting('latest_layout_style', style.name)
278 func _on_duplicate_button_pressed() -> void:
279 if !StyleList.is_anything_selected():
281 find_parent('EditorView').godot_file_dialog(
282 add_style_undoable.bind(current_style.clone(), null),
284 EditorFileDialog.FILE_MODE_SAVE_FILE,
285 "Select folder for new style")
288 func _on_remove_button_pressed() -> void:
289 if !StyleList.is_anything_selected():
292 if current_style.name == default_style:
293 push_warning("[Dialogic] You cannot delete the default style!")
296 delete_style(current_style)
300 func _on_edit_name_button_pressed() -> void:
301 %LayoutStyleName.grab_focus()
302 %LayoutStyleName.select_all()
305 func _on_layout_style_name_text_submitted(_new_text:String) -> void:
306 _on_layout_style_name_focus_exited()
309 func _on_layout_style_name_focus_exited() -> void:
310 var new_name: String = %LayoutStyleName.text.strip_edges()
311 if new_name == current_style.name:
315 if style.name == new_name:
316 %LayoutStyleName.text = current_style.name
319 current_style.name = new_name
320 DialogicUtil.set_editor_setting('latest_layout_style', new_name)
324 func _on_make_default_button_pressed() -> void:
325 default_style = current_style.resource_path
331 func _on_test_style_button_pressed() -> void:
332 var dialogic_plugin := DialogicUtil.get_dialogic_plugin()
334 # Save the current opened timeline
335 DialogicUtil.set_editor_setting('current_test_style', current_style.name)
337 DialogicUtil.get_dialogic_plugin().get_editor_interface().play_custom_scene("res://addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn")
338 await get_tree().create_timer(3).timeout
339 DialogicUtil.set_editor_setting('current_test_style', '')
342 func _on_inheritance_index_pressed(index:int) -> void:
348 func _on_start_styling_button_pressed() -> void:
349 var new_style := DialogicUtil.get_fallback_style().clone()
351 find_parent('EditorView').godot_file_dialog(
352 add_style_undoable.bind(new_style),
354 EditorFileDialog.FILE_MODE_SAVE_FILE,
355 "Select folder for new style")
360 func _on_stylelist_drag(vector:Vector2) -> Variant:
364 func _on_stylelist_can_drop(at_position: Vector2, data: Variant) -> bool:
365 if not data is Dictionary:
367 if not data.get('type', 's') == 'files':
371 if style is DialogicStyle:
372 if not style in styles:
377 func _on_style_list_drop(at_position: Vector2, data: Variant) -> void:
378 for file in data.files:
379 var style := load(file)
380 if style is DialogicStyle:
381 if not style in styles:
388 func _get_new_name(base_name:String) -> String:
389 var new_name_idx := 1
390 var found_unique_name := false
391 var new_name := base_name
392 while not found_unique_name:
393 found_unique_name = true
395 if style.name == new_name:
397 new_name = base_name+" "+str(new_name_idx)
398 found_unique_name = false