From 652aad19ff3b63caa7056fa9cf2cb4a6401a2f5a Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Sun, 25 Dec 2022 17:03:30 +0100 Subject: [PATCH 1/7] Move global portrait settings to own tab and autosave # Autosave on all changes for the character editor This is not optimal, but is a quick fix for the portrait preview not working. Also character resources aren't complex enough to make this a problem I believe. # Move global portrait settings to seperate tab This makes default portrait and main_scale, *_offset and *_mirror part of the character editor again in the portrait section. This makes the editor less crowded. --- .../CharacterEditor/character_editor.gd | 57 ++++- .../CharacterEditor/character_editor.tscn | 241 +++++++----------- .../character_editor_tab_general.gd | 49 ---- .../character_editor_tab_general.tscn | 171 +------------ .../Events/Character/default_portrait.gd | 2 + .../Events/Character/default_portrait.tscn | 2 +- 6 files changed, 154 insertions(+), 368 deletions(-) diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd b/addons/dialogic/Editor/CharacterEditor/character_editor.gd index 89e9d7605..965433320 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd @@ -52,6 +52,13 @@ func _open_resource(resource:Resource) -> void: for main_edit in %MainEditTabs.get_children(): main_edit._load_character(current_resource) + %DefaultPortraitPicker.set_value(resource.default_portrait) + + %MainScale.value = 100*resource.scale + %MainOffsetX.value = resource.offset.x + %MainOffsetY.value = resource.offset.y + %MainMirror.button_pressed = resource.mirror + # Portrait section %PortraitSearch.text = "" load_portrait_tree() @@ -64,8 +71,22 @@ func _save_resource() -> void: if ! visible or not current_resource: return + # Portrait list current_resource.portraits = get_updated_portrait_dict() + # Portrait settings + if %DefaultPortraitPicker.current_value in current_resource.portraits.keys(): + current_resource.default_portrait = %DefaultPortraitPicker.current_value + elif !current_resource.portraits.is_empty(): + current_resource.default_portrait = current_resource.portraits.keys()[0] + else: + current_resource.default_portrait = "" + + current_resource.scale = %MainScale.value/100.0 + current_resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.value) + current_resource.mirror = %MainMirror.button_pressed + + # Main tabs for main_edit in %MainEditTabs.get_children(): current_resource = main_edit._save_changes(current_resource) @@ -102,6 +123,17 @@ func _ready() -> void: %PortraitTree.item_selected.connect(load_selected_portrait) %PortraitTree.item_edited.connect(_on_item_edited) + %DefaultPortraitPicker.value_changed.connect(default_portrait_changed) + %MainScale.value_changed.connect(main_portrait_settings_update) + %MainOffsetX.value_changed.connect(main_portrait_settings_update) + %MainOffsetY.value_changed.connect(main_portrait_settings_update) + %MainMirror.toggled.connect(main_portrait_settings_update) + + # Setting up Default Portrait Picker + %DefaultPortraitPicker.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/portrait.svg") + %DefaultPortraitPicker.get_suggestions_func = suggest_portraits + %DefaultPortraitPicker.set_left_text("") + %PreviewMode.item_selected.connect(_on_PreviewMode_item_selected) %PreviewMode.select(DialogicUtil.get_project_setting('dialogic/editor/character_preview_mode', 0)) _on_PreviewMode_item_selected(%PreviewMode.selected) @@ -158,7 +190,7 @@ func add_main_tab(scene_path:String) -> void: func something_changed(fake_argument = "", fake_arg2 = null) -> void: if not loading: current_resource_state = ResourceStates.Unsaved -# _save_resource() TODO, should this happen? + editors_manager.save_current_resource() #TODO, should this happen? ############################################################################## @@ -365,11 +397,28 @@ func _on_PreviewMode_item_selected(index:int) -> void: ProjectSettings.save() +func _on_full_preview_available_rect_resized(): + if current_preview_mode == PreviewModes.Full: + update_preview() + + +# Make sure preview get's updated when portrait settings change func main_portrait_settings_update(value = null) -> void: + current_resource.scale = %MainScale.value/100.0 + current_resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.value) + current_resource.mirror = %MainMirror.button_pressed update_preview() something_changed() +func default_portrait_changed(property:String, value:String) -> void: + current_resource.default_portrait = value + update_default_portrait_star(value) + + +# Get suggestions for DefaultPortraitPicker +func suggest_portraits(search:String) -> Dictionary: + var suggestions := {} + for portrait in get_updated_portrait_dict().keys(): + suggestions[portrait] = {'value':portrait} + return suggestions -func _on_full_preview_available_rect_resized(): - if current_preview_mode == PreviewModes.Full: - update_preview() diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn index 702a2d7fe..6dc984098 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn @@ -1,12 +1,13 @@ -[gd_scene load_steps=11 format=3 uid="uid://dxt0c6mx24nxo"] +[gd_scene load_steps=12 format=3 uid="uid://dxt0c6mx24nxo"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor.gd" id="2"] +[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/ComplexPicker.tscn" id="2_01va3"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_image.gd" id="2_cusvj"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_scene.gd" id="4_6tltp"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/FilePicker.tscn" id="4_a4bcu"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_layout.gd" id="5_eicvp"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cf78c"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_83hxt"] content_margin_left = 10.0 content_margin_top = 4.0 content_margin_right = 10.0 @@ -16,7 +17,7 @@ border_width_top = 2 border_color = Color(1, 1, 1, 0.75) corner_detail = 1 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_l8t00"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1cl71"] content_margin_left = 7.5 content_margin_top = 7.5 content_margin_right = 7.5 @@ -27,7 +28,7 @@ corner_radius_top_right = 3 corner_radius_bottom_right = 3 corner_radius_bottom_left = 3 -[sub_resource type="Image" id="Image_fyuk7"] +[sub_resource type="Image" id="Image_6yblc"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -36,13 +37,12 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_asiy6"] -image = SubResource("Image_fyuk7") +[sub_resource type="ImageTexture" id="ImageTexture_osvex"] +image = SubResource("Image_6yblc") [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4xgdx"] [node name="CharacterEditor" type="MarginContainer"] -visible = false self_modulate = Color(0, 0, 0, 1) anchors_preset = 15 anchor_right = 1.0 @@ -57,24 +57,16 @@ script = ExtResource("2") [node name="Split" type="HSplitContainer" parent="."] layout_mode = 2 -offset_right = 1152.0 -offset_bottom = 648.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="Editor" type="VSplitContainer" parent="Split"] layout_mode = 2 -offset_right = 454.0 -offset_bottom = 648.0 -grow_horizontal = 2 -grow_vertical = 2 size_flags_horizontal = 3 size_flags_vertical = 11 [node name="EditorScroll" type="ScrollContainer" parent="Split/Editor"] layout_mode = 2 -offset_right = 454.0 -offset_bottom = 54.0 size_flags_horizontal = 3 size_flags_stretch_ratio = 0.0 vertical_scroll_mode = 0 @@ -82,93 +74,129 @@ vertical_scroll_mode = 0 [node name="MainEditTabs" type="TabContainer" parent="Split/Editor/EditorScroll"] unique_name_in_owner = true layout_mode = 2 -offset_right = 454.0 -offset_bottom = 54.0 size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_cf78c") -theme_override_styles/panel = SubResource("StyleBoxFlat_l8t00") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_83hxt") +theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") [node name="PortraitListSection" type="TabContainer" parent="Split/Editor"] unique_name_in_owner = true layout_mode = 2 -offset_top = 66.0 -offset_right = 454.0 -offset_bottom = 648.0 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_cf78c") -theme_override_styles/panel = SubResource("StyleBoxFlat_l8t00") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_83hxt") +theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") [node name="Portraits" type="VBoxContainer" parent="Split/Editor/PortraitListSection"] +visible = false layout_mode = 2 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 7.5 -offset_top = 38.5 -offset_right = -7.5 -offset_bottom = -7.5 -grow_horizontal = 2 -grow_vertical = 2 [node name="PortraitListTools" type="HBoxContainer" parent="Split/Editor/PortraitListSection/Portraits"] layout_mode = 2 -offset_right = 439.0 -offset_bottom = 31.0 [node name="AddPortraitButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -offset_right = 24.0 -offset_bottom = 31.0 -icon = SubResource("ImageTexture_asiy6") +icon = SubResource("ImageTexture_osvex") [node name="ImportPortraitsButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -offset_left = 28.0 -offset_right = 52.0 -offset_bottom = 31.0 -icon = SubResource("ImageTexture_asiy6") +icon = SubResource("ImageTexture_osvex") [node name="PortraitSearch" type="LineEdit" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -offset_left = 56.0 -offset_right = 439.0 -offset_bottom = 31.0 size_flags_horizontal = 3 size_flags_vertical = 4 placeholder_text = "Search" expand_to_text_length = true clear_button_enabled = true -right_icon = SubResource("ImageTexture_asiy6") +right_icon = SubResource("ImageTexture_osvex") caret_blink = true caret_blink_interval = 0.5 [node name="Panel" type="PanelContainer" parent="Split/Editor/PortraitListSection/Portraits"] layout_mode = 2 -offset_top = 35.0 -offset_right = 439.0 -offset_bottom = 314.0 size_flags_vertical = 3 theme_override_styles/panel = SubResource("StyleBoxEmpty_4xgdx") [node name="PortraitTree" type="Tree" parent="Split/Editor/PortraitListSection/Portraits/Panel"] unique_name_in_owner = true layout_mode = 2 -offset_right = 439.0 -offset_bottom = 279.0 allow_rmb_select = true hide_folding = true hide_root = true +[node name="P Settings" type="VBoxContainer" parent="Split/Editor/PortraitListSection"] +layout_mode = 2 + +[node name="DefaultPortrait" type="HBoxContainer" parent="Split/Editor/PortraitListSection/P Settings"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label5" type="Label" parent="Split/Editor/PortraitListSection/P Settings/DefaultPortrait"] +layout_mode = 2 +text = "Default:" + +[node name="DefaultPortraitPicker" parent="Split/Editor/PortraitListSection/P Settings/DefaultPortrait" instance=ExtResource("2_01va3")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Select Portrait" + +[node name="HSeparator" type="HSeparator" parent="Split/Editor/PortraitListSection/P Settings"] +layout_mode = 2 + +[node name="PortraitMainSettings" type="HFlowContainer" parent="Split/Editor/PortraitListSection/P Settings"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings"] +layout_mode = 2 +text = "Scale" + +[node name="MainScale" type="SpinBox" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings"] +unique_name_in_owner = true +layout_mode = 2 +value = 100.0 +allow_greater = true +suffix = "%" + +[node name="Offset" type="HBoxContainer" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings"] +layout_mode = 2 + +[node name="Label2" type="Label" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings/Offset"] +layout_mode = 2 +text = "Offset" + +[node name="MainOffsetX" type="SpinBox" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings/Offset"] +unique_name_in_owner = true +layout_mode = 2 +allow_greater = true +allow_lesser = true +suffix = "X" + +[node name="MainOffsetY" type="SpinBox" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings/Offset"] +unique_name_in_owner = true +layout_mode = 2 +allow_greater = true +allow_lesser = true +suffix = "Y" + +[node name="MirrorOption" type="HBoxContainer" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings"] +layout_mode = 2 + +[node name="Label" type="Label" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings/MirrorOption"] +layout_mode = 2 +text = "Mirror" + +[node name="MainMirror" type="CheckBox" parent="Split/Editor/PortraitListSection/P Settings/PortraitMainSettings/MirrorOption"] +unique_name_in_owner = true +layout_mode = 2 + [node name="RightSection" type="VSplitContainer" parent="Split"] layout_mode = 2 -offset_left = 466.0 -offset_right = 1152.0 -offset_bottom = 648.0 size_flags_horizontal = 3 size_flags_vertical = 3 size_flags_stretch_ratio = 1.5 @@ -177,11 +205,9 @@ size_flags_stretch_ratio = 1.5 unique_name_in_owner = true clip_contents = true layout_mode = 2 -offset_right = 686.0 -offset_bottom = 492.0 size_flags_horizontal = 3 size_flags_vertical = 3 -theme_override_styles/panel = SubResource("StyleBoxFlat_l8t00") +theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") [node name="Node2D" type="Node2D" parent="Split/RightSection/PortraitPreviewSection"] position = Vector2(13, 17) @@ -189,7 +215,7 @@ position = Vector2(13, 17) [node name="RealPreviewPivot" type="Sprite2D" parent="Split/RightSection/PortraitPreviewSection/Node2D"] unique_name_in_owner = true position = Vector2(289, 362) -texture = SubResource("ImageTexture_asiy6") +texture = SubResource("ImageTexture_osvex") [node name="ScenePreviewWarning" type="Label" parent="Split/RightSection/PortraitPreviewSection"] unique_name_in_owner = true @@ -229,11 +255,6 @@ metadata/_edit_layout_mode = 1 [node name="Control" type="Control" parent="Split/RightSection/PortraitPreviewSection/PreviewReal"] layout_mode = 2 -anchors_preset = 0 -offset_left = 302.0 -offset_top = 69.0 -offset_right = 302.0 -offset_bottom = 69.0 [node name="RealSizeRemotePivotTransform" type="RemoteTransform2D" parent="Split/RightSection/PortraitPreviewSection/PreviewReal/Control"] unique_name_in_owner = true @@ -291,188 +312,115 @@ offset_bottom = -12.0 [node name="PortraitSettingsSection" type="TabContainer" parent="Split/RightSection"] unique_name_in_owner = true layout_mode = 2 -offset_top = 504.0 -offset_right = 686.0 -offset_bottom = 648.0 size_flags_vertical = 3 size_flags_stretch_ratio = 0.3 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_cf78c") -theme_override_styles/panel = SubResource("StyleBoxFlat_l8t00") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_83hxt") +theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") [node name="Image" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] custom_minimum_size = Vector2(0, 35) layout_mode = 2 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 7.5 -offset_top = 38.5 -offset_right = -7.5 -offset_bottom = -7.5 -grow_horizontal = 2 -grow_vertical = 2 horizontal_scroll_mode = 0 script = ExtResource("2_cusvj") [node name="Flow" type="HFlowContainer" parent="Split/RightSection/PortraitSettingsSection/Image"] layout_mode = 2 -offset_right = 671.0 -offset_bottom = 98.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="GridContainer" type="GridContainer" parent="Split/RightSection/PortraitSettingsSection/Image/Flow"] layout_mode = 2 -offset_right = 671.0 -offset_bottom = 38.0 size_flags_horizontal = 3 size_flags_vertical = 3 columns = 2 [node name="Label" type="Label" parent="Split/RightSection/PortraitSettingsSection/Image/Flow/GridContainer"] layout_mode = 2 -offset_top = 6.0 -offset_right = 57.0 -offset_bottom = 32.0 text = "Image: " [node name="ImagePicker" parent="Split/RightSection/PortraitSettingsSection/Image/Flow/GridContainer" instance=ExtResource("4_a4bcu")] unique_name_in_owner = true layout_mode = 2 -offset_left = 61.0 -offset_right = 671.0 -offset_bottom = 38.0 size_flags_horizontal = 3 file_filter = "*.png, *.svg" -resource_icon = SubResource("ImageTexture_asiy6") +resource_icon = SubResource("ImageTexture_osvex") [node name="Scene" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] visible = false custom_minimum_size = Vector2(0, 35) layout_mode = 2 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_left = 10.0 -offset_top = 41.0 -offset_right = -10.0 -offset_bottom = -10.0 -grow_horizontal = 2 -grow_vertical = 2 horizontal_scroll_mode = 0 script = ExtResource("4_6tltp") [node name="Flow" type="HFlowContainer" parent="Split/RightSection/PortraitSettingsSection/Scene"] unique_name_in_owner = true layout_mode = 2 -offset_right = 666.0 -offset_bottom = 93.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="GridContainer" type="GridContainer" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow"] layout_mode = 2 -offset_right = 584.0 -offset_bottom = 63.0 size_flags_horizontal = 3 size_flags_vertical = 3 columns = 2 [node name="Label" type="Label" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow/GridContainer"] layout_mode = 2 -offset_top = 3.0 -offset_right = 102.0 -offset_bottom = 29.0 text = "Scene: " [node name="ScenePicker" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow/GridContainer" instance=ExtResource("4_a4bcu")] unique_name_in_owner = true layout_mode = 2 -offset_left = 106.0 -offset_right = 584.0 -offset_bottom = 33.0 size_flags_horizontal = 3 file_filter = "*.tscn" placeholder = "Default scene" -resource_icon = SubResource("ImageTexture_asiy6") +resource_icon = SubResource("ImageTexture_osvex") [node name="Label2" type="Label" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow/GridContainer"] layout_mode = 2 -offset_top = 37.0 -offset_right = 102.0 -offset_bottom = 63.0 text = "Ignore scale: " [node name="IgnoreScale" type="CheckBox" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow/GridContainer"] unique_name_in_owner = true layout_mode = 2 -offset_left = 106.0 -offset_top = 37.0 -offset_right = 584.0 -offset_bottom = 63.0 [node name="Layout" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] visible = false custom_minimum_size = Vector2(0, 35) layout_mode = 2 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -offset_top = 31.0 -grow_horizontal = 2 -grow_vertical = 2 horizontal_scroll_mode = 0 script = ExtResource("5_eicvp") [node name="Flow" type="HFlowContainer" parent="Split/RightSection/PortraitSettingsSection/Layout"] layout_mode = 2 -offset_right = 686.0 -offset_bottom = 113.0 size_flags_horizontal = 3 size_flags_vertical = 3 [node name="HBoxContainer" type="HBoxContainer" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow"] layout_mode = 2 -offset_right = 150.0 -offset_bottom = 33.0 [node name="Label" type="Label" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/HBoxContainer"] layout_mode = 2 -offset_top = 3.0 -offset_right = 40.0 -offset_bottom = 29.0 text = "Scale:" [node name="PortraitScale" type="SpinBox" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/HBoxContainer"] unique_name_in_owner = true layout_mode = 2 -offset_left = 44.0 -offset_right = 150.0 -offset_bottom = 33.0 value = 100.0 allow_greater = true suffix = "%" [node name="HBoxContainer2" type="HBoxContainer" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow"] layout_mode = 2 -offset_top = 37.0 -offset_right = 268.0 -offset_bottom = 70.0 [node name="Label2" type="Label" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/HBoxContainer2"] layout_mode = 2 -offset_top = 3.0 -offset_right = 48.0 -offset_bottom = 29.0 text = "Offset:" [node name="PortraitOffsetX" type="SpinBox" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/HBoxContainer2"] unique_name_in_owner = true layout_mode = 2 -offset_left = 52.0 -offset_right = 158.0 -offset_bottom = 33.0 allow_greater = true allow_lesser = true suffix = "X" @@ -480,33 +428,20 @@ suffix = "X" [node name="PortraitOffsetY" type="SpinBox" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/HBoxContainer2"] unique_name_in_owner = true layout_mode = 2 -offset_left = 162.0 -offset_right = 268.0 -offset_bottom = 33.0 allow_greater = true allow_lesser = true suffix = "Y" [node name="MirrorOption" type="HBoxContainer" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow"] layout_mode = 2 -offset_left = 272.0 -offset_top = 37.0 -offset_right = 350.0 -offset_bottom = 70.0 [node name="Label" type="Label" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/MirrorOption"] layout_mode = 2 -offset_top = 3.0 -offset_right = 50.0 -offset_bottom = 29.0 text = "Mirror:" [node name="PortraitMirror" type="CheckBox" parent="Split/RightSection/PortraitSettingsSection/Layout/Flow/MirrorOption"] unique_name_in_owner = true layout_mode = 2 -offset_left = 54.0 -offset_right = 78.0 -offset_bottom = 33.0 [connection signal="button_clicked" from="Split/Editor/PortraitListSection/Portraits/Panel/PortraitTree" to="." method="_on_portrait_tree_button_clicked"] [connection signal="resized" from="Split/RightSection/PortraitPreviewSection/FullPreviewAvailableRect" to="." method="_on_full_preview_available_rect_resized"] diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.gd b/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.gd index 36f56855b..4aa3fec9c 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.gd @@ -10,16 +10,6 @@ func _ready() -> void: %DisplayNameLineEdit.text_changed.connect(character_editor.something_changed) %NicknameLineEdit.text_changed.connect(character_editor.something_changed) %DescriptionTextEdit.text_changed.connect(character_editor.something_changed) - %DefaultPortraitPicker.value_changed.connect(default_portrait_changed) - %MainScale.value_changed.connect(main_portrait_settings_update) - %MainOffsetX.value_changed.connect(main_portrait_settings_update) - %MainOffsetY.value_changed.connect(main_portrait_settings_update) - %MainMirror.toggled.connect(main_portrait_settings_update) - - # Setting up Default Portrait Picker - %DefaultPortraitPicker.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/portrait.svg") - %DefaultPortraitPicker.get_suggestions_func = suggest_portraits - %DefaultPortraitPicker.set_left_text("") func _load_character(resource:DialogicCharacter) -> void: @@ -32,12 +22,6 @@ func _load_character(resource:DialogicCharacter) -> void: %NicknameLineEdit.text = %NicknameLineEdit.text.trim_suffix(', ') %DescriptionTextEdit.text = resource.description - %DefaultPortraitPicker.set_value(resource.default_portrait) - - %MainScale.value = 100*resource.scale - %MainOffsetX.value = resource.offset.x - %MainOffsetY.value = resource.offset.y - %MainMirror.button_pressed = resource.mirror func _save_changes(resource:DialogicCharacter) -> DialogicCharacter: @@ -49,37 +33,4 @@ func _save_changes(resource:DialogicCharacter) -> DialogicCharacter: resource.nicknames = nicknames resource.description = %DescriptionTextEdit.text - if $'%DefaultPortraitPicker'.current_value in resource.portraits.keys(): - resource.default_portrait = $'%DefaultPortraitPicker'.current_value - elif !resource.portraits.is_empty(): - resource.default_portrait = resource.portraits.keys()[0] - else: - resource.default_portrait = "" - - resource.scale = %MainScale.value/100.0 - resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.value) - resource.mirror = %MainMirror.button_pressed - return resource - - -# Get suggestions for DefaultPortraitPicker -func suggest_portraits(search:String) -> Dictionary: - var suggestions := {} - for portrait in character_editor.get_updated_portrait_dict().keys(): - suggestions[portrait] = {'value':portrait} - return suggestions - - -# Make sure preview get's updated when portrait settings change -func main_portrait_settings_update(value = null) -> void: - character_editor.current_resource.scale = %MainScale.value/100.0 - character_editor.current_resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.value) - character_editor.current_resource.mirror = %MainMirror.button_pressed - character_editor.update_preview() - character_editor.something_changed() - -func default_portrait_changed(property:String, value:String) -> void: - character_editor.current_resource.default_portrait = value - character_editor.update_default_portrait_star(value) - diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn b/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn index 98cea1dd7..6395c73e8 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn @@ -1,6 +1,5 @@ -[gd_scene load_steps=3 format=3 uid="uid://de5kj4vd0we1w"] +[gd_scene load_steps=2 format=3 uid="uid://de5kj4vd0we1w"] -[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/ComplexPicker.tscn" id="1_3b04d"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.gd" id="1_3e1i1"] [node name="General" type="GridContainer"] @@ -20,27 +19,17 @@ script = ExtResource("1_3e1i1") [node name="Label2" type="Label" parent="."] layout_mode = 2 -offset_right = 131.0 -offset_bottom = 26.0 -size_flags_vertical = 0 +tooltip_text = "This name will be displayed on the name label. You can use a dialogic variable: {Player.name}" text = "Display Name: " [node name="DisplayName" type="HBoxContainer" parent="."] layout_mode = 2 -offset_left = 132.0 -offset_right = 1137.0 -offset_bottom = 31.0 size_flags_horizontal = 3 -[node name="CheckBox" type="CheckBox" parent="DisplayName"] -visible = false -layout_mode = 2 - [node name="DisplayNameLineEdit" type="LineEdit" parent="DisplayName"] unique_name_in_owner = true layout_mode = 2 -offset_right = 67.0 -offset_bottom = 31.0 +tooltip_text = "This name will be displayed on the name label. You can use a dialogic variable: {Player.name}" expand_to_text_length = true caret_blink = true caret_blink_interval = 0.5 @@ -49,173 +38,33 @@ caret_blink_interval = 0.5 unique_name_in_owner = true custom_minimum_size = Vector2(30, 0) layout_mode = 2 -offset_left = 71.0 -offset_right = 101.0 -offset_bottom = 31.0 +tooltip_text = "This color can be used on the name label and for occurences of the characters name in text (autocolor names)." color = Color(1, 1, 1, 1) edit_alpha = false [node name="Label3" type="Label" parent="."] layout_mode = 2 -offset_top = 37.0 -offset_right = 131.0 -offset_bottom = 63.0 -size_flags_vertical = 0 +tooltip_text = "If autocolor names is enabled, these will be colored in the characters color as well." text = "Nicknames:" -[node name="DisplayNickname" type="HBoxContainer" parent="."] -layout_mode = 2 -offset_left = 132.0 -offset_top = 37.0 -offset_right = 1137.0 -offset_bottom = 68.0 -size_flags_horizontal = 3 - -[node name="NicknameLineEdit" type="LineEdit" parent="DisplayNickname"] +[node name="NicknameLineEdit" type="LineEdit" parent="."] unique_name_in_owner = true layout_mode = 2 -offset_right = 1005.0 -offset_bottom = 31.0 size_flags_horizontal = 3 +tooltip_text = "If autocolor names is enabled, these will be colored in the characters color as well." caret_blink = true caret_blink_interval = 0.5 [node name="Label4" type="Label" parent="."] layout_mode = 2 -offset_top = 74.0 -offset_right = 131.0 -offset_bottom = 100.0 size_flags_vertical = 0 +tooltip_text = "No effect, just for you." text = "Description:" -[node name="Description" type="HBoxContainer" parent="."] -layout_mode = 2 -offset_left = 132.0 -offset_top = 74.0 -offset_right = 1137.0 -offset_bottom = 109.0 -size_flags_horizontal = 3 - -[node name="DescriptionTextEdit" type="TextEdit" parent="Description"] +[node name="DescriptionTextEdit" type="TextEdit" parent="."] unique_name_in_owner = true layout_mode = 2 -offset_right = 1005.0 -offset_bottom = 35.0 size_flags_horizontal = 3 +tooltip_text = "No effect, just for you." wrap_mode = 1 scroll_fit_content_height = true - -[node name="Label5" type="Label" parent="."] -layout_mode = 2 -offset_top = 115.0 -offset_right = 131.0 -offset_bottom = 141.0 -size_flags_vertical = 0 -text = "Default Portrait:" - -[node name="DefaultPortrait" type="HBoxContainer" parent="."] -layout_mode = 2 -offset_left = 132.0 -offset_top = 115.0 -offset_right = 1137.0 -offset_bottom = 150.0 -size_flags_horizontal = 3 - -[node name="DefaultPortraitPicker" parent="DefaultPortrait" instance=ExtResource("1_3b04d")] -unique_name_in_owner = true -layout_mode = 2 -anchors_preset = 0 -anchor_right = 0.0 -anchor_bottom = 0.0 -offset_left = 0.0 -offset_top = 0.0 -offset_right = 180.0 -offset_bottom = 35.0 -grow_horizontal = 1 -grow_vertical = 1 - -[node name="Label6" type="Label" parent="."] -layout_mode = 2 -offset_top = 156.0 -offset_right = 131.0 -offset_bottom = 182.0 -size_flags_vertical = 0 -text = "Portrait Settings:" - -[node name="PortraitMainSettings" type="HFlowContainer" parent="."] -layout_mode = 2 -offset_left = 132.0 -offset_top = 156.0 -offset_right = 1137.0 -offset_bottom = 187.0 -size_flags_horizontal = 3 - -[node name="Label" type="Label" parent="PortraitMainSettings"] -layout_mode = 2 -offset_top = 2.0 -offset_right = 40.0 -offset_bottom = 28.0 -text = "Scale" - -[node name="MainScale" type="SpinBox" parent="PortraitMainSettings"] -unique_name_in_owner = true -layout_mode = 2 -offset_left = 44.0 -offset_right = 127.0 -offset_bottom = 31.0 -value = 100.0 -allow_greater = true -suffix = "%" - -[node name="Offset" type="HBoxContainer" parent="PortraitMainSettings"] -layout_mode = 2 -offset_left = 131.0 -offset_right = 353.0 -offset_bottom = 31.0 - -[node name="Label2" type="Label" parent="PortraitMainSettings/Offset"] -layout_mode = 2 -offset_top = 2.0 -offset_right = 48.0 -offset_bottom = 28.0 -text = "Offset" - -[node name="MainOffsetX" type="SpinBox" parent="PortraitMainSettings/Offset"] -unique_name_in_owner = true -layout_mode = 2 -offset_left = 52.0 -offset_right = 135.0 -offset_bottom = 31.0 -allow_greater = true -allow_lesser = true -suffix = "X" - -[node name="MainOffsetY" type="SpinBox" parent="PortraitMainSettings/Offset"] -unique_name_in_owner = true -layout_mode = 2 -offset_left = 139.0 -offset_right = 222.0 -offset_bottom = 31.0 -allow_greater = true -allow_lesser = true -suffix = "Y" - -[node name="MirrorOption" type="HBoxContainer" parent="PortraitMainSettings"] -layout_mode = 2 -offset_left = 357.0 -offset_right = 435.0 -offset_bottom = 31.0 - -[node name="Label" type="Label" parent="PortraitMainSettings/MirrorOption"] -layout_mode = 2 -offset_top = 2.0 -offset_right = 50.0 -offset_bottom = 28.0 -text = "Mirror" - -[node name="MainMirror" type="CheckBox" parent="PortraitMainSettings/MirrorOption"] -unique_name_in_owner = true -layout_mode = 2 -offset_left = 54.0 -offset_right = 78.0 -offset_bottom = 31.0 diff --git a/addons/dialogic/Events/Character/default_portrait.gd b/addons/dialogic/Events/Character/default_portrait.gd index e14d17856..a8dee89cc 100644 --- a/addons/dialogic/Events/Character/default_portrait.gd +++ b/addons/dialogic/Events/Character/default_portrait.gd @@ -43,4 +43,6 @@ func _set_mirror(mirror:bool) -> void: ## If implemented, this is used by the editor for the "full view" mode func _get_covered_rect() -> Rect2: + if $Portrait.texture == null: + return Rect2() return Rect2($Portrait.position, $Portrait.get_rect().size) diff --git a/addons/dialogic/Events/Character/default_portrait.tscn b/addons/dialogic/Events/Character/default_portrait.tscn index 9f0e0edb0..073d111ec 100644 --- a/addons/dialogic/Events/Character/default_portrait.tscn +++ b/addons/dialogic/Events/Character/default_portrait.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=3 format=3] +[gd_scene load_steps=3 format=3 uid="uid://c4yp65n7ju1br"] [ext_resource type="Script" path="res://addons/dialogic/Events/Character/default_portrait.gd" id="1_wn77n"] From 25eadec072c073336e9c3b4abaad1653b75a30ec Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Sun, 25 Dec 2022 17:36:23 +0100 Subject: [PATCH 2/7] Make sure portrait preview gets cleared if no portrait --- addons/dialogic/Editor/CharacterEditor/character_editor.gd | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd b/addons/dialogic/Editor/CharacterEditor/character_editor.gd index 965433320..b8dfabb5a 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd @@ -43,7 +43,7 @@ func _register() -> void: # Called when a character is opened somehow func _open_resource(resource:Resource) -> void: # update resource - current_resource = resource + current_resource = (resource as DialogicCharacter) # make sure changes in the ui won't trigger saving loading = true @@ -63,6 +63,9 @@ func _open_resource(resource:Resource) -> void: %PortraitSearch.text = "" load_portrait_tree() + if resource.portraits.is_empty(): + update_preview() + loading = false character_loaded.emit(resource.resource_path) From 4d1817283b6736225b7f64d7414297976ba77142 Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Mon, 26 Dec 2022 14:46:19 +0100 Subject: [PATCH 3/7] Add export overrides section to custom portrait scene settings New portrait settings section "Exports" if a custom portrait scene is selected. This tab shows all the exported variables of that scene and allows to set those. The editor will now also keep the same scene if _should_do_portrait_update is defined and true. This allows blending from one portrait to the other in editor. --- .../CharacterEditor/character_editor.gd | 60 ++++++++--- .../CharacterEditor/character_editor.tscn | 71 ++++++++---- .../character_editor_portrait_settings_tab.gd | 2 +- .../character_editor_ptab_exports.gd | 102 ++++++++++++++++++ .../character_editor_ptab_image.gd | 7 +- 5 files changed, 198 insertions(+), 44 deletions(-) create mode 100644 addons/dialogic/Editor/CharacterEditor/character_editor_ptab_exports.gd diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd b/addons/dialogic/Editor/CharacterEditor/character_editor.gd index b8dfabb5a..4619b2f44 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd @@ -13,6 +13,7 @@ enum PreviewModes {Full, Real} # Current state var current_preview_mode = PreviewModes.Full var loading = false +var current_previewed_scene = null # References var selected_item: TreeItem @@ -63,9 +64,6 @@ func _open_resource(resource:Resource) -> void: %PortraitSearch.text = "" load_portrait_tree() - if resource.portraits.is_empty(): - update_preview() - loading = false character_loaded.emit(resource.resource_path) @@ -236,6 +234,9 @@ func load_portrait_tree() -> void: if root.get_child_count(): root.get_first_child().select(0) + else: + # Call anyways to clear preview and hide portrait settings section + load_selected_portrait() @@ -276,7 +277,7 @@ func load_selected_portrait(): selected_item = %PortraitTree.get_selected() if selected_item: - + %PortraitSettingsSection.show() var current_portrait_data :Dictionary = selected_item.get_metadata(0) portrait_selected.emit(selected_item.get_text(0), current_portrait_data) @@ -289,8 +290,20 @@ func load_selected_portrait(): tab.selected_item = selected_item tab._load_portrait_data(current_portrait_data) + # switch tabs if the current one is hidden (until the next not hidden tab) + for i in range(%PortraitSettingsSection.get_tab_count()): + if %PortraitSettingsSection.is_tab_hidden(%PortraitSettingsSection.current_tab): + if %PortraitSettingsSection.current_tab == %PortraitSettingsSection.get_tab_count()-1: + %PortraitSettingsSection.current_tab = 0 + else: + %PortraitSettingsSection.current_tab += 1 + else: + break + await get_tree().create_timer(0.01).timeout selected_item.set_editable(0, true) + else: + %PortraitSettingsSection.hide() func delete_portrait_item(item:TreeItem) -> void: @@ -312,8 +325,6 @@ func _on_portrait_tree_button_clicked(item:TreeItem, column:int, id:int, mouse_b func update_preview() -> void: - for node in %RealPreviewPivot.get_children(): - node.queue_free() %ScenePreviewWarning.hide() if selected_item and is_instance_valid(selected_item): %PreviewLabel.text = 'Preview of "'+selected_item.get_text(0)+'"' @@ -322,24 +333,35 @@ func update_preview() -> void: var scale:float = current_portrait_data.get('scale', 1) * current_resource.scale var offset:Vector2 =current_portrait_data.get('offset', Vector2()) + current_resource.offset - var scene = null - if current_portrait_data.get('scene', '').is_empty(): - scene = load("res://addons/dialogic/Events/Character/default_portrait.tscn") + if current_previewed_scene != null and current_previewed_scene.get_meta('path', null) == current_portrait_data.get('scene') and current_previewed_scene.has_method('_should_do_portrait_update') and current_previewed_scene._should_do_portrait_update(current_resource, selected_item.get_text(0)): + pass # we keep the same scene else: - scene = load(current_portrait_data.get('scene')) - - if scene: - scene = scene.instantiate() + for node in %RealPreviewPivot.get_children(): + node.queue_free() + current_previewed_scene = null + if current_portrait_data.get('scene', '').is_empty(): + if FileAccess.file_exists("res://addons/dialogic/Events/Character/default_portrait.tscn"): + current_previewed_scene = load("res://addons/dialogic/Events/Character/default_portrait.tscn").instantiate() + current_previewed_scene.set_meta('path', '') + else: + if FileAccess.file_exists(current_portrait_data.get('scene')): + current_previewed_scene = load(current_portrait_data.get('scene')).instantiate() + current_previewed_scene.set_meta('path', current_portrait_data.get('scene')) + if current_previewed_scene: + %RealPreviewPivot.add_child(current_previewed_scene) + + if current_previewed_scene != null: + var scene = current_previewed_scene scene.show_behind_parent = true - %RealPreviewPivot.add_child(scene) + for prop in current_portrait_data.get('export_overrides', {}).keys(): + scene.set(prop, str_to_var(current_portrait_data['export_overrides'][prop])) if is_instance_valid(scene.get_script()) and scene.script.is_tool(): if scene.has_method('_update_portrait'): scene._update_portrait(current_resource, selected_item.get_text(0)) if scene.has_method('_set_mirror'): scene._set_mirror(mirror) - if current_preview_mode == PreviewModes.Real: scene.position = Vector2() + offset @@ -359,7 +381,13 @@ func update_preview() -> void: %PreviewRealRect.texture = null %PreviewFullRect.texture = null %PreviewLabel.text = 'Nothing to preview' - + + else: + %PreviewLabel.text = 'No portrait to preview.' + for node in %RealPreviewPivot.get_children(): + node.queue_free() + current_previewed_scene = null + # this removes/and adds the DEFAULT star on the portrait list func update_default_portrait_star(default_portrait_name:String) -> void: diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn index 6dc984098..a3b6c1899 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=3 uid="uid://dxt0c6mx24nxo"] +[gd_scene load_steps=14 format=3 uid="uid://dxt0c6mx24nxo"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/ComplexPicker.tscn" id="2_01va3"] @@ -6,8 +6,9 @@ [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_scene.gd" id="4_6tltp"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/FilePicker.tscn" id="4_a4bcu"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_layout.gd" id="5_eicvp"] +[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_exports.gd" id="7_4enie"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_83hxt"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hdqef"] content_margin_left = 10.0 content_margin_top = 4.0 content_margin_right = 10.0 @@ -17,7 +18,7 @@ border_width_top = 2 border_color = Color(1, 1, 1, 0.75) corner_detail = 1 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1cl71"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jc1xk"] content_margin_left = 7.5 content_margin_top = 7.5 content_margin_right = 7.5 @@ -28,7 +29,7 @@ corner_radius_top_right = 3 corner_radius_bottom_right = 3 corner_radius_bottom_left = 3 -[sub_resource type="Image" id="Image_6yblc"] +[sub_resource type="Image" id="Image_dqs53"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -37,11 +38,24 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_osvex"] -image = SubResource("Image_6yblc") +[sub_resource type="ImageTexture" id="ImageTexture_ckfua"] +image = SubResource("Image_dqs53") [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4xgdx"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_sf73i"] +content_margin_left = 4.0 +content_margin_top = 4.0 +content_margin_right = 4.0 +content_margin_bottom = 4.0 +bg_color = Color(1, 0.365, 0.365, 1) +draw_center = false +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 +corner_detail = 1 + [node name="CharacterEditor" type="MarginContainer"] self_modulate = Color(0, 0, 0, 1) anchors_preset = 15 @@ -77,18 +91,17 @@ layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_83hxt") -theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_hdqef") +theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") [node name="PortraitListSection" type="TabContainer" parent="Split/Editor"] unique_name_in_owner = true layout_mode = 2 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_83hxt") -theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_hdqef") +theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") [node name="Portraits" type="VBoxContainer" parent="Split/Editor/PortraitListSection"] -visible = false layout_mode = 2 [node name="PortraitListTools" type="HBoxContainer" parent="Split/Editor/PortraitListSection/Portraits"] @@ -97,12 +110,12 @@ layout_mode = 2 [node name="AddPortraitButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -icon = SubResource("ImageTexture_osvex") +icon = SubResource("ImageTexture_ckfua") [node name="ImportPortraitsButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -icon = SubResource("ImageTexture_osvex") +icon = SubResource("ImageTexture_ckfua") [node name="PortraitSearch" type="LineEdit" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true @@ -112,7 +125,7 @@ size_flags_vertical = 4 placeholder_text = "Search" expand_to_text_length = true clear_button_enabled = true -right_icon = SubResource("ImageTexture_osvex") +right_icon = SubResource("ImageTexture_ckfua") caret_blink = true caret_blink_interval = 0.5 @@ -129,6 +142,7 @@ hide_folding = true hide_root = true [node name="P Settings" type="VBoxContainer" parent="Split/Editor/PortraitListSection"] +visible = false layout_mode = 2 [node name="DefaultPortrait" type="HBoxContainer" parent="Split/Editor/PortraitListSection/P Settings"] @@ -207,7 +221,7 @@ clip_contents = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") +theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") [node name="Node2D" type="Node2D" parent="Split/RightSection/PortraitPreviewSection"] position = Vector2(13, 17) @@ -215,7 +229,7 @@ position = Vector2(13, 17) [node name="RealPreviewPivot" type="Sprite2D" parent="Split/RightSection/PortraitPreviewSection/Node2D"] unique_name_in_owner = true position = Vector2(289, 362) -texture = SubResource("ImageTexture_osvex") +texture = SubResource("ImageTexture_ckfua") [node name="ScenePreviewWarning" type="Label" parent="Split/RightSection/PortraitPreviewSection"] unique_name_in_owner = true @@ -282,7 +296,7 @@ unique_name_in_owner = true layout_mode = 0 offset_right = 40.0 offset_bottom = 23.0 -text = "Preview" +text = "No portrait to preview." [node name="PreviewMode" type="OptionButton" parent="Split/RightSection/PortraitPreviewSection"] unique_name_in_owner = true @@ -315,10 +329,11 @@ layout_mode = 2 size_flags_vertical = 3 size_flags_stretch_ratio = 0.3 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_83hxt") -theme_override_styles/panel = SubResource("StyleBoxFlat_1cl71") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_hdqef") +theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") [node name="Image" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] +visible = false custom_minimum_size = Vector2(0, 35) layout_mode = 2 horizontal_scroll_mode = 0 @@ -344,7 +359,7 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 file_filter = "*.png, *.svg" -resource_icon = SubResource("ImageTexture_osvex") +resource_icon = SubResource("ImageTexture_ckfua") [node name="Scene" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] visible = false @@ -375,7 +390,7 @@ layout_mode = 2 size_flags_horizontal = 3 file_filter = "*.tscn" placeholder = "Default scene" -resource_icon = SubResource("ImageTexture_osvex") +resource_icon = SubResource("ImageTexture_ckfua") [node name="Label2" type="Label" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow/GridContainer"] layout_mode = 2 @@ -443,6 +458,20 @@ text = "Mirror:" unique_name_in_owner = true layout_mode = 2 +[node name="Exports" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] +custom_minimum_size = Vector2(0, 35) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_sf73i") +horizontal_scroll_mode = 0 +script = ExtResource("7_4enie") + +[node name="Grid" type="GridContainer" parent="Split/RightSection/PortraitSettingsSection/Exports"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/h_separation = 10 +columns = 2 + [connection signal="button_clicked" from="Split/Editor/PortraitListSection/Portraits/Panel/PortraitTree" to="." method="_on_portrait_tree_button_clicked"] [connection signal="resized" from="Split/RightSection/PortraitPreviewSection/FullPreviewAvailableRect" to="." method="_on_full_preview_available_rect_resized"] [connection signal="value_changed" from="Split/RightSection/PortraitSettingsSection/Image/Flow/GridContainer/ImagePicker" to="Split/RightSection/PortraitSettingsSection/Image" method="_on_image_picker_value_changed"] diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_tab.gd b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_tab.gd index 4874e8da5..5570a62dd 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_tab.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_tab.gd @@ -12,5 +12,5 @@ var character_editor:Control var selected_item :TreeItem = null -func _load_portrait(data:Dictionary) -> void: +func _load_portrait_data(data:Dictionary) -> void: pass diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_exports.gd b/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_exports.gd new file mode 100644 index 000000000..883aaf3f4 --- /dev/null +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_exports.gd @@ -0,0 +1,102 @@ +@tool +extends DialogicCharacterEditorPortraitSettingsTab + +## Tab that allows setting values of exported scene variables +## for custom portrait scenes + +var current_portrait_data := {} + +func _ready() -> void: + get_parent().set_tab_icon(get_index(), get_theme_icon("EditInternal", "EditorIcons")) + add_theme_stylebox_override('panel', get_theme_stylebox("Background", "EditorStyles")) + +func _load_portrait_data(data:Dictionary) -> void: + if data.get('scene', '').is_empty(): + get_parent().set_tab_hidden(get_index(), true) + else: + get_parent().set_tab_hidden(get_index(), false) + + current_portrait_data = data + load_portrait_scene_export_variables() + +func load_portrait_scene_export_variables(): + var scene = null + if !current_portrait_data.get('scene', '').is_empty(): + scene = load(current_portrait_data.get('scene')) + + if !scene: + return + + for child in $Grid.get_children(): + child.queue_free() + + scene = scene.instantiate() + for i in scene.script.get_script_property_list(): + if i['usage'] & PROPERTY_USAGE_EDITOR: + var label = Label.new() + label.text = i['name'] + label.add_theme_stylebox_override('normal', get_theme_stylebox("CanvasItemInfoOverlay", "EditorStyles")) + label.size_flags_horizontal = SIZE_EXPAND_FILL + $Grid.add_child(label) + + + var input = null + var current_value :String = "" + if current_portrait_data.has('export_overrides') and current_portrait_data['export_overrides'].has(i['name']): + current_value = current_portrait_data['export_overrides'][i['name']] + match typeof(scene.get(i['name'])): + TYPE_BOOL: + input = CheckBox.new() + if current_value: + input.button_pressed = current_value == "true" + input.toggled.connect(_on_export_bool_submitted.bind(i['name'])) + TYPE_COLOR: + input = ColorPickerButton.new() + if current_value: + input.color = str_to_var(current_value) + input.color_changed.connect(_on_export_color_submitted.bind(i['name'])) + input.custom_minimum_size.x = DialogicUtil.get_editor_scale()*50 + TYPE_INT: + if i['hint'] & PROPERTY_HINT_ENUM: + input = OptionButton.new() + for x in i['hint_string'].split(','): + input.add_item(x) + input.item_selected.connect(_on_export_int_enum_submitted.bind(i['name'])) + _: + input = LineEdit.new() + if current_value: + input.text = current_value + input.text_submitted.connect(_on_export_input_text_submitted.bind(i['name'])) + input.size_flags_horizontal = SIZE_EXPAND_FILL + $Grid.add_child(input) + if i['usage'] & PROPERTY_USAGE_GROUP: + var title := Label.new() + title.text = i['name'] + title.add_theme_stylebox_override('normal', get_theme_stylebox("ContextualToolbar", "EditorStyles")) + $Grid.add_child(title) + $Grid.add_child(Control.new()) + +func set_export_override(property_name:String, value:String = "") -> void: + var data:Dictionary = selected_item.get_metadata(0) + if !data.has('export_overrides'): + data['export_overrides'] = {} + + if !value.is_empty(): + data['export_overrides'][property_name] = value + else: + data['export_overrides'].erase(property_name) + + changed.emit() + update_preview.emit() + +func _on_export_input_text_submitted(text:String, property_name:String) -> void: + set_export_override(property_name, var_to_str(text)) + +func _on_export_bool_submitted(value:bool, property_name:String) -> void: + set_export_override(property_name, var_to_str(value)) + +func _on_export_color_submitted(color:Color, property_name:String) -> void: + set_export_override(property_name, var_to_str(color)) + +func _on_export_int_enum_submitted(item:int, property_name:String) -> void: + set_export_override(property_name, var_to_str(item)) diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_image.gd b/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_image.gd index b3d8cde8d..bec8e40a3 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_image.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_ptab_image.gd @@ -13,12 +13,7 @@ func _ready() -> void: func _load_portrait_data(data:Dictionary) -> void: # hides/shows this tab based on the scene value of this portrait # (only shown if the default scene is used) - if !data.get('scene', '').is_empty(): - get_parent().set_tab_hidden(get_index(), true) - while get_parent().is_tab_hidden(get_parent().current_tab): - get_parent().current_tab = (get_parent().current_tab+1)%get_parent().get_tab_count() - else: - get_parent().set_tab_hidden(get_index(), false) + get_parent().set_tab_hidden(get_index(), !data.get('scene', '').is_empty()) %ImagePicker.set_value(data.get('image', '')) From 6e218fa6456e3aa7b26b6b057e4544a0acc5211c Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Mon, 26 Dec 2022 14:47:53 +0100 Subject: [PATCH 4/7] Small fixes - makes sure typing pitch cannot be set to <= 0 by randomness. - forgot to stage the code that actually makes the export overrides work in game --- .../Events/Character/subsystem_portraits.gd | 4 + .../Text/character_settings/ui_mood_item.tscn | 122 ++++++------------ .../dialogic/Events/Text/node_type_sound.gd | 2 +- addons/dialogic/plugin.gd | 8 +- 4 files changed, 50 insertions(+), 86 deletions(-) diff --git a/addons/dialogic/Events/Character/subsystem_portraits.gd b/addons/dialogic/Events/Character/subsystem_portraits.gd index c20392b46..a102d7576 100644 --- a/addons/dialogic/Events/Character/subsystem_portraits.gd +++ b/addons/dialogic/Events/Character/subsystem_portraits.gd @@ -130,6 +130,10 @@ func change_portrait(character:DialogicCharacter, portrait:String, mirrored:bool portrait_node.scale = Vector2(1,1)*character.scale * character.portraits[portrait].get('scale', 1) else: portrait_node.scale = Vector2(1,1)*character.portraits[portrait].get('scale', 1) + + for property in character.portraits[portrait].get('export_overrides', {}).keys(): + portrait_node.set(property, str_to_var(character.portraits[portrait]['export_overrides'][property])) + if portrait_node.has_method('_update_portrait'): portrait_node._update_portrait(character, portrait) if portrait_node.has_method('_set_mirror'): diff --git a/addons/dialogic/Events/Text/character_settings/ui_mood_item.tscn b/addons/dialogic/Events/Text/character_settings/ui_mood_item.tscn index 38bb0e2e1..f7a715c2f 100644 --- a/addons/dialogic/Events/Text/character_settings/ui_mood_item.tscn +++ b/addons/dialogic/Events/Text/character_settings/ui_mood_item.tscn @@ -1,14 +1,14 @@ -[gd_scene load_steps=6 format=3] +[gd_scene load_steps=6 format=3 uid="uid://x8alx74fnm10"] [ext_resource type="Script" path="res://addons/dialogic/Events/Text/character_settings/ui_mood_item.gd" id="2"] [ext_resource type="Script" path="res://addons/dialogic/Events/Text/node_type_sound.gd" id="3"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_h1p4u"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rsmy0"] content_margin_left = 4.0 content_margin_top = 4.0 content_margin_right = 4.0 content_margin_bottom = 4.0 -bg_color = Color(0.147, 0.168, 0.203, 1) +bg_color = Color(1, 0.365, 0.365, 1) draw_center = false border_width_left = 2 border_width_top = 2 @@ -16,7 +16,7 @@ border_width_right = 2 border_width_bottom = 2 corner_detail = 1 -[sub_resource type="Image" id="Image_7wswg"] +[sub_resource type="Image" id="Image_uegt4"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -25,163 +25,123 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_o5mle"] -image = SubResource("Image_7wswg") +[sub_resource type="ImageTexture" id="ImageTexture_osvex"] +image = SubResource("Image_uegt4") [node name="MoodItem" type="PanelContainer"] size_flags_horizontal = 3 -theme_override_styles/panel = SubResource("StyleBoxFlat_h1p4u") +theme_override_styles/panel = SubResource("StyleBoxFlat_rsmy0") script = ExtResource("2") [node name="VBox" type="VBoxContainer" parent="."] -offset_left = 4.0 -offset_top = 4.0 -offset_right = 241.0 -offset_bottom = 135.0 +layout_mode = 2 [node name="General" type="HBoxContainer" parent="VBox"] -offset_right = 237.0 -offset_bottom = 31.0 +layout_mode = 2 [node name="Name" type="LineEdit" parent="VBox/General"] unique_name_in_owner = true -offset_right = 125.0 -offset_bottom = 31.0 +layout_mode = 2 size_flags_horizontal = 3 -hint_tooltip = "Mood name" +tooltip_text = "Mood name" caret_blink = true -caret_blink_speed = 0.5 [node name="Play" type="Button" parent="VBox/General"] unique_name_in_owner = true -offset_left = 129.0 -offset_right = 153.0 -offset_bottom = 31.0 -hint_tooltip = "Preview" -icon = SubResource("ImageTexture_o5mle") +layout_mode = 2 +tooltip_text = "Preview" +icon = SubResource("ImageTexture_osvex") [node name="Duplicate" type="Button" parent="VBox/General"] unique_name_in_owner = true -offset_left = 157.0 -offset_right = 181.0 -offset_bottom = 31.0 -hint_tooltip = "Duplicate" -icon = SubResource("ImageTexture_o5mle") +layout_mode = 2 +tooltip_text = "Duplicate" +icon = SubResource("ImageTexture_osvex") [node name="Delete" type="Button" parent="VBox/General"] unique_name_in_owner = true -offset_left = 185.0 -offset_right = 209.0 -offset_bottom = 31.0 -hint_tooltip = "Delete" -icon = SubResource("ImageTexture_o5mle") +layout_mode = 2 +tooltip_text = "Delete" +icon = SubResource("ImageTexture_osvex") [node name="Fold" type="Button" parent="VBox/General"] unique_name_in_owner = true -offset_left = 213.0 -offset_right = 237.0 -offset_bottom = 31.0 -hint_tooltip = "Fold/Unfold" +layout_mode = 2 +tooltip_text = "Fold/Unfold" toggle_mode = true button_pressed = true -icon = SubResource("ImageTexture_o5mle") +icon = SubResource("ImageTexture_osvex") [node name="Content" type="HBoxContainer" parent="VBox"] unique_name_in_owner = true -offset_top = 35.0 -offset_right = 237.0 -offset_bottom = 131.0 +visible = false +layout_mode = 2 [node name="Control" type="Control" parent="VBox/Content"] -offset_bottom = 96.0 +layout_mode = 2 [node name="Content" type="VBoxContainer" parent="VBox/Content"] -offset_left = 4.0 -offset_right = 237.0 -offset_bottom = 96.0 +layout_mode = 2 size_flags_horizontal = 3 [node name="SoundFolderSect" type="HBoxContainer" parent="VBox/Content/Content"] -offset_right = 233.0 -offset_bottom = 26.0 +layout_mode = 2 [node name="Label" type="Label" parent="VBox/Content/Content/SoundFolderSect"] -offset_right = 107.0 -offset_bottom = 26.0 +layout_mode = 2 size_flags_horizontal = 3 text = "Sounds folder" [node name="SoundFolder" type="Label" parent="VBox/Content/Content/SoundFolderSect"] unique_name_in_owner = true -offset_left = 111.0 -offset_top = 1.0 -offset_right = 205.0 -offset_bottom = 24.0 +layout_mode = 2 size_flags_horizontal = 3 horizontal_alignment = 2 [node name="ChangeSoundFolderButton" type="Button" parent="VBox/Content/Content/SoundFolderSect"] unique_name_in_owner = true -offset_left = 209.0 -offset_right = 233.0 -offset_bottom = 26.0 -hint_tooltip = "Change sounds folder" -icon = SubResource("ImageTexture_o5mle") +layout_mode = 2 +tooltip_text = "Change sounds folder" +icon = SubResource("ImageTexture_osvex") [node name="Pitch" type="HBoxContainer" parent="VBox/Content/Content"] -offset_top = 30.0 -offset_right = 233.0 -offset_bottom = 61.0 +layout_mode = 2 [node name="Label2" type="Label" parent="VBox/Content/Content/Pitch"] -offset_top = 2.0 -offset_right = 59.0 -offset_bottom = 28.0 +layout_mode = 2 size_flags_horizontal = 3 text = "Pitch" [node name="PitchBase" type="SpinBox" parent="VBox/Content/Content/Pitch"] unique_name_in_owner = true -offset_left = 63.0 -offset_right = 146.0 -offset_bottom = 31.0 +layout_mode = 2 step = 0.001 value = 1.0 [node name="PitchVariance" type="SpinBox" parent="VBox/Content/Content/Pitch"] unique_name_in_owner = true -offset_left = 150.0 -offset_right = 233.0 -offset_bottom = 31.0 +layout_mode = 2 step = 0.001 prefix = "+/-" [node name="Volume" type="HBoxContainer" parent="VBox/Content/Content"] -offset_top = 65.0 -offset_right = 233.0 -offset_bottom = 96.0 +layout_mode = 2 [node name="Label3" type="Label" parent="VBox/Content/Content/Volume"] -offset_top = 2.0 -offset_right = 59.0 -offset_bottom = 28.0 +layout_mode = 2 size_flags_horizontal = 3 text = "Volume" [node name="VolumeBase" type="SpinBox" parent="VBox/Content/Content/Volume"] unique_name_in_owner = true -offset_left = 63.0 -offset_right = 146.0 -offset_bottom = 31.0 +layout_mode = 2 min_value = -80.0 step = 0.001 suffix = "db" [node name="VolumeVariance" type="SpinBox" parent="VBox/Content/Content/Volume"] unique_name_in_owner = true -offset_left = 150.0 -offset_right = 233.0 -offset_bottom = 31.0 +layout_mode = 2 step = 0.001 prefix = "+/-" diff --git a/addons/dialogic/Events/Text/node_type_sound.gd b/addons/dialogic/Events/Text/node_type_sound.gd index 89b6a57b3..19a629a0b 100644 --- a/addons/dialogic/Events/Text/node_type_sound.gd +++ b/addons/dialogic/Events/Text/node_type_sound.gd @@ -76,7 +76,7 @@ func _on_continued_revealing_text(new_character) -> void: stream = current_overwrite_data.get('sounds', sounds)[RNG.randi_range(0, sounds.size() - 1)] #choose a random pitch and volume - pitch_scale = current_overwrite_data.get('pitch_base', base_pitch) + current_overwrite_data.get('pitch_variance', pitch_variance) * RNG.randf_range(-1.0, 1.0) + pitch_scale = max(0, current_overwrite_data.get('pitch_base', base_pitch) + current_overwrite_data.get('pitch_variance', pitch_variance) * RNG.randf_range(-1.0, 1.0)) volume_db = current_overwrite_data.get('volume_base', base_volume) + current_overwrite_data.get('volume_variance',volume_variance) * RNG.randf_range(-1.0, 1.0) #play the sound diff --git a/addons/dialogic/plugin.gd b/addons/dialogic/plugin.gd index 6d5bccc1a..ae61b378d 100644 --- a/addons/dialogic/plugin.gd +++ b/addons/dialogic/plugin.gd @@ -14,8 +14,8 @@ const MainPanel := preload("res://addons/dialogic/Editor/editor_main.tscn") var editor_view: Control # multiple editor compononents/helper classes -var _parts_inspector : EditorInspectorPlugin -var _export_plugin : EditorExportPlugin +#var _parts_inspector : EditorInspectorPlugin # TODO remove +#var _export_plugin : EditorExportPlugin # TODO remove var editor_interface : EditorInterface # emitted if godot wants us to save @@ -56,8 +56,8 @@ func _exit_tree() -> void: if editor_view: remove_control_from_bottom_panel(editor_view) editor_view.queue_free() - remove_inspector_plugin(_parts_inspector) - remove_export_plugin(_export_plugin) +# remove_inspector_plugin(_parts_inspector) +# remove_export_plugin(_export_plugin) func _has_main_screen() -> bool: From b0737662c2c304894fca04ae2f0d0ada5d9036c1 Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Tue, 27 Dec 2022 10:53:54 +0100 Subject: [PATCH 5/7] Add group and ordering support to portrait list The groups are just a fake representations of portraits named with / in them. So "Emotions/Happy" will be represented as a group Emotions with an item Happy. As this was quite the change from the single level list we had before, many things like searching had to be redone. Search will only look for portrait items (not group items). --- .../CharacterEditor/character_editor.gd | 262 +++++++++++------- .../CharacterEditor/character_editor.tscn | 58 ++-- .../character_editor_portrait_tree.gd | 115 ++++++++ .../character_editor_tab_general.tscn | 5 +- 4 files changed, 307 insertions(+), 133 deletions(-) create mode 100644 addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd b/addons/dialogic/Editor/CharacterEditor/character_editor.gd index 4619b2f44..680cd364d 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd @@ -98,7 +98,7 @@ func _save_resource() -> void: # Saves a new empty character to the given path func new_character(path: String) -> void: - var resource = DialogicCharacter.new() + var resource := DialogicCharacter.new() resource.resource_path = path resource.display_name = path.get_file().trim_suffix("."+path.get_extension()) resource.color = Color(1,1,1,1) @@ -113,27 +113,9 @@ func new_character(path: String) -> void: ############################################################################## func _ready() -> void: - ## Portrait section styling/connections - %AddPortraitButton.icon = get_theme_icon("Add", "EditorIcons") - %AddPortraitButton.pressed.connect(add_portrait) - %ImportPortraitsButton.icon = get_theme_icon("Folder", "EditorIcons") - %ImportPortraitsButton.pressed.connect(open_portrait_folder_select) - %PortraitSearch.right_icon = get_theme_icon("Search", "EditorIcons") - %PortraitSearch.text_changed.connect(filter_portrait_list) + setup_portrait_list_tab() - %PortraitTree.item_selected.connect(load_selected_portrait) - %PortraitTree.item_edited.connect(_on_item_edited) - - %DefaultPortraitPicker.value_changed.connect(default_portrait_changed) - %MainScale.value_changed.connect(main_portrait_settings_update) - %MainOffsetX.value_changed.connect(main_portrait_settings_update) - %MainOffsetY.value_changed.connect(main_portrait_settings_update) - %MainMirror.toggled.connect(main_portrait_settings_update) - - # Setting up Default Portrait Picker - %DefaultPortraitPicker.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/portrait.svg") - %DefaultPortraitPicker.get_suggestions_func = suggest_portraits - %DefaultPortraitPicker.set_left_text("") + setup_portrait_settings_tab() %PreviewMode.item_selected.connect(_on_PreviewMode_item_selected) %PreviewMode.select(DialogicUtil.get_project_setting('dialogic/editor/character_preview_mode', 0)) @@ -198,6 +180,22 @@ func something_changed(fake_argument = "", fake_arg2 = null) -> void: ## PORTRAIT SECTION ############################################################################## +func setup_portrait_list_tab() -> void: + %PortraitTree.editor = self + + ## Portrait section styling/connections + %AddPortraitButton.icon = get_theme_icon("Add", "EditorIcons") + %AddPortraitButton.pressed.connect(add_portrait) + %AddPortraitGroupButton.icon = get_theme_icon("Groups", "EditorIcons") + %AddPortraitGroupButton.pressed.connect(add_portrait_group) + %ImportPortraitsButton.icon = get_theme_icon("Folder", "EditorIcons") + %ImportPortraitsButton.pressed.connect(open_portrait_folder_select) + %PortraitSearch.right_icon = get_theme_icon("Search", "EditorIcons") + %PortraitSearch.text_changed.connect(filter_portrait_list) + + %PortraitTree.item_selected.connect(load_selected_portrait) + %PortraitTree.item_edited.connect(_on_item_edited) + func open_portrait_folder_select() -> void: find_parent("EditorView").godot_file_dialog( import_portraits_from_folder, "*", @@ -205,6 +203,10 @@ func open_portrait_folder_select() -> void: func import_portraits_from_folder(path:String) -> void: + var parent: TreeItem = %PortraitTree.get_root() + if %PortraitTree.get_selected() and %PortraitTree.get_selected().get_metadata(0).has('group'): + parent = %PortraitTree.get_selected() + var dir := DirAccess.open(path) dir.list_dir_begin() var file_name :String = dir.get_next() @@ -214,23 +216,44 @@ func import_portraits_from_folder(path:String) -> void: if '.svg' in file_lower or '.png' in file_lower: if not '.import' in file_lower: var final_name: String= path+ "/" + file_name - add_portrait(file_name.trim_suffix('.'+file_name.get_extension()), - {'scene':"",'image':final_name, 'scale':1, 'offset':Vector2(), 'mirror':false}) + %PortraitTree.add_portrait_item(file_name.trim_suffix('.'+file_name.get_extension()), + {'scene':"",'image':final_name, 'scale':1, 'offset':Vector2(), 'mirror':false}, parent) file_name = dir.get_next() + something_changed() func add_portrait(portrait_name:String='New portrait', portrait_data:Dictionary={'scene':"", 'image':'', 'scale':1, 'offset':Vector2(), 'mirror':false}) -> void: - var root: TreeItem = %PortraitTree.get_root() - add_portrait_item(portrait_name, portrait_data, root).select(0) + var parent: TreeItem = %PortraitTree.get_root() + if %PortraitTree.get_selected(): + if %PortraitTree.get_selected().get_metadata(0).has('group'): + parent = %PortraitTree.get_selected() + else: + parent = %PortraitTree.get_selected().get_parent() + %PortraitTree.add_portrait_item(portrait_name, portrait_data, parent).select(0) something_changed() +func add_portrait_group() -> void: + var parent_item :TreeItem = %PortraitTree.get_root() + if %PortraitTree.get_selected() and %PortraitTree.get_selected().get_metadata(0).has('group'): + parent_item = %PortraitTree.get_selected() + %PortraitTree.add_portrait_group("Group", parent_item) + + func load_portrait_tree() -> void: - %PortraitTree.clear() + %PortraitTree.clear_tree() var root:TreeItem = %PortraitTree.create_item() for portrait in current_resource.portraits.keys(): - add_portrait_item(portrait, current_resource.portraits[portrait], root) + var portrait_label = portrait + var parent = %PortraitTree.get_root() + if '/' in portrait: + parent = %PortraitTree.create_necessary_group_items(portrait) + portrait_label = portrait.split('/')[-1] + + %PortraitTree.add_portrait_item(portrait_label, current_resource.portraits[portrait], parent) + + update_default_portrait_star(current_resource.default_portrait) if root.get_child_count(): root.get_first_child().select(0) @@ -239,35 +262,36 @@ func load_portrait_tree() -> void: load_selected_portrait() - func filter_portrait_list(filter_term:String = '') -> void: - var item : TreeItem = %PortraitTree.get_root().get_first_child() - while true: - item.visible = filter_term.is_empty() or filter_term.to_lower() in item.get_text(0).to_lower() - item = item.get_next() - if !item: - break + filter_branch(%PortraitTree.get_root(), filter_term) + + +func filter_branch(parent:TreeItem, filter_term:String) -> bool: + var anything_visible := false + for item in parent.get_children(): + if item.get_metadata(0).has('group'): + item.visible = filter_branch(item, filter_term) + anything_visible = item.visible + elif filter_term.is_empty() or filter_term.to_lower() in item.get_text(0).to_lower(): + item.visible = true + anything_visible = true + else: + item.visible = false + return anything_visible # this is used to save the portrait data func get_updated_portrait_dict() -> Dictionary: - var dict : Dictionary = {} - var item : TreeItem = %PortraitTree.get_root().get_first_child() - while item: - dict[item.get_text(0)] = item.get_metadata(0) - item = item.get_next() - return dict + return list_portraits(%PortraitTree.get_root().get_children()) -func add_portrait_item(portrait_name:String, portrait_data:Dictionary, parent_item:TreeItem) -> TreeItem: - var item :TreeItem = %PortraitTree.create_item(parent_item) - item.set_text(0, portrait_name) - item.set_metadata(0, portrait_data) - if portrait_name == current_resource.default_portrait: - item.add_button(0, get_theme_icon('Favorites', 'EditorIcons'), 2, true, 'Default') - item.add_button(0, get_theme_icon('Duplicate', 'EditorIcons'), 3, false, 'Duplicate') - item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove') - return item +func list_portraits(tree_items:Array[TreeItem], dict:Dictionary = {}, path_prefix = "") -> Dictionary: + for item in tree_items: + if item.get_metadata(0).has('group'): + dict = list_portraits(item.get_children(), dict, path_prefix+item.get_text(0)+"/") + else: + dict[path_prefix +item.get_text(0)] = item.get_metadata(0) + return dict func load_selected_portrait(): @@ -276,10 +300,11 @@ func load_selected_portrait(): selected_item = %PortraitTree.get_selected() - if selected_item: + + if selected_item and !selected_item.get_metadata(0).has('group'): %PortraitSettingsSection.show() var current_portrait_data :Dictionary = selected_item.get_metadata(0) - portrait_selected.emit(selected_item.get_text(0), current_portrait_data) + portrait_selected.emit(%PortraitTree.get_full_item_name(selected_item), current_portrait_data) update_preview() @@ -299,11 +324,13 @@ func load_selected_portrait(): %PortraitSettingsSection.current_tab += 1 else: break - - await get_tree().create_timer(0.01).timeout - selected_item.set_editable(0, true) else: %PortraitSettingsSection.hide() + update_preview() + + if selected_item: + await get_tree().create_timer(0.01).timeout + selected_item.set_editable(0, true) func delete_portrait_item(item:TreeItem) -> void: @@ -312,7 +339,7 @@ func delete_portrait_item(item:TreeItem) -> void: func duplicate_item(item:TreeItem) -> void: - add_portrait_item(item.get_text(0)+'_duplicated', item.get_metadata(0), item.get_parent()).select(0) + %PortraitTree.add_portrait_item(item.get_text(0)+'_duplicated', item.get_metadata(0), item.get_parent()).select(0) func _on_portrait_tree_button_clicked(item:TreeItem, column:int, id:int, mouse_button_index:int): @@ -324,10 +351,82 @@ func _on_portrait_tree_button_clicked(item:TreeItem, column:int, id:int, mouse_b duplicate_item(item) +# this removes/and adds the DEFAULT star on the portrait list +func update_default_portrait_star(default_portrait_name:String) -> void: + var item_list : Array = %PortraitTree.get_root().get_children() + while true: + var item = item_list.pop_back() + if item.get_button_by_id(0, 2) != -1: + item.erase_button(0, item.get_button_by_id(0, 2)) + if %PortraitTree.get_full_item_name(item) == default_portrait_name: + item.erase_button(0, item.get_button_by_id(0, 1)) + item.erase_button(0, item.get_button_by_id(0, 3)) + item.add_button(0, get_theme_icon('Favorites', 'EditorIcons'), 2, true, 'Default') + item.add_button(0, get_theme_icon('Duplicate', 'EditorIcons'), 3, false, 'Duplicate') + item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove') + item_list.append_array(item.get_children()) + + if item_list.is_empty(): + break + + +func _on_item_edited(): + selected_item = %PortraitTree.get_selected() + something_changed() + if selected_item: + if %PreviewLabel.text.trim_prefix('Preview of "').trim_suffix('"') == current_resource.default_portrait: + current_resource.default_portrait = %PortraitTree.get_full_item_name(selected_item) + update_preview() + + + +############################################################################## +## PORTRAIT SETTINGS TAB +############################################################################## + +func setup_portrait_settings_tab() -> void: + %DefaultPortraitPicker.value_changed.connect(default_portrait_changed) + %MainScale.value_changed.connect(main_portrait_settings_update) + %MainOffsetX.value_changed.connect(main_portrait_settings_update) + %MainOffsetY.value_changed.connect(main_portrait_settings_update) + %MainMirror.toggled.connect(main_portrait_settings_update) + + # Setting up Default Portrait Picker + %DefaultPortraitPicker.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/portrait.svg") + %DefaultPortraitPicker.get_suggestions_func = suggest_portraits + %DefaultPortraitPicker.set_left_text("") + + +# Make sure preview get's updated when portrait settings change +func main_portrait_settings_update(value = null) -> void: + current_resource.scale = %MainScale.value/100.0 + current_resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.value) + current_resource.mirror = %MainMirror.button_pressed + update_preview() + something_changed() + + +func default_portrait_changed(property:String, value:String) -> void: + current_resource.default_portrait = value + update_default_portrait_star(value) + + +# Get suggestions for DefaultPortraitPicker +func suggest_portraits(search:String) -> Dictionary: + var suggestions := {} + for portrait in get_updated_portrait_dict().keys(): + suggestions[portrait] = {'value':portrait} + return suggestions + + +############################################################################## +## PREVIEW +############################################################################## + func update_preview() -> void: %ScenePreviewWarning.hide() - if selected_item and is_instance_valid(selected_item): - %PreviewLabel.text = 'Preview of "'+selected_item.get_text(0)+'"' + if selected_item and is_instance_valid(selected_item) and !selected_item.get_metadata(0).has('group'): + %PreviewLabel.text = 'Preview of "'+%PortraitTree.get_full_item_name(selected_item)+'"' var current_portrait_data: Dictionary = selected_item.get_metadata(0) var mirror:bool = current_portrait_data.get('mirror', false) != current_resource.mirror var scale:float = current_portrait_data.get('scale', 1) * current_resource.scale @@ -359,7 +458,7 @@ func update_preview() -> void: if is_instance_valid(scene.get_script()) and scene.script.is_tool(): if scene.has_method('_update_portrait'): - scene._update_portrait(current_resource, selected_item.get_text(0)) + scene._update_portrait(current_resource, %PortraitTree.get_full_item_name(selected_item)) if scene.has_method('_set_mirror'): scene._set_mirror(mirror) if current_preview_mode == PreviewModes.Real: @@ -387,32 +486,6 @@ func update_preview() -> void: for node in %RealPreviewPivot.get_children(): node.queue_free() current_previewed_scene = null - - -# this removes/and adds the DEFAULT star on the portrait list -func update_default_portrait_star(default_portrait_name:String) -> void: - var item : TreeItem = %PortraitTree.get_root().get_first_child() - while true: - if item.get_button_by_id(0, 2) != -1: - item.erase_button(0, item.get_button_by_id(0, 2)) - if item.get_text(0) == default_portrait_name: - item.erase_button(0, item.get_button_by_id(0, 1)) - item.erase_button(0, item.get_button_by_id(0, 3)) - item.add_button(0, get_theme_icon('Favorites', 'EditorIcons'), 2, true, 'Default') - item.add_button(0, get_theme_icon('Duplicate', 'EditorIcons'), 3, false, 'Duplicate') - item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove') - item = item.get_next() - if !item: - break - - -func _on_item_edited(): - selected_item = %PortraitTree.get_selected() - something_changed() - if selected_item: - if %PreviewLabel.text.trim_prefix('Preview of "').trim_suffix('"') == current_resource.default_portrait: - current_resource.default_portrait = selected_item.get_text(0) - update_preview() func _on_PreviewMode_item_selected(index:int) -> void: @@ -432,24 +505,3 @@ func _on_full_preview_available_rect_resized(): if current_preview_mode == PreviewModes.Full: update_preview() - -# Make sure preview get's updated when portrait settings change -func main_portrait_settings_update(value = null) -> void: - current_resource.scale = %MainScale.value/100.0 - current_resource.offset = Vector2(%MainOffsetX.value, %MainOffsetY.value) - current_resource.mirror = %MainMirror.button_pressed - update_preview() - something_changed() - -func default_portrait_changed(property:String, value:String) -> void: - current_resource.default_portrait = value - update_default_portrait_star(value) - - -# Get suggestions for DefaultPortraitPicker -func suggest_portraits(search:String) -> Dictionary: - var suggestions := {} - for portrait in get_updated_portrait_dict().keys(): - suggestions[portrait] = {'value':portrait} - return suggestions - diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn index a3b6c1899..489e5bf36 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn @@ -1,14 +1,15 @@ -[gd_scene load_steps=14 format=3 uid="uid://dxt0c6mx24nxo"] +[gd_scene load_steps=15 format=3 uid="uid://dlskc36c5hrwv"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/ComplexPicker.tscn" id="2_01va3"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_image.gd" id="2_cusvj"] +[ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd" id="2_vad0i"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_scene.gd" id="4_6tltp"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/FilePicker.tscn" id="4_a4bcu"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_layout.gd" id="5_eicvp"] [ext_resource type="Script" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_ptab_exports.gd" id="7_4enie"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hdqef"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kxihh"] content_margin_left = 10.0 content_margin_top = 4.0 content_margin_right = 10.0 @@ -18,7 +19,7 @@ border_width_top = 2 border_color = Color(1, 1, 1, 0.75) corner_detail = 1 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jc1xk"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1pdx5"] content_margin_left = 7.5 content_margin_top = 7.5 content_margin_right = 7.5 @@ -29,7 +30,7 @@ corner_radius_top_right = 3 corner_radius_bottom_right = 3 corner_radius_bottom_left = 3 -[sub_resource type="Image" id="Image_dqs53"] +[sub_resource type="Image" id="Image_8q5e2"] data = { "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -38,12 +39,12 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_ckfua"] -image = SubResource("Image_dqs53") +[sub_resource type="ImageTexture" id="ImageTexture_uf4x7"] +image = SubResource("Image_8q5e2") [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_4xgdx"] -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_sf73i"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_81xk6"] content_margin_left = 4.0 content_margin_top = 4.0 content_margin_right = 4.0 @@ -91,15 +92,15 @@ layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_hdqef") -theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_kxihh") +theme_override_styles/panel = SubResource("StyleBoxFlat_1pdx5") [node name="PortraitListSection" type="TabContainer" parent="Split/Editor"] unique_name_in_owner = true layout_mode = 2 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_hdqef") -theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_kxihh") +theme_override_styles/panel = SubResource("StyleBoxFlat_1pdx5") [node name="Portraits" type="VBoxContainer" parent="Split/Editor/PortraitListSection"] layout_mode = 2 @@ -110,12 +111,20 @@ layout_mode = 2 [node name="AddPortraitButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -icon = SubResource("ImageTexture_ckfua") +tooltip_text = "Add portrait" +icon = SubResource("ImageTexture_uf4x7") + +[node name="AddPortraitGroupButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Add Group" +icon = SubResource("ImageTexture_uf4x7") [node name="ImportPortraitsButton" type="Button" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true layout_mode = 2 -icon = SubResource("ImageTexture_ckfua") +tooltip_text = "Import images from folder" +icon = SubResource("ImageTexture_uf4x7") [node name="PortraitSearch" type="LineEdit" parent="Split/Editor/PortraitListSection/Portraits/PortraitListTools"] unique_name_in_owner = true @@ -125,7 +134,7 @@ size_flags_vertical = 4 placeholder_text = "Search" expand_to_text_length = true clear_button_enabled = true -right_icon = SubResource("ImageTexture_ckfua") +right_icon = SubResource("ImageTexture_uf4x7") caret_blink = true caret_blink_interval = 0.5 @@ -138,8 +147,9 @@ theme_override_styles/panel = SubResource("StyleBoxEmpty_4xgdx") unique_name_in_owner = true layout_mode = 2 allow_rmb_select = true -hide_folding = true hide_root = true +drop_mode_flags = 1 +script = ExtResource("2_vad0i") [node name="P Settings" type="VBoxContainer" parent="Split/Editor/PortraitListSection"] visible = false @@ -221,15 +231,15 @@ clip_contents = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") +theme_override_styles/panel = SubResource("StyleBoxFlat_1pdx5") [node name="Node2D" type="Node2D" parent="Split/RightSection/PortraitPreviewSection"] position = Vector2(13, 17) [node name="RealPreviewPivot" type="Sprite2D" parent="Split/RightSection/PortraitPreviewSection/Node2D"] unique_name_in_owner = true -position = Vector2(289, 362) -texture = SubResource("ImageTexture_ckfua") +position = Vector2(330, 405) +texture = SubResource("ImageTexture_uf4x7") [node name="ScenePreviewWarning" type="Label" parent="Split/RightSection/PortraitPreviewSection"] unique_name_in_owner = true @@ -329,11 +339,10 @@ layout_mode = 2 size_flags_vertical = 3 size_flags_stretch_ratio = 0.3 theme_override_constants/side_margin = 5 -theme_override_styles/tab_selected = SubResource("StyleBoxFlat_hdqef") -theme_override_styles/panel = SubResource("StyleBoxFlat_jc1xk") +theme_override_styles/tab_selected = SubResource("StyleBoxFlat_kxihh") +theme_override_styles/panel = SubResource("StyleBoxFlat_1pdx5") [node name="Image" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] -visible = false custom_minimum_size = Vector2(0, 35) layout_mode = 2 horizontal_scroll_mode = 0 @@ -359,7 +368,7 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 file_filter = "*.png, *.svg" -resource_icon = SubResource("ImageTexture_ckfua") +resource_icon = SubResource("ImageTexture_uf4x7") [node name="Scene" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] visible = false @@ -390,7 +399,7 @@ layout_mode = 2 size_flags_horizontal = 3 file_filter = "*.tscn" placeholder = "Default scene" -resource_icon = SubResource("ImageTexture_ckfua") +resource_icon = SubResource("ImageTexture_uf4x7") [node name="Label2" type="Label" parent="Split/RightSection/PortraitSettingsSection/Scene/Flow/GridContainer"] layout_mode = 2 @@ -459,9 +468,10 @@ unique_name_in_owner = true layout_mode = 2 [node name="Exports" type="ScrollContainer" parent="Split/RightSection/PortraitSettingsSection"] +visible = false custom_minimum_size = Vector2(0, 35) layout_mode = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_sf73i") +theme_override_styles/panel = SubResource("StyleBoxFlat_81xk6") horizontal_scroll_mode = 0 script = ExtResource("7_4enie") diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd new file mode 100644 index 000000000..37cc5ec7e --- /dev/null +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd @@ -0,0 +1,115 @@ +@tool +extends Tree + +## Tree that displays the portrait list as a hirarchy + +var editor := find_parent('Character Editor') +var current_group_nodes := {} + + +func clear_tree() -> void: + clear() + current_group_nodes = {} + + +func add_portrait_item(portrait_name:String, portrait_data:Dictionary, parent_item:TreeItem) -> TreeItem: + var item :TreeItem = %PortraitTree.create_item(parent_item) + item.set_text(0, portrait_name) + item.set_metadata(0, portrait_data) + if portrait_name == editor.current_resource.default_portrait: + item.add_button(0, get_theme_icon('Favorites', 'EditorIcons'), 2, true, 'Default') + item.add_button(0, get_theme_icon('Duplicate', 'EditorIcons'), 3, false, 'Duplicate') + item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove') + return item + + +func add_portrait_group(goup_name:String = "Group", parent_item:TreeItem = get_root()): + var item :TreeItem = %PortraitTree.create_item(parent_item) + item.set_icon(0, get_theme_icon("Groups", "EditorIcons")) + item.set_text(0, goup_name) + item.set_metadata(0, {'group':true}) + item.add_button(0, get_theme_icon('Remove', 'EditorIcons'), 1, false, 'Remove') + return item + + +func get_full_item_name(item:TreeItem) -> String: + var item_name := item.get_text(0) + while item.get_parent() != get_root() and item != get_root(): + item_name = item.get_parent().get_text(0)+"/"+item_name + item = item.get_parent() + return item_name + + +# Will create all not yet existing folders in the given path. +# Returns the last folder (the parent of the portrait item of this path). +func create_necessary_group_items(path:String) -> void: + var last_item := get_root() + var item_path := "" + + for i in Array(path.split('/')).slice(0, -1): + item_path += "/"+i + item_path = item_path.trim_prefix('/') + if current_group_nodes.has(item_path+"/"+i): + last_item = current_group_nodes[item_path+"/"+i] + else: + var new_item := add_portrait_group(i, last_item) + current_group_nodes[item_path+"/"+i] = new_item + last_item = new_item + return last_item + + +################################################################################ +## DRAG AND DROP +################################################################################ + +func _get_drag_data(position:Vector2) -> Variant: + set_drop_mode_flags(DROP_MODE_ON_ITEM) + + var preview := Label.new() + preview.text = " "+get_selected().get_text(0) + preview.add_theme_stylebox_override('normal', get_theme_stylebox("Background", "EditorStyles")) + set_drag_preview(preview) + + return get_selected() + + +func _can_drop_data(position:Vector2, data:Variant) -> bool: + return data is TreeItem + + +func _drop_data(position:Vector2, item:Variant) -> void: + var to_item := get_item_at_position(position) + if to_item: + var test_item:= to_item + while true: + if test_item == item: + return + test_item = test_item.get_parent() + if test_item == get_root(): + break + + var parent := get_root() + if to_item: + parent = to_item.get_parent() + + if to_item and to_item.get_metadata(0).has('group'): + parent = to_item + + var new_item := copy_branch_or_item(item, parent) + + if to_item and !to_item.get_metadata(0).has('group'): + new_item.move_after(to_item) + + item.free() + + +func copy_branch_or_item(item:TreeItem, new_parent:TreeItem) -> TreeItem: + var new_item :TreeItem = null + if item.get_metadata(0).has('group'): + new_item = add_portrait_group(item.get_text(0), new_parent) + else: + new_item = add_portrait_item(item.get_text(0), item.get_metadata(0), new_parent) + + for child in item.get_children(): + copy_branch_or_item(child, new_item) + return new_item diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn b/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn index 6395c73e8..326e06187 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_tab_general.tscn @@ -19,7 +19,6 @@ script = ExtResource("1_3e1i1") [node name="Label2" type="Label" parent="."] layout_mode = 2 -tooltip_text = "This name will be displayed on the name label. You can use a dialogic variable: {Player.name}" text = "Display Name: " [node name="DisplayName" type="HBoxContainer" parent="."] @@ -29,7 +28,7 @@ size_flags_horizontal = 3 [node name="DisplayNameLineEdit" type="LineEdit" parent="DisplayName"] unique_name_in_owner = true layout_mode = 2 -tooltip_text = "This name will be displayed on the name label. You can use a dialogic variable: {Player.name}" +tooltip_text = "This name will be displayed on the name label. You can use a dialogic variable. E.g. :{Player.name}" expand_to_text_length = true caret_blink = true caret_blink_interval = 0.5 @@ -44,7 +43,6 @@ edit_alpha = false [node name="Label3" type="Label" parent="."] layout_mode = 2 -tooltip_text = "If autocolor names is enabled, these will be colored in the characters color as well." text = "Nicknames:" [node name="NicknameLineEdit" type="LineEdit" parent="."] @@ -58,7 +56,6 @@ caret_blink_interval = 0.5 [node name="Label4" type="Label" parent="."] layout_mode = 2 size_flags_vertical = 0 -tooltip_text = "No effect, just for you." text = "Description:" [node name="DescriptionTextEdit" type="TextEdit" parent="."] From 37ee8fd01522fd3f62e361c513982413674cf3c0 Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Tue, 27 Dec 2022 10:54:46 +0100 Subject: [PATCH 6/7] Make sure non existing portrait doesn't cause problem in default scene --- addons/dialogic/Events/Character/default_portrait.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/dialogic/Events/Character/default_portrait.gd b/addons/dialogic/Events/Character/default_portrait.gd index a8dee89cc..bd18289fb 100644 --- a/addons/dialogic/Events/Character/default_portrait.gd +++ b/addons/dialogic/Events/Character/default_portrait.gd @@ -22,7 +22,7 @@ func _should_do_portrait_update(character:DialogicCharacter, portrait:String) -> ## If the custom portrait accepts a change, then accept it here func _update_portrait(passed_character:DialogicCharacter, passed_portrait:String) -> void: - if passed_portrait == "": + if passed_portrait == "" or not passed_portrait in passed_character.portraits.keys(): passed_portrait = passed_character['default_portrait'] portrait = passed_portrait if passed_character != null: From 4b46c2ea54f73e2f9d0ea72cadf59502b3edadf7 Mon Sep 17 00:00:00 2001 From: Jowan Spooner Date: Tue, 27 Dec 2022 17:00:20 +0100 Subject: [PATCH 7/7] Small fix --- addons/dialogic/Editor/CharacterEditor/character_editor.gd | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd b/addons/dialogic/Editor/CharacterEditor/character_editor.gd index 680cd364d..48183dbf6 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd @@ -432,7 +432,11 @@ func update_preview() -> void: var scale:float = current_portrait_data.get('scale', 1) * current_resource.scale var offset:Vector2 =current_portrait_data.get('offset', Vector2()) + current_resource.offset - if current_previewed_scene != null and current_previewed_scene.get_meta('path', null) == current_portrait_data.get('scene') and current_previewed_scene.has_method('_should_do_portrait_update') and current_previewed_scene._should_do_portrait_update(current_resource, selected_item.get_text(0)): + if current_previewed_scene != null \ + and current_previewed_scene.get_meta('path', null) == current_portrait_data.get('scene') \ + and current_previewed_scene.has_method('_should_do_portrait_update') \ + and is_instance_valid(current_previewed_scene.get_script()) \ + and current_previewed_scene._should_do_portrait_update(current_resource, selected_item.get_text(0)): pass # we keep the same scene else: for node in %RealPreviewPivot.get_children():