You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
11 KiB
392 lines
11 KiB
6 months ago
|
@tool
|
||
|
extends DialogicEditor
|
||
|
|
||
|
## Editor that handles the editing of styles and their layers.
|
||
|
|
||
|
|
||
|
var styles: Array[DialogicStyle] = []
|
||
|
var current_style : DialogicStyle = null
|
||
|
var default_style := ""
|
||
|
|
||
|
var premade_style_parts := {}
|
||
|
|
||
|
|
||
|
|
||
|
#region EDITOR MANAGEMENT
|
||
|
################################################################################
|
||
|
|
||
|
func _get_title() -> String:
|
||
|
return "Styles"
|
||
|
|
||
|
|
||
|
func _get_icon() -> Texture:
|
||
|
return load(DialogicUtil.get_module_path('StyleEditor').path_join("styles_icon.svg"))
|
||
|
|
||
|
|
||
|
func _register() -> void:
|
||
|
editors_manager.register_simple_editor(self)
|
||
|
alternative_text = "Change the look of the dialog in your game"
|
||
|
|
||
|
|
||
|
func _open(extra_info:Variant = null) -> void:
|
||
|
load_style_list()
|
||
|
|
||
|
|
||
|
func _close() -> void:
|
||
|
save_style_list()
|
||
|
save_style()
|
||
|
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
func _ready() -> void:
|
||
|
collect_styles()
|
||
|
|
||
|
setup_ui()
|
||
|
|
||
|
|
||
|
#region STYLE MANAGEMENT
|
||
|
################################################################################
|
||
|
|
||
|
func collect_styles() -> void:
|
||
|
for indexer in DialogicUtil.get_indexers():
|
||
|
for layout in indexer._get_layout_parts():
|
||
|
premade_style_parts[layout['path']] = layout
|
||
|
|
||
|
var style_list: Array = ProjectSettings.get_setting('dialogic/layout/style_list', [])
|
||
|
for style in style_list:
|
||
|
if ResourceLoader.exists(style):
|
||
|
var style_res := load(style)
|
||
|
if style != null:
|
||
|
styles.append(ResourceLoader.load(style, "DialogicStyle"))
|
||
|
else:
|
||
|
print("[Dialogic] Failed to open style '", style, "'. Some dependency might be broken.")
|
||
|
else:
|
||
|
print("[Dialogic] Failed to open style '", style, "'. Might have been moved or deleted.")
|
||
|
|
||
|
default_style = ProjectSettings.get_setting('dialogic/layout/default_style', 'Default')
|
||
|
|
||
|
|
||
|
func save_style_list() -> void:
|
||
|
ProjectSettings.set_setting('dialogic/layout/style_list', styles.map(func(style:DialogicStyle): return style.resource_path))
|
||
|
ProjectSettings.set_setting('dialogic/layout/default_style', default_style)
|
||
|
ProjectSettings.save()
|
||
|
|
||
|
|
||
|
func save_style() -> void:
|
||
|
if current_style == null:
|
||
|
return
|
||
|
|
||
|
ResourceSaver.save(current_style)
|
||
|
|
||
|
|
||
|
func add_style(file_path:String, style:DialogicStyle, inherits:DialogicStyle= null) -> void:
|
||
|
style.resource_path = file_path
|
||
|
style.inherits = inherits
|
||
|
if style.layers.is_empty() and style.inherits != null:
|
||
|
for l in style.get_layer_list():
|
||
|
style.add_layer('', {})
|
||
|
ResourceSaver.save(style, file_path)
|
||
|
styles.append(style)
|
||
|
if len(styles) == 1:
|
||
|
default_style = style.resource_path
|
||
|
save_style_list()
|
||
|
load_style_list()
|
||
|
select_style(style)
|
||
|
|
||
|
|
||
|
func delete_style(style:DialogicStyle) -> void:
|
||
|
for other_style in styles:
|
||
|
if other_style.inherits == style:
|
||
|
other_style.realize_inheritance()
|
||
|
push_warning('[Dialogic] Style "',other_style.name,'" had to be realized because it inherited "', style.name,'" which was deleted!')
|
||
|
|
||
|
if style.resource_path == default_style:
|
||
|
default_style = ""
|
||
|
styles.erase(style)
|
||
|
save_style_list()
|
||
|
|
||
|
|
||
|
func delete_style_by_name(style_name:String) -> void:
|
||
|
for style in styles:
|
||
|
if style.name == style_name:
|
||
|
delete_style(style)
|
||
|
return
|
||
|
|
||
|
|
||
|
func realize_style() -> void:
|
||
|
current_style.realize_inheritance()
|
||
|
|
||
|
select_style(current_style)
|
||
|
|
||
|
|
||
|
#endregion
|
||
|
#region USER INTERFACE
|
||
|
################################################################################
|
||
|
|
||
|
func setup_ui() -> void:
|
||
|
%AddButton.icon = get_theme_icon("Add", "EditorIcons")
|
||
|
%DuplicateButton.icon = get_theme_icon("Duplicate", "EditorIcons")
|
||
|
%InheritanceButton.icon = get_theme_icon("GuiDropdown", "EditorIcons")
|
||
|
%RemoveButton.icon = get_theme_icon("Remove", "EditorIcons")
|
||
|
|
||
|
%EditNameButton.icon = get_theme_icon("Edit", "EditorIcons")
|
||
|
%TestStyleButton.icon = get_theme_icon("PlayCustom", "EditorIcons")
|
||
|
%MakeDefaultButton.icon = get_theme_icon("Favorites", "EditorIcons")
|
||
|
|
||
|
%StyleList.item_selected.connect(_on_stylelist_selected)
|
||
|
%AddButton.get_popup().index_pressed.connect(_on_AddStyleMenu_selected)
|
||
|
%AddButton.about_to_popup.connect(_on_AddStyleMenu_about_to_popup)
|
||
|
%InheritanceButton.get_popup().index_pressed.connect(_on_inheritance_index_pressed)
|
||
|
%StyleList.set_drag_forwarding(_on_stylelist_drag, _on_stylelist_can_drop, _on_style_list_drop)
|
||
|
%StyleView.hide()
|
||
|
%NoStyleView.show()
|
||
|
|
||
|
func load_style_list() -> void:
|
||
|
var latest: String = DialogicUtil.get_editor_setting('latest_layout_style', 'Default')
|
||
|
|
||
|
%StyleList.clear()
|
||
|
var idx := 0
|
||
|
for style in styles:
|
||
|
%StyleList.add_item(style.name, get_theme_icon("PopupMenu", "EditorIcons"))
|
||
|
if style.resource_path == default_style:
|
||
|
%StyleList.set_item_icon_modulate(idx, get_theme_color("warning_color", "Editor"))
|
||
|
if style.name == latest:
|
||
|
%StyleList.select(idx)
|
||
|
load_style(style)
|
||
|
%StyleList.set_item_tooltip(idx, style.resource_path)
|
||
|
%StyleList.set_item_metadata(idx, style)
|
||
|
idx += 1
|
||
|
|
||
|
if len(styles) == 0:
|
||
|
%StyleView.hide()
|
||
|
%NoStyleView.show()
|
||
|
|
||
|
elif !%StyleList.is_anything_selected():
|
||
|
%StyleList.select(0)
|
||
|
load_style(%StyleList.get_item_metadata(0))
|
||
|
|
||
|
|
||
|
func _on_stylelist_selected(index:int) -> void:
|
||
|
load_style(%StyleList.get_item_metadata(index))
|
||
|
|
||
|
|
||
|
func select_style(style:DialogicStyle) -> void:
|
||
|
DialogicUtil.set_editor_setting('latest_layout_style', style.name)
|
||
|
for idx in range(%StyleList.item_count):
|
||
|
if %StyleList.get_item_metadata(idx) == style:
|
||
|
%StyleList.select(idx)
|
||
|
return
|
||
|
|
||
|
|
||
|
func load_style(style:DialogicStyle) -> void:
|
||
|
if current_style != null:
|
||
|
current_style.changed.disconnect(save_style)
|
||
|
save_style()
|
||
|
current_style = style
|
||
|
if current_style == null:
|
||
|
return
|
||
|
current_style.changed.connect(save_style)
|
||
|
|
||
|
%LayoutStyleName.text = style.name
|
||
|
if style.resource_path == default_style:
|
||
|
%MakeDefaultButton.tooltip_text = "Is Default"
|
||
|
%MakeDefaultButton.disabled = true
|
||
|
else:
|
||
|
%MakeDefaultButton.tooltip_text = "Make Default"
|
||
|
%MakeDefaultButton.disabled = false
|
||
|
|
||
|
%StyleEditor.load_style(style)
|
||
|
|
||
|
%InheritanceButton.visible = style.inherits_anything()
|
||
|
if %InheritanceButton.visible:
|
||
|
%InheritanceButton.text = "Inherits " + style.inherits.name
|
||
|
|
||
|
|
||
|
DialogicUtil.set_editor_setting('latest_layout_style', style.name)
|
||
|
|
||
|
%StyleView.show()
|
||
|
%NoStyleView.hide()
|
||
|
|
||
|
|
||
|
func _on_AddStyleMenu_about_to_popup() -> void:
|
||
|
%AddButton.get_popup().set_item_disabled(3, not %StyleList.is_anything_selected())
|
||
|
|
||
|
|
||
|
func _on_AddStyleMenu_selected(index:int) -> void:
|
||
|
# add preset style
|
||
|
if index == 2:
|
||
|
%StyleBrowserWindow.popup_centered_ratio(0.6)
|
||
|
%StyleBrowser.current_type = 1
|
||
|
%StyleBrowser.load_parts()
|
||
|
var picked_info: Dictionary = await %StyleBrowserWindow.get_picked_info()
|
||
|
if not picked_info.has('style_path'):
|
||
|
return
|
||
|
|
||
|
if not ResourceLoader.exists(picked_info.style_path):
|
||
|
return
|
||
|
|
||
|
var new_style: DialogicStyle = load(picked_info.style_path).clone()
|
||
|
|
||
|
find_parent('EditorView').godot_file_dialog(
|
||
|
add_style_undoable.bind(new_style),
|
||
|
'*.tres',
|
||
|
EditorFileDialog.FILE_MODE_SAVE_FILE,
|
||
|
"Select folder for new style")
|
||
|
|
||
|
if index == 3:
|
||
|
if %StyleList.get_selected_items().is_empty():
|
||
|
return
|
||
|
find_parent('EditorView').godot_file_dialog(
|
||
|
add_style_undoable.bind(DialogicStyle.new(), current_style),
|
||
|
'*.tres',
|
||
|
EditorFileDialog.FILE_MODE_SAVE_FILE,
|
||
|
"Select folder for new style")
|
||
|
|
||
|
if index == 4:
|
||
|
find_parent('EditorView').godot_file_dialog(
|
||
|
add_style_undoable.bind(DialogicStyle.new()),
|
||
|
'*.tres',
|
||
|
EditorFileDialog.FILE_MODE_SAVE_FILE,
|
||
|
"Select folder for new style")
|
||
|
|
||
|
|
||
|
func add_style_undoable(file_path:String, style:DialogicStyle, inherits:DialogicStyle = null) -> void:
|
||
|
style.name = _get_new_name(file_path.get_file().trim_suffix('.'+file_path.get_extension()))
|
||
|
var undo_redo: EditorUndoRedoManager = DialogicUtil.get_dialogic_plugin().get_undo_redo()
|
||
|
undo_redo.create_action('Add Style', UndoRedo.MERGE_ALL)
|
||
|
undo_redo.add_do_method(self, "add_style", file_path, style, inherits)
|
||
|
undo_redo.add_do_method(self, "load_style_list")
|
||
|
undo_redo.add_undo_method(self, "delete_style", style)
|
||
|
undo_redo.add_undo_method(self, "load_style_list")
|
||
|
undo_redo.commit_action()
|
||
|
DialogicUtil.set_editor_setting('latest_layout_style', style.name)
|
||
|
|
||
|
|
||
|
func _on_duplicate_button_pressed():
|
||
|
if !%StyleList.is_anything_selected():
|
||
|
return
|
||
|
find_parent('EditorView').godot_file_dialog(
|
||
|
add_style_undoable.bind(current_style.clone(), null),
|
||
|
'*.tres',
|
||
|
EditorFileDialog.FILE_MODE_SAVE_FILE,
|
||
|
"Select folder for new style")
|
||
|
|
||
|
|
||
|
func _on_remove_button_pressed():
|
||
|
if !%StyleList.is_anything_selected():
|
||
|
return
|
||
|
|
||
|
if current_style.name == default_style:
|
||
|
push_warning("[Dialogic] You cannot delete the default style!")
|
||
|
return
|
||
|
|
||
|
delete_style(current_style)
|
||
|
load_style_list()
|
||
|
|
||
|
|
||
|
func _on_edit_name_button_pressed():
|
||
|
%LayoutStyleName.grab_focus()
|
||
|
%LayoutStyleName.select_all()
|
||
|
|
||
|
|
||
|
func _on_layout_style_name_text_submitted(new_text:String) -> void:
|
||
|
_on_layout_style_name_focus_exited()
|
||
|
|
||
|
|
||
|
func _on_layout_style_name_focus_exited():
|
||
|
var new_name :String= %LayoutStyleName.text.strip_edges()
|
||
|
if new_name == current_style.name:
|
||
|
return
|
||
|
|
||
|
for style in styles:
|
||
|
if style.name == new_name:
|
||
|
%LayoutStyleName.text = current_style.name
|
||
|
return
|
||
|
|
||
|
current_style.name = new_name
|
||
|
DialogicUtil.set_editor_setting('latest_layout_style', new_name)
|
||
|
load_style_list()
|
||
|
|
||
|
|
||
|
func _on_make_default_button_pressed():
|
||
|
default_style = current_style.resource_path
|
||
|
save_style_list()
|
||
|
load_style_list()
|
||
|
|
||
|
|
||
|
|
||
|
func _on_test_style_button_pressed():
|
||
|
var dialogic_plugin := DialogicUtil.get_dialogic_plugin()
|
||
|
|
||
|
# Save the current opened timeline
|
||
|
DialogicUtil.set_editor_setting('current_test_style', current_style.name)
|
||
|
|
||
|
DialogicUtil.get_dialogic_plugin().get_editor_interface().play_custom_scene("res://addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn")
|
||
|
await get_tree().create_timer(3).timeout
|
||
|
DialogicUtil.set_editor_setting('current_test_style', '')
|
||
|
|
||
|
|
||
|
func _on_inheritance_index_pressed(index:int) -> void:
|
||
|
if index == 0:
|
||
|
realize_style()
|
||
|
|
||
|
|
||
|
|
||
|
func _on_start_styling_button_pressed() -> void:
|
||
|
var new_style := DialogicUtil.get_fallback_style().clone()
|
||
|
|
||
|
find_parent('EditorView').godot_file_dialog(
|
||
|
add_style_undoable.bind(new_style),
|
||
|
'*.tres',
|
||
|
EditorFileDialog.FILE_MODE_SAVE_FILE,
|
||
|
"Select folder for new style")
|
||
|
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
func _on_stylelist_drag(vector:Vector2) -> Variant:
|
||
|
return null
|
||
|
|
||
|
|
||
|
func _on_stylelist_can_drop(at_position: Vector2, data: Variant) -> bool:
|
||
|
if not data is Dictionary:
|
||
|
return false
|
||
|
if not data.get('type', 's') == 'files':
|
||
|
return false
|
||
|
for f in data.files:
|
||
|
var style := load(f)
|
||
|
if style is DialogicStyle:
|
||
|
if not style in styles:
|
||
|
return true
|
||
|
|
||
|
return false
|
||
|
|
||
|
func _on_style_list_drop(at_position: Vector2, data: Variant) -> void:
|
||
|
for file in data.files:
|
||
|
var style := load(file)
|
||
|
if style is DialogicStyle:
|
||
|
if not style in styles:
|
||
|
styles.append(style)
|
||
|
save_style_list()
|
||
|
load_style_list()
|
||
|
|
||
|
|
||
|
#region Helpers
|
||
|
func _get_new_name(base_name:String) -> String:
|
||
|
var new_name_idx := 1
|
||
|
var found_unique_name := false
|
||
|
var new_name := base_name
|
||
|
while not found_unique_name:
|
||
|
found_unique_name = true
|
||
|
for style in styles:
|
||
|
if style.name == new_name:
|
||
|
new_name_idx += 1
|
||
|
new_name = base_name+" "+str(new_name_idx)
|
||
|
found_unique_name = false
|
||
|
return new_name
|
||
|
|
||
|
#endregion
|
||
|
|