From cbb82512ee46d8b9805bf7a9bc8907a26728fc42 Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Mon, 5 Jan 2026 16:00:41 +0100 Subject: [PATCH] Updated dialogic --- addons/dialogic/Core/DialogicGameHandler.gd | 123 ++++-- .../dialogic/Core/DialogicGameHandler.gd.uid | 2 +- addons/dialogic/Core/DialogicResourceUtil.gd | 97 ++++- .../dialogic/Core/DialogicResourceUtil.gd.uid | 2 +- addons/dialogic/Core/DialogicUtil.gd | 227 +++++++--- addons/dialogic/Core/DialogicUtil.gd.uid | 2 +- .../dialogic/Core/Dialogic_Subsystem.gd.uid | 2 +- addons/dialogic/Core/index_class.gd | 2 +- addons/dialogic/Core/index_class.gd.uid | 2 +- .../char_edit_p_section_exports.gd.uid | 2 +- .../char_edit_p_section_exports.tscn | 2 +- .../char_edit_p_section_layout.gd | 6 +- .../char_edit_p_section_layout.gd.uid | 2 +- .../char_edit_p_section_layout.tscn | 15 +- .../char_edit_p_section_main.gd.uid | 2 +- .../char_edit_p_section_main.tscn | 2 +- .../char_edit_p_section_main_exports.gd.uid | 2 +- .../char_edit_p_section_main_exports.tscn | 2 +- .../char_edit_section_general.gd.uid | 2 +- .../char_edit_section_general.tscn | 2 +- .../char_edit_section_portraits.gd | 9 +- .../char_edit_section_portraits.gd.uid | 2 +- .../char_edit_section_portraits.tscn | 18 +- .../CharacterEditor/character_editor.gd | 14 +- .../CharacterEditor/character_editor.gd.uid | 2 +- .../CharacterEditor/character_editor.tscn | 4 +- .../character_editor_main_settings_section.gd | 3 +- ...racter_editor_main_settings_section.gd.uid | 2 +- ...er_editor_portrait_settings_section.gd.uid | 2 +- .../character_editor_portrait_tree.gd.uid | 2 +- .../character_prefix_suffix.gd | 79 ++++ .../character_prefix_suffix.gd.uid | 1 + .../character_prefix_suffix.tscn | 48 +++ .../portrait_scene_browser.gd.uid | 2 +- .../portrait_scene_browser.tscn | 2 +- .../dialogic/Editor/Common/BrowserItem.gd.uid | 2 +- .../dialogic/Editor/Common/BrowserItem.tscn | 2 +- addons/dialogic/Editor/Common/DCSS.gd.uid | 2 +- .../ReferenceManager_AddReplacementPanel.gd | 5 +- ...eferenceManager_AddReplacementPanel.gd.uid | 2 +- .../Editor/Common/broken_reference_manager.gd | 36 +- .../Common/broken_reference_manager.gd.uid | 2 +- .../Editor/Common/hint_tooltip_icon.gd.uid | 2 +- .../Editor/Common/hint_tooltip_icon.tscn | 6 +- .../Editor/Common/reference_manager.gd.uid | 2 +- .../Editor/Common/reference_manager.tscn | 67 +-- .../Editor/Common/reference_manager_window.gd | 9 +- .../Common/reference_manager_window.gd.uid | 2 +- addons/dialogic/Editor/Common/side_bar.tscn | 2 +- addons/dialogic/Editor/Common/sidebar.gd | 6 +- addons/dialogic/Editor/Common/sidebar.gd.uid | 2 +- addons/dialogic/Editor/Common/toolbar.gd | 5 +- addons/dialogic/Editor/Common/toolbar.gd.uid | 2 +- .../Common/unique_identifiers_manager.gd.uid | 2 +- .../Editor/Common/update_install_window.gd | 3 +- .../Common/update_install_window.gd.uid | 2 +- .../Editor/Common/update_install_window.tscn | 2 +- .../Editor/Common/update_manager.gd.uid | 2 +- .../dialogic/Editor/Events/BranchEnd.gd.uid | 2 +- addons/dialogic/Editor/Events/BranchEnd.tscn | 2 +- .../Editor/Events/EventBlock/event_block.gd | 14 +- .../Events/EventBlock/event_block.gd.uid | 2 +- .../Editor/Events/EventBlock/event_block.tscn | 2 +- .../EventBlock/event_right_click_menu.gd | 14 +- .../EventBlock/event_right_click_menu.gd.uid | 2 +- .../Editor/Events/Fields/array_part.gd.uid | 2 +- .../Editor/Events/Fields/array_part.tscn | 2 +- .../Editor/Events/Fields/dictionary_part.gd | 1 - .../Events/Fields/dictionary_part.gd.uid | 2 +- .../Editor/Events/Fields/dictionary_part.tscn | 2 +- .../Editor/Events/Fields/field_array.gd.uid | 2 +- .../Editor/Events/Fields/field_array.tscn | 2 +- .../Events/Fields/field_audio_preview.gd.uid | 2 +- .../Events/Fields/field_audio_preview.tscn | 2 +- .../Events/Fields/field_bool_button.gd.uid | 2 +- .../Events/Fields/field_bool_button.tscn | 2 +- .../Events/Fields/field_bool_check.gd.uid | 2 +- .../Events/Fields/field_bool_check.tscn | 2 +- .../Editor/Events/Fields/field_color.gd.uid | 2 +- .../Editor/Events/Fields/field_color.tscn | 2 +- .../Editor/Events/Fields/field_condition.gd | 3 +- .../Events/Fields/field_condition.gd.uid | 2 +- .../Editor/Events/Fields/field_condition.tscn | 2 +- .../Events/Fields/field_dictionary.gd.uid | 2 +- .../Events/Fields/field_dictionary.tscn | 2 +- .../Editor/Events/Fields/field_file.gd | 13 + .../Editor/Events/Fields/field_file.gd.uid | 2 +- .../Editor/Events/Fields/field_file.tscn | 31 +- .../Events/Fields/field_flex_value.gd.uid | 2 +- .../Events/Fields/field_flex_value.tscn | 2 +- .../Events/Fields/field_image_preview.gd | 64 +++ .../Events/Fields/field_image_preview.gd.uid | 1 + .../Events/Fields/field_image_preview.tscn | 23 + .../Editor/Events/Fields/field_number.gd | 57 +-- .../Editor/Events/Fields/field_number.gd.uid | 2 +- .../Editor/Events/Fields/field_number.tscn | 24 +- .../Events/Fields/field_options_dynamic.gd | 110 ++++- .../Fields/field_options_dynamic.gd.uid | 2 +- .../Events/Fields/field_options_dynamic.tscn | 13 +- .../Events/Fields/field_options_fixed.gd | 9 +- .../Events/Fields/field_options_fixed.gd.uid | 2 +- .../Events/Fields/field_options_fixed.tscn | 2 +- .../Events/Fields/field_text_multiline.gd | 2 +- .../Events/Fields/field_text_multiline.gd.uid | 2 +- .../Events/Fields/field_text_multiline.tscn | 4 +- .../Fields/field_text_singleline.gd.uid | 2 +- .../Events/Fields/field_text_singleline.tscn | 2 +- .../Editor/Events/Fields/field_vector2.gd | 5 + .../Editor/Events/Fields/field_vector2.gd.uid | 2 +- .../Editor/Events/Fields/field_vector2.tscn | 12 +- .../Editor/Events/Fields/field_vector3.gd | 6 + .../Editor/Events/Fields/field_vector3.gd.uid | 2 +- .../Editor/Events/Fields/field_vector3.tscn | 7 +- .../Editor/Events/Fields/field_vector4.gd | 7 + .../Editor/Events/Fields/field_vector4.gd.uid | 2 +- .../Editor/Events/Fields/field_vector4.tscn | 15 +- .../Editor/Events/Fields/field_vector_base.gd | 9 + .../Events/Fields/field_vector_base.gd.uid | 2 +- addons/dialogic/Editor/Events/event_field.gd | 5 +- .../dialogic/Editor/Events/event_field.gd.uid | 2 +- .../dialogic/Editor/HomePage/home_page.gd.uid | 2 +- .../dialogic/Editor/HomePage/home_page.tscn | 2 +- .../Editor/Images/Resources/timeline.svg | 115 +++++ .../Images/Resources/timeline.svg.import | 43 ++ .../Editor/Images/Toolbar/add-timeline.svg | 66 ++- .../Images/Toolbar/add-timeline.svg.import | 6 + .../Editor/Inspector/inspector_plugin.gd.uid | 2 +- .../Inspector/timeline_inspector_field.gd | 6 +- .../Inspector/timeline_inspector_field.gd.uid | 2 +- .../{ => CoreSettingsPages}/csv_file.gd | 0 .../CoreSettingsPages/csv_file.gd.uid | 1 + .../CoreSettingsPages/settings_editor.gd | 154 +++++++ .../CoreSettingsPages/settings_editor.gd.uid | 1 + .../CoreSettingsPages/settings_editor.tscn | 161 +++++++ .../settings_general.gd | 76 +--- .../CoreSettingsPages/settings_general.gd.uid | 1 + .../settings_general.tscn | 127 ++---- .../settings_modules.gd | 1 - .../CoreSettingsPages/settings_modules.gd.uid | 1 + .../settings_modules.tscn | 10 +- .../CoreSettingsPages/settings_tools.gd | 80 ++++ .../CoreSettingsPages/settings_tools.gd.uid | 1 + .../settings_translation.gd | 5 +- .../settings_translation.gd.uid | 1 + .../settings_translation.tscn | 6 +- .../Settings/CoreSettingsPages/tool_resave.gd | 32 ++ .../CoreSettingsPages/tool_resave.gd.uid | 1 + .../Settings/HintLabelStylingScript.gd.uid | 2 +- .../dialogic/Editor/Settings/csv_file.gd.uid | 1 - .../Editor/Settings/settings_editor.gd | 8 +- .../Editor/Settings/settings_editor.gd.uid | 2 +- .../Editor/Settings/settings_editor.tscn | 2 +- .../Editor/Settings/settings_general.gd.uid | 1 - .../Editor/Settings/settings_modules.gd.uid | 1 - .../dialogic/Editor/Settings/settings_page.gd | 1 + .../Editor/Settings/settings_page.gd.uid | 2 +- .../Settings/settings_translation.gd.uid | 1 - .../TextEditor/CodeCompletionHelper.gd | 67 +-- .../TextEditor/CodeCompletionHelper.gd.uid | 2 +- .../TextEditor/syntax_highlighter.gd | 17 +- .../TextEditor/syntax_highlighter.gd.uid | 2 +- .../TextEditor/timeline_editor_text.gd | 212 ++++++---- .../TextEditor/timeline_editor_text.gd.uid | 2 +- .../TextEditor/timeline_editor_text.tscn | 8 +- .../VisualEditor/AddEventButton.gd.uid | 2 +- .../VisualEditor/AddEventButton.tscn | 2 +- .../VisualEditor/TimelineArea.gd.uid | 2 +- .../VisualEditor/timeline_editor_visual.gd | 257 +++++++++--- .../timeline_editor_visual.gd.uid | 2 +- .../VisualEditor/timeline_editor_visual.tscn | 47 ++- .../Editor/TimelineEditor/shortcut_popup.gd | 118 ++++++ .../TimelineEditor/shortcut_popup.gd.uid | 1 + .../TimelineEditor/test_timeline_scene.gd | 4 +- .../TimelineEditor/test_timeline_scene.gd.uid | 2 +- .../TimelineEditor/test_timeline_scene.tscn | 2 +- .../Editor/TimelineEditor/timeline_editor.gd | 104 ++++- .../TimelineEditor/timeline_editor.gd.uid | 2 +- .../TimelineEditor/timeline_editor.tscn | 204 +++++++-- addons/dialogic/Editor/dialogic_editor.gd | 1 + addons/dialogic/Editor/dialogic_editor.gd.uid | 2 +- addons/dialogic/Editor/editor_main.gd | 202 ++++----- addons/dialogic/Editor/editor_main.gd.uid | 2 +- addons/dialogic/Editor/editor_main.tscn | 12 +- addons/dialogic/Editor/editors_manager.gd.uid | 2 +- .../dialogic/Example Assets/Fonts/LICENSE.txt | 202 +++++++++ .../already_read_indicator.gd.uid | 2 +- .../bbcode_transition_effect.gd | 84 ++++ .../bbcode_transition_effect.gd.uid | 1 + .../bbcode_transitions/fade_in.tres | 17 + .../bbcode_transitions/fade_scale_in.tres | 24 ++ .../bbcode_transitions/fancy_in.tres | 35 ++ .../bbcode_transitions/shaky_in.tres | 35 ++ .../Example Assets/default_event.gd.uid | 2 +- .../CustomPortrait_AnimatedSprite.gd.uid | 2 +- .../CustomPortrait_AnimatedSprite.tscn | 2 +- .../portraits/CustomPortrait_FaceAtlas.gd.uid | 2 +- .../portraits/CustomPortrait_FaceAtlas.tscn | 2 +- addons/dialogic/Modules/Audio/event_audio.gd | 397 ++++++++++++++++++ .../dialogic/Modules/Audio/event_audio.gd.uid | 1 + addons/dialogic/Modules/Audio/event_music.gd | 105 ----- .../dialogic/Modules/Audio/event_music.gd.uid | 1 - addons/dialogic/Modules/Audio/event_sound.gd | 86 ---- .../dialogic/Modules/Audio/event_sound.gd.uid | 1 - addons/dialogic/Modules/Audio/index.gd | 2 +- addons/dialogic/Modules/Audio/index.gd.uid | 2 +- .../dialogic/Modules/Audio/settings_audio.gd | 223 +++++++++- .../Modules/Audio/settings_audio.gd.uid | 2 +- .../Modules/Audio/settings_audio.tscn | 111 +++-- .../dialogic/Modules/Audio/subsystem_audio.gd | 349 ++++++++------- .../Modules/Audio/subsystem_audio.gd.uid | 2 +- .../default_background.gd | 4 + .../default_background.gd.uid | 2 +- .../default_background.tscn | 2 +- .../Transitions/Defaults/push_down.gd.uid | 2 +- .../Transitions/Defaults/push_left.gd.uid | 2 +- .../Transitions/Defaults/push_right.gd.uid | 2 +- .../Transitions/Defaults/push_up.gd.uid | 2 +- .../Transitions/Defaults/simple_fade.gd.uid | 2 +- .../Defaults/swipe_diagonal_up_left.gd.uid | 2 +- .../Defaults/swipe_left_to_right.gd.uid | 2 +- .../Defaults/swipe_right_to_left.gd.uid | 2 +- .../class_dialogic_background_transition.gd | 1 + ...lass_dialogic_background_transition.gd.uid | 2 +- .../default_transition_shader.gdshader.uid | 2 +- .../push_transition_shader.gdshader.uid | 2 +- .../simple_push_transitions.gd.uid | 2 +- .../simple_swipe_transitions.gd.uid | 2 +- .../Modules/Background/dialogic_background.gd | 1 + .../Background/dialogic_background.gd.uid | 2 +- .../Modules/Background/event_background.gd | 14 +- .../Background/event_background.gd.uid | 2 +- .../dialogic/Modules/Background/index.gd.uid | 2 +- .../Background/node_background_holder.gd.uid | 2 +- .../Background/subsystem_backgrounds.gd | 8 + .../Background/subsystem_backgrounds.gd.uid | 2 +- addons/dialogic/Modules/Call/event_call.gd | 62 +-- .../dialogic/Modules/Call/event_call.gd.uid | 2 +- addons/dialogic/Modules/Call/index.gd.uid | 2 +- .../Character/DefaultAnimations/bounce.gd.uid | 2 +- .../DefaultAnimations/bounce_in_out.gd.uid | 2 +- .../DefaultAnimations/fade_down_in_out.gd.uid | 2 +- .../DefaultAnimations/fade_in_out.gd.uid | 2 +- .../DefaultAnimations/fade_up_in_out.gd.uid | 2 +- .../DefaultAnimations/heartbeat.gd.uid | 2 +- .../DefaultAnimations/instant_in_out.gd.uid | 2 +- .../Character/DefaultAnimations/shake_x.gd | 2 +- .../DefaultAnimations/shake_x.gd.uid | 2 +- .../DefaultAnimations/shake_y.gd.uid | 2 +- .../DefaultAnimations/slide_down_in_out.gd | 9 +- .../slide_down_in_out.gd.uid | 2 +- .../DefaultAnimations/slide_left_in_out.gd | 13 +- .../slide_left_in_out.gd.uid | 2 +- .../DefaultAnimations/slide_right_in_out.gd | 21 +- .../slide_right_in_out.gd.uid | 2 +- .../DefaultAnimations/slide_up_in.gd | 13 +- .../DefaultAnimations/slide_up_in.gd.uid | 2 +- .../Character/DefaultAnimations/tada.gd.uid | 2 +- .../zoom_center_in_out.gd.uid | 2 +- .../DefaultAnimations/zoom_in_out.gd.uid | 2 +- .../DialogicPortraitAnimationsUtil.gd.uid | 2 +- .../Character/class_dialogic_animation.gd | 25 ++ .../Character/class_dialogic_animation.gd.uid | 2 +- .../Modules/Character/default_portrait.gd.uid | 2 +- .../Modules/Character/default_portrait.tscn | 2 +- .../Character/dialogic_portrait.gd.uid | 2 +- .../Modules/Character/event_character.gd | 29 +- .../Modules/Character/event_character.gd.uid | 2 +- .../dialogic/Modules/Character/index.gd.uid | 2 +- .../Character/node_portrait_container.gd.uid | 2 +- .../Modules/Character/preview_character.tres | 2 +- .../Modules/Character/settings_portraits.gd | 6 +- .../Character/settings_portraits.gd.uid | 2 +- .../Modules/Character/settings_portraits.tscn | 11 +- .../Modules/Character/subsystem_containers.gd | 3 +- .../Character/subsystem_containers.gd.uid | 2 +- .../Modules/Character/subsystem_portraits.gd | 181 ++++---- .../Character/subsystem_portraits.gd.uid | 2 +- .../dialogic/Modules/Choice/event_choice.gd | 6 +- .../Modules/Choice/event_choice.gd.uid | 2 +- addons/dialogic/Modules/Choice/index.gd.uid | 2 +- .../Modules/Choice/node_button_sound.gd.uid | 2 +- .../Modules/Choice/node_choice_button.gd | 95 ++++- .../Modules/Choice/node_choice_button.gd.uid | 2 +- .../Modules/Choice/settings_choices.gd.uid | 2 +- .../Modules/Choice/settings_choices.tscn | 2 +- .../Modules/Choice/subsystem_choices.gd | 88 ++-- .../Modules/Choice/subsystem_choices.gd.uid | 2 +- .../Modules/Choice/ui_choice_end.gd.uid | 2 +- .../Modules/Choice/ui_choice_end.tscn | 2 +- addons/dialogic/Modules/Clear/event_clear.gd | 14 +- .../dialogic/Modules/Clear/event_clear.gd.uid | 2 +- addons/dialogic/Modules/Clear/index.gd.uid | 2 +- .../Modules/Comment/event_comment.gd.uid | 2 +- addons/dialogic/Modules/Comment/index.gd.uid | 2 +- .../Modules/Condition/event_condition.gd | 21 +- .../Modules/Condition/event_condition.gd.uid | 2 +- .../dialogic/Modules/Condition/index.gd.uid | 2 +- .../Modules/Condition/ui_condition_end.gd.uid | 2 +- .../Modules/Condition/ui_condition_end.tscn | 4 +- .../dialogic/Modules/Core/event_end_branch.gd | 43 +- .../Modules/Core/event_end_branch.gd.uid | 2 +- addons/dialogic/Modules/Core/index.gd | 2 +- addons/dialogic/Modules/Core/index.gd.uid | 2 +- .../Modules/Core/subsystem_animation.gd.uid | 2 +- .../Modules/Core/subsystem_expression.gd | 14 +- .../Modules/Core/subsystem_expression.gd.uid | 2 +- .../dialogic/Modules/Core/subsystem_input.gd | 2 +- .../Modules/Core/subsystem_input.gd.uid | 2 +- .../Base_Default/default_layout_base.gd | 2 + .../Base_Default/default_layout_base.gd.uid | 2 +- .../Base_Default/default_layout_base.tscn | 2 +- .../Base_TextBubble/text_bubble_base.gd | 3 +- .../Base_TextBubble/text_bubble_base.gd.uid | 2 +- .../Base_TextBubble/text_bubble_base.tscn | 2 +- .../full_background_layer.gd.uid | 2 +- .../full_background_layer.tscn | 4 +- .../Layer_Glossary/glossary_popup_layer.gd | 2 +- .../glossary_popup_layer.gd.uid | 2 +- .../Layer_Glossary/glossary_popup_layer.tscn | 2 +- .../Layer_History/example_history_item.gd.uid | 2 +- .../Layer_History/example_history_item.tscn | 2 +- .../Layer_History/history_layer.gd.uid | 2 +- .../Layer_History/history_layer.tscn | 2 +- .../full_advance_input_layer.gd.uid | 2 +- .../Layer_Input/full_advance_input_layer.tscn | 4 +- ...ms_stylebox.tres => default_stylebox.tres} | 2 +- .../speaker_portrait_textbox_layer.gd.uid | 2 +- .../textbox_with_speaker_portrait.tscn | 10 +- .../Layer_TextInput/text_input_layer.gd.uid | 2 +- .../Layer_TextInput/text_input_layer.tscn | 4 +- .../speech_bubble.gdshader.uid | 2 +- .../Layer_Textbubble/text_bubble.gd | 64 ++- .../Layer_Textbubble/text_bubble.gd.uid | 2 +- .../Layer_Textbubble/text_bubble.gdshader.uid | 2 +- .../Layer_Textbubble/text_bubble.tscn | 11 +- .../Layer_Textbubble/text_bubble_layer.gd | 12 +- .../Layer_Textbubble/text_bubble_layer.gd.uid | 2 +- .../Layer_Textbubble/text_bubble_layer.tscn | 2 +- .../Layer_VN_Choices/vn_choice_layer.gd | 37 +- .../Layer_VN_Choices/vn_choice_layer.gd.uid | 2 +- .../Layer_VN_Choices/vn_choice_layer.tscn | 61 +-- .../vn_portrait_layer.gd.uid | 2 +- .../Layer_VN_Portraits/vn_portrait_layer.tscn | 4 +- .../Layer_VN_Textbox/animations.gd.uid | 2 +- .../autoadvance_indicator.gd.uid | 2 +- .../Layer_VN_Textbox/vn_textbox_layer.gd.uid | 2 +- .../Layer_VN_Textbox/vn_textbox_layer.tscn | 14 +- .../speaker_textbox_style.tres | 4 +- .../Style_TextBubbles/textbubble_style.tres | 4 +- .../Style_VN_Default/default_vn_style.tres | 4 +- .../Modules/DefaultLayoutParts/index.gd | 1 + .../Modules/DefaultLayoutParts/index.gd.uid | 2 +- addons/dialogic/Modules/End/event_end.gd.uid | 2 +- addons/dialogic/Modules/End/index.gd.uid | 2 +- .../Modules/Glossary/event_glossary.gd.uid | 2 +- .../Modules/Glossary/glossary_editor.gd.uid | 2 +- .../Modules/Glossary/glossary_editor.tscn | 2 +- .../Modules/Glossary/glossary_resource.gd.uid | 2 +- addons/dialogic/Modules/Glossary/index.gd.uid | 2 +- .../Modules/Glossary/subsystem_glossary.gd | 4 +- .../Glossary/subsystem_glossary.gd.uid | 2 +- .../Modules/HighlightPortrait/index.gd.uid | 2 +- .../simple_highlight_portrait.gd | 4 + .../simple_highlight_portrait.gd.uid | 2 +- .../simple_highlight_portrait.tscn | 2 +- .../Modules/History/event_history.gd.uid | 2 +- addons/dialogic/Modules/History/index.gd.uid | 2 +- .../Modules/History/settings_history.gd.uid | 2 +- .../Modules/History/settings_history.tscn | 2 +- .../Modules/History/subsystem_history.gd.uid | 2 +- addons/dialogic/Modules/Jump/event_jump.gd | 11 +- .../dialogic/Modules/Jump/event_jump.gd.uid | 2 +- addons/dialogic/Modules/Jump/event_label.gd | 2 +- .../dialogic/Modules/Jump/event_label.gd.uid | 2 +- addons/dialogic/Modules/Jump/event_return.gd | 2 +- .../dialogic/Modules/Jump/event_return.gd.uid | 2 +- addons/dialogic/Modules/Jump/index.gd.uid | 2 +- .../dialogic/Modules/Jump/subsystem_jump.gd | 43 +- .../Modules/Jump/subsystem_jump.gd.uid | 2 +- .../custom_layered_portrait.gd.uid | 2 +- .../Modules/LayeredPortrait/index.gd.uid | 2 +- .../LayeredPortrait/layered_portrait.gd.uid | 2 +- .../LayeredPortrait/layered_portrait.tscn | 2 +- .../dialogic/Modules/Save/event_save.gd.uid | 2 +- addons/dialogic/Modules/Save/index.gd.uid | 2 +- .../Modules/Save/settings_save.gd.uid | 2 +- .../dialogic/Modules/Save/settings_save.tscn | 2 +- .../Modules/Save/subsystem_save.gd.uid | 2 +- .../Modules/Settings/event_setting.gd.uid | 2 +- addons/dialogic/Modules/Settings/index.gd.uid | 2 +- .../Settings/subsystem_settings.gd.uid | 2 +- .../Modules/Signal/event_signal.gd.uid | 2 +- addons/dialogic/Modules/Signal/index.gd.uid | 2 +- .../Modules/Style/DialogicStylesUtil.gd | 79 ++++ .../Modules/Style/DialogicStylesUtil.gd.uid | 1 + .../Modules/Style/character_settings_style.gd | 2 +- .../Style/character_settings_style.gd.uid | 2 +- .../Style/character_settings_style.tscn | 2 +- .../dialogic/Modules/Style/event_style.gd.uid | 2 +- addons/dialogic/Modules/Style/index.gd.uid | 2 +- .../dialogic/Modules/Style/node_style.gd.uid | 2 +- .../Modules/Style/subsystem_styles.gd | 14 +- .../Modules/Style/subsystem_styles.gd.uid | 2 +- .../Components/style_browser.gd.uid | 2 +- .../StyleEditor/Components/style_browser.tscn | 2 +- .../Components/style_browser_window.gd.uid | 2 +- .../Components/style_layer_tree.gd.uid | 2 +- addons/dialogic/Modules/StyleEditor/index.gd | 1 + .../dialogic/Modules/StyleEditor/index.gd.uid | 2 +- .../Modules/StyleEditor/style_editor.gd | 2 +- .../Modules/StyleEditor/style_editor.gd.uid | 2 +- .../Modules/StyleEditor/style_editor.tscn | 8 +- .../StyleEditor/style_layer_editor.gd.uid | 2 +- .../dialogic/Modules/Text/auto_advance.gd.uid | 2 +- addons/dialogic/Modules/Text/auto_skip.gd.uid | 2 +- .../character_moods_settings.gd | 1 + .../character_moods_settings.gd.uid | 2 +- .../character_moods_settings.tscn | 4 +- .../character_portrait_mood_settings.gd | 2 +- .../character_portrait_mood_settings.gd.uid | 2 +- .../character_portrait_mood_settings.tscn | 2 +- addons/dialogic/Modules/Text/event_text.gd | 169 +++++--- .../dialogic/Modules/Text/event_text.gd.uid | 2 +- addons/dialogic/Modules/Text/index.gd.uid | 2 +- .../Modules/Text/manual_advance.gd.uid | 2 +- .../dialogic/Modules/Text/node_dialog_text.gd | 36 +- .../Modules/Text/node_dialog_text.gd.uid | 2 +- .../dialogic/Modules/Text/node_input.gd.uid | 2 +- .../Modules/Text/node_name_label.gd.uid | 2 +- .../Modules/Text/node_next_indicator.gd.uid | 2 +- .../Modules/Text/node_type_sound.gd.uid | 2 +- addons/dialogic/Modules/Text/settings_text.gd | 17 +- .../Modules/Text/settings_text.gd.uid | 2 +- .../dialogic/Modules/Text/settings_text.tscn | 87 ++-- .../dialogic/Modules/Text/subsystem_text.gd | 197 ++++++--- .../Modules/Text/subsystem_text.gd.uid | 2 +- .../Modules/TextInput/event_text_input.gd | 37 +- .../Modules/TextInput/event_text_input.gd.uid | 2 +- .../dialogic/Modules/TextInput/index.gd.uid | 2 +- .../Modules/TextInput/node_text_input.gd.uid | 2 +- .../Modules/TextInput/subsystem_text_input.gd | 2 + .../TextInput/subsystem_text_input.gd.uid | 2 +- .../Modules/Variable/event_variable.gd | 37 +- .../Modules/Variable/event_variable.gd.uid | 2 +- addons/dialogic/Modules/Variable/index.gd.uid | 2 +- .../Modules/Variable/subsystem_variables.gd | 3 +- .../Variable/subsystem_variables.gd.uid | 2 +- .../variables_editor/variable_tree.gd | 279 ++++++++++-- .../variables_editor/variable_tree.gd.uid | 2 +- .../variables_editor/variables_editor.gd | 10 +- .../variables_editor/variables_editor.gd.uid | 2 +- .../variables_editor/variables_editor.tscn | 32 +- .../dialogic/Modules/Voice/event_voice.gd.uid | 2 +- addons/dialogic/Modules/Voice/index.gd.uid | 2 +- .../Modules/Voice/subsystem_voice.gd.uid | 2 +- .../dialogic/Modules/Wait/event_wait.gd.uid | 2 +- addons/dialogic/Modules/Wait/index.gd.uid | 2 +- .../Modules/WaitInput/event_wait_input.gd.uid | 2 +- .../dialogic/Modules/WaitInput/index.gd.uid | 2 +- .../Resources/CharacterResourceLoader.gd | 20 +- .../Resources/CharacterResourceLoader.gd.uid | 2 +- .../Resources/CharacterResourceSaver.gd.uid | 2 +- .../Resources/TimelineResourceLoader.gd | 21 + .../Resources/TimelineResourceLoader.gd.uid | 2 +- .../Resources/TimelineResourceSaver.gd | 32 +- .../Resources/TimelineResourceSaver.gd.uid | 2 +- addons/dialogic/Resources/character.gd | 23 +- addons/dialogic/Resources/character.gd.uid | 2 +- .../dialogic_identifiable_resource.gd | 36 ++ .../dialogic_identifiable_resource.gd.uid | 1 + .../Resources/dialogic_layout_base.gd | 8 +- .../Resources/dialogic_layout_base.gd.uid | 2 +- .../Resources/dialogic_layout_layer.gd.uid | 2 +- addons/dialogic/Resources/dialogic_style.gd | 13 +- .../dialogic/Resources/dialogic_style.gd.uid | 2 +- .../Resources/dialogic_style_layer.gd | 7 + .../Resources/dialogic_style_layer.gd.uid | 2 +- addons/dialogic/Resources/event.gd | 67 ++- addons/dialogic/Resources/event.gd.uid | 2 +- addons/dialogic/Resources/timeline.gd | 71 +++- addons/dialogic/Resources/timeline.gd.uid | 2 +- addons/dialogic/plugin.cfg | 2 +- addons/dialogic/plugin.gd.uid | 2 +- 483 files changed, 5771 insertions(+), 2205 deletions(-) create mode 100644 addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd create mode 100644 addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd.uid create mode 100644 addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.tscn create mode 100644 addons/dialogic/Editor/Events/Fields/field_image_preview.gd create mode 100644 addons/dialogic/Editor/Events/Fields/field_image_preview.gd.uid create mode 100644 addons/dialogic/Editor/Events/Fields/field_image_preview.tscn create mode 100644 addons/dialogic/Editor/Images/Resources/timeline.svg create mode 100644 addons/dialogic/Editor/Images/Resources/timeline.svg.import rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/csv_file.gd (100%) create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/csv_file.gd.uid create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd.uid create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.tscn rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/settings_general.gd (67%) create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd.uid rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/settings_general.tscn (52%) rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/settings_modules.gd (99%) create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd.uid rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/settings_modules.tscn (98%) create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd.uid rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/settings_translation.gd (99%) create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd.uid rename addons/dialogic/Editor/Settings/{ => CoreSettingsPages}/settings_translation.tscn (98%) create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd create mode 100644 addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd.uid delete mode 100644 addons/dialogic/Editor/Settings/csv_file.gd.uid delete mode 100644 addons/dialogic/Editor/Settings/settings_general.gd.uid delete mode 100644 addons/dialogic/Editor/Settings/settings_modules.gd.uid delete mode 100644 addons/dialogic/Editor/Settings/settings_translation.gd.uid create mode 100644 addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd create mode 100644 addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd.uid create mode 100644 addons/dialogic/Example Assets/Fonts/LICENSE.txt create mode 100644 addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd create mode 100644 addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd.uid create mode 100644 addons/dialogic/Example Assets/bbcode_transitions/fade_in.tres create mode 100644 addons/dialogic/Example Assets/bbcode_transitions/fade_scale_in.tres create mode 100644 addons/dialogic/Example Assets/bbcode_transitions/fancy_in.tres create mode 100644 addons/dialogic/Example Assets/bbcode_transitions/shaky_in.tres create mode 100644 addons/dialogic/Modules/Audio/event_audio.gd create mode 100644 addons/dialogic/Modules/Audio/event_audio.gd.uid delete mode 100644 addons/dialogic/Modules/Audio/event_music.gd delete mode 100644 addons/dialogic/Modules/Audio/event_music.gd.uid delete mode 100644 addons/dialogic/Modules/Audio/event_sound.gd delete mode 100644 addons/dialogic/Modules/Audio/event_sound.gd.uid rename addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/{comms_stylebox.tres => default_stylebox.tres} (78%) create mode 100644 addons/dialogic/Modules/Style/DialogicStylesUtil.gd create mode 100644 addons/dialogic/Modules/Style/DialogicStylesUtil.gd.uid create mode 100644 addons/dialogic/Resources/dialogic_identifiable_resource.gd create mode 100644 addons/dialogic/Resources/dialogic_identifiable_resource.gd.uid diff --git a/addons/dialogic/Core/DialogicGameHandler.gd b/addons/dialogic/Core/DialogicGameHandler.gd index d1a6c28c..1d07f935 100644 --- a/addons/dialogic/Core/DialogicGameHandler.gd +++ b/addons/dialogic/Core/DialogicGameHandler.gd @@ -70,64 +70,71 @@ var paused := false: dialogic_resumed.emit() +## A timeline that will be played when dialog ends. +## By default this timeline only contains a clear event. +var dialog_ending_timeline: DialogicTimeline + ## Emitted when [member paused] changes to `true`. signal dialogic_paused ## Emitted when [member paused] changes to `false`. signal dialogic_resumed -## Emitted when the timeline ends. -## This can be a timeline ending or [method end_timeline] being called. -signal timeline_ended ## Emitted when a timeline starts by calling either [method start] ## or [method start_timeline]. signal timeline_started +## Emitted when the timeline ends. +## This can be a timeline ending or [method end_timeline] being called. +signal timeline_ended ## Emitted when an event starts being executed. ## The event may not have finished executing yet. signal event_handled(resource: DialogicEvent) ## Emitted when a [class SignalEvent] event was reached. +@warning_ignore("unused_signal") # This is emitted by the signal event. signal signal_event(argument: Variant) + ## Emitted when a signal event gets fired from a [class TextEvent] event. +@warning_ignore("unused_signal") # This is emitted by the text subsystem. signal text_signal(argument: String) # Careful, this section is repopulated automatically at certain moments. #region SUBSYSTEMS +var Animations := preload("res://addons/dialogic/Modules/Core/subsystem_animation.gd").new(): + get: return get_subsystem("Animations") + var Audio := preload("res://addons/dialogic/Modules/Audio/subsystem_audio.gd").new(): get: return get_subsystem("Audio") var Backgrounds := preload("res://addons/dialogic/Modules/Background/subsystem_backgrounds.gd").new(): get: return get_subsystem("Backgrounds") -var Portraits := preload("res://addons/dialogic/Modules/Character/subsystem_portraits.gd").new(): - get: return get_subsystem("Portraits") - -var PortraitContainers := preload("res://addons/dialogic/Modules/Character/subsystem_containers.gd").new(): - get: return get_subsystem("PortraitContainers") - var Choices := preload("res://addons/dialogic/Modules/Choice/subsystem_choices.gd").new(): get: return get_subsystem("Choices") var Expressions := preload("res://addons/dialogic/Modules/Core/subsystem_expression.gd").new(): get: return get_subsystem("Expressions") -var Animations := preload("res://addons/dialogic/Modules/Core/subsystem_animation.gd").new(): - get: return get_subsystem("Animations") - -var Inputs := preload("res://addons/dialogic/Modules/Core/subsystem_input.gd").new(): - get: return get_subsystem("Inputs") - var Glossary := preload("res://addons/dialogic/Modules/Glossary/subsystem_glossary.gd").new(): get: return get_subsystem("Glossary") var History := preload("res://addons/dialogic/Modules/History/subsystem_history.gd").new(): get: return get_subsystem("History") +var Inputs := preload("res://addons/dialogic/Modules/Core/subsystem_input.gd").new(): + get: return get_subsystem("Inputs") + var Jump := preload("res://addons/dialogic/Modules/Jump/subsystem_jump.gd").new(): get: return get_subsystem("Jump") +var PortraitContainers := preload("res://addons/dialogic/Modules/Character/subsystem_containers.gd").new(): + get: return get_subsystem("PortraitContainers") + +var Portraits := preload("res://addons/dialogic/Modules/Character/subsystem_portraits.gd").new(): + get: return get_subsystem("Portraits") + var Save := preload("res://addons/dialogic/Modules/Save/subsystem_save.gd").new(): get: return get_subsystem("Save") @@ -149,9 +156,6 @@ var VAR := preload("res://addons/dialogic/Modules/Variable/subsystem_variables.g var Voice := preload("res://addons/dialogic/Modules/Voice/subsystem_voice.gd").new(): get: return get_subsystem("Voice") -var ShowImage := preload("res://addons/dialogic_additions/ShowImage/subsystem_show_image.gd").new(): - get: return get_subsystem("ShowImage") - #endregion @@ -161,6 +165,11 @@ func _ready() -> void: clear() + DialogicResourceUtil.update_event_cache() + + dialog_ending_timeline = DialogicTimeline.new() + dialog_ending_timeline.from_text("[clear]") + #region TIMELINE & EVENT HANDLING ################################################################################ @@ -168,12 +177,12 @@ func _ready() -> void: ## Method to start a timeline AND ensure that a layout scene is present. ## For argument info, checkout [method start_timeline]. ## -> returns the layout node -func start(timeline:Variant, label:Variant="") -> Node: +func start(timeline:Variant, label_or_idx:Variant="") -> Node: # If we don't have a style subsystem, default to just start_timeline() if not has_subsystem('Styles'): printerr("[Dialogic] You called Dialogic.start() but the Styles subsystem is missing!") clear(ClearFlags.KEEP_VARIABLES) - start_timeline(timeline, label) + start_timeline(timeline, label_or_idx) return null # Otherwise make sure there is a style active. @@ -185,10 +194,12 @@ func start(timeline:Variant, label:Variant="") -> Node: scene.show() if not scene.is_node_ready(): - scene.ready.connect(clear.bind(ClearFlags.KEEP_VARIABLES)) - scene.ready.connect(start_timeline.bind(timeline, label)) + if not scene.ready.is_connected(clear.bind(ClearFlags.KEEP_VARIABLES)): + scene.ready.connect(clear.bind(ClearFlags.KEEP_VARIABLES)) + if not scene.ready.is_connected(start_timeline.bind(timeline, label_or_idx)): + scene.ready.connect(start_timeline.bind(timeline, label_or_idx)) else: - start_timeline(timeline, label) + start_timeline(timeline, label_or_idx) return scene @@ -198,12 +209,12 @@ func start(timeline:Variant, label:Variant="") -> Node: ## @label_or_idx can be a label (string) or index (int) to skip to immediatly. func start_timeline(timeline:Variant, label_or_idx:Variant = "") -> void: # load the resource if only the path is given - if typeof(timeline) == TYPE_STRING: + if typeof(timeline) in [TYPE_STRING, TYPE_STRING_NAME]: #check the lookup table if it's not a full file name - if (timeline as String).contains("res://"): - timeline = load((timeline as String)) + if "://" in timeline: + timeline = load(timeline) else: - timeline = DialogicResourceUtil.get_timeline_resource((timeline as String)) + timeline = DialogicResourceUtil.get_timeline_resource(timeline) if timeline == null: printerr("[Dialogic] There was an error loading this timeline. Check the filename, and the timeline for errors") @@ -217,7 +228,7 @@ func start_timeline(timeline:Variant, label_or_idx:Variant = "") -> void: event.dialogic = self current_event_idx = -1 - if typeof(label_or_idx) == TYPE_STRING: + if typeof(label_or_idx) in [TYPE_STRING, TYPE_STRING_NAME]: if label_or_idx: if has_subsystem('Jump'): Jump.jump_to_label((label_or_idx as String)) @@ -225,7 +236,9 @@ func start_timeline(timeline:Variant, label_or_idx:Variant = "") -> void: if label_or_idx >-1: current_event_idx = label_or_idx -1 - timeline_started.emit() + if not current_timeline == dialog_ending_timeline: + timeline_started.emit() + handle_next_event() @@ -233,8 +246,12 @@ func start_timeline(timeline:Variant, label_or_idx:Variant = "") -> void: ## [param timeline_resource] can be either a path (string) or a loaded timeline (resource) func preload_timeline(timeline_resource:Variant) -> Variant: # I think ideally this should be on a new thread, will test - if typeof(timeline_resource) == TYPE_STRING: - timeline_resource = load((timeline_resource as String)) + if typeof(timeline_resource) in [TYPE_STRING, TYPE_STRING_NAME]: + if "://" in timeline_resource: + timeline_resource = load(timeline_resource) + else: + timeline_resource = DialogicResourceUtil.get_timeline_resource(timeline_resource) + if timeline_resource == null: printerr("[Dialogic] There was an error preloading this timeline. Check the filename, and the timeline for errors") return null @@ -245,12 +262,37 @@ func preload_timeline(timeline_resource:Variant) -> Variant: ## Clears and stops the current timeline. -func end_timeline() -> void: +## If [param skip_ending] is `true`, the dialog_ending_timeline is not getting played +func end_timeline(skip_ending := false) -> void: + if not skip_ending and dialog_ending_timeline and current_timeline != dialog_ending_timeline: + start(dialog_ending_timeline) + return + await clear(ClearFlags.TIMELINE_INFO_ONLY) - _on_timeline_ended() + + if Styles.has_active_layout_node() and Styles.get_layout_node().is_inside_tree(): + match ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0): + 0: + Styles.get_layout_node().get_parent().remove_child(Styles.get_layout_node()) + Styles.get_layout_node().queue_free() + 1: + Styles.get_layout_node().hide() + timeline_ended.emit() +## Method to check if timeline exists. +## @timeline can be either a loaded timeline resource or a path to a timeline file. +func timeline_exists(timeline:Variant) -> bool: + if typeof(timeline) in [TYPE_STRING, TYPE_STRING_NAME]: + if "://" in timeline and ResourceLoader.exists(timeline): + return load(timeline) is DialogicTimeline + else: + return DialogicResourceUtil.timeline_resource_exists(timeline) + + return timeline is DialogicTimeline + + ## Handles the next event. func handle_next_event(_ignore_argument: Variant = "") -> void: handle_event(current_event_idx+1) @@ -271,6 +313,7 @@ func handle_event(event_index:int) -> void: end_timeline() return + # TODO: Check if necessary. This should be impossible. #actually process the event now, since we didnt earlier at runtime #this needs to happen before we create the copy DialogicEvent variable, so it doesn't throw an error if not ready if current_timeline_events[event_index].event_node_ready == false: @@ -370,7 +413,7 @@ func load_full_state(state_info:Dictionary) -> void: if current_state_info.get('current_timeline', null): start_timeline(current_state_info.current_timeline, current_state_info.get('current_event_idx', 0)) else: - end_timeline.call_deferred() + end_timeline.call_deferred(true) #endregion @@ -415,22 +458,12 @@ func add_subsystem(subsystem_name:String, script_path:String) -> DialogicSubsyst #region HELPERS ################################################################################ -## This handles the `Layout End Behaviour` setting that can be changed in the Dialogic settings. -func _on_timeline_ended() -> void: - if self.Styles.has_active_layout_node() and self.Styles.get_layout_node().is_inside_tree(): - match ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0): - 0: - self.Styles.get_layout_node().get_parent().remove_child(self.Styles.get_layout_node()) - self.Styles.get_layout_node().queue_free() - 1: - @warning_ignore("unsafe_method_access") - self.Styles.get_layout_node().hide() func print_debug_moment() -> void: if not current_timeline: return - printerr("\tAt event ", current_event_idx+1, " (",current_timeline_events[current_event_idx].event_name, ' Event) in timeline "', DialogicResourceUtil.get_unique_identifier(current_timeline.resource_path), '" (',current_timeline.resource_path,').') + printerr("\tAt event ", current_event_idx+1, " (",current_timeline_events[current_event_idx].event_name, ' Event) in timeline "', current_timeline.get_identifier(), '" (',current_timeline.resource_path,').') print("\n") #endregion diff --git a/addons/dialogic/Core/DialogicGameHandler.gd.uid b/addons/dialogic/Core/DialogicGameHandler.gd.uid index 4d7a8cbd..1565a565 100644 --- a/addons/dialogic/Core/DialogicGameHandler.gd.uid +++ b/addons/dialogic/Core/DialogicGameHandler.gd.uid @@ -1 +1 @@ -uid://dwg1hpegqijbk +uid://ds2q0uclmolvu diff --git a/addons/dialogic/Core/DialogicResourceUtil.gd b/addons/dialogic/Core/DialogicResourceUtil.gd index a86356cb..e5449c8c 100644 --- a/addons/dialogic/Core/DialogicResourceUtil.gd +++ b/addons/dialogic/Core/DialogicResourceUtil.gd @@ -3,6 +3,7 @@ class_name DialogicResourceUtil static var label_cache := {} static var event_cache: Array[DialogicEvent] = [] +static var channel_cache := {} static var special_resources := {} @@ -11,6 +12,8 @@ static func update() -> void: update_directory('.dch') update_directory('.dtl') update_label_cache() + update_audio_channel_cache() + DialogicStylesUtil.build_style_directory() #region RESOURCE DIRECTORIES @@ -53,30 +56,54 @@ static func update_directory(extension:String) -> void: static func add_resource_to_directory(file_path:String, directory:Dictionary) -> Dictionary: var suggested_name := file_path.get_file().trim_suffix("."+file_path.get_extension()) + var temp := suggested_name while suggested_name in directory: suggested_name = file_path.trim_suffix("/"+suggested_name+"."+file_path.get_extension()).get_file().path_join(suggested_name) + if suggested_name == temp: + break + temp = suggested_name directory[suggested_name] = file_path return directory ## Returns the unique identifier for the given resource path. ## Returns an empty string if no identifier was found. -static func get_unique_identifier(file_path:String) -> String: - var identifier: String = get_directory(file_path.get_extension()).find_key(file_path) +static func get_unique_identifier_by_path(file_path:String) -> String: + if not file_path: return "" + var identifier: Variant = get_directory(file_path.get_extension()).find_key(file_path) if typeof(identifier) == TYPE_STRING: return identifier return "" +static func get_resource_path_from_identifier(identifier:String, extension:String) -> String: + var value: Variant = get_directory(extension).get(identifier, '') + if value is String: + return value + return "" + + ## Returns the resource associated with the given unique identifier. ## The expected extension is needed to use the right directory. static func get_resource_from_identifier(identifier:String, extension:String) -> Resource: - var path: String = get_directory(extension).get(identifier, '') - if ResourceLoader.exists(path): - return load(path) + var value: Variant = get_directory(extension).get(identifier, '') + if typeof(value) == TYPE_STRING and ResourceLoader.exists(value): + return load(value) + elif value is Resource: + return value return null +## Returns a boolean that expresses whether the resource exists. +## The expected extension is needed to use the right directory. +static func resource_exists_from_identifier(identifier:String, extension:String) -> bool: + var value: Variant = get_directory(extension).get(identifier, '') + if typeof(value) == TYPE_STRING: + return ResourceLoader.exists(value) + return value is Resource + + +## Editor Only static func change_unique_identifier(file_path:String, new_identifier:String) -> void: var directory := get_directory(file_path.get_extension()) var key: String = directory.find_key(file_path) @@ -110,6 +137,21 @@ static func remove_resource(file_path:String) -> void: static func is_identifier_unused(extension:String, identifier:String) -> bool: return not identifier in get_directory(extension) + +## While usually the directory maps identifiers to paths, this method (only supposed to be used at runtime) +## allows mapping resources that are not saved to an identifier. +static func register_runtime_resource(resource:Resource, identifier:String, extension:String) -> void: + var directory := get_directory(extension) + directory[identifier] = resource + set_directory(extension, directory) + + +static func get_runtime_unique_identifier(resource:Resource, extension:String) -> String: + var identifier: Variant = get_directory(extension).find_key(resource) + if typeof(identifier) == TYPE_STRING: + return identifier + return "" + #endregion #region LABEL CACHE @@ -139,6 +181,45 @@ static func update_label_cache() -> void: #endregion +#region AUDIO CHANNEL CACHE +################################################################################ +# The audio channel cache is only for the editor so we don't have to scan all timelines +# whenever we want to suggest channels. This has no use in game and is not always perfect. + +static func get_audio_channel_cache() -> Dictionary: + if not channel_cache.is_empty(): + return channel_cache + + channel_cache = DialogicUtil.get_editor_setting('channel_ref', {}) + return channel_cache + + +static func get_channel_list() -> Array: + if channel_cache.is_empty(): + return [] + + var cached_names := [] + for timeline in channel_cache: + for name in channel_cache[timeline]: + if not cached_names.has(name): + cached_names.append(name) + return cached_names + + +static func set_audio_channel_cache(cache:Dictionary) -> void: + channel_cache = cache + + +static func update_audio_channel_cache() -> void: + var cache := get_audio_channel_cache() + var timelines := get_timeline_directory().values() + for timeline in cache: + if !timeline in timelines: + cache.erase(timeline) + set_audio_channel_cache(cache) + +#endregion + #region EVENT CACHE ################################################################################ @@ -260,6 +341,10 @@ static func get_timeline_directory() -> Dictionary: return get_directory('dtl') +static func timeline_resource_exists(timeline_identifier:String) -> bool: + return resource_exists_from_identifier(timeline_identifier, 'dtl') + + static func get_timeline_resource(timeline_identifier:String) -> DialogicTimeline: return get_resource_from_identifier(timeline_identifier, 'dtl') @@ -275,7 +360,7 @@ static func list_resources_of_type(extension:String) -> Array: static func scan_folder(path:String, extension:String) -> Array: var list: Array = [] - if DirAccess.dir_exists_absolute(path): + if DirAccess.dir_exists_absolute(path) and not FileAccess.file_exists(path + "/" + ".gdignore"): var dir := DirAccess.open(path) dir.list_dir_begin() var file_name := dir.get_next() diff --git a/addons/dialogic/Core/DialogicResourceUtil.gd.uid b/addons/dialogic/Core/DialogicResourceUtil.gd.uid index 06f041e5..21ba6f90 100644 --- a/addons/dialogic/Core/DialogicResourceUtil.gd.uid +++ b/addons/dialogic/Core/DialogicResourceUtil.gd.uid @@ -1 +1 @@ -uid://dsn41e1wjwfp4 +uid://bdt5bbxxkvab4 diff --git a/addons/dialogic/Core/DialogicUtil.gd b/addons/dialogic/Core/DialogicUtil.gd index 978b4185..897a61e5 100644 --- a/addons/dialogic/Core/DialogicUtil.gd +++ b/addons/dialogic/Core/DialogicUtil.gd @@ -9,7 +9,9 @@ class_name DialogicUtil ## This method should be used instead of EditorInterface.get_editor_scale(), because if you use that ## it will run perfectly fine from the editor, but crash when the game is exported. static func get_editor_scale() -> float: - return get_dialogic_plugin().get_editor_interface().get_editor_scale() + if Engine.is_editor_hint(): + return get_dialogic_plugin().get_editor_interface().get_editor_scale() + return 1.0 ## Although this does in fact always return a EditorPlugin node, @@ -77,11 +79,19 @@ static func _update_autoload_subsystem_access() -> void: var script: Script = load("res://addons/dialogic/Core/DialogicGameHandler.gd") var new_subsystem_access_list := "#region SUBSYSTEMS\n" + var subsystems_sorted := [] for indexer: DialogicIndexer in get_indexers(true, true): for subsystem: Dictionary in indexer._get_subsystems().duplicate(true): - new_subsystem_access_list += '\nvar {name} := preload("{script}").new():\n\tget: return get_subsystem("{name}")\n'.format(subsystem) + subsystems_sorted.append(subsystem) + + subsystems_sorted.sort_custom(func (a: Dictionary, b: Dictionary) -> bool: + return a.name < b.name + ) + + for subsystem: Dictionary in subsystems_sorted: + new_subsystem_access_list += '\nvar {name} := preload("{script}").new():\n\tget: return get_subsystem("{name}")\n'.format(subsystem) new_subsystem_access_list += "\n#endregion" script.source_code = RegEx.create_from_string(r"#region SUBSYSTEMS\n#*\n((?!#endregion)(.*\n))*#endregion").sub(script.source_code, new_subsystem_access_list) @@ -90,11 +100,10 @@ static func _update_autoload_subsystem_access() -> void: static func get_indexers(include_custom := true, force_reload := false) -> Array[DialogicIndexer]: - if Engine.get_main_loop().has_meta('dialogic_indexers') and !force_reload: + if Engine.get_main_loop().has_meta('dialogic_indexers') and not force_reload: return Engine.get_main_loop().get_meta('dialogic_indexers') var indexers: Array[DialogicIndexer] = [] - for file in listdir(DialogicUtil.get_module_path(''), false): var possible_script: String = DialogicUtil.get_module_path(file).path_join("index.gd") if ResourceLoader.exists(possible_script): @@ -287,40 +296,6 @@ static func _get_value_in_dictionary(path:String, dictionary:Dictionary, default #endregion - -#region STYLES -################################################################################ - -static func get_default_layout_base() -> PackedScene: - return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Base_Default/default_layout_base.tscn")) - - -static func get_fallback_style() -> DialogicStyle: - return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Style_VN_Default/default_vn_style.tres")) - - -static func get_default_style() -> DialogicStyle: - var default: String = ProjectSettings.get_setting('dialogic/layout/default_style', '') - if !ResourceLoader.exists(default): - return get_fallback_style() - return load(default) - - -static func get_style_by_name(name:String) -> DialogicStyle: - if name.is_empty(): - return get_default_style() - - var styles: Array = ProjectSettings.get_setting('dialogic/layout/style_list', []) - for style in styles: - if not ResourceLoader.exists(style): - continue - if load(style).name == name: - return load(style) - - return get_default_style() -#endregion - - #region SCENE EXPORT OVERRIDES ################################################################################ @@ -458,39 +433,53 @@ static func setup_script_property_edit_node(property_info: Dictionary, value:Var input.select(value) input.item_selected.connect(DialogicUtil._on_export_int_enum_submitted.bind(property_info.name, property_changed)) else: - input = SpinBox.new() - input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_info.name, property_changed)) - if property_info.hint_string == 'int': - input.step = 1 - input.allow_greater = true - input.allow_lesser = true - elif ',' in property_info.hint_string: + input = load("res://addons/dialogic/Editor/Events/Fields/field_number.tscn").instantiate() + input.property_name = property_info['name'] + input.use_int_mode() + + if ',' in property_info.hint_string: input.min_value = int(property_info.hint_string.get_slice(',', 0)) input.max_value = int(property_info.hint_string.get_slice(',', 1)) if property_info.hint_string.count(',') > 1: input.step = int(property_info.hint_string.get_slice(',', 2)) + else: + input.step = 1 + input.max_value = INF + input.min_value = -INF + if value != null: - input.value = value + input.set_value(value) + input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_changed)) TYPE_FLOAT: - input = SpinBox.new() + input = load("res://addons/dialogic/Editor/Events/Fields/field_number.tscn").instantiate() + input.property_name = property_info['name'] + input.use_float_mode() input.step = 0.01 if ',' in property_info.hint_string: input.min_value = float(property_info.hint_string.get_slice(',', 0)) input.max_value = float(property_info.hint_string.get_slice(',', 1)) if property_info.hint_string.count(',') > 1: input.step = float(property_info.hint_string.get_slice(',', 2)) - input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_info.name, property_changed)) if value != null: - input.value = value + input.set_value(value) + input.value_changed.connect(DialogicUtil._on_export_number_submitted.bind(property_changed)) TYPE_VECTOR2, TYPE_VECTOR3, TYPE_VECTOR4: var vectorSize: String = type_string(typeof(value))[-1] input = load("res://addons/dialogic/Editor/Events/Fields/field_vector" + vectorSize + ".tscn").instantiate() input.property_name = property_info['name'] input.set_value(value) input.value_changed.connect(DialogicUtil._on_export_vector_submitted.bind(property_changed)) + TYPE_VECTOR2I, TYPE_VECTOR3I, TYPE_VECTOR4I: + var vectorSize: String = type_string(typeof(value))[-2] + input = load("res://addons/dialogic/Editor/Events/Fields/field_vector" + vectorSize + ".tscn").instantiate() + input.step = 1 + input.property_name = property_info['name'] + input.set_value(value) + input.value_changed.connect(DialogicUtil._on_export_vectori_submitted.bind(property_changed)) TYPE_STRING: if property_info['hint'] & PROPERTY_HINT_FILE or property_info['hint'] & PROPERTY_HINT_DIR: input = load("res://addons/dialogic/Editor/Events/Fields/field_file.tscn").instantiate() + input.show_editing_button = true input.file_filter = property_info['hint_string'] input.file_mode = FileDialog.FILE_MODE_OPEN_FILE if property_info['hint'] == PROPERTY_HINT_DIR: @@ -518,6 +507,7 @@ static func setup_script_property_edit_node(property_info: Dictionary, value:Var TYPE_DICTIONARY: input = load("res://addons/dialogic/Editor/Events/Fields/field_dictionary.tscn").instantiate() input.property_name = property_info["name"] + input.set_value(value) input.value_changed.connect(_on_export_dict_submitted.bind(property_changed)) TYPE_OBJECT: input = load("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn").instantiate() @@ -543,7 +533,7 @@ static func _on_export_color_submitted(color:Color, property_name:String, callab static func _on_export_int_enum_submitted(item:int, property_name:String, callable: Callable) -> void: callable.call(property_name, var_to_str(item)) -static func _on_export_number_submitted(value:float, property_name:String, callable: Callable) -> void: +static func _on_export_number_submitted(property_name:String, value:float, callable: Callable) -> void: callable.call(property_name, var_to_str(value)) static func _on_export_file_submitted(property_name:String, value:String, callable: Callable) -> void: @@ -555,6 +545,13 @@ static func _on_export_string_enum_submitted(value:int, property_name:String, li static func _on_export_vector_submitted(property_name:String, value:Variant, callable: Callable) -> void: callable.call(property_name, var_to_str(value)) +static func _on_export_vectori_submitted(property_name:String, value:Variant, callable: Callable) -> void: + match typeof(value): + TYPE_VECTOR2: value = Vector2i(value) + TYPE_VECTOR3: value = Vector3i(value) + TYPE_VECTOR4: value = Vector4i(value) + callable.call(property_name, var_to_str(value)) + static func _on_export_dict_submitted(property_name:String, value:Variant, callable: Callable) -> void: callable.call(property_name, var_to_str(value)) @@ -674,3 +671,133 @@ static func get_portrait_position_suggestions(search_text := "") -> Dictionary: suggestions.erase(search_text) return suggestions + + +static func get_autoload_suggestions(filter:String="") -> Dictionary: + var suggestions := {} + + for prop in ProjectSettings.get_property_list(): + if prop.name.begins_with('autoload/'): + var some_autoload: String = prop.name.trim_prefix('autoload/') + suggestions[some_autoload] = {'value': some_autoload, 'tooltip':some_autoload, 'editor_icon': ["Node", "EditorIcons"]} + if filter.begins_with(some_autoload): + suggestions[filter] = {'value': filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]} + return suggestions + + +static func get_autoload_script_resource(autoload_name:String) -> Script: + var script: Script + if autoload_name and ProjectSettings.has_setting('autoload/'+autoload_name): + var loaded_autoload := load(ProjectSettings.get_setting('autoload/'+autoload_name).trim_prefix('*')) + + if loaded_autoload is PackedScene: + var packed_scene: PackedScene = loaded_autoload + script = packed_scene.instantiate().get_script() + + else: + script = loaded_autoload + return script + + +static func get_autoload_method_suggestions(filter:String, autoload_name:String) -> Dictionary: + var suggestions := {} + + var script := get_autoload_script_resource(autoload_name) + if script: + for script_method in script.get_script_method_list(): + if script_method.name.begins_with('@') or script_method.name.begins_with('_'): + continue + suggestions[script_method.name] = {'value': script_method.name, 'tooltip':script_method.name, 'editor_icon': ["Callable", "EditorIcons"]} + + if not filter.is_empty(): + suggestions[filter] = {'value': filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]} + + return suggestions + + +static func get_autoload_property_suggestions(_filter:String, autoload_name:String) -> Dictionary: + var suggestions := {} + var script := get_autoload_script_resource(autoload_name) + if script: + for property in script.get_script_property_list(): + if property.name.ends_with('.gd') or property.name.begins_with('_'): + continue + suggestions[property.name] = {'value': property.name, 'tooltip':property.name, 'editor_icon': ["MemberProperty", "EditorIcons"]} + + return suggestions + + +static func get_audio_bus_suggestions(_filter:= "") -> Dictionary: + var bus_name_list := {} + for i in range(AudioServer.bus_count): + if i == 0: + bus_name_list[AudioServer.get_bus_name(i)] = {'value':''} + else: + bus_name_list[AudioServer.get_bus_name(i)] = {'value':AudioServer.get_bus_name(i)} + return bus_name_list + + +static func get_audio_channel_suggestions(_search_text:String) -> Dictionary: + var suggestions := {} + var channel_defaults := DialogicUtil.get_audio_channel_defaults() + var cached_names := DialogicResourceUtil.get_channel_list() + + for i in channel_defaults.keys(): + if not cached_names.has(i): + cached_names.append(i) + + cached_names.sort() + + for i in cached_names: + if i.is_empty(): + continue + + suggestions[i] = {'value': i} + + if i in channel_defaults.keys(): + suggestions[i]["editor_icon"] = ["ProjectList", "EditorIcons"] + suggestions[i]["tooltip"] = "A default channel defined in the settings." + + else: + suggestions[i]["editor_icon"] = ["AudioStreamPlayer", "EditorIcons"] + suggestions[i]["tooltip"] = "A temporary channel without defaults." + + return suggestions + + +static func get_audio_channel_defaults() -> Dictionary: + return ProjectSettings.get_setting('dialogic/audio/channel_defaults', { + "": { + 'volume': 0.0, + 'audio_bus': '', + 'fade_length': 0.0, + 'loop': false, + }, + "music": { + 'volume': 0.0, + 'audio_bus': '', + 'fade_length': 0.0, + 'loop': true, + }}) + + +static func validate_audio_channel_name(text: String) -> Dictionary: + var result := {} + var channel_name_regex := RegEx.create_from_string(r'(?^-$)|(?[^\w-]{1})') + var matches := channel_name_regex.search_all(text) + var invalid_chars := [] + + for regex_match in matches: + if regex_match.get_string('dash_only'): + result['error_tooltip'] = "Channel name cannot be '-'." + result['valid_text'] = '' + else: + var invalid_char = regex_match.get_string('invalid') + if not invalid_char in invalid_chars: + invalid_chars.append(invalid_char) + + if invalid_chars: + result['valid_text'] = channel_name_regex.sub(text, '', true) + result['error_tooltip'] = "Channel names cannot contain the following characters: " + "".join(invalid_chars) + + return result diff --git a/addons/dialogic/Core/DialogicUtil.gd.uid b/addons/dialogic/Core/DialogicUtil.gd.uid index d4616f56..a6c19002 100644 --- a/addons/dialogic/Core/DialogicUtil.gd.uid +++ b/addons/dialogic/Core/DialogicUtil.gd.uid @@ -1 +1 @@ -uid://7bp2a34fvy0d +uid://c848iwoo6mnms diff --git a/addons/dialogic/Core/Dialogic_Subsystem.gd.uid b/addons/dialogic/Core/Dialogic_Subsystem.gd.uid index f0c0ea76..f1010fa4 100644 --- a/addons/dialogic/Core/Dialogic_Subsystem.gd.uid +++ b/addons/dialogic/Core/Dialogic_Subsystem.gd.uid @@ -1 +1 @@ -uid://b7qj1lgysmwlc +uid://d4iojsqnbdphm diff --git a/addons/dialogic/Core/index_class.gd b/addons/dialogic/Core/index_class.gd index 30c8fa08..c6bd7c54 100644 --- a/addons/dialogic/Core/index_class.gd +++ b/addons/dialogic/Core/index_class.gd @@ -78,7 +78,7 @@ func list_dir(subdir:='') -> Array: func list_special_resources(subdir:='', extension:="") -> Dictionary: var dict := {} for i in list_dir(subdir): - if extension.is_empty() or i.ends_with(extension): + if extension.is_empty() or i.ends_with(extension) or (extension == ".gd" and i.ends_with(".gdc")): dict[DialogicUtil.pretty_name(i).to_lower()] = {"path":i} return dict diff --git a/addons/dialogic/Core/index_class.gd.uid b/addons/dialogic/Core/index_class.gd.uid index 513027c8..92c8db92 100644 --- a/addons/dialogic/Core/index_class.gd.uid +++ b/addons/dialogic/Core/index_class.gd.uid @@ -1 +1 @@ -uid://d06pvy04nmmby +uid://ciwsx3rjhhmg7 diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd.uid b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd.uid index 4144e52c..3ed27df4 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd.uid @@ -1 +1 @@ -uid://drwfgv17x3478 +uid://bcsda7vbawlgv diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.tscn b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.tscn index 6f0cc626..6b23ccdc 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.tscn +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://cfcs7lb6gqnmd"] -[ext_resource type="Script" uid="uid://drwfgv17x3478" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd" id="1_isys8"] +[ext_resource type="Script" uid="uid://bcsda7vbawlgv" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_exports.gd" id="1_isys8"] [node name="Settings" type="VBoxContainer"] custom_minimum_size = Vector2(0, 35) diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd index 03f4346e..2c92085d 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd @@ -10,13 +10,13 @@ func _get_title() -> String: func _load_portrait_data(data:Dictionary) -> void: %IgnoreScale.set_pressed_no_signal(data.get('ignore_char_scale', false)) - %PortraitScale.value = data.get('scale', 1.0)*100 + %PortraitScale.set_value(data.get('scale', 1.0)*100) %PortraitOffset.set_value(data.get('offset', Vector2())) %PortraitOffset._load_display_info({'step':1}) %PortraitMirror.set_pressed_no_signal(data.get('mirror', false)) -func _on_portrait_scale_value_changed(value:float) -> void: +func _on_portrait_scale_value_changed(_property:String, value:float) -> void: var data: Dictionary = selected_item.get_metadata(0) data['scale'] = value/100.0 update_preview.emit() @@ -37,7 +37,7 @@ func _on_ignore_scale_toggled(button_pressed:bool) -> void: changed.emit() -func _on_portrait_offset_value_changed(property:String, value:Vector2) -> void: +func _on_portrait_offset_value_changed(_property:String, value:Vector2) -> void: var data: Dictionary = selected_item.get_metadata(0) data['offset'] = value update_preview.emit() diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd.uid b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd.uid index a43c037e..4f28f277 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd.uid @@ -1 +1 @@ -uid://kq0tngakxiwn +uid://uv6dx3sofwae diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.tscn b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.tscn index 7b2d96f6..89121d90 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.tscn +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://crke8suvv52c6"] +[gd_scene load_steps=4 format=3 uid="uid://crke8suvv52c6"] -[ext_resource type="Script" uid="uid://kq0tngakxiwn" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd" id="1_76vf2"] +[ext_resource type="Script" uid="uid://uv6dx3sofwae" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_layout.gd" id="1_76vf2"] [ext_resource type="PackedScene" uid="uid://dtimnsj014cu" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn" id="2_c8kyi"] +[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="2_daw3l"] [node name="Layout" type="HFlowContainer"] offset_right = 428.0 @@ -25,13 +26,13 @@ layout_mode = 2 layout_mode = 2 text = "Scale:" -[node name="PortraitScale" type="SpinBox" parent="HBoxContainer"] +[node name="PortraitScale" parent="HBoxContainer" instance=ExtResource("2_daw3l")] unique_name_in_owner = true layout_mode = 2 -tooltip_text = "A scale to be applied on top of the main scale -(unless ignore main scale is pressed)." -value = 100.0 -allow_greater = true +mode = 1 +step = 1.0 +min_value = 0.0 +max_value = 100.0 suffix = "%" [node name="HBoxContainer2" type="HBoxContainer" parent="."] diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd.uid b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd.uid index 55b45c81..ca578289 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd.uid @@ -1 +1 @@ -uid://b2026s2q7x8d4 +uid://busjn8oo7kl1s diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.tscn b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.tscn index fd9ad53f..431f940c 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.tscn +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=6 format=3 uid="uid://djq4aasoihexj"] -[ext_resource type="Script" uid="uid://b2026s2q7x8d4" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd" id="1_ht8lu"] +[ext_resource type="Script" uid="uid://busjn8oo7kl1s" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main.gd" id="1_ht8lu"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="2_k8xs0"] [ext_resource type="PackedScene" uid="uid://b1wn8r84uh11b" path="res://addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.tscn" id="3_ngvgq"] diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd.uid b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd.uid index f94d2e2c..d21f2adf 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd.uid @@ -1 +1 @@ -uid://tmtk8wwimgxt +uid://cp0o6sycac85b diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.tscn b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.tscn index 1b5fc69d..98c290f0 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.tscn +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://ba5w02lm3ewkj"] -[ext_resource type="Script" uid="uid://tmtk8wwimgxt" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd" id="1_mttrr"] +[ext_resource type="Script" uid="uid://cp0o6sycac85b" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.gd" id="1_mttrr"] [node name="MainExports" type="VBoxContainer"] offset_right = 374.0 diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd.uid b/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd.uid index 33580e2c..3d1db094 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd.uid @@ -1 +1 @@ -uid://ckh08sqv1a081 +uid://c0nilv2pybryh diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.tscn b/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.tscn index 2a42ce7d..2ce41fe1 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.tscn +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_section_general.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://bnkck3hocbkk5"] -[ext_resource type="Script" uid="uid://ckh08sqv1a081" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd" id="1_3e1i1"] +[ext_resource type="Script" uid="uid://c0nilv2pybryh" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_section_general.gd" id="1_3e1i1"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_cxfqm"] [sub_resource type="Image" id="Image_ywoka"] diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd b/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd index 44f4ec37..127aa08a 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd @@ -19,7 +19,7 @@ func _ready() -> void: # Setting up Default Portrait Picker %DefaultPortraitPicker.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/portrait.svg") - %DefaultPortraitPicker.get_suggestions_func = suggest_portraits + %DefaultPortraitPicker.suggestions_func = suggest_portraits ## Make sure preview get's updated when portrait settings change @@ -33,7 +33,7 @@ func main_portrait_settings_update(_something=null, _value=null) -> void: character_editor.something_changed() -func default_portrait_changed(property:String, value:String) -> void: +func default_portrait_changed(_property:String, value:String) -> void: character_editor.current_resource.default_portrait = value character_editor.update_default_portrait_star(value) @@ -47,7 +47,7 @@ func _load_character(resource:DialogicCharacter) -> void: loading = true %DefaultPortraitPicker.set_value(resource.default_portrait) - %MainScale.value = 100*resource.scale + %MainScale.set_value(100*resource.scale) %MainOffset.set_value(resource.offset) %MainMirror.button_pressed = resource.mirror loading = false @@ -69,9 +69,8 @@ func _save_changes(resource:DialogicCharacter) -> DialogicCharacter: ## Get suggestions for DefaultPortraitPicker -func suggest_portraits(search:String) -> Dictionary: +func suggest_portraits(_search:String) -> Dictionary: var suggestions := {} for portrait in character_editor.get_updated_portrait_dict().keys(): suggestions[portrait] = {'value':portrait} return suggestions - diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd.uid b/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd.uid index bb3fc89e..b5a784f9 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd.uid @@ -1 +1 @@ -uid://0pki4ffx8ix4 +uid://yulfiomudcob diff --git a/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.tscn b/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.tscn index 9b7109ab..99bb34cf 100644 --- a/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.tscn +++ b/addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=4 format=3 uid="uid://cmrgbo8qi145o"] +[gd_scene load_steps=5 format=3 uid="uid://cmrgbo8qi145o"] -[ext_resource type="Script" uid="uid://0pki4ffx8ix4" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd" id="1_6sxsl"] +[ext_resource type="Script" uid="uid://yulfiomudcob" path="res://addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.gd" id="1_6sxsl"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="2_birla"] [ext_resource type="PackedScene" uid="uid://dtimnsj014cu" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn" id="3_vcvin"] +[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="4_w4pvv"] [node name="Portraits" type="GridContainer"] offset_right = 453.0 @@ -29,8 +30,9 @@ layout_mode = 2 size_flags_vertical = 0 text = "Main Scale" -[node name="MainScale" type="SpinBox" parent="."] +[node name="MainScaleOld" type="SpinBox" parent="."] unique_name_in_owner = true +visible = false layout_mode = 2 size_flags_horizontal = 8 value = 100.0 @@ -38,6 +40,16 @@ allow_greater = true alignment = 1 suffix = "%" +[node name="MainScale" parent="." instance=ExtResource("4_w4pvv")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 8 +mode = 1 +step = 1.0 +min_value = 0.0 +max_value = 100.0 +suffix = "%" + [node name="Label2" type="Label" parent="."] layout_mode = 2 size_flags_vertical = 0 diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd b/addons/dialogic/Editor/CharacterEditor/character_editor.gd index 47b9a677..3233674a 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd @@ -71,9 +71,9 @@ func _open_resource(resource:Resource) -> void: load_portrait_tree() loading = false - character_loaded.emit(resource.resource_path) + character_loaded.emit(current_resource.resource_path) - %CharacterName.text = DialogicResourceUtil.get_unique_identifier(resource.resource_path) + %CharacterName.text = current_resource.get_identifier() $NoCharacterScreen.hide() %PortraitChangeInfo.hide() @@ -119,6 +119,9 @@ func _save() -> void: ## Saves a new empty character to the given path func new_character(path: String) -> void: + if not path.ends_with(".dch"): + path = path.trim_suffix(".") + path += ".dch" var resource := DialogicCharacter.new() resource.resource_path = path resource.display_name = path.get_file().trim_suffix("."+path.get_extension()) @@ -165,6 +168,7 @@ func _ready() -> void: ## Add general tabs add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_section_general.tscn").instantiate(), %MainSettingsSections) add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_section_portraits.tscn").instantiate(), %MainSettingsSections) + add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.tscn").instantiate(), %MainSettingsSections) add_settings_section(load("res://addons/dialogic/Editor/CharacterEditor/char_edit_p_section_main_exports.tscn").instantiate(), %PortraitSettingsSection) @@ -188,10 +192,12 @@ func _ready() -> void: func add_settings_section(edit:Control, parent:Node) -> void: edit.changed.connect(something_changed) edit.character_editor = self + if edit.has_signal('update_preview'): edit.update_preview.connect(update_preview) var button: Button + if edit._show_title(): var hbox := HBoxContainer.new() hbox.name = edit._get_title()+"BOX" @@ -365,7 +371,7 @@ func add_portrait(portrait_name:String='New portrait', portrait_data:Dictionary= 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'): + if %PortraitTree.get_selected() and %PortraitTree.get_selected().get_metadata(0) and %PortraitTree.get_selected().get_metadata(0).has('group'): parent_item = %PortraitTree.get_selected() var item: TreeItem = %PortraitTree.add_portrait_group("Group", parent_item) item.set_meta('new', true) @@ -543,7 +549,7 @@ func report_name_change(item: TreeItem) -> void: editors_manager.reference_manager.add_portrait_ref_change( item.get_meta('previous_name'), %PortraitTree.get_full_item_name(item), - [DialogicResourceUtil.get_unique_identifier(current_resource.resource_path)]) + [current_resource.get_identifier()]) item.set_meta('previous_name', %PortraitTree.get_full_item_name(item)) %PortraitChangeInfo.show() diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.gd.uid b/addons/dialogic/Editor/CharacterEditor/character_editor.gd.uid index cbd21699..4997d860 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.gd.uid @@ -1 +1 @@ -uid://b05ouwe0s28rb +uid://cwhe7tpe75oh7 diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn index a402b690..49fc117b 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor.tscn +++ b/addons/dialogic/Editor/CharacterEditor/character_editor.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=11 format=3 uid="uid://dlskc36c5hrwv"] -[ext_resource type="Script" uid="uid://b05ouwe0s28rb" path="res://addons/dialogic/Editor/CharacterEditor/character_editor.gd" id="2"] +[ext_resource type="Script" uid="uid://cwhe7tpe75oh7" path="res://addons/dialogic/Editor/CharacterEditor/character_editor.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_uhhqs"] -[ext_resource type="Script" uid="uid://b0elpsugbconk" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd" id="2_vad0i"] +[ext_resource type="Script" uid="uid://deliic6d8vajo" path="res://addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd" id="2_vad0i"] [ext_resource type="Texture2D" uid="uid://babwe22dqjta" path="res://addons/dialogic/Editor/Images/Pieces/add-folder.svg" id="3_v1qnr"] [sub_resource type="Image" id="Image_r5ayh"] diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd b/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd index d329d065..55253f35 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd @@ -5,6 +5,7 @@ extends Control ## Base class for all character editor main sections. Methods should be overriden. ## Emit this, if something changed +@warning_ignore("unused_signal") # this is used by extending scripts signal changed ## Reference to the character editor, set when instantiated @@ -30,7 +31,7 @@ func _start_opened() -> bool: ## Overwrite to load all the information from the character into this section. -func _load_character(resource:DialogicCharacter) -> void: +func _load_character(_resource:DialogicCharacter) -> void: pass diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd.uid b/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd.uid index 7c4948c9..bc894212 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_main_settings_section.gd.uid @@ -1 +1 @@ -uid://cm0wi5jwnqitc +uid://wltbab3qq63b diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_section.gd.uid b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_section.gd.uid index 77c29668..00679388 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_section.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_settings_section.gd.uid @@ -1 +1 @@ -uid://d11n63mblxvlw +uid://ckblurnjla80i diff --git a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd.uid b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd.uid index 094b9722..9f24a8c6 100644 --- a/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/character_editor_portrait_tree.gd.uid @@ -1 +1 @@ -uid://b0elpsugbconk +uid://deliic6d8vajo diff --git a/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd b/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd new file mode 100644 index 00000000..6c54255c --- /dev/null +++ b/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd @@ -0,0 +1,79 @@ +@tool +class_name DialogicCharacterPrefixSuffixSection +extends DialogicCharacterEditorMainSection +## Character Editor Section for setting the prefix and suffix of a character. +## +## loads and sets the prefix and suffix of a character. +## Provides [const PREFIX_CUSTOM_KEY] and [const SUFFIX_CUSTOM_KEY] to +## access the `custom_info` dictionary of the [class DialogicCharacter]. + +@export var prefix_input: LineEdit +@export var suffix_input: LineEdit + +## We won't force any prefixes or suffixes onto the player, +## to ensure their games are working as previously when updating. +const DEFAULT_PREFIX = "" +const DEFAULT_SUFFIX = "" + +## `custom_info` dictionary keys for the prefix. +const PREFIX_CUSTOM_KEY = "prefix" + +## `custom_info` dictionary keys for the prefix. +const SUFFIX_CUSTOM_KEY = "suffix" + +var suffix := "" +var prefix := "" + + +func _ready() -> void: + suffix_input.text_changed.connect(_suffix_changed) + prefix_input.text_changed.connect(_prefix_changed) + + +func _suffix_changed(text: String) -> void: + suffix = text + + +func _prefix_changed(text: String) -> void: + prefix = text + + +func _get_title() -> String: + return "Character Prefix & Suffix" + + +func _show_title() -> bool: + return true + + +func _start_opened() -> bool: + return false + + +func _load_portrait_data(portrait_data: Dictionary) -> void: + _load_prefix_data(portrait_data) + + +## We load the prefix and suffix from the character's `custom_info` dictionary. +func _load_character(resource: DialogicCharacter) -> void: + _load_prefix_data(resource.custom_info) + + +func _load_prefix_data(data: Dictionary) -> void: + suffix = data.get(SUFFIX_CUSTOM_KEY, DEFAULT_SUFFIX) + prefix = data.get(PREFIX_CUSTOM_KEY, DEFAULT_PREFIX) + + suffix_input.text = suffix + prefix_input.text = prefix + + +## Whenever the user makes a save to the character, we save the prefix and suffix. +func _save_changes(character: DialogicCharacter) -> DialogicCharacter: + if not character: + printerr("[Dialogic] Unable to save Prefix and Suffix, the character is missing.") + return character + + character.custom_info[PREFIX_CUSTOM_KEY] = prefix + character.custom_info[SUFFIX_CUSTOM_KEY] = suffix + + return character diff --git a/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd.uid b/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd.uid new file mode 100644 index 00000000..7a3aeb70 --- /dev/null +++ b/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd.uid @@ -0,0 +1 @@ +uid://i1ujoar8jf80 diff --git a/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.tscn b/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.tscn new file mode 100644 index 00000000..2ab9c95e --- /dev/null +++ b/addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.tscn @@ -0,0 +1,48 @@ +[gd_scene load_steps=3 format=3 uid="uid://1ctcs6ywjjtd"] + +[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="1_o3alv"] +[ext_resource type="Script" uid="uid://i1ujoar8jf80" path="res://addons/dialogic/Editor/CharacterEditor/character_prefix_suffix.gd" id="1_tkxff"] + +[node name="CharacterPrefixSuffix" type="GridContainer" node_paths=PackedStringArray("prefix_input", "suffix_input")] +offset_right = 121.0 +offset_bottom = 66.0 +columns = 2 +script = ExtResource("1_tkxff") +prefix_input = NodePath("PrefixInput") +suffix_input = NodePath("SuffixInput") + +[node name="Prefix" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="Prefix"] +layout_mode = 2 +text = "Prefix" + +[node name="HintTooltip" parent="Prefix" instance=ExtResource("1_o3alv")] +layout_mode = 2 +texture = null +hint_text = "If a character speaks, this appears before their text. +Example: Color Tags or Quotation Marks." + +[node name="PrefixInput" type="LineEdit" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +caret_blink = true + +[node name="Suffix" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="Suffix"] +layout_mode = 2 +text = "Suffix" + +[node name="HintTooltip" parent="Suffix" instance=ExtResource("1_o3alv")] +layout_mode = 2 +texture = null +hint_text = "If a character speaks, this appears after their text. +Example: Color Tags or Quotation Marks." + +[node name="SuffixInput" type="LineEdit" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +caret_blink = true diff --git a/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd.uid b/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd.uid index 9aae505a..f8b8094b 100644 --- a/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd.uid +++ b/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd.uid @@ -1 +1 @@ -uid://duj68ruvoapq0 +uid://iwv7qff6g0f0 diff --git a/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.tscn b/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.tscn index fbd40f12..f760591e 100644 --- a/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.tscn +++ b/addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=11 format=3 uid="uid://b1wn8r84uh11b"] -[ext_resource type="Script" uid="uid://duj68ruvoapq0" path="res://addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd" id="1_an6nc"] +[ext_resource type="Script" uid="uid://iwv7qff6g0f0" path="res://addons/dialogic/Editor/CharacterEditor/portrait_scene_browser.gd" id="1_an6nc"] [sub_resource type="Gradient" id="Gradient_0o1u0"] colors = PackedColorArray(0.100572, 0.303996, 0.476999, 1, 0.296448, 0.231485, 0.52887, 1) diff --git a/addons/dialogic/Editor/Common/BrowserItem.gd.uid b/addons/dialogic/Editor/Common/BrowserItem.gd.uid index 8d79397a..6dc7cc1d 100644 --- a/addons/dialogic/Editor/Common/BrowserItem.gd.uid +++ b/addons/dialogic/Editor/Common/BrowserItem.gd.uid @@ -1 +1 @@ -uid://convbgmij84l4 +uid://ckthmmkodqqwt diff --git a/addons/dialogic/Editor/Common/BrowserItem.tscn b/addons/dialogic/Editor/Common/BrowserItem.tscn index 000b311d..8d47d20e 100644 --- a/addons/dialogic/Editor/Common/BrowserItem.tscn +++ b/addons/dialogic/Editor/Common/BrowserItem.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=6 format=3 uid="uid://ddlxjde1cx035"] -[ext_resource type="Script" uid="uid://convbgmij84l4" path="res://addons/dialogic/Editor/Common/BrowserItem.gd" id="1_s3kf0"] +[ext_resource type="Script" uid="uid://ckthmmkodqqwt" path="res://addons/dialogic/Editor/Common/BrowserItem.gd" id="1_s3kf0"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_pfw08"] bg_color = Color(1, 1, 1, 0.32549) diff --git a/addons/dialogic/Editor/Common/DCSS.gd.uid b/addons/dialogic/Editor/Common/DCSS.gd.uid index dbf2b532..6f4fa145 100644 --- a/addons/dialogic/Editor/Common/DCSS.gd.uid +++ b/addons/dialogic/Editor/Common/DCSS.gd.uid @@ -1 +1 @@ -uid://cebtnppbckjw0 +uid://m3ufop8ao16l diff --git a/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd b/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd index 22626199..7d3f355e 100644 --- a/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd +++ b/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd @@ -11,7 +11,7 @@ var item: TreeItem = null func _ready() -> void: hide() %Character.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/character.svg") - %Character.get_suggestions_func = get_character_suggestions + %Character.suggestions_func = get_character_suggestions %WholeWords.icon = get_theme_icon("FontItem", "EditorIcons") %MatchCase.icon = get_theme_icon("MatchCase", "EditorIcons") @@ -52,6 +52,9 @@ func open_existing(_item:TreeItem, info:Dictionary): %Old.text = info.what %New.text = info.forwhat + %MatchCase.button_pressed = info.case_sensitive + %WholeWords.button_pressed = info.whole_words + func _on_type_item_selected(index:int) -> void: match index: 0: diff --git a/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd.uid b/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd.uid index 900b7d6e..6b38dc43 100644 --- a/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd.uid +++ b/addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd.uid @@ -1 +1 @@ -uid://dx58wywm7min8 +uid://dca6a1a74jfur diff --git a/addons/dialogic/Editor/Common/broken_reference_manager.gd b/addons/dialogic/Editor/Common/broken_reference_manager.gd index b0d11cc3..5113c540 100644 --- a/addons/dialogic/Editor/Common/broken_reference_manager.gd +++ b/addons/dialogic/Editor/Common/broken_reference_manager.gd @@ -158,6 +158,8 @@ func display_search_results(finds:Array[Dictionary]) -> void: %ReferenceTree.clear() %ReferenceTree.set_column_expand(0, false) + %ReferenceTree.set_column_expand(1, false) + %ReferenceTree.set_column_custom_minimum_width(1, 50) %ReferenceTree.create_item() var timelines := {} @@ -166,20 +168,25 @@ func display_search_results(finds:Array[Dictionary]) -> void: var parent: TreeItem = null if !i.timeline in timelines: parent = %ReferenceTree.create_item() - parent.set_text(1, i.timeline) - parent.set_custom_color(1, get_theme_color("disabled_font_color", "Editor")) + parent.set_text(0, i.timeline) + parent.set_custom_color(0, get_theme_color("disabled_font_color", "Editor")) + parent.set_expand_right(0, true) timelines[i.timeline] = parent height += %ReferenceTree.get_item_area_rect(parent).size.y+10 else: parent = timelines[i.timeline] var item: TreeItem = %ReferenceTree.create_item(parent) - item.set_text(1, 'Line '+str(i.line_number)+': '+i.line) - item.set_tooltip_text(1, i.info.what+' -> '+i.info.forwhat) item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK) item.set_checked(0, true) item.set_editable(0, true) item.set_metadata(0, i) + item.set_text(1, str(i.line_number)+':') + item.set_text_alignment(1, HORIZONTAL_ALIGNMENT_RIGHT) + item.set_cell_mode(2, TreeItem.CELL_MODE_CUSTOM) + item.set_text(2, i.line) + item.set_tooltip_text(2, i.info.what+' -> '+i.info.forwhat) + item.set_custom_draw_callback(2, _custom_draw) height += %ReferenceTree.get_item_area_rect(item).size.y+10 var change_item: TreeItem = i.info.item change_item.set_meta('found_items', change_item.get_meta('found_items', [])+[item]) @@ -194,6 +201,27 @@ func display_search_results(finds:Array[Dictionary]) -> void: %Replace.grab_focus() +## Highlights the found text in the result tree +## Inspired by how godot highlights stuff in its search results +func _custom_draw(item:TreeItem, rect:Rect2) -> void: + var text := item.get_text(2) + var find: Dictionary = item.get_metadata(0) + + var font: Font = %ReferenceTree.get_theme_font("font") + var font_size: int = %ReferenceTree.get_theme_font_size("font_size") + + var match_rect := rect + var beginning_index: int = find.match.get_start("replace")-find.line_start-1 + match_rect.position.x += font.get_string_size(text.left(beginning_index), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x -1 + match_rect.size.x = font.get_string_size(find.info.what, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).x + 1 + match_rect.position.y += 1 * DialogicUtil.get_editor_scale() + match_rect.size.y -= 2 * DialogicUtil.get_editor_scale() + match_rect.position.x += 4 + + %ReferenceTree.draw_rect(match_rect, get_theme_color("highlight_color", "Editor"), true) + %ReferenceTree.draw_rect(match_rect, get_theme_color("box_selection_stroke_color", "Editor"), false) + + func search_timelines(regexes:Array[Array]) -> Array[Dictionary]: var finds: Array[Dictionary] = [] diff --git a/addons/dialogic/Editor/Common/broken_reference_manager.gd.uid b/addons/dialogic/Editor/Common/broken_reference_manager.gd.uid index c33998c2..c18902bf 100644 --- a/addons/dialogic/Editor/Common/broken_reference_manager.gd.uid +++ b/addons/dialogic/Editor/Common/broken_reference_manager.gd.uid @@ -1 +1 @@ -uid://cxy2bedubs15y +uid://nrhtjk2rgmgk diff --git a/addons/dialogic/Editor/Common/hint_tooltip_icon.gd.uid b/addons/dialogic/Editor/Common/hint_tooltip_icon.gd.uid index e7b2114a..9aeec68f 100644 --- a/addons/dialogic/Editor/Common/hint_tooltip_icon.gd.uid +++ b/addons/dialogic/Editor/Common/hint_tooltip_icon.gd.uid @@ -1 +1 @@ -uid://b4bvwxge5p8qs +uid://b0vm440bs3ckd diff --git a/addons/dialogic/Editor/Common/hint_tooltip_icon.tscn b/addons/dialogic/Editor/Common/hint_tooltip_icon.tscn index a3950f07..b12c0580 100644 --- a/addons/dialogic/Editor/Common/hint_tooltip_icon.tscn +++ b/addons/dialogic/Editor/Common/hint_tooltip_icon.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=3 uid="uid://dbpkta2tjsqim"] -[ext_resource type="Script" uid="uid://b4bvwxge5p8qs" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.gd" id="1_x8t45"] +[ext_resource type="Script" uid="uid://b0vm440bs3ckd" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.gd" id="1_x8t45"] [sub_resource type="Image" id="Image_c5s34"] data = { @@ -11,11 +11,11 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_lseut"] +[sub_resource type="ImageTexture" id="ImageTexture_ydy7j"] image = SubResource("Image_c5s34") [node name="HintTooltip" type="TextureRect"] modulate = Color(0, 0, 0, 1) -texture = SubResource("ImageTexture_lseut") +texture = SubResource("ImageTexture_ydy7j") stretch_mode = 3 script = ExtResource("1_x8t45") diff --git a/addons/dialogic/Editor/Common/reference_manager.gd.uid b/addons/dialogic/Editor/Common/reference_manager.gd.uid index 84d27fa3..566b3ece 100644 --- a/addons/dialogic/Editor/Common/reference_manager.gd.uid +++ b/addons/dialogic/Editor/Common/reference_manager.gd.uid @@ -1 +1 @@ -uid://d1163xkcv1c8w +uid://dugy11ebty3yq diff --git a/addons/dialogic/Editor/Common/reference_manager.tscn b/addons/dialogic/Editor/Common/reference_manager.tscn index a973d178..3154a38b 100644 --- a/addons/dialogic/Editor/Common/reference_manager.tscn +++ b/addons/dialogic/Editor/Common/reference_manager.tscn @@ -1,14 +1,15 @@ -[gd_scene load_steps=13 format=3 uid="uid://c7lmt5cp7bxcm"] +[gd_scene load_steps=14 format=3 uid="uid://c7lmt5cp7bxcm"] -[ext_resource type="Script" uid="uid://d1163xkcv1c8w" path="res://addons/dialogic/Editor/Common/reference_manager.gd" id="1_3t531"] -[ext_resource type="Script" uid="uid://cxy2bedubs15y" path="res://addons/dialogic/Editor/Common/broken_reference_manager.gd" id="1_agmg4"] -[ext_resource type="Script" uid="uid://dx58wywm7min8" path="res://addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd" id="2_tt4jd"] +[ext_resource type="Script" uid="uid://dugy11ebty3yq" path="res://addons/dialogic/Editor/Common/reference_manager.gd" id="1_3t531"] +[ext_resource type="Script" uid="uid://nrhtjk2rgmgk" path="res://addons/dialogic/Editor/Common/broken_reference_manager.gd" id="1_agmg4"] +[ext_resource type="Script" uid="uid://dca6a1a74jfur" path="res://addons/dialogic/Editor/Common/ReferenceManager_AddReplacementPanel.gd" id="2_tt4jd"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3_yomsc"] -[ext_resource type="Script" uid="uid://dwkxd7m2p2lkj" path="res://addons/dialogic/Editor/Common/unique_identifiers_manager.gd" id="5_wnvbq"] +[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="5_sdymt"] +[ext_resource type="Script" uid="uid://bvbsqai5sh0na" path="res://addons/dialogic/Editor/Common/unique_identifiers_manager.gd" id="5_wnvbq"] [sub_resource type="ButtonGroup" id="ButtonGroup_l6uiy"] -[sub_resource type="Image" id="Image_n016d"] +[sub_resource type="Image" id="Image_pnutm"] data = { "data": PackedByteArray(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, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 255, 255, 255, 0, 255, 255, 255, 0, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 224, 224, 224, 255, 224, 224, 224, 255, 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, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), "format": "RGBA8", @@ -18,18 +19,6 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_a0gfq"] -image = SubResource("Image_n016d") - -[sub_resource type="Image" id="Image_pnutm"] -data = { -"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_mr0fw"] image = SubResource("Image_pnutm") [sub_resource type="Image" id="Image_asrh0"] @@ -41,9 +30,21 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_lce2m"] +[sub_resource type="ImageTexture" id="ImageTexture_2hc6a"] image = SubResource("Image_asrh0") +[sub_resource type="Image" id="Image_xvpjt"] +data = { +"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_lce2m"] +image = SubResource("Image_xvpjt") + [node name="Manager" type="PanelContainer"] anchors_preset = 15 anchor_right = 1.0 @@ -119,11 +120,10 @@ layout_mode = 2 [node name="Type" type="OptionButton" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer3"] unique_name_in_owner = true layout_mode = 2 -tooltip_text = "This decides the regexes for searching. Pure text allows you to enter your own regex into into \"Old\". " -item_count = 5 +tooltip_text = "This decides the regexes for searching. Pure text allows you to enter your own regex into \"Old\". " selected = 0 +item_count = 5 popup/item_0/text = "Pure Text" -popup/item_0/id = 0 popup/item_1/text = "Variable" popup/item_1/id = 1 popup/item_2/text = "Portrait" @@ -163,14 +163,14 @@ unique_name_in_owner = true layout_mode = 2 tooltip_text = "Match Case" toggle_mode = true -icon = SubResource("ImageTexture_mr0fw") +icon = SubResource("ImageTexture_2hc6a") [node name="WholeWords" type="Button" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/PureTextFlags"] unique_name_in_owner = true layout_mode = 2 tooltip_text = "Whole World" toggle_mode = true -icon = SubResource("ImageTexture_mr0fw") +icon = SubResource("ImageTexture_2hc6a") [node name="HBoxContainer4" type="HBoxContainer" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox"] layout_mode = 2 @@ -178,11 +178,10 @@ layout_mode = 2 [node name="Where" type="OptionButton" parent="Tabs/BrokenReferences/ChangesList/VBox/ReplacementEditPanel/VBox/HBoxContainer4"] unique_name_in_owner = true layout_mode = 2 -item_count = 3 selected = 0 fit_to_longest_item = false +item_count = 3 popup/item_0/text = "Everywhere" -popup/item_0/id = 0 popup/item_1/text = "Only for Character" popup/item_1/id = 1 popup/item_2/text = "Texts only" @@ -247,7 +246,7 @@ unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 3 theme_override_constants/draw_relationship_lines = 1 -columns = 2 +columns = 3 hide_root = true [node name="Progress" type="ProgressBar" parent="Tabs/BrokenReferences/ReplacementSection/FindList"] @@ -255,7 +254,11 @@ unique_name_in_owner = true layout_mode = 2 max_value = 1.0 -[node name="Replace" type="Button" parent="Tabs/BrokenReferences/ReplacementSection/FindList"] +[node name="HBoxContainer" type="HBoxContainer" parent="Tabs/BrokenReferences/ReplacementSection/FindList"] +layout_mode = 2 +alignment = 1 + +[node name="Replace" type="Button" parent="Tabs/BrokenReferences/ReplacementSection/FindList/HBoxContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 4 @@ -263,6 +266,12 @@ tooltip_text = "Replace all selected findings (Careful, no undo!)" text = "Replace Selected" icon = SubResource("ImageTexture_lce2m") +[node name="HintTooltip" parent="Tabs/BrokenReferences/ReplacementSection/FindList/HBoxContainer" instance=ExtResource("5_sdymt")] +layout_mode = 2 +texture = null +hint_text = "Note that searching and replacing is only implemented for timelines. +E.g. variables used in character display names or glossary entries will have to be replaced manually." + [node name="UniqueIdentifiers" type="PanelContainer" parent="Tabs"] visible = false layout_mode = 2 @@ -317,7 +326,7 @@ uri = "https://docs.dialogic.pro/reference-manager.html" [connection signal="button_clicked" from="Tabs/BrokenReferences/ChangesList/VBox/ChangeTree" to="Tabs/BrokenReferences" method="_on_change_tree_button_clicked"] [connection signal="item_edited" from="Tabs/BrokenReferences/ChangesList/VBox/ChangeTree" to="Tabs/BrokenReferences" method="_on_change_tree_item_edited"] [connection signal="pressed" from="Tabs/BrokenReferences/ChangesList/VBox/CheckButton" to="Tabs/BrokenReferences" method="_on_check_button_pressed"] -[connection signal="pressed" from="Tabs/BrokenReferences/ReplacementSection/FindList/Replace" to="Tabs/BrokenReferences" method="_on_replace_pressed"] +[connection signal="pressed" from="Tabs/BrokenReferences/ReplacementSection/FindList/HBoxContainer/Replace" to="Tabs/BrokenReferences" method="_on_replace_pressed"] [connection signal="text_changed" from="Tabs/UniqueIdentifiers/VBox/Tools/Search" to="Tabs/UniqueIdentifiers" method="_on_search_text_changed"] [connection signal="button_clicked" from="Tabs/UniqueIdentifiers/VBox/IdentifierTable" to="Tabs/UniqueIdentifiers" method="_on_identifier_table_button_clicked"] [connection signal="item_edited" from="Tabs/UniqueIdentifiers/VBox/IdentifierTable" to="Tabs/UniqueIdentifiers" method="_on_identifier_table_item_edited"] diff --git a/addons/dialogic/Editor/Common/reference_manager_window.gd b/addons/dialogic/Editor/Common/reference_manager_window.gd index 7bb42ec7..c8d85815 100644 --- a/addons/dialogic/Editor/Common/reference_manager_window.gd +++ b/addons/dialogic/Editor/Common/reference_manager_window.gd @@ -111,7 +111,9 @@ func add_ref_change(old_name:String, new_name:String, type:Types, where:=Where.T 'category':category_name, 'character_names':character_names, 'texts_only':where == Where.TEXTS_ONLY, - 'type':type + 'type':type, + 'case_sensitive':case_sensitive, + 'whole_words':whole_words, }) update_indicator() @@ -161,7 +163,6 @@ func open() -> void: DialogicResourceUtil.update_directory('dch') DialogicResourceUtil.update_directory('dtl') popup_centered_ratio(0.5) - move_to_foreground() grab_focus() @@ -170,6 +171,10 @@ func _on_close_requested() -> void: broken_manager.close() +func get_change_count() -> int: + return len(broken_manager.reference_changes) + + func update_indicator() -> void: icon_button.get_child(0).visible = !broken_manager.reference_changes.is_empty() diff --git a/addons/dialogic/Editor/Common/reference_manager_window.gd.uid b/addons/dialogic/Editor/Common/reference_manager_window.gd.uid index 32e59519..90b9f2f2 100644 --- a/addons/dialogic/Editor/Common/reference_manager_window.gd.uid +++ b/addons/dialogic/Editor/Common/reference_manager_window.gd.uid @@ -1 +1 @@ -uid://bwsjqnvqt6dp2 +uid://bxr2qomm7wm85 diff --git a/addons/dialogic/Editor/Common/side_bar.tscn b/addons/dialogic/Editor/Common/side_bar.tscn index df9ef3e2..1950d70e 100644 --- a/addons/dialogic/Editor/Common/side_bar.tscn +++ b/addons/dialogic/Editor/Common/side_bar.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=7 format=3 uid="uid://cwe3r2tbh2og1"] -[ext_resource type="Script" uid="uid://lwjkgosd1r60" path="res://addons/dialogic/Editor/Common/sidebar.gd" id="1_jnq65"] +[ext_resource type="Script" uid="uid://myogqmakusx3" path="res://addons/dialogic/Editor/Common/sidebar.gd" id="1_jnq65"] [ext_resource type="Texture2D" uid="uid://bff65e82555qr" path="res://addons/dialogic/Editor/Images/Pieces/close-icon.svg" id="2_54pks"] [ext_resource type="Texture2D" uid="uid://dx3o2ild56i76" path="res://addons/dialogic/Editor/Images/Pieces/closed-icon.svg" id="2_ilyps"] diff --git a/addons/dialogic/Editor/Common/sidebar.gd b/addons/dialogic/Editor/Common/sidebar.gd index a4755f77..dd328f5a 100644 --- a/addons/dialogic/Editor/Common/sidebar.gd +++ b/addons/dialogic/Editor/Common/sidebar.gd @@ -168,7 +168,7 @@ func update_resource_list(resources_list: PackedStringArray = []) -> void: resource_tree.clear() var character_items: Array = get_directory_items.call(character_directory, filter, load("res://addons/dialogic/Editor/Images/Resources/character.svg"), resources_list) - var timeline_items: Array = get_directory_items.call(timeline_directory, filter, get_theme_icon("TripleBar", "EditorIcons"), resources_list) + var timeline_items: Array = get_directory_items.call(timeline_directory, filter, load("res://addons/dialogic/Editor/Images/Resources/timeline.svg"), resources_list) var all_items := character_items + timeline_items # BUILD TREE @@ -391,7 +391,7 @@ func _on_resources_tree_item_clicked(_pos: Vector2, mouse_button_index: int) -> func _on_resources_tree_item_collapsed(item:TreeItem) -> void: - var collapsed_info := DialogicUtil.get_editor_setting("resource_list_collapsed_info", []) + var collapsed_info: Array = DialogicUtil.get_editor_setting("resource_list_collapsed_info", []) if item.get_text(0) in collapsed_info: if not item.collapsed: collapsed_info.erase(item.get_text(0)) @@ -433,7 +433,7 @@ func _on_right_click_menu_id_pressed(id: int) -> void: ) 4: # COPY IDENTIFIER DisplayServer.clipboard_set( - DialogicResourceUtil.get_unique_identifier( + DialogicResourceUtil.get_unique_identifier_by_path( %RightClickMenu.get_meta("item_clicked").get_metadata(0) ) ) diff --git a/addons/dialogic/Editor/Common/sidebar.gd.uid b/addons/dialogic/Editor/Common/sidebar.gd.uid index 54f13224..f6953527 100644 --- a/addons/dialogic/Editor/Common/sidebar.gd.uid +++ b/addons/dialogic/Editor/Common/sidebar.gd.uid @@ -1 +1 @@ -uid://lwjkgosd1r60 +uid://myogqmakusx3 diff --git a/addons/dialogic/Editor/Common/toolbar.gd b/addons/dialogic/Editor/Common/toolbar.gd index e49c1ea0..e4658d3c 100644 --- a/addons/dialogic/Editor/Common/toolbar.gd +++ b/addons/dialogic/Editor/Common/toolbar.gd @@ -4,7 +4,7 @@ extends HBoxContainer # Dialogic Editor toolbar. Works together with editors_mangager. ################################################################################ -## EDITOR BUTTONS/LABELS +## EDITOR BUTTONS/LABELS ################################################################################ func _ready() -> void: if owner.get_parent() is SubViewport: @@ -44,6 +44,3 @@ func add_custom_button(label:String, icon:Texture) -> Button: func hide_all_custom_buttons() -> void: for button in %CustomButtons.get_children(): button.hide() - - - diff --git a/addons/dialogic/Editor/Common/toolbar.gd.uid b/addons/dialogic/Editor/Common/toolbar.gd.uid index 0e393c14..6bebec89 100644 --- a/addons/dialogic/Editor/Common/toolbar.gd.uid +++ b/addons/dialogic/Editor/Common/toolbar.gd.uid @@ -1 +1 @@ -uid://ckucbhl6k6w3r +uid://1m3sqaws1hin diff --git a/addons/dialogic/Editor/Common/unique_identifiers_manager.gd.uid b/addons/dialogic/Editor/Common/unique_identifiers_manager.gd.uid index 40ebc7eb..50b0d67d 100644 --- a/addons/dialogic/Editor/Common/unique_identifiers_manager.gd.uid +++ b/addons/dialogic/Editor/Common/unique_identifiers_manager.gd.uid @@ -1 +1 @@ -uid://dwkxd7m2p2lkj +uid://bvbsqai5sh0na diff --git a/addons/dialogic/Editor/Common/update_install_window.gd b/addons/dialogic/Editor/Common/update_install_window.gd index f1c659d1..128c62ee 100644 --- a/addons/dialogic/Editor/Common/update_install_window.gd +++ b/addons/dialogic/Editor/Common/update_install_window.gd @@ -19,7 +19,6 @@ func _ready() -> void: func open() -> void: get_parent().popup_centered_ratio(0.5) get_parent().mode = Window.MODE_WINDOWED - get_parent().move_to_foreground() get_parent().grab_focus() @@ -108,7 +107,7 @@ func _on_update_manager_downdload_completed(result:int): func _on_resources_reimported(resources:Array) -> void: if is_inside_tree(): await get_tree().process_frame - get_parent().move_to_foreground() + get_parent().grab_focus() func markdown_to_bbcode(text:String) -> String: diff --git a/addons/dialogic/Editor/Common/update_install_window.gd.uid b/addons/dialogic/Editor/Common/update_install_window.gd.uid index a1261b6d..4964b439 100644 --- a/addons/dialogic/Editor/Common/update_install_window.gd.uid +++ b/addons/dialogic/Editor/Common/update_install_window.gd.uid @@ -1 +1 @@ -uid://db4gl62lskryf +uid://cskkip1wso0pu diff --git a/addons/dialogic/Editor/Common/update_install_window.tscn b/addons/dialogic/Editor/Common/update_install_window.tscn index 362e2220..58186dbc 100644 --- a/addons/dialogic/Editor/Common/update_install_window.tscn +++ b/addons/dialogic/Editor/Common/update_install_window.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=9 format=3 uid="uid://vv3m5m68fwg7"] -[ext_resource type="Script" uid="uid://db4gl62lskryf" path="res://addons/dialogic/Editor/Common/update_install_window.gd" id="1_p1pbx"] +[ext_resource type="Script" uid="uid://cskkip1wso0pu" path="res://addons/dialogic/Editor/Common/update_install_window.gd" id="1_p1pbx"] [ext_resource type="Texture2D" uid="uid://dybg3l5pwetne" path="res://addons/dialogic/Editor/Images/plugin-icon.svg" id="2_20ke0"] [sub_resource type="Gradient" id="Gradient_lt7uf"] diff --git a/addons/dialogic/Editor/Common/update_manager.gd.uid b/addons/dialogic/Editor/Common/update_manager.gd.uid index d5fafb17..c6e01cf9 100644 --- a/addons/dialogic/Editor/Common/update_manager.gd.uid +++ b/addons/dialogic/Editor/Common/update_manager.gd.uid @@ -1 +1 @@ -uid://dm3a08uuk04ky +uid://1tph6ios6ry2 diff --git a/addons/dialogic/Editor/Events/BranchEnd.gd.uid b/addons/dialogic/Editor/Events/BranchEnd.gd.uid index 0fc1fa93..f190a6cc 100644 --- a/addons/dialogic/Editor/Events/BranchEnd.gd.uid +++ b/addons/dialogic/Editor/Events/BranchEnd.gd.uid @@ -1 +1 @@ -uid://bbcblody1vn3k +uid://cyjmcay08lmr8 diff --git a/addons/dialogic/Editor/Events/BranchEnd.tscn b/addons/dialogic/Editor/Events/BranchEnd.tscn index a5bc68c4..63df64e6 100644 --- a/addons/dialogic/Editor/Events/BranchEnd.tscn +++ b/addons/dialogic/Editor/Events/BranchEnd.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=3 uid="uid://de13fdeebrkcb"] -[ext_resource type="Script" uid="uid://bbcblody1vn3k" path="res://addons/dialogic/Editor/Events/BranchEnd.gd" id="1"] +[ext_resource type="Script" uid="uid://cyjmcay08lmr8" path="res://addons/dialogic/Editor/Events/BranchEnd.gd" id="1"] [sub_resource type="Image" id="Image_6aqdp"] data = { diff --git a/addons/dialogic/Editor/Events/EventBlock/event_block.gd b/addons/dialogic/Editor/Events/EventBlock/event_block.gd index 7d459148..47fa94d1 100644 --- a/addons/dialogic/Editor/Events/EventBlock/event_block.gd +++ b/addons/dialogic/Editor/Events/EventBlock/event_block.gd @@ -55,6 +55,8 @@ func _ready() -> void: func initialize_ui() -> void: var _scale := DialogicUtil.get_editor_scale() + add_theme_constant_override("margin_bottom", DialogicUtil.get_editor_setting("event_block_margin", 0) * _scale) + $PanelContainer.self_modulate = get_theme_color("accent_color", "Editor") # Warning Icon @@ -168,6 +170,7 @@ var FIELD_SCENES := { DialogicEvent.ValueType.VECTOR4: "res://addons/dialogic/Editor/Events/Fields/field_vector4.tscn", DialogicEvent.ValueType.COLOR: "res://addons/dialogic/Editor/Events/Fields/field_color.tscn", DialogicEvent.ValueType.AUDIO_PREVIEW: "res://addons/dialogic/Editor/Events/Fields/field_audio_preview.tscn", + DialogicEvent.ValueType.IMAGE_PREVIEW: "res://addons/dialogic/Editor/Events/Fields/field_image_preview.tscn", } func build_editor(build_header:bool = true, build_body:bool = false) -> void: @@ -356,6 +359,13 @@ func _evaluate_visibility_condition(p: Dictionary) -> bool: return result +func get_field_node(property_name:String) -> Node: + for i in field_list: + if i.get("property", "") == property_name: + return i.node + return null + + func _on_resource_ui_update_needed() -> void: for node_info in field_list: if node_info.node and node_info.node.has_method('set_value'): @@ -415,6 +425,6 @@ func _on_EventNode_gui_input(event:InputEvent) -> void: popup.current_event = self popup.popup_on_parent(Rect2(get_global_mouse_position(),Vector2())) if resource.help_page_path == "": - popup.set_item_disabled(2, true) + popup.set_item_disabled(4, true) else: - popup.set_item_disabled(2, false) + popup.set_item_disabled(4, false) diff --git a/addons/dialogic/Editor/Events/EventBlock/event_block.gd.uid b/addons/dialogic/Editor/Events/EventBlock/event_block.gd.uid index 43453d3f..d3830479 100644 --- a/addons/dialogic/Editor/Events/EventBlock/event_block.gd.uid +++ b/addons/dialogic/Editor/Events/EventBlock/event_block.gd.uid @@ -1 +1 @@ -uid://dprlmuv5kwkpa +uid://dbncx2w0btjyx diff --git a/addons/dialogic/Editor/Events/EventBlock/event_block.tscn b/addons/dialogic/Editor/Events/EventBlock/event_block.tscn index cf9b7ef5..54022735 100644 --- a/addons/dialogic/Editor/Events/EventBlock/event_block.tscn +++ b/addons/dialogic/Editor/Events/EventBlock/event_block.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=8 format=3 uid="uid://bwaxj1n401fp4"] -[ext_resource type="Script" uid="uid://dprlmuv5kwkpa" path="res://addons/dialogic/Editor/Events/EventBlock/event_block.gd" id="1"] +[ext_resource type="Script" uid="uid://dbncx2w0btjyx" path="res://addons/dialogic/Editor/Events/EventBlock/event_block.gd" id="1"] [ext_resource type="StyleBox" uid="uid://cl75ikyq2is7c" path="res://addons/dialogic/Editor/Events/styles/unselected_stylebox.tres" id="2_axj84"] [ext_resource type="Texture2D" uid="uid://dybg3l5pwetne" path="res://addons/dialogic/Editor/Images/plugin-icon.svg" id="6"] diff --git a/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd b/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd index 0b765f63..7fad3978 100644 --- a/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd +++ b/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd @@ -5,15 +5,17 @@ var current_event: Node = null func _ready() -> void: clear() - add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), "Duplicate") + add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), "Duplicate", 0) add_separator() - add_icon_item(get_theme_icon("Help", "EditorIcons"), "Documentation") - add_icon_item(get_theme_icon("CodeHighlighter", "EditorIcons"), "Open Code") + add_icon_item(get_theme_icon("PlayStart", "EditorIcons"), "Play from here", 1) add_separator() - add_icon_item(get_theme_icon("ArrowUp", "EditorIcons"), "Move up") - add_icon_item(get_theme_icon("ArrowDown", "EditorIcons"), "Move down") + add_icon_item(get_theme_icon("Help", "EditorIcons"), "Documentation", 2) + add_icon_item(get_theme_icon("CodeHighlighter", "EditorIcons"), "Open Code", 3) add_separator() - add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Delete") + add_icon_item(get_theme_icon("ArrowUp", "EditorIcons"), "Move up", 4) + add_icon_item(get_theme_icon("ArrowDown", "EditorIcons"), "Move down", 5) + add_separator() + add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Delete", 6) var menu_background := StyleBoxFlat.new() menu_background.bg_color = get_parent().get_theme_color("base_color", "Editor") diff --git a/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd.uid b/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd.uid index e0921afe..1bf48609 100644 --- a/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd.uid +++ b/addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd.uid @@ -1 +1 @@ -uid://doek0kltvf65w +uid://n1knm2ohcehu diff --git a/addons/dialogic/Editor/Events/Fields/array_part.gd.uid b/addons/dialogic/Editor/Events/Fields/array_part.gd.uid index fd0810ef..693d1c82 100644 --- a/addons/dialogic/Editor/Events/Fields/array_part.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/array_part.gd.uid @@ -1 +1 @@ -uid://lsk3tuggakt6 +uid://cm8w2iamuulp7 diff --git a/addons/dialogic/Editor/Events/Fields/array_part.tscn b/addons/dialogic/Editor/Events/Fields/array_part.tscn index 4728e2bc..75932ec1 100644 --- a/addons/dialogic/Editor/Events/Fields/array_part.tscn +++ b/addons/dialogic/Editor/Events/Fields/array_part.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://ch4j2lesn1sis"] -[ext_resource type="Script" uid="uid://lsk3tuggakt6" path="res://addons/dialogic/Editor/Events/Fields/array_part.gd" id="1"] +[ext_resource type="Script" uid="uid://cm8w2iamuulp7" path="res://addons/dialogic/Editor/Events/Fields/array_part.gd" id="1"] [ext_resource type="PackedScene" uid="uid://dl08ubinx6ugu" path="res://addons/dialogic/Editor/Events/Fields/field_flex_value.tscn" id="3_s4j7i"] [sub_resource type="Image" id="Image_28ws6"] diff --git a/addons/dialogic/Editor/Events/Fields/dictionary_part.gd b/addons/dialogic/Editor/Events/Fields/dictionary_part.gd index 7c28572d..c5b8b39d 100644 --- a/addons/dialogic/Editor/Events/Fields/dictionary_part.gd +++ b/addons/dialogic/Editor/Events/Fields/dictionary_part.gd @@ -41,4 +41,3 @@ func _on_flex_value_value_changed() -> void: func _on_delete_pressed() -> void: queue_free() value_changed.emit() - diff --git a/addons/dialogic/Editor/Events/Fields/dictionary_part.gd.uid b/addons/dialogic/Editor/Events/Fields/dictionary_part.gd.uid index 550df1df..a73c516b 100644 --- a/addons/dialogic/Editor/Events/Fields/dictionary_part.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/dictionary_part.gd.uid @@ -1 +1 @@ -uid://c6u35t2t7k8mm +uid://b41laec1d54io diff --git a/addons/dialogic/Editor/Events/Fields/dictionary_part.tscn b/addons/dialogic/Editor/Events/Fields/dictionary_part.tscn index 0f808550..e0824b13 100644 --- a/addons/dialogic/Editor/Events/Fields/dictionary_part.tscn +++ b/addons/dialogic/Editor/Events/Fields/dictionary_part.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://b27yweami3mxi"] -[ext_resource type="Script" uid="uid://c6u35t2t7k8mm" path="res://addons/dialogic/Editor/Events/Fields/dictionary_part.gd" id="2_q88pg"] +[ext_resource type="Script" uid="uid://b41laec1d54io" path="res://addons/dialogic/Editor/Events/Fields/dictionary_part.gd" id="2_q88pg"] [ext_resource type="PackedScene" uid="uid://dl08ubinx6ugu" path="res://addons/dialogic/Editor/Events/Fields/field_flex_value.tscn" id="3_p082d"] [sub_resource type="Image" id="Image_teqf1"] diff --git a/addons/dialogic/Editor/Events/Fields/field_array.gd.uid b/addons/dialogic/Editor/Events/Fields/field_array.gd.uid index 437281f2..5c155b86 100644 --- a/addons/dialogic/Editor/Events/Fields/field_array.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_array.gd.uid @@ -1 +1 @@ -uid://cm1yxhxo57dd6 +uid://kmn7rns1g4fc diff --git a/addons/dialogic/Editor/Events/Fields/field_array.tscn b/addons/dialogic/Editor/Events/Fields/field_array.tscn index c8bfa265..4ba17ff2 100644 --- a/addons/dialogic/Editor/Events/Fields/field_array.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_array.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=3 uid="uid://btmy7ageqpyq1"] -[ext_resource type="Script" uid="uid://cm1yxhxo57dd6" path="res://addons/dialogic/Editor/Events/Fields/field_array.gd" id="2"] +[ext_resource type="Script" uid="uid://kmn7rns1g4fc" path="res://addons/dialogic/Editor/Events/Fields/field_array.gd" id="2"] [sub_resource type="Image" id="Image_v6fhx"] data = { diff --git a/addons/dialogic/Editor/Events/Fields/field_audio_preview.gd.uid b/addons/dialogic/Editor/Events/Fields/field_audio_preview.gd.uid index c973cb58..185e71c9 100644 --- a/addons/dialogic/Editor/Events/Fields/field_audio_preview.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_audio_preview.gd.uid @@ -1 +1 @@ -uid://b2fdm4rg2lsq5 +uid://lnr24bngydn2 diff --git a/addons/dialogic/Editor/Events/Fields/field_audio_preview.tscn b/addons/dialogic/Editor/Events/Fields/field_audio_preview.tscn index 2fc09514..949d94c9 100644 --- a/addons/dialogic/Editor/Events/Fields/field_audio_preview.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_audio_preview.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://dotvrsumm5y5c"] -[ext_resource type="Script" uid="uid://b2fdm4rg2lsq5" path="res://addons/dialogic/Editor/Events/Fields/field_audio_preview.gd" id="1_7wm54"] +[ext_resource type="Script" uid="uid://lnr24bngydn2" path="res://addons/dialogic/Editor/Events/Fields/field_audio_preview.gd" id="1_7wm54"] [node name="Field_Audio_Preview" type="Button"] offset_right = 8.0 diff --git a/addons/dialogic/Editor/Events/Fields/field_bool_button.gd.uid b/addons/dialogic/Editor/Events/Fields/field_bool_button.gd.uid index 826a59d5..76968687 100644 --- a/addons/dialogic/Editor/Events/Fields/field_bool_button.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_bool_button.gd.uid @@ -1 +1 @@ -uid://bvx3n3jfkyt7f +uid://do3x030t162u1 diff --git a/addons/dialogic/Editor/Events/Fields/field_bool_button.tscn b/addons/dialogic/Editor/Events/Fields/field_bool_button.tscn index eebacf61..9a8a4df8 100644 --- a/addons/dialogic/Editor/Events/Fields/field_bool_button.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_bool_button.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://iypxcctv080u"] -[ext_resource type="Script" uid="uid://bvx3n3jfkyt7f" path="res://addons/dialogic/Editor/Events/Fields/field_bool_button.gd" id="1_t1n1f"] +[ext_resource type="Script" uid="uid://do3x030t162u1" path="res://addons/dialogic/Editor/Events/Fields/field_bool_button.gd" id="1_t1n1f"] [node name="Field_BoolButton" type="Button"] theme_override_colors/icon_normal_color = Color(0, 0, 0, 1) diff --git a/addons/dialogic/Editor/Events/Fields/field_bool_check.gd.uid b/addons/dialogic/Editor/Events/Fields/field_bool_check.gd.uid index ba5fa378..716669b3 100644 --- a/addons/dialogic/Editor/Events/Fields/field_bool_check.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_bool_check.gd.uid @@ -1 +1 @@ -uid://dnwdfshaj4rv7 +uid://ddxcyihcistll diff --git a/addons/dialogic/Editor/Events/Fields/field_bool_check.tscn b/addons/dialogic/Editor/Events/Fields/field_bool_check.tscn index f218980d..3eb2edaf 100644 --- a/addons/dialogic/Editor/Events/Fields/field_bool_check.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_bool_check.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://dm5hxmhyyxgq"] -[ext_resource type="Script" uid="uid://dnwdfshaj4rv7" path="res://addons/dialogic/Editor/Events/Fields/field_bool_check.gd" id="1_ckmtx"] +[ext_resource type="Script" uid="uid://ddxcyihcistll" path="res://addons/dialogic/Editor/Events/Fields/field_bool_check.gd" id="1_ckmtx"] [node name="Field_BoolCheck" type="CheckButton"] offset_right = 44.0 diff --git a/addons/dialogic/Editor/Events/Fields/field_color.gd.uid b/addons/dialogic/Editor/Events/Fields/field_color.gd.uid index df46000e..8bdd8f61 100644 --- a/addons/dialogic/Editor/Events/Fields/field_color.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_color.gd.uid @@ -1 +1 @@ -uid://cj3yoscgycygy +uid://o26ppdmyst02 diff --git a/addons/dialogic/Editor/Events/Fields/field_color.tscn b/addons/dialogic/Editor/Events/Fields/field_color.tscn index f947b48a..3b8fb36d 100644 --- a/addons/dialogic/Editor/Events/Fields/field_color.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_color.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://4e0kjekan5e7"] -[ext_resource type="Script" uid="uid://cj3yoscgycygy" path="res://addons/dialogic/Editor/Events/Fields/field_color.gd" id="1_l666a"] +[ext_resource type="Script" uid="uid://o26ppdmyst02" path="res://addons/dialogic/Editor/Events/Fields/field_color.gd" id="1_l666a"] [node name="Field_Color" type="ColorPickerButton"] custom_minimum_size = Vector2(48, 0) diff --git a/addons/dialogic/Editor/Events/Fields/field_condition.gd b/addons/dialogic/Editor/Events/Fields/field_condition.gd index db40270b..9e0ef1a0 100644 --- a/addons/dialogic/Editor/Events/Fields/field_condition.gd +++ b/addons/dialogic/Editor/Events/Fields/field_condition.gd @@ -56,7 +56,7 @@ func _ready() -> void: for i in [%Value1Variable, %Value2Variable]: - i.get_suggestions_func = get_variable_suggestions + i.suggestions_func = get_variable_suggestions i.value_changed.connect(something_changed) %Value1Number.value_changed.connect(something_changed) @@ -264,4 +264,3 @@ func _on_value_1_variable_value_changed(property_name: Variant, value: Variant) %Value2Type.index_pressed(1) something_changed() - diff --git a/addons/dialogic/Editor/Events/Fields/field_condition.gd.uid b/addons/dialogic/Editor/Events/Fields/field_condition.gd.uid index 1d0bb2c7..5c18a72f 100644 --- a/addons/dialogic/Editor/Events/Fields/field_condition.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_condition.gd.uid @@ -1 +1 @@ -uid://dtni8g3dujujh +uid://gx1mq5xn4mri diff --git a/addons/dialogic/Editor/Events/Fields/field_condition.tscn b/addons/dialogic/Editor/Events/Fields/field_condition.tscn index 54a3daf4..67ef8df5 100644 --- a/addons/dialogic/Editor/Events/Fields/field_condition.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_condition.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=9 format=3 uid="uid://ir6334lqtuwt"] -[ext_resource type="Script" uid="uid://dtni8g3dujujh" path="res://addons/dialogic/Editor/Events/Fields/field_condition.gd" id="1_owjj0"] +[ext_resource type="Script" uid="uid://gx1mq5xn4mri" path="res://addons/dialogic/Editor/Events/Fields/field_condition.gd" id="1_owjj0"] [ext_resource type="PackedScene" uid="uid://d3bhehatwoio" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn" id="2_f6v80"] [ext_resource type="PackedScene" uid="uid://c0vkcehgjsjy" path="res://addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn" id="3_3kfwc"] [ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="4_6q3a6"] diff --git a/addons/dialogic/Editor/Events/Fields/field_dictionary.gd.uid b/addons/dialogic/Editor/Events/Fields/field_dictionary.gd.uid index 77a87adf..4dcbcefa 100644 --- a/addons/dialogic/Editor/Events/Fields/field_dictionary.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_dictionary.gd.uid @@ -1 +1 @@ -uid://ntqvlvpqgjwc +uid://cjhy1b218xsh0 diff --git a/addons/dialogic/Editor/Events/Fields/field_dictionary.tscn b/addons/dialogic/Editor/Events/Fields/field_dictionary.tscn index 6827ecaf..801906e4 100644 --- a/addons/dialogic/Editor/Events/Fields/field_dictionary.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_dictionary.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=3 uid="uid://c74bnmhefu72w"] -[ext_resource type="Script" uid="uid://ntqvlvpqgjwc" path="res://addons/dialogic/Editor/Events/Fields/field_dictionary.gd" id="1_p4kmu"] +[ext_resource type="Script" uid="uid://cjhy1b218xsh0" path="res://addons/dialogic/Editor/Events/Fields/field_dictionary.gd" id="1_p4kmu"] [sub_resource type="Image" id="Image_mpo34"] data = { diff --git a/addons/dialogic/Editor/Events/Fields/field_file.gd b/addons/dialogic/Editor/Events/Fields/field_file.gd index 1227dfaf..4ad03a03 100644 --- a/addons/dialogic/Editor/Events/Fields/field_file.gd +++ b/addons/dialogic/Editor/Events/Fields/field_file.gd @@ -23,6 +23,7 @@ var resource_icon: Texture: var max_width := 200 var current_value: String var hide_reset := false +var show_editing_button := false #endregion @@ -36,6 +37,9 @@ func _ready() -> void: %OpenButton.icon = get_theme_icon("Folder", "EditorIcons") %OpenButton.button_down.connect(_on_OpenButton_pressed) + %EditButton.icon = get_theme_icon("Edit", "EditorIcons") + %EditButton.button_down.connect(_on_EditButton_pressed) + %ClearButton.icon = get_theme_icon("Reload", "EditorIcons") %ClearButton.button_up.connect(clear_path) %ClearButton.visible = !hide_reset @@ -72,6 +76,8 @@ func _set_value(value: Variant) -> void: %Field.custom_minimum_size.x = 0 %Field.expand_to_text_length = true + %EditButton.visible = show_editing_button and value + if not %Field.text == text: value_changed.emit(property_name, current_value) %Field.text = text @@ -94,6 +100,11 @@ func _on_file_dialog_selected(path:String) -> void: value_changed.emit(property_name, path) +func _on_EditButton_pressed() -> void: + if ResourceLoader.exists(current_value): + EditorInterface.inspect_object(load(current_value), "", true) + + func clear_path() -> void: _set_value("") value_changed.emit(property_name, "") @@ -134,6 +145,8 @@ func _on_field_focus_entered() -> void: func _on_field_focus_exited() -> void: $FocusStyle.hide() var field_text: String = %Field.text + if current_value == field_text or (file_mode != EditorFileDialog.FILE_MODE_OPEN_DIR and current_value.get_file() == field_text): + return _on_file_dialog_selected(field_text) #endregion diff --git a/addons/dialogic/Editor/Events/Fields/field_file.gd.uid b/addons/dialogic/Editor/Events/Fields/field_file.gd.uid index 2aa3bb31..0c00aa96 100644 --- a/addons/dialogic/Editor/Events/Fields/field_file.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_file.gd.uid @@ -1 +1 @@ -uid://n3gpu77wxspf +uid://buepm260xnmaa diff --git a/addons/dialogic/Editor/Events/Fields/field_file.tscn b/addons/dialogic/Editor/Events/Fields/field_file.tscn index e913fc16..f8dccd35 100644 --- a/addons/dialogic/Editor/Events/Fields/field_file.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_file.tscn @@ -1,26 +1,14 @@ -[gd_scene load_steps=8 format=3 uid="uid://7mvxuaulctcq"] +[gd_scene load_steps=6 format=3 uid="uid://7mvxuaulctcq"] -[ext_resource type="Script" uid="uid://n3gpu77wxspf" path="res://addons/dialogic/Editor/Events/Fields/field_file.gd" id="1_0grcf"] +[ext_resource type="Script" uid="uid://buepm260xnmaa" path="res://addons/dialogic/Editor/Events/Fields/field_file.gd" id="1_0grcf"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tr837"] -[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wq6bt"] - [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_6b7on"] -[sub_resource type="Image" id="Image_ye6ml"] -data = { -"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", -"height": 16, -"mipmaps": false, -"width": 16 -} +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wq6bt"] -[sub_resource type="ImageTexture" id="ImageTexture_dkuon"] -image = SubResource("Image_ye6ml") - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_yv1pn"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ye6ml"] content_margin_left = 4.0 content_margin_top = 4.0 content_margin_right = 4.0 @@ -60,27 +48,30 @@ layout_mode = 2 size_flags_horizontal = 3 mouse_filter = 1 theme_override_styles/normal = SubResource("StyleBoxEmpty_tr837") -theme_override_styles/focus = SubResource("StyleBoxEmpty_wq6bt") theme_override_styles/read_only = SubResource("StyleBoxEmpty_6b7on") +theme_override_styles/focus = SubResource("StyleBoxEmpty_wq6bt") expand_to_text_length = true [node name="OpenButton" type="Button" parent="BG/HBox"] unique_name_in_owner = true layout_mode = 2 -icon = SubResource("ImageTexture_dkuon") +flat = true + +[node name="EditButton" type="Button" parent="BG/HBox"] +unique_name_in_owner = true +layout_mode = 2 flat = true [node name="ClearButton" type="Button" parent="BG/HBox"] unique_name_in_owner = true layout_mode = 2 -icon = SubResource("ImageTexture_dkuon") flat = true [node name="FocusStyle" type="Panel" parent="."] visible = false layout_mode = 2 mouse_filter = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_yv1pn") +theme_override_styles/panel = SubResource("StyleBoxFlat_ye6ml") [connection signal="focus_entered" from="BG/HBox/Field" to="." method="_on_field_focus_entered"] [connection signal="focus_exited" from="BG/HBox/Field" to="." method="_on_field_focus_exited"] diff --git a/addons/dialogic/Editor/Events/Fields/field_flex_value.gd.uid b/addons/dialogic/Editor/Events/Fields/field_flex_value.gd.uid index 5dbd849b..2bc636da 100644 --- a/addons/dialogic/Editor/Events/Fields/field_flex_value.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_flex_value.gd.uid @@ -1 +1 @@ -uid://c67ocy8gudoug +uid://bl8pqdbnw005y diff --git a/addons/dialogic/Editor/Events/Fields/field_flex_value.tscn b/addons/dialogic/Editor/Events/Fields/field_flex_value.tscn index 4a413929..18799bb7 100644 --- a/addons/dialogic/Editor/Events/Fields/field_flex_value.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_flex_value.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://dl08ubinx6ugu"] -[ext_resource type="Script" uid="uid://c67ocy8gudoug" path="res://addons/dialogic/Editor/Events/Fields/field_flex_value.gd" id="1_m5nnp"] +[ext_resource type="Script" uid="uid://bl8pqdbnw005y" path="res://addons/dialogic/Editor/Events/Fields/field_flex_value.gd" id="1_m5nnp"] [ext_resource type="PackedScene" uid="uid://d3bhehatwoio" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn" id="3_h10fc"] [node name="FlexValue" type="HBoxContainer"] diff --git a/addons/dialogic/Editor/Events/Fields/field_image_preview.gd b/addons/dialogic/Editor/Events/Fields/field_image_preview.gd new file mode 100644 index 00000000..d5e93f45 --- /dev/null +++ b/addons/dialogic/Editor/Events/Fields/field_image_preview.gd @@ -0,0 +1,64 @@ +@tool +extends DialogicVisualEditorField + + +var body: Control +var image_path: String + +func _ready() -> void: + body = find_parent('Body') as Control + body.visibility_changed.connect(_on_body_visibility_toggled) + + +func _enter_tree() -> void: + %HiddenLabel.add_theme_color_override( + 'font_color', + event_resource.event_color.lerp(get_theme_color("font_color", "Editor"), 0.8)) + + +#region OVERWRITES +################################################################################ + +## To be overwritten +func _set_value(value:Variant) -> void: + if ResourceLoader.exists(value): + image_path = value + + if is_preview_enabled(): + self.texture = load(value) + custom_minimum_size.y = get_preview_size() + else: + self.texture = null + + minimum_size_changed.emit() + +#endregion + + +#region SIGNAL METHODS +################################################################################ + + +func _on_body_visibility_toggled() -> void: + custom_minimum_size.y = 0 + + if body.is_visible: + %HiddenLabel.visible = not is_preview_enabled() + + if is_preview_enabled() and ResourceLoader.exists(image_path): + self.texture = load(image_path) + custom_minimum_size.y = get_preview_size() + else: + self.texture = null + + minimum_size_changed.emit() + +#endregion + +func is_preview_enabled() -> bool: + return get_preview_size() != 0 + + +func get_preview_size() -> int: + return DialogicUtil.get_editor_setting( + "image_preview_height", 50) * DialogicUtil.get_editor_scale() diff --git a/addons/dialogic/Editor/Events/Fields/field_image_preview.gd.uid b/addons/dialogic/Editor/Events/Fields/field_image_preview.gd.uid new file mode 100644 index 00000000..4c456213 --- /dev/null +++ b/addons/dialogic/Editor/Events/Fields/field_image_preview.gd.uid @@ -0,0 +1 @@ +uid://u6evsmx7tynf diff --git a/addons/dialogic/Editor/Events/Fields/field_image_preview.tscn b/addons/dialogic/Editor/Events/Fields/field_image_preview.tscn new file mode 100644 index 00000000..e6007f0c --- /dev/null +++ b/addons/dialogic/Editor/Events/Fields/field_image_preview.tscn @@ -0,0 +1,23 @@ +[gd_scene load_steps=2 format=3 uid="uid://bar0t74j5v4sa"] + +[ext_resource type="Script" uid="uid://u6evsmx7tynf" path="res://addons/dialogic/Editor/Events/Fields/field_image_preview.gd" id="1_e5vbc"] + +[node name="Field_Image_Preview" type="TextureRect"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 +expand_mode = 2 +stretch_mode = 4 +script = ExtResource("1_e5vbc") + +[node name="HiddenLabel" type="Label" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 0 +tooltip_text = "Preview hidden because project setting 'dialogic/accessibility/image_preview_height' is 0." +mouse_filter = 1 +text = "(Hidden)" diff --git a/addons/dialogic/Editor/Events/Fields/field_number.gd b/addons/dialogic/Editor/Events/Fields/field_number.gd index 30d50eb2..27145d9e 100644 --- a/addons/dialogic/Editor/Events/Fields/field_number.gd +++ b/addons/dialogic/Editor/Events/Fields/field_number.gd @@ -4,11 +4,18 @@ extends DialogicVisualEditorField ## Event block field for integers and floats. Improved version of the native spinbox. +@export_enum("Float", "Int", "Decible") var mode := 0 : + set(new_mode): + mode = new_mode + match mode: + 0: use_float_mode() #FLOAT + 1: use_int_mode() #INT + 2: use_decibel_mode() #DECIBLE @export var allow_string: bool = false @export var step: float = 0.1 @export var enforce_step: bool = true -@export var min: float = -INF -@export var max: float = INF +@export var min_value: float = -INF +@export var max_value: float = INF @export var value = 0.0 @export var prefix: String = "" @export var suffix: String = "" @@ -27,18 +34,11 @@ func _ready() -> void: func _load_display_info(info: Dictionary) -> void: - match info.get('mode', 0): - 0: #FLOAT - use_float_mode(info.get('step', 0.1)) - 1: #INT - use_int_mode(info.get('step', 1)) - 2: #DECIBLE: - use_decibel_mode(info.get('step', step)) for option in info.keys(): match option: - 'min': min = info[option] - 'max': max = info[option] + 'min': min_value = info[option] + 'max': max_value = info[option] 'prefix': update_prefix(info[option]) 'suffix': update_suffix(info[option]) 'step': @@ -46,6 +46,7 @@ func _load_display_info(info: Dictionary) -> void: step = info[option] 'hide_step_button': %Spin.hide() + mode = info.get('mode', mode) func _set_value(new_value: Variant) -> void: _on_value_text_submitted(str(new_value), true) @@ -60,22 +61,20 @@ func get_value() -> float: return value -func use_float_mode(value_step: float = 0.1) -> void: - step = value_step +func use_float_mode() -> void: update_suffix("") enforce_step = false -func use_int_mode(value_step: float = 1) -> void: - step = value_step +func use_int_mode() -> void: update_suffix("") enforce_step = true -func use_decibel_mode(value_step: float = step) -> void: - max = 6 +func use_decibel_mode() -> void: + max_value = 6 update_suffix("dB") - min = -80 + min_value = -80 #endregion @@ -147,31 +146,38 @@ func _on_gui_input(event: InputEvent) -> void: func _on_increment_button_down(button: NodePath) -> void: _on_value_text_submitted(str(value+step)) - _holding_button(1.0, get_node(button) as BaseButton) + _holding_button(1, get_node(button) as BaseButton) func _on_decrement_button_down(button: NodePath) -> void: _on_value_text_submitted(str(value-step)) - _holding_button(-1.0, get_node(button) as BaseButton) + _holding_button(-1, get_node(button) as BaseButton) func _on_value_text_submitted(new_text: String, no_signal:= false) -> void: if new_text.is_empty() and not allow_string: new_text = "0.0" if new_text.is_valid_float(): - var temp: float = min(max(new_text.to_float(), min), max) - if !enforce_step: + var temp: float = min(max(new_text.to_float(), min_value), max_value) + if not enforce_step: value = temp else: value = snapped(temp, step) elif allow_string: value = new_text - %Value.text = str(value).pad_decimals(len(str(float(step)-floorf(step)))-2) + + if int(step) == step and step != 0: + %Value.text = str(int(value)) + else: + %Value.text = str(value).pad_decimals( + max( + len(str(float(step)-floorf(step)))-2, + len(str(float(value)-floorf(value)))-2,)) if not no_signal: value_changed.emit(property_name, value) # Visually disable Up or Down arrow when limit is reached to better indicate a limit has been hit - %Spin/Decrement.disabled = value <= min - %Spin/Increment.disabled = value >= max + %Spin/Decrement.disabled = value <= min_value + %Spin/Increment.disabled = value >= max_value # If prefix or suffix was clicked, select the actual value box instead and move the caret to the closest side. @@ -196,4 +202,3 @@ func _on_value_focus_entered() -> void: %Value.select_all.call_deferred() #endregion - diff --git a/addons/dialogic/Editor/Events/Fields/field_number.gd.uid b/addons/dialogic/Editor/Events/Fields/field_number.gd.uid index c4ade458..57cc0b50 100644 --- a/addons/dialogic/Editor/Events/Fields/field_number.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_number.gd.uid @@ -1 +1 @@ -uid://b60ru6qhj10c3 +uid://dbegwhxegm271 diff --git a/addons/dialogic/Editor/Events/Fields/field_number.tscn b/addons/dialogic/Editor/Events/Fields/field_number.tscn index 94994c49..0e125d5a 100644 --- a/addons/dialogic/Editor/Events/Fields/field_number.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_number.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=9 format=3 uid="uid://kdpp3mibml33"] -[ext_resource type="Script" uid="uid://b60ru6qhj10c3" path="res://addons/dialogic/Editor/Events/Fields/field_number.gd" id="1_0jdnn"] +[ext_resource type="Script" uid="uid://dbegwhxegm271" path="res://addons/dialogic/Editor/Events/Fields/field_number.gd" id="1_0jdnn"] [ext_resource type="Texture2D" uid="uid://dh1ycbmw8anqh" path="res://addons/dialogic/Editor/Images/Interactable/increment_icon.svg" id="3_v5cne"] [ext_resource type="Texture2D" uid="uid://brjikovneb63n" path="res://addons/dialogic/Editor/Images/Interactable/decrement_icon.svg" id="4_ph52o"] @@ -34,7 +34,7 @@ border_color = Color(0, 0, 0, 0) anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = -1102.0 +offset_right = -1011.0 offset_bottom = -617.0 grow_horizontal = 2 grow_vertical = 2 @@ -43,6 +43,7 @@ script = ExtResource("1_0jdnn") [node name="Value_Panel" type="PanelContainer" parent="."] layout_mode = 2 +size_flags_horizontal = 3 theme_type_variation = &"DialogicEventEdit" [node name="Layout" type="HBoxContainer" parent="Value_Panel"] @@ -60,8 +61,8 @@ size_flags_vertical = 4 mouse_filter = 1 mouse_default_cursor_shape = 1 theme_override_colors/default_color = Color(0.54099, 0.540991, 0.54099, 1) -theme_override_styles/focus = SubResource("StyleBoxEmpty_sj3oj") theme_override_styles/normal = SubResource("StyleBoxEmpty_sj3oj") +theme_override_styles/focus = SubResource("StyleBoxEmpty_sj3oj") bbcode_enabled = true fit_content = true scroll_active = false @@ -78,10 +79,9 @@ size_flags_horizontal = 3 focus_mode = 1 theme_override_constants/minimum_character_width = 0 theme_override_styles/normal = SubResource("StyleBoxEmpty_8yqsu") -theme_override_styles/focus = SubResource("StyleBoxEmpty_8yqsu") theme_override_styles/read_only = SubResource("StyleBoxEmpty_8yqsu") +theme_override_styles/focus = SubResource("StyleBoxEmpty_8yqsu") text = "0" -alignment = 1 expand_to_text_length = true virtual_keyboard_type = 3 @@ -95,8 +95,8 @@ size_flags_horizontal = 8 size_flags_vertical = 4 mouse_default_cursor_shape = 1 theme_override_colors/default_color = Color(0.435192, 0.435192, 0.435192, 1) -theme_override_styles/focus = SubResource("StyleBoxEmpty_smq50") theme_override_styles/normal = SubResource("StyleBoxEmpty_smq50") +theme_override_styles/focus = SubResource("StyleBoxEmpty_smq50") bbcode_enabled = true fit_content = true scroll_active = false @@ -113,17 +113,17 @@ theme_override_constants/separation = 0 alignment = 1 [node name="Increment" type="Button" parent="Value_Panel/Layout/Spin"] +auto_translate_mode = 2 layout_mode = 2 size_flags_vertical = 3 -auto_translate = false focus_neighbor_left = NodePath("../../Value") focus_neighbor_top = NodePath(".") focus_neighbor_bottom = NodePath("../Decrement") -theme_override_colors/icon_hover_color = Color(0.412738, 0.550094, 0.760917, 1) theme_override_colors/icon_focus_color = Color(0.412738, 0.550094, 0.760917, 1) +theme_override_colors/icon_hover_color = Color(0.412738, 0.550094, 0.760917, 1) theme_override_styles/normal = SubResource("StyleBoxFlat_increment") -theme_override_styles/hover = SubResource("StyleBoxFlat_increment") theme_override_styles/pressed = SubResource("StyleBoxFlat_increment") +theme_override_styles/hover = SubResource("StyleBoxFlat_increment") theme_override_styles/disabled = SubResource("StyleBoxFlat_increment") theme_override_styles/focus = SubResource("StyleBoxFlat_increment") icon = ExtResource("3_v5cne") @@ -131,17 +131,17 @@ flat = true vertical_icon_alignment = 2 [node name="Decrement" type="Button" parent="Value_Panel/Layout/Spin"] +auto_translate_mode = 2 layout_mode = 2 size_flags_vertical = 3 -auto_translate = false focus_neighbor_left = NodePath("../../Value") focus_neighbor_top = NodePath("../Increment") focus_neighbor_bottom = NodePath(".") -theme_override_colors/icon_hover_color = Color(0.412738, 0.550094, 0.760917, 1) theme_override_colors/icon_focus_color = Color(0.412738, 0.550094, 0.760917, 1) +theme_override_colors/icon_hover_color = Color(0.412738, 0.550094, 0.760917, 1) theme_override_styles/normal = SubResource("StyleBoxFlat_decrement") -theme_override_styles/hover = SubResource("StyleBoxFlat_decrement") theme_override_styles/pressed = SubResource("StyleBoxFlat_decrement") +theme_override_styles/hover = SubResource("StyleBoxFlat_decrement") theme_override_styles/disabled = SubResource("StyleBoxFlat_decrement") theme_override_styles/focus = SubResource("StyleBoxFlat_decrement") icon = ExtResource("4_ph52o") diff --git a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd index 16a315f1..8e1ee7aa 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd +++ b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd @@ -6,12 +6,13 @@ extends DialogicVisualEditorField ## SETTINGS @export var placeholder_text := "Select Resource" @export var empty_text := "" -enum Modes {PURE_STRING, PRETTY_PATH, IDENTIFIER} +enum Modes {PURE_STRING, PRETTY_PATH, IDENTIFIER, ANY_VALID_STRING} @export var mode := Modes.PURE_STRING @export var fit_text_length := true var collapse_when_empty := false var valid_file_drop_extension := "" -var get_suggestions_func: Callable +var suggestions_func: Callable +var validation_func: Callable var resource_icon: Texture = null: get: @@ -21,8 +22,13 @@ var resource_icon: Texture = null: %Icon.texture = new_icon ## STATE -var current_value: String +var current_value: String: + set(value): + if current_value != value: + current_value = value + current_value_updated = true var current_selected := 0 +var current_value_updated := false ## SUGGESTIONS ITEM LIST var _v_separation := 0 @@ -38,12 +44,15 @@ var _max_height := 200 * DialogicUtil.get_editor_scale() func _set_value(value:Variant) -> void: if value == null or value.is_empty(): %Search.text = empty_text + update_error_tooltip('') else: match mode: Modes.PRETTY_PATH: %Search.text = DialogicUtil.pretty_name(value) Modes.IDENTIFIER when value.begins_with("res://"): - %Search.text = DialogicResourceUtil.get_unique_identifier(value) + %Search.text = DialogicResourceUtil.get_unique_identifier_by_path(value) + Modes.ANY_VALID_STRING when validation_func: + %Search.text = validation_func.call(value).get('valid_text', value) _: %Search.text = str(value) @@ -51,11 +60,11 @@ func _set_value(value:Variant) -> void: current_value = str(value) - func _load_display_info(info:Dictionary) -> void: valid_file_drop_extension = info.get('file_extension', '') collapse_when_empty = info.get('collapse_when_empty', false) - get_suggestions_func = info.get('suggestions_func', get_suggestions_func) + suggestions_func = info.get('suggestions_func', suggestions_func) + validation_func = info.get('validation_func', validation_func) empty_text = info.get('empty_text', '') placeholder_text = info.get('placeholder', 'Select Resource') mode = info.get("mode", 0) @@ -101,16 +110,59 @@ func _ready() -> void: if resource_icon == null: self.resource_icon = null + var error_label_style := StyleBoxFlat.new() + error_label_style.bg_color = get_theme_color('background', 'Editor') + error_label_style.border_color = get_theme_color('error_color', 'Editor') + error_label_style.set_border_width_all(1) + error_label_style.set_corner_radius_all(4) + error_label_style.set_content_margin_all(6) + + %ErrorTooltip.add_theme_stylebox_override('normal', error_label_style) + func change_to_empty() -> void: + update_error_tooltip('') value_changed.emit(property_name, "") + +func validate() -> void: + if mode == Modes.ANY_VALID_STRING and validation_func: + var validation_result: Dictionary = validation_func.call(current_value) + current_value = validation_result.get('valid_text', current_value) + update_error_tooltip(validation_result.get('error_tooltip', '')) + + +func update_error_tooltip(text: String) -> void: + %ErrorTooltip.text = text + if text.is_empty(): + %ErrorTooltip.hide() + %Search.remove_theme_color_override("font_color") + else: + %ErrorTooltip.reset_size() + %ErrorTooltip.global_position = global_position - Vector2(0, %ErrorTooltip.size.y + 4) + %ErrorTooltip.show() + %Search.add_theme_color_override("font_color", get_theme_color('error_color', 'Editor')) + #endregion #region SEARCH & SUGGESTION POPUP ################################################################################ + func _on_Search_text_entered(new_text:String) -> void: + if mode == Modes.ANY_VALID_STRING: + if validation_func: + var validation_result: Dictionary = validation_func.call(new_text) + new_text = validation_result.get('valid_text', new_text) + update_error_tooltip(validation_result.get('error_tooltip', '')) + + set_value(new_text) + + value_changed.emit(property_name, current_value) + current_value_updated = false + hide_suggestions() + return + if %Suggestions.get_item_count(): if %Suggestions.is_anything_selected(): suggestion_selected(%Suggestions.get_selected_items()[0]) @@ -123,21 +175,41 @@ func _on_Search_text_entered(new_text:String) -> void: func _on_Search_text_changed(new_text:String, just_update:bool = false) -> void: %Suggestions.clear() - if new_text == "" and !just_update: + if new_text == "" and not just_update: change_to_empty() else: %Search.show() - var suggestions: Dictionary = get_suggestions_func.call(new_text) + if mode == Modes.ANY_VALID_STRING and !just_update: + if validation_func: + var validation_result: Dictionary = validation_func.call(new_text) + new_text = validation_result.get('valid_text', new_text) + update_error_tooltip(validation_result.get('error_tooltip', '')) + + current_value = new_text + + if just_update and new_text.is_empty() and %Search.text.ends_with("."): + new_text = %Search.text + + var suggestions: Dictionary = suggestions_func.call(new_text) var line_length := 0 var idx := 0 + + if new_text and mode == Modes.ANY_VALID_STRING and not new_text in suggestions.keys(): + %Suggestions.add_item(new_text, get_theme_icon('GuiScrollArrowRight', 'EditorIcons')) + %Suggestions.set_item_metadata(idx, new_text) + line_length = get_theme_font('font', 'Label').get_string_size( + new_text, HORIZONTAL_ALIGNMENT_LEFT, -1, get_theme_font_size("font_size", 'Label') + ).x + %Suggestions.fixed_icon_size.x * %Suggestions.get_icon_scale() + _icon_margin * 2 + _h_separation + idx += 1 + for element in suggestions: if new_text.is_empty() or new_text.to_lower() in element.to_lower() or new_text.to_lower() in str(suggestions[element].value).to_lower() or new_text.to_lower() in suggestions[element].get('tooltip', '').to_lower(): var curr_line_length: int = 0 - curr_line_length = get_theme_font('font', 'Label').get_string_size( + curr_line_length = int(get_theme_font('font', 'Label').get_string_size( element, HORIZONTAL_ALIGNMENT_LEFT, -1, get_theme_font_size("font_size", 'Label') - ).x + ).x) %Suggestions.add_item(element) if suggestions[element].has('icon'): @@ -166,7 +238,7 @@ func _on_Search_text_changed(new_text:String, just_update:bool = false) -> void: var total_height: int = 0 for item in %Suggestions.item_count: - total_height += _line_height * DialogicUtil.get_editor_scale() + _v_separation + total_height += int(_line_height * DialogicUtil.get_editor_scale() + _v_separation) total_height += _v_separation * 2 if total_height > _max_height: line_length += %Suggestions.get_v_scroll_bar().get_minimum_size().x @@ -182,7 +254,7 @@ func _on_Search_text_changed(new_text:String, just_update:bool = false) -> void: %Suggestions.size.x = max(%PanelContainer.size.x, line_length) -func suggestion_selected(index: int, position := Vector2(), button_index := MOUSE_BUTTON_LEFT) -> void: +func suggestion_selected(index: int, _position := Vector2(), button_index := MOUSE_BUTTON_LEFT) -> void: if button_index != MOUSE_BUTTON_LEFT: return if %Suggestions.is_item_disabled(index): @@ -196,10 +268,12 @@ func suggestion_selected(index: int, position := Vector2(), button_index := MOUS else: current_value = %Suggestions.get_item_metadata(index) + update_error_tooltip('') hide_suggestions() grab_focus() value_changed.emit(property_name, current_value) + current_value_updated = false func _input(event:InputEvent) -> void: @@ -256,12 +330,17 @@ func _on_search_focus_entered() -> void: _on_Search_text_changed("") %Search.call_deferred('select_all') %Focus.show() + validate() func _on_search_focus_exited() -> void: %Focus.hide() if !%Suggestions.get_global_rect().has_point(get_global_mouse_position()): hide_suggestions() + validate() + if current_value_updated: + value_changed.emit(property_name, current_value) + current_value_updated = false #endregion @@ -269,7 +348,7 @@ func _on_search_focus_exited() -> void: #region DRAG AND DROP ################################################################################ -func _can_drop_data(position:Vector2, data:Variant) -> bool: +func _can_drop_data(_position:Vector2, data:Variant) -> bool: if typeof(data) == TYPE_DICTIONARY and data.has('files') and len(data.files) == 1: if valid_file_drop_extension: if data.files[0].ends_with(valid_file_drop_extension): @@ -279,11 +358,12 @@ func _can_drop_data(position:Vector2, data:Variant) -> bool: return false -func _drop_data(position:Vector2, data:Variant) -> void: +func _drop_data(_position:Vector2, data:Variant) -> void: var path := str(data.files[0]) if mode == Modes.IDENTIFIER: - path = DialogicResourceUtil.get_unique_identifier(path) + path = DialogicResourceUtil.get_unique_identifier_by_path(path) _set_value(path) value_changed.emit(property_name, path) + current_value_updated = false #endregion diff --git a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd.uid b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd.uid index 73ed44af..1e6f2223 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd.uid @@ -1 +1 @@ -uid://cgh1jncreeyuu +uid://cowk63wwk126v diff --git a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn index 5c604e89..c2c898e6 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=7 format=3 uid="uid://dpwhshre1n4t6"] -[ext_resource type="Script" uid="uid://cgh1jncreeyuu" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd" id="1_b07gq"] +[ext_resource type="Script" uid="uid://cowk63wwk126v" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd" id="1_b07gq"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tmt5n"] @@ -127,9 +127,18 @@ mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_g74jb") metadata/_edit_use_anchors_ = true +[node name="ErrorTooltip" type="Label" parent="PanelContainer/Focus"] +unique_name_in_owner = true +visible = false +top_level = true +layout_mode = 0 +offset_left = -2.0 +offset_top = -44.5 +offset_right = 11.0 +offset_bottom = -9.5 + [connection signal="focus_entered" from="." to="." method="_on_focus_entered"] [connection signal="focus_entered" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_focus_entered"] [connection signal="focus_exited" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_focus_exited"] [connection signal="gui_input" from="PanelContainer/MarginContainer/HBoxContainer/Search" to="." method="_on_search_gui_input"] -[connection signal="gui_input" from="PanelContainer/MarginContainer/HBoxContainer/Search/Suggestions" to="." method="_on_suggestions_gui_input"] [connection signal="toggled" from="PanelContainer/MarginContainer/HBoxContainer/SelectButton" to="." method="_on_SelectButton_toggled"] diff --git a/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd b/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd index 3f7efb2e..b899b0b8 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd +++ b/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd @@ -3,7 +3,11 @@ extends DialogicVisualEditorField ## Event block field for constant options. For varying options use ComplexPicker. -var options: Array = [] +var options: Array = []: + set(o): + options = o + if current_value != -1: + set_value(current_value) ## if true, only the symbol will be displayed. In the dropdown text will be visible. ## Useful for making UI simpler @@ -21,6 +25,7 @@ func _ready() -> void: call("get_popup").index_pressed.connect(index_pressed) + func _load_display_info(info:Dictionary) -> void: options = info.get('options', []) self.disabled = info.get('disabled', false) @@ -35,7 +40,7 @@ func _set_value(value:Variant) -> void: if !symbol_only: self.text = option['label'] self.icon = option.get('icon', null) - current_value = value + current_value = value func get_value() -> Variant: diff --git a/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd.uid b/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd.uid index 0a4a763a..15187ecd 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd.uid @@ -1 +1 @@ -uid://ddymwkrijul30 +uid://l6jbshj3y66l diff --git a/addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn b/addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn index 6e4963a1..ad909ee0 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_options_fixed.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://d3bhehatwoio"] -[ext_resource type="Script" uid="uid://ddymwkrijul30" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.gd" id="1"] +[ext_resource type="Script" uid="uid://l6jbshj3y66l" path="res://addons/dialogic/Editor/Events/Fields/field_options_fixed.gd" id="1"] [node name="Field_FixedOptions" type="MenuButton"] offset_right = 137.0 diff --git a/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd b/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd index aaeb4c4d..db46b518 100644 --- a/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd +++ b/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd @@ -31,7 +31,7 @@ func _autofocus() -> void: #region SIGNAL METHODS ################################################################################ -func _on_text_changed(value := "") -> void: +func _on_text_changed(_value := "") -> void: value_changed.emit(property_name, self.text) #endregion diff --git a/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd.uid b/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd.uid index 75810302..d2745f75 100644 --- a/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_text_multiline.gd.uid @@ -1 +1 @@ -uid://e63vkf3hk2td +uid://do4y48h30412d diff --git a/addons/dialogic/Editor/Events/Fields/field_text_multiline.tscn b/addons/dialogic/Editor/Events/Fields/field_text_multiline.tscn index f99e83e8..63e095c6 100644 --- a/addons/dialogic/Editor/Events/Fields/field_text_multiline.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_text_multiline.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=4 format=3 uid="uid://dyp7m2nvab1aj"] -[ext_resource type="Script" uid="uid://ccjw4fyc586j1" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd" id="2_ww6ga"] -[ext_resource type="Script" uid="uid://e63vkf3hk2td" path="res://addons/dialogic/Editor/Events/Fields/field_text_multiline.gd" id="3_q7600"] +[ext_resource type="Script" uid="uid://bf2nivn8txcw5" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd" id="2_ww6ga"] +[ext_resource type="Script" uid="uid://do4y48h30412d" path="res://addons/dialogic/Editor/Events/Fields/field_text_multiline.gd" id="3_q7600"] [sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_2q5dk"] script = ExtResource("2_ww6ga") diff --git a/addons/dialogic/Editor/Events/Fields/field_text_singleline.gd.uid b/addons/dialogic/Editor/Events/Fields/field_text_singleline.gd.uid index 16ea26f6..1a2799fa 100644 --- a/addons/dialogic/Editor/Events/Fields/field_text_singleline.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_text_singleline.gd.uid @@ -1 +1 @@ -uid://c3pgscvl707c8 +uid://cgx1rn8km87ya diff --git a/addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn b/addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn index 9c04142c..374fcb54 100644 --- a/addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_text_singleline.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://c0vkcehgjsjy"] -[ext_resource type="Script" uid="uid://c3pgscvl707c8" path="res://addons/dialogic/Editor/Events/Fields/field_text_singleline.gd" id="1_4vnxv"] +[ext_resource type="Script" uid="uid://cgx1rn8km87ya" path="res://addons/dialogic/Editor/Events/Fields/field_text_singleline.gd" id="1_4vnxv"] [node name="Field_Text_Singleline" type="LineEdit"] offset_right = 1152.0 diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.gd b/addons/dialogic/Editor/Events/Fields/field_vector2.gd index 040abf07..89773496 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.gd @@ -24,3 +24,8 @@ func _on_sub_value_changed(sub_component: String, value: float) -> void: func _update_sub_component_text(value: Variant) -> void: $X._on_value_text_submitted(str(value.x), true) $Y._on_value_text_submitted(str(value.y), true) + + +func _on_step_changed(new_step:float) -> void: + $X.step = new_step + $Y.step = new_step diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.gd.uid b/addons/dialogic/Editor/Events/Fields/field_vector2.gd.uid index d27b3ca1..23b972e7 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.gd.uid @@ -1 +1 @@ -uid://yia1ug0bha8n +uid://2dk2fuatjwru diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.tscn b/addons/dialogic/Editor/Events/Fields/field_vector2.tscn index 46601189..cd70c102 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://dtimnsj014cu"] -[ext_resource type="Script" uid="uid://yia1ug0bha8n" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.gd" id="1_v6lp0"] +[ext_resource type="Script" uid="uid://2dk2fuatjwru" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.gd" id="1_v6lp0"] [ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="2_a0b6y"] [node name="Field_Vector2" type="HBoxContainer"] @@ -16,14 +16,16 @@ script = ExtResource("1_v6lp0") [node name="X" parent="." instance=ExtResource("2_a0b6y")] layout_mode = 2 -step = 0.001 +size_flags_horizontal = 3 +enforce_step = false min = -9999.0 max = 9999.0 -prefix = "" +prefix = "x" [node name="Y" parent="." instance=ExtResource("2_a0b6y")] layout_mode = 2 -step = 0.001 +size_flags_horizontal = 3 +enforce_step = false min = -9999.0 max = 9999.0 -prefix = "" +prefix = "y" diff --git a/addons/dialogic/Editor/Events/Fields/field_vector3.gd b/addons/dialogic/Editor/Events/Fields/field_vector3.gd index c5b9f6de..cc244a01 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector3.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector3.gd @@ -26,3 +26,9 @@ func _update_sub_component_text(value: Variant) -> void: $X._on_value_text_submitted(str(value.x), true) $Y._on_value_text_submitted(str(value.y), true) $Z._on_value_text_submitted(str(value.z), true) + + +func _on_step_changed(new_step:float) -> void: + $X.step = new_step + $Y.step = new_step + $Z.step = new_step diff --git a/addons/dialogic/Editor/Events/Fields/field_vector3.gd.uid b/addons/dialogic/Editor/Events/Fields/field_vector3.gd.uid index bd1de890..c10644ab 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector3.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_vector3.gd.uid @@ -1 +1 @@ -uid://1e3wqmg6kvor +uid://y01tg3q2homo diff --git a/addons/dialogic/Editor/Events/Fields/field_vector3.tscn b/addons/dialogic/Editor/Events/Fields/field_vector3.tscn index 53cc4eb8..781509a6 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector3.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_vector3.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=4 format=3 uid="uid://cklkpfrcvopgw"] [ext_resource type="PackedScene" uid="uid://dtimnsj014cu" path="res://addons/dialogic/Editor/Events/Fields/field_vector2.tscn" id="1_l3y0o"] -[ext_resource type="Script" uid="uid://1e3wqmg6kvor" path="res://addons/dialogic/Editor/Events/Fields/field_vector3.gd" id="2_gktf1"] +[ext_resource type="Script" uid="uid://y01tg3q2homo" path="res://addons/dialogic/Editor/Events/Fields/field_vector3.gd" id="2_gktf1"] [ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="3_k0u0p"] [node name="Field_Vector3" instance=ExtResource("1_l3y0o")] @@ -10,7 +10,8 @@ script = ExtResource("2_gktf1") [node name="Z" parent="." index="2" instance=ExtResource("3_k0u0p")] layout_mode = 2 -step = 0.001 +size_flags_horizontal = 3 +enforce_step = false min = -9999.0 max = 9999.0 -affix = "z:" +prefix = "z" diff --git a/addons/dialogic/Editor/Events/Fields/field_vector4.gd b/addons/dialogic/Editor/Events/Fields/field_vector4.gd index 3259ce37..e584b829 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector4.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector4.gd @@ -28,3 +28,10 @@ func _update_sub_component_text(value: Variant) -> void: $Y._on_value_text_submitted(str(value.y), true) $Z._on_value_text_submitted(str(value.z), true) $W._on_value_text_submitted(str(value.w), true) + + +func _on_step_changed(new_step:float) -> void: + $X.step = new_step + $Y.step = new_step + $Z.step = new_step + $W.step = new_step diff --git a/addons/dialogic/Editor/Events/Fields/field_vector4.gd.uid b/addons/dialogic/Editor/Events/Fields/field_vector4.gd.uid index ee38e20d..dd8716f2 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector4.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_vector4.gd.uid @@ -1 +1 @@ -uid://c06oke50dvorg +uid://chr6fkvkjugep diff --git a/addons/dialogic/Editor/Events/Fields/field_vector4.tscn b/addons/dialogic/Editor/Events/Fields/field_vector4.tscn index 480a7217..86acc6fb 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector4.tscn +++ b/addons/dialogic/Editor/Events/Fields/field_vector4.tscn @@ -1,16 +1,25 @@ [gd_scene load_steps=4 format=3 uid="uid://dykss037r2rsc"] [ext_resource type="PackedScene" uid="uid://cklkpfrcvopgw" path="res://addons/dialogic/Editor/Events/Fields/field_vector3.tscn" id="1_20tvl"] -[ext_resource type="Script" uid="uid://c06oke50dvorg" path="res://addons/dialogic/Editor/Events/Fields/field_vector4.gd" id="2_yksrc"] +[ext_resource type="Script" uid="uid://chr6fkvkjugep" path="res://addons/dialogic/Editor/Events/Fields/field_vector4.gd" id="2_yksrc"] [ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="3_1jogk"] [node name="Field_Vector4" instance=ExtResource("1_20tvl")] offset_right = -908.0 script = ExtResource("2_yksrc") +[node name="X" parent="." index="0"] +size_flags_horizontal = 1 +prefix = "" + +[node name="Y" parent="." index="1"] +size_flags_horizontal = 1 +prefix = "" + [node name="W" parent="." index="3" instance=ExtResource("3_1jogk")] layout_mode = 2 -step = 0.001 +size_flags_horizontal = 3 +enforce_step = false min = -9999.0 max = 9999.0 -affix = "w:" +prefix = "w" diff --git a/addons/dialogic/Editor/Events/Fields/field_vector_base.gd b/addons/dialogic/Editor/Events/Fields/field_vector_base.gd index 5d5d9e95..c34b41c4 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector_base.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector_base.gd @@ -1,7 +1,12 @@ +@tool class_name DialogicVisualEditorFieldVector extends DialogicVisualEditorField ## Base type for Vector event blocks +var step := 0.001 : + set(val): + step = val + _on_step_changed(step) func _ready() -> void: for child in get_children(): @@ -36,3 +41,7 @@ func _on_sub_value_changed(sub_component: String, value: float) -> void: func _update_sub_component_text(value: Variant) -> void: pass + + +func _on_step_changed(step:float) -> void: + pass diff --git a/addons/dialogic/Editor/Events/Fields/field_vector_base.gd.uid b/addons/dialogic/Editor/Events/Fields/field_vector_base.gd.uid index cbf3f8bc..6273507a 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector_base.gd.uid +++ b/addons/dialogic/Editor/Events/Fields/field_vector_base.gd.uid @@ -1 +1 @@ -uid://knuu5u6056yv +uid://c25u8dv20exfr diff --git a/addons/dialogic/Editor/Events/event_field.gd b/addons/dialogic/Editor/Events/event_field.gd index f5db871f..920758e1 100644 --- a/addons/dialogic/Editor/Events/event_field.gd +++ b/addons/dialogic/Editor/Events/event_field.gd @@ -2,6 +2,7 @@ class_name DialogicVisualEditorField extends Control +@warning_ignore("unused_signal") signal value_changed(property_name:String, value:Variant) var property_name := "" @@ -11,12 +12,12 @@ var event_resource: DialogicEvent = null ################################################################################ ## To be overwritten -func _load_display_info(info:Dictionary) -> void: +func _load_display_info(_info:Dictionary) -> void: pass ## To be overwritten -func _set_value(value:Variant) -> void: +func _set_value(_value:Variant) -> void: pass diff --git a/addons/dialogic/Editor/Events/event_field.gd.uid b/addons/dialogic/Editor/Events/event_field.gd.uid index 80a46506..47e9cfe7 100644 --- a/addons/dialogic/Editor/Events/event_field.gd.uid +++ b/addons/dialogic/Editor/Events/event_field.gd.uid @@ -1 +1 @@ -uid://b8c84dsomcgp8 +uid://cbwisirnxfqtm diff --git a/addons/dialogic/Editor/HomePage/home_page.gd.uid b/addons/dialogic/Editor/HomePage/home_page.gd.uid index 620775c5..80bfac75 100644 --- a/addons/dialogic/Editor/HomePage/home_page.gd.uid +++ b/addons/dialogic/Editor/HomePage/home_page.gd.uid @@ -1 +1 @@ -uid://r0kest3cexsb +uid://bl3vudjf3wn2x diff --git a/addons/dialogic/Editor/HomePage/home_page.tscn b/addons/dialogic/Editor/HomePage/home_page.tscn index 73eff2b0..5e917570 100644 --- a/addons/dialogic/Editor/HomePage/home_page.tscn +++ b/addons/dialogic/Editor/HomePage/home_page.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=23 format=3 uid="uid://cqy73hshqqgga"] -[ext_resource type="Script" uid="uid://r0kest3cexsb" path="res://addons/dialogic/Editor/HomePage/home_page.gd" id="1_6g38w"] +[ext_resource type="Script" uid="uid://bl3vudjf3wn2x" path="res://addons/dialogic/Editor/HomePage/home_page.gd" id="1_6g38w"] [ext_resource type="Texture2D" uid="uid://cvmlp5nxb2rer" path="res://addons/dialogic/Editor/HomePage/icon_bg.png" id="1_ed1g1"] [ext_resource type="Texture2D" uid="uid://bt87p6qlso0ya" path="res://addons/dialogic/Editor/Images/dialogic-logo.svg" id="3_3leok"] diff --git a/addons/dialogic/Editor/Images/Resources/timeline.svg b/addons/dialogic/Editor/Images/Resources/timeline.svg new file mode 100644 index 00000000..fd0a48ad --- /dev/null +++ b/addons/dialogic/Editor/Images/Resources/timeline.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + diff --git a/addons/dialogic/Editor/Images/Resources/timeline.svg.import b/addons/dialogic/Editor/Images/Resources/timeline.svg.import new file mode 100644 index 00000000..aaa55219 --- /dev/null +++ b/addons/dialogic/Editor/Images/Resources/timeline.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://j7ym07anlusi" +path="res://.godot/imported/timeline.svg-4b0b3233c6ce249f8277502cd9b13eaf.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogic/Editor/Images/Resources/timeline.svg" +dest_files=["res://.godot/imported/timeline.svg-4b0b3233c6ce249f8277502cd9b13eaf.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg b/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg index 5fa7ac13..6f09e2e5 100644 --- a/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg +++ b/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg @@ -1,7 +1,61 @@ - - - - - - + + + + + + + + + diff --git a/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg.import b/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg.import index 807fec0a..9f497f95 100644 --- a/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg.import +++ b/addons/dialogic/Editor/Images/Toolbar/add-timeline.svg.import @@ -19,6 +19,8 @@ dest_files=["res://.godot/imported/add-timeline.svg-86961b528ebdf01f585931a15fea compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -26,6 +28,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/addons/dialogic/Editor/Inspector/inspector_plugin.gd.uid b/addons/dialogic/Editor/Inspector/inspector_plugin.gd.uid index 2dedf138..b44f0e5a 100644 --- a/addons/dialogic/Editor/Inspector/inspector_plugin.gd.uid +++ b/addons/dialogic/Editor/Inspector/inspector_plugin.gd.uid @@ -1 +1 @@ -uid://bg23uw15w7ik5 +uid://bok1je25mskp7 diff --git a/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd b/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd index 6e617fea..78274d14 100644 --- a/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd +++ b/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd @@ -22,7 +22,7 @@ func _init() -> void: field.fit_text_length = false field.valid_file_drop_extension = ".dtl" field.value_changed.connect(_on_field_value_changed) - field.get_suggestions_func = get_timeline_suggestions + field.suggestions_func = get_timeline_suggestions button = Button.new() hbox.add_child(button) @@ -49,7 +49,7 @@ func _on_field_value_changed(property:String, value:Variant) -> void: func _update_property() -> void: - field.resource_icon = get_theme_icon("TripleBar", "EditorIcons") + field.resource_icon = load("res://addons/dialogic/Editor/Images/Resources/timeline.svg") button.icon = get_theme_icon("ExternalLink", "EditorIcons") # Read the current value from the property. @@ -61,7 +61,7 @@ func _update_property() -> void: updating = true current_value = new_value if current_value: - field.set_value(DialogicResourceUtil.get_unique_identifier(current_value.resource_path)) + field.set_value(current_value.get_identifier()) button.show() else: button.hide() diff --git a/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd.uid b/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd.uid index b02241e2..47a91e01 100644 --- a/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd.uid +++ b/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd.uid @@ -1 +1 @@ -uid://b00fydu3snk85 +uid://58xvx63rw20a diff --git a/addons/dialogic/Editor/Settings/csv_file.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/csv_file.gd similarity index 100% rename from addons/dialogic/Editor/Settings/csv_file.gd rename to addons/dialogic/Editor/Settings/CoreSettingsPages/csv_file.gd diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/csv_file.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/csv_file.gd.uid new file mode 100644 index 00000000..6b17b204 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/csv_file.gd.uid @@ -0,0 +1 @@ +uid://ddof34f216ceq diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd new file mode 100644 index 00000000..5b855125 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd @@ -0,0 +1,154 @@ +@tool +extends DialogicSettingsPage + +## Settings tab that holds dialogic editor settings. + +const _SETTING_IMAGE_PREVIEW_HEIGHT = "image_preview_height" +const _SETTING_EVENT_BLOCK_MARGIN = "event_block_margin" +const _SETTING_SHOW_EVENT_NAMES = "show_event_names" + +const _SETTING_EVENT_COLOR_PALETTE = "color_palette" +const _SETTING_EVENT_SECTION_ODER = "event_section_order" + +var do_timeline_editor_refresh_on_close := false + +func _get_title() -> String: + return "Editor" + + +func _get_priority() -> int: + return 98 + + +func _refresh() -> void: + do_timeline_editor_refresh_on_close = false + %ImagePreviewHeight.value = DialogicUtil.get_editor_setting(_SETTING_IMAGE_PREVIEW_HEIGHT, 100) + %EventBlockMargin.value = DialogicUtil.get_editor_setting(_SETTING_EVENT_BLOCK_MARGIN, 0) + %ShowEventNames.set_pressed_no_signal(DialogicUtil.get_editor_setting(_SETTING_SHOW_EVENT_NAMES, false)) + + update_color_palette() + reload_section_list() + + +func _ready() -> void: + %ResetColorsButton.icon = get_theme_icon("Reload", "EditorIcons") + %ResetColorsButton.pressed.connect(_on_reset_colors_button) + + %ImagePreviewHeight.value_changed.connect(_on_ImagePreviewHeight_value_changed) + %EventBlockMargin.value_changed.connect(_on_EventBlockMargin_value_changed) + %ShowEventNames.toggled.connect(_on_ShowEventNames_toggled) + + +func _about_to_close(): + if do_timeline_editor_refresh_on_close: + refresh_visual_timeline_editor() + + +func refresh_visual_timeline_editor() -> void: + var timeline_node: DialogicEditor = settings_editor.editors_manager.editors["Timeline"]["node"] + timeline_node.get_node("%VisualEditor").load_event_buttons() + + # If the visual editor is open, close and reopen the timeline to have the colors reloaded. + if timeline_node.get_node("%VisualEditor").visible: + + var current_timeline := timeline_node.current_resource + settings_editor.editors_manager.clear_editor(timeline_node) + + settings_editor.editors_manager.edit_resource(current_timeline, true, true) + + + +#region SECTION ORDER +################################################################################ + +func reload_section_list(): + %SectionList.clear() + %SectionList.create_item() + var cached_events := DialogicResourceUtil.get_event_cache() + var sections := [] + var section_order: Array = DialogicUtil.get_editor_setting(_SETTING_EVENT_SECTION_ODER, ['Main', 'Logic', 'Flow', 'Audio', 'Visuals','Other', 'Helper']) + for ev in cached_events: + if !ev.event_category in sections: + sections.append(ev.event_category) + var item: TreeItem = %SectionList.create_item(null) + item.set_text(0, ev.event_category) + item.add_button(0, get_theme_icon("ArrowUp", "EditorIcons")) + item.add_button(0, get_theme_icon("ArrowDown", "EditorIcons")) + if ev.event_category in section_order: + + item.move_before(item.get_parent().get_child(min(section_order.find(ev.event_category),item.get_parent().get_child_count()-1))) + + %SectionList.get_root().get_child(0).set_button_disabled(0, 0, true) + %SectionList.get_root().get_child(-1).set_button_disabled(0, 1, true) + + +func _on_section_list_button_clicked(item:TreeItem, column, id, mouse_button_index): + if id == 0: + item.move_before(item.get_parent().get_child(item.get_index()-1)) + else: + item.move_after(item.get_parent().get_child(item.get_index()+1)) + + for child in %SectionList.get_root().get_children(): + child.set_button_disabled(0, 0, false) + child.set_button_disabled(0, 1, false) + + %SectionList.get_root().get_child(0).set_button_disabled(0, 0, true) + %SectionList.get_root().get_child(-1).set_button_disabled(0, 1, true) + + var sections := [] + for child in %SectionList.get_root().get_children(): + sections.append(child.get_text(0)) + + DialogicUtil.set_editor_setting(_SETTING_EVENT_SECTION_ODER, sections) + do_timeline_editor_refresh_on_close = true + +#endregion + + +#region COLOR PALETTE +################################################################################ + +## Completely reloads the color palette buttons +func update_color_palette() -> void: + for child in %Colors.get_children(): + child.queue_free() + for color in DialogicUtil.get_color_palette(): + var button := ColorPickerButton.new() + button.custom_minimum_size = Vector2(50 ,50) * DialogicUtil.get_editor_scale() + %Colors.add_child(button) + button.color = DialogicUtil.get_color(color) + button.popup_closed.connect(_on_palette_color_popup_closed) + + +func _on_palette_color_popup_closed() -> void: + var new_palette := {} + for i in %Colors.get_children(): + new_palette["Color"+str(i.get_index()+1)] = i.color + DialogicUtil.set_editor_setting(_SETTING_EVENT_COLOR_PALETTE, new_palette) + + do_timeline_editor_refresh_on_close = true + + +func _on_reset_colors_button() -> void: + DialogicUtil.set_editor_setting(_SETTING_EVENT_COLOR_PALETTE, null) + update_color_palette() + + do_timeline_editor_refresh_on_close = true + +#endregion + + + + +func _on_ImagePreviewHeight_value_changed(value:float) -> void: + DialogicUtil.set_editor_setting(_SETTING_IMAGE_PREVIEW_HEIGHT, value) + + +func _on_EventBlockMargin_value_changed(value:float) -> void: + DialogicUtil.set_editor_setting(_SETTING_EVENT_BLOCK_MARGIN, value) + do_timeline_editor_refresh_on_close = true + + +func _on_ShowEventNames_toggled(toggled:bool) -> void: + DialogicUtil.set_editor_setting(_SETTING_SHOW_EVENT_NAMES, toggled) + do_timeline_editor_refresh_on_close = true diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd.uid new file mode 100644 index 00000000..e273fb33 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd.uid @@ -0,0 +1 @@ +uid://3akc4p71r5rn diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.tscn b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.tscn new file mode 100644 index 00000000..4587e3f2 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.tscn @@ -0,0 +1,161 @@ +[gd_scene load_steps=5 format=3 uid="uid://dbdmosh6v536s"] + +[ext_resource type="Script" uid="uid://3akc4p71r5rn" path="res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.gd" id="1_kdw7t"] +[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_ey6hj"] + +[sub_resource type="Image" id="Image_1n4qk"] +data = { +"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", +"height": 16, +"mipmaps": false, +"width": 16 +} + +[sub_resource type="ImageTexture" id="ImageTexture_dfv70"] +image = SubResource("Image_1n4qk") + +[node name="EditorSettingsPage" type="VBoxContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_kdw7t") + +[node name="PaletteTitle" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="SectionPaletteTitle" type="Label" parent="PaletteTitle"] +layout_mode = 2 +theme_type_variation = &"DialogicSettingsSection" +text = "Color Palette" + +[node name="HintTooltip" parent="PaletteTitle" instance=ExtResource("2_ey6hj")] +layout_mode = 2 +tooltip_text = "These colors are used for the events." +texture = null +hint_text = "These colors are used for the events." + +[node name="ResetColorsButton" type="Button" parent="PaletteTitle"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +tooltip_text = "Reset Colors to default" +icon = SubResource("ImageTexture_dfv70") +flat = true + +[node name="ScrollContainer" type="ScrollContainer" parent="."] +layout_mode = 2 +horizontal_scroll_mode = 3 +vertical_scroll_mode = 0 + +[node name="Colors" type="HBoxContainer" parent="ScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="HSeparator" type="HSeparator" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="TimelineTitle" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="SectionTimelineTitle" type="Label" parent="TimelineTitle"] +layout_mode = 2 +theme_type_variation = &"DialogicSettingsSection" +text = "Visual Events" + +[node name="HintTooltip" parent="TimelineTitle" instance=ExtResource("2_ey6hj")] +layout_mode = 2 +texture = null +hint_text = "These settings affect the visual timeline editor." + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="HBoxContainer"] +layout_mode = 2 +text = "Image preview height" + +[node name="HintTooltip" parent="HBoxContainer" instance=ExtResource("2_ey6hj")] +layout_mode = 2 +texture = null +hint_text = "If set to 0, image previews will be disabled." + +[node name="ImagePreviewHeight" type="SpinBox" parent="HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +rounded = true +allow_greater = true +update_on_text_changed = true +suffix = "px" +select_all_on_focus = true + +[node name="HBoxContainer2" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="HBoxContainer2"] +layout_mode = 2 +text = "Event block bottom margin" + +[node name="HintTooltip" parent="HBoxContainer2" instance=ExtResource("2_ey6hj")] +layout_mode = 2 +texture = null +hint_text = "This adds extra space at the bottom of event blocks." + +[node name="EventBlockMargin" type="SpinBox" parent="HBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +rounded = true +allow_greater = true +update_on_text_changed = true +suffix = "px" +select_all_on_focus = true + +[node name="HBoxContainer3" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="HBoxContainer3"] +layout_mode = 2 +text = "Show event names" + +[node name="HintTooltip" parent="HBoxContainer3" instance=ExtResource("2_ey6hj")] +layout_mode = 2 +texture = null +hint_text = "Enabling this prepends the event name at the beginning of event blocks." + +[node name="ShowEventNames" type="CheckButton" parent="HBoxContainer3"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="HSeparator5" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="HBoxContainer4" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="SectionSections" type="Label" parent="HBoxContainer4"] +layout_mode = 2 +theme_type_variation = &"DialogicSettingsSection" +text = "Section Order" + +[node name="HintTooltip" parent="HBoxContainer4" instance=ExtResource("2_ey6hj")] +layout_mode = 2 +tooltip_text = "You can change the order of the event sections here. " +texture = null +hint_text = "You can change the order of the event sections here. " + +[node name="SectionList" type="Tree" parent="."] +unique_name_in_owner = true +custom_minimum_size = Vector2(150, 150) +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/button_margin = 0 +allow_reselect = true +allow_rmb_select = true +hide_folding = true +hide_root = true +drop_mode_flags = 1 + +[connection signal="button_clicked" from="SectionList" to="." method="_on_section_list_button_clicked"] diff --git a/addons/dialogic/Editor/Settings/settings_general.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd similarity index 67% rename from addons/dialogic/Editor/Settings/settings_general.gd rename to addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd index 4587915a..d44907df 100644 --- a/addons/dialogic/Editor/Settings/settings_general.gd +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd @@ -22,9 +22,6 @@ func _ready() -> void: %ExtensionsFolderPicker.value_changed.connect(_on_ExtensionsFolder_value_changed) %PhysicsTimerButton.toggled.connect(_on_physics_timer_button_toggled) - # Colors - %ResetColorsButton.icon = get_theme_icon("Reload", "EditorIcons") - %ResetColorsButton.button_up.connect(_on_reset_colors_button) # Extension creator %ExtensionCreator.hide() @@ -35,76 +32,6 @@ func _refresh() -> void: %LayoutNodeEndBehaviour.select(ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0)) %ExtensionsFolderPicker.set_value(ProjectSettings.get_setting('dialogic/extensions_folder', 'res://addons/dialogic_additions')) - update_color_palette() - - %SectionList.clear() - %SectionList.create_item() - var cached_events := DialogicResourceUtil.get_event_cache() - var sections := [] - var section_order: Array = DialogicUtil.get_editor_setting('event_section_order', ['Main', 'Logic', 'Flow', 'Audio', 'Visuals','Other', 'Helper']) - for ev in cached_events: - if !ev.event_category in sections: - sections.append(ev.event_category) - var item: TreeItem = %SectionList.create_item(null) - item.set_text(0, ev.event_category) - item.add_button(0, get_theme_icon("ArrowUp", "EditorIcons")) - item.add_button(0, get_theme_icon("ArrowDown", "EditorIcons")) - if ev.event_category in section_order: - - item.move_before(item.get_parent().get_child(min(section_order.find(ev.event_category),item.get_parent().get_child_count()-1))) - - %SectionList.get_root().get_child(0).set_button_disabled(0, 0, true) - %SectionList.get_root().get_child(-1).set_button_disabled(0, 1, true) - - -func _on_section_list_button_clicked(item:TreeItem, column, id, mouse_button_index): - if id == 0: - item.move_before(item.get_parent().get_child(item.get_index()-1)) - else: - item.move_after(item.get_parent().get_child(item.get_index()+1)) - - for child in %SectionList.get_root().get_children(): - child.set_button_disabled(0, 0, false) - child.set_button_disabled(0, 1, false) - - %SectionList.get_root().get_child(0).set_button_disabled(0, 0, true) - %SectionList.get_root().get_child(-1).set_button_disabled(0, 1, true) - - var sections := [] - for child in %SectionList.get_root().get_children(): - sections.append(child.get_text(0)) - - DialogicUtil.set_editor_setting('event_section_order', sections) - force_event_button_list_reload() - - -func force_event_button_list_reload() -> void: - find_parent('EditorsManager').editors['Timeline'].node.get_node('%VisualEditor').load_event_buttons() - - -func update_color_palette() -> void: - # Color Palette - for child in %Colors.get_children(): - child.queue_free() - for color in DialogicUtil.get_color_palette(): - var button := ColorPickerButton.new() - button.custom_minimum_size = Vector2(50 ,50) * DialogicUtil.get_editor_scale() - %Colors.add_child(button) - button.color = DialogicUtil.get_color(color) - button.color_changed.connect(_on_color_change) - - -func _on_color_change(color:Color) -> void: - var new_palette := {} - for i in %Colors.get_children(): - new_palette['Color'+str(i.get_index()+1)] = i.color - DialogicUtil.set_editor_setting('color_palette', new_palette) - - - -func _on_reset_colors_button() -> void: - DialogicUtil.set_editor_setting('color_palette', null) - update_color_palette() func _on_physics_timer_button_toggled(is_toggled: bool) -> void: @@ -242,6 +169,9 @@ func load_game_state(load_flag:=LoadFlags.FULL_LOAD) -> void: force_event_button_list_reload() +func force_event_button_list_reload() -> void: + find_parent('EditorsManager').editors['Timeline'].node.get_node('%VisualEditor').load_event_buttons() + func _on_reload_pressed() -> void: DialogicUtil._update_autoload_subsystem_access() diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd.uid new file mode 100644 index 00000000..7acfdfcf --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd.uid @@ -0,0 +1 @@ +uid://chb81lvjh47jr diff --git a/addons/dialogic/Editor/Settings/settings_general.tscn b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.tscn similarity index 52% rename from addons/dialogic/Editor/Settings/settings_general.tscn rename to addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.tscn index 766ad058..777d634c 100644 --- a/addons/dialogic/Editor/Settings/settings_general.tscn +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.tscn @@ -1,21 +1,11 @@ [gd_scene load_steps=6 format=3 uid="uid://b873ho41sklv8"] -[ext_resource type="Script" uid="uid://b3clj6o1qcpvn" path="res://addons/dialogic/Editor/Settings/settings_general.gd" id="2"] +[ext_resource type="Script" uid="uid://chb81lvjh47jr" path="res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.gd" id="2"] +[ext_resource type="Script" uid="uid://bo0dfmsyky1mm" path="res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd" id="2_3xeuv"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_kqhx5"] +[ext_resource type="Script" uid="uid://vg4wbm0n64ws" path="res://addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd" id="3_dbfvv"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="3_i7rug"] -[sub_resource type="Image" id="Image_ssidd"] -data = { -"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_4wgbv"] -image = SubResource("Image_ssidd") - [node name="General" type="VBoxContainer"] anchors_preset = 15 anchor_right = 1.0 @@ -24,55 +14,49 @@ grow_horizontal = 2 grow_vertical = 2 script = ExtResource("2") -[node name="PaletteTitle" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="SectionPaletteTitle" type="Label" parent="PaletteTitle"] -layout_mode = 2 -theme_type_variation = &"DialogicSettingsSection" -text = "Color Palette" - -[node name="HintTooltip" parent="PaletteTitle" instance=ExtResource("2_kqhx5")] -layout_mode = 2 -tooltip_text = "These colors are used for the events." -texture = SubResource("ImageTexture_4wgbv") -hint_text = "These colors are used for the events." - -[node name="ResetColorsButton" type="Button" parent="PaletteTitle"] -unique_name_in_owner = true -layout_mode = 2 -size_flags_horizontal = 0 -tooltip_text = "Reset Colors to default" -icon = SubResource("ImageTexture_4wgbv") -flat = true - -[node name="ScrollContainer" type="ScrollContainer" parent="."] -layout_mode = 2 -horizontal_scroll_mode = 3 -vertical_scroll_mode = 0 - -[node name="Colors" type="HBoxContainer" parent="ScrollContainer"] -unique_name_in_owner = true -layout_mode = 2 - -[node name="HSeparator" type="HSeparator" parent="."] -layout_mode = 2 - [node name="HBoxContainer2" type="HBoxContainer" parent="."] layout_mode = 2 -[node name="SectionBehaviourTitle" type="Label" parent="HBoxContainer2"] +[node name="SectionToolsTitle" type="Label" parent="HBoxContainer2"] +layout_mode = 2 +theme_type_variation = &"DialogicSettingsSection" +text = "Tools" + +[node name="Tools" type="Node" parent="."] +script = ExtResource("2_3xeuv") + +[node name="ResaveTool" type="Node" parent="Tools"] +script = ExtResource("3_dbfvv") + +[node name="ToolButtons" type="VBoxContainer" parent="."] +unique_name_in_owner = true +layout_mode = 2 + +[node name="ToolProgress" type="ProgressBar" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 2 +max_value = 1.0 +value = 1.0 + +[node name="HSeparator5" type="HSeparator" parent="."] +layout_mode = 2 + +[node name="HBoxContainer5" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="SectionBehaviourTitle" type="Label" parent="HBoxContainer5"] layout_mode = 2 theme_type_variation = &"DialogicSettingsSection" text = "Layout Node Behaviour" -[node name="HintTooltip" parent="HBoxContainer2" instance=ExtResource("2_kqhx5")] +[node name="HintTooltip" parent="HBoxContainer5" instance=ExtResource("2_kqhx5")] layout_mode = 2 tooltip_text = "The layout scene configured in the Layout editor is automatically instanced when calling Dialogic.start(). Depending on your game, you might want it to be deleted after the dialogue, be hidden (as reinstancing often is wasting resources) or kept visible. " -texture = SubResource("ImageTexture_4wgbv") +texture = null hint_text = "The layout scene configured in the Layout editor is automatically instanced when calling Dialogic.start(). Depending on your game, you might want it to be deleted after the dialogue, be hidden @@ -88,11 +72,10 @@ text = "On timeline end" [node name="LayoutNodeEndBehaviour" type="OptionButton" parent="HBoxContainer3"] unique_name_in_owner = true layout_mode = 2 -item_count = 3 selected = 0 fit_to_longest_item = false +item_count = 3 popup/item_0/text = "Delete Layout Node" -popup/item_0/id = 0 popup/item_1/text = "Hide Layout Node" popup/item_1/id = 1 popup/item_2/text = "Keep Layout Node" @@ -121,7 +104,7 @@ layout_mode = 2 tooltip_text = "Configure where dialogic looks for custom modules. You will have to restart the project to see the change take action." -texture = SubResource("ImageTexture_4wgbv") +texture = null hint_text = "Configure where dialogic looks for custom modules. You will have to restart the project to see the change take action." @@ -144,7 +127,6 @@ layout_mode = 2 size_flags_horizontal = 3 placeholder = "res://addons/dialogic_additions/Events" file_mode = 2 -resource_icon = SubResource("ImageTexture_4wgbv") [node name="VSeparator" type="VSeparator" parent="HBoxContainer6"] layout_mode = 2 @@ -169,7 +151,7 @@ text = "Extension Creator " [node name="HintTooltip" parent="HBoxContainer6/ExtensionsPanel/VBox/HBoxContainer6" instance=ExtResource("2_kqhx5")] layout_mode = 2 tooltip_text = "Use the Exension Creator to quickly setup custom modules!" -texture = SubResource("ImageTexture_4wgbv") +texture = null hint_text = "Use the Exension Creator to quickly setup custom modules!" [node name="CreateExtensionButton" type="Button" parent="HBoxContainer6/ExtensionsPanel/VBox"] @@ -203,10 +185,9 @@ text = "Setup mode:" [node name="ExtensionMode" type="OptionButton" parent="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/ExtensionCreatorOptions"] unique_name_in_owner = true layout_mode = 2 -item_count = 4 selected = 0 +item_count = 4 popup/item_0/text = "Event only" -popup/item_0/id = 0 popup/item_1/text = "Event+Subsystem" popup/item_1/id = 1 popup/item_2/text = "Subsystem only" @@ -233,7 +214,7 @@ text = "Timer processing" [node name="HintTooltip" parent="HBoxContainer7" instance=ExtResource("2_kqhx5")] layout_mode = 2 tooltip_text = "Change whether dialogics timers process in physics_process (frame-rate independent) or process." -texture = SubResource("ImageTexture_4wgbv") +texture = null hint_text = "Change whether dialogics timers process in physics_process (frame-rate independent) or process." [node name="HBoxContainer4" type="HBoxContainer" parent="."] @@ -247,37 +228,7 @@ text = "Process timers in physics_process" unique_name_in_owner = true layout_mode = 2 -[node name="HSeparator5" type="HSeparator" parent="."] -layout_mode = 2 - -[node name="HBoxContainer" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="SectionSections" type="Label" parent="HBoxContainer"] -layout_mode = 2 -theme_type_variation = &"DialogicSettingsSection" -text = "Section Order" - -[node name="HintTooltip" parent="HBoxContainer" instance=ExtResource("2_kqhx5")] -layout_mode = 2 -tooltip_text = "You can change the order of the event sections here. " -texture = SubResource("ImageTexture_4wgbv") -hint_text = "You can change the order of the event sections here. " - -[node name="SectionList" type="Tree" parent="."] -unique_name_in_owner = true -custom_minimum_size = Vector2(150, 150) -layout_mode = 2 -size_flags_horizontal = 3 -theme_override_constants/button_margin = 0 -allow_reselect = true -allow_rmb_select = true -hide_folding = true -hide_root = true -drop_mode_flags = 1 - [connection signal="item_selected" from="HBoxContainer3/LayoutNodeEndBehaviour" to="." method="_on_layout_node_end_behaviour_item_selected"] [connection signal="pressed" from="HBoxContainer6/HBoxContainer4/HBoxContainer5/Reload" to="." method="_on_reload_pressed"] [connection signal="pressed" from="HBoxContainer6/ExtensionsPanel/VBox/CreateExtensionButton" to="." method="_on_create_extension_button_pressed"] [connection signal="pressed" from="HBoxContainer6/ExtensionsPanel/VBox/ExtensionCreator/SubmitExtensionButton" to="." method="_on_submit_extension_button_pressed"] -[connection signal="button_clicked" from="SectionList" to="." method="_on_section_list_button_clicked"] diff --git a/addons/dialogic/Editor/Settings/settings_modules.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd similarity index 99% rename from addons/dialogic/Editor/Settings/settings_modules.gd rename to addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd index 008453e8..a9f159dd 100644 --- a/addons/dialogic/Editor/Settings/settings_modules.gd +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd @@ -440,4 +440,3 @@ func _on_event_default_value_changed(prop:String, value:Variant) -> void: func _on_event_default_bool_toggled(value:bool, prop:String) -> void: set_event_default_override(prop, value) - diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd.uid new file mode 100644 index 00000000..1ad48049 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd.uid @@ -0,0 +1 @@ +uid://bcu347pvraog6 diff --git a/addons/dialogic/Editor/Settings/settings_modules.tscn b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.tscn similarity index 98% rename from addons/dialogic/Editor/Settings/settings_modules.tscn rename to addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.tscn index c7a68b19..db242b8b 100644 --- a/addons/dialogic/Editor/Settings/settings_modules.tscn +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=7 format=3 uid="uid://o7ljiritpgap"] -[ext_resource type="Script" uid="uid://cpjf8y5xw834m" path="res://addons/dialogic/Editor/Settings/settings_modules.gd" id="1_l2hk0"] +[ext_resource type="Script" uid="uid://bcu347pvraog6" path="res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.gd" id="1_l2hk0"] -[sub_resource type="Image" id="Image_edthq"] +[sub_resource type="Image" id="Image_1yyxk"] data = { "data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", @@ -12,9 +12,9 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_lce2m"] -image = SubResource("Image_edthq") +image = SubResource("Image_1yyxk") -[sub_resource type="Image" id="Image_ub3c3"] +[sub_resource type="Image" id="Image_bclq7"] 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", @@ -24,7 +24,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_137g7"] -image = SubResource("Image_ub3c3") +image = SubResource("Image_bclq7") [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_315cl"] content_margin_left = 4.0 diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd new file mode 100644 index 00000000..6b84a79b --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd @@ -0,0 +1,80 @@ +@tool +extends Node + +var tool_thread : Thread +var tool_progress := 1.0 +var tool_progress_mutex : Mutex +signal tool_finished_signal + + +func _ready() -> void: + for button in %ToolButtons.get_children(): + button.queue_free() + + for i in get_children(): + var button := Button.new() + button.text = i.button_text + button.tooltip_text = i.tooltip + button.pressed.connect(execute_tool.bind(i.method)) + %ToolButtons.add_child(button) + + +func execute_tool(method:Callable) -> void: + for button in %ToolButtons.get_children(): + button.disabled = true + + var prev_timeline := close_active_timeline() + await get_tree().process_frame + if tool_thread and tool_thread.is_alive(): + tool_thread.wait_to_finish() + + tool_thread = Thread.new() + tool_progress_mutex = Mutex.new() + tool_thread.start(method) + + await tool_finished_signal + silently_open_timeline(prev_timeline) + for button in %ToolButtons.get_children(): + button.disabled = false + + +func _process(_delta: float) -> void: + if (tool_thread and tool_thread.is_alive()) or %ToolProgress.value < 1: + if tool_progress_mutex: tool_progress_mutex.lock() + %ToolProgress.value = tool_progress + if tool_progress_mutex: tool_progress_mutex.unlock() + %ToolProgress.show() + if %ToolProgress.value == 1: + tool_finished_signal.emit() + %ToolProgress.hide() + + +func _exit_tree() -> void: + if tool_thread: + tool_thread.wait_to_finish() + + + +#region HELPERS + +## Closes the current timeline in the Dialogic Editor and returns the timeline +## as a resource. +## If no timeline has been opened, returns null. +func close_active_timeline() -> Resource: + var timeline_node: DialogicEditor = get_parent().settings_editor.editors_manager.editors['Timeline']['node'] + # We will close this timeline to ensure it will properly update. + # By saving this reference, we can open it again. + var current_timeline := timeline_node.current_resource + # Clean the current editor, this will also close the timeline. + get_parent().settings_editor.editors_manager.clear_editor(timeline_node, true) + + return current_timeline + + +## Opens the timeline resource into the Dialogic Editor. +## If the timeline is null, does nothing. +func silently_open_timeline(timeline_to_open: Resource) -> void: + if timeline_to_open != null: + get_parent().settings_editor.editors_manager.edit_resource(timeline_to_open, true, true) + +#endregion diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd.uid new file mode 100644 index 00000000..f01f9749 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_tools.gd.uid @@ -0,0 +1 @@ +uid://bo0dfmsyky1mm diff --git a/addons/dialogic/Editor/Settings/settings_translation.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd similarity index 99% rename from addons/dialogic/Editor/Settings/settings_translation.gd rename to addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd index fe0714ed..d882ec7f 100644 --- a/addons/dialogic/Editor/Settings/settings_translation.gd +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd @@ -8,7 +8,6 @@ enum TranslationModes {PER_PROJECT, PER_TIMELINE, NONE} enum SaveLocationModes {INSIDE_TRANSLATION_FOLDER, NEXT_TO_TIMELINE, NONE} var loading := false -@onready var settings_editor: Control = find_parent('Settings') ## The default CSV filename that contains the translations for character ## properties. @@ -36,10 +35,10 @@ func _is_feature_tab() -> bool: func _ready() -> void: %TransEnabled.toggled.connect(store_changes) - %OrigLocale.get_suggestions_func = get_locales + %OrigLocale.suggestions_func = get_locales %OrigLocale.resource_icon = get_theme_icon("Translation", "EditorIcons") %OrigLocale.value_changed.connect(store_changes) - %TestingLocale.get_suggestions_func = get_locales + %TestingLocale.suggestions_func = get_locales %TestingLocale.resource_icon = get_theme_icon("Translation", "EditorIcons") %TestingLocale.value_changed.connect(store_changes) %TransFolderPicker.value_changed.connect(store_changes) diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd.uid new file mode 100644 index 00000000..76f5d8fa --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd.uid @@ -0,0 +1 @@ +uid://b0bm772xo8n2j diff --git a/addons/dialogic/Editor/Settings/settings_translation.tscn b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.tscn similarity index 98% rename from addons/dialogic/Editor/Settings/settings_translation.tscn rename to addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.tscn index f1afac67..eadce4ad 100644 --- a/addons/dialogic/Editor/Settings/settings_translation.tscn +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.tscn @@ -1,11 +1,11 @@ [gd_scene load_steps=7 format=3 uid="uid://chpb1mj03xjxv"] -[ext_resource type="Script" uid="uid://3cf5qeqgf0a0" path="res://addons/dialogic/Editor/Settings/settings_translation.gd" id="1_dvmyi"] +[ext_resource type="Script" uid="uid://b0bm772xo8n2j" path="res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.gd" id="1_dvmyi"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_k2lou"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3_dq4j2"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="4_kvsma"] -[sub_resource type="Image" id="Image_4ypqi"] +[sub_resource type="Image" id="Image_4jaem"] data = { "data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", @@ -15,7 +15,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_xbph7"] -image = SubResource("Image_4ypqi") +image = SubResource("Image_4jaem") [node name="Translations" type="VBoxContainer"] anchors_preset = 15 diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd b/addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd new file mode 100644 index 00000000..03200bb9 --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd @@ -0,0 +1,32 @@ +@tool +extends Node + +@onready var ToolUtil := get_parent() + +var button_text := "Resave all timelines" +var tooltip := "Opens and resaves all timelines. This can be useful if an update introduced a syntax change." +var method := resave_tool + + +func resave_tool() -> void: + ToolUtil.tool_progress_mutex.lock() + ToolUtil.tool_progress = 0 + ToolUtil.tool_progress_mutex.unlock() + + var index := 0 + var timelines := DialogicResourceUtil.get_timeline_directory() + for timeline_identifier in timelines: + var timeline := DialogicResourceUtil.get_timeline_resource(timeline_identifier) + await timeline.process() + timeline.set_meta("timeline_not_saved", true) + ResourceSaver.save(timeline) + + ToolUtil.tool_progress_mutex.lock() + ToolUtil.tool_progress = 1.0/len(timelines)*index + ToolUtil.tool_progress_mutex.unlock() + + index += 1 + + ToolUtil.tool_progress_mutex.lock() + ToolUtil.tool_progress = 1 + ToolUtil.tool_progress_mutex.unlock() diff --git a/addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd.uid b/addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd.uid new file mode 100644 index 00000000..738db88a --- /dev/null +++ b/addons/dialogic/Editor/Settings/CoreSettingsPages/tool_resave.gd.uid @@ -0,0 +1 @@ +uid://vg4wbm0n64ws diff --git a/addons/dialogic/Editor/Settings/HintLabelStylingScript.gd.uid b/addons/dialogic/Editor/Settings/HintLabelStylingScript.gd.uid index 25c74ffc..37185c92 100644 --- a/addons/dialogic/Editor/Settings/HintLabelStylingScript.gd.uid +++ b/addons/dialogic/Editor/Settings/HintLabelStylingScript.gd.uid @@ -1 +1 @@ -uid://p5sl8ccpekpq +uid://dhl3w5a4mujud diff --git a/addons/dialogic/Editor/Settings/csv_file.gd.uid b/addons/dialogic/Editor/Settings/csv_file.gd.uid deleted file mode 100644 index ebcc7ba8..00000000 --- a/addons/dialogic/Editor/Settings/csv_file.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cwqw4smlpi6kx diff --git a/addons/dialogic/Editor/Settings/settings_editor.gd b/addons/dialogic/Editor/Settings/settings_editor.gd index 3d87c4ab..0e01464e 100644 --- a/addons/dialogic/Editor/Settings/settings_editor.gd +++ b/addons/dialogic/Editor/Settings/settings_editor.gd @@ -24,9 +24,10 @@ func _ready() -> void: if get_parent() is SubViewport: return - register_settings_section("res://addons/dialogic/Editor/Settings/settings_general.tscn") - register_settings_section("res://addons/dialogic/Editor/Settings/settings_translation.tscn") - register_settings_section("res://addons/dialogic/Editor/Settings/settings_modules.tscn") + register_settings_section("res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_general.tscn") + register_settings_section("res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_editor.tscn") + register_settings_section("res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_translation.tscn") + register_settings_section("res://addons/dialogic/Editor/Settings/CoreSettingsPages/settings_modules.tscn") for indexer in DialogicUtil.get_indexers(): for settings_page in indexer._get_settings_pages(): @@ -166,4 +167,3 @@ func refresh() -> void: for child in %SettingsContent.get_children(): if child.get_meta('section').has_method('_refresh'): child.get_meta('section')._refresh() - diff --git a/addons/dialogic/Editor/Settings/settings_editor.gd.uid b/addons/dialogic/Editor/Settings/settings_editor.gd.uid index 58aaa088..69a43aa7 100644 --- a/addons/dialogic/Editor/Settings/settings_editor.gd.uid +++ b/addons/dialogic/Editor/Settings/settings_editor.gd.uid @@ -1 +1 @@ -uid://dyjdv0hsuj2th +uid://c1virlyy8gl7 diff --git a/addons/dialogic/Editor/Settings/settings_editor.tscn b/addons/dialogic/Editor/Settings/settings_editor.tscn index 45ed0a2c..c7ed7a3b 100644 --- a/addons/dialogic/Editor/Settings/settings_editor.tscn +++ b/addons/dialogic/Editor/Settings/settings_editor.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://dganirw26brfb"] -[ext_resource type="Script" uid="uid://dyjdv0hsuj2th" path="res://addons/dialogic/Editor/Settings/settings_editor.gd" id="1"] +[ext_resource type="Script" uid="uid://c1virlyy8gl7" path="res://addons/dialogic/Editor/Settings/settings_editor.gd" id="1"] [node name="Settings" type="HSplitContainer"] anchors_preset = 15 diff --git a/addons/dialogic/Editor/Settings/settings_general.gd.uid b/addons/dialogic/Editor/Settings/settings_general.gd.uid deleted file mode 100644 index 13bdf4af..00000000 --- a/addons/dialogic/Editor/Settings/settings_general.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://b3clj6o1qcpvn diff --git a/addons/dialogic/Editor/Settings/settings_modules.gd.uid b/addons/dialogic/Editor/Settings/settings_modules.gd.uid deleted file mode 100644 index 3d3e4cf3..00000000 --- a/addons/dialogic/Editor/Settings/settings_modules.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://cpjf8y5xw834m diff --git a/addons/dialogic/Editor/Settings/settings_page.gd b/addons/dialogic/Editor/Settings/settings_page.gd index 2b7dd811..06c1b789 100644 --- a/addons/dialogic/Editor/Settings/settings_page.gd +++ b/addons/dialogic/Editor/Settings/settings_page.gd @@ -3,6 +3,7 @@ extends Control class_name DialogicSettingsPage @export_multiline var short_info := "" +@onready var settings_editor: Control = find_parent('Settings') ## Called to get the title of the page func _get_title() -> String: diff --git a/addons/dialogic/Editor/Settings/settings_page.gd.uid b/addons/dialogic/Editor/Settings/settings_page.gd.uid index 1e770f21..cf365d64 100644 --- a/addons/dialogic/Editor/Settings/settings_page.gd.uid +++ b/addons/dialogic/Editor/Settings/settings_page.gd.uid @@ -1 +1 @@ -uid://kqjgculyl34h +uid://be8xcha2jwdur diff --git a/addons/dialogic/Editor/Settings/settings_translation.gd.uid b/addons/dialogic/Editor/Settings/settings_translation.gd.uid deleted file mode 100644 index b80f3ce9..00000000 --- a/addons/dialogic/Editor/Settings/settings_translation.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://3cf5qeqgf0a0 diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd b/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd index 8a12cd5e..28179512 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd @@ -23,9 +23,10 @@ var shortcode_events := {} var custom_syntax_events := [] var text_event: DialogicTextEvent = null + func _ready() -> void: # Compile RegEx's - completion_word_regex.compile("(?(\\W)|^)(?\\w*)\\x{FFFF}") + completion_word_regex.compile(r"(?(\W)|^)(?[\w]*)\x{FFFF}") completion_shortcode_getter_regex.compile("\\[(?\\w*)") completion_shortcode_param_getter_regex.compile("(?\\w*)\\W*=\\s*\"?(\\w|\\s)*"+String.chr(0xFFFF)) completion_shortcode_value_regex.compile(r'(\[|\s)[^\[\s=]*="(?[^"$]*)'+String.chr(0xFFFF)) @@ -143,25 +144,9 @@ func request_code_completion(force:bool, text:CodeEdit, mode:=Modes.FULL_HIGHLIG # suggest values elif symbol == '=' or symbol == '"': - var current_parameter_gex := completion_shortcode_param_getter_regex.search(line) - if !current_parameter_gex: - text.update_code_completion_options(false) - return - - var current_parameter := current_parameter_gex.get_string('param') - if !shortcode_events[code].get_shortcode_parameters().has(current_parameter): - text.update_code_completion_options(false) - return - if !shortcode_events[code].get_shortcode_parameters()[current_parameter].has('suggestions'): - if typeof(shortcode_events[code].get_shortcode_parameters()[current_parameter].default) == TYPE_BOOL: - suggest_bool(text, shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3)) - elif len(word) > 0: - text.add_code_completion_option(CodeEdit.KIND_VARIABLE, word, word, shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3), text.get_theme_icon("GuiScrollArrowRight", "EditorIcons"), '" ') - text.update_code_completion_options(true) - return - - var suggestions: Dictionary = shortcode_events[code].get_shortcode_parameters()[current_parameter]['suggestions'].call() - suggest_custom_suggestions(suggestions, text, shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3)) + suggest_shortcode_values(text, shortcode_events[code], line, word) + text.update_code_completion_options(true) + return # Force update and showing of the popup text.update_code_completion_options(true) @@ -172,7 +157,7 @@ func request_code_completion(force:bool, text:CodeEdit, mode:=Modes.FULL_HIGHLIG if mode == Modes.TEXT_EVENT_ONLY and !event is DialogicTextEvent: continue - if ! ' ' in line_part: + if not ' ' in line_part: event._get_start_code_completion(self, text) if event.is_valid_event(line): @@ -182,19 +167,23 @@ func request_code_completion(force:bool, text:CodeEdit, mode:=Modes.FULL_HIGHLIG # Force update and showing of the popup text.update_code_completion_options(true) + # USEFUL FOR DEBUGGING + #print(text.get_code_completion_options().map(func(x):return "{display_text}".format(x))) + # Helper that adds all characters as options -func suggest_characters(text:CodeEdit, type := CodeEdit.KIND_MEMBER, text_event_start:=false) -> void: +func suggest_characters(text:CodeEdit, type := CodeEdit.KIND_MEMBER, event:DialogicEvent=null) -> void: for character in DialogicResourceUtil.get_character_directory(): var result: String = character if " " in character: result = '"'+character+'"' - if text_event_start and load(DialogicResourceUtil.get_character_directory()[character]).portraits.is_empty(): - result += ':' + if event and event is DialogicTextEvent and load(DialogicResourceUtil.get_character_directory()[character]).portraits.is_empty(): + result += ': ' + elif event and event is DialogicCharacterEvent: + result += " " text.add_code_completion_option(type, character, result, syntax_highlighter.character_name_color, load("res://addons/dialogic/Editor/Images/Resources/character.svg")) - # Helper that adds all timelines as options func suggest_timelines(text:CodeEdit, type := CodeEdit.KIND_MEMBER, color:=Color()) -> void: for timeline in DialogicResourceUtil.get_timeline_directory(): @@ -209,7 +198,7 @@ func suggest_labels(text:CodeEdit, timeline:String='', end:='', color:=Color()) # Helper that adds all portraits of a given character as options func suggest_portraits(text:CodeEdit, character_name:String, end_check:=')') -> void: - if !character_name in DialogicResourceUtil.get_character_directory(): + if not character_name in DialogicResourceUtil.get_character_directory(): return var character_resource: DialogicCharacter = load(DialogicResourceUtil.get_character_directory()[character_name]) for portrait in character_resource.portraits: @@ -238,10 +227,30 @@ func suggest_custom_suggestions(suggestions:Dictionary, text:CodeEdit, color:Col text.add_code_completion_option(CodeEdit.KIND_VARIABLE, key, str(suggestions[key].value), color, suggestions[key].get('icon', null), '" ') -# Filters the list of all possible options, depending on what was typed -# Purpose of the different Kinds is explained in [_request_code_completion] +func suggest_shortcode_values(text:CodeEdit, event:DialogicEvent, line:String, word:String) -> void: + var current_parameter_gex := completion_shortcode_param_getter_regex.search(line) + if !current_parameter_gex: + return + + var current_parameter := current_parameter_gex.get_string('param') + if !event.get_shortcode_parameters().has(current_parameter): + return + if !event.get_shortcode_parameters()[current_parameter].has('suggestions'): + if typeof(event.get_shortcode_parameters()[current_parameter].default) == TYPE_BOOL: + suggest_bool(text, event.event_color.lerp(syntax_highlighter.normal_color, 0.3)) + elif len(word) > 0: + text.add_code_completion_option(CodeEdit.KIND_VARIABLE, word, word, event.event_color.lerp(syntax_highlighter.normal_color, 0.3), text.get_theme_icon("GuiScrollArrowRight", "EditorIcons"), '" ') + return + + var suggestions: Dictionary = event.get_shortcode_parameters()[current_parameter]['suggestions'].call() + suggest_custom_suggestions(suggestions, text, event.event_color.lerp(syntax_highlighter.normal_color, 0.3)) + + +## Filters the list of all possible options, depending on what was typed +## Purpose of the different Kinds is explained in [_request_code_completion] func filter_code_completion_candidates(candidates:Array, text:CodeEdit) -> Array: var valid_candidates := [] + var current_word := get_code_completion_word(text) for candidate in candidates: if candidate.kind == text.KIND_PLAIN_TEXT: @@ -289,7 +298,7 @@ func confirm_code_completion(replace:bool, text:CodeEdit) -> void: if code_completion.has('default_value') and typeof(code_completion['default_value']) == TYPE_STRING: var next_letter := text.get_line(text.get_caret_line()).substr(text.get_caret_column(), len(code_completion['default_value'])) - if next_letter == code_completion['default_value'] or next_letter[0] == code_completion['default_value'][0]: + if next_letter and (next_letter == code_completion['default_value'] or next_letter[0] == code_completion['default_value'][0]): text.set_caret_column(text.get_caret_column()+1) else: text.insert_text_at_caret(code_completion['default_value']) diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd.uid b/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd.uid index a3da5163..9fd0176e 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd.uid @@ -1 +1 @@ -uid://b60na7qjgkmaa +uid://camdhr6iwaywr diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd b/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd index 400dbe23..2e9ee90d 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd @@ -11,7 +11,7 @@ var mode := Modes.FULL_HIGHLIGHTING var word_regex := RegEx.new() var region_regex := RegEx.new() var number_regex := RegEx.create_from_string(r"(\d|\.)+") -var shortcode_regex := RegEx.create_from_string(r"\W*\[(?\w*)(?[^\]]*)?") +var shortcode_regex := RegEx.create_from_string(r'\W*\[(?\w*)(?([^\]"]|"[^"]*")*)?') var shortcode_param_regex := RegEx.create_from_string(r'((?[^\s=]*)\s*=\s*"(?([^=]|\\=)*)(? Color: + var prev_idx := -1 + for i in dict: + if i > prev_idx and i <= column: + prev_idx = i + if prev_idx != -1: + return dict[prev_idx].color + return normal_color diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd.uid b/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd.uid index 3647d709..158c9b93 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd.uid @@ -1 +1 @@ -uid://ccjw4fyc586j1 +uid://bf2nivn8txcw5 diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd b/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd index 64ae34cd..a49ed736 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd @@ -4,15 +4,19 @@ extends CodeEdit ## Sub-Editor that allows editing timelines in a text format. @onready var timeline_editor := get_parent().get_parent() -@onready var code_completion_helper: Node= find_parent('EditorsManager').get_node('CodeCompletionHelper') +@onready var code_completion_helper: Node = find_parent('EditorsManager').get_node('CodeCompletionHelper') var label_regex := RegEx.create_from_string('label +(?[^\n]+)') +var channel_regex := RegEx.create_from_string(r'audio +(?[\w-]{2,}|[\w]+)') func _ready() -> void: await find_parent('EditorView').ready syntax_highlighter = code_completion_helper.syntax_highlighter timeline_editor.editors_manager.sidebar.content_item_activated.connect(_on_content_item_clicked) + get_menu().add_icon_item(get_theme_icon("PlayStart", "EditorIcons"), "Play from here", 42) + get_menu().id_pressed.connect(_on_context_menu_id_pressed) + func _on_text_editor_text_changed() -> void: timeline_editor.current_resource_state = DialogicEditor.ResourceStates.UNSAVED @@ -72,22 +76,52 @@ func text_timeline_to_array(text:String) -> Array: ## HELPFUL EDITOR FUNCTIONALITY ################################################################################ +func _on_context_menu_id_pressed(id:int) -> void: + if id == 42: + play_from_here() + + +func play_from_here() -> void: + timeline_editor.play_timeline(timeline_editor.current_resource.get_index_from_text_line(text, get_caret_line())) + + func _gui_input(event): if not event is InputEventKey: return if not event.is_pressed(): return match event.as_text(): - "Ctrl+K": + "Ctrl+K", "Ctrl+Slash": toggle_comment() + # TODO clean this up when dropping 4.2 support "Alt+Up": - move_line(-1) + if has_method("move_lines_up"): + call("move_lines_up") "Alt+Down": - move_line(1) - "Ctrl+Shift+D": - duplicate_line() + if has_method("move_lines_down"): + call("move_lines_down") + + "Ctrl+Shift+D", "Ctrl+D": + duplicate_lines() + + "Ctrl+F6" when OS.get_name() != "macOS": # Play from here + play_from_here() + "Ctrl+Shift+B" when OS.get_name() == "macOS": # Play from here + play_from_here() + "Enter": + if get_code_completion_options(): + return + for caret in range(get_caret_count()): + var line := get_line(get_caret_line(caret)).strip_edges() + var event_res := DialogicTimeline.event_from_string(line, DialogicResourceUtil.get_event_cache()) + var indent_format: String = timeline_editor.current_resource.indent_format + if event_res.can_contain_events: + insert_text_at_caret("\n"+indent_format.repeat(get_indent_level(get_caret_line(caret))/4+1), caret) + else: + insert_text_at_caret("\n"+indent_format.repeat(get_indent_level(get_caret_line(caret))/4), caret) _: return get_viewport().set_input_as_handled() + # Toggle the selected lines as comments func toggle_comment() -> void: var cursor: Vector2 = Vector2(get_caret_column(), get_caret_line()) @@ -127,78 +161,27 @@ func toggle_comment() -> void: text_changed.emit() -# Move the selected lines up or down -func move_line(offset: int) -> void: - offset = clamp(offset, -1, 1) - - var cursor: Vector2 = Vector2(get_caret_column(), get_caret_line()) - var reselect: bool = false - var from: int = cursor.y - var to: int = cursor.y - if has_selection(): - reselect = true - from = get_selection_from_line() - to = get_selection_to_line() - - var lines := text.split("\n") - - if from + offset < 0 or to + offset >= lines.size(): return - - var target_from_index: int = from - 1 if offset == -1 else to + 1 - var target_to_index: int = to if offset == -1 else from - var line_to_move: String = lines[target_from_index] - lines.remove_at(target_from_index) - lines.insert(target_to_index, line_to_move) - - text = "\n".join(lines) - - cursor.y += offset - from += offset - to += offset - if reselect: - select(from, 0, to, get_line_width(to)) - set_caret_line(cursor.y) - set_caret_column(cursor.x) - text_changed.emit() - - -func duplicate_line() -> void: - var cursor: Vector2 = Vector2(get_caret_column(), get_caret_line()) - var from: int = cursor.y - var to: int = cursor.y+1 - if has_selection(): - from = get_selection_from_line() - to = get_selection_to_line()+1 - - var lines := text.split("\n") - var lines_to_dupl: PackedStringArray = lines.slice(from, to) - - text = "\n".join(lines.slice(0, from)+lines_to_dupl+lines.slice(from)) - - set_caret_line(cursor.y+to-from) - set_caret_column(cursor.x) - text_changed.emit() - - -# Allows dragging files into the editor +## Allows dragging files into the editor func _can_drop_data(at_position:Vector2, data:Variant) -> bool: if typeof(data) == TYPE_DICTIONARY and 'files' in data.keys() and len(data.files) == 1: return true return false -# Allows dragging files into the editor +## Allows dragging files into the editor func _drop_data(at_position:Vector2, data:Variant) -> void: if typeof(data) == TYPE_DICTIONARY and 'files' in data.keys() and len(data.files) == 1: set_caret_column(get_line_column_at_pos(at_position).x) set_caret_line(get_line_column_at_pos(at_position).y) var result: String = data.files[0] - if get_line(get_caret_line())[get_caret_column()-1] != '"': + var line := get_line(get_caret_line()) + if line[get_caret_column()-1] != '"': result = '"'+result - if get_line(get_caret_line())[get_caret_column()] != '"': + if line.length() == get_caret_column() or line[get_caret_column()] != '"': result = result+'"' insert_text_at_caret(result) + grab_focus() func _on_update_timer_timeout() -> void: @@ -211,6 +194,11 @@ func update_content_list() -> void: labels.append(i.get_string('name')) timeline_editor.editors_manager.sidebar.update_content_list(labels) + var channels: PackedStringArray = [] + for i in channel_regex.search_all(text): + channels.append(i.get_string('channel')) + timeline_editor.update_audio_channel_cache(channels) + func _on_content_item_clicked(label:String) -> void: if label == "~ Top": @@ -227,12 +215,23 @@ func _on_content_item_clicked(label:String) -> void: return -func _search_timeline(search_text:String) -> bool: - set_search_text(search_text) - queue_redraw() +func _search_timeline(search_text:String, match_case := false, whole_words := false) -> bool: + var flags := 0 + if match_case: + flags = flags | SEARCH_MATCH_CASE + if whole_words: + flags = flags | SEARCH_WHOLE_WORDS set_meta("current_search", search_text) + set_meta("current_search_flags", flags) - return search(search_text, 0, 0, 0).y != -1 + set_search_text(search_text) + set_search_flags(flags) + queue_redraw() + + var result := search(search_text, flags, get_selection_from_line(), get_selection_from_column()) + if result.y != -1: + select.call_deferred(result.y, result.x, result.y, result.x + search_text.length()) + return result.y != -1 func _search_navigate_down() -> void: @@ -244,8 +243,18 @@ func _search_navigate_up() -> void: func search_navigate(navigate_up := false) -> void: - if not has_meta("current_search"): + var pos := get_next_search_position(navigate_up) + if pos.x == -1: return + select(pos.y, pos.x, pos.y, pos.x+len(get_meta("current_search"))) + set_caret_line(pos.y) + center_viewport_to_caret() + queue_redraw() + + +func get_next_search_position(navigate_up := false) -> Vector2i: + if not has_meta("current_search"): + return Vector2i(-1, -1) var pos: Vector2i var search_from_line := 0 var search_from_column := 0 @@ -266,30 +275,75 @@ func search_navigate(navigate_up := false) -> void: search_from_line = get_caret_line() search_from_column = get_caret_column() - pos = search(get_meta("current_search"), 4 if navigate_up else 0, search_from_line, search_from_column) - select(pos.y, pos.x, pos.y, pos.x+len(get_meta("current_search"))) + var flags: int = get_meta("current_search_flags", 0) + if navigate_up: + flags = flags | SEARCH_BACKWARDS + + pos = search(get_meta("current_search"), flags, search_from_line, search_from_column) + return pos + + +func replace(replace_text:String) -> void: + if has_selection(): + set_caret_line(get_selection_from_line()) + set_caret_column(get_selection_from_column()) + + var pos := get_next_search_position() + if pos.x == -1: + return + + if not has_meta("current_search"): + return + + begin_complex_operation() + insert_text("@@", pos.y, pos.x) + if get_meta("current_search_flags") & SEARCH_MATCH_CASE: + text = text.replace("@@"+get_meta("current_search"), replace_text) + else: + text = text.replacen("@@"+get_meta("current_search"), replace_text) + end_complex_operation() + set_caret_line(pos.y) - center_viewport_to_caret() - queue_redraw() + set_caret_column(pos.x) + + timeline_editor.replace_in_timeline() + + +func replace_all(replace_text:String) -> void: + begin_complex_operation() + var next_pos := get_next_search_position() + var counter := 0 + while next_pos.y != -1: + insert_text("@@", next_pos.y, next_pos.x) + if get_meta("current_search_flags") & SEARCH_MATCH_CASE: + text = text.replace("@@"+get_meta("current_search"), replace_text) + else: + text = text.replacen("@@"+get_meta("current_search"), replace_text) + next_pos = get_next_search_position() + set_caret_line(next_pos.y) + set_caret_column(next_pos.x) + end_complex_operation() + + timeline_editor.replace_in_timeline() ################################################################################ ## AUTO COMPLETION ################################################################################ -# Called if something was typed +## Called if something was typed func _request_code_completion(force:bool): code_completion_helper.request_code_completion(force, self) -# Filters the list of all possible options, depending on what was typed -# Purpose of the different Kinds is explained in [_request_code_completion] +## Filters the list of all possible options, depending on what was typed +## Purpose of the different Kinds is explained in [_request_code_completion] func _filter_code_completion_candidates(candidates:Array) -> Array: return code_completion_helper.filter_code_completion_candidates(candidates, self) -# Called when code completion was activated -# Inserts the selected item +## Called when code completion was activated +## Inserts the selected item func _confirm_code_completion(replace:bool) -> void: code_completion_helper.confirm_code_completion(replace, self) @@ -298,11 +352,11 @@ func _confirm_code_completion(replace:bool) -> void: ## SYMBOL CLICKING ################################################################################ -# Performs an action (like opening a link) when a valid symbol was clicked +## Performs an action (like opening a link) when a valid symbol was clicked func _on_symbol_lookup(symbol, line, column): code_completion_helper.symbol_lookup(symbol, line, column) -# Called to test if a symbol can be clicked +## Called to test if a symbol can be clicked func _on_symbol_validate(symbol:String) -> void: code_completion_helper.symbol_validate(symbol, self) diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd.uid b/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd.uid index 692d5dec..6daf3f52 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd.uid @@ -1 +1 @@ -uid://ckdcx4qnilpv1 +uid://dshp0vy2xrxv diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.tscn b/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.tscn index f7f82157..172a501c 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.tscn +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.tscn @@ -1,17 +1,17 @@ [gd_scene load_steps=2 format=3 uid="uid://defdeav8rli6o"] -[ext_resource type="Script" uid="uid://ckdcx4qnilpv1" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd" id="1_1kbx2"] +[ext_resource type="Script" uid="uid://dshp0vy2xrxv" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.gd" id="1_1kbx2"] [node name="TimelineTextEditor" type="CodeEdit"] offset_top = 592.0 offset_right = 1024.0 offset_bottom = 600.0 -theme_override_constants/line_spacing = 10 wrap_mode = 1 -highlight_current_line = true -draw_tabs = true minimap_draw = true caret_blink = true +highlight_current_line = true +draw_tabs = true +symbol_lookup_on_click = true line_folding = true gutters_draw_line_numbers = true gutters_draw_fold_gutter = true diff --git a/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.gd.uid b/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.gd.uid index 5efa54b2..53cfcea8 100644 --- a/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.gd.uid @@ -1 +1 @@ -uid://ckqar2hsatqrt +uid://dofrrscd4c61l diff --git a/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.tscn b/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.tscn index fff2cb15..0aff01e2 100644 --- a/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.tscn +++ b/addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=3 uid="uid://depcrpeh3f4rv"] -[ext_resource type="Script" uid="uid://ckqar2hsatqrt" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.gd" id="1_s43sc"] +[ext_resource type="Script" uid="uid://dofrrscd4c61l" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.gd" id="1_s43sc"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qx31r"] content_margin_left = 4.0 diff --git a/addons/dialogic/Editor/TimelineEditor/VisualEditor/TimelineArea.gd.uid b/addons/dialogic/Editor/TimelineEditor/VisualEditor/TimelineArea.gd.uid index 2e734bb8..d1141f6c 100644 --- a/addons/dialogic/Editor/TimelineEditor/VisualEditor/TimelineArea.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/VisualEditor/TimelineArea.gd.uid @@ -1 +1 @@ -uid://b1y8xx4okklym +uid://b6ka2avnh1u55 diff --git a/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd b/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd index 8319d047..9c71fb0e 100644 --- a/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd +++ b/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd @@ -22,7 +22,7 @@ signal timeline_loaded ################################################################################ var _batches := [] var _building_timeline := false -var _timeline_changed_while_loading := false +var _cancel_loading := false var _initialized := false ################## TIMELINE EVENT MANAGEMENT ################################### @@ -75,11 +75,8 @@ func _notification(what:int) -> void: func load_timeline(resource:DialogicTimeline) -> void: - if _building_timeline: - _timeline_changed_while_loading = true - await batch_loaded - _timeline_changed_while_loading = false - _building_timeline = false + # In case another timeline is still loading + cancel_loading() clear_timeline_nodes() @@ -99,11 +96,24 @@ func load_timeline(resource:DialogicTimeline) -> void: while batch_events(data, batch_size, page).size() != 0: _batches.append(batch_events(data, batch_size, page)) page += 1 + set_meta("batch_count", len(_batches)) batch_loaded.emit() # Reset the scroll position %TimelineArea.scroll_vertical = 0 +func is_loading_timeline() -> bool: + return _building_timeline + +func cancel_loading() -> void: + timeline_editor.set_progress(1) + if _building_timeline: + _cancel_loading = true + await batch_loaded + _cancel_loading = false + _building_timeline = false + + func batch_events(array: Array, size: int, batch_number: int) -> Array: return array.slice((batch_number - 1) * size, batch_number * size) @@ -127,19 +137,27 @@ func load_batch(data:Array) -> void: func _on_batch_loaded() -> void: - if _timeline_changed_while_loading: + if _cancel_loading: return + if _batches.size() > 0: indent_events() + var progress: float = 1-(1.0/get_meta("batch_count")*len(_batches)) + timeline_editor.set_progress(progress) await get_tree().process_frame load_batch(_batches) return + # This hides the progress bar again + timeline_editor.set_progress(1) + if opener_events_stack: for ev in opener_events_stack: if is_instance_valid(ev): create_end_branch_event(%Timeline.get_child_count(), ev) + timeline_loaded.emit() + opener_events_stack = [] indent_events() update_content_list() @@ -195,7 +213,7 @@ func load_event_buttons() -> void: var button_scene := load("res://addons/dialogic/Editor/TimelineEditor/VisualEditor/AddEventButton.tscn") var scripts := DialogicResourceUtil.get_event_cache() - var hidden_buttons :Array = DialogicUtil.get_editor_setting('hidden_event_buttons', []) + var hidden_buttons: Array = DialogicUtil.get_editor_setting('hidden_event_buttons', []) var sections := {} for event_script in scripts: @@ -283,6 +301,7 @@ func update_content_list() -> void: if not is_inside_tree(): return + var channels: PackedStringArray = [] var labels: PackedStringArray = [] for event in %Timeline.get_children(): @@ -290,7 +309,12 @@ func update_content_list() -> void: if 'event_name' in event.resource and event.resource is DialogicLabelEvent: labels.append(event.resource.name) + if 'event_name' in event.resource and event.resource is DialogicAudioEvent: + if not event.resource.channel_name in channels: + channels.append(event.resource.channel_name) + timeline_editor.editors_manager.sidebar.update_content_list(labels) + timeline_editor.update_audio_channel_cache(channels) #endregion @@ -312,6 +336,11 @@ func _on_event_block_gui_input(event: InputEvent, item: Node) -> void: drag_allowed = true + if event.is_released() and not %TimelineArea.dragging and not Input.is_key_pressed(KEY_SHIFT): + if len(selected_items) > 1 and item in selected_items and not Input.is_key_pressed(KEY_CTRL): + deselect_all_items() + select_item(item) + if len(selected_items) > 0 and event is InputEventMouseMotion: if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): if !%TimelineArea.dragging and !get_viewport().gui_is_dragging() and drag_allowed: @@ -357,6 +386,8 @@ func add_event_node(event_resource:DialogicEvent, at_index:int = -1, auto_select if event_resource.event_name == "Label": block.content_changed.connect(update_content_list) + if event_resource.event_name == "Audio": + block.content_changed.connect(update_content_list) if at_index == -1: if len(selected_items) != 0: selected_items[0].add_sibling(block) @@ -387,7 +418,7 @@ func create_end_branch_event(at_index:int, parent_node:Node) -> Node: end_branch_event.gui_input.connect(_on_event_block_gui_input.bind(end_branch_event)) parent_node.end_node = end_branch_event end_branch_event.parent_node = parent_node - end_branch_event.add_end_control(parent_node.resource.get_end_branch_control()) + end_branch_event.add_end_control(parent_node.resource._get_end_branch_control()) %Timeline.add_child(end_branch_event) %Timeline.move_child(end_branch_event, at_index) return end_branch_event @@ -425,12 +456,12 @@ func get_events_indexed(events:Array) -> Dictionary: if event.resource is DialogicEndBranchEvent: continue - indexed_dict[event.get_index()] = event.resource.to_text() + indexed_dict[event.get_index()] = event.resource._store_as_string() # store an end branch if it is selected or connected to a selected event if 'end_node' in event and event.end_node: event = event.end_node - indexed_dict[event.get_index()] = event.resource.to_text() + indexed_dict[event.get_index()] = event.resource._store_as_string() elif event.resource is DialogicEndBranchEvent: if event.parent_node in events: # add local index indexed_dict[event.get_index()] += str(events.find(event.parent_node)) @@ -465,13 +496,13 @@ func add_events_indexed(indexed_events:Dictionary) -> void: var events := [] for event_idx in indexes: # first get a new resource from the text version - var event_resource :DialogicEvent + var event_resource: DialogicEvent for i in DialogicResourceUtil.get_event_cache(): if i._test_event_string(indexed_events[event_idx]): event_resource = i.duplicate() break - event_resource.from_text(indexed_events[event_idx]) + event_resource._load_from_string(indexed_events[event_idx]) # now create the visual block. deselect_all_items() @@ -540,14 +571,16 @@ func copy_selected_events() -> void: if len(selected_items) == 0: return + sort_selection() var event_copy_array := [] for item in selected_items: - event_copy_array.append(item.resource.to_text()) + event_copy_array.append(item.resource._store_as_string()) if item.resource is DialogicEndBranchEvent: if item.parent_node in selected_items: # add local index event_copy_array[-1] += str(selected_items.find(item.parent_node)) else: # add global index event_copy_array[-1] += '#'+str(item.parent_node.get_index()) + DisplayServer.clipboard_set(var_to_str({ "events":event_copy_array, "project_name": ProjectSettings.get_setting("application/config/name") @@ -905,25 +938,30 @@ func indent_events() -> void: #region SPECIAL BLOCK OPERATIONS ################################################################################ -func _on_event_popup_menu_index_pressed(index:int) -> void: +func _on_event_popup_menu_id_pressed(id:int) -> void: var item: Control = %EventPopupMenu.current_event - if index == 0: + if id == 0: if not item in selected_items: selected_items = [item] duplicate_selected() - elif index == 2: + + elif id == 1: + play_from_here(%EventPopupMenu.current_event.get_index()) + + elif id == 2: if not item.resource.help_page_path.is_empty(): OS.shell_open(item.resource.help_page_path) - elif index == 3: + + elif id == 3: find_parent('EditorView').plugin_reference.get_editor_interface().set_main_screen_editor('Script') find_parent('EditorView').plugin_reference.get_editor_interface().edit_script(item.resource.get_script(), 1, 1) - elif index == 5 or index == 6: - if index == 5: + elif id == 4 or id == 5: + if id == 4: offset_blocks_by_index(selected_items, -1) else: offset_blocks_by_index(selected_items, +1) - elif index == 8: + elif id == 6: var events_indexed : Dictionary if item in selected_items: events_indexed = get_events_indexed(selected_items) @@ -936,6 +974,12 @@ func _on_event_popup_menu_index_pressed(index:int) -> void: indent_events() +func play_from_here(index:=-1) -> void: + if index == -1: + if not selected_items.is_empty(): + index = selected_items[0].get_index() + timeline_editor.play_timeline(index) + func _on_right_sidebar_resized() -> void: var _scale := DialogicUtil.get_editor_scale() @@ -1045,6 +1089,11 @@ func _input(event:InputEvent) -> void: _add_event_button_pressed(DialogicLabelEvent.new(), true) get_viewport().set_input_as_handled() + "Ctrl+F6" when OS.get_name() != "macOS": # Play from here + play_from_here() + "Ctrl+Shift+B" when OS.get_name() == "macOS": # Play from here + play_from_here() + ## Some shortcuts should be disabled when writing text. var focus_owner: Control = get_viewport().gui_get_focus_owner() if focus_owner is TextEdit or focus_owner is LineEdit or (focus_owner is Button and focus_owner.get_parent_control().name == "Spin"): @@ -1099,16 +1148,17 @@ func _input(event:InputEvent) -> void: get_viewport().set_input_as_handled() "Ctrl+C": + select_events_indexed(get_events_indexed(selected_items)) copy_selected_events() get_viewport().set_input_as_handled() "Ctrl+V": var events_list := get_clipboard_data() - var paste_position := -1 + var paste_position := 0 if selected_items: paste_position = selected_items[-1].get_index()+1 else: - paste_position = %Timeline.get_child_count()-1 + paste_position = %Timeline.get_child_count() if events_list: TimelineUndoRedo.create_action("[D] Pasting "+str(len(events_list))+" event(s).") TimelineUndoRedo.add_do_method(add_events_at_index.bind(events_list, paste_position)) @@ -1178,23 +1228,37 @@ func get_previous_character(double_previous := false) -> DialogicCharacter: ################################################################################ var search_results := {} -func _search_timeline(search_text:String) -> bool: - for event in search_results: - if is_instance_valid(search_results[event]): - search_results[event].set_search_text("") - search_results[event].deselect() - search_results[event].queue_redraw() +func _search_timeline(search_text:String, match_case := false, whole_words := false) -> bool: + var flags := 0 + if match_case: + flags = flags | TextEdit.SEARCH_MATCH_CASE + if whole_words: + flags = flags | TextEdit.SEARCH_WHOLE_WORDS + search_results.clear() + # This checks all text events for whether they contain the text. + # If so, the text field is stored in search_results + # which is later used to navigate through only the relevant text fields. + for block in %Timeline.get_children(): if block.resource is DialogicTextEvent: - var text_field: TextEdit = block.get_node("%BodyContent").find_child("Field_Text_Multiline", true, false) + var text_field: TextEdit = block.get_field_node("text") + + text_field.deselect() text_field.set_search_text(search_text) - if text_field.search(search_text, 0, 0, 0).x != -1: + text_field.set_search_flags(flags) + + if text_field.search(search_text, flags, 0, 0).x != -1: search_results[block] = text_field - text_field.queue_redraw() + + text_field.queue_redraw() + set_meta("current_search", search_text) + set_meta("current_search_flags", flags) + search_navigate(false) + return not search_results.is_empty() @@ -1207,25 +1271,61 @@ func _search_navigate_up() -> void: func search_navigate(navigate_up := false) -> void: + var next_pos := get_next_search_position(navigate_up) + if next_pos: + var event: Node = next_pos[0] + var field: TextEdit = next_pos[1] + var result: Vector2i = next_pos[2] + if not event in selected_items: + select_item(next_pos[0], false) + %TimelineArea.ensure_control_visible(event) + event._on_ToggleBodyVisibility_toggled(true) + field.call_deferred("select", result.y, result.x, result.y, result.x+len(get_meta("current_search"))) + + +func get_next_search_position(navigate_up:= false, include_current := false) -> Array: var search_text: String = get_meta("current_search", "") + var search_flags: int = get_meta("current_search_flags", 0) if search_results.is_empty() or %Timeline.get_child_count() == 0: - return - if selected_items.is_empty(): - select_item(%Timeline.get_child(0), false) + return [] + + # We start the search on the selected item, + # so these checks make sure something sensible is selected + + # Try to select the event that has focus + if get_viewport().gui_get_focus_owner() is TextEdit and get_viewport().gui_get_focus_owner() is DialogicVisualEditorField: + select_item(get_viewport().gui_get_focus_owner().event_resource.editor_node, false) + get_viewport().gui_get_focus_owner().deselect() + + # Select the first event if nothing is selected + if selected_items.is_empty(): + select_item(search_results.keys()[0], false) + + # Loop to the next event that where something was found + if not selected_items[0] in search_results: + var index: int = selected_items[0].get_index() + while not %Timeline.get_child(index) in search_results: + index = wrapi(index+1, 0, %Timeline.get_child_count()-1) + select_item(%Timeline.get_child(index), false) - while not selected_items[0] in search_results: - select_item(%Timeline.get_child(wrapi(selected_items[0].get_index()+1, 0, %Timeline.get_child_count()-1)), false) var event: Node = selected_items[0] var counter := 0 + var first := true while true: counter += 1 var field: TextEdit = search_results[event] field.queue_redraw() - var result := search_text_field(field, search_text, navigate_up) + + # First locates the next result in this field + var result := search_text_field(field, search_text, search_flags, navigate_up, first and include_current) var current_line := field.get_selection_from_line() if field.has_selection() else -1 var current_column := field.get_selection_from_column() if field.has_selection() else -1 + + first = false + + # Determines if the found result is valid or navigation should continue into the next event var next_is_in_this_event := false if result.y == -1: next_is_in_this_event = false @@ -1234,28 +1334,27 @@ func search_navigate(navigate_up := false) -> void: current_line = field.get_line_count()-1 current_column = field.get_line(current_line).length() next_is_in_this_event = result.x < current_column or result.y < current_line + elif include_current: + next_is_in_this_event = true else: next_is_in_this_event = result.x > current_column or result.y > current_line + # If the next result was found return it if next_is_in_this_event: - if not event in selected_items: - select_item(event, false) - %TimelineArea.ensure_control_visible(event) - event._on_ToggleBodyVisibility_toggled(true) - field.select(result.y, result.x, result.y, result.x+len(search_text)) - break + return [event, field, result] - else: - field.deselect() - var index := search_results.keys().find(event) - event = search_results.keys()[wrapi(index+(-1 if navigate_up else 1), 0, search_results.size())] + # Otherwise deselct this field and continue in the next/previous + field.deselect() + var index := search_results.keys().find(event) + event = search_results.keys()[wrapi(index+(-1 if navigate_up else 1), 0, search_results.size())] if counter > 5: print("[Dialogic] Search failed.") break + return [] -func search_text_field(field:TextEdit, search_text := "", navigate_up:= false) -> Vector2i: +func search_text_field(field:TextEdit, search_text := "", flags:= 0, navigate_up:= false, include_current := false) -> Vector2i: var search_from_line: int = 0 var search_from_column: int = 0 if field.has_selection(): @@ -1267,6 +1366,9 @@ func search_text_field(field:TextEdit, search_text := "", navigate_up:= false) - if search_from_line == -1: return Vector2i(-1, -1) search_from_column = field.get_line(search_from_line).length()-1 + elif include_current: + search_from_line = field.get_selection_from_line() + search_from_column = field.get_selection_from_column() else: search_from_line = field.get_selection_to_line() search_from_column = field.get_selection_to_column() @@ -1275,7 +1377,62 @@ func search_text_field(field:TextEdit, search_text := "", navigate_up:= false) - search_from_line = field.get_line_count()-1 search_from_column = field.get_line(search_from_line).length()-1 - var search := field.search(search_text, 4 if navigate_up else 0, search_from_line, search_from_column) + if navigate_up: + flags = flags | TextEdit.SEARCH_BACKWARDS + + var search := field.search(search_text, flags, search_from_line, search_from_column) return search + +func replace(replace_text:String) -> void: + var next_pos := get_next_search_position(false, true) + var event: Node = next_pos[0] + var field: TextEdit = next_pos[1] + var result: Vector2i = next_pos[2] + + if field.has_selection(): + field.set_caret_column(field.get_selection_from_column()) + field.set_caret_line(field.get_selection_from_line()) + + field.begin_complex_operation() + field.insert_text("@@", result.y, result.x) + if get_meta("current_search_flags") & TextEdit.SEARCH_MATCH_CASE: + field.text = field.text.replace("@@"+get_meta("current_search"), replace_text) + else: + field.text = field.text.replacen("@@"+get_meta("current_search"), replace_text) + field.end_complex_operation() + + timeline_editor.replace_in_timeline() + + +func replace_all(replace_text:String) -> void: + var next_pos := get_next_search_position() + if not next_pos: + return + var event: Node = next_pos[0] + var field: TextEdit = next_pos[1] + var result: Vector2i = next_pos[2] + field.begin_complex_operation() + while next_pos: + event = next_pos[0] + if field != next_pos[1]: + field.end_complex_operation() + field = next_pos[1] + field.begin_complex_operation() + result = next_pos[2] + + if field.has_selection(): + field.set_caret_column(field.get_selection_from_column()) + field.set_caret_line(field.get_selection_from_line()) + + field.insert_text("@@", result.y, result.x) + if get_meta("current_search_flags") & TextEdit.SEARCH_MATCH_CASE: + field.text = field.text.replace("@@"+get_meta("current_search"), replace_text) + else: + field.text = field.text.replacen("@@"+get_meta("current_search"), replace_text) + + next_pos = get_next_search_position() + field.end_complex_operation() + timeline_editor.replace_in_timeline() + #endregion diff --git a/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd.uid b/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd.uid index 16f38e96..27001722 100644 --- a/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd.uid @@ -1 +1 @@ -uid://csmcfo7lnabpw +uid://cvgok7bxva5e2 diff --git a/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.tscn b/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.tscn index 244f8908..34f9b5c5 100644 --- a/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.tscn +++ b/addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.tscn @@ -1,17 +1,17 @@ [gd_scene load_steps=10 format=3 uid="uid://ysqbusmy0qma"] -[ext_resource type="Script" uid="uid://csmcfo7lnabpw" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd" id="1_8smxc"] +[ext_resource type="Script" uid="uid://cvgok7bxva5e2" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd" id="1_8smxc"] [ext_resource type="Theme" uid="uid://cqst728xxipcw" path="res://addons/dialogic/Editor/Theme/MainTheme.tres" id="2_x0fhp"] -[ext_resource type="Script" uid="uid://b1y8xx4okklym" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/TimelineArea.gd" id="3_sap1x"] -[ext_resource type="Script" uid="uid://doek0kltvf65w" path="res://addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd" id="4_ugiq6"] +[ext_resource type="Script" uid="uid://b6ka2avnh1u55" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/TimelineArea.gd" id="3_sap1x"] +[ext_resource type="Script" uid="uid://n1knm2ohcehu" path="res://addons/dialogic/Editor/Events/EventBlock/event_right_click_menu.gd" id="4_ugiq6"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_phyjj"] content_margin_top = 10.0 -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_plab4"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6gqu8"] bg_color = Color(0, 0, 0, 1) -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dov6v"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jujwh"] content_margin_left = 4.0 content_margin_top = 4.0 content_margin_right = 4.0 @@ -33,7 +33,7 @@ data = { "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_vg181"] +[sub_resource type="ImageTexture" id="ImageTexture_xe7d2"] image = SubResource("Image_3temo") [node name="TimelineVisualEditor" type="MarginContainer"] @@ -70,27 +70,32 @@ size_flags_vertical = 3 [node name="EventPopupMenu" type="PopupMenu" parent="View/TimelineArea"] unique_name_in_owner = true size = Vector2i(165, 124) -theme_override_styles/panel = SubResource("StyleBoxFlat_plab4") -theme_override_styles/hover = SubResource("StyleBoxFlat_dov6v") -item_count = 6 -item_0/text = "Documentation" -item_0/icon = SubResource("ImageTexture_vg181") -item_0/id = 0 -item_1/text = "" +theme_override_styles/panel = SubResource("StyleBoxFlat_6gqu8") +theme_override_styles/hover = SubResource("StyleBoxFlat_jujwh") +item_count = 9 +item_0/text = "Duplicate" +item_0/icon = SubResource("ImageTexture_xe7d2") item_1/id = -1 item_1/separator = true -item_2/text = "Move up" -item_2/icon = SubResource("ImageTexture_vg181") +item_2/text = "Documentation" +item_2/icon = SubResource("ImageTexture_xe7d2") item_2/id = 2 -item_3/text = "Move down" -item_3/icon = SubResource("ImageTexture_vg181") +item_3/text = "Open Code" +item_3/icon = SubResource("ImageTexture_xe7d2") item_3/id = 3 -item_4/text = "" item_4/id = -1 item_4/separator = true -item_5/text = "Delete" -item_5/icon = SubResource("ImageTexture_vg181") +item_5/text = "Move up" +item_5/icon = SubResource("ImageTexture_xe7d2") item_5/id = 5 +item_6/text = "Move down" +item_6/icon = SubResource("ImageTexture_xe7d2") +item_6/id = 6 +item_7/id = -1 +item_7/separator = true +item_8/text = "Delete" +item_8/icon = SubResource("ImageTexture_xe7d2") +item_8/id = 8 script = ExtResource("4_ugiq6") [node name="RightSidebar" type="ScrollContainer" parent="View"] @@ -107,5 +112,5 @@ size_flags_vertical = 3 size_flags_stretch_ratio = 0.2 [connection signal="drag_completed" from="View/TimelineArea" to="." method="_on_timeline_area_drag_completed"] -[connection signal="index_pressed" from="View/TimelineArea/EventPopupMenu" to="." method="_on_event_popup_menu_index_pressed"] +[connection signal="id_pressed" from="View/TimelineArea/EventPopupMenu" to="." method="_on_event_popup_menu_id_pressed"] [connection signal="resized" from="View/RightSidebar" to="." method="_on_right_sidebar_resized"] diff --git a/addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd b/addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd new file mode 100644 index 00000000..5661d09e --- /dev/null +++ b/addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd @@ -0,0 +1,118 @@ +@tool +extends PanelContainer + + +var shortcuts := [ + + {"shortcut":"Ctrl+T", "text":"Add Text event", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+Shift+T", "text":"Add Text event with current character", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+Alt/Opt+T", "text":"Add Text event with previous character", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+E", "text":"Add Character join event", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+Shift+E", "text":"Add Character update event", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+Alt/Opt+E", "text":"Add Character leave event", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+J", "text":"Add Jump event", "editor":"VisualEditor"}, + {"shortcut":"Ctrl+L", "text":"Add Label event", "editor":"VisualEditor"}, + {}, + {"shortcut":"Alt/Opt+Up", "text":"Move selected events/lines up"}, + {"shortcut":"Alt/Opt+Down", "text":"Move selected events/lines down"}, + {}, + {"shortcut":"Ctrl+F", "text":"Search"}, + {"shortcut":"Ctrl+R", "text":"Replace"}, + {}, + {"shortcut":"Ctrl+F5", "text":"Play timeline", "platform":"-macOS"}, + {"shortcut":"Ctrl+B", "text":"Play timeline", "platform":"macOS"}, + {"shortcut":"Ctrl+F6", "text":"Play timeline from here", "platform":"-macOS"}, + {"shortcut":"Ctrl+Shift+B", "text":"Play timeline from here", "platform":"macOS"}, + + {}, + {"shortcut":"Ctrl+C", "text":"Copy"}, + {"shortcut":"Ctrl+V", "text":"Paste"}, + {"shortcut":"Ctrl+D", "text":"Duplicate selected events/lines"}, + {"shortcut":"Ctrl+X", "text":"Cut selected events/lines"}, + {"shortcut":"Ctrl+K", "text":"Toggle Comment" , "editor":"TextEditor"}, + {"shortcut":"Delete", "text":"Delete events", "editor":"VisualEditor"}, + {}, + {"shortcut":"Ctrl+A", "text":"Select All"}, + {"shortcut":"Ctrl+Shift+A", "text":"Select Nothing", "editor":"VisualEditor"}, + {"shortcut":"Up", "text":"Select previous event", "editor":"VisualEditor"}, + {"shortcut":"Down", "text":"Select next event", "editor":"VisualEditor"}, + {}, + {"shortcut":"Ctrl+Z", "text":"Undo"}, + {"shortcut":"Ctrl+Shift+Z", "text":"Redo"}, + {}, +] + + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + %CloseShortcutPanel.icon = get_theme_icon("Close", "EditorIcons") + get_theme_stylebox("panel").bg_color = get_theme_color("dark_color_3", "Editor") + + +func reload_shortcuts() -> void: + for i in %ShortcutList.get_children(): + i.queue_free() + + var is_text_editor: bool = %TextEditor.visible + for i in shortcuts: + if i.is_empty(): + %ShortcutList.add_child(HSeparator.new()) + %ShortcutList.add_child(HSeparator.new()) + continue + + if "editor" in i and not get_node("%"+i.editor).visible: + continue + + if "platform" in i: + var platform := OS.get_name() + if not (platform == i.platform.trim_prefix("-") != i.platform.begins_with("-")): + continue + + var hbox := HBoxContainer.new() + hbox.add_theme_constant_override("separation", 0) + for key_text in i.shortcut.split("+"): + if hbox.get_child_count(): + var plus_l := Label.new() + plus_l.text = "+" + hbox.add_child(plus_l) + + var key := Button.new() + if key_text == "Up": + key.icon = get_theme_icon("ArrowUp", "EditorIcons") + elif key_text == "Down": + key.icon = get_theme_icon("ArrowDown", "EditorIcons") + else: + key_text = key_text.replace("Alt/Opt", "Opt" if OS.get_name() == "macOS" else "Alt") + key.text = key_text + key.disabled = true + key.theme_type_variation = "ShortcutKeyLabel" + key.add_theme_font_override("font", get_theme_font("source", "EditorFonts")) + hbox.add_child(key) + + %ShortcutList.add_child(hbox) + + var text := Label.new() + text.text = i.text.replace("events/lines", "lines" if is_text_editor else "events") + text.theme_type_variation = "DialogicHintText2" + %ShortcutList.add_child(text) + + +func open(): + if visible: + close() + return + reload_shortcuts() + + show() + await get_tree().process_frame + size = get_parent().size - Vector2(100, 100)*DialogicUtil.get_editor_scale() + size.x = %ShortcutList.get_minimum_size().x + 100 + size.y = min(size.y, %ShortcutList.get_minimum_size().y+100) + global_position = get_parent().global_position+get_parent().size/2-size/2 + + +func _on_close_shortcut_panel_pressed() -> void: + close() + +func close() -> void: + hide() diff --git a/addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd.uid b/addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd.uid new file mode 100644 index 00000000..1ab08052 --- /dev/null +++ b/addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd.uid @@ -0,0 +1 @@ +uid://b35hvsvrvjjl4 diff --git a/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd b/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd index 5818e162..2a907a18 100644 --- a/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd +++ b/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd @@ -15,9 +15,10 @@ func _ready() -> void: randomize() var current_timeline: String = DialogicUtil.get_editor_setting("current_timeline_path", "") + var start_from_index: int = DialogicUtil.get_editor_setting("play_from_index", -1) if not current_timeline: get_tree().quit() - DialogicUtil.autoload().start(current_timeline) + DialogicUtil.autoload().start(current_timeline, start_from_index) DialogicUtil.autoload().timeline_ended.connect(get_tree().quit) DialogicUtil.autoload().signal_event.connect(receive_event_signal) DialogicUtil.autoload().text_signal.connect(receive_text_signal) @@ -41,4 +42,3 @@ func _input(event:InputEvent) -> void: auto_skip.disable_on_unread_text = false auto_skip.enabled = not is_auto_skip_enabled - diff --git a/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd.uid b/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd.uid index a23a37fd..800625bb 100644 --- a/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd.uid @@ -1 +1 @@ -uid://c8m3dmu53kupl +uid://cbq0n68r4pwu7 diff --git a/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn b/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn index 2649dd7b..ed877d5c 100644 --- a/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn +++ b/addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://ud18ke1g2nw4"] -[ext_resource type="Script" uid="uid://c8m3dmu53kupl" path="res://addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd" id="1_bamud"] +[ext_resource type="Script" uid="uid://cbq0n68r4pwu7" path="res://addons/dialogic/Editor/TimelineEditor/test_timeline_scene.gd" id="1_bamud"] [node name="TestTimelineScene" type="Control"] layout_mode = 3 diff --git a/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd b/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd index ab6538b5..fec801e9 100644 --- a/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd +++ b/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd @@ -73,7 +73,7 @@ func _open_resource(resource:Resource) -> void: EditorMode.TEXT: %TextEditor.load_timeline(current_resource) $NoTimelineScreen.hide() - %TimelineName.text = DialogicResourceUtil.get_unique_identifier(current_resource.resource_path) + %TimelineName.text = current_resource.get_identifier() play_timeline_button.disabled = false @@ -100,16 +100,20 @@ func _input(event: InputEvent) -> void: if is_ancestor_of(get_viewport().gui_get_focus_owner()): search_timeline() + if event.keycode == KEY_R and event.pressed: + if Input.is_key_pressed(KEY_CTRL): + if is_ancestor_of(get_viewport().gui_get_focus_owner()): + replace_in_timeline(true) ## Method to play the current timeline. Connected to the button in the sidebar. -func play_timeline() -> void: +func play_timeline(index := -1) -> void: _save() var dialogic_plugin := DialogicUtil.get_dialogic_plugin() # Save the current opened timeline DialogicUtil.set_editor_setting('current_timeline_path', current_resource.resource_path) - + DialogicUtil.set_editor_setting('play_from_index', index) DialogicUtil.get_dialogic_plugin().get_editor_interface().play_custom_scene("res://addons/dialogic/Editor/TimelineEditor/test_timeline_scene.tscn") @@ -118,19 +122,25 @@ func toggle_editor_mode() -> void: match current_editor_mode: EditorMode.VISUAL: current_editor_mode = EditorMode.TEXT - %VisualEditor.save_timeline() + if %VisualEditor.is_loading_timeline(): + %VisualEditor.cancel_loading() + else: + %VisualEditor.save_timeline() %VisualEditor.hide() %TextEditor.show() %TextEditor.load_timeline(current_resource) %SwitchEditorMode.text = "Visual Editor" + _on_search_text_changed(%Search.text) EditorMode.TEXT: + _on_search_text_changed.bind("") current_editor_mode = EditorMode.VISUAL %TextEditor.save_timeline() %TextEditor.hide() %VisualEditor.load_timeline(current_resource) %VisualEditor.show() %SwitchEditorMode.text = "Text Editor" - _on_search_text_changed(%Search.text) + if not %VisualEditor.timeline_loaded.is_connected(_on_search_text_changed): + %VisualEditor.timeline_loaded.connect(_on_search_text_changed.bind(%Search.text), CONNECT_ONE_SHOT) DialogicUtil.set_editor_setting('timeline_editor_mode', current_editor_mode) @@ -147,6 +157,9 @@ func _on_resource_saved() -> void: func new_timeline(path:String) -> void: _save() var new_timeline := DialogicTimeline.new() + if not path.ends_with(".dtl"): + path = path.trim_suffix(".") + path += ".dtl" new_timeline.resource_path = path new_timeline.set_meta('timeline_not_saved', true) var err := ResourceSaver.save(new_timeline) @@ -155,6 +168,20 @@ func new_timeline(path:String) -> void: editors_manager.edit_resource(new_timeline) +func update_audio_channel_cache(list:PackedStringArray) -> void: + var timeline_directory := DialogicResourceUtil.get_timeline_directory() + var channel_directory := DialogicResourceUtil.get_audio_channel_cache() + if current_resource != null: + for i in timeline_directory: + if timeline_directory[i] == current_resource.resource_path: + channel_directory[i] = list + + # also always store the current timelines channels for easy access + channel_directory[""] = list + + DialogicResourceUtil.set_audio_channel_cache(channel_directory) + + func _ready() -> void: $NoTimelineScreen.add_theme_stylebox_override("panel", get_theme_stylebox("Background", "EditorStyles")) @@ -164,10 +191,19 @@ func _ready() -> void: %SwitchEditorMode.pressed.connect(toggle_editor_mode) %SwitchEditorMode.custom_minimum_size.x = 200 * DialogicUtil.get_editor_scale() + %Shortcuts.icon = get_theme_icon("InputEventShortcut", "EditorIcons") + %Shortcuts.pressed.connect(%ShortcutsPanel.open) + %SearchClose.icon = get_theme_icon("Close", "EditorIcons") %SearchUp.icon = get_theme_icon("MoveUp", "EditorIcons") %SearchDown.icon = get_theme_icon("MoveDown", "EditorIcons") + %ReplaceGlobal.icon = get_theme_icon("ExternalLink", "EditorIcons") + + %ProgressSection.hide() + + %SearchReplaceSection.hide() + %SearchReplaceSection.add_theme_stylebox_override("panel", get_theme_stylebox("PanelForeground", "EditorStyles")) func _on_create_timeline_button_pressed() -> void: @@ -199,24 +235,25 @@ func get_current_editor() -> Node: #region SEARCH func search_timeline() -> void: + %SearchReplaceSection.show() %SearchSection.show() + %ReplaceSection.hide() if get_viewport().gui_get_focus_owner() is TextEdit: - %Search.text = get_viewport().gui_get_focus_owner().get_selected_text() - _on_search_text_changed(%Search.text) - else: - %Search.text = "" + if get_viewport().gui_get_focus_owner().get_selected_text(): + %Search.text = get_viewport().gui_get_focus_owner().get_selected_text() + _on_search_text_changed(%Search.text) %Search.grab_focus() func _on_close_search_pressed() -> void: - %SearchSection.hide() + %SearchReplaceSection.hide() %Search.text = "" _on_search_text_changed('') func _on_search_text_changed(new_text: String) -> void: var editor: Node = null - var anything_found: bool = get_current_editor()._search_timeline(new_text) + var anything_found: bool = get_current_editor()._search_timeline(new_text, %MatchCase.button_pressed, %WholeWords.button_pressed) if anything_found or new_text.is_empty(): %SearchLabel.hide() %Search.add_theme_color_override("font_color", get_theme_color("font_color", "Editor")) @@ -234,6 +271,51 @@ func _on_search_down_pressed() -> void: func _on_search_up_pressed() -> void: get_current_editor()._search_navigate_up() + +func _on_match_case_toggled(toggled_on: bool) -> void: + _on_search_text_changed(%Search.text) + + +func _on_whole_words_toggled(toggled_on: bool) -> void: + _on_search_text_changed(%Search.text) + + #endregion +#region REPLACE + +func replace_in_timeline(focus_grab:=false) -> void: + search_timeline() + %ReplaceSection.show() + if focus_grab: + %ReplaceText.grab_focus() + %ReplaceText.select_all() + + +func _on_replace_button_pressed() -> void: + get_current_editor().replace(%ReplaceText.text) + + +func _on_replace_all_button_pressed() -> void: + get_current_editor().replace_all(%ReplaceText.text) + + +func _on_replace_global_pressed() -> void: + editors_manager.reference_manager.add_ref_change(%Search.text, %ReplaceText.text, 0, 0, [], + %WholeWords.button_pressed, %MatchCase.button_pressed) + editors_manager.reference_manager.open() + +#endregion + + +#region PROGRESS + +func set_progress(percentage:float, text := "") -> void: + %ProgressSection.visible = percentage != 1 + + %ProgressBar.value = percentage + %ProgressLabel.text = text + %ProgressLabel.visible = not text.is_empty() + +#endregion diff --git a/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd.uid b/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd.uid index 8d6ae9a5..a8c04d26 100644 --- a/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd.uid +++ b/addons/dialogic/Editor/TimelineEditor/timeline_editor.gd.uid @@ -1 +1 @@ -uid://c86cjvf8l8e3t +uid://x21vral0xsxy diff --git a/addons/dialogic/Editor/TimelineEditor/timeline_editor.tscn b/addons/dialogic/Editor/TimelineEditor/timeline_editor.tscn index c6c6cf47..1816c535 100644 --- a/addons/dialogic/Editor/TimelineEditor/timeline_editor.tscn +++ b/addons/dialogic/Editor/TimelineEditor/timeline_editor.tscn @@ -1,27 +1,24 @@ -[gd_scene load_steps=10 format=3 uid="uid://crce0na84rhfd"] +[gd_scene load_steps=12 format=3 uid="uid://crce0na84rhfd"] -[ext_resource type="Script" uid="uid://c86cjvf8l8e3t" path="res://addons/dialogic/Editor/TimelineEditor/timeline_editor.gd" id="1_4aceh"] +[ext_resource type="Script" uid="uid://x21vral0xsxy" path="res://addons/dialogic/Editor/TimelineEditor/timeline_editor.gd" id="1_4aceh"] [ext_resource type="PackedScene" uid="uid://ysqbusmy0qma" path="res://addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.tscn" id="2_qs7vc"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_yqd26"] [ext_resource type="PackedScene" uid="uid://defdeav8rli6o" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/timeline_editor_text.tscn" id="3_up2bn"] -[ext_resource type="Script" uid="uid://ccjw4fyc586j1" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/syntax_highlighter.gd" id="4_1t6bf"] +[ext_resource type="Script" uid="uid://b35hvsvrvjjl4" path="res://addons/dialogic/Editor/TimelineEditor/shortcut_popup.gd" id="6_rfuk0"] [sub_resource type="Image" id="Image_6bv6r"] data = { -"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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), +"data": PackedByteArray(255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 0, 255, 92, 92, 127, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 0, 255, 93, 93, 255, 255, 92, 92, 127, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 92, 92, 127, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 92, 92, 127, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 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, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 231, 255, 90, 90, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 90, 90, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 0, 255, 93, 93, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 42, 255, 90, 90, 0, 255, 94, 94, 0, 255, 91, 91, 42, 255, 93, 93, 233, 255, 92, 92, 232, 255, 93, 93, 41, 255, 90, 90, 0, 255, 94, 94, 0, 255, 91, 91, 42, 255, 93, 93, 233, 255, 92, 92, 232, 255, 92, 92, 0, 255, 92, 92, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 45, 255, 93, 93, 44, 255, 91, 91, 0, 255, 91, 91, 42, 255, 91, 91, 42, 255, 93, 93, 0, 255, 91, 91, 45, 255, 93, 93, 44, 255, 91, 91, 0, 255, 91, 91, 42, 255, 91, 91, 42, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 45, 255, 92, 92, 235, 255, 92, 92, 234, 255, 89, 89, 43, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 45, 255, 92, 92, 235, 255, 92, 92, 234, 255, 89, 89, 43, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 91, 91, 0, 255, 92, 92, 0, 255, 92, 92, 0, 255, 92, 92, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 91, 91, 59, 255, 92, 92, 61, 255, 92, 92, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 91, 91, 59, 255, 92, 92, 61, 255, 92, 92, 0, 255, 92, 92, 0, 255, 93, 93, 0, 255, 93, 93, 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, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 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, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0, 255, 93, 93, 0), "format": "RGBA8", "height": 16, "mipmaps": false, "width": 16 } -[sub_resource type="ImageTexture" id="ImageTexture_lvr8x"] +[sub_resource type="ImageTexture" id="ImageTexture_u2118"] image = SubResource("Image_6bv6r") -[sub_resource type="SyntaxHighlighter" id="SyntaxHighlighter_7lpql"] -script = ExtResource("4_1t6bf") - -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lpeon"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_boacm"] content_margin_left = 4.0 content_margin_top = 4.0 content_margin_right = 4.0 @@ -34,6 +31,45 @@ border_width_right = 2 border_width_bottom = 2 corner_detail = 1 +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_4bvbc"] +content_margin_left = 0.0 +content_margin_top = 0.0 +content_margin_right = 0.0 +content_margin_bottom = 0.0 +bg_color = Color(0.458405, 0.458405, 0.458405, 1) +draw_center = false +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.370364, 0.370365, 0.370364, 1) +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 + +[sub_resource type="Theme" id="Theme_feml8"] +HSeparator/constants/separation = 10 +ShortcutKeyLabel/base_type = &"Button" +ShortcutKeyLabel/colors/font_disabled_color = Color(1, 1, 1, 1) +ShortcutKeyLabel/colors/icon_disabled_color = Color(1, 1, 1, 1) +ShortcutKeyLabel/font_sizes/font_size = 14 +ShortcutKeyLabel/styles/disabled = SubResource("StyleBoxFlat_4bvbc") +ShortcutKeyLabel/styles/normal = SubResource("StyleBoxFlat_4bvbc") + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_j85ew"] +content_margin_left = 20.0 +content_margin_top = 20.0 +content_margin_right = 20.0 +content_margin_bottom = 20.0 +bg_color = Color(0, 0, 0, 1) +corner_radius_top_left = 20 +corner_radius_top_right = 20 +corner_radius_bottom_right = 20 +corner_radius_bottom_left = 20 +shadow_color = Color(0, 0, 0, 0.407843) +shadow_size = 15 + [node name="Timeline" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -66,7 +102,7 @@ tooltip_text = "This unique identifier is based on the file name. You can change This is what you should use in a jump event to reference this timeline. You can also use this name in Dialogic.start()." -texture = SubResource("ImageTexture_lvr8x") +texture = null hint_text = "This unique identifier is based on the file name. You can change it in the Reference Manager. This is what you should use in a jump event to reference this timeline. @@ -80,7 +116,15 @@ size_flags_horizontal = 10 size_flags_vertical = 4 tooltip_text = "Switch between Text Editor and Visual Editor" text = "Text editor" -icon = SubResource("ImageTexture_lvr8x") +icon = SubResource("ImageTexture_u2118") + +[node name="Shortcuts" type="Button" parent="VBox/HBox"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 4 +tooltip_text = "Shortcuts" +icon = SubResource("ImageTexture_u2118") [node name="VisualEditor" parent="VBox" instance=ExtResource("2_qs7vc")] unique_name_in_owner = true @@ -95,36 +139,98 @@ theme_override_constants/margin_bottom = 0 unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 3 -syntax_highlighter = SubResource("SyntaxHighlighter_7lpql") -symbol_lookup_on_click = true -line_folding = false -gutters_draw_fold_gutter = false -[node name="SearchSection" type="HBoxContainer" parent="VBox"] +[node name="SearchReplaceSection" type="PanelContainer" parent="VBox"] unique_name_in_owner = true visible = false layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_boacm") -[node name="Search" type="LineEdit" parent="VBox/SearchSection"] +[node name="VBox" type="VBoxContainer" parent="VBox/SearchReplaceSection"] +layout_mode = 2 + +[node name="SearchSection" type="HBoxContainer" parent="VBox/SearchReplaceSection/VBox"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="Search" type="LineEdit" parent="VBox/SearchReplaceSection/VBox/SearchSection"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 placeholder_text = "Search" -[node name="SearchLabel" type="Label" parent="VBox/SearchSection"] +[node name="SearchLabel" type="Label" parent="VBox/SearchReplaceSection/VBox/SearchSection"] unique_name_in_owner = true visible = false layout_mode = 2 -[node name="SearchUp" type="Button" parent="VBox/SearchSection"] +[node name="SearchUp" type="Button" parent="VBox/SearchReplaceSection/VBox/SearchSection"] +unique_name_in_owner = true +layout_mode = 2 +icon = SubResource("ImageTexture_u2118") +flat = true + +[node name="SearchDown" type="Button" parent="VBox/SearchReplaceSection/VBox/SearchSection"] +unique_name_in_owner = true +layout_mode = 2 +icon = SubResource("ImageTexture_u2118") +flat = true + +[node name="MatchCase" type="CheckBox" parent="VBox/SearchReplaceSection/VBox/SearchSection"] +unique_name_in_owner = true +layout_mode = 2 +text = "Match Case" + +[node name="WholeWords" type="CheckBox" parent="VBox/SearchReplaceSection/VBox/SearchSection"] +unique_name_in_owner = true +layout_mode = 2 +text = "Whole Words" + +[node name="SearchClose" type="Button" parent="VBox/SearchReplaceSection/VBox/SearchSection"] +unique_name_in_owner = true +layout_mode = 2 +icon = SubResource("ImageTexture_u2118") +flat = true + +[node name="ReplaceSection" type="HBoxContainer" parent="VBox/SearchReplaceSection/VBox"] unique_name_in_owner = true layout_mode = 2 -[node name="SearchDown" type="Button" parent="VBox/SearchSection"] +[node name="ReplaceText" type="LineEdit" parent="VBox/SearchReplaceSection/VBox/ReplaceSection"] unique_name_in_owner = true layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Replace" -[node name="SearchClose" type="Button" parent="VBox/SearchSection"] +[node name="ReplaceButton" type="Button" parent="VBox/SearchReplaceSection/VBox/ReplaceSection"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace" + +[node name="ReplaceAllButton" type="Button" parent="VBox/SearchReplaceSection/VBox/ReplaceSection"] +unique_name_in_owner = true +layout_mode = 2 +text = "Replace All" + +[node name="ReplaceGlobal" type="Button" parent="VBox/SearchReplaceSection/VBox/ReplaceSection"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Replace in all timelines" +icon = SubResource("ImageTexture_u2118") + +[node name="ProgressSection" type="HBoxContainer" parent="VBox"] +unique_name_in_owner = true +visible = false +layout_mode = 2 + +[node name="ProgressBar" type="ProgressBar" parent="VBox/ProgressSection"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +max_value = 1.0 +step = 0.001 + +[node name="ProgressLabel" type="Label" parent="VBox/ProgressSection"] unique_name_in_owner = true layout_mode = 2 @@ -136,7 +242,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -theme_override_styles/panel = SubResource("StyleBoxFlat_lpeon") +theme_override_styles/panel = SubResource("StyleBoxFlat_boacm") [node name="CenterContainer" type="CenterContainer" parent="NoTimelineScreen"] layout_mode = 2 @@ -156,8 +262,54 @@ autowrap_mode = 3 layout_mode = 2 text = "Create New Timeline" -[connection signal="text_changed" from="VBox/SearchSection/Search" to="." method="_on_search_text_changed"] -[connection signal="pressed" from="VBox/SearchSection/SearchUp" to="." method="_on_search_up_pressed"] -[connection signal="pressed" from="VBox/SearchSection/SearchDown" to="." method="_on_search_down_pressed"] -[connection signal="pressed" from="VBox/SearchSection/SearchClose" to="." method="_on_close_search_pressed"] +[node name="ShortcutsPanel" type="PanelContainer" parent="."] +unique_name_in_owner = true +visible = false +layout_mode = 0 +offset_left = 51.0 +offset_top = 57.0 +offset_right = 571.0 +offset_bottom = 416.0 +theme = SubResource("Theme_feml8") +theme_override_styles/panel = SubResource("StyleBoxFlat_j85ew") +script = ExtResource("6_rfuk0") + +[node name="VBoxContainer" type="VBoxContainer" parent="ShortcutsPanel"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="ShortcutsPanel/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="ShortcutsPanel/VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_type_variation = &"DialogicSectionBig" +text = "Shortcuts " + +[node name="CloseShortcutPanel" type="Button" parent="ShortcutsPanel/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +icon = SubResource("ImageTexture_u2118") +flat = true + +[node name="ScrollContainer" type="ScrollContainer" parent="ShortcutsPanel/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ShortcutList" type="GridContainer" parent="ShortcutsPanel/VBoxContainer/ScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/h_separation = 11 +columns = 2 + +[connection signal="text_changed" from="VBox/SearchReplaceSection/VBox/SearchSection/Search" to="." method="_on_search_text_changed"] +[connection signal="pressed" from="VBox/SearchReplaceSection/VBox/SearchSection/SearchUp" to="." method="_on_search_up_pressed"] +[connection signal="pressed" from="VBox/SearchReplaceSection/VBox/SearchSection/SearchDown" to="." method="_on_search_down_pressed"] +[connection signal="toggled" from="VBox/SearchReplaceSection/VBox/SearchSection/MatchCase" to="." method="_on_match_case_toggled"] +[connection signal="toggled" from="VBox/SearchReplaceSection/VBox/SearchSection/WholeWords" to="." method="_on_whole_words_toggled"] +[connection signal="pressed" from="VBox/SearchReplaceSection/VBox/SearchSection/SearchClose" to="." method="_on_close_search_pressed"] +[connection signal="pressed" from="VBox/SearchReplaceSection/VBox/ReplaceSection/ReplaceButton" to="." method="_on_replace_button_pressed"] +[connection signal="pressed" from="VBox/SearchReplaceSection/VBox/ReplaceSection/ReplaceAllButton" to="." method="_on_replace_all_button_pressed"] +[connection signal="pressed" from="VBox/SearchReplaceSection/VBox/ReplaceSection/ReplaceGlobal" to="." method="_on_replace_global_pressed"] [connection signal="pressed" from="NoTimelineScreen/CenterContainer/VBoxContainer/CreateTimelineButton" to="." method="_on_create_timeline_button_pressed"] +[connection signal="pressed" from="ShortcutsPanel/VBoxContainer/HBoxContainer/CloseShortcutPanel" to="ShortcutsPanel" method="_on_close_shortcut_panel_pressed"] diff --git a/addons/dialogic/Editor/dialogic_editor.gd b/addons/dialogic/Editor/dialogic_editor.gd index 353958ac..4dfbe2a4 100644 --- a/addons/dialogic/Editor/dialogic_editor.gd +++ b/addons/dialogic/Editor/dialogic_editor.gd @@ -8,6 +8,7 @@ extends Control signal resource_saved() signal resource_unsaved() +@warning_ignore("unused_signal")# This is emitted from the Editors Manager signal opened var current_resource: Resource diff --git a/addons/dialogic/Editor/dialogic_editor.gd.uid b/addons/dialogic/Editor/dialogic_editor.gd.uid index a56b1347..c28b30bb 100644 --- a/addons/dialogic/Editor/dialogic_editor.gd.uid +++ b/addons/dialogic/Editor/dialogic_editor.gd.uid @@ -1 +1 @@ -uid://yyrlq2xfeqex +uid://dorbh771j7fyf diff --git a/addons/dialogic/Editor/editor_main.gd b/addons/dialogic/Editor/editor_main.gd index 59940575..0e4a4455 100644 --- a/addons/dialogic/Editor/editor_main.gd +++ b/addons/dialogic/Editor/editor_main.gd @@ -53,61 +53,45 @@ func _on_sidebar_toggled(sidebar_shown: bool) -> void: func update_theme_additions() -> void: - add_theme_stylebox_override( - "panel", - ( - DCSS - . inline( - { - "background": get_theme_color("base_color", "Editor"), - "padding": - [5 * DialogicUtil.get_editor_scale(), 5 * DialogicUtil.get_editor_scale()], - } - ) - ) - ) - var holder_panel := ( - DCSS - . inline( - { - "border-radius": 5, - #'border': 2, - #'border-color': get_theme_color("base_color", "Editor"), - "background": get_theme_color("dark_color_2", "Editor"), - "padding": - [5 * DialogicUtil.get_editor_scale(), 5 * DialogicUtil.get_editor_scale()], - } - ) - ) + add_theme_stylebox_override("panel", DCSS.inline({ + "background": get_theme_color("base_color", "Editor"), + "padding": + [5 * DialogicUtil.get_editor_scale(), 5 * DialogicUtil.get_editor_scale()], + })) + var holder_panel := (DCSS.inline({ + "border-radius": 5, + "background": get_theme_color("dark_color_2", "Editor"), + "padding": + [5 * DialogicUtil.get_editor_scale(), 5 * DialogicUtil.get_editor_scale()], + })) + holder_panel.border_width_top = 0 holder_panel.corner_radius_top_left = 0 editors_manager.editors_holder.add_theme_stylebox_override("panel", holder_panel) - if theme == null: - theme = Theme.new() - theme.clear() + var new_theme := Theme.new() - theme.set_type_variation("DialogicTitle", "Label") - theme.set_font("font", "DialogicTitle", get_theme_font("title", "EditorFonts")) - theme.set_color("font_color", "DialogicTitle", get_theme_color("warning_color", "Editor")) - theme.set_color( + new_theme.set_type_variation("DialogicTitle", "Label") + new_theme.set_font("font", "DialogicTitle", get_theme_font("title", "EditorFonts")) + new_theme.set_color("font_color", "DialogicTitle", get_theme_color("warning_color", "Editor")) + new_theme.set_color( "font_uneditable_color", "DialogicTitle", get_theme_color("warning_color", "Editor") ) - theme.set_color( + new_theme.set_color( "font_selected_color", "DialogicTitle", get_theme_color("warning_color", "Editor") ) - theme.set_font_size( + new_theme.set_font_size( "font_size", "DialogicTitle", get_theme_font_size("doc_size", "EditorFonts") ) - theme.set_type_variation("DialogicSubTitle", "Label") - theme.set_font("font", "DialogicSubTitle", get_theme_font("title", "EditorFonts")) - theme.set_font_size( + new_theme.set_type_variation("DialogicSubTitle", "Label") + new_theme.set_font("font", "DialogicSubTitle", get_theme_font("title", "EditorFonts")) + new_theme.set_font_size( "font_size", "DialogicSubTitle", get_theme_font_size("doc_size", "EditorFonts") ) - theme.set_color("font_color", "DialogicSubTitle", get_theme_color("accent_color", "Editor")) + new_theme.set_color("font_color", "DialogicSubTitle", get_theme_color("accent_color", "Editor")) - theme.set_type_variation("DialogicPanelA", "PanelContainer") + new_theme.set_type_variation("DialogicPanelA", "PanelContainer") var panel_style := ( DCSS . inline( @@ -118,19 +102,19 @@ func update_theme_additions() -> void: } ) ) - theme.set_stylebox("panel", "DialogicPanelA", panel_style) - theme.set_stylebox("normal", "DialogicPanelA", panel_style) + new_theme.set_stylebox("panel", "DialogicPanelA", panel_style) + new_theme.set_stylebox("normal", "DialogicPanelA", panel_style) var dark_panel := panel_style.duplicate() dark_panel.bg_color = get_theme_color("dark_color_3", "Editor") - theme.set_stylebox("panel", "DialogicPanelDarkA", dark_panel) + new_theme.set_stylebox("panel", "DialogicPanelDarkA", dark_panel) var cornerless_panel := panel_style.duplicate() cornerless_panel.corner_radius_top_left = 0 - theme.set_stylebox("panel", "DialogicPanelA_cornerless", cornerless_panel) + new_theme.set_stylebox("panel", "DialogicPanelA_cornerless", cornerless_panel) # panel used for example for portrait previews in character editor - theme.set_type_variation("DialogicPanelB", "PanelContainer") + new_theme.set_type_variation("DialogicPanelB", "PanelContainer") var side_panel: StyleBoxFlat = panel_style.duplicate() side_panel.corner_radius_top_left = 0 side_panel.corner_radius_bottom_left = 0 @@ -138,10 +122,11 @@ func update_theme_additions() -> void: side_panel.bg_color = get_theme_color("dark_color_2", "Editor") side_panel.set_border_width_all(1) side_panel.border_width_left = 0 + side_panel.content_margin_left = 0 side_panel.border_color = get_theme_color("contrast_color_2", "Editor") - theme.set_stylebox("panel", "DialogicPanelB", side_panel) + new_theme.set_stylebox("panel", "DialogicPanelB", side_panel) - theme.set_type_variation("DialogicEventEdit", "Control") + new_theme.set_type_variation("DialogicEventEdit", "Control") var edit_panel := StyleBoxFlat.new() edit_panel.draw_center = true edit_panel.bg_color = get_theme_color("accent_color", "Editor") @@ -153,96 +138,81 @@ func update_theme_additions() -> void: edit_panel.content_margin_left = 5 edit_panel.content_margin_right = 5 edit_panel.set_corner_radius_all(1) - theme.set_stylebox("panel", "DialogicEventEdit", edit_panel) - theme.set_stylebox("normal", "DialogicEventEdit", edit_panel) + new_theme.set_stylebox("panel", "DialogicEventEdit", edit_panel) + new_theme.set_stylebox("normal", "DialogicEventEdit", edit_panel) var focus_edit := edit_panel.duplicate() focus_edit.border_color = get_theme_color("property_color_z", "Editor") focus_edit.draw_center = false - theme.set_stylebox("focus", "DialogicEventEdit", focus_edit) + new_theme.set_stylebox("focus", "DialogicEventEdit", focus_edit) var hover_edit := edit_panel.duplicate() hover_edit.border_color = get_theme_color("warning_color", "Editor") - theme.set_stylebox("hover", "DialogicEventEdit", hover_edit) + new_theme.set_stylebox("hover", "DialogicEventEdit", hover_edit) var disabled_edit := edit_panel.duplicate() disabled_edit.border_color = get_theme_color("property_color", "Editor") - theme.set_stylebox("disabled", "DialogicEventEdit", disabled_edit) + new_theme.set_stylebox("disabled", "DialogicEventEdit", disabled_edit) - theme.set_type_variation("DialogicHintText", "Label") - theme.set_color("font_color", "DialogicHintText", get_theme_color("readonly_color", "Editor")) - theme.set_font("font", "DialogicHintText", get_theme_font("doc_italic", "EditorFonts")) + new_theme.set_type_variation("DialogicHintText", "Label") + new_theme.set_color("font_color", "DialogicHintText", get_theme_color("readonly_color", "Editor")) + new_theme.set_font("font", "DialogicHintText", get_theme_font("doc_italic", "EditorFonts")) - theme.set_type_variation("DialogicHintText2", "Label") - theme.set_color( + new_theme.set_type_variation("DialogicHintText2", "Label") + new_theme.set_color( "font_color", "DialogicHintText2", get_theme_color("property_color_w", "Editor") ) - theme.set_font("font", "DialogicHintText2", get_theme_font("doc_italic", "EditorFonts")) + new_theme.set_font("font", "DialogicHintText2", get_theme_font("doc_italic", "EditorFonts")) - theme.set_type_variation("DialogicSection", "Label") - theme.set_font("font", "DialogicSection", get_theme_font("main_msdf", "EditorFonts")) - theme.set_color("font_color", "DialogicSection", get_theme_color("property_color_z", "Editor")) - theme.set_font_size( + new_theme.set_type_variation("DialogicSection", "Label") + new_theme.set_font("font", "DialogicSection", get_theme_font("main_msdf", "EditorFonts")) + new_theme.set_color("font_color", "DialogicSection", get_theme_color("property_color_z", "Editor")) + new_theme.set_font_size( "font_size", "DialogicSection", get_theme_font_size("doc_size", "EditorFonts") ) - theme.set_type_variation("DialogicSettingsSection", "DialogicSection") - theme.set_font("font", "DialogicSettingsSection", get_theme_font("main_msdf", "EditorFonts")) - theme.set_color( + new_theme.set_type_variation("DialogicSettingsSection", "DialogicSection") + new_theme.set_font("font", "DialogicSettingsSection", get_theme_font("main_msdf", "EditorFonts")) + new_theme.set_color( "font_color", "DialogicSettingsSection", get_theme_color("property_color_z", "Editor") ) - theme.set_font_size( + new_theme.set_font_size( "font_size", "DialogicSettingsSection", get_theme_font_size("doc_size", "EditorFonts") ) - theme.set_type_variation("DialogicSectionBig", "DialogicSection") - theme.set_color("font_color", "DialogicSectionBig", get_theme_color("accent_color", "Editor")) - theme.set_font_size( + new_theme.set_type_variation("DialogicSectionBig", "DialogicSection") + new_theme.set_color("font_color", "DialogicSectionBig", get_theme_color("accent_color", "Editor")) + new_theme.set_font_size( "font_size", "DialogicSectionBig", get_theme_font_size("doc_title_size", "EditorFonts") ) - theme.set_type_variation("DialogicLink", "LinkButton") - theme.set_color("font_hover_color", "DialogicLink", get_theme_color("warning_color", "Editor")) + new_theme.set_type_variation("DialogicLink", "LinkButton") + new_theme.set_color("font_hover_color", "DialogicLink", get_theme_color("warning_color", "Editor")) - theme.set_type_variation("DialogicMegaSeparator", "HSeparator") - ( - theme - . set_stylebox( - "separator", - "DialogicMegaSeparator", - ( - DCSS - . inline( - { + new_theme.set_type_variation("DialogicMegaSeparator", "HSeparator") + new_theme.set_stylebox("separator", "DialogicMegaSeparator", + DCSS.inline({ "border-radius": 10, "border": 0, "background": get_theme_color("accent_color", "Editor"), "padding": [5, 5], - } + }) ) - ) - ) - ) - theme.set_constant("separation", "DialogicMegaSeparator", 50) + new_theme.set_constant("separation", "DialogicMegaSeparator", 50) - theme.set_type_variation("DialogicTextEventTextEdit", "CodeEdit") + new_theme.set_type_variation("DialogicTextEventTextEdit", "CodeEdit") var editor_settings := plugin_reference.get_editor_interface().get_editor_settings() - var text_panel := ( - DCSS - . inline( - { + var text_panel := DCSS.inline({ "border-radius": 8, "background": editor_settings.get_setting("text_editor/theme/highlighting/background_color").lerp( editor_settings.get_setting("text_editor/theme/highlighting/text_color"), 0.05 ), "padding": [8, 8], - } - ) - ) + }) text_panel.content_margin_bottom = 5 text_panel.content_margin_left = 13 - theme.set_stylebox("normal", "DialogicTextEventTextEdit", text_panel) + new_theme.set_stylebox("normal", "DialogicTextEventTextEdit", text_panel) var event_field_group_panel := DCSS.inline({ 'border-radius': 8, @@ -250,10 +220,12 @@ func update_theme_additions() -> void: "padding":2, "boder-color": get_theme_color("property_color", "Editor"), "background":"none"}) - theme.set_type_variation("DialogicEventEditGroup", "PanelContainer") - theme.set_stylebox("panel", "DialogicEventEditGroup", event_field_group_panel) + new_theme.set_type_variation("DialogicEventEditGroup", "PanelContainer") + new_theme.set_stylebox("panel", "DialogicEventEditGroup", event_field_group_panel) - theme.set_icon('Plugin', 'Dialogic', load("res://addons/dialogic/Editor/Images/plugin-icon.svg")) + new_theme.set_icon('Plugin', 'Dialogic', load("res://addons/dialogic/Editor/Images/plugin-icon.svg")) + + theme = new_theme ## Switches from floating window mode to embedded mode based on current mode @@ -301,21 +273,28 @@ func swap_to_embedded_editor() -> void: func godot_file_dialog( - callable: Callable, - filter: String, - mode := EditorFileDialog.FILE_MODE_OPEN_FILE, - window_title := "Save", - current_file_name := "New_File", - saving_something := false, - extra_message: String = "" -) -> EditorFileDialog: + callable: Callable, filter: String, mode := EditorFileDialog.FILE_MODE_OPEN_FILE, + window_title := "Save", + current_file_name := "New_File", + saving_something := false, + extra_message: String = "" + ) -> EditorFileDialog: + for connection in editor_file_dialog.file_selected.get_connections(): editor_file_dialog.file_selected.disconnect(connection.callable) for connection in editor_file_dialog.dir_selected.get_connections(): editor_file_dialog.dir_selected.disconnect(connection.callable) + + if mode == EditorFileDialog.FILE_MODE_OPEN_FILE or mode == EditorFileDialog.FILE_MODE_SAVE_FILE: + editor_file_dialog.file_selected.connect(callable) + elif mode == EditorFileDialog.FILE_MODE_OPEN_DIR: + editor_file_dialog.dir_selected.connect(callable) + elif mode == EditorFileDialog.FILE_MODE_OPEN_ANY: + editor_file_dialog.dir_selected.connect(callable) + editor_file_dialog.file_selected.connect(callable) + editor_file_dialog.file_mode = mode editor_file_dialog.clear_filters() - editor_file_dialog.popup_centered_ratio(0.6) editor_file_dialog.add_filter(filter) editor_file_dialog.title = window_title editor_file_dialog.current_file = current_file_name @@ -325,12 +304,7 @@ func godot_file_dialog( editor_file_dialog.get_meta("info_message_label").text = extra_message else: editor_file_dialog.get_meta("info_message_label").hide() + editor_file_dialog.popup_centered_ratio(0.6) + - if mode == EditorFileDialog.FILE_MODE_OPEN_FILE or mode == EditorFileDialog.FILE_MODE_SAVE_FILE: - editor_file_dialog.file_selected.connect(callable) - elif mode == EditorFileDialog.FILE_MODE_OPEN_DIR: - editor_file_dialog.dir_selected.connect(callable) - elif mode == EditorFileDialog.FILE_MODE_OPEN_ANY: - editor_file_dialog.dir_selected.connect(callable) - editor_file_dialog.file_selected.connect(callable) return editor_file_dialog diff --git a/addons/dialogic/Editor/editor_main.gd.uid b/addons/dialogic/Editor/editor_main.gd.uid index 4934e5d9..04b57ece 100644 --- a/addons/dialogic/Editor/editor_main.gd.uid +++ b/addons/dialogic/Editor/editor_main.gd.uid @@ -1 +1 @@ -uid://mgyyluu8m3ye +uid://q24lthmavkvn diff --git a/addons/dialogic/Editor/editor_main.tscn b/addons/dialogic/Editor/editor_main.tscn index b796b540..6b8074c0 100644 --- a/addons/dialogic/Editor/editor_main.tscn +++ b/addons/dialogic/Editor/editor_main.tscn @@ -1,18 +1,18 @@ [gd_scene load_steps=18 format=3 uid="uid://de6yhw4r8jqb3"] -[ext_resource type="Script" uid="uid://mgyyluu8m3ye" path="res://addons/dialogic/Editor/editor_main.gd" id="1_x88ov"] -[ext_resource type="Script" uid="uid://badmd3xomongp" path="res://addons/dialogic/Editor/editors_manager.gd" id="2_pe2tl"] +[ext_resource type="Script" uid="uid://q24lthmavkvn" path="res://addons/dialogic/Editor/editor_main.gd" id="1_x88ov"] +[ext_resource type="Script" uid="uid://cefv8yoo8q7k6" path="res://addons/dialogic/Editor/editors_manager.gd" id="2_pe2tl"] [ext_resource type="Texture2D" uid="uid://dybg3l5pwetne" path="res://addons/dialogic/Editor/Images/plugin-icon.svg" id="2_scwcl"] [ext_resource type="PackedScene" uid="uid://cwe3r2tbh2og1" path="res://addons/dialogic/Editor/Common/side_bar.tscn" id="3_lp6hj"] -[ext_resource type="Script" uid="uid://ckucbhl6k6w3r" path="res://addons/dialogic/Editor/Common/toolbar.gd" id="4_6cx8s"] +[ext_resource type="Script" uid="uid://1m3sqaws1hin" path="res://addons/dialogic/Editor/Common/toolbar.gd" id="4_6cx8s"] [ext_resource type="Texture2D" uid="uid://bbea0efx0ybu7" path="res://addons/dialogic/Editor/Images/Resources/character.svg" id="6_8yp76"] [ext_resource type="Texture2D" uid="uid://b5xwnxdb7064n" path="res://addons/dialogic/Modules/Glossary/icon.svg" id="7_45ytg"] [ext_resource type="Texture2D" uid="uid://1mccycya6eua" path="res://addons/dialogic/Modules/StyleEditor/styles_icon.svg" id="8_jj1i6"] [ext_resource type="Texture2D" uid="uid://ckilxvwc34s84" path="res://addons/dialogic/Modules/Variable/variable.svg" id="9_k4reh"] [ext_resource type="PackedScene" uid="uid://c7lmt5cp7bxcm" path="res://addons/dialogic/Editor/Common/reference_manager.tscn" id="10_l1rf8"] -[ext_resource type="Script" uid="uid://bwsjqnvqt6dp2" path="res://addons/dialogic/Editor/Common/reference_manager_window.gd" id="10_xbkrt"] -[ext_resource type="Script" uid="uid://b60na7qjgkmaa" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd" id="11_fyce4"] -[ext_resource type="Script" uid="uid://dm3a08uuk04ky" path="res://addons/dialogic/Editor/Common/update_manager.gd" id="14_l6b1p"] +[ext_resource type="Script" uid="uid://bxr2qomm7wm85" path="res://addons/dialogic/Editor/Common/reference_manager_window.gd" id="10_xbkrt"] +[ext_resource type="Script" uid="uid://camdhr6iwaywr" path="res://addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd" id="11_fyce4"] +[ext_resource type="Script" uid="uid://1tph6ios6ry2" path="res://addons/dialogic/Editor/Common/update_manager.gd" id="14_l6b1p"] [ext_resource type="PackedScene" uid="uid://vv3m5m68fwg7" path="res://addons/dialogic/Editor/Common/update_install_window.tscn" id="15_cu4xj"] [sub_resource type="Image" id="Image_4esak"] diff --git a/addons/dialogic/Editor/editors_manager.gd.uid b/addons/dialogic/Editor/editors_manager.gd.uid index 5fc8a9b9..4c21af9c 100644 --- a/addons/dialogic/Editor/editors_manager.gd.uid +++ b/addons/dialogic/Editor/editors_manager.gd.uid @@ -1 +1 @@ -uid://badmd3xomongp +uid://cefv8yoo8q7k6 diff --git a/addons/dialogic/Example Assets/Fonts/LICENSE.txt b/addons/dialogic/Example Assets/Fonts/LICENSE.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/addons/dialogic/Example Assets/Fonts/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/addons/dialogic/Example Assets/already_read_indicator.gd.uid b/addons/dialogic/Example Assets/already_read_indicator.gd.uid index 379fecc9..99091114 100644 --- a/addons/dialogic/Example Assets/already_read_indicator.gd.uid +++ b/addons/dialogic/Example Assets/already_read_indicator.gd.uid @@ -1 +1 @@ -uid://b36mpbo5v3tc8 +uid://qru8kj5n8hup diff --git a/addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd b/addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd new file mode 100644 index 00000000..536d62a5 --- /dev/null +++ b/addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd @@ -0,0 +1,84 @@ +@tool +class_name DialogicRichTextTransitionEffect +extends RichTextEffect + +var visible_characters := -1 + +@export var bbcode := "animate_in" +var cache := [] + +@export_range(0.0, 5.0, 0.01) var time := 0.2 +@export_group("Color", "color") +@export var color_modulate: Gradient = null +@export var color_replace: Gradient = null +@export_group("Scale", "scale") +@export var scale_enabled := false +@export var scale_curve := Curve.new() +@export var scale_pivot := Vector2() +@export_group("Position", "position") +@export var position_enabled := false +@export var position_x_curve := Curve.new() +@export var position_y_curve := Curve.new() + +@export_group("Test", "test") +@export_range(-0.1, 1.0, 0.1) var test_value := -0.1 + +var was_skipped := false +var was_reset := false + + +func reset() -> void: + was_reset = true + was_skipped = false + cache.clear() + + +func skip() -> void: + was_skipped = true + + +func _process_custom_fx(char_fx: CharFXTransform) -> bool: + var char_age :float = 0.0 + if test_value >= 0: + char_age = test_value + + else: + if visible_characters == 0: + cache.clear() + return false + if was_reset: + if visible_characters != -1: + was_reset = false + else: + return false + + if len(cache) < visible_characters or visible_characters == -1 or was_skipped: + if char_fx.range.x >= len(cache): + cache.append(char_fx.elapsed_time) + + if was_skipped: + for i in range(len(cache)): + cache[i] = char_fx.elapsed_time-time + + if len(cache) > char_fx.range.x: + char_age = char_fx.elapsed_time - cache[char_fx.range.x] + + var text_server := TextServerManager.get_primary_interface() + var trans: float = clamp(char_age, 0.0, time)/time + + if color_replace: + var c := color_replace.sample(trans) + c.a = 1 + char_fx.color = char_fx.color.lerp(c, color_replace.sample(trans).a) + if color_modulate: + char_fx.color *= color_modulate.sample(trans) + if char_fx.font.is_valid(): + var glyph_size := text_server.font_get_glyph_size(char_fx.font, Vector2i(16,1), char_fx.glyph_index) + if scale_enabled: + char_fx.transform = char_fx.transform.translated_local(scale_pivot*glyph_size*Vector2(1, -1)*(1-scale_curve.sample(trans))) + char_fx.transform = char_fx.transform.scaled_local(Vector2.ONE*scale_curve.sample(trans)) + + if position_enabled: + char_fx.transform = char_fx.transform.translated_local(Vector2(position_x_curve.sample(trans), position_y_curve.sample(trans))*glyph_size) + + return true diff --git a/addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd.uid b/addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd.uid new file mode 100644 index 00000000..bcd0176b --- /dev/null +++ b/addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd.uid @@ -0,0 +1 @@ +uid://wf7hpguw17ex diff --git a/addons/dialogic/Example Assets/bbcode_transitions/fade_in.tres b/addons/dialogic/Example Assets/bbcode_transitions/fade_in.tres new file mode 100644 index 00000000..ac150244 --- /dev/null +++ b/addons/dialogic/Example Assets/bbcode_transitions/fade_in.tres @@ -0,0 +1,17 @@ +[gd_resource type="RichTextEffect" script_class="DialogicRichTextTransitionEffect" load_steps=3 format=3 uid="uid://qegqrr4g2riu"] + +[ext_resource type="Script" uid="uid://wf7hpguw17ex" path="res://addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd" id="1_5w3vn"] + +[sub_resource type="Gradient" id="Gradient_5w3vn"] +colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1) + +[resource] +script = ExtResource("1_5w3vn") +bbcode = "fade_in" +time = 0.2 +color_modulate = SubResource("Gradient_5w3vn") +scale_enabled = false +scale_pivot = Vector2(0, 0) +position_enabled = false +test_value = -0.1 +metadata/_custom_type_script = "uid://wf7hpguw17ex" diff --git a/addons/dialogic/Example Assets/bbcode_transitions/fade_scale_in.tres b/addons/dialogic/Example Assets/bbcode_transitions/fade_scale_in.tres new file mode 100644 index 00000000..0c91435c --- /dev/null +++ b/addons/dialogic/Example Assets/bbcode_transitions/fade_scale_in.tres @@ -0,0 +1,24 @@ +[gd_resource type="RichTextEffect" script_class="DialogicRichTextTransitionEffect" load_steps=4 format=3 uid="uid://hx8qyt5ry3h0"] + +[ext_resource type="Script" uid="uid://wf7hpguw17ex" path="res://addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd" id="1_rsak6"] + +[sub_resource type="Gradient" id="Gradient_rsak6"] +offsets = PackedFloat32Array(0, 0.6351706) +colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1) + +[sub_resource type="Curve" id="Curve_oitc5"] +_limits = [0.0, 2.0, 0.0, 1.0] +_data = [Vector2(0, 2), 0.0, 0.0, 0, 0, Vector2(0.40294844, 1.0066038), -0.13865282, 0.0, 0, 0] +point_count = 2 + +[resource] +script = ExtResource("1_rsak6") +bbcode = "fade_scale_in" +time = 0.30000000000000004 +color_modulate = SubResource("Gradient_rsak6") +scale_enabled = true +scale_curve = SubResource("Curve_oitc5") +scale_pivot = Vector2(0.5, 0.5) +position_enabled = false +test_value = -0.1 +metadata/_custom_type_script = "uid://wf7hpguw17ex" diff --git a/addons/dialogic/Example Assets/bbcode_transitions/fancy_in.tres b/addons/dialogic/Example Assets/bbcode_transitions/fancy_in.tres new file mode 100644 index 00000000..5f48cfc6 --- /dev/null +++ b/addons/dialogic/Example Assets/bbcode_transitions/fancy_in.tres @@ -0,0 +1,35 @@ +[gd_resource type="RichTextEffect" script_class="DialogicRichTextTransitionEffect" load_steps=6 format=3 uid="uid://c8b884puc720d"] + +[ext_resource type="Script" uid="uid://wf7hpguw17ex" path="res://addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd" id="1_n3lqs"] + +[sub_resource type="Gradient" id="Gradient_n3lqs"] +offsets = PackedFloat32Array(0, 0.45292622) +colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1) + +[sub_resource type="Gradient" id="Gradient_lhhwu"] +interpolation_mode = 1 +offsets = PackedFloat32Array(0, 0.6666667, 0.86513996) +colors = PackedColorArray(0.5208, 0.76631993, 0.93, 0, 0.5242275, 0.76595265, 0.93170327, 1, 0.5208, 0.76631993, 0.93, 0) + +[sub_resource type="Curve" id="Curve_lhhwu"] +_data = [Vector2(0.002457004, 1), 0.0, -1.993977, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="Curve" id="Curve_4i73d"] +_limits = [0.0, 1.5, 0.0, 1.0] +_data = [Vector2(0, 0.6627359), 0.0, 1.7969435, 0, 0, Vector2(0.4987715, 1.0308962), -1.6188686, -1.6188686, 0, 0, Vector2(0.66093373, 1), -0.34929827, 0.0, 0, 0] +point_count = 3 + +[resource] +script = ExtResource("1_n3lqs") +bbcode = "fancy_in" +time = 0.4 +color_modulate = SubResource("Gradient_n3lqs") +color_replace = SubResource("Gradient_lhhwu") +scale_enabled = true +scale_curve = SubResource("Curve_4i73d") +scale_pivot = Vector2(0.5, 0) +position_enabled = true +position_x_curve = SubResource("Curve_lhhwu") +test_value = -0.1 +metadata/_custom_type_script = "uid://wf7hpguw17ex" diff --git a/addons/dialogic/Example Assets/bbcode_transitions/shaky_in.tres b/addons/dialogic/Example Assets/bbcode_transitions/shaky_in.tres new file mode 100644 index 00000000..f781b310 --- /dev/null +++ b/addons/dialogic/Example Assets/bbcode_transitions/shaky_in.tres @@ -0,0 +1,35 @@ +[gd_resource type="RichTextEffect" script_class="DialogicRichTextTransitionEffect" load_steps=6 format=3 uid="uid://dnxkgwncm1pt5"] + +[ext_resource type="Script" uid="uid://wf7hpguw17ex" path="res://addons/dialogic/Example Assets/bbcode_transitions/bbcode_transition_effect.gd" id="1_ur6c5"] + +[sub_resource type="Gradient" id="Gradient_ur6c5"] +offsets = PackedFloat32Array(0, 0.5089058) +colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1) + +[sub_resource type="Curve" id="Curve_5qe3f"] +_limits = [-0.5, 0.51556605, 0.0, 1.0] +_data = [Vector2(0, 0.0235914), 0.0, 0.0, 0, 0, Vector2(0.019656021, -0.2441923), 0.0, 0.0, 0, 0, Vector2(0.046683047, 0.17305207), 0.0, 0.0, 0, 0, Vector2(0.1081081, -0.23173726), 0.0, 0.0, 0, 0, Vector2(0.16216215, 0.12323183), 0.0, 0.0, 0, 0, Vector2(0.2997543, -0.16946197), 0.0, 0.0, 0, 0, Vector2(0.38329238, 0.042274), 0.0, 0.0, 0, 0, Vector2(0.46928746, -0.107186675), 0.0, 0.0, 0, 0, Vector2(0.5135135, 0.054729044), 0.0, 0.0, 0, 0, Vector2(0.66339064, -0.07604903), 0.0, 0.0, 0, 0, Vector2(0.86240786, 0.054729044), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 12 + +[sub_resource type="Curve" id="Curve_ur6c5"] +_limits = [-0.5, 0.51556605, 0.0, 1.0] +_data = [Vector2(0, 0.042274), 0.0, 0.0, 0, 0, Vector2(0.051597048, -0.13209677), 0.0, 0.0, 0, 0, Vector2(0.09336609, 0.21041724), 0.0, 0.0, 0, 0, Vector2(0.14742014, -0.25664735), 0.0, 0.0, 0, 0, Vector2(0.22850122, 0.098321736), 0.0, 0.0, 0, 0, Vector2(0.31203932, -0.107186675), 0.0, 0.0, 0, 0, Vector2(0.44717443, 0.054729044), 0.0, 0.0, 0, 0, Vector2(0.5995086, -0.08227658), 0.0, 0.0, 0, 0, Vector2(0.8132678, 0.042274), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] +point_count = 10 + +[sub_resource type="Curve" id="Curve_qelc7"] +_data = [Vector2(0, 0.57688683), 0.0, 0.0, 0, 0, Vector2(0.14250615, 0.77311325), 0.0, 0.0, 0, 0, Vector2(0.2850123, 0.6443397), 0.0, 0.0, 0, 0, Vector2(0.41769046, 0.7976416), 0.0, 0.0, 0, 0, Vector2(0.5503686, 0.74245286), 0.0, 0.0, 0, 0, Vector2(0.6781328, 0.8712265), 0.0, 0.0, 0, 0, Vector2(0.79606885, 0.8528303), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0] +point_count = 8 + +[resource] +script = ExtResource("1_ur6c5") +bbcode = "shaky_in" +time = 0.4 +color_modulate = SubResource("Gradient_ur6c5") +scale_enabled = true +scale_curve = SubResource("Curve_qelc7") +scale_pivot = Vector2(0.5, 0.5) +position_enabled = true +position_x_curve = SubResource("Curve_5qe3f") +position_y_curve = SubResource("Curve_ur6c5") +test_value = -0.1 +metadata/_custom_type_script = "uid://wf7hpguw17ex" diff --git a/addons/dialogic/Example Assets/default_event.gd.uid b/addons/dialogic/Example Assets/default_event.gd.uid index 7cc6f647..46e302f4 100644 --- a/addons/dialogic/Example Assets/default_event.gd.uid +++ b/addons/dialogic/Example Assets/default_event.gd.uid @@ -1 +1 @@ -uid://wksbyrr22x0g +uid://dgs7be3hh1crk diff --git a/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.gd.uid b/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.gd.uid index 3eb18c06..5d3a158d 100644 --- a/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.gd.uid +++ b/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.gd.uid @@ -1 +1 @@ -uid://cgxkxy1oihxju +uid://b0dpsqdeb27km diff --git a/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.tscn b/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.tscn index 136e66dc..7c0af5b3 100644 --- a/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.tscn +++ b/addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://cyns86lydp1tl"] -[ext_resource type="Script" uid="uid://cgxkxy1oihxju" path="res://addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.gd" id="1_63c5k"] +[ext_resource type="Script" uid="uid://b0dpsqdeb27km" path="res://addons/dialogic/Example Assets/portraits/CustomPortrait_AnimatedSprite.gd" id="1_63c5k"] [ext_resource type="Texture2D" uid="uid://bfkpn7mrd786b" path="res://addons/dialogic/Example Assets/portraits/Antonio/pl5.png" id="2_15o4t"] [ext_resource type="Texture2D" uid="uid://s2jsr1aqiu84" path="res://addons/dialogic/Example Assets/portraits/Antonio/pl5 blink.png" id="3_qen6e"] diff --git a/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.gd.uid b/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.gd.uid index 8af83326..a8470154 100644 --- a/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.gd.uid +++ b/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.gd.uid @@ -1 +1 @@ -uid://cspwplht7sm14 +uid://dixl3myysljgs diff --git a/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.tscn b/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.tscn index 1e25f8de..3af48eb2 100644 --- a/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.tscn +++ b/addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=10 format=3 uid="uid://bgshjju5v2q0i"] -[ext_resource type="Script" uid="uid://cspwplht7sm14" path="res://addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.gd" id="1_fc12l"] +[ext_resource type="Script" uid="uid://dixl3myysljgs" path="res://addons/dialogic/Example Assets/portraits/CustomPortrait_FaceAtlas.gd" id="1_fc12l"] [ext_resource type="Texture2D" uid="uid://djqit26f4be4f" path="res://addons/dialogic/Example Assets/portraits/Princess/princess_blank.png" id="2_igcyp"] [ext_resource type="Texture2D" uid="uid://ndmjrpk41eo4" path="res://addons/dialogic/Example Assets/portraits/Portrait1.png" id="3_6xy1t"] [ext_resource type="Texture2D" uid="uid://dokv225cp85ja" path="res://addons/dialogic/Example Assets/portraits/Princess/anger.png" id="3_wdpjk"] diff --git a/addons/dialogic/Modules/Audio/event_audio.gd b/addons/dialogic/Modules/Audio/event_audio.gd new file mode 100644 index 00000000..cd4f8cc3 --- /dev/null +++ b/addons/dialogic/Modules/Audio/event_audio.gd @@ -0,0 +1,397 @@ +@tool +## Event that can play audio on a channel. The channel can be prededinfed +## (with default settings defined in the settings) or created on the spot. +## If no channel is given will play as a One-Shot SFX. +class_name DialogicAudioEvent +extends DialogicEvent + +### Settings + +## The file to play. If empty, the previous audio will be faded out. +var file_path := "": + set(value): + if file_path != value: + file_path = value + ui_update_needed.emit() +## The channel name to use. If none given plays as a One-Shot SFX. +var channel_name := "": + set(value): + if channel_name != channel_name_regex.sub(value, '', true): + channel_name = channel_name_regex.sub(value, '', true) + var defaults: Dictionary = DialogicUtil.get_audio_channel_defaults().get(channel_name, {}) + if defaults: + fade_length = defaults.fade_length + volume = defaults.volume + audio_bus = defaults.audio_bus + loop = defaults.loop + ui_update_needed.emit() + +## The length of the fade. If 0 it's an instant change. +var fade_length: float = 0.0 +## The volume in decibel. +var volume: float = 0.0 +## The audio bus the audio will be played on. +var audio_bus := "" +## If true, the audio will loop, otherwise only play once. +var loop := true +## Sync starting time with different channel (if playing audio on that channel) +var sync_channel := "" + +## Helpers. Set automatically +var set_fade_length := false +var set_volume := false +var set_audio_bus := false +var set_loop := false +var set_sync_channel := false + +var regex := RegEx.create_from_string(r'(?:audio)\s*(?[\w-]{2,}|[\w]*)?\s*(")?(?(?(2)[^"\n]*|[^(: \n]*))(?(2)"|)(?:\s*\[(?.*)\])?') +var channel_name_regex := RegEx.create_from_string(r'(?^-$)|(?[^\w-]{1})') + +################################################################################ +## EXECUTE +################################################################################ + +func _execute() -> void: + var audio_settings_overrides := {} + if set_audio_bus: + audio_settings_overrides["audio_bus"] = audio_bus + if set_volume: + audio_settings_overrides["volume"] = volume + if set_fade_length: + audio_settings_overrides["fade_length"] = fade_length + if set_loop: + audio_settings_overrides["loop"] = loop + audio_settings_overrides["sync_channel"] = sync_channel + dialogic.Audio.update_audio(channel_name, file_path, audio_settings_overrides) + + finish() + +################################################################################ +## INITIALIZE +################################################################################ + +func _init() -> void: + event_name = "Audio" + set_default_color('Color7') + event_category = "Audio" + event_sorting_index = 2 + + +func _get_icon() -> Resource: + return load(this_folder.path_join('icon_music.png')) + +################################################################################ +## SAVING/LOADING +################################################################################ + +func to_text () -> String: + var result_string := "audio " + + if not channel_name.is_empty(): + result_string += channel_name + " " + else: + loop = false + + if not file_path.is_empty(): + result_string += "\"" + file_path + "\"" + else: + result_string += "-" + + var shortcode := store_to_shortcode_parameters() + if not shortcode.is_empty(): + result_string += " [" + shortcode + "]" + + return result_string + + +func from_text(string:String) -> void: + # Pre Alpha 17 Conversion + if string.begins_with('[music'): + _music_from_text(string) + return + elif string.begins_with('[sound'): + _sound_from_text(string) + return + + var result := regex.search(string) + + channel_name = result.get_string('channel') + + if result.get_string('file_path') == '-': + file_path = "" + else: + file_path = result.get_string('file_path') + + if not result.get_string('shortcode'): + return + + load_from_shortcode_parameters(result.get_string('shortcode')) + + +func get_shortcode_parameters() -> Dictionary: + return { + #param_name : property_info + "path" : {"property": "file_path", "default": "", "custom_stored":true, "ext_file":true}, + "channel" : {"property": "channel_name", "default": "", "custom_stored":true}, + "fade" : {"property": "fade_length", "default": 0.0}, + "volume" : {"property": "volume", "default": 0.0}, + "bus" : {"property": "audio_bus", "default": "", + "suggestions": DialogicUtil.get_audio_bus_suggestions}, + "loop" : {"property": "loop", "default": true}, + "sync" : {"property": "sync_channel", "default": "", + "suggestions": get_sync_audio_channel_suggestions}, + } + + +## Returns a string with all the shortcode parameters. +func store_to_shortcode_parameters(params:Dictionary = {}) -> String: + if params.is_empty(): + params = get_shortcode_parameters() + var custom_defaults: Dictionary = DialogicUtil.get_custom_event_defaults(event_name) + var channel_defaults := DialogicUtil.get_audio_channel_defaults() + var result_string := "" + for parameter in params.keys(): + var parameter_info: Dictionary = params[parameter] + var value: Variant = get(parameter_info.property) + var default_value: Variant = custom_defaults.get(parameter_info.property, parameter_info.default) + + if parameter_info.get('custom_stored', false): + continue + + if "set_" + parameter_info.property in self and not get("set_" + parameter_info.property): + continue + + if channel_name in channel_defaults.keys(): + default_value = channel_defaults[channel_name].get(parameter_info.property, default_value) + + if typeof(value) == typeof(default_value) and value == default_value: + if not "set_" + parameter_info.property in self or not get("set_" + parameter_info.property): + continue + + result_string += " " + parameter + '="' + value_to_string(value, parameter_info.get("suggestions", Callable())) + '"' + + return result_string.strip_edges() + + +func is_valid_event(string:String) -> bool: + if string.begins_with("audio"): + return true + # Pre Alpha 17 Converter + if string.strip_edges().begins_with('[music '): + return true + if string.strip_edges().begins_with('[sound '): + return true + return false + + +#region PreAlpha17 Conversion + +func _music_from_text(string:String) -> void: + var data := parse_shortcode_parameters(string) + + if data.has('channel') and data['channel'].to_int() > 0: + channel_name = 'music' + str(data['channel'].to_int() + 1) + else: + channel_name = 'music' + + # Reapply original defaults as setting channel name may have overridden them + fade_length = 0.0 + volume = 0.0 + audio_bus = '' + loop = true + + # Apply any custom event defaults + for default_prop in DialogicUtil.get_custom_event_defaults('music'): + if default_prop in self: + set(default_prop, DialogicUtil.get_custom_event_defaults('music')[default_prop]) + + # Apply shortcodes that exist + if data.has('path'): + file_path = data['path'] + if data.has('fade'): + set_fade_length = true + fade_length = data['fade'].to_float() + if data.has('volume'): + set_volume = true + volume = data['volume'].to_float() + if data.has('bus'): + set_audio_bus = true + audio_bus = data['bus'] + if data.has('loop'): + set_loop = true + loop = str_to_var(data['loop']) + update_text_version() + + +func _sound_from_text(string:String) -> void: + var data := parse_shortcode_parameters(string) + + channel_name = '' + + # Reapply original defaults as setting channel name may have overridden them + fade_length = 0.0 + volume = 0.0 + audio_bus = '' + loop = false + + # Apply any custom event defaults + for default_prop in DialogicUtil.get_custom_event_defaults('sound'): + if default_prop in self: + set(default_prop, DialogicUtil.get_custom_event_defaults('sound')[default_prop]) + + # Apply shortcodes that exist + if data.has('path'): + file_path = data['path'] + if data.has('volume'): + set_volume = true + volume = data['volume'].to_float() + if data.has('bus'): + set_audio_bus = true + audio_bus = data['bus'] + if data.has('loop'): + set_loop = true + loop = str_to_var(data['loop']) + update_text_version() + + +#endregion + +################################################################################ +## EDITOR REPRESENTATION +################################################################################ + +func build_event_editor() -> void: + add_header_edit('file_path', ValueType.FILE, { + 'left_text' : 'Play', + 'file_filter' : "*.mp3, *.ogg, *.wav; Supported Audio Files", + 'placeholder' : "Nothing", + 'editor_icon' : ["AudioStreamMP3", "EditorIcons"]}) + add_header_edit('file_path', ValueType.AUDIO_PREVIEW) + + add_header_edit('channel_name', ValueType.DYNAMIC_OPTIONS, { + 'left_text' :"on", + "right_text" : "channel.", + 'placeholder' : '(One-Shot SFX)', + 'mode' : 3, + 'suggestions_func' : get_audio_channel_suggestions, + 'validation_func' : DialogicUtil.validate_audio_channel_name, + 'tooltip' : 'Use an existing channel or type the name for a new channel.', + }) + + add_header_button('', _open_audio_settings, 'Edit Audio Channels', + editor_node.get_theme_icon("ExternalLink", "EditorIcons")) + + add_body_edit("set_fade_length", ValueType.BOOL_BUTTON,{ + "editor_icon" : ["FadeCross", "EditorIcons"], + "tooltip" : "Overwrite Fade Length" + },"!channel_name.is_empty() and has_channel_defaults()") + add_body_edit('fade_length', ValueType.NUMBER, {'left_text':'Fade Time:'}, + '!channel_name.is_empty() and (not has_channel_defaults() or set_fade_length)') + + add_body_edit("set_volume", ValueType.BOOL_BUTTON,{ + "editor_icon" : ["AudioStreamPlayer", "EditorIcons"], + "tooltip" : "Overwrite Volume" + },"!file_path.is_empty() and has_channel_defaults()") + add_body_edit('volume', ValueType.NUMBER, {'left_text':'Volume:', 'mode':2}, + '!file_path.is_empty() and (not has_channel_defaults() or set_volume)') + add_body_edit("set_audio_bus", ValueType.BOOL_BUTTON,{ + "editor_icon" : ["AudioBusBypass", "EditorIcons"], + "tooltip" : "Overwrite Audio Bus" + },"!file_path.is_empty() and has_channel_defaults()") + add_body_edit('audio_bus', ValueType.DYNAMIC_OPTIONS, { + 'left_text':'Audio Bus:', + 'placeholder' : 'Master', + 'mode' : 2, + 'suggestions_func' : DialogicUtil.get_audio_bus_suggestions, + }, '!file_path.is_empty() and (not has_channel_defaults() or set_audio_bus)') + add_body_edit("set_loop", ValueType.BOOL_BUTTON,{ + "editor_icon" : ["Loop", "EditorIcons"], + "tooltip" : "Overwrite Loop" + },"!channel_name.is_empty() and !file_path.is_empty() and has_channel_defaults()") + add_body_edit('loop', ValueType.BOOL, {'left_text':'Loop:'}, + '!channel_name.is_empty() and !file_path.is_empty() and (not has_channel_defaults() or set_loop)') + add_body_line_break("!channel_name.is_empty() and !file_path.is_empty()") + add_body_edit("set_sync_channel", ValueType.BOOL_BUTTON,{ + "editor_icon" : ["TransitionSync", "EditorIcons"], + "tooltip" : "Enable Syncing" + },"!channel_name.is_empty() and !file_path.is_empty()") + + add_body_edit('sync_channel', ValueType.DYNAMIC_OPTIONS, { + 'left_text' :'Sync with:', + 'placeholder' : '(No Sync)', + 'mode' : 3, + 'suggestions_func' : get_sync_audio_channel_suggestions, + 'validation_func' : DialogicUtil.validate_audio_channel_name, + 'tooltip' : "Use an existing channel or type the name for a new channel. If channel doesn't exist, this setting will be ignored.", + }, '!channel_name.is_empty() and !file_path.is_empty() and set_sync_channel') + + +## Used by the button on the visual event +func _open_audio_settings() -> void: + var editor_manager := editor_node.find_parent('EditorsManager') + if editor_manager: + editor_manager.open_editor(editor_manager.editors['Settings']['node'], true, "Audio") + + +## Helper for the visibility conditions +func has_channel_defaults() -> bool: + var defaults := DialogicUtil.get_audio_channel_defaults() + return defaults.has(channel_name) + + +func get_audio_channel_suggestions(filter:String) -> Dictionary: + var suggestions := {} + suggestions["(One-Shot SFX)"] = { + "value":"", + "tooltip": "Used for one shot sounds effects. Plays each sound in its own AudioStreamPlayer.", + "editor_icon": ["GuiRadioUnchecked", "EditorIcons"] + } + # TODO use .merged after dropping 4.2 support + suggestions.merge(DialogicUtil.get_audio_channel_suggestions(filter)) + return suggestions + +func get_sync_audio_channel_suggestions(filter:="") -> Dictionary: + return DialogicUtil.get_audio_channel_suggestions(filter) + + + +####################### CODE COMPLETION ######################################## +################################################################################ + +func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, word:String, symbol:String) -> void: + var line_until: String = CodeCompletionHelper.get_line_untill_caret(line) + if symbol == ' ': + if line_until.count(' ') == 1: + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, "One-Shot SFX", ' ', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6)) + for i in DialogicUtil.get_audio_channel_suggestions(""): + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i, event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6), null, " ") + elif line_until.count(" ") == 2: + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, '"', '"', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6)) + + if symbol == "[" or (symbol == " " and line.count("[")): + for i in ["fade", "volume", "bus", "loop", "sync"]: + if not i+"=" in line: + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i+'="', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6)) + + if (symbol == '"' or symbol == "=") and line.count("["): + CodeCompletionHelper.suggest_shortcode_values(TextNode, self, line, word) + + +func _get_start_code_completion(_CodeCompletionHelper:Node, TextNode:TextEdit) -> void: + TextNode.add_code_completion_option(CodeEdit.KIND_PLAIN_TEXT, 'audio', 'audio ', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.3)) + + +#################### SYNTAX HIGHLIGHTING ####################################### +################################################################################ + +func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary: + var result := regex.search(line) + + dict[result.get_start()] = {"color":event_color.lerp(Highlighter.normal_color, 0.3)} + dict[result.get_start("channel")] = {"color":event_color.lerp(Highlighter.normal_color, 0.8)} + dict[result.get_start("file_path")] = {"color":event_color.lerp(Highlighter.string_color, 0.8)} + if result.get_string("shortcode"): + dict[result.get_start("shortcode")-1] = {"color":Highlighter.normal_color} + dict = Highlighter.color_shortcode_content(dict, line, result.get_start("shortcode"), 0, event_color) + + return dict diff --git a/addons/dialogic/Modules/Audio/event_audio.gd.uid b/addons/dialogic/Modules/Audio/event_audio.gd.uid new file mode 100644 index 00000000..f22125e7 --- /dev/null +++ b/addons/dialogic/Modules/Audio/event_audio.gd.uid @@ -0,0 +1 @@ +uid://8p4qchmcuj68 diff --git a/addons/dialogic/Modules/Audio/event_music.gd b/addons/dialogic/Modules/Audio/event_music.gd deleted file mode 100644 index b7b096e1..00000000 --- a/addons/dialogic/Modules/Audio/event_music.gd +++ /dev/null @@ -1,105 +0,0 @@ -@tool -## Event that can change the currently playing background music. -## This event won't play new music if it's already playing. -class_name DialogicMusicEvent -extends DialogicEvent - - -### Settings - -## The file to play. If empty, the previous music will be faded out. -var file_path := "": - set(value): - if file_path != value: - file_path = value - ui_update_needed.emit() -## The channel to use. -var channel_id: int = 0 -## The length of the fade. If 0 (by default) it's an instant change. -var fade_length: float = 0 -## The volume the music will be played at. -var volume: float = 0 -## The audio bus the music will be played at. -var audio_bus := "" -## If true, the audio will loop, otherwise only play once. -var loop := true - - -################################################################################ -## EXECUTE -################################################################################ - -func _execute() -> void: - if not dialogic.Audio.is_music_playing_resource(file_path, channel_id): - dialogic.Audio.update_music(file_path, volume, audio_bus, fade_length, loop, channel_id) - - finish() - -################################################################################ -## INITIALIZE -################################################################################ - -func _init() -> void: - event_name = "Music" - set_default_color('Color7') - event_category = "Audio" - event_sorting_index = 2 - - -func _get_icon() -> Resource: - return load(self.get_script().get_path().get_base_dir().path_join('icon_music.png')) - -################################################################################ -## SAVING/LOADING -################################################################################ - -func get_shortcode() -> String: - return "music" - - -func get_shortcode_parameters() -> Dictionary: - return { - #param_name : property_info - "path" : {"property": "file_path", "default": ""}, - "channel" : {"property": "channel_id", "default": 0}, - "fade" : {"property": "fade_length", "default": 0}, - "volume" : {"property": "volume", "default": 0}, - "bus" : {"property": "audio_bus", "default": "", - "suggestions": get_bus_suggestions}, - "loop" : {"property": "loop", "default": true}, - } - - -################################################################################ -## EDITOR REPRESENTATION -################################################################################ - -func build_event_editor() -> void: - add_header_edit('file_path', ValueType.FILE, { - 'left_text' : 'Play', - 'file_filter' : "*.mp3, *.ogg, *.wav; Supported Audio Files", - 'placeholder' : "No music", - 'editor_icon' : ["AudioStreamPlayer", "EditorIcons"]}) - add_header_edit('channel_id', ValueType.FIXED_OPTIONS, {'left_text':'on:', 'options': get_channel_list()}) - add_header_edit('file_path', ValueType.AUDIO_PREVIEW) - add_body_edit('fade_length', ValueType.NUMBER, {'left_text':'Fade Time:'}) - add_body_edit('volume', ValueType.NUMBER, {'left_text':'Volume:', 'mode':2}, '!file_path.is_empty()') - add_body_edit('audio_bus', ValueType.SINGLELINE_TEXT, {'left_text':'Audio Bus:'}, '!file_path.is_empty()') - add_body_edit('loop', ValueType.BOOL, {'left_text':'Loop:'}, '!file_path.is_empty() and not file_path.to_lower().ends_with(".wav")') - - -func get_bus_suggestions() -> Dictionary: - var bus_name_list := {} - for i in range(AudioServer.bus_count): - bus_name_list[AudioServer.get_bus_name(i)] = {'value':AudioServer.get_bus_name(i)} - return bus_name_list - - -func get_channel_list() -> Array: - var channel_name_list := [] - for i in ProjectSettings.get_setting('dialogic/audio/max_channels', 4): - channel_name_list.append({ - 'label': 'Channel %s' % (i + 1), - 'value': i, - }) - return channel_name_list diff --git a/addons/dialogic/Modules/Audio/event_music.gd.uid b/addons/dialogic/Modules/Audio/event_music.gd.uid deleted file mode 100644 index 68ffb9ca..00000000 --- a/addons/dialogic/Modules/Audio/event_music.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bqnhktqs2281 diff --git a/addons/dialogic/Modules/Audio/event_sound.gd b/addons/dialogic/Modules/Audio/event_sound.gd deleted file mode 100644 index 0784bbf2..00000000 --- a/addons/dialogic/Modules/Audio/event_sound.gd +++ /dev/null @@ -1,86 +0,0 @@ -@tool -class_name DialogicSoundEvent -extends DialogicEvent - -## Event that allows to play a sound effect. Requires the Audio subsystem! - - -### Settings - -## The path to the file to play. -var file_path := "": - set(value): - if file_path != value: - file_path = value - ui_update_needed.emit() -## The volume to play the sound at. -var volume: float = 0 -## The bus to play the sound on. -var audio_bus := "" -## If true, the sound will loop infinitely. Not recommended (as there is no way to stop it). -var loop := false - - -################################################################################ -## EXECUTE -################################################################################ - -func _execute() -> void: - dialogic.Audio.play_sound(file_path, volume, audio_bus, loop) - finish() - - -################################################################################ -## INITIALIZE -################################################################################ - -func _init() -> void: - event_name = "Sound" - set_default_color('Color7') - event_category = "Audio" - event_sorting_index = 3 - help_page_path = "https://dialogic.coppolaemilio.com" - - -func _get_icon() -> Resource: - return load(self.get_script().get_path().get_base_dir().path_join('icon_sound.png')) - -################################################################################ -## SAVING/LOADING -################################################################################ - -func get_shortcode() -> String: - return "sound" - - -func get_shortcode_parameters() -> Dictionary: - return { - #param_name : property_name - "path" : {"property": "file_path", "default": "",}, - "volume" : {"property": "volume", "default": 0}, - "bus" : {"property": "audio_bus", "default": "", - "suggestions": get_bus_suggestions}, - "loop" : {"property": "loop", "default": false}, - } - - -################################################################################ -## EDITOR REPRESENTATION -################################################################################ - -func build_event_editor() -> void: - add_header_edit('file_path', ValueType.FILE, - {'left_text' : 'Play', - 'file_filter' : '*.mp3, *.ogg, *.wav; Supported Audio Files', - 'placeholder' : "Select file", - 'editor_icon' : ["AudioStreamPlayer", "EditorIcons"]}) - add_header_edit('file_path', ValueType.AUDIO_PREVIEW) - add_body_edit('volume', ValueType.NUMBER, {'left_text':'Volume:', 'mode':2}, '!file_path.is_empty()') - add_body_edit('audio_bus', ValueType.SINGLELINE_TEXT, {'left_text':'Audio Bus:'}, '!file_path.is_empty()') - - -func get_bus_suggestions() -> Dictionary: - var bus_name_list := {} - for i in range(AudioServer.bus_count): - bus_name_list[AudioServer.get_bus_name(i)] = {'value':AudioServer.get_bus_name(i)} - return bus_name_list diff --git a/addons/dialogic/Modules/Audio/event_sound.gd.uid b/addons/dialogic/Modules/Audio/event_sound.gd.uid deleted file mode 100644 index e382c2ff..00000000 --- a/addons/dialogic/Modules/Audio/event_sound.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://w1ofu2qjmefo diff --git a/addons/dialogic/Modules/Audio/index.gd b/addons/dialogic/Modules/Audio/index.gd index f2ff1270..61ca7fa7 100644 --- a/addons/dialogic/Modules/Audio/index.gd +++ b/addons/dialogic/Modules/Audio/index.gd @@ -3,7 +3,7 @@ extends DialogicIndexer func _get_events() -> Array: - return [this_folder.path_join('event_music.gd'), this_folder.path_join('event_sound.gd')] + return [this_folder.path_join('event_audio.gd')] func _get_subsystems() -> Array: diff --git a/addons/dialogic/Modules/Audio/index.gd.uid b/addons/dialogic/Modules/Audio/index.gd.uid index 2629a043..81c5d1f4 100644 --- a/addons/dialogic/Modules/Audio/index.gd.uid +++ b/addons/dialogic/Modules/Audio/index.gd.uid @@ -1 +1 @@ -uid://c7po0y8sx23v4 +uid://dk46l1toqeswc diff --git a/addons/dialogic/Modules/Audio/settings_audio.gd b/addons/dialogic/Modules/Audio/settings_audio.gd index d7afd3c3..8dbfc729 100644 --- a/addons/dialogic/Modules/Audio/settings_audio.gd +++ b/addons/dialogic/Modules/Audio/settings_audio.gd @@ -3,16 +3,19 @@ extends DialogicSettingsPage ## Settings page that contains settings for the audio subsystem -const MUSIC_MAX_CHANNELS := "dialogic/audio/max_channels" const TYPE_SOUND_AUDIO_BUS := "dialogic/audio/type_sound_bus" +const CHANNEL_DEFAULTS := "dialogic/audio/channel_defaults" + +var channel_defaults := {} +var _revalidate_channel_names := false + func _ready() -> void: - %MusicChannelCount.value_changed.connect(_on_music_channel_count_value_changed) %TypeSoundBus.item_selected.connect(_on_type_sound_bus_item_selected) + $Panel.add_theme_stylebox_override('panel', get_theme_stylebox("Background", "EditorStyles")) func _refresh() -> void: - %MusicChannelCount.value = ProjectSettings.get_setting(MUSIC_MAX_CHANNELS, 4) %TypeSoundBus.clear() var idx := 0 for i in range(AudioServer.bus_count): @@ -21,12 +24,218 @@ func _refresh() -> void: idx = i %TypeSoundBus.select(idx) - -func _on_music_channel_count_value_changed(value:float) -> void: - ProjectSettings.set_setting(MUSIC_MAX_CHANNELS, value) - ProjectSettings.save() + load_channel_defaults(DialogicUtil.get_audio_channel_defaults()) +func _about_to_close() -> void: + save_channel_defaults() + + +## TYPE SOUND AUDIO BUS func _on_type_sound_bus_item_selected(index:int) -> void: ProjectSettings.set_setting(TYPE_SOUND_AUDIO_BUS, %TypeSoundBus.get_item_text(index)) ProjectSettings.save() + + +#region AUDIO CHANNELS +################################################################################ + +func load_channel_defaults(dictionary:Dictionary) -> void: + channel_defaults.clear() + for i in %AudioChannelDefaults.get_children(): + i.queue_free() + + var column_names := [ + "Channel Name", + "Volume", + "Audio Bus", + "Fade", + "Loop", + "" + ] + + for column in column_names: + var label := Label.new() + label.text = column + label.theme_type_variation = 'DialogicHintText2' + %AudioChannelDefaults.add_child(label) + + var channel_names := dictionary.keys() + channel_names.sort() + + for channel_name in channel_names: + add_channel_defaults( + channel_name, + dictionary[channel_name].volume, + dictionary[channel_name].audio_bus, + dictionary[channel_name].fade_length, + dictionary[channel_name].loop) + + await get_tree().process_frame + + _revalidate_channel_names = true + revalidate_channel_names.call_deferred() + + +func save_channel_defaults() -> void: + var dictionary := {} + + for i in channel_defaults: + if is_instance_valid(channel_defaults[i].channel_name): + var channel_name := "" + if not channel_defaults[i].channel_name is Label: + if channel_defaults[i].channel_name.current_value.is_empty(): + continue + + channel_name = channel_defaults[i].channel_name.current_value + #channel_name = DialogicUtil.channel_name_regex.sub(channel_name, '', true) + + if channel_name.is_empty(): + dictionary[channel_name] = { + 'volume': channel_defaults[i].volume.get_value(), + 'audio_bus': channel_defaults[i].audio_bus.current_value, + 'fade_length': 0.0, + 'loop': false, + } + else: + dictionary[channel_name] = { + 'volume': channel_defaults[i].volume.get_value(), + 'audio_bus': channel_defaults[i].audio_bus.current_value, + 'fade_length': channel_defaults[i].fade_length.get_value(), + 'loop': channel_defaults[i].loop.button_pressed, + } + + ProjectSettings.set_setting(CHANNEL_DEFAULTS, dictionary) + ProjectSettings.save() + + +func _on_add_channel_defaults_pressed() -> void: + var added_node := add_channel_defaults('new_channel_name', 0.0, '', 0.0, true) + if added_node: + added_node.take_autofocus() + _revalidate_channel_names = true + revalidate_channel_names.call_deferred() + + +func add_channel_defaults(channel_name: String, volume: float, audio_bus: String, fade_length: float, loop: bool) -> Control: + var info := {} + + for i in %AudioChannelDefaultRow.get_children(): + var x := i.duplicate() + %AudioChannelDefaults.add_child(x) + info[i.name] = x + + + if channel_name.is_empty(): + var channel_label := Label.new() + channel_label.text = &"One-Shot SFX" + channel_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL + + %AudioChannelDefaults.add_child(channel_label) + %AudioChannelDefaults.move_child(channel_label, info.channel_name.get_index()) + info.channel_name.queue_free() + info.channel_name = channel_label + + var HintTooltip := preload("res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn") + var fade_hint := HintTooltip.instantiate() + fade_hint.hint_text = "Fading is disabled for this channel." + %AudioChannelDefaults.add_child(fade_hint) + %AudioChannelDefaults.move_child(fade_hint, info.fade_length.get_index()) + info.fade_length.queue_free() + info.fade_length = fade_hint + + var loop_hint := HintTooltip.instantiate() + loop_hint.hint_text = "Looping is disabled for this channel." + %AudioChannelDefaults.add_child(loop_hint) + %AudioChannelDefaults.move_child(loop_hint, info.loop.get_index()) + info.loop.queue_free() + info.loop = loop_hint + + info.delete.disabled = true + + else: + info.channel_name.suggestions_func = get_audio_channel_suggestions + info.channel_name.validation_func = validate_channel_names.bind(info.channel_name) + info.channel_name.set_value(channel_name) + + info.fade_length.set_value(fade_length) + + info.loop.set_pressed_no_signal(loop) + + info.audio_bus.suggestions_func = DialogicUtil.get_audio_bus_suggestions + info.audio_bus.set_value(audio_bus) + + info.delete.icon = get_theme_icon(&"Remove", &"EditorIcons") + + channel_defaults[len(channel_defaults)] = info + return info['channel_name'] + + +func _on_remove_channel_defaults_pressed(index: int) -> void: + for key in channel_defaults[index]: + channel_defaults[index][key].queue_free() + channel_defaults.erase(index) + + +func get_audio_channel_suggestions(search_text:String) -> Dictionary: + var suggestions := DialogicUtil.get_audio_channel_suggestions(search_text) + + for i in channel_defaults.values(): + if i.channel_name is DialogicVisualEditorField: + suggestions.erase(i.channel_name.current_value) + + for key in suggestions.keys(): + suggestions[key].erase('tooltip') + suggestions[key]['editor_icon'] = ["AudioStreamPlayer", "EditorIcons"] + + return suggestions + + +func revalidate_channel_names() -> void: + _revalidate_channel_names = false + for i in channel_defaults: + if (is_instance_valid(channel_defaults[i].channel_name) + and not channel_defaults[i].channel_name is Label): + channel_defaults[i].channel_name.validate() + + +func validate_channel_names(search_text: String, field_node: Control) -> Dictionary: + var channel_cache = {} + var result := {} + var tooltips := [] + + if search_text.is_empty(): + result['error_tooltip'] = 'Must not be empty.' + return result + + if field_node: + channel_cache[search_text] = [field_node] + if field_node.current_value != search_text: + _revalidate_channel_names = true + revalidate_channel_names.call_deferred() + + # Collect all channel names entered + for i in channel_defaults: + if (is_instance_valid(channel_defaults[i].channel_name) + and not channel_defaults[i].channel_name is Label + and channel_defaults[i].channel_name != field_node): + var text := channel_defaults[i].channel_name.current_value as String + if not channel_cache.has(text): + channel_cache[text] = [] + + channel_cache[text].append(channel_defaults[i].channel_name) + + # Check for duplicate names + if channel_cache.has(search_text) and channel_cache[search_text].size() > 1: + tooltips.append("Duplicate channel name.") + + # Check for invalid characters + result = DialogicUtil.validate_audio_channel_name(search_text) + if result: + tooltips.append(result.error_tooltip) + result.error_tooltip = "\n".join(tooltips) + elif not tooltips.is_empty(): + result['error_tooltip'] = "\n".join(tooltips) + + return result +#endregion diff --git a/addons/dialogic/Modules/Audio/settings_audio.gd.uid b/addons/dialogic/Modules/Audio/settings_audio.gd.uid index b4305a45..5b8c54ff 100644 --- a/addons/dialogic/Modules/Audio/settings_audio.gd.uid +++ b/addons/dialogic/Modules/Audio/settings_audio.gd.uid @@ -1 +1 @@ -uid://1w40lwv540il +uid://cqyhm6offcitc diff --git a/addons/dialogic/Modules/Audio/settings_audio.tscn b/addons/dialogic/Modules/Audio/settings_audio.tscn index 2b855b4b..41805b7b 100644 --- a/addons/dialogic/Modules/Audio/settings_audio.tscn +++ b/addons/dialogic/Modules/Audio/settings_audio.tscn @@ -1,36 +1,28 @@ -[gd_scene load_steps=3 format=3 uid="uid://c2qgetjc3mfo3"] +[gd_scene load_steps=6 format=3 uid="uid://c2qgetjc3mfo3"] -[ext_resource type="Script" uid="uid://1w40lwv540il" path="res://addons/dialogic/Modules/Audio/settings_audio.gd" id="1_2iyyr"] +[ext_resource type="Script" uid="uid://cqyhm6offcitc" path="res://addons/dialogic/Modules/Audio/settings_audio.gd" id="1_2iyyr"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_o1ban"] +[ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3_bx557"] +[ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="4_xfyvc"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_m57ns"] +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="Audio" type="VBoxContainer"] offset_right = 121.0 offset_bottom = 58.0 script = ExtResource("1_2iyyr") -[node name="Label" type="Label" parent="."] -layout_mode = 2 -theme_type_variation = &"DialogicSettingsSection" -text = "Music Channels" - -[node name="HBoxContainer" type="HBoxContainer" parent="."] -layout_mode = 2 - -[node name="Label" type="Label" parent="HBoxContainer"] -layout_mode = 2 -text = "Max music channels" - -[node name="HintTooltip" parent="HBoxContainer" instance=ExtResource("2_o1ban")] -layout_mode = 2 -texture = null -hint_text = "Lowering this value may invalidate existing music events!" - -[node name="MusicChannelCount" type="SpinBox" parent="HBoxContainer"] -unique_name_in_owner = true -layout_mode = 2 -min_value = 1.0 -value = 1.0 - [node name="TypingSoundsTitle" type="Label" parent="."] layout_mode = 2 theme_type_variation = &"DialogicSettingsSection" @@ -45,10 +37,77 @@ text = "Audio Bus" [node name="HintTooltip" parent="HBoxContainer2" instance=ExtResource("2_o1ban")] layout_mode = 2 -tooltip_text = "Lowering this value may invalidate existing music events!" texture = null hint_text = "The default audio bus used by TypeSound nodes." [node name="TypeSoundBus" type="OptionButton" parent="HBoxContainer2"] unique_name_in_owner = true layout_mode = 2 + +[node name="HBoxContainer3" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Label" type="Label" parent="HBoxContainer3"] +layout_mode = 2 +theme_type_variation = &"DialogicSettingsSection" +text = "Audio Channel Defaults" + +[node name="HintTooltip" parent="HBoxContainer3" instance=ExtResource("2_o1ban")] +layout_mode = 2 +texture = null +hint_text = "Default settings for named audio channels." + +[node name="Panel" type="PanelContainer" parent="."] +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_m57ns") + +[node name="VBox" type="VBoxContainer" parent="Panel"] +layout_mode = 2 + +[node name="AudioChannelDefaults" type="GridContainer" parent="Panel/VBox"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +columns = 6 + +[node name="AudioChannelDefaultRow" type="HBoxContainer" parent="Panel/VBox"] +unique_name_in_owner = true +visible = false +layout_mode = 2 + +[node name="channel_name" parent="Panel/VBox/AudioChannelDefaultRow" instance=ExtResource("3_bx557")] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "Enter Channel Name" +mode = 3 + +[node name="volume" parent="Panel/VBox/AudioChannelDefaultRow" instance=ExtResource("4_xfyvc")] +layout_mode = 2 +mode = 2 +min = -80.0 +max = 6.0 +suffix = "dB" + +[node name="audio_bus" parent="Panel/VBox/AudioChannelDefaultRow" instance=ExtResource("3_bx557")] +layout_mode = 2 +placeholder_text = "Master" +mode = 2 + +[node name="fade_length" parent="Panel/VBox/AudioChannelDefaultRow" instance=ExtResource("4_xfyvc")] +layout_mode = 2 +mode = 0 +enforce_step = false +min = 0.0 + +[node name="loop" type="CheckButton" parent="Panel/VBox/AudioChannelDefaultRow"] +layout_mode = 2 + +[node name="delete" type="Button" parent="Panel/VBox/AudioChannelDefaultRow"] +layout_mode = 2 + +[node name="Add" type="Button" parent="Panel/VBox"] +layout_mode = 2 +size_flags_vertical = 4 +text = "Add channel" + +[connection signal="pressed" from="Panel/VBox/Add" to="." method="_on_add_channel_defaults_pressed"] diff --git a/addons/dialogic/Modules/Audio/subsystem_audio.gd b/addons/dialogic/Modules/Audio/subsystem_audio.gd index 18db7282..8749828c 100644 --- a/addons/dialogic/Modules/Audio/subsystem_audio.gd +++ b/addons/dialogic/Modules/Audio/subsystem_audio.gd @@ -1,101 +1,77 @@ extends DialogicSubsystem -## Subsystem for managing background music and one-shot sound effects. +## Subsystem for managing background audio and one-shot sound effects. ## ## This subsystem has many different helper methods for managing audio ## in your timeline. -## For instance, you can listen to music changes via [signal music_started]. +## For instance, you can listen to audio changes via [signal audio_started]. -## Whenever a new background music is started, this signal is emitted and +## Whenever a new audio event is started, this signal is emitted and ## contains a dictionary with the following keys: [br] ## [br] ## Key | Value Type | Value [br] ## ----------- | ------------- | ----- [br] ## `path` | [type String] | The path to the audio resource file. [br] -## `volume` | [type float] | The volume of the audio resource that will be set to the [member base_music_player]. [br] -## `audio_bus` | [type String] | The audio bus name that the [member base_music_player] will use. [br] +## `channel` | [type String] | The channel name to play the audio on. [br] +## `volume` | [type float] | The volume in `db` of the audio resource that will be set to the [AudioStreamPlayer]. [br] +## `audio_bus` | [type String] | The audio bus name that the [AudioStreamPlayer] will use. [br] ## `loop` | [type bool] | Whether the audio resource will loop or not once it finishes playing. [br] -## `channel` | [type int] | The channel ID to play the audio on. [br] -signal music_started(info: Dictionary) +signal audio_started(info: Dictionary) -## Whenever a new sound effect is set, this signal is emitted and contains a -## dictionary with the following keys: [br] -## [br] -## Key | Value Type | Value [br] -## ----------- | ------------- | ----- [br] -## `path` | [type String] | The path to the audio resource file. [br] -## `volume` | [type float] | The volume of the audio resource that will be set to [member base_sound_player]. [br] -## `audio_bus` | [type String] | The audio bus name that the [member base_sound_player] will use. [br] -## `loop` | [type bool] | Whether the audio resource will loop or not once it finishes playing. [br] -signal sound_started(info: Dictionary) - - -var max_channels: int: - set(value): - if max_channels != value: - max_channels = value - ProjectSettings.set_setting('dialogic/audio/max_channels', value) - ProjectSettings.save() - current_music_player.resize(value) - get: - return ProjectSettings.get_setting('dialogic/audio/max_channels', 4) - -## Audio player base duplicated to play background music. -## -## Background music is long audio. -var base_music_player := AudioStreamPlayer.new() -## Reference to the last used music player. -var current_music_player: Array[AudioStreamPlayer] = [] -## Audio player base, that will be duplicated to play sound effects. -## -## Sound effects are short audio. -var base_sound_player := AudioStreamPlayer.new() - +## Audio node for holding audio players +var audio_node := Node.new() +## Sound node for holding sound players +var one_shot_audio_node := Node.new() +## Dictionary with info of all current audio channels +var current_audio_channels: Dictionary = {} #region STATE #################################################################################################### ## Clears the state on this subsystem and stops all audio. -## -## If you want to stop sounds only, use [method stop_all_sounds]. func clear_game_state(_clear_flag := DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void: - for idx in max_channels: - update_music('', 0.0, '', 0.0, true, idx) - stop_all_sounds() + stop_all_channels() + stop_all_one_shot_sounds() ## Loads the state on this subsystem from the current state info. func load_game_state(load_flag:=LoadFlags.FULL_LOAD) -> void: if load_flag == LoadFlags.ONLY_DNODES: return - var info: Dictionary = dialogic.current_state_info.get("music", {}) - if not info.is_empty() and info.has('path'): - update_music(info.path, info.volume, info.audio_bus, 0, info.loop, 0) - else: - for channel_id in info.keys(): - if info[channel_id].is_empty() or info[channel_id].path.is_empty(): - update_music('', 0.0, '', 0.0, true, channel_id) - else: - update_music(info[channel_id].path, info[channel_id].volume, info[channel_id].audio_bus, 0, info[channel_id].loop, channel_id) + + # Pre Alpha 17 Converter + _convert_state_info() + + var info: Dictionary = dialogic.current_state_info.get("audio", {}) + + for channel_name in info.keys(): + if info[channel_name].path.is_empty(): + update_audio(channel_name) + else: + update_audio(channel_name, info[channel_name].path, info[channel_name].settings_overrides) ## Pauses playing audio. func pause() -> void: - for child in get_children(): + for child in audio_node.get_children(): + child.stream_paused = true + for child in one_shot_audio_node.get_children(): child.stream_paused = true ## Resumes playing audio. func resume() -> void: - for child in get_children(): + for child in audio_node.get_children(): + child.stream_paused = false + for child in one_shot_audio_node.get_children(): child.stream_paused = false func _on_dialogic_timeline_ended() -> void: if not dialogic.Styles.get_layout_node(): clear_game_state() - pass + #endregion @@ -105,115 +81,204 @@ func _on_dialogic_timeline_ended() -> void: func _ready() -> void: dialogic.timeline_ended.connect(_on_dialogic_timeline_ended) - base_music_player.name = "Music" - add_child(base_music_player) - - base_sound_player.name = "Sound" - add_child(base_sound_player) - - current_music_player.resize(max_channels) + audio_node.name = "Audio" + add_child(audio_node) + one_shot_audio_node.name = "OneShotAudios" + add_child(one_shot_audio_node) -## Updates the background music. Will fade out previous music. -func update_music(path := "", volume := 0.0, audio_bus := "", fade_time := 0.0, loop := true, channel_id := 0) -> void: - - if channel_id > max_channels: - printerr("\tChannel ID (%s) higher than Max Music Channels (%s)" % [channel_id, max_channels]) - dialogic.print_debug_moment() +## Plays the given file (or nothing) on the given channel. +## No channel given defaults to the "One-Shot SFX" channel, +## which does not save audio but can have multiple audios playing simultaneously. +func update_audio(channel_name:= "", path := "", settings_overrides := {}) -> void: + #volume := 0.0, audio_bus := "", fade_time := 0.0, loop := true, sync_channel := "") -> void: + if not is_channel_playing(channel_name) and path.is_empty(): return - if not dialogic.current_state_info.has('music'): - dialogic.current_state_info['music'] = {} + ## Determine audio settings + ## TODO use .merged after dropping 4.2 support + var audio_settings: Dictionary = DialogicUtil.get_audio_channel_defaults().get(channel_name, {}) + audio_settings.merge( + {"volume":0, "audio_bus":"", "fade_length":0.0, "loop":true, "sync_channel":""} + ) + audio_settings.merge(settings_overrides, true) - dialogic.current_state_info['music'][channel_id] = {'path':path, 'volume':volume, 'audio_bus':audio_bus, 'loop':loop, 'channel':channel_id} - music_started.emit(dialogic.current_state_info['music'][channel_id]) + ## Handle previous audio on channel + if is_channel_playing(channel_name): + var prev_audio_node: AudioStreamPlayer = current_audio_channels[channel_name] + prev_audio_node.name += "_Prev" + if audio_settings.fade_length > 0.0: + var fade_out_tween: Tween = create_tween() + fade_out_tween.tween_method( + interpolate_volume_linearly.bind(prev_audio_node), + db_to_linear(prev_audio_node.volume_db), + 0.0, + audio_settings.fade_length) + fade_out_tween.tween_callback(prev_audio_node.queue_free) - var fader: Tween = null - if is_instance_valid(current_music_player[channel_id]) and current_music_player[channel_id].playing or !path.is_empty(): - fader = create_tween() + else: + prev_audio_node.queue_free() - var prev_node: Node = null - if is_instance_valid(current_music_player[channel_id]) and current_music_player[channel_id].playing: - prev_node = current_music_player[channel_id] - fader.tween_method(interpolate_volume_linearly.bind(prev_node), db_to_linear(prev_node.volume_db),0.0,fade_time) + ## Set state + if not dialogic.current_state_info.has('audio'): + dialogic.current_state_info['audio'] = {} - if path: - current_music_player[channel_id] = base_music_player.duplicate() - add_child(current_music_player[channel_id]) - current_music_player[channel_id].stream = load(path) - current_music_player[channel_id].volume_db = volume - if audio_bus: - current_music_player[channel_id].bus = audio_bus - if not current_music_player[channel_id].stream is AudioStreamWAV: - if "loop" in current_music_player[channel_id].stream: - current_music_player[channel_id].stream.loop = loop - elif "loop_mode" in current_music_player[channel_id].stream: - if loop: - current_music_player[channel_id].stream.loop_mode = AudioStreamWAV.LOOP_FORWARD - else: - current_music_player[channel_id].stream.loop_mode = AudioStreamWAV.LOOP_DISABLED + if not path: + dialogic.current_state_info['audio'].erase(channel_name) + return - current_music_player[channel_id].play(0) - fader.parallel().tween_method(interpolate_volume_linearly.bind(current_music_player[channel_id]), 0.0, db_to_linear(volume),fade_time) + dialogic.current_state_info['audio'][channel_name] = {'path':path, 'settings_overrides':settings_overrides} + audio_started.emit(dialogic.current_state_info['audio'][channel_name]) - if prev_node: - fader.tween_callback(prev_node.queue_free) + var new_player := AudioStreamPlayer.new() + if channel_name: + new_player.name = channel_name.validate_node_name() + audio_node.add_child(new_player) + else: + new_player.name = "OneShotSFX" + one_shot_audio_node.add_child(new_player) + + var file := load(path) + if file == null: + printerr("[Dialogic] Audio file \"%s\" failed to load." % path) + return + + new_player.stream = load(path) + + ## Apply audio settings + + ## Volume & Fade + if audio_settings.fade_length > 0.0: + new_player.volume_db = linear_to_db(0.0) + var fade_in_tween := create_tween() + fade_in_tween.tween_method( + interpolate_volume_linearly.bind(new_player), + 0.0, + db_to_linear(audio_settings.volume), + audio_settings.fade_length) + + else: + new_player.volume_db = audio_settings.volume + + ## Audio Bus + new_player.bus = audio_settings.audio_bus + + ## Loop + if "loop" in new_player.stream: + new_player.stream.loop = audio_settings.loop + elif "loop_mode" in new_player.stream: + if audio_settings.loop: + new_player.stream.loop_mode = AudioStreamWAV.LOOP_FORWARD + new_player.stream.loop_begin = 0 + new_player.stream.loop_end = new_player.stream.mix_rate * new_player.stream.get_length() + else: + new_player.stream.loop_mode = AudioStreamWAV.LOOP_DISABLED + + ## Sync & start player + if audio_settings.sync_channel and is_channel_playing(audio_settings.sync_channel): + var play_position: float = current_audio_channels[audio_settings.sync_channel].get_playback_position() + new_player.play(play_position) + + # TODO Remove this once https://github.com/godotengine/godot/issues/18878 is fixed + if new_player.stream is AudioStreamWAV and new_player.stream.format == AudioStreamWAV.FORMAT_IMA_ADPCM: + printerr("[Dialogic] WAV files using Ima-ADPCM compression cannot be synced. Reimport the file using a different compression mode.") + dialogic.print_debug_moment() + else: + new_player.play() + + new_player.finished.connect(_on_audio_finished.bind(new_player, channel_name, path)) + + if channel_name: + current_audio_channels[channel_name] = new_player -## Whether music is playing. -func has_music(channel_id := 0) -> bool: - return !dialogic.current_state_info.get('music', {}).get(channel_id, {}).get('path', '').is_empty() +## Returns `true` if any audio is playing on the given [param channel_name]. +func is_channel_playing(channel_name: String) -> bool: + return (current_audio_channels.has(channel_name) + and is_instance_valid(current_audio_channels[channel_name]) + and current_audio_channels[channel_name].is_playing()) -## Plays a given sound file. -func play_sound(path: String, volume := 0.0, audio_bus := "", loop := false) -> void: - if base_sound_player != null and !path.is_empty(): - sound_started.emit({'path':path, 'volume':volume, 'audio_bus':audio_bus, 'loop':loop}) - - var new_sound_node := base_sound_player.duplicate() - new_sound_node.name += "Sound" - new_sound_node.stream = load(path) - - if "loop" in new_sound_node.stream: - new_sound_node.stream.loop = loop - elif "loop_mode" in new_sound_node.stream: - if loop: - new_sound_node.stream.loop_mode = AudioStreamWAV.LOOP_FORWARD - else: - new_sound_node.stream.loop_mode = AudioStreamWAV.LOOP_DISABLED - - new_sound_node.volume_db = volume - if audio_bus: - new_sound_node.bus = audio_bus - - add_child(new_sound_node) - new_sound_node.play() - new_sound_node.finished.connect(new_sound_node.queue_free) +## Stops audio on all channels. +func stop_all_channels(fade := 0.0) -> void: + for channel_name in current_audio_channels.keys(): + update_audio(channel_name, '', {"fade_length":fade}) -## Stops all audio. -func stop_all_sounds() -> void: - for node in get_children(): - if node == base_sound_player: - continue - if "Sound" in node.name: - node.queue_free() +### Stops all one-shot sounds. +func stop_all_one_shot_sounds() -> void: + for i in one_shot_audio_node.get_children(): + i.queue_free() ## Converts a linear loudness value to decibel and sets that volume to ## the given [param node]. -func interpolate_volume_linearly(value: float, node: Node) -> void: +func interpolate_volume_linearly(value: float, node: AudioStreamPlayer) -> void: node.volume_db = linear_to_db(value) ## Returns whether the currently playing audio resource is the same as this -## event's [param resource_path], for [param channel_id]. -func is_music_playing_resource(resource_path: String, channel_id := 0) -> bool: - var is_playing_resource: bool = (current_music_player.size() > channel_id - and is_instance_valid(current_music_player[channel_id]) - and current_music_player[channel_id].is_playing() - and current_music_player[channel_id].stream.resource_path == resource_path) +## event's [param resource_path], for [param channel_name]. +func is_channel_playing_file(file_path: String, channel_name: String) -> bool: + return (is_channel_playing(channel_name) + and current_audio_channels[channel_name].stream.resource_path == file_path) - return is_playing_resource + +## Returns `true` if any channel is playing. +func is_any_channel_playing() -> bool: + for channel in current_audio_channels: + if is_channel_playing(channel): + return true + return false + + +func _on_audio_finished(player: AudioStreamPlayer, channel_name: String, path: String) -> void: + if current_audio_channels.has(channel_name) and current_audio_channels[channel_name] == player: + current_audio_channels.erase(channel_name) + player.queue_free() + if dialogic.current_state_info.get('audio', {}).get(channel_name, {}).get('path', '') == path: + dialogic.current_state_info['audio'].erase(channel_name) + +#endregion + + +#region Pre Alpha 17 Conversion + +func _convert_state_info() -> void: + var info: Dictionary = dialogic.current_state_info.get("music", {}) + if info.is_empty(): + return + + var new_info := {} + if info.has("path"): + # Pre Alpha 16 Save Data Conversion + new_info['music'] = { + "path":info.path, + "settings_overrides": { + "volume":info.volume, + "audio_bus":info.audio_bus, + "loop":info.loop} + } + + else: + # Pre Alpha 17 Save Data Conversion + for channel_id in info.keys(): + if info[channel_id].is_empty(): + continue + + var channel_name = "music" + if channel_id > 0: + channel_name += str(channel_id + 1) + new_info[channel_name] = { + "path": info[channel_id].path, + "settings_overrides":{ + 'volume': info[channel_id].volume, + 'audio_bus': info[channel_id].audio_bus, + 'loop': info[channel_id].loop, + } + } + + dialogic.current_state_info['audio'] = new_info + dialogic.current_state_info.erase('music') #endregion diff --git a/addons/dialogic/Modules/Audio/subsystem_audio.gd.uid b/addons/dialogic/Modules/Audio/subsystem_audio.gd.uid index 527d72ff..5911d0a2 100644 --- a/addons/dialogic/Modules/Audio/subsystem_audio.gd.uid +++ b/addons/dialogic/Modules/Audio/subsystem_audio.gd.uid @@ -1 +1 @@ -uid://7pht2qiwn6xf +uid://do8vgqtp35d6w diff --git a/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd index ef3c5705..048a61f5 100644 --- a/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd +++ b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd @@ -19,6 +19,10 @@ func _update_background(argument:String, _time:float) -> void: if argument.begins_with('res://'): image_node.texture = load(argument) color_node.color = Color.TRANSPARENT + elif argument.begins_with('user://'): + var ext_image = Image.load_from_file(argument) + image_node.texture = ImageTexture.create_from_image(ext_image) + color_node.color = Color.TRANSPARENT elif argument.is_valid_html_color(): image_node.texture = null color_node.color = Color(argument, 1) diff --git a/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd.uid b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd.uid index 0daa5a45..9b60d171 100644 --- a/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd.uid +++ b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd.uid @@ -1 +1 @@ -uid://xwj105ltniqb +uid://ci7s5odxo7543 diff --git a/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.tscn b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.tscn index 20d73d52..44f6db85 100644 --- a/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.tscn +++ b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://cl6g6ymkhjven"] -[ext_resource type="Script" uid="uid://xwj105ltniqb" path="res://addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd" id="1_nkdrp"] +[ext_resource type="Script" uid="uid://ci7s5odxo7543" path="res://addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd" id="1_nkdrp"] [node name="DefaultBackground" type="Control"] layout_mode = 3 diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_down.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/push_down.gd.uid index adc255ee..a4edee4c 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/push_down.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_down.gd.uid @@ -1 +1 @@ -uid://dhqujsj8oqa7p +uid://blaaa6obvwknl diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd.uid index a989c866..9165bf26 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd.uid @@ -1 +1 @@ -uid://020a4llqpjlv +uid://6f7qewx7aga diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd.uid index 7909a6ac..52cdaccc 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd.uid @@ -1 +1 @@ -uid://b6f6s6rsoy2bw +uid://m3anyujei6ro diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd.uid index ac70c9ce..bf242dd4 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd.uid @@ -1 +1 @@ -uid://y8jr5c8l3e0a +uid://dnuvmtb036bi3 diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd.uid index 7b82d3a7..1a4ab9f5 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd.uid @@ -1 +1 @@ -uid://bjqdjfxjcvj7s +uid://bed16hbuh4atn diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd.uid index 9436b63c..d3e25d36 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd.uid @@ -1 +1 @@ -uid://d2ghxhx2432ro +uid://ctoc2p12vahcc diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd.uid index b2394b16..57d788ab 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd.uid @@ -1 +1 @@ -uid://c3bd283fo14yy +uid://dknape5pbyevn diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd.uid b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd.uid index d0a14a43..1e1859f3 100644 --- a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd.uid @@ -1 +1 @@ -uid://c63rtrqaasjey +uid://dwhod30peco4c diff --git a/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd b/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd index 3f4f1f01..ea5fc142 100644 --- a/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd +++ b/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd @@ -22,6 +22,7 @@ var time: float var bg_holder: DialogicNode_BackgroundHolder +@warning_ignore("unused_signal") # Used by scripts inheriting this class signal transition_finished diff --git a/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd.uid b/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd.uid index 5f371bd0..884c65b6 100644 --- a/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd.uid @@ -1 +1 @@ -uid://cn1cj14nuhrk6 +uid://cf47aj5eivati diff --git a/addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader.uid b/addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader.uid index cae4882a..1396f0c2 100644 --- a/addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader.uid +++ b/addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader.uid @@ -1 +1 @@ -uid://b2ybl1gbf0jej +uid://clabj6a02r7iv diff --git a/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader.uid b/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader.uid index 01a07bd6..469402ee 100644 --- a/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader.uid +++ b/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader.uid @@ -1 +1 @@ -uid://b7oxjroxkqi5q +uid://cuj1xsi7d7r5y diff --git a/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd.uid b/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd.uid index 2e26d629..f5e5125c 100644 --- a/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd.uid @@ -1 +1 @@ -uid://5kc4er8aj0s3 +uid://bue1pfm6eu7ww diff --git a/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd.uid b/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd.uid index 50ae8f1e..ee5c4e90 100644 --- a/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd.uid +++ b/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd.uid @@ -1 +1 @@ -uid://bd73gvgsuaxay +uid://bkj1kaqcq5208 diff --git a/addons/dialogic/Modules/Background/dialogic_background.gd b/addons/dialogic/Modules/Background/dialogic_background.gd index 10596333..9e84a91a 100644 --- a/addons/dialogic/Modules/Background/dialogic_background.gd +++ b/addons/dialogic/Modules/Background/dialogic_background.gd @@ -35,3 +35,4 @@ func _custom_fade_in(_time:float) -> bool: ## If you return false (by default) it will attempt to animate the "modulate" property. func _custom_fade_out(_time:float) -> bool: return false + diff --git a/addons/dialogic/Modules/Background/dialogic_background.gd.uid b/addons/dialogic/Modules/Background/dialogic_background.gd.uid index db9172d1..2518d6a8 100644 --- a/addons/dialogic/Modules/Background/dialogic_background.gd.uid +++ b/addons/dialogic/Modules/Background/dialogic_background.gd.uid @@ -1 +1 @@ -uid://5rp6alg02rv0 +uid://blsjcvm6gvd78 diff --git a/addons/dialogic/Modules/Background/event_background.gd b/addons/dialogic/Modules/Background/event_background.gd index 0380e698..f2c0c4c1 100644 --- a/addons/dialogic/Modules/Background/event_background.gd +++ b/addons/dialogic/Modules/Background/event_background.gd @@ -13,7 +13,11 @@ extends DialogicEvent var scene := "" ## The argument that is passed to the background scene. ## For the default scene it's the path to the image to show. -var argument := "" +var argument := "": + set(value): + if argument != value: + argument = value + ui_update_needed.emit() ## The time the fade animation will take. Leave at 0 for instant change. var fade: float = 0.0 ## Name of the transition to use. @@ -82,8 +86,8 @@ func get_shortcode() -> String: func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info - "scene" : {"property": "scene", "default": ""}, - "arg" : {"property": "argument", "default": ""}, + "scene" : {"property": "scene", "default": "", "ext_file":true}, + "arg" : {"property": "argument", "default": "", "ext_file":true}, "fade" : {"property": "fade", "default": 0}, "transition" : {"property": "transition", "default": "", "suggestions": get_transition_suggestions}, @@ -138,6 +142,10 @@ func build_event_editor() -> void: '_arg_type == ArgumentTypes.IMAGE or _scene_type == SceneTypes.DEFAULT') add_header_edit('argument', ValueType.SINGLELINE_TEXT, {}, '_arg_type == ArgumentTypes.CUSTOM') + add_body_edit("argument", ValueType.IMAGE_PREVIEW, {'left_text':'Preview:'}, + '(_arg_type == ArgumentTypes.IMAGE or _scene_type == SceneTypes.DEFAULT) and !argument.is_empty()') + add_body_line_break('(_arg_type == ArgumentTypes.IMAGE or _scene_type == SceneTypes.DEFAULT) and !argument.is_empty()') + add_body_edit("transition", ValueType.DYNAMIC_OPTIONS, {'left_text':'Transition:', 'empty_text':'Simple Fade', diff --git a/addons/dialogic/Modules/Background/event_background.gd.uid b/addons/dialogic/Modules/Background/event_background.gd.uid index ed746e4b..7ab0952e 100644 --- a/addons/dialogic/Modules/Background/event_background.gd.uid +++ b/addons/dialogic/Modules/Background/event_background.gd.uid @@ -1 +1 @@ -uid://ccksowqutf0np +uid://sioj2uwexnwx diff --git a/addons/dialogic/Modules/Background/index.gd.uid b/addons/dialogic/Modules/Background/index.gd.uid index 411b3b86..74d5f01f 100644 --- a/addons/dialogic/Modules/Background/index.gd.uid +++ b/addons/dialogic/Modules/Background/index.gd.uid @@ -1 +1 @@ -uid://cpl0roawa546c +uid://bj085abnvwkyh diff --git a/addons/dialogic/Modules/Background/node_background_holder.gd.uid b/addons/dialogic/Modules/Background/node_background_holder.gd.uid index 7b1325fc..a96ea967 100644 --- a/addons/dialogic/Modules/Background/node_background_holder.gd.uid +++ b/addons/dialogic/Modules/Background/node_background_holder.gd.uid @@ -1 +1 @@ -uid://bisx1nk1bjyjc +uid://oxcjhq2817c7 diff --git a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd index b8f8c4ca..e2dbec3c 100644 --- a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd +++ b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd @@ -99,6 +99,12 @@ func update_background(scene := "", argument := "", fade_time := 0.0, transition else: new_viewport = null + # if there is still a transition going on, stop it now + for node in get_children(): + if node is DialogicBackgroundTransition: + node.queue_free() + + var trans_script: Script = load(DialogicResourceUtil.guess_special_resource("BackgroundTransition", transition_path, {"path":default_transition}).path) var trans_node := Node.new() trans_node.set_script(trans_script) @@ -107,6 +113,7 @@ func update_background(scene := "", argument := "", fade_time := 0.0, transition trans_node.time = fade_time if old_viewport: + old_viewport.name = "OldBackground" trans_node.prev_scene = old_viewport.get_meta('node', null) trans_node.prev_texture = old_viewport.get_child(0).get_texture() old_viewport.get_meta('node')._custom_fade_out(fade_time) @@ -115,6 +122,7 @@ func update_background(scene := "", argument := "", fade_time := 0.0, transition old_viewport.get_child(0).render_target_update_mode = SubViewport.UPDATE_ALWAYS trans_node.transition_finished.connect(old_viewport.queue_free) if new_viewport: + new_viewport.name = "NewBackground" trans_node.next_scene = new_viewport.get_meta('node', null) trans_node.next_texture = new_viewport.get_child(0).get_texture() new_viewport.get_meta('node')._update_background(argument, fade_time) diff --git a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd.uid b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd.uid index bb064f72..12c344bc 100644 --- a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd.uid +++ b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd.uid @@ -1 +1 @@ -uid://b41q2p73ce000 +uid://5uwbnllu1kfv diff --git a/addons/dialogic/Modules/Call/event_call.gd b/addons/dialogic/Modules/Call/event_call.gd index 0f2c05dd..e00a63e6 100644 --- a/addons/dialogic/Modules/Call/event_call.gd +++ b/addons/dialogic/Modules/Call/event_call.gd @@ -139,53 +139,17 @@ func get_shortcode_parameters() -> Dictionary: func build_event_editor() -> void: add_header_edit('autoload_name', ValueType.DYNAMIC_OPTIONS, {'left_text':'On autoload', 'empty_text':'Autoload', - 'suggestions_func':get_autoload_suggestions, + 'suggestions_func': DialogicUtil.get_autoload_suggestions, 'editor_icon':["Node", "EditorIcons"]}) add_header_edit('method', ValueType.DYNAMIC_OPTIONS, {'left_text':'call', 'empty_text':'Method', - 'suggestions_func':get_method_suggestions, + 'suggestions_func': get_method_suggestions, 'editor_icon':["Callable", "EditorIcons"]}, 'autoload_name') add_body_edit('arguments', ValueType.ARRAY, {'left_text':'Arguments:'}, 'not autoload_name.is_empty() and not method.is_empty()') - -func get_autoload_suggestions(filter:String="") -> Dictionary: - var suggestions := {} - - for prop in ProjectSettings.get_property_list(): - if prop.name.begins_with('autoload/'): - var autoload: String = prop.name.trim_prefix('autoload/') - suggestions[autoload] = {'value': autoload, 'tooltip':autoload, 'editor_icon': ["Node", "EditorIcons"]} - if filter.begins_with(autoload): - suggestions[filter] = {'value': filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]} - return suggestions - - -func get_method_suggestions(filter:String="", temp_autoload:String = "") -> Dictionary: - var suggestions := {} - - var script: Script - if temp_autoload and ProjectSettings.has_setting('autoload/'+temp_autoload): - script = load(ProjectSettings.get_setting('autoload/'+temp_autoload).trim_prefix('*')) - - elif autoload_name and ProjectSettings.has_setting('autoload/'+autoload_name): - var loaded_autoload := load(ProjectSettings.get_setting('autoload/'+autoload_name).trim_prefix('*')) - - if loaded_autoload is PackedScene: - var packed_scene: PackedScene = loaded_autoload - script = packed_scene.instantiate().get_script() - - else: - script = loaded_autoload - - if script: - for script_method in script.get_script_method_list(): - if script_method.name.begins_with('@') or script_method.name.begins_with('_'): - continue - suggestions[script_method.name] = {'value': script_method.name, 'tooltip':script_method.name, 'editor_icon': ["Callable", "EditorIcons"]} - if !filter.is_empty(): - suggestions[filter] = {'value': filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]} - return suggestions +func get_method_suggestions(filter:="") -> Dictionary: + return DialogicUtil.get_autoload_method_suggestions(filter, autoload_name) func update_argument_info() -> void: @@ -236,13 +200,21 @@ func check_arguments_and_update_warning() -> void: ####################### CODE COMPLETION ######################################## ################################################################################ -func _get_code_completion(_CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void: +func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void: + var autoloads := DialogicUtil.get_autoload_suggestions() + var line_until_caret: String = CodeCompletionHelper.get_line_untill_caret(line) + if line.count(' ') == 1 and not '.' in line: - for i in get_autoload_suggestions(): + for i in autoloads: TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i+'.', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.3), TextNode.get_theme_icon("Node", "EditorIcons")) - elif symbol == '.' and not '(' in line: - for i in get_method_suggestions('', line.get_slice('.', 0).trim_prefix('do ')): - TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i+'(', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.3), TextNode.get_theme_icon("Callable", "EditorIcons")) + + elif (line_until_caret.ends_with(".") or symbol == "."): + var some_autoload := line_until_caret.split(" ")[-1].split(".")[0] + if some_autoload in autoloads: + var methods := DialogicUtil.get_autoload_method_suggestions("", some_autoload) + for i in methods.keys(): + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i+'(', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.3), TextNode.get_theme_icon("MemberMethod", "EditorIcons")) + func _get_start_code_completion(_CodeCompletionHelper:Node, TextNode:TextEdit) -> void: diff --git a/addons/dialogic/Modules/Call/event_call.gd.uid b/addons/dialogic/Modules/Call/event_call.gd.uid index 0eb73c82..551ff02d 100644 --- a/addons/dialogic/Modules/Call/event_call.gd.uid +++ b/addons/dialogic/Modules/Call/event_call.gd.uid @@ -1 +1 @@ -uid://cx3saaa1iyvre +uid://uhicnbvlk57s diff --git a/addons/dialogic/Modules/Call/index.gd.uid b/addons/dialogic/Modules/Call/index.gd.uid index c8023239..3f50c78d 100644 --- a/addons/dialogic/Modules/Call/index.gd.uid +++ b/addons/dialogic/Modules/Call/index.gd.uid @@ -1 +1 @@ -uid://huqsmyyipv62 +uid://bthb47untmgoo diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd.uid index 23eed09e..2068624a 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd.uid @@ -1 +1 @@ -uid://fgk8hal7nugw +uid://qruxugkg6y8w diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd.uid index 9174f4a8..d397af94 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd.uid @@ -1 +1 @@ -uid://cb4xhtqnifsrf +uid://rfgxn0xtuen3 diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd.uid index 6fa41cf7..c98a48a0 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd.uid @@ -1 +1 @@ -uid://ckqo0ncifb40s +uid://bcs0jdci4mngb diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd.uid index 74d8c30d..7f7960d2 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd.uid @@ -1 +1 @@ -uid://cobrccabo638p +uid://fekbbs23rj4m diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd.uid index 70021916..547dbbf8 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd.uid @@ -1 +1 @@ -uid://df6ex8wqhaxix +uid://dwnfbyjtc2anb diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd.uid index a9c183a1..9893d4d4 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd.uid @@ -1 +1 @@ -uid://dttqyslijg03r +uid://8ro2ayitmjcp diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd.uid index 25fdad06..b6c4e80e 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd.uid @@ -1 +1 @@ -uid://clwy8nsaw1phe +uid://cn4yveni7rdr7 diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd b/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd index de445fc9..c71cfdeb 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd @@ -11,7 +11,7 @@ func animate() -> void: tween.tween_method(bound_multitween, Vector2(), Vector2(-1,0)*strength, time*0.1) tween.tween_method(bound_multitween, Vector2(), Vector2(1, 0)*strength, time*0.1) tween.tween_method(bound_multitween, Vector2(), Vector2(-1,0)*strength, time*0.1) - tween.tween_method(bound_multitween, Vector2(), Vector2(1, 0)*strength, time*0.2) + tween.tween_method(bound_multitween, Vector2(), Vector2(0, 0)*strength, time*0.2) tween.finished.connect(emit_signal.bind('finished_once')) func _get_named_variations() -> Dictionary: diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd.uid index 23f9b7ad..df5b2b44 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd.uid @@ -1 +1 @@ -uid://jp8nhoprsqdh +uid://3tqien23j50t diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd.uid index 007917a8..9db5c830 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd.uid @@ -1 +1 @@ -uid://j0si5xem8teo +uid://lur75holg34f diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd index af012481..d59d34f1 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd @@ -4,16 +4,17 @@ func animate() -> void: var tween := (node.create_tween() as Tween) tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK) - var target_position := base_position.y - var start_position: float = -node.get_viewport().size.y + var end_position_y: float = base_position.y + node.get_parent().global_position.y + var start_position: float = -get_node_size().y + get_node_origin().y if is_reversed: - target_position = -node.get_viewport().size.y + tween.set_ease(Tween.EASE_IN) + end_position_y = -get_node_size().y + get_node_origin().y start_position = base_position.y node.position.y = start_position - tween.tween_property(node, 'position:y', target_position, time) + tween.tween_property(node, 'global_position:y', end_position_y, time) await tween.finished finished_once.emit() diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd.uid index f8b72141..ba6b76cb 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd.uid @@ -1 +1 @@ -uid://b3cvsvayqobsk +uid://d0a5sgbr5imas diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd index f0d7df38..ed9987fc 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd @@ -5,15 +5,16 @@ func animate() -> void: var tween := (node.create_tween() as Tween) tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK) - var end_position_x: float = base_position.x + var end_position_x: float = base_position.x + node.get_parent().global_position.x if is_reversed: - end_position_x = -node.get_viewport().size.x / 2 + end_position_x = - get_node_size().x + get_node_origin().x + tween.set_ease(Tween.EASE_IN) else: - node.position.x = -node.get_viewport().size.x / 5 + node.global_position.x = -get_node_size().x + get_node_origin().x - tween.tween_property(node, 'position:x', end_position_x, time) + tween.tween_property(node, 'global_position:x', end_position_x, time) await tween.finished finished_once.emit() @@ -21,6 +22,6 @@ func animate() -> void: func _get_named_variations() -> Dictionary: return { - "slide in left": {"reversed": false, "type": AnimationType.IN}, - "slide out right": {"reversed": true, "type": AnimationType.OUT}, + "slide from left": {"reversed": false, "type": AnimationType.IN}, + "slide to left": {"reversed": true, "type": AnimationType.OUT}, } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd.uid index 37cb1683..adda345b 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd.uid @@ -1 +1 @@ -uid://bs763k4612fht +uid://c8il877nw3xqw diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd index 3e4a5a4b..b248156f 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd @@ -4,24 +4,21 @@ func animate() -> void: var tween := (node.create_tween() as Tween) tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK) - var viewport_x: float = node.get_viewport().size.x - - var start_position_x: float = viewport_x + viewport_x / 5 - var end_position_x := base_position.x + var viewport_x: float = get_viewport_size().x + var end_position_x : float = base_position.x + node.get_parent().global_position.x if is_reversed: - start_position_x = base_position.x - end_position_x = viewport_x + node.get_viewport().size.x / 5 - - - node.position.x = start_position_x - tween.tween_property(node, 'position:x', end_position_x, time) + end_position_x = viewport_x + get_node_origin().x + tween.set_ease(Tween.EASE_IN) + else: + node.global_position.x = viewport_x + get_node_origin().x + tween.tween_property(node, 'global_position:x', end_position_x, time) tween.finished.connect(emit_signal.bind('finished_once')) func _get_named_variations() -> Dictionary: return { - "slide in right": {"reversed": false, "type": AnimationType.IN}, - "slide out left": {"reversed": true, "type": AnimationType.OUT}, + "slide from right": {"reversed": false, "type": AnimationType.IN}, + "slide to right": {"reversed": true, "type": AnimationType.OUT}, } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd.uid index 6d72ec25..fb8adfad 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd.uid @@ -1 +1 @@ -uid://cswjq5jlqrn3g +uid://daj7cqft5hnxg diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd index fcb1e337..7e89a064 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd @@ -4,15 +4,16 @@ func animate() -> void: var tween := (node.create_tween() as Tween) tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK) - var start_position_y: float = node.get_viewport().size.y * 2 - var end_position_y := base_position.y + var start_position_y: float = get_viewport_size().y + get_node_origin().y + var end_position_y: float = base_position.y + node.get_parent().global_position.y if is_reversed: - start_position_y = base_position.y - end_position_y = node.get_viewport().size.y * 2 + tween.set_ease(Tween.EASE_IN) + start_position_y = end_position_y + end_position_y = get_viewport_size().y + get_node_origin().y - node.position.y = start_position_y - tween.tween_property(node, 'position:y', end_position_y, time) + node.global_position.y = start_position_y + tween.tween_property(node, 'global_position:y', end_position_y, time) await tween.finished finished_once.emit() diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd.uid index fd41f871..e63f6f5d 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd.uid @@ -1 +1 @@ -uid://b43hklc4t83ic +uid://bj5ak53i7s8ux diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd.uid index 5a99328f..21553de2 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd.uid @@ -1 +1 @@ -uid://b4iouoy0lsmg3 +uid://crv1pn60clrvx diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd.uid index 876ddc69..154ef7d9 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd.uid @@ -1 +1 @@ -uid://guke2u7jqwkt +uid://cjwdb0jkjrcxe diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd.uid b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd.uid index 81556bd6..05fe8149 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd.uid +++ b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd.uid @@ -1 +1 @@ -uid://bb2xwtcht84yq +uid://bl5sdpj631mtt diff --git a/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd.uid b/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd.uid index cf8591c0..9ddf9120 100644 --- a/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd.uid +++ b/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd.uid @@ -1 +1 @@ -uid://b7mq20hi3v6m8 +uid://j2k3uogf5715 diff --git a/addons/dialogic/Modules/Character/class_dialogic_animation.gd b/addons/dialogic/Modules/Character/class_dialogic_animation.gd index 9792ab23..3c0d8ef5 100644 --- a/addons/dialogic/Modules/Character/class_dialogic_animation.gd +++ b/addons/dialogic/Modules/Character/class_dialogic_animation.gd @@ -75,3 +75,28 @@ func get_modulation_property() -> String: return "self_modulate" else: return "modulate" + + +## Tries to return the size of the node to be animated. +## For portraits this uses the portrait containers size. +## This is useful if your animation depends on the size of the node. +func get_node_size() -> Vector2: + if not node: + return Vector2() + if node.get_parent() is DialogicNode_PortraitContainer: + return node.get_parent().size + if "size" in node: + return node.size * node.scale + return node.get_viewport().size + + +func get_node_origin() -> Vector2: + if not node: + return Vector2() + if node.get_parent() is DialogicNode_PortraitContainer: + return node.get_parent()._get_origin_position() + return Vector2() + + +func get_viewport_size() -> Vector2: + return node.get_viewport().get_visible_rect().size diff --git a/addons/dialogic/Modules/Character/class_dialogic_animation.gd.uid b/addons/dialogic/Modules/Character/class_dialogic_animation.gd.uid index a6b40ed0..e8ff8b48 100644 --- a/addons/dialogic/Modules/Character/class_dialogic_animation.gd.uid +++ b/addons/dialogic/Modules/Character/class_dialogic_animation.gd.uid @@ -1 +1 @@ -uid://blu2it3fdcxr8 +uid://0hsjlurlblou diff --git a/addons/dialogic/Modules/Character/default_portrait.gd.uid b/addons/dialogic/Modules/Character/default_portrait.gd.uid index f9376359..c4e680f2 100644 --- a/addons/dialogic/Modules/Character/default_portrait.gd.uid +++ b/addons/dialogic/Modules/Character/default_portrait.gd.uid @@ -1 +1 @@ -uid://c3a0wujs6kev3 +uid://cork0heubbx7f diff --git a/addons/dialogic/Modules/Character/default_portrait.tscn b/addons/dialogic/Modules/Character/default_portrait.tscn index 0d94d7a1..cd3d57d3 100644 --- a/addons/dialogic/Modules/Character/default_portrait.tscn +++ b/addons/dialogic/Modules/Character/default_portrait.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://b32paf0ll6um8"] -[ext_resource type="Script" uid="uid://c3a0wujs6kev3" path="res://addons/dialogic/Modules/Character/default_portrait.gd" id="1_wn77n"] +[ext_resource type="Script" uid="uid://cork0heubbx7f" path="res://addons/dialogic/Modules/Character/default_portrait.gd" id="1_wn77n"] [node name="DefaultPortrait" type="Node2D"] script = ExtResource("1_wn77n") diff --git a/addons/dialogic/Modules/Character/dialogic_portrait.gd.uid b/addons/dialogic/Modules/Character/dialogic_portrait.gd.uid index 2aa2af7f..54280916 100644 --- a/addons/dialogic/Modules/Character/dialogic_portrait.gd.uid +++ b/addons/dialogic/Modules/Character/dialogic_portrait.gd.uid @@ -1 +1 @@ -uid://du4fl3cae5jml +uid://djbg8sc0q67ow diff --git a/addons/dialogic/Modules/Character/event_character.gd b/addons/dialogic/Modules/Character/event_character.gd index 923be74e..41256e36 100644 --- a/addons/dialogic/Modules/Character/event_character.gd +++ b/addons/dialogic/Modules/Character/event_character.gd @@ -82,14 +82,14 @@ var character_identifier: String: if character_identifier == '--All--': return '--All--' if character: - var identifier := DialogicResourceUtil.get_unique_identifier(character.resource_path) + var identifier := character.get_identifier() if not identifier.is_empty(): return identifier return character_identifier set(value): character_identifier = value character = DialogicResourceUtil.get_character_resource(value) - if character and not character.portraits.has(portrait): + if (not character) or (character and not character.portraits.has(portrait)): portrait = "" ui_update_needed.emit() @@ -154,10 +154,10 @@ func _execute() -> void: finish() return - dialogic.Portraits.change_character_extradata(character, extra_data) - if set_portrait: - dialogic.Portraits.change_character_portrait(character, portrait, fade_animation, fade_length) + await dialogic.Portraits.change_character_portrait(character, portrait, fade_animation, fade_length) + + dialogic.Portraits.change_character_extradata(character, extra_data) if set_mirrored: dialogic.Portraits.change_character_mirror(character, mirrored) @@ -225,7 +225,7 @@ func to_text() -> String: if action == Actions.LEAVE and character_identifier == '--All--': result_string += "--All--" elif character: - var name := DialogicResourceUtil.get_unique_identifier(character.resource_path) + var name := character.get_character_name() if name.count(" ") > 0: name = '"' + name + '"' @@ -302,7 +302,7 @@ func get_shortcode_parameters() -> Dictionary: {'value':Actions.JOIN}, 'Leave':{'value':Actions.LEAVE}, 'Update':{'value':Actions.UPDATE}}}, - "character" : {"property": "character_identifier", "default": "", "custom_stored":true,}, + "character" : {"property": "character_identifier", "default": "", "custom_stored":true, "ext_file":true}, "portrait" : {"property": "portrait", "default": "", "custom_stored":true,}, "transform" : {"property": "transform", "default": "center", "custom_stored":true,}, @@ -478,8 +478,8 @@ func get_fade_suggestions(search_text:String='') -> Dictionary: func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void: var line_until_caret: String = CodeCompletionHelper.get_line_untill_caret(line) - if symbol == ' ' and line_until_caret.count(' ') == 1: - CodeCompletionHelper.suggest_characters(TextNode, CodeEdit.KIND_MEMBER) + if symbol == ' ' and line_until_caret.count(" ") == 1: + CodeCompletionHelper.suggest_characters(TextNode, CodeEdit.KIND_MEMBER, self) if line.begins_with('leave'): TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'All', '--All-- ', event_color, TextNode.get_theme_icon("GuiEllipsis", "EditorIcons")) @@ -487,10 +487,11 @@ func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:Str var completion_character := regex.search(line).get_string('name') CodeCompletionHelper.suggest_portraits(TextNode, completion_character) - elif not '[' in line_until_caret and symbol == ' ': + elif not '[' in line_until_caret and symbol == ' ' and line_until_caret.split(" ", false).size() > 1: if not line.begins_with("leave"): - for position in get_position_suggestions(): - TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, position, position+' ', TextNode.syntax_highlighter.normal_color) + if not line_until_caret.split(" ", false)[-1] in get_position_suggestions(): + for position in get_position_suggestions(): + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, position, position+' ', TextNode.syntax_highlighter.normal_color) # Shortcode Part if '[' in line_until_caret: @@ -504,8 +505,10 @@ func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:Str if line.begins_with('update'): suggest_parameter("repeat", line, TextNode) if line.begins_with("update"): - for param in ["move_time", "move_trans", "move_ease"]: + for param in ["move_time", "move_trans", "move_ease", "fade"]: suggest_parameter(param, line, TextNode) + if "fade=" in line_until_caret: + suggest_parameter("fade_length", line, TextNode) if not line.begins_with('leave'): for param in ["mirrored", "z_index", "extra_data"]: suggest_parameter(param, line, TextNode) diff --git a/addons/dialogic/Modules/Character/event_character.gd.uid b/addons/dialogic/Modules/Character/event_character.gd.uid index 0066d857..cedaeb71 100644 --- a/addons/dialogic/Modules/Character/event_character.gd.uid +++ b/addons/dialogic/Modules/Character/event_character.gd.uid @@ -1 +1 @@ -uid://duu0jekiba20n +uid://b88y7tdin2uu5 diff --git a/addons/dialogic/Modules/Character/index.gd.uid b/addons/dialogic/Modules/Character/index.gd.uid index 4faa6f23..0f8ab239 100644 --- a/addons/dialogic/Modules/Character/index.gd.uid +++ b/addons/dialogic/Modules/Character/index.gd.uid @@ -1 +1 @@ -uid://drl3os1svksa2 +uid://4tu24b2ex257 diff --git a/addons/dialogic/Modules/Character/node_portrait_container.gd.uid b/addons/dialogic/Modules/Character/node_portrait_container.gd.uid index 52ff35bd..5e01837d 100644 --- a/addons/dialogic/Modules/Character/node_portrait_container.gd.uid +++ b/addons/dialogic/Modules/Character/node_portrait_container.gd.uid @@ -1 +1 @@ -uid://cfcx0of1aekhk +uid://d0ptqnbudhkyj diff --git a/addons/dialogic/Modules/Character/preview_character.tres b/addons/dialogic/Modules/Character/preview_character.tres index 2cd9bf5b..5ec5b32e 100644 --- a/addons/dialogic/Modules/Character/preview_character.tres +++ b/addons/dialogic/Modules/Character/preview_character.tres @@ -1,6 +1,6 @@ [gd_resource type="Resource" script_class="DialogicCharacter" load_steps=2 format=3 uid="uid://dykf1j17ct5mo"] -[ext_resource type="Script" uid="uid://w3vtr3asq7b3" path="res://addons/dialogic/Resources/character.gd" id="1_qsljv"] +[ext_resource type="Script" uid="uid://don4ds5f38byo" path="res://addons/dialogic/Resources/character.gd" id="1_qsljv"] [resource] script = ExtResource("1_qsljv") diff --git a/addons/dialogic/Modules/Character/settings_portraits.gd b/addons/dialogic/Modules/Character/settings_portraits.gd index 57686a4e..51b45ac2 100644 --- a/addons/dialogic/Modules/Character/settings_portraits.gd +++ b/addons/dialogic/Modules/Character/settings_portraits.gd @@ -17,11 +17,11 @@ const ANIMATION_CROSSFADE_DEFAULT_LENGTH_KEY:= 'dialogic/animations/cross_fade_d func _ready(): - %JoinDefault.get_suggestions_func = get_join_animation_suggestions + %JoinDefault.suggestions_func = get_join_animation_suggestions %JoinDefault.mode = 1 - %LeaveDefault.get_suggestions_func = get_leave_animation_suggestions + %LeaveDefault.suggestions_func = get_leave_animation_suggestions %LeaveDefault.mode = 1 - %CrossFadeDefault.get_suggestions_func = get_crossfade_animation_suggestions + %CrossFadeDefault.suggestions_func = get_crossfade_animation_suggestions %CrossFadeDefault.mode = 1 %PositionSuggestions.text_submitted.connect(save_setting.bind(POSITION_SUGGESTION_KEY)) diff --git a/addons/dialogic/Modules/Character/settings_portraits.gd.uid b/addons/dialogic/Modules/Character/settings_portraits.gd.uid index 84bbbbb9..4feebaec 100644 --- a/addons/dialogic/Modules/Character/settings_portraits.gd.uid +++ b/addons/dialogic/Modules/Character/settings_portraits.gd.uid @@ -1 +1 @@ -uid://0hdug2yw0j7u +uid://c3hdycwp0hrdm diff --git a/addons/dialogic/Modules/Character/settings_portraits.tscn b/addons/dialogic/Modules/Character/settings_portraits.tscn index d10ff21f..9969701a 100644 --- a/addons/dialogic/Modules/Character/settings_portraits.tscn +++ b/addons/dialogic/Modules/Character/settings_portraits.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://cp463rpri5j8a"] -[ext_resource type="Script" uid="uid://0hdug2yw0j7u" path="res://addons/dialogic/Modules/Character/settings_portraits.gd" id="2"] +[ext_resource type="Script" uid="uid://c3hdycwp0hrdm" path="res://addons/dialogic/Modules/Character/settings_portraits.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_dce78"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="3_m06d8"] @@ -19,8 +19,7 @@ size_flags_stretch_ratio = 0.5 [node name="Title2" type="Label" parent="PositionsTitle"] layout_mode = 2 theme_type_variation = &"DialogicSettingsSection" -text = "Position Suggestions -" +text = "Position Suggestions" [node name="HintTooltip" parent="PositionsTitle" instance=ExtResource("2_dce78")] layout_mode = 2 @@ -40,8 +39,7 @@ size_flags_stretch_ratio = 0.5 [node name="Title2" type="Label" parent="DefaultSceneTitle"] layout_mode = 2 theme_type_variation = &"DialogicSettingsSection" -text = "Default Portrait Scene -" +text = "Default Portrait Scene" [node name="HintTooltip" parent="DefaultSceneTitle" instance=ExtResource("2_dce78")] layout_mode = 2 @@ -70,8 +68,7 @@ size_flags_stretch_ratio = 0.5 [node name="Title2" type="Label" parent="Animations2"] layout_mode = 2 theme_type_variation = &"DialogicSettingsSection" -text = "Default Animations -" +text = "Default Animations" [node name="HintTooltip" parent="Animations2" instance=ExtResource("2_dce78")] layout_mode = 2 diff --git a/addons/dialogic/Modules/Character/subsystem_containers.gd b/addons/dialogic/Modules/Character/subsystem_containers.gd index 1e1e8502..239e423d 100644 --- a/addons/dialogic/Modules/Character/subsystem_containers.gd +++ b/addons/dialogic/Modules/Character/subsystem_containers.gd @@ -182,7 +182,8 @@ func resize_container(container: DialogicNode_PortraitContainer, rect_size: Vari tween.finished.connect(save_position_container.bind(container)) else: container.position = container.position + relative_position_change - container.size = final_rect_resize + #container.size = final_rect_resize + container.set_deferred("size", final_rect_resize) save_position_container(container) position_changed.emit({&'change':'resized', &'container_node':container}) diff --git a/addons/dialogic/Modules/Character/subsystem_containers.gd.uid b/addons/dialogic/Modules/Character/subsystem_containers.gd.uid index 62366854..98412dba 100644 --- a/addons/dialogic/Modules/Character/subsystem_containers.gd.uid +++ b/addons/dialogic/Modules/Character/subsystem_containers.gd.uid @@ -1 +1 @@ -uid://c8ug08wx4f1d0 +uid://c5dk5rh4vj8rd diff --git a/addons/dialogic/Modules/Character/subsystem_portraits.gd b/addons/dialogic/Modules/Character/subsystem_portraits.gd index 9bed6983..c87468de 100644 --- a/addons/dialogic/Modules/Character/subsystem_portraits.gd +++ b/addons/dialogic/Modules/Character/subsystem_portraits.gd @@ -19,8 +19,8 @@ var default_portrait_scene: PackedScene = load(get_script().resource_path.get_ba #################################################################################################### func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void: - for character in dialogic.current_state_info.get('portraits', {}).keys(): - remove_character(load(character)) + for character_identifier in dialogic.current_state_info.get('portraits', {}).keys(): + remove_character(DialogicResourceUtil.get_character_resource(character_identifier)) dialogic.current_state_info['portraits'] = {} @@ -31,21 +31,24 @@ func load_game_state(_load_flag:=LoadFlags.FULL_LOAD) -> void: # Load Position Portraits var portraits_info: Dictionary = dialogic.current_state_info.portraits.duplicate() dialogic.current_state_info.portraits = {} - for character_path in portraits_info: - var character_info: Dictionary = portraits_info[character_path] - var character: DialogicCharacter = load(character_path) - var container := dialogic.PortraitContainers.load_position_container(character.get_character_name()) - add_character(character, container, character_info.portrait, character_info.position_id) - change_character_mirror(character, character_info.get('custom_mirror', false)) - change_character_z_index(character, character_info.get('z_index', 0)) - change_character_extradata(character, character_info.get('extra_data', "")) + for character_identifier in portraits_info: + var character_info: Dictionary = portraits_info[character_identifier] + var character: DialogicCharacter = DialogicResourceUtil.get_character_resource(character_identifier) + if character: + var container := dialogic.PortraitContainers.load_position_container(character.get_character_name()) + add_character(character, container, character_info.portrait, character_info.position_id) + change_character_mirror(character, character_info.get('custom_mirror', false)) + change_character_z_index(character, character_info.get('z_index', 0)) + change_character_extradata(character, character_info.get('extra_data', "")) + else: + push_error('[Dialogic] Failed to load character "' + str(character_identifier) + '".') # Load Speaker Portrait - var speaker: Variant = dialogic.current_state_info.get('speaker', "") + var speaker: Variant = dialogic.current_state_info.get("speaker", "") if speaker: - dialogic.current_state_info['speaker'] = "" - change_speaker(load(speaker)) - dialogic.current_state_info['speaker'] = speaker + dialogic.current_state_info["speaker"] = "" + change_speaker(DialogicResourceUtil.get_character_resource(speaker)) + dialogic.current_state_info["speaker"] = speaker func pause() -> void: @@ -117,6 +120,7 @@ func _change_portrait(character_node: Node2D, portrait: String, fade_animation:= if (not previous_portrait == null and previous_portrait.get_meta('scene', '') == scene_path and # Also check if the scene supports changing to the given portrait. + previous_portrait.has_method('_should_do_portrait_update') and previous_portrait._should_do_portrait_update(character, portrait)): portrait_node = previous_portrait info['same_scene'] = true @@ -124,12 +128,21 @@ func _change_portrait(character_node: Node2D, portrait: String, fade_animation:= else: if ResourceLoader.exists(scene_path): - var packed_scene: PackedScene = load(scene_path) + ResourceLoader.load_threaded_request(scene_path) - if packed_scene: - portrait_node = packed_scene.instantiate() + var load_status := ResourceLoader.load_threaded_get_status(scene_path) + while load_status == ResourceLoader.THREAD_LOAD_IN_PROGRESS: + await get_tree().process_frame + load_status = ResourceLoader.load_threaded_get_status(scene_path) + + if load_status == ResourceLoader.THREAD_LOAD_LOADED: + var packed_scene: PackedScene = ResourceLoader.load_threaded_get(scene_path) + if packed_scene: + portrait_node = packed_scene.instantiate() + else: + push_error('[Dialogic] Portrait node "' + str(scene_path) + '" for character [' + character.display_name + '] could not be loaded. Your portrait might not show up on the screen. Confirm the path is correct.') else: - push_error('[Dialogic] Portrait node "' + str(scene_path) + '" for character [' + character.display_name + '] could not be loaded. Your portrait might not show up on the screen. Confirm the path is correct.') + push_error('[Dialogic] Failed to load portrait node "' + str(scene_path) + '" for character [' + character.display_name + '].') if !portrait_node: portrait_node = default_portrait_scene.instantiate() @@ -167,20 +180,26 @@ func _change_portrait(character_node: Node2D, portrait: String, fade_animation:= ## Unless @force is false, this will take into consideration the character mirror, ## portrait mirror and portrait position mirror settings. func _change_portrait_mirror(character_node: Node2D, mirrored := false, force := false) -> void: - var latest_portrait := character_node.get_child(-1) + var latest_portrait := character_node.get_child(-1) if character_node.get_child_count() > 0 else null - if latest_portrait.has_method('_set_mirror'): + if latest_portrait and latest_portrait.has_method("_set_mirror"): var character: DialogicCharacter = character_node.get_meta('character') var current_portrait_info := character.get_portrait_info(character_node.get_meta('portrait')) latest_portrait._set_mirror(force or (mirrored != character.mirror != character_node.get_parent().mirrored != current_portrait_info.get('mirror', false))) func _change_portrait_extradata(character_node: Node2D, extra_data := "") -> void: - var latest_portrait := character_node.get_child(-1) + if not is_instance_valid(character_node): + push_error("[Dialogic] Invalid character node provided.") + return - if latest_portrait.has_method('_set_extra_data'): - latest_portrait._set_extra_data(extra_data) + if character_node.get_child_count() > 0: + var latest_portrait := character_node.get_child(-1) + if latest_portrait and latest_portrait.has_method("_set_extra_data"): + latest_portrait._set_extra_data(extra_data) + else: + push_warning("[Dialogic] No portrait found for character node: " + character_node.name) func _update_character_transform(character_node:Node, time := 0.0) -> void: for child in character_node.get_children(): @@ -287,7 +306,7 @@ func _change_portrait_z_index(character_node: Node, z_index:int, update_zindex:= ## fully visible yet. func get_character_portrait(character: DialogicCharacter) -> DialogicPortrait: if is_character_joined(character): - var portrait_node: DialogicPortrait = dialogic.current_state_info['portraits'][character.resource_path].node.get_child(-1) + var portrait_node: DialogicPortrait = dialogic.current_state_info['portraits'][character.get_identifier()].node.get_child(-1) return portrait_node return null @@ -342,7 +361,7 @@ func get_valid_portrait(character:DialogicCharacter, portrait:String) -> String: if not portrait in character.portraits: if not portrait.is_empty(): - printerr('[Dialogic] Tried to use invalid portrait "', portrait, '" on character "', DialogicResourceUtil.get_unique_identifier(character.resource_path), '". Using default portrait instead.') + printerr('[Dialogic] Tried to use invalid portrait "', portrait, '" on character "', character.get_character_name(), '". Using default portrait instead.') dialogic.print_debug_moment() portrait = character.default_portrait @@ -379,18 +398,18 @@ func join_character(character:DialogicCharacter, portrait:String, position_id:S return var container := dialogic.PortraitContainers.add_container(character.get_character_name()) - var character_node := add_character(character, container, portrait, position_id) + var character_node := await add_character(character, container, portrait, position_id) if character_node == null: return null - dialogic.current_state_info['portraits'][character.resource_path] = {'portrait':portrait, 'node':character_node, 'position_id':position_id, 'custom_mirror':mirrored} + dialogic.current_state_info['portraits'][character.get_identifier()] = {'portrait':portrait, 'node':character_node, 'position_id':position_id, 'custom_mirror':mirrored} _change_portrait_mirror(character_node, mirrored) _change_portrait_extradata(character_node, extra_data) _change_portrait_z_index(character_node, z_index) var info := {'character':character} - info.merge(dialogic.current_state_info['portraits'][character.resource_path]) + info.merge(dialogic.current_state_info['portraits'][character.get_identifier()]) character_joined.emit(info) if animation_name.is_empty(): @@ -410,9 +429,9 @@ func join_character(character:DialogicCharacter, portrait:String, position_id:S return character_node -func add_character(character:DialogicCharacter, container: DialogicNode_PortraitContainer, portrait:String, position_id:String) -> Node: +func add_character(character: DialogicCharacter, container: DialogicNode_PortraitContainer, portrait: String, position_id: String) -> Node: if is_character_joined(character): - printerr('[DialogicError] Cannot add a already joined character. If this is intended call _create_character_node manually.') + printerr('[DialogicError] Cannot add an already joined character. If this is intended, call _create_character_node manually.') return null portrait = get_valid_portrait(character, portrait) @@ -430,36 +449,35 @@ func add_character(character:DialogicCharacter, container: DialogicNode_Portrait printerr('[Dialogic] Failed to join character to position ', position_id, ". Could not find position container.") return null - - dialogic.current_state_info['portraits'][character.resource_path] = {'portrait':portrait, 'node':character_node, 'position_id':position_id} + dialogic.current_state_info['portraits'][character.get_identifier()] = {'portrait': portrait, 'node': character_node, 'position_id': position_id} _move_character(character_node, position_id) - _change_portrait(character_node, portrait) + await _change_portrait(character_node, portrait) return character_node ## Changes the portrait of a character. Only works with joined characters. -func change_character_portrait(character: DialogicCharacter, portrait: String, fade_animation:="DEFAULT", fade_length := -1.0) -> void: +func change_character_portrait(character: DialogicCharacter, portrait: String, fade_animation:="", fade_length := -1.0) -> void: if not is_character_joined(character): return portrait = get_valid_portrait(character, portrait) - if dialogic.current_state_info.portraits[character.resource_path].portrait == portrait: + if dialogic.current_state_info.portraits[character.get_identifier()].portrait == portrait: return - if fade_animation == "DEFAULT": + if fade_animation == "": fade_animation = ProjectSettings.get_setting('dialogic/animations/cross_fade_default', "Fade Cross") fade_length = ProjectSettings.get_setting('dialogic/animations/cross_fade_default_length', 0.5) fade_animation = DialogicPortraitAnimationUtil.guess_animation(fade_animation, DialogicPortraitAnimationUtil.AnimationType.CROSSFADE) - var info := _change_portrait(dialogic.current_state_info.portraits[character.resource_path].node, portrait, fade_animation, fade_length) - dialogic.current_state_info.portraits[character.resource_path].portrait = info.portrait + var info := await _change_portrait(dialogic.current_state_info.portraits[character.get_identifier()].node, portrait, fade_animation, fade_length) + dialogic.current_state_info.portraits[character.get_identifier()].portrait = info.portrait _change_portrait_mirror( - dialogic.current_state_info.portraits[character.resource_path].node, - dialogic.current_state_info.portraits[character.resource_path].get('custom_mirror', false) + dialogic.current_state_info.portraits[character.get_identifier()].node, + dialogic.current_state_info.portraits[character.get_identifier()].get('custom_mirror', false) ) character_portrait_changed.emit(info) @@ -469,8 +487,8 @@ func change_character_mirror(character:DialogicCharacter, mirrored:= false, forc if !is_character_joined(character): return - _change_portrait_mirror(dialogic.current_state_info.portraits[character.resource_path].node, mirrored, force) - dialogic.current_state_info.portraits[character.resource_path]['custom_mirror'] = mirrored + _change_portrait_mirror(dialogic.current_state_info.portraits[character.get_identifier()].node, mirrored, force) + dialogic.current_state_info.portraits[character.get_identifier()]['custom_mirror'] = mirrored ## Changes the z_index of a character. Only works with joined characters @@ -478,17 +496,17 @@ func change_character_z_index(character:DialogicCharacter, z_index:int, update_z if !is_character_joined(character): return - _change_portrait_z_index(dialogic.current_state_info.portraits[character.resource_path].node, z_index, update_zindex) + _change_portrait_z_index(dialogic.current_state_info.portraits[character.get_identifier()].node, z_index, update_zindex) if update_zindex: - dialogic.current_state_info.portraits[character.resource_path]['z_index'] = z_index + dialogic.current_state_info.portraits[character.get_identifier()]['z_index'] = z_index ## Changes the extra data on the given character. Only works with joined characters func change_character_extradata(character:DialogicCharacter, extra_data:="") -> void: if !is_character_joined(character): return - _change_portrait_extradata(dialogic.current_state_info.portraits[character.resource_path].node, extra_data) - dialogic.current_state_info.portraits[character.resource_path]['extra_data'] = extra_data + _change_portrait_extradata(dialogic.current_state_info.portraits[character.get_identifier()].node, extra_data) + dialogic.current_state_info.portraits[character.get_identifier()]['extra_data'] = extra_data ## Starts the given animation on the given character. Only works with joined characters @@ -498,7 +516,7 @@ func animate_character(character: DialogicCharacter, animation_path: String, len animation_path = DialogicPortraitAnimationUtil.guess_animation(animation_path) - var character_node: Node = dialogic.current_state_info.portraits[character.resource_path].node + var character_node: Node = dialogic.current_state_info.portraits[character.get_identifier()].node return _animate_node(character_node, animation_path, length, repeats, is_reversed) @@ -508,11 +526,11 @@ func move_character(character:DialogicCharacter, position_id:String, time:= 0.0, if !is_character_joined(character): return - if dialogic.current_state_info.portraits[character.resource_path].position_id == position_id: + if dialogic.current_state_info.portraits[character.get_identifier()].position_id == position_id: return - _move_character(dialogic.current_state_info.portraits[character.resource_path].node, position_id, time, easing, trans) - dialogic.current_state_info.portraits[character.resource_path].position_id = position_id + _move_character(dialogic.current_state_info.portraits[character.get_identifier()].node, position_id, time, easing, trans) + dialogic.current_state_info.portraits[character.get_identifier()].position_id = position_id character_moved.emit({'character':character, 'position_id':position_id, 'time':time}) @@ -554,8 +572,8 @@ func leave_all_characters(animation_name:="", animation_length:=0.0, animation_w ## Return `null` if the [param character] is not part of the scene. func get_character_node(character: DialogicCharacter) -> Node: if is_character_joined(character): - if is_instance_valid(dialogic.current_state_info['portraits'][character.resource_path].node): - return dialogic.current_state_info['portraits'][character.resource_path].node + if is_instance_valid(dialogic.current_state_info['portraits'][character.get_identifier()].node): + return dialogic.current_state_info['portraits'][character.get_identifier()].node return null @@ -571,19 +589,12 @@ func remove_character(character: DialogicCharacter) -> void: character_node.queue_free() character_left.emit({'character': character}) - dialogic.current_state_info['portraits'].erase(character.resource_path) - - -func get_current_character() -> DialogicCharacter: - if dialogic.current_state_info.get('speaker', null): - return load(dialogic.current_state_info.speaker) - return null - + dialogic.current_state_info['portraits'].erase(character.get_identifier()) ## Returns true if the given character is currently joined. func is_character_joined(character: DialogicCharacter) -> bool: - if character == null or not character.resource_path in dialogic.current_state_info['portraits']: + if character == null or not character.get_identifier() in dialogic.current_state_info['portraits']: return false return true @@ -593,8 +604,8 @@ func is_character_joined(character: DialogicCharacter) -> bool: func get_joined_characters() -> Array[DialogicCharacter]: var chars: Array[DialogicCharacter] = [] - for char_path: String in dialogic.current_state_info.get('portraits', {}).keys(): - chars.append(load(char_path)) + for char_identifier: String in dialogic.current_state_info.get('portraits', {}).keys(): + chars.append(DialogicResourceUtil.get_character_resource(char_identifier)) return chars @@ -604,7 +615,7 @@ func get_joined_characters() -> Array[DialogicCharacter]: ## Only joined is included (and false) for not joined characters func get_character_info(character:DialogicCharacter) -> Dictionary: if is_character_joined(character): - var info: Dictionary = dialogic.current_state_info['portraits'][character.resource_path] + var info: Dictionary = dialogic.current_state_info['portraits'][character.get_identifier()] info['joined'] = true return info else: @@ -629,7 +640,8 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: if leave_animation and leave_animation_length: var animate_out := _animate_node(character_node, leave_animation, leave_animation_length, 1, true) - animate_out.finished.connect(character_node.queue_free) + await animate_out.finished + character_node.queue_free() else: character_node.get_parent().remove_child(character_node) character_node.queue_free() @@ -655,10 +667,10 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: fade_animation = DialogicPortraitAnimationUtil.guess_animation(fade_animation, DialogicPortraitAnimationUtil.AnimationType.CROSSFADE) - if container.portrait_prefix+portrait in speaker.portraits: - portrait = container.portrait_prefix+portrait + if container.portrait_prefix + portrait in speaker.portraits: + portrait = container.portrait_prefix + portrait - _change_portrait(character_node, portrait, fade_animation, fade_length) + await _change_portrait(character_node, portrait, fade_animation, fade_length) # if the character has no portraits _change_portrait won't actually add a child node if character_node.get_child_count() == 0: @@ -671,26 +683,28 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: character_node.hide() if not container.is_visible_in_tree(): await get_tree().process_frame + + # There is chance that the style changed (due to a speaker style) and thus the character node is gone now. + # In that case, just give up. + if not is_instance_valid(character_node): + return character_node.show() var join_animation: String = ProjectSettings.get_setting('dialogic/animations/join_default', "Fade In Up") join_animation = DialogicPortraitAnimationUtil.guess_animation(join_animation, DialogicPortraitAnimationUtil.AnimationType.IN) var join_animation_length := _get_join_default_length() if join_animation and join_animation_length: - _animate_node(character_node, join_animation, join_animation_length) + await _animate_node(character_node, join_animation, join_animation_length).finished _change_portrait_mirror(character_node) - if speaker: - if speaker.resource_path != dialogic.current_state_info['speaker']: - if dialogic.current_state_info['speaker'] and is_character_joined(load(dialogic.current_state_info['speaker'])): - dialogic.current_state_info['portraits'][dialogic.current_state_info['speaker']].node.get_child(-1)._unhighlight() + var prev_speaker: DialogicCharacter = dialogic.Text.get_current_speaker() + if speaker != prev_speaker: + if is_character_joined(prev_speaker): + dialogic.current_state_info["portraits"][prev_speaker.get_identifier()].node.get_child(-1)._unhighlight() - if speaker and is_character_joined(speaker): - dialogic.current_state_info['portraits'][speaker.resource_path].node.get_child(-1)._highlight() - - elif dialogic.current_state_info['speaker'] and is_character_joined(load(dialogic.current_state_info['speaker'])): - dialogic.current_state_info['portraits'][dialogic.current_state_info['speaker']].node.get_child(-1)._unhighlight() + if is_character_joined(speaker): + dialogic.current_state_info["portraits"][speaker.get_identifier()].node.get_child(-1)._highlight() #endregion @@ -701,14 +715,15 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: ## Called from the [portrait=something] text effect. func text_effect_portrait(_text_node:Control, _skipped:bool, argument:String) -> void: if argument: - if dialogic.current_state_info.get('speaker', null): - change_character_portrait(load(dialogic.current_state_info.speaker), argument) - change_speaker(load(dialogic.current_state_info.speaker), argument) + var current_speaker := dialogic.Text.get_current_speaker() + if current_speaker: + change_character_portrait(current_speaker, argument) + change_speaker(current_speaker, argument) ## Called from the [extra_data=something] text effect. func text_effect_extradata(_text_node:Control, _skipped:bool, argument:String) -> void: if argument: - if dialogic.current_state_info.get('speaker', null): - change_character_extradata(load(dialogic.current_state_info.speaker), argument) + if dialogic.Text.get_current_speaker(): + change_character_extradata(dialogic.Text.get_current_speaker(), argument) #endregion diff --git a/addons/dialogic/Modules/Character/subsystem_portraits.gd.uid b/addons/dialogic/Modules/Character/subsystem_portraits.gd.uid index 3326cb1e..7f2b29c5 100644 --- a/addons/dialogic/Modules/Character/subsystem_portraits.gd.uid +++ b/addons/dialogic/Modules/Character/subsystem_portraits.gd.uid @@ -1 +1 @@ -uid://c1531cn2fwxf6 +uid://fyhfur7bpp4v diff --git a/addons/dialogic/Modules/Choice/event_choice.gd b/addons/dialogic/Modules/Choice/event_choice.gd index 7e4364c3..cbe15e36 100644 --- a/addons/dialogic/Modules/Choice/event_choice.gd +++ b/addons/dialogic/Modules/Choice/event_choice.gd @@ -37,6 +37,10 @@ func _execute() -> void: dialogic.Choices.show_current_question(false) dialogic.current_state = dialogic.States.AWAITING_CHOICE + +func _is_branch_starter() -> bool: + return dialogic.Choices.is_question(dialogic.current_timeline_events.find(self)) + #endregion @@ -53,7 +57,7 @@ func _init() -> void: # return a control node that should show on the END BRANCH node -func get_end_branch_control() -> Control: +func _get_end_branch_control() -> Control: return load(get_script().resource_path.get_base_dir().path_join('ui_choice_end.tscn')).instantiate() #endregion diff --git a/addons/dialogic/Modules/Choice/event_choice.gd.uid b/addons/dialogic/Modules/Choice/event_choice.gd.uid index 784493ed..5ea1d4c6 100644 --- a/addons/dialogic/Modules/Choice/event_choice.gd.uid +++ b/addons/dialogic/Modules/Choice/event_choice.gd.uid @@ -1 +1 @@ -uid://evfcdip3607c +uid://cltu1tykths0n diff --git a/addons/dialogic/Modules/Choice/index.gd.uid b/addons/dialogic/Modules/Choice/index.gd.uid index f5afed9f..ea404830 100644 --- a/addons/dialogic/Modules/Choice/index.gd.uid +++ b/addons/dialogic/Modules/Choice/index.gd.uid @@ -1 +1 @@ -uid://cpp7qjji6ck8p +uid://bo0dqybasbqd diff --git a/addons/dialogic/Modules/Choice/node_button_sound.gd.uid b/addons/dialogic/Modules/Choice/node_button_sound.gd.uid index f0090b6e..e40f8b20 100644 --- a/addons/dialogic/Modules/Choice/node_button_sound.gd.uid +++ b/addons/dialogic/Modules/Choice/node_button_sound.gd.uid @@ -1 +1 @@ -uid://bijk2aslmrx2r +uid://b1stj4ljd2vo7 diff --git a/addons/dialogic/Modules/Choice/node_choice_button.gd b/addons/dialogic/Modules/Choice/node_choice_button.gd index aa0d431b..724f5924 100644 --- a/addons/dialogic/Modules/Choice/node_choice_button.gd +++ b/addons/dialogic/Modules/Choice/node_choice_button.gd @@ -1,15 +1,28 @@ class_name DialogicNode_ChoiceButton extends Button -## The button allows the player to make a choice in the Dialogic system. +## This button allows the player to make a choice in the Dialogic system. ## -## This class is used in the Choice Layer. [br] -## You may change the [member text_node] to any [class Node] that has a -## `text` property. [br] -## If you don't set the [member text_node], the text will be set on this -## button instead. -## -## Using a different node may allow using rich text effects; they are -## not supported on buttons at this point. +## When a choice is reached Dialogic will automatically show ChoiceButtons +## and call their [code]_load_info()[/code] method which will display the choices. +## You will need to ensure that enough choice buttons are available in the tree +## to display all choices.[br] +## +## [br] +## You can extend this node and implement some custom logic by overwriting +## the [code]_load_info(info:Dictionary)[/code] method. [br] +## [br] +## If you need RichText support, consider adding a RichTextLabel child and setting it as the [member text_node].[br] +## +## [br] +## DialogicChoiceButtons will grab the focus when hovered to avoid a confusing +## focus style being present for players who use the mouse.[br] +## To avoid the opposite situation, when the focus is changed by the player +## and a different button is still hovered the mouse pointer will be moved +## to the now focused button as well. + + +## Emitted when the choice is selected. Unless overridden, this is when the button or its shortcut is pressed. +signal choice_selected ## Used to identify what choices to put on. If you leave it at -1, choices will be distributed automatically. @@ -21,7 +34,9 @@ extends Button @export var sound_hover: AudioStream ## Can be set to play this sound when focused. Requires a sibling DialogicNode_ButtonSound node. @export var sound_focus: AudioStream -## If set, the text will be set on this node's `text` property instead. + +## If set, the text will be set on this node's `text` property instead. +## This can be used to have a custom text rendering child, like a RichTextLabel. @export var text_node: Node @@ -29,8 +44,34 @@ func _ready() -> void: add_to_group('dialogic_choice_button') shortcut_in_tooltip = false hide() + + # For players who use a mouse to make choices, mouse hover should grab focus. + # Otherwise the auto-focused button will always show a highlighted color when + # the mouse cursor is hovering on another button. + if not mouse_entered.is_connected(grab_focus): + mouse_entered.connect(grab_focus) + if not focus_entered.is_connected(_on_choice_button_focus_entred): + focus_entered.connect(_on_choice_button_focus_entred.bind(self)) +## Custom choice buttons can override this for specialized behavior when the choice button is pressed. +func _pressed(): + choice_selected.emit() + + +## Custom choice buttons can override this if their behavior should change +## based on event data. If the custom choice button does not override +## visibility, disabled-ness, nor the choice text, consider +## calling super(choice_info) at the start of the override. +## +## The choice_info Dictionary has the following keys: +## - event_index: The index of the choice event in the timeline. +## - button_index: The relative index of the choice (starts from 1). +## - visible: If the choice should be visible. +## - disabled: If the choice should be selectable. +## - text: The text of the choice. +## - visited_before: If the choice has been selected before. Only available is the History submodule is enabled. +## - *: Information from the event's additional info. func _load_info(choice_info: Dictionary) -> void: set_choice_text(choice_info.text) visible = choice_info.visible @@ -43,3 +84,37 @@ func set_choice_text(new_text: String) -> void: text_node.text = new_text else: text = new_text + + +## This method moves the mouse to the focused choice when the focus changes +## while a choice button was hovered. [br] +## For players who use many devices (mouse/keyboard/gamepad, etc) at the same time to make choices, +## a grabing-focus triggered by keyboard/gamepad should also change the mouse cursor's +## position otherwise two buttons will have highlighted color(one highlighted button +## triggered by mouse hover and another highlighted button triggered by other devices' choice). +func _on_choice_button_focus_entred(focused_button: Button): + var global_mouse_pos = get_global_mouse_position() + var focused_button_rect = focused_button.get_global_rect() + if focused_button_rect.has_point(global_mouse_pos): + return + # Only change mouse curor position when an unfocused button' rect has the cursor. + for node in get_tree().get_nodes_in_group('dialogic_choice_button'): + if node is Button: + if node != focused_button and node.get_global_rect().has_point(global_mouse_pos): + # We prefer to change only mouse_position.y or mouse_position.x to warp the + # mouse to the focused button's rect to achieve the best visual effect. + var modify_y_pos = Vector2(global_mouse_pos.x, focused_button.get_global_rect().get_center().y) + if focused_button_rect.has_point(modify_y_pos): + get_viewport().warp_mouse(modify_y_pos) + return + + var modify_x_pos = Vector2(focused_button.get_global_rect().get_center().x, global_mouse_pos.y) + if focused_button_rect.has_point(modify_x_pos): + get_viewport().warp_mouse(modify_x_pos) + return + + # Maybe the buttons are not aligned as vertically or horizontlly. + # Or perhaps the length difference between the two buttons is quite large. + # So we just make the cursor hover on the center of the focused button. + get_viewport().warp_mouse(focused_button.get_global_rect().get_center()) + return diff --git a/addons/dialogic/Modules/Choice/node_choice_button.gd.uid b/addons/dialogic/Modules/Choice/node_choice_button.gd.uid index d2c21607..dbb12efa 100644 --- a/addons/dialogic/Modules/Choice/node_choice_button.gd.uid +++ b/addons/dialogic/Modules/Choice/node_choice_button.gd.uid @@ -1 +1 @@ -uid://bcirqrep7rvr4 +uid://bldt7xlfum7ov diff --git a/addons/dialogic/Modules/Choice/settings_choices.gd.uid b/addons/dialogic/Modules/Choice/settings_choices.gd.uid index bc4ec66b..70d99249 100644 --- a/addons/dialogic/Modules/Choice/settings_choices.gd.uid +++ b/addons/dialogic/Modules/Choice/settings_choices.gd.uid @@ -1 +1 @@ -uid://cyog6egbjdhg0 +uid://dbbbq1hcbhmi2 diff --git a/addons/dialogic/Modules/Choice/settings_choices.tscn b/addons/dialogic/Modules/Choice/settings_choices.tscn index 24ca8943..195c5f8b 100644 --- a/addons/dialogic/Modules/Choice/settings_choices.tscn +++ b/addons/dialogic/Modules/Choice/settings_choices.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://uarvgnbrcltm"] -[ext_resource type="Script" uid="uid://cyog6egbjdhg0" path="res://addons/dialogic/Modules/Choice/settings_choices.gd" id="2"] +[ext_resource type="Script" uid="uid://dbbbq1hcbhmi2" path="res://addons/dialogic/Modules/Choice/settings_choices.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_nxutt"] [sub_resource type="Image" id="Image_xvnnc"] diff --git a/addons/dialogic/Modules/Choice/subsystem_choices.gd b/addons/dialogic/Modules/Choice/subsystem_choices.gd index aa7caa9a..cbafed6a 100644 --- a/addons/dialogic/Modules/Choice/subsystem_choices.gd +++ b/addons/dialogic/Modules/Choice/subsystem_choices.gd @@ -70,8 +70,8 @@ func post_install() -> void: func hide_all_choices() -> void: for node in get_tree().get_nodes_in_group('dialogic_choice_button'): node.hide() - if node.is_connected('button_up', _on_choice_selected): - node.disconnect('button_up', _on_choice_selected) + if node.choice_selected.is_connected(_on_choice_selected): + node.choice_selected.disconnect(_on_choice_selected) ## Collects information on all the choices of the current question. @@ -120,7 +120,7 @@ func get_current_question_info() -> Dictionary: if not hide: button_idx += 1 - choice_info.text = dialogic.Text.parse_text(choice_info.text, true, true, false, true, false, false) + choice_info.text = dialogic.Text.parse_text(choice_info.text, 1) choice_info.merge(choice_event.extra_data) @@ -128,6 +128,7 @@ func get_current_question_info() -> Dictionary: choice_info['visited_before'] = dialogic.History.has_event_been_visited(choice_index) question_info['choices'].append(choice_info) + last_question_info['choices'].append(choice_info['text']) return question_info @@ -155,7 +156,7 @@ func show_current_question(instant:=true) -> void: var question_info := get_current_question_info() for choice in question_info.choices: - var node: DialogicNode_ChoiceButton = get_choice_button_node(choice.button_index) + var node: DialogicNode_ChoiceButton = get_choice_button(choice.button_index) if not node: missing_button = true @@ -181,9 +182,9 @@ func show_current_question(instant:=true) -> void: shortcut.events.append(input_key) node.shortcut = shortcut - if node.pressed.is_connected(_on_choice_selected): - node.pressed.disconnect(_on_choice_selected) - node.pressed.connect(_on_choice_selected.bind(choice)) + if node.choice_selected.is_connected(_on_choice_selected): + node.choice_selected.disconnect(_on_choice_selected) + node.choice_selected.connect(_on_choice_selected.bind(choice)) _choice_blocker.start(block_delay) question_shown.emit(question_info) @@ -192,8 +193,24 @@ func show_current_question(instant:=true) -> void: printerr("[Dialogic] The layout you are using doesn't have enough Choice Buttons for the choices you are trying to display.") +func focus_choice(button_index:int) -> void: + var node: DialogicNode_ChoiceButton = get_choice_button(button_index) + if node: + node.grab_focus() -func get_choice_button_node(button_index:int) -> DialogicNode_ChoiceButton: + +func select_choice(button_index:int) -> void: + var node: DialogicNode_ChoiceButton = get_choice_button(button_index) + if node: + node.choice_selected.emit() + + +func select_focused_choice() -> void: + if get_viewport().gui_get_focus_owner() is DialogicNode_ChoiceButton: + (get_viewport().gui_get_focus_owner() as DialogicNode_ChoiceButton).choice_selected.emit() + + +func get_choice_button(button_index:int) -> DialogicNode_ChoiceButton: var idx := 1 for node: DialogicNode_ChoiceButton in get_tree().get_nodes_in_group('dialogic_choice_button'): if !node.get_parent().is_visible_in_tree(): @@ -227,33 +244,29 @@ func _on_choice_selected(choice_info := {}) -> void: dialogic.handle_event(choice_info.event_index + 1) - +## Returns the indexes of the choice events related to the current question. func get_current_choice_indexes() -> Array: var choices := [] - var evt_idx := dialogic.current_event_idx - var ignore := 0 + var index := dialogic.current_event_idx-1 while true: - if evt_idx >= len(dialogic.current_timeline_events): + index += 1 + if index >= len(dialogic.current_timeline_events): + break + + var event: DialogicEvent = dialogic.current_timeline_events[index] + if event is DialogicChoiceEvent: + choices.append(index) + index = event.get_end_branch_index() + else: break - if dialogic.current_timeline_events[evt_idx] is DialogicChoiceEvent: - if ignore == 0: - choices.append(evt_idx) - ignore += 1 - elif dialogic.current_timeline_events[evt_idx].can_contain_events: - ignore += 1 - else: - if ignore == 0: - break - if dialogic.current_timeline_events[evt_idx] is DialogicEndBranchEvent: - ignore -= 1 - evt_idx += 1 return choices +## Forward the dialogic action to the focused button func _on_dialogic_action() -> void: - if get_viewport().gui_get_focus_owner() is DialogicNode_ChoiceButton and use_input_action and not dialogic.Inputs.input_was_mouse_input: - get_viewport().gui_get_focus_owner().pressed.emit() + if use_input_action and not dialogic.Inputs.input_was_mouse_input: + select_focused_choice() #endregion @@ -262,20 +275,27 @@ func _on_dialogic_action() -> void: #region HELPERS #################################################################################################### +## Returns `true` if the given index is a text event before a question or the first choice event of a question. func is_question(index:int) -> bool: - if dialogic.current_timeline_events[index] is DialogicTextEvent: + var event: DialogicEvent = dialogic.current_timeline_events[index] + if event is DialogicTextEvent: if len(dialogic.current_timeline_events)-1 != index: - if dialogic.current_timeline_events[index+1] is DialogicChoiceEvent: + var next_event: DialogicEvent = dialogic.current_timeline_events[index+1] + if next_event is DialogicChoiceEvent: return true - if dialogic.current_timeline_events[index] is DialogicChoiceEvent: - if index != 0 and dialogic.current_timeline_events[index-1] is DialogicEndBranchEvent: - if dialogic.current_timeline_events[dialogic.current_timeline_events[index-1].find_opening_index(index-1)] is DialogicChoiceEvent: - return false - else: - return true + if event is DialogicChoiceEvent: + if index == 0: + return true + var prev_event: DialogicEvent = dialogic.current_timeline_events[index-1] + if not prev_event is DialogicEndBranchEvent: + return true + var prev_event_opener: DialogicEvent = dialogic.current_timeline_events[prev_event.get_opening_index()] + if prev_event_opener is DialogicChoiceEvent: + return false else: return true + return false #endregion diff --git a/addons/dialogic/Modules/Choice/subsystem_choices.gd.uid b/addons/dialogic/Modules/Choice/subsystem_choices.gd.uid index 225fd4fa..1f069887 100644 --- a/addons/dialogic/Modules/Choice/subsystem_choices.gd.uid +++ b/addons/dialogic/Modules/Choice/subsystem_choices.gd.uid @@ -1 +1 @@ -uid://70q8j1ji8wm +uid://cewv4d3aw0kj3 diff --git a/addons/dialogic/Modules/Choice/ui_choice_end.gd.uid b/addons/dialogic/Modules/Choice/ui_choice_end.gd.uid index 8d2d97ee..04c99dfa 100644 --- a/addons/dialogic/Modules/Choice/ui_choice_end.gd.uid +++ b/addons/dialogic/Modules/Choice/ui_choice_end.gd.uid @@ -1 +1 @@ -uid://yt5h64x4n67s +uid://d28x7h2ufh3dd diff --git a/addons/dialogic/Modules/Choice/ui_choice_end.tscn b/addons/dialogic/Modules/Choice/ui_choice_end.tscn index 1d59861b..835a65c6 100644 --- a/addons/dialogic/Modules/Choice/ui_choice_end.tscn +++ b/addons/dialogic/Modules/Choice/ui_choice_end.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://cn0wbb2lk0s22"] -[ext_resource type="Script" uid="uid://yt5h64x4n67s" path="res://addons/dialogic/Modules/Choice/ui_choice_end.gd" id="1_7qd85"] +[ext_resource type="Script" uid="uid://d28x7h2ufh3dd" path="res://addons/dialogic/Modules/Choice/ui_choice_end.gd" id="1_7qd85"] [node name="Choice_End" type="HBoxContainer"] anchors_preset = 15 diff --git a/addons/dialogic/Modules/Clear/event_clear.gd b/addons/dialogic/Modules/Clear/event_clear.gd index d1fa8480..9b1b3d7a 100644 --- a/addons/dialogic/Modules/Clear/event_clear.gd +++ b/addons/dialogic/Modules/Clear/event_clear.gd @@ -26,9 +26,9 @@ func _execute() -> void: var time_per_event: float = dialogic.Inputs.auto_skip.time_per_event final_time = min(time, time_per_event) - if clear_textbox and dialogic.has_subsystem("Text"): + if clear_textbox and dialogic.has_subsystem("Text") and dialogic.Text.is_textbox_visible(): dialogic.Text.update_dialog_text('') - dialogic.Text.hide_textbox() + dialogic.Text.hide_textbox(final_time == 0) dialogic.current_state = dialogic.States.IDLE if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout @@ -44,10 +44,10 @@ func _execute() -> void: if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout if clear_music and dialogic.has_subsystem('Audio'): - for channel_id in dialogic.Audio.max_channels: - if dialogic.Audio.has_music(channel_id): - dialogic.Audio.update_music('', 0.0, "", final_time, channel_id) - if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout + dialogic.Audio.stop_all_one_shot_sounds() + if dialogic.Audio.is_any_channel_playing(): + dialogic.Audio.stop_all_channels(final_time) + if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout if clear_style and dialogic.has_subsystem('Styles'): dialogic.Styles.change_style() @@ -109,6 +109,6 @@ func build_event_editor() -> void: add_body_edit('clear_textbox', ValueType.BOOL_BUTTON, {'left_text':'Clear:', 'icon':load("res://addons/dialogic/Modules/Clear/clear_textbox.svg"), 'tooltip':'Clear Textbox'}) add_body_edit('clear_portraits', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_characters.svg"), 'tooltip':'Clear Portraits'}) add_body_edit('clear_background', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_background.svg"), 'tooltip':'Clear Background'}) - add_body_edit('clear_music', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_music.svg"), 'tooltip':'Clear Music'}) + add_body_edit('clear_music', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_music.svg"), 'tooltip':'Clear Audio'}) add_body_edit('clear_style', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_style.svg"), 'tooltip':'Clear Style'}) add_body_edit('clear_portrait_positions', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_positions.svg"), 'tooltip':'Clear Portrait Positions'}) diff --git a/addons/dialogic/Modules/Clear/event_clear.gd.uid b/addons/dialogic/Modules/Clear/event_clear.gd.uid index f24274eb..7f8fe272 100644 --- a/addons/dialogic/Modules/Clear/event_clear.gd.uid +++ b/addons/dialogic/Modules/Clear/event_clear.gd.uid @@ -1 +1 @@ -uid://dny1dhrq768ul +uid://7aikid38is1o diff --git a/addons/dialogic/Modules/Clear/index.gd.uid b/addons/dialogic/Modules/Clear/index.gd.uid index e18ecd45..e637770a 100644 --- a/addons/dialogic/Modules/Clear/index.gd.uid +++ b/addons/dialogic/Modules/Clear/index.gd.uid @@ -1 +1 @@ -uid://cj5o6vkiga2r6 +uid://cyftouhvjfun2 diff --git a/addons/dialogic/Modules/Comment/event_comment.gd.uid b/addons/dialogic/Modules/Comment/event_comment.gd.uid index a7c57611..ba26e815 100644 --- a/addons/dialogic/Modules/Comment/event_comment.gd.uid +++ b/addons/dialogic/Modules/Comment/event_comment.gd.uid @@ -1 +1 @@ -uid://drrny0bn1d8ls +uid://dbcesveorhh6m diff --git a/addons/dialogic/Modules/Comment/index.gd.uid b/addons/dialogic/Modules/Comment/index.gd.uid index 19b1b821..47a801fb 100644 --- a/addons/dialogic/Modules/Comment/index.gd.uid +++ b/addons/dialogic/Modules/Comment/index.gd.uid @@ -1 +1 @@ -uid://bi1ru7ecbb7ag +uid://b27oui35aoff4 diff --git a/addons/dialogic/Modules/Condition/event_condition.gd b/addons/dialogic/Modules/Condition/event_condition.gd index d56f34ac..936a690c 100644 --- a/addons/dialogic/Modules/Condition/event_condition.gd +++ b/addons/dialogic/Modules/Condition/event_condition.gd @@ -7,7 +7,8 @@ extends DialogicEvent enum ConditionTypes {IF, ELIF, ELSE} ### Settings -## condition type (see [ConditionTypes]). Defaults to if. + +## Condition type (see [ConditionTypes]). Defaults to if. var condition_type := ConditionTypes.IF ## The condition as a string. Will be executed as an Expression. var condition := "" @@ -26,24 +27,12 @@ func _execute() -> void: var result: bool = dialogic.Expressions.execute_condition(condition) if not result: - var idx: int = dialogic.current_event_idx - var ignore := 1 - while true: - idx += 1 - if not dialogic.current_timeline.get_event(idx) or ignore == 0: - break - elif dialogic.current_timeline.get_event(idx).can_contain_events: - ignore += 1 - elif dialogic.current_timeline.get_event(idx) is DialogicEndBranchEvent: - ignore -= 1 + dialogic.current_event_idx = get_end_branch_index() - dialogic.current_event_idx = idx-1 finish() -## only called if the previous event was an end-branch event -## return true if this event should be executed if the previous event was an end-branch event -func should_execute_this_branch() -> bool: +func _is_branch_starter() -> bool: return condition_type == ConditionTypes.IF @@ -60,7 +49,7 @@ func _init() -> void: # return a control node that should show on the END BRANCH node -func get_end_branch_control() -> Control: +func _get_end_branch_control() -> Control: return load(get_script().resource_path.get_base_dir().path_join('ui_condition_end.tscn')).instantiate() ################################################################################ diff --git a/addons/dialogic/Modules/Condition/event_condition.gd.uid b/addons/dialogic/Modules/Condition/event_condition.gd.uid index 89831bcc..91be9b83 100644 --- a/addons/dialogic/Modules/Condition/event_condition.gd.uid +++ b/addons/dialogic/Modules/Condition/event_condition.gd.uid @@ -1 +1 @@ -uid://doeh3g7s7d4h8 +uid://g8gaor7ewun6 diff --git a/addons/dialogic/Modules/Condition/index.gd.uid b/addons/dialogic/Modules/Condition/index.gd.uid index 4a40d777..b3b4e52c 100644 --- a/addons/dialogic/Modules/Condition/index.gd.uid +++ b/addons/dialogic/Modules/Condition/index.gd.uid @@ -1 +1 @@ -uid://b1mfu6jjyirnm +uid://bsn2cv832qlam diff --git a/addons/dialogic/Modules/Condition/ui_condition_end.gd.uid b/addons/dialogic/Modules/Condition/ui_condition_end.gd.uid index 5a473871..4c3145c1 100644 --- a/addons/dialogic/Modules/Condition/ui_condition_end.gd.uid +++ b/addons/dialogic/Modules/Condition/ui_condition_end.gd.uid @@ -1 +1 @@ -uid://bkov88asfeg1j +uid://hiahx6lrlm17 diff --git a/addons/dialogic/Modules/Condition/ui_condition_end.tscn b/addons/dialogic/Modules/Condition/ui_condition_end.tscn index e002c4db..00c36ba8 100644 --- a/addons/dialogic/Modules/Condition/ui_condition_end.tscn +++ b/addons/dialogic/Modules/Condition/ui_condition_end.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=2 format=3 uid="uid://c60oc5r1aj6me"] +[gd_scene load_steps=2 format=3 uid="uid://dpt6fwem03sqw"] -[ext_resource type="Script" uid="uid://bkov88asfeg1j" path="res://addons/dialogic/Modules/Condition/ui_condition_end.gd" id="1_sh52m"] +[ext_resource type="Script" uid="uid://hiahx6lrlm17" path="res://addons/dialogic/Modules/Condition/ui_condition_end.gd" id="1_sh52m"] [node name="Condition_End" type="HBoxContainer"] offset_right = 90.0 diff --git a/addons/dialogic/Modules/Core/event_end_branch.gd b/addons/dialogic/Modules/Core/event_end_branch.gd index 60a53dd0..306adc5c 100644 --- a/addons/dialogic/Modules/Core/event_end_branch.gd +++ b/addons/dialogic/Modules/Core/event_end_branch.gd @@ -14,43 +14,42 @@ func _execute() -> void: finish() +## Returns the index of the first event that +## - is on the same "indentation" +## - is not a branching event (unless it is a branch starter) func find_next_index() -> int: var idx: int = dialogic.current_event_idx - - var ignore: int = 1 while true: idx += 1 var event: DialogicEvent = dialogic.current_timeline.get_event(idx) if not event: return idx - if event is DialogicEndBranchEvent: - if ignore > 1: - ignore -= 1 - elif event.can_contain_events and not event.should_execute_this_branch(): - ignore += 1 - elif ignore <= 1: - return idx + + if event.can_contain_events: + if event._is_branch_starter(): + break + else: + idx = event.get_end_branch_index() + break + else: + break return idx -func find_opening_index(at_index:int) -> int: - var idx: int = at_index - - var ignore: int = 1 +func get_opening_index() -> int: + var index: int = dialogic.current_timeline_events.find(self) while true: - idx -= 1 - var event: DialogicEvent = dialogic.current_timeline.get_event(idx) - if not event: - return idx + index -= 1 + if index < 0: + break + var event: DialogicEvent = dialogic.current_timeline_events[index] if event is DialogicEndBranchEvent: - ignore += 1 + index = event.get_opening_index() elif event.can_contain_events: - ignore -= 1 - if ignore == 0: - return idx + return index + return 0 - return idx #endregion #region INITIALIZE diff --git a/addons/dialogic/Modules/Core/event_end_branch.gd.uid b/addons/dialogic/Modules/Core/event_end_branch.gd.uid index c1312da3..892b16c7 100644 --- a/addons/dialogic/Modules/Core/event_end_branch.gd.uid +++ b/addons/dialogic/Modules/Core/event_end_branch.gd.uid @@ -1 +1 @@ -uid://u1fgjw2pmu7f +uid://3wq6lhrhifgj diff --git a/addons/dialogic/Modules/Core/index.gd b/addons/dialogic/Modules/Core/index.gd index 7082d4ba..4842c348 100644 --- a/addons/dialogic/Modules/Core/index.gd +++ b/addons/dialogic/Modules/Core/index.gd @@ -23,5 +23,5 @@ func _get_text_effects() -> Array[Dictionary]: func _get_text_modifiers() -> Array[Dictionary]: return [ - {'subsystem':'Expressions', 'method':"modifier_condition", 'command':'if', 'mode':-1}, + {'subsystem':'Expressions', 'method':"modifier_condition", 'command':'if', 'mode':-1, "order":20}, ] diff --git a/addons/dialogic/Modules/Core/index.gd.uid b/addons/dialogic/Modules/Core/index.gd.uid index c14dd114..ab8c9c1e 100644 --- a/addons/dialogic/Modules/Core/index.gd.uid +++ b/addons/dialogic/Modules/Core/index.gd.uid @@ -1 +1 @@ -uid://v3bsjawf3iff +uid://hdi17v8hqb0p diff --git a/addons/dialogic/Modules/Core/subsystem_animation.gd.uid b/addons/dialogic/Modules/Core/subsystem_animation.gd.uid index 32f95508..f107f507 100644 --- a/addons/dialogic/Modules/Core/subsystem_animation.gd.uid +++ b/addons/dialogic/Modules/Core/subsystem_animation.gd.uid @@ -1 +1 @@ -uid://ds2fsl72rli0o +uid://drgk63svehoum diff --git a/addons/dialogic/Modules/Core/subsystem_expression.gd b/addons/dialogic/Modules/Core/subsystem_expression.gd index 5aef9843..763d741e 100644 --- a/addons/dialogic/Modules/Core/subsystem_expression.gd +++ b/addons/dialogic/Modules/Core/subsystem_expression.gd @@ -55,13 +55,21 @@ func execute_condition(condition:String) -> bool: return false -var condition_modifier_regex := RegEx.create_from_string(r"(?(DEFINE)(?([^{}]|\{(?P>nobraces)\})*))\[if *(?\{(?P>nobraces)\})(?(\\\]|\\\/|[^\]\/])*)(\/(?(\\\]|[^\]])*))?\]") +var condition_modifier_regex := RegEx.create_from_string(r"(?(DEFINE)(?([^{}]|\{(?P>nobraces)\})*))\[if *(?(\{(?P>nobraces)\}|true\b|false\b))(?(\\\]|\\\/|[^\]\/])*)(\/(?(\\\]|[^\]])*))?\]") func modifier_condition(text:String) -> String: for find in condition_modifier_regex.search_all(text): + var insert := "" if execute_condition(find.get_string("condition")): - text = text.replace(find.get_string(), find.get_string("truetext").strip_edges()) + insert = find.get_string("truetext") else: - text = text.replace(find.get_string(), find.get_string("falsetext").strip_edges()) + insert = find.get_string("falsetext") + + # Avoid double spaces at the insert position if the insert is empty. + if not insert.strip_edges() and " "+find.get_string()+" " in text: + text = text.replace(find.get_string()+" ", insert.strip_edges()) + else: + text = text.replace(find.get_string(), insert.strip_edges()) + return text #endregion diff --git a/addons/dialogic/Modules/Core/subsystem_expression.gd.uid b/addons/dialogic/Modules/Core/subsystem_expression.gd.uid index 55e9c805..de98ff10 100644 --- a/addons/dialogic/Modules/Core/subsystem_expression.gd.uid +++ b/addons/dialogic/Modules/Core/subsystem_expression.gd.uid @@ -1 +1 @@ -uid://bavk51trmafsh +uid://cn3846afxgeux diff --git a/addons/dialogic/Modules/Core/subsystem_input.gd b/addons/dialogic/Modules/Core/subsystem_input.gd index dec4f657..8b315648 100644 --- a/addons/dialogic/Modules/Core/subsystem_input.gd +++ b/addons/dialogic/Modules/Core/subsystem_input.gd @@ -127,7 +127,7 @@ func handle_node_gui_input(event:InputEvent) -> void: func is_input_blocked() -> bool: - return input_block_timer.time_left > 0.0 + return input_block_timer.time_left > 0.0 and not auto_skip.enabled func block_input(time:=0.1) -> void: diff --git a/addons/dialogic/Modules/Core/subsystem_input.gd.uid b/addons/dialogic/Modules/Core/subsystem_input.gd.uid index 59ca9e9d..29cc8469 100644 --- a/addons/dialogic/Modules/Core/subsystem_input.gd.uid +++ b/addons/dialogic/Modules/Core/subsystem_input.gd.uid @@ -1 +1 @@ -uid://8rbn1lo8jefn +uid://crdsvy044intj diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd b/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd index 4562d68f..af6878ca 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd @@ -17,3 +17,5 @@ func _apply_export_overrides() -> void: # apply layer set(&'layer', canvas_layer) set(&'follow_viewport_enabled', follow_viewport) + + diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd.uid index 5ac83552..b39227f4 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd.uid @@ -1 +1 @@ -uid://bcowue6w1sdxs +uid://yivwmkfwrvfr diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.tscn index 7394c639..da9159f1 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://cqpb3ie51rwl5"] -[ext_resource type="Script" uid="uid://bcowue6w1sdxs" path="res://addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd" id="1_ifsho"] +[ext_resource type="Script" uid="uid://yivwmkfwrvfr" path="res://addons/dialogic/Modules/DefaultLayoutParts/Base_Default/default_layout_base.gd" id="1_ifsho"] [node name="DefaultLayoutBase" type="CanvasLayer"] script = ExtResource("1_ifsho") diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd b/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd index ed4707ab..604b46bc 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd @@ -82,7 +82,8 @@ func _on_dialogic_text_event(info:Dictionary): bubble_to_use.current_character = info.character bubble_to_use.node_to_point_at = node_to_point_at - bubble_to_use.reset() + if not bubble_to_use.visible: + bubble_to_use.reset() if has_node('TextBubbleLayer'): get_node("TextBubbleLayer").bubble_apply_overrides(bubble_to_use) bubble_to_use.open() diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd.uid index 7e2c3161..b1e68a36 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd.uid @@ -1 +1 @@ -uid://dr53w8p0iwcn2 +uid://v8guu7n6gv8a diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.tscn index 5a88a42a..9b08a540 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://syki6k0e6aac"] -[ext_resource type="Script" uid="uid://dr53w8p0iwcn2" path="res://addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd" id="1_urqwc"] +[ext_resource type="Script" uid="uid://v8guu7n6gv8a" path="res://addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.gd" id="1_urqwc"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_70ljh"] content_margin_left = 5.0 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd.uid index 0cceff22..6006d13a 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd.uid @@ -1 +1 @@ -uid://c7frh5xu7x34r +uid://bqdylb4maacf0 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn index d67bd82e..7e2bdcb2 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://c1k5m0w3r40xf"] -[ext_resource type="Script" uid="uid://c7frh5xu7x34r" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd" id="1_tu40u"] -[ext_resource type="Script" uid="uid://bisx1nk1bjyjc" path="res://addons/dialogic/Modules/Background/node_background_holder.gd" id="2_ghan2"] +[ext_resource type="Script" uid="uid://bqdylb4maacf0" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd" id="1_tu40u"] +[ext_resource type="Script" uid="uid://oxcjhq2817c7" path="res://addons/dialogic/Modules/Background/node_background_holder.gd" id="2_ghan2"] [node name="BackgroundLayer" type="Control"] layout_direction = 2 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd index 60f4e914..bcc1eef0 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd @@ -122,7 +122,7 @@ func _on_dialogic_display_dialog_text_meta_hover_ended(_meta:String) -> void: func _apply_export_overrides() -> void: # Apply fonts - var font: FontFile + var font: Font var global_font_setting: String = get_global_setting(&"font", '') if font_use_global and ResourceLoader.exists(global_font_setting): font = load(global_font_setting) diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd.uid index 5392e3a9..2204abd5 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd.uid @@ -1 +1 @@ -uid://dbbd73i5odrjs +uid://o2cnjam8bomr diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.tscn index e0e50409..933fc6ee 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://dsbwnp5hegnu3"] -[ext_resource type="Script" uid="uid://dbbd73i5odrjs" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd" id="1_3nmfj"] +[ext_resource type="Script" uid="uid://o2cnjam8bomr" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.gd" id="1_3nmfj"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_a3cyk"] bg_color = Color(0.12549, 0.12549, 0.12549, 1) diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.gd.uid index 986ed605..a06b4bf2 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.gd.uid @@ -1 +1 @@ -uid://2amxe6fvddmu +uid://67t6pr2eatac diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.tscn index b2d6ebb5..4ae76d49 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://cuoywrmvda1yg"] -[ext_resource type="Script" uid="uid://2amxe6fvddmu" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.gd" id="1_dgoja"] +[ext_resource type="Script" uid="uid://67t6pr2eatac" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.gd" id="1_dgoja"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_upgjp"] content_margin_left = 5.0 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.gd.uid index 3a236555..5641a013 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.gd.uid @@ -1 +1 @@ -uid://jlhgg7cs1iap +uid://gv8mqbjor5nu diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.tscn index f8de3ab1..030e357a 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=4 format=3 uid="uid://lx24i8fl6uo"] -[ext_resource type="Script" uid="uid://jlhgg7cs1iap" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.gd" id="1_4mqm3"] +[ext_resource type="Script" uid="uid://gv8mqbjor5nu" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.gd" id="1_4mqm3"] [ext_resource type="PackedScene" uid="uid://cuoywrmvda1yg" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/example_history_item.tscn" id="2_x1xgk"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1hdvb"] diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.gd.uid index d5ef822f..b70af5f7 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.gd.uid @@ -1 +1 @@ -uid://bqc33k65j5ioy +uid://dwml743wmb7mn diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.tscn index 6a547ece..e66cc341 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://cn674foxwedqu"] -[ext_resource type="Script" uid="uid://bqc33k65j5ioy" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.gd" id="1_3cmha"] -[ext_resource type="Script" uid="uid://do47nn7beuhn5" path="res://addons/dialogic/Modules/Text/node_input.gd" id="2_dxpjw"] +[ext_resource type="Script" uid="uid://dwml743wmb7mn" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.gd" id="1_3cmha"] +[ext_resource type="Script" uid="uid://ctog34kdg222q" path="res://addons/dialogic/Modules/Text/node_input.gd" id="2_dxpjw"] [node name="FullAdvanceInputLayer" type="Control"] layout_mode = 3 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/comms_stylebox.tres b/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/default_stylebox.tres similarity index 78% rename from addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/comms_stylebox.tres rename to addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/default_stylebox.tres index 4e82a7d5..b4230c2d 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/comms_stylebox.tres +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/default_stylebox.tres @@ -1,4 +1,4 @@ -[gd_resource type="StyleBoxFlat" format=3 uid="uid://bqfhagiyjgkf6"] +[gd_resource type="StyleBoxFlat" load_steps=0 format=3 uid="uid://chjt73i3hjh1e"] [resource] content_margin_left = 10.0 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/speaker_portrait_textbox_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/speaker_portrait_textbox_layer.gd.uid index 80099a8f..080aec0a 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/speaker_portrait_textbox_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/speaker_portrait_textbox_layer.gd.uid @@ -1 +1 @@ -uid://dmxeo7lm8ftsi +uid://bk84r61kckpxa diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/textbox_with_speaker_portrait.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/textbox_with_speaker_portrait.tscn index e08b25c1..ae6a3b3a 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/textbox_with_speaker_portrait.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/textbox_with_speaker_portrait.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=7 format=3 uid="uid://by6waso0mjpjp"] -[ext_resource type="Script" uid="uid://cfcx0of1aekhk" path="res://addons/dialogic/Modules/Character/node_portrait_container.gd" id="1_4jxq7"] -[ext_resource type="Script" uid="uid://dmxeo7lm8ftsi" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/speaker_portrait_textbox_layer.gd" id="1_7jt4d"] -[ext_resource type="Script" uid="uid://be3h8wr0w68dx" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="2_y0h34"] -[ext_resource type="Script" uid="uid://ddkvkdb6nxtyi" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_11puy"] -[ext_resource type="Script" uid="uid://bkfrnlul8c6cv" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="5_sr2qw"] +[ext_resource type="Script" uid="uid://d0ptqnbudhkyj" path="res://addons/dialogic/Modules/Character/node_portrait_container.gd" id="1_4jxq7"] +[ext_resource type="Script" uid="uid://bk84r61kckpxa" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/speaker_portrait_textbox_layer.gd" id="1_7jt4d"] +[ext_resource type="Script" uid="uid://bak74s0kcr0ao" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="2_y0h34"] +[ext_resource type="Script" uid="uid://drhfq6rmdeuri" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_11puy"] +[ext_resource type="Script" uid="uid://dpv2dfiv5dhmr" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="5_sr2qw"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dmg1w"] bg_color = Color(0.254902, 0.254902, 0.254902, 1) diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.gd.uid index 244c166a..e67f09fa 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.gd.uid @@ -1 +1 @@ -uid://i5l4pdftho0h +uid://cjdvjwjrj86sj diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.tscn index d6843404..4198bd77 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=5 format=3 uid="uid://cvgf4c6gg0tsy"] -[ext_resource type="Script" uid="uid://i5l4pdftho0h" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.gd" id="1_7ahrn"] -[ext_resource type="Script" uid="uid://rlnfypr752xa" path="res://addons/dialogic/Modules/TextInput/node_text_input.gd" id="1_mxdep"] +[ext_resource type="Script" uid="uid://cjdvjwjrj86sj" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.gd" id="1_7ahrn"] +[ext_resource type="Script" uid="uid://biqpjv0qyefvf" path="res://addons/dialogic/Modules/TextInput/node_text_input.gd" id="1_mxdep"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3dpjm"] content_margin_left = 15.0 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/speech_bubble.gdshader.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/speech_bubble.gdshader.uid index 096d3a58..f6eb3605 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/speech_bubble.gdshader.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/speech_bubble.gdshader.uid @@ -1 +1 @@ -uid://0uxoslmpurip +uid://cs2o12y1i6cti diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd index 669c2e2f..ff7913ce 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd @@ -9,7 +9,12 @@ extends Control @onready var name_label_box: PanelContainer = (%NameLabelPanel as PanelContainer) @onready var name_label_holder: HBoxContainer = $DialogText/NameLabelPositioner -var node_to_point_at: Node = null +var node_to_point_at: Node = null: + set(val): + node_to_point_at = val + base_position = get_speaker_canvas_position() + base_direction * safe_zone + position = base_position + var current_character: DialogicCharacter = null var max_width := 300 @@ -36,13 +41,14 @@ func _ready() -> void: func reset() -> void: + set_process(false) scale = Vector2.ZERO modulate.a = 0.0 tail.points = [] bubble_rect = Rect2(0,0,2,2) - base_position = get_speaker_canvas_position() + base_position = get_speaker_canvas_position() + base_direction * safe_zone position = base_position @@ -106,7 +112,7 @@ func close() -> void: func _on_dialog_text_started_revealing_text() -> void: - _resize_bubble(get_base_content_size(), true) + _resize_bubble(await get_base_content_size(), true) func _resize_bubble(content_size:Vector2, popup:=false) -> void: @@ -137,25 +143,43 @@ func _on_question_shown(info:Dictionary) -> void: if !is_visible_in_tree(): return - await get_tree().process_frame + # Avoid choice_container's flickering(because some ticks will happen in + # `await get_base_content_size()` which will make choice_container exist + # at its old position for several tens of milliseconds). + choice_container.modulate.a = 0 - var content_size := get_base_content_size() + var content_size := await get_base_content_size() content_size.y += choice_container.size.y content_size.x = max(content_size.x, choice_container.size.x) _resize_bubble(content_size) + + # Now, choice_container has changed to its new position, so we can make it + # actually show up. + choice_container.modulate.a = 1 func get_base_content_size() -> Vector2: var font: Font = text.get_theme_font(&"normal_font") - return font.get_multiline_string_size( + var text_width = font.get_multiline_string_size( text.get_parsed_text(), HORIZONTAL_ALIGNMENT_LEFT, max_width, text.get_theme_font_size(&"normal_font_size") - ) + ).x + + # Let text use content's width, and let text auto shrink height to its content. + text.size = Vector2(text_width, 0) + await get_tree().process_frame + + # Don't know why text.size.y != content's height, + # so we re-set text.size.y to 0 to let text shrink to its content again. + # Finally works this time. + text.size.y = 0 + await get_tree().process_frame + return text.size -func add_choice_container(node:Container, alignment:=FlowContainer.ALIGNMENT_BEGIN) -> void: +func add_choice_container(node:Container, alignment:=FlowContainer.ALIGNMENT_BEGIN, choices_button_path:="", maximum_choices:=5) -> void: if choice_container: choice_container.get_parent().remove_child(choice_container) choice_container.queue_free() @@ -168,9 +192,21 @@ func add_choice_container(node:Container, alignment:=FlowContainer.ALIGNMENT_BEG if node is HFlowContainer: (node as HFlowContainer).alignment = alignment + + var choices_button: PackedScene = null + if not choices_button_path.is_empty(): + if ResourceLoader.exists(choices_button_path): + choices_button = (load(choices_button_path) as PackedScene) + else: + printerr("[Dialogic] Unable to load custom choice button from ", choices_button_path) - for i:int in range(5): - choice_container.add_child(DialogicNode_ChoiceButton.new()) + for i:int in range(maximum_choices): + var new_button : DialogicNode_ChoiceButton + if choices_button == null: + new_button = DialogicNode_ChoiceButton.new() + else: + new_button = (choices_button.instantiate() as DialogicNode_ChoiceButton) + choice_container.add_child(new_button) if node is HFlowContainer: continue match alignment: @@ -200,3 +236,11 @@ func get_speaker_canvas_position() -> Vector2: if node_to_point_at is CanvasItem: base_position = (node_to_point_at as CanvasItem).get_global_transform_with_canvas().origin return base_position + + +## Changes the property of mouse filter of the bubble and its children (text and label). +func change_mouse_filter(mouse_filter: Control.MouseFilter) -> void: + mouse_filter = mouse_filter + text.mouse_filter = mouse_filter + name_label_box.mouse_filter = mouse_filter + name_label_holder.mouse_filter = mouse_filter diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd.uid index 49b7bc9d..354cf8bc 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd.uid @@ -1 +1 @@ -uid://cgs1ywlncs4t8 +uid://bminl7x3r40vc diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gdshader.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gdshader.uid index 769de5c0..1a32b4df 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gdshader.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gdshader.uid @@ -1 +1 @@ -uid://cdw3feu6lc4yp +uid://byskpb7ypvuab diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.tscn index d57ed2f9..010ec4b0 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=11 format=3 uid="uid://dlx7jcvm52tyw"] -[ext_resource type="Script" uid="uid://cgs1ywlncs4t8" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd" id="1_jdhpk"] -[ext_resource type="Shader" uid="uid://cdw3feu6lc4yp" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gdshader" id="2_1mhvf"] -[ext_resource type="Script" uid="uid://ddkvkdb6nxtyi" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_syv35"] -[ext_resource type="Script" uid="uid://bkfrnlul8c6cv" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="4_7bm4b"] -[ext_resource type="Script" uid="uid://be3h8wr0w68dx" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="6_5gd03"] +[ext_resource type="Script" uid="uid://bminl7x3r40vc" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd" id="1_jdhpk"] +[ext_resource type="Shader" uid="uid://byskpb7ypvuab" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gdshader" id="2_1mhvf"] +[ext_resource type="Script" uid="uid://drhfq6rmdeuri" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_syv35"] +[ext_resource type="Script" uid="uid://dpv2dfiv5dhmr" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="4_7bm4b"] +[ext_resource type="Script" uid="uid://bak74s0kcr0ao" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="6_5gd03"] [sub_resource type="Curve" id="Curve_0j8nu"] _data = [Vector2(0, 1), 0.0, -1.0, 0, 1, Vector2(1, 0), -1.0, 0.0, 1, 0] @@ -79,6 +79,7 @@ offset_bottom = 12.0 grow_horizontal = 2 grow_vertical = 2 theme_override_colors/default_color = Color(0, 0, 0, 1) +fit_content = true scroll_active = false visible_characters_behavior = 1 script = ExtResource("3_syv35") diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd index d88d4ba0..394095d7 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd @@ -25,6 +25,7 @@ extends DialogicLayoutLayer @export_subgroup('Behaviour') @export var behaviour_distance: int = 50 @export var behaviour_direction: Vector2 = Vector2(1, -1) +@export var behaviour_mouse_filter: Control.MouseFilter @export_group('Name Label') @export_subgroup("Name Label") @@ -55,6 +56,10 @@ extends DialogicLayoutLayer @export var choices_layout_force_lines: bool = false @export_file('*.tres', "*.res") var choices_base_theme: String = "" +@export_subgroup('Behavior') +@export var maximum_choices: int = 5 +@export_file('*.tscn') var choices_custom_button: String = "" + const TextBubble := preload("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd") var bubbles: Array[TextBubble] = [] @@ -93,7 +98,7 @@ func bubble_apply_overrides(bubble:TextBubble) -> void: if !bold_font.is_empty(): rtl.add_theme_font_override(&"bold_font", load(bold_font) as Font) if !italic_font.is_empty(): - rtl.add_theme_font_override(&"italitc_font", load(italic_font) as Font) + rtl.add_theme_font_override(&"italics_font", load(italic_font) as Font) if !bold_italic_font.is_empty(): rtl.add_theme_font_override(&"bold_italics_font", load(bold_italic_font) as Font) bubble.set(&'max_width', text_max_width) @@ -118,6 +123,7 @@ func bubble_apply_overrides(bubble:TextBubble) -> void: ## BEHAVIOUR bubble.safe_zone = behaviour_distance bubble.base_direction = behaviour_direction + bubble.change_mouse_filter(behaviour_mouse_filter) ## NAME LABEL SETTINGS @@ -148,9 +154,9 @@ func bubble_apply_overrides(bubble:TextBubble) -> void: ## CHOICE SETTINGS if choices_layout_force_lines: - bubble.add_choice_container(VBoxContainer.new(), choices_layout_alignment) + bubble.add_choice_container(VBoxContainer.new(), choices_layout_alignment, choices_custom_button, maximum_choices) else: - bubble.add_choice_container(HFlowContainer.new(), choices_layout_alignment) + bubble.add_choice_container(HFlowContainer.new(), choices_layout_alignment, choices_custom_button, maximum_choices) var choice_theme: Theme = null if choices_base_theme.is_empty() or not ResourceLoader.exists(choices_base_theme): diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd.uid index 2d8bcc1a..51bd1b9a 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd.uid @@ -1 +1 @@ -uid://b0npb8ibpyhbx +uid://dcae6nsh8fgtp diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.tscn index 0f7ab17b..141e2983 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://d2it0xiap3gnt"] -[ext_resource type="Script" uid="uid://b0npb8ibpyhbx" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd" id="1_b37je"] +[ext_resource type="Script" uid="uid://dcae6nsh8fgtp" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.gd" id="1_b37je"] [node name="TextBubbleLayer" type="Control"] layout_mode = 3 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd index 97195f5b..2eb30f26 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd @@ -39,6 +39,11 @@ extends DialogicLayoutLayer @export_file("*.wav", "*.ogg", "*.mp3") var sounds_hover: String = "res://addons/dialogic/Example Assets/sound-effects/typing2.wav" @export_file("*.wav", "*.ogg", "*.mp3") var sounds_focus: String = "res://addons/dialogic/Example Assets/sound-effects/typing4.wav" +@export_group('Choices') +@export_subgroup('Behavior') +@export var maximum_choices: int = 10 +@export_file('*.tscn') var choices_custom_button: String = "" + func get_choices() -> VBoxContainer: return $Choices @@ -96,20 +101,36 @@ func _apply_export_overrides() -> void: if ResourceLoader.exists(boxes_stylebox_focused): layer_theme.set_stylebox(&'focus', &'Button', load(boxes_stylebox_focused) as StyleBox) - get_choices().add_theme_constant_override(&"separation", boxes_v_separation) + var choices : Control = get_choices() + choices.add_theme_constant_override(&"separation", boxes_v_separation) self.position = boxes_offset - for child: Node in get_choices().get_children(): - if not child is DialogicNode_ChoiceButton: - continue - var choice: DialogicNode_ChoiceButton = child as DialogicNode_ChoiceButton + # replace choice buttons and apply settings + for child: Node in choices.get_children(): + if child is DialogicNode_ChoiceButton: + child.queue_free() + + var choices_button: PackedScene = null + if not choices_custom_button.is_empty(): + if ResourceLoader.exists(choices_custom_button): + choices_button = (load(choices_custom_button) as PackedScene) + else: + printerr("[Dialogic] Unable to load custom choice button from ", choices_custom_button) + + for i in range(0, maximum_choices): + var new_choice : DialogicNode_ChoiceButton + if choices_button != null: + new_choice = (choices_button.instantiate() as DialogicNode_ChoiceButton) + else: + new_choice = DialogicNode_ChoiceButton.new() + choices.add_child(new_choice) if boxes_fill_width: - choice.size_flags_horizontal = Control.SIZE_FILL + new_choice.size_flags_horizontal = Control.SIZE_FILL else: - choice.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + new_choice.size_flags_horizontal = Control.SIZE_SHRINK_CENTER - choice.custom_minimum_size = boxes_min_size + new_choice.custom_minimum_size = boxes_min_size set(&'theme', layer_theme) diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd.uid index 0582c116..8207b1ac 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd.uid @@ -1 +1 @@ -uid://c8we4ppbftu0e +uid://ij0qm2ew6plv diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.tscn index 08dfd62a..926d6ec9 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=7 format=3 uid="uid://dhk6j6eb6e3q"] -[ext_resource type="Script" uid="uid://c8we4ppbftu0e" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd" id="1_kurgw"] -[ext_resource type="Script" uid="uid://bcirqrep7rvr4" path="res://addons/dialogic/Modules/Choice/node_choice_button.gd" id="1_w632k"] -[ext_resource type="Script" uid="uid://bijk2aslmrx2r" path="res://addons/dialogic/Modules/Choice/node_button_sound.gd" id="2_mgko6"] +[ext_resource type="Script" uid="uid://ij0qm2ew6plv" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.gd" id="1_kurgw"] +[ext_resource type="Script" uid="uid://bldt7xlfum7ov" path="res://addons/dialogic/Modules/Choice/node_choice_button.gd" id="1_w632k"] +[ext_resource type="Script" uid="uid://b1stj4ljd2vo7" path="res://addons/dialogic/Modules/Choice/node_button_sound.gd" id="2_mgko6"] [ext_resource type="AudioStream" uid="uid://b6c1p14bc20p1" path="res://addons/dialogic/Example Assets/sound-effects/typing1.wav" id="3_mql8i"] [ext_resource type="AudioStream" uid="uid://c2viukvbub6v6" path="res://addons/dialogic/Example Assets/sound-effects/typing4.wav" id="4_420fr"] @@ -35,61 +35,6 @@ mouse_filter = 2 alignment = 1 metadata/_edit_layout_mode = 1 -[node name="DialogicNode_ChoiceButton1" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton2" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton3" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton4" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton5" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton6" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton7" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton8" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton9" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton10" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - -[node name="DialogicNode_ChoiceButton11" type="Button" parent="Choices"] -layout_mode = 2 -text = "Some text" -script = ExtResource("1_w632k") - [node name="DialogicNode_ButtonSound" type="AudioStreamPlayer" parent="Choices"] unique_name_in_owner = true script = ExtResource("2_mgko6") diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.gd.uid index e99a0f05..a69879bb 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.gd.uid @@ -1 +1 @@ -uid://cy6akeag2vjh4 +uid://cx1i44s2olq2d diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.tscn index c891eac8..2f7ca1ec 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://cy1y14inwkplb"] -[ext_resource type="Script" uid="uid://cy6akeag2vjh4" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.gd" id="1_1i7em"] -[ext_resource type="Script" uid="uid://cfcx0of1aekhk" path="res://addons/dialogic/Modules/Character/node_portrait_container.gd" id="1_rxdcc"] +[ext_resource type="Script" uid="uid://cx1i44s2olq2d" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.gd" id="1_1i7em"] +[ext_resource type="Script" uid="uid://d0ptqnbudhkyj" path="res://addons/dialogic/Modules/Character/node_portrait_container.gd" id="1_rxdcc"] [node name="VN_PortraitLayer" type="Control"] layout_mode = 3 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd.uid index 26f48e6b..b19a51f1 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd.uid @@ -1 +1 @@ -uid://b1nyasc86bvlp +uid://bfc03rn8slceu diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/autoadvance_indicator.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/autoadvance_indicator.gd.uid index 61df08c5..54c1e691 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/autoadvance_indicator.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/autoadvance_indicator.gd.uid @@ -1 +1 @@ -uid://cd42pehtw2oq5 +uid://bklme8oymw6h7 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.gd.uid index 928d25ff..d7ca10e8 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.gd.uid @@ -1 +1 @@ -uid://cyho51h8hmlrh +uid://bl43m5qw8pso3 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.tscn index 5e2b7a45..4621c611 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.tscn @@ -1,14 +1,14 @@ [gd_scene load_steps=17 format=3 uid="uid://bquja8jyk8kbr"] -[ext_resource type="Script" uid="uid://cyho51h8hmlrh" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.gd" id="1_bpydr"] -[ext_resource type="Script" uid="uid://b1nyasc86bvlp" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd" id="2_xy7a2"] -[ext_resource type="Script" uid="uid://ddkvkdb6nxtyi" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_4634k"] +[ext_resource type="Script" uid="uid://bl43m5qw8pso3" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.gd" id="1_bpydr"] +[ext_resource type="Script" uid="uid://bfc03rn8slceu" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd" id="2_xy7a2"] +[ext_resource type="Script" uid="uid://drhfq6rmdeuri" path="res://addons/dialogic/Modules/Text/node_dialog_text.gd" id="3_4634k"] +[ext_resource type="Script" uid="uid://dpv2dfiv5dhmr" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="4_ma5mw"] +[ext_resource type="Script" uid="uid://dve1vwse2peji" path="res://addons/dialogic/Modules/Text/node_next_indicator.gd" id="5_40a50"] +[ext_resource type="Script" uid="uid://bklme8oymw6h7" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/autoadvance_indicator.gd" id="6_07xym"] [ext_resource type="StyleBox" uid="uid://dkv1pl1c1dq6" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_default_panel.tres" id="3_ssa84"] -[ext_resource type="Script" uid="uid://bkfrnlul8c6cv" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="4_ma5mw"] -[ext_resource type="Script" uid="uid://dk0xy5qppo033" path="res://addons/dialogic/Modules/Text/node_next_indicator.gd" id="5_40a50"] -[ext_resource type="Script" uid="uid://cd42pehtw2oq5" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/autoadvance_indicator.gd" id="6_07xym"] [ext_resource type="Texture2D" uid="uid://b0rpqfg4fhebk" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/next.svg" id="6_uch03"] -[ext_resource type="Script" uid="uid://be3h8wr0w68dx" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="7_bi7sh"] +[ext_resource type="Script" uid="uid://bak74s0kcr0ao" path="res://addons/dialogic/Modules/Text/node_name_label.gd" id="7_bi7sh"] [ext_resource type="StyleBox" uid="uid://m7gyepkysu83" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_name_label_panel.tres" id="9_yg8ig"] [sub_resource type="Animation" id="Animation_au0a2"] diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Style_SpeakerTextbox/speaker_textbox_style.tres b/addons/dialogic/Modules/DefaultLayoutParts/Style_SpeakerTextbox/speaker_textbox_style.tres index 5a471d23..ce61f628 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Style_SpeakerTextbox/speaker_textbox_style.tres +++ b/addons/dialogic/Modules/DefaultLayoutParts/Style_SpeakerTextbox/speaker_textbox_style.tres @@ -1,14 +1,14 @@ [gd_resource type="Resource" script_class="DialogicStyle" load_steps=18 format=3 uid="uid://dgkmuyvy5qc35"] [ext_resource type="PackedScene" uid="uid://c1k5m0w3r40xf" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn" id="1_sde84"] -[ext_resource type="Script" uid="uid://dh4po8pgey4yv" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="2_i34tx"] +[ext_resource type="Script" uid="uid://bwg6yncmh2cml" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="2_i34tx"] [ext_resource type="PackedScene" uid="uid://by6waso0mjpjp" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_SpeakerPortraitTextbox/textbox_with_speaker_portrait.tscn" id="3_epko4"] [ext_resource type="PackedScene" uid="uid://cn674foxwedqu" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.tscn" id="4_8y2vo"] [ext_resource type="PackedScene" uid="uid://dsbwnp5hegnu3" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.tscn" id="5_ll78j"] [ext_resource type="PackedScene" uid="uid://dhk6j6eb6e3q" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.tscn" id="6_36eid"] [ext_resource type="PackedScene" uid="uid://cvgf4c6gg0tsy" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.tscn" id="7_hx5el"] [ext_resource type="PackedScene" uid="uid://lx24i8fl6uo" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.tscn" id="8_00chv"] -[ext_resource type="Script" uid="uid://dfja8ptqdlfix" path="res://addons/dialogic/Resources/dialogic_style.gd" id="9_sdr6x"] +[ext_resource type="Script" uid="uid://dv08k6ljua6fm" path="res://addons/dialogic/Resources/dialogic_style.gd" id="9_sdr6x"] [sub_resource type="Resource" id="Resource_1cyj6"] script = ExtResource("2_i34tx") diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Style_TextBubbles/textbubble_style.tres b/addons/dialogic/Modules/DefaultLayoutParts/Style_TextBubbles/textbubble_style.tres index 7e89b368..78bdbc1c 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Style_TextBubbles/textbubble_style.tres +++ b/addons/dialogic/Modules/DefaultLayoutParts/Style_TextBubbles/textbubble_style.tres @@ -1,9 +1,9 @@ [gd_resource type="Resource" script_class="DialogicStyle" load_steps=9 format=3 uid="uid://b0sbwssin2kuk"] [ext_resource type="PackedScene" uid="uid://syki6k0e6aac" path="res://addons/dialogic/Modules/DefaultLayoutParts/Base_TextBubble/text_bubble_base.tscn" id="1_a7s28"] -[ext_resource type="Script" uid="uid://dfja8ptqdlfix" path="res://addons/dialogic/Resources/dialogic_style.gd" id="1_q3xp1"] +[ext_resource type="Script" uid="uid://dv08k6ljua6fm" path="res://addons/dialogic/Resources/dialogic_style.gd" id="1_q3xp1"] [ext_resource type="PackedScene" uid="uid://d2it0xiap3gnt" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble_layer.tscn" id="2_ctkoo"] -[ext_resource type="Script" uid="uid://dh4po8pgey4yv" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="3_3a5cc"] +[ext_resource type="Script" uid="uid://bwg6yncmh2cml" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="3_3a5cc"] [ext_resource type="PackedScene" uid="uid://cn674foxwedqu" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Input/full_advance_input_layer.tscn" id="4_rr4hm"] [sub_resource type="Resource" id="Resource_u2jf8"] diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Style_VN_Default/default_vn_style.tres b/addons/dialogic/Modules/DefaultLayoutParts/Style_VN_Default/default_vn_style.tres index c8b82dcc..673fb886 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Style_VN_Default/default_vn_style.tres +++ b/addons/dialogic/Modules/DefaultLayoutParts/Style_VN_Default/default_vn_style.tres @@ -1,7 +1,7 @@ [gd_resource type="Resource" script_class="DialogicStyle" load_steps=20 format=3 uid="uid://8t1mr302tmqs"] -[ext_resource type="Script" uid="uid://dfja8ptqdlfix" path="res://addons/dialogic/Resources/dialogic_style.gd" id="1_mvpc0"] -[ext_resource type="Script" uid="uid://dh4po8pgey4yv" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="2_3b8ue"] +[ext_resource type="Script" uid="uid://dv08k6ljua6fm" path="res://addons/dialogic/Resources/dialogic_style.gd" id="1_mvpc0"] +[ext_resource type="Script" uid="uid://bwg6yncmh2cml" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="2_3b8ue"] [ext_resource type="PackedScene" uid="uid://c1k5m0w3r40xf" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn" id="2_dtgi6"] [ext_resource type="PackedScene" uid="uid://cy1y14inwkplb" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Portraits/vn_portrait_layer.tscn" id="4_q1t5h"] [ext_resource type="PackedScene" uid="uid://bquja8jyk8kbr" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/vn_textbox_layer.tscn" id="5_o6sv8"] diff --git a/addons/dialogic/Modules/DefaultLayoutParts/index.gd b/addons/dialogic/Modules/DefaultLayoutParts/index.gd index ad5e9859..f07b3b3e 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/index.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/index.gd @@ -1,3 +1,4 @@ +@tool extends DialogicIndexer diff --git a/addons/dialogic/Modules/DefaultLayoutParts/index.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/index.gd.uid index 298461fa..c644837e 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/index.gd.uid +++ b/addons/dialogic/Modules/DefaultLayoutParts/index.gd.uid @@ -1 +1 @@ -uid://bic8b0imerwgk +uid://c1dc5xk6urgfg diff --git a/addons/dialogic/Modules/End/event_end.gd.uid b/addons/dialogic/Modules/End/event_end.gd.uid index 0b2d35e3..29415086 100644 --- a/addons/dialogic/Modules/End/event_end.gd.uid +++ b/addons/dialogic/Modules/End/event_end.gd.uid @@ -1 +1 @@ -uid://ca1bpgoloioma +uid://gyh5a2l1ltmc diff --git a/addons/dialogic/Modules/End/index.gd.uid b/addons/dialogic/Modules/End/index.gd.uid index 2f12da71..c5234f15 100644 --- a/addons/dialogic/Modules/End/index.gd.uid +++ b/addons/dialogic/Modules/End/index.gd.uid @@ -1 +1 @@ -uid://cyua3xkn72xym +uid://rvs5ddidyxmc diff --git a/addons/dialogic/Modules/Glossary/event_glossary.gd.uid b/addons/dialogic/Modules/Glossary/event_glossary.gd.uid index 74275e99..9ec06ad4 100644 --- a/addons/dialogic/Modules/Glossary/event_glossary.gd.uid +++ b/addons/dialogic/Modules/Glossary/event_glossary.gd.uid @@ -1 +1 @@ -uid://cebop4iepynvu +uid://or77lo7du0ot diff --git a/addons/dialogic/Modules/Glossary/glossary_editor.gd.uid b/addons/dialogic/Modules/Glossary/glossary_editor.gd.uid index f5a44cd5..608b7179 100644 --- a/addons/dialogic/Modules/Glossary/glossary_editor.gd.uid +++ b/addons/dialogic/Modules/Glossary/glossary_editor.gd.uid @@ -1 +1 @@ -uid://bylu81d2no1m5 +uid://bqu863yjcjc8y diff --git a/addons/dialogic/Modules/Glossary/glossary_editor.tscn b/addons/dialogic/Modules/Glossary/glossary_editor.tscn index dde1270c..a30d33dc 100644 --- a/addons/dialogic/Modules/Glossary/glossary_editor.tscn +++ b/addons/dialogic/Modules/Glossary/glossary_editor.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://due48ce7jiudt"] -[ext_resource type="Script" uid="uid://bylu81d2no1m5" path="res://addons/dialogic/Modules/Glossary/glossary_editor.gd" id="1_tf3p1"] +[ext_resource type="Script" uid="uid://bqu863yjcjc8y" path="res://addons/dialogic/Modules/Glossary/glossary_editor.gd" id="1_tf3p1"] [ext_resource type="Texture2D" uid="uid://cenut3sc5cul0" path="res://addons/dialogic/Modules/Glossary/add-glossary.svg" id="2_0elx7"] [sub_resource type="Image" id="Image_2730t"] diff --git a/addons/dialogic/Modules/Glossary/glossary_resource.gd.uid b/addons/dialogic/Modules/Glossary/glossary_resource.gd.uid index a7b8cf9f..da873653 100644 --- a/addons/dialogic/Modules/Glossary/glossary_resource.gd.uid +++ b/addons/dialogic/Modules/Glossary/glossary_resource.gd.uid @@ -1 +1 @@ -uid://defa11l8ebb1n +uid://80elcodyqohb diff --git a/addons/dialogic/Modules/Glossary/index.gd.uid b/addons/dialogic/Modules/Glossary/index.gd.uid index 1ffe3405..66d012aa 100644 --- a/addons/dialogic/Modules/Glossary/index.gd.uid +++ b/addons/dialogic/Modules/Glossary/index.gd.uid @@ -1 +1 @@ -uid://lcdc2gipcdh2 +uid://787tgkcn11ya diff --git a/addons/dialogic/Modules/Glossary/subsystem_glossary.gd b/addons/dialogic/Modules/Glossary/subsystem_glossary.gd index d438bc4b..74077b74 100644 --- a/addons/dialogic/Modules/Glossary/subsystem_glossary.gd +++ b/addons/dialogic/Modules/Glossary/subsystem_glossary.gd @@ -64,7 +64,7 @@ func parse_glossary(text: String) -> String: if regex_options.is_empty(): continue - var pattern: String = '(?<=\\W|^)(?' + regex_options + ')(?!])(?=\\W|$)' + var pattern: String = r'(?<=\W|^)(?' + regex_options + r')(?!])(?=\W|$)' if entry.get('case_sensitive', def_case_sensitive): regex.compile(pattern) @@ -78,7 +78,7 @@ func parse_glossary(text: String) -> String: color = color_overrides[entry_key].to_html() text = regex.sub(text, - '[url=' + entry_key + ']' + + '[url="' + entry_key + '"]' + '[color=' + color + ']${word}[/color]' + '[/url]', true diff --git a/addons/dialogic/Modules/Glossary/subsystem_glossary.gd.uid b/addons/dialogic/Modules/Glossary/subsystem_glossary.gd.uid index ada48be8..666f8002 100644 --- a/addons/dialogic/Modules/Glossary/subsystem_glossary.gd.uid +++ b/addons/dialogic/Modules/Glossary/subsystem_glossary.gd.uid @@ -1 +1 @@ -uid://57up7ahwbwwi +uid://drwqxg5amy4u diff --git a/addons/dialogic/Modules/HighlightPortrait/index.gd.uid b/addons/dialogic/Modules/HighlightPortrait/index.gd.uid index 87b3ba09..46483fc4 100644 --- a/addons/dialogic/Modules/HighlightPortrait/index.gd.uid +++ b/addons/dialogic/Modules/HighlightPortrait/index.gd.uid @@ -1 +1 @@ -uid://dgf0hejyljbhf +uid://rsqhj802vgdj diff --git a/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd b/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd index 5ed6649d..f2d39f34 100644 --- a/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd +++ b/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd @@ -19,6 +19,10 @@ func _ready() -> void: self.modulate = unhighlighted_color +func _should_do_portrait_update(_character: DialogicCharacter, _portrait: String) -> bool: + return true + + func _highlight() -> void: create_tween().tween_property(self, 'modulate', Color.WHITE, 0.15) _prev_z_index = DialogicUtil.autoload().Portraits.get_character_info(character).get('z_index', 0) diff --git a/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd.uid b/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd.uid index acd50b41..69528878 100644 --- a/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd.uid +++ b/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd.uid @@ -1 +1 @@ -uid://gnfe6vvyhp2k +uid://24gbl2wbl1d5 diff --git a/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.tscn b/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.tscn index c7f30bf4..4d831c09 100644 --- a/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.tscn +++ b/addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://br18lgpga2y2v"] -[ext_resource type="Script" uid="uid://gnfe6vvyhp2k" path="res://addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd" id="1_ceqva"] +[ext_resource type="Script" uid="uid://24gbl2wbl1d5" path="res://addons/dialogic/Modules/HighlightPortrait/simple_highlight_portrait.gd" id="1_ceqva"] [node name="DefaultPortrait" type="Node2D"] script = ExtResource("1_ceqva") diff --git a/addons/dialogic/Modules/History/event_history.gd.uid b/addons/dialogic/Modules/History/event_history.gd.uid index 7d309981..74dde802 100644 --- a/addons/dialogic/Modules/History/event_history.gd.uid +++ b/addons/dialogic/Modules/History/event_history.gd.uid @@ -1 +1 @@ -uid://cw4ejofd4pq6a +uid://dmedm3l78l7gx diff --git a/addons/dialogic/Modules/History/index.gd.uid b/addons/dialogic/Modules/History/index.gd.uid index f64afd90..47238a47 100644 --- a/addons/dialogic/Modules/History/index.gd.uid +++ b/addons/dialogic/Modules/History/index.gd.uid @@ -1 +1 @@ -uid://qvmwqiwq302j +uid://bpcgxmwxm5pif diff --git a/addons/dialogic/Modules/History/settings_history.gd.uid b/addons/dialogic/Modules/History/settings_history.gd.uid index 4a69215f..a1c9502a 100644 --- a/addons/dialogic/Modules/History/settings_history.gd.uid +++ b/addons/dialogic/Modules/History/settings_history.gd.uid @@ -1 +1 @@ -uid://2qmfgh84ub6j +uid://cqfmftweedlvb diff --git a/addons/dialogic/Modules/History/settings_history.tscn b/addons/dialogic/Modules/History/settings_history.tscn index b526d7be..f8451d07 100644 --- a/addons/dialogic/Modules/History/settings_history.tscn +++ b/addons/dialogic/Modules/History/settings_history.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://b5yq6xh412ilm"] -[ext_resource type="Script" uid="uid://2qmfgh84ub6j" path="res://addons/dialogic/Modules/History/settings_history.gd" id="1_hbhst"] +[ext_resource type="Script" uid="uid://cqfmftweedlvb" path="res://addons/dialogic/Modules/History/settings_history.gd" id="1_hbhst"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_wefye"] [sub_resource type="Image" id="Image_cvlu0"] diff --git a/addons/dialogic/Modules/History/subsystem_history.gd.uid b/addons/dialogic/Modules/History/subsystem_history.gd.uid index aef70e1a..53c77cc9 100644 --- a/addons/dialogic/Modules/History/subsystem_history.gd.uid +++ b/addons/dialogic/Modules/History/subsystem_history.gd.uid @@ -1 +1 @@ -uid://cvpi46puxu81n +uid://bfcdxeqbr1by1 diff --git a/addons/dialogic/Modules/Jump/event_jump.gd b/addons/dialogic/Modules/Jump/event_jump.gd index fc257bd8..9566e460 100644 --- a/addons/dialogic/Modules/Jump/event_jump.gd +++ b/addons/dialogic/Modules/Jump/event_jump.gd @@ -19,7 +19,7 @@ var label_name := "" var timeline_identifier := "": get: if timeline: - var identifier := DialogicResourceUtil.get_unique_identifier(timeline.resource_path) + var identifier := timeline.get_identifier() if not identifier.is_empty(): return identifier return timeline_identifier @@ -95,7 +95,7 @@ func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info "timeline" : {"property": "timeline_identifier", "default": null, - "suggestions": get_timeline_suggestions}, + "suggestions": get_timeline_suggestions, "ext_file":true}, "label" : {"property": "label_name", "default": ""}, } @@ -109,7 +109,7 @@ func build_event_editor() -> void: 'file_extension': '.dtl', 'mode' : 2, 'suggestions_func': get_timeline_suggestions, - 'editor_icon' : ["TripleBar", "EditorIcons"], + 'icon' : load("res://addons/dialogic/Editor/Images/Resources/timeline.svg"), 'empty_text' : '(this timeline)', 'autofocus' : true, }) @@ -134,6 +134,9 @@ func get_label_suggestions(_filter:String="") -> Dictionary: if timeline_identifier in DialogicResourceUtil.get_label_cache().keys(): for label in DialogicResourceUtil.get_label_cache()[timeline_identifier]: suggestions[label] = {'value': label, 'tooltip':label, 'editor_icon': ["ArrowRight", "EditorIcons"]} + if _filter.begins_with("{"): + for var_path in DialogicUtil.list_variables(DialogicUtil.get_default_variables()): + suggestions["{"+var_path+"}"] = {'value':"{"+var_path+"}", 'icon':load("res://addons/dialogic/Editor/Images/Pieces/variable.svg")} return suggestions @@ -144,6 +147,8 @@ func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:Str if symbol == ' ' and line.count(' ') == 1: CodeCompletionHelper.suggest_labels(TextNode, '', '\n', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6)) CodeCompletionHelper.suggest_timelines(TextNode, CodeEdit.KIND_MEMBER, event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6)) + if symbol == "{": + CodeCompletionHelper.suggest_variables(TextNode) if symbol == '/': CodeCompletionHelper.suggest_labels(TextNode, line.strip_edges().trim_prefix('jump ').trim_suffix('/'+String.chr(0xFFFF)).strip_edges(), '\n', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.6)) diff --git a/addons/dialogic/Modules/Jump/event_jump.gd.uid b/addons/dialogic/Modules/Jump/event_jump.gd.uid index 0b437fbd..668bcfac 100644 --- a/addons/dialogic/Modules/Jump/event_jump.gd.uid +++ b/addons/dialogic/Modules/Jump/event_jump.gd.uid @@ -1 +1 @@ -uid://cptoxigoty8kr +uid://ckayb5m8qyh0p diff --git a/addons/dialogic/Modules/Jump/event_label.gd b/addons/dialogic/Modules/Jump/event_label.gd index 97f7ac65..e324739b 100644 --- a/addons/dialogic/Modules/Jump/event_label.gd +++ b/addons/dialogic/Modules/Jump/event_label.gd @@ -24,7 +24,7 @@ func _execute() -> void: "identifier": name, "display_name": get_property_translated("display_name"), "display_name_orig": display_name, - "timeline": DialogicResourceUtil.get_unique_identifier(dialogic.current_timeline.resource_path) + "timeline": dialogic.current_timeline.get_identifier() }) finish() diff --git a/addons/dialogic/Modules/Jump/event_label.gd.uid b/addons/dialogic/Modules/Jump/event_label.gd.uid index 0912ed04..6d248f18 100644 --- a/addons/dialogic/Modules/Jump/event_label.gd.uid +++ b/addons/dialogic/Modules/Jump/event_label.gd.uid @@ -1 +1 @@ -uid://doigeg6vvu0yd +uid://c87eqjyrb1mm0 diff --git a/addons/dialogic/Modules/Jump/event_return.gd b/addons/dialogic/Modules/Jump/event_return.gd index 411e2616..33f02234 100644 --- a/addons/dialogic/Modules/Jump/event_return.gd +++ b/addons/dialogic/Modules/Jump/event_return.gd @@ -11,7 +11,7 @@ extends DialogicEvent ################################################################################ func _execute() -> void: - if !dialogic.Jump.is_jump_stack_empty(): + if not dialogic.Jump.is_jump_stack_empty(): dialogic.Jump.resume_from_last_jump() else: dialogic.end_timeline() diff --git a/addons/dialogic/Modules/Jump/event_return.gd.uid b/addons/dialogic/Modules/Jump/event_return.gd.uid index ebc077b6..dd6b6e28 100644 --- a/addons/dialogic/Modules/Jump/event_return.gd.uid +++ b/addons/dialogic/Modules/Jump/event_return.gd.uid @@ -1 +1 @@ -uid://cl6u17e7k7d8f +uid://dqc8e0tnb7qsc diff --git a/addons/dialogic/Modules/Jump/index.gd.uid b/addons/dialogic/Modules/Jump/index.gd.uid index e4cc099e..efe721fd 100644 --- a/addons/dialogic/Modules/Jump/index.gd.uid +++ b/addons/dialogic/Modules/Jump/index.gd.uid @@ -1 +1 @@ -uid://cxjpiba6v5ddc +uid://45g7pgoc6boa diff --git a/addons/dialogic/Modules/Jump/subsystem_jump.gd b/addons/dialogic/Modules/Jump/subsystem_jump.gd index b993973c..7ff68330 100644 --- a/addons/dialogic/Modules/Jump/subsystem_jump.gd +++ b/addons/dialogic/Modules/Jump/subsystem_jump.gd @@ -2,11 +2,42 @@ extends DialogicSubsystem ## Subsystem that holds methods for jumping to specific labels, or return to the previous jump. -signal switched_timeline(info:Dictionary) -signal jumped_to_label(info:Dictionary) -signal returned_from_jump(info:Dictionary) -signal passed_label(info:Dictionary) +@warning_ignore("unused_signal") # this is emitted from the jump event +## Emitted when a jump event switches from one timeline to another. Gives a dictionary witht the keys: +## [br] +## Key | Value Type | Value [br] +## -------------------- | ----------------------- | ----- [br] +## `previous_timeline` | [type DialogicTimeline] | The timeline that we were in previously. [br] +## `timeline` | [type DialogicTimeline] | The timeline we are in now. [br] +## `label` | [type String] | The label we went to (empty if beginning). [br] +signal switched_timeline(info:Dictionary) + +## Emitted when a jump event jumps to a label. Gives a dictionary witht the keys: +## [br] +## Key | Value Type | Value [br] +## ----------- | ----------------------- | ----- [br] +## `timeline` | [type DialogicTimeline] | The timeline we are in now. [br] +## `label` | [type String] | The label we went to (empty if beginning). [br] +signal jumped_to_label(info:Dictionary) + +## Emitted when a return event is hit and there was a timeline to return to. Gives a dictionary witht the keys: +## [br] +## Key | Value Type | Value [br] +## --------------- | ----------------------- | ----- [br] +## `sub_timeline` | [type DialogicTimeline] | The timeline we were in before. [br] +## `label` | [type String] | The label we went back to (empty if beginning). [br] +signal returned_from_jump(info:Dictionary) + +## Emitted when a label event is executed (usually does nothing else). Gives a dictionary witht the keys: +## [br] +## Key | Value Type | Value [br] +## ------------------- | ----------------------- | ----- [br] +## `identifier` | [type String] | The identifier of the label event. [br] +## `display_name` | [type String] | The display name, possibly translated. [br] +## `display_name_orig` | [type String] | The untranslated display name. [br] +## `timeline` | [type String] | The identifier of the timeline we are in. [br] +signal passed_label(info:Dictionary) #region STATE #################################################################################################### @@ -29,8 +60,10 @@ func load_game_state(_load_flag:=LoadFlags.FULL_LOAD) -> void: func jump_to_label(label:String) -> void: if label.is_empty(): dialogic.current_event_idx = 0 - jumped_to_label.emit({'timeline':dialogic.current_timeline, 'label':"TOP"}) + jumped_to_label.emit({'timeline':dialogic.current_timeline, 'label':""}) return + ## Allows label to be a variable, making the jump event dynamic + label = str(dialogic.VAR.parse_variables(label)) var idx: int = -1 while true: diff --git a/addons/dialogic/Modules/Jump/subsystem_jump.gd.uid b/addons/dialogic/Modules/Jump/subsystem_jump.gd.uid index 6b646013..ee4b8fab 100644 --- a/addons/dialogic/Modules/Jump/subsystem_jump.gd.uid +++ b/addons/dialogic/Modules/Jump/subsystem_jump.gd.uid @@ -1 +1 @@ -uid://dpxn3c2bwclq7 +uid://w5mnpl7oui4j diff --git a/addons/dialogic/Modules/LayeredPortrait/custom_layered_portrait.gd.uid b/addons/dialogic/Modules/LayeredPortrait/custom_layered_portrait.gd.uid index 07253165..053f0874 100644 --- a/addons/dialogic/Modules/LayeredPortrait/custom_layered_portrait.gd.uid +++ b/addons/dialogic/Modules/LayeredPortrait/custom_layered_portrait.gd.uid @@ -1 +1 @@ -uid://bghgjtovkcy8x +uid://cfwf5d8exox4f diff --git a/addons/dialogic/Modules/LayeredPortrait/index.gd.uid b/addons/dialogic/Modules/LayeredPortrait/index.gd.uid index aadfa5fb..cc25c79d 100644 --- a/addons/dialogic/Modules/LayeredPortrait/index.gd.uid +++ b/addons/dialogic/Modules/LayeredPortrait/index.gd.uid @@ -1 +1 @@ -uid://boyn1givv60g1 +uid://bevafbsglh3dy diff --git a/addons/dialogic/Modules/LayeredPortrait/layered_portrait.gd.uid b/addons/dialogic/Modules/LayeredPortrait/layered_portrait.gd.uid index 02e7caee..a3a82ca6 100644 --- a/addons/dialogic/Modules/LayeredPortrait/layered_portrait.gd.uid +++ b/addons/dialogic/Modules/LayeredPortrait/layered_portrait.gd.uid @@ -1 +1 @@ -uid://sur7la03f7er +uid://qoonb27oal7l diff --git a/addons/dialogic/Modules/LayeredPortrait/layered_portrait.tscn b/addons/dialogic/Modules/LayeredPortrait/layered_portrait.tscn index fbac5de2..3e893a3d 100644 --- a/addons/dialogic/Modules/LayeredPortrait/layered_portrait.tscn +++ b/addons/dialogic/Modules/LayeredPortrait/layered_portrait.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=3 uid="uid://jac4eurttev1"] -[ext_resource type="Script" uid="uid://bghgjtovkcy8x" path="res://addons/dialogic/Modules/LayeredPortrait/custom_layered_portrait.gd" id="1_uubi5"] +[ext_resource type="Script" uid="uid://cfwf5d8exox4f" path="res://addons/dialogic/Modules/LayeredPortrait/custom_layered_portrait.gd" id="1_uubi5"] [node name="LayeredPortrait" type="CanvasGroup"] script = ExtResource("1_uubi5") diff --git a/addons/dialogic/Modules/Save/event_save.gd.uid b/addons/dialogic/Modules/Save/event_save.gd.uid index 2e4e85d3..b6e7d258 100644 --- a/addons/dialogic/Modules/Save/event_save.gd.uid +++ b/addons/dialogic/Modules/Save/event_save.gd.uid @@ -1 +1 @@ -uid://bh14ixn684hxt +uid://j3d7ocv2fui7 diff --git a/addons/dialogic/Modules/Save/index.gd.uid b/addons/dialogic/Modules/Save/index.gd.uid index df37ff2c..58497ce3 100644 --- a/addons/dialogic/Modules/Save/index.gd.uid +++ b/addons/dialogic/Modules/Save/index.gd.uid @@ -1 +1 @@ -uid://ddo3oaqijdub0 +uid://gyh46etsbyyf diff --git a/addons/dialogic/Modules/Save/settings_save.gd.uid b/addons/dialogic/Modules/Save/settings_save.gd.uid index 1ac2d2bc..63b75831 100644 --- a/addons/dialogic/Modules/Save/settings_save.gd.uid +++ b/addons/dialogic/Modules/Save/settings_save.gd.uid @@ -1 +1 @@ -uid://cwl7wfn67ckx7 +uid://bxgl1awhvasa1 diff --git a/addons/dialogic/Modules/Save/settings_save.tscn b/addons/dialogic/Modules/Save/settings_save.tscn index 6ae5729e..c6f9ea62 100644 --- a/addons/dialogic/Modules/Save/settings_save.tscn +++ b/addons/dialogic/Modules/Save/settings_save.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://cd340w7blofak"] -[ext_resource type="Script" uid="uid://cwl7wfn67ckx7" path="res://addons/dialogic/Modules/Save/settings_save.gd" id="2"] +[ext_resource type="Script" uid="uid://bxgl1awhvasa1" path="res://addons/dialogic/Modules/Save/settings_save.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_v2wt8"] [sub_resource type="Image" id="Image_6yfie"] diff --git a/addons/dialogic/Modules/Save/subsystem_save.gd.uid b/addons/dialogic/Modules/Save/subsystem_save.gd.uid index 4fde18da..9b97a5b7 100644 --- a/addons/dialogic/Modules/Save/subsystem_save.gd.uid +++ b/addons/dialogic/Modules/Save/subsystem_save.gd.uid @@ -1 +1 @@ -uid://bfqphbspe63yj +uid://4cjnn8utcm6n diff --git a/addons/dialogic/Modules/Settings/event_setting.gd.uid b/addons/dialogic/Modules/Settings/event_setting.gd.uid index b7b65632..cff74406 100644 --- a/addons/dialogic/Modules/Settings/event_setting.gd.uid +++ b/addons/dialogic/Modules/Settings/event_setting.gd.uid @@ -1 +1 @@ -uid://dprgjv1cjkquo +uid://c1r4lgnfmbcnq diff --git a/addons/dialogic/Modules/Settings/index.gd.uid b/addons/dialogic/Modules/Settings/index.gd.uid index a2f64727..e2c451fe 100644 --- a/addons/dialogic/Modules/Settings/index.gd.uid +++ b/addons/dialogic/Modules/Settings/index.gd.uid @@ -1 +1 @@ -uid://duf5xcmv3d8vt +uid://duw5552xl4nb5 diff --git a/addons/dialogic/Modules/Settings/subsystem_settings.gd.uid b/addons/dialogic/Modules/Settings/subsystem_settings.gd.uid index 7ca3b100..436e11cf 100644 --- a/addons/dialogic/Modules/Settings/subsystem_settings.gd.uid +++ b/addons/dialogic/Modules/Settings/subsystem_settings.gd.uid @@ -1 +1 @@ -uid://cmaxlqb2cwm5q +uid://id1hgvjvgjqv diff --git a/addons/dialogic/Modules/Signal/event_signal.gd.uid b/addons/dialogic/Modules/Signal/event_signal.gd.uid index 3ecf8e65..a39f44bd 100644 --- a/addons/dialogic/Modules/Signal/event_signal.gd.uid +++ b/addons/dialogic/Modules/Signal/event_signal.gd.uid @@ -1 +1 @@ -uid://ccswsde70em3e +uid://bpe3v0v5ig4al diff --git a/addons/dialogic/Modules/Signal/index.gd.uid b/addons/dialogic/Modules/Signal/index.gd.uid index 9d0c5d62..9f1dd61d 100644 --- a/addons/dialogic/Modules/Signal/index.gd.uid +++ b/addons/dialogic/Modules/Signal/index.gd.uid @@ -1 +1 @@ -uid://h088u214hjwa +uid://c0rhhq1hvy2ct diff --git a/addons/dialogic/Modules/Style/DialogicStylesUtil.gd b/addons/dialogic/Modules/Style/DialogicStylesUtil.gd new file mode 100644 index 00000000..f4bb2c60 --- /dev/null +++ b/addons/dialogic/Modules/Style/DialogicStylesUtil.gd @@ -0,0 +1,79 @@ +@tool +class_name DialogicStylesUtil +extends Node + +static var style_directory := {} + +#region STYLES +################################################################################ + +static func update_style_directory() -> void: + style_directory = ProjectSettings.get_setting('dialogic/layout/style_directory', {}) + + +static func build_style_directory() -> void: + style_directory.clear() + + var default := get_default_style_path() + if ResourceLoader.exists(default): + style_directory[""] = default + + var styles: Array = ProjectSettings.get_setting('dialogic/layout/style_list', []) + for style_path in styles: + if not ResourceLoader.exists(style_path): + continue + # TODO this is bad + var resource: DialogicStyle = load(style_path) + style_directory[resource.name] = style_path + + if Engine.is_editor_hint(): + ProjectSettings.set_setting('dialogic/layout/style_directory', style_directory) + ProjectSettings.save() + + +static func get_default_style_path() -> String: + return ProjectSettings.get_setting('dialogic/layout/default_style', '') + + +static func get_default_layout_base() -> PackedScene: + return load(DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Base_Default/default_layout_base.tscn")) + + +static func get_fallback_style_path() -> String: + return DialogicUtil.get_module_path('DefaultLayoutParts').path_join("Style_VN_Default/default_vn_style.tres") + + +static func get_fallback_style() -> DialogicStyle: + return load(get_fallback_style_path()) + + +static func get_style_path(name_or_path:String) -> String: + if name_or_path.begins_with("res://"): + if not ResourceLoader.exists(name_or_path): + name_or_path = "" + + if name_or_path in style_directory: + name_or_path = style_directory[name_or_path] + + if not name_or_path: + name_or_path = get_default_style_path() + + if not name_or_path or not ResourceLoader.exists(name_or_path): + return get_fallback_style_path() + + return name_or_path + + +static func start_style_preload(name_or_path:String) -> void: + ResourceLoader.load_threaded_request(get_style_path(name_or_path)) + + +static func get_style(style_name:String) -> DialogicStyle: + var path := get_style_path(style_name) + if ResourceLoader.load_threaded_get_status(path) == ResourceLoader.THREAD_LOAD_LOADED: + return ResourceLoader.load_threaded_get(path) + + return load(path) + + +#endregion diff --git a/addons/dialogic/Modules/Style/DialogicStylesUtil.gd.uid b/addons/dialogic/Modules/Style/DialogicStylesUtil.gd.uid new file mode 100644 index 00000000..eb2451d1 --- /dev/null +++ b/addons/dialogic/Modules/Style/DialogicStylesUtil.gd.uid @@ -0,0 +1 @@ +uid://df671mnqushqc diff --git a/addons/dialogic/Modules/Style/character_settings_style.gd b/addons/dialogic/Modules/Style/character_settings_style.gd index f594cf30..445de04e 100644 --- a/addons/dialogic/Modules/Style/character_settings_style.gd +++ b/addons/dialogic/Modules/Style/character_settings_style.gd @@ -12,7 +12,7 @@ func _get_title() -> String: func _ready() -> void: %StyleName.resource_icon = get_theme_icon("PopupMenu", "EditorIcons") - %StyleName.get_suggestions_func = get_style_suggestions + %StyleName.suggestions_func = get_style_suggestions func _load_character(character:DialogicCharacter) -> void: diff --git a/addons/dialogic/Modules/Style/character_settings_style.gd.uid b/addons/dialogic/Modules/Style/character_settings_style.gd.uid index 040fa49c..7862f411 100644 --- a/addons/dialogic/Modules/Style/character_settings_style.gd.uid +++ b/addons/dialogic/Modules/Style/character_settings_style.gd.uid @@ -1 +1 @@ -uid://b4dbbs0oeuh77 +uid://dbc2xad3oixyw diff --git a/addons/dialogic/Modules/Style/character_settings_style.tscn b/addons/dialogic/Modules/Style/character_settings_style.tscn index a953f836..60a9d75c 100644 --- a/addons/dialogic/Modules/Style/character_settings_style.tscn +++ b/addons/dialogic/Modules/Style/character_settings_style.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://fgplvp0f3giu"] -[ext_resource type="Script" uid="uid://b4dbbs0oeuh77" path="res://addons/dialogic/Modules/Style/character_settings_style.gd" id="2"] +[ext_resource type="Script" uid="uid://dbc2xad3oixyw" path="res://addons/dialogic/Modules/Style/character_settings_style.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="2_a46q0"] [node name="Style" type="VBoxContainer"] diff --git a/addons/dialogic/Modules/Style/event_style.gd.uid b/addons/dialogic/Modules/Style/event_style.gd.uid index 4c2c12c4..be248c3c 100644 --- a/addons/dialogic/Modules/Style/event_style.gd.uid +++ b/addons/dialogic/Modules/Style/event_style.gd.uid @@ -1 +1 @@ -uid://di2liywvvbhgc +uid://db0qg83hh428s diff --git a/addons/dialogic/Modules/Style/index.gd.uid b/addons/dialogic/Modules/Style/index.gd.uid index 8adf7de9..9269c17f 100644 --- a/addons/dialogic/Modules/Style/index.gd.uid +++ b/addons/dialogic/Modules/Style/index.gd.uid @@ -1 +1 @@ -uid://b74nhjvk3j215 +uid://cdiqm2ipo7k4w diff --git a/addons/dialogic/Modules/Style/node_style.gd.uid b/addons/dialogic/Modules/Style/node_style.gd.uid index f327b82d..824509b3 100644 --- a/addons/dialogic/Modules/Style/node_style.gd.uid +++ b/addons/dialogic/Modules/Style/node_style.gd.uid @@ -1 +1 @@ -uid://bl040syhccq05 +uid://dlrhbqth4gipl diff --git a/addons/dialogic/Modules/Style/subsystem_styles.gd b/addons/dialogic/Modules/Style/subsystem_styles.gd index a28d9c1d..64acfd21 100644 --- a/addons/dialogic/Modules/Style/subsystem_styles.gd +++ b/addons/dialogic/Modules/Style/subsystem_styles.gd @@ -8,6 +8,10 @@ signal style_changed(info:Dictionary) #region STATE #################################################################################################### +func _ready() -> void: + DialogicStylesUtil.update_style_directory() + + func clear_game_state(_clear_flag := DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void: pass @@ -33,7 +37,7 @@ func change_style(style_name := "", is_base_style := true) -> Node: ## [br] If [param state_reload] is true, the current state will be loaded into a new layout scenes nodes. ## That should not be done before calling start() or load() as it would be unnecessary or cause double-loading. func load_style(style_name := "", parent: Node = null, is_base_style := true, state_reload := false) -> Node: - var style := DialogicUtil.get_style_by_name(style_name) + var style := DialogicStylesUtil.get_style(style_name) var signal_info := {'style':style_name} dialogic.current_state_info['style'] = style_name @@ -51,7 +55,7 @@ func load_style(style_name := "", parent: Node = null, is_base_style := true, st return previous_layout # If this has the same scene setup, just apply the new overrides - elif previous_layout.get_meta('style') == style.get_inheritance_root(): + elif previous_layout.get_meta('style') == style.get_inheritance_root() or previous_layout.get_meta('style').get_inheritance_root() == style.get_inheritance_root(): DialogicUtil.apply_scene_export_overrides(previous_layout, style.get_layer_inherited_info("").overrides) var index := 0 for layer in previous_layout.get_layers(): @@ -92,7 +96,7 @@ func create_layout(style: DialogicStyle, parent: Node = null) -> DialogicLayoutB var base_scene: DialogicLayoutBase var base_layer_info := style.get_layer_inherited_info("") if base_layer_info.path.is_empty(): - base_scene = DialogicUtil.get_default_layout_base().instantiate() + base_scene = DialogicStylesUtil.get_default_layout_base().instantiate() else: base_scene = load(base_layer_info.path).instantiate() @@ -172,4 +176,8 @@ func get_first_node_in_layout(group_name: String) -> Node: return node return null + +func preload_style(name_or_path:String = "") -> void: + DialogicStylesUtil.start_style_preload(name_or_path) + #endregion diff --git a/addons/dialogic/Modules/Style/subsystem_styles.gd.uid b/addons/dialogic/Modules/Style/subsystem_styles.gd.uid index 74001f6c..e8424efd 100644 --- a/addons/dialogic/Modules/Style/subsystem_styles.gd.uid +++ b/addons/dialogic/Modules/Style/subsystem_styles.gd.uid @@ -1 +1 @@ -uid://d3wsgq8i1hlqn +uid://ct3rrlxpj2kxj diff --git a/addons/dialogic/Modules/StyleEditor/Components/style_browser.gd.uid b/addons/dialogic/Modules/StyleEditor/Components/style_browser.gd.uid index 96617904..cda2520d 100644 --- a/addons/dialogic/Modules/StyleEditor/Components/style_browser.gd.uid +++ b/addons/dialogic/Modules/StyleEditor/Components/style_browser.gd.uid @@ -1 +1 @@ -uid://bdmv5t6o4khle +uid://dpuqnw4cshljm diff --git a/addons/dialogic/Modules/StyleEditor/Components/style_browser.tscn b/addons/dialogic/Modules/StyleEditor/Components/style_browser.tscn index ac10e5c1..a0ae6088 100644 --- a/addons/dialogic/Modules/StyleEditor/Components/style_browser.tscn +++ b/addons/dialogic/Modules/StyleEditor/Components/style_browser.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=11 format=3 uid="uid://cs381i3h7sveq"] -[ext_resource type="Script" uid="uid://bdmv5t6o4khle" path="res://addons/dialogic/Modules/StyleEditor/Components/style_browser.gd" id="1_3sdb0"] +[ext_resource type="Script" uid="uid://dpuqnw4cshljm" path="res://addons/dialogic/Modules/StyleEditor/Components/style_browser.gd" id="1_3sdb0"] [sub_resource type="Gradient" id="Gradient_0o1u0"] colors = PackedColorArray(0.296448, 0.231485, 0.52887, 1, 0.100572, 0.303996, 0.476999, 1) diff --git a/addons/dialogic/Modules/StyleEditor/Components/style_browser_window.gd.uid b/addons/dialogic/Modules/StyleEditor/Components/style_browser_window.gd.uid index 24133bd5..d3397f16 100644 --- a/addons/dialogic/Modules/StyleEditor/Components/style_browser_window.gd.uid +++ b/addons/dialogic/Modules/StyleEditor/Components/style_browser_window.gd.uid @@ -1 +1 @@ -uid://brmb00ubiypwj +uid://i2qxk6l78uax diff --git a/addons/dialogic/Modules/StyleEditor/Components/style_layer_tree.gd.uid b/addons/dialogic/Modules/StyleEditor/Components/style_layer_tree.gd.uid index c31bc869..a6abdde9 100644 --- a/addons/dialogic/Modules/StyleEditor/Components/style_layer_tree.gd.uid +++ b/addons/dialogic/Modules/StyleEditor/Components/style_layer_tree.gd.uid @@ -1 +1 @@ -uid://c8fhdujj1gcfm +uid://orsplfberna diff --git a/addons/dialogic/Modules/StyleEditor/index.gd b/addons/dialogic/Modules/StyleEditor/index.gd index 21ffc383..f4b190be 100644 --- a/addons/dialogic/Modules/StyleEditor/index.gd +++ b/addons/dialogic/Modules/StyleEditor/index.gd @@ -1,3 +1,4 @@ +@tool extends DialogicIndexer func _get_editors() -> Array: diff --git a/addons/dialogic/Modules/StyleEditor/index.gd.uid b/addons/dialogic/Modules/StyleEditor/index.gd.uid index f538a335..cb60bb08 100644 --- a/addons/dialogic/Modules/StyleEditor/index.gd.uid +++ b/addons/dialogic/Modules/StyleEditor/index.gd.uid @@ -1 +1 @@ -uid://bsarruqlo1buy +uid://7oxkedvsovao diff --git a/addons/dialogic/Modules/StyleEditor/style_editor.gd b/addons/dialogic/Modules/StyleEditor/style_editor.gd index bff6c70e..4205be86 100644 --- a/addons/dialogic/Modules/StyleEditor/style_editor.gd +++ b/addons/dialogic/Modules/StyleEditor/style_editor.gd @@ -346,7 +346,7 @@ func _on_inheritance_index_pressed(index:int) -> void: func _on_start_styling_button_pressed() -> void: - var new_style := DialogicUtil.get_fallback_style().clone() + var new_style := DialogicStylesUtil.get_fallback_style().clone() find_parent('EditorView').godot_file_dialog( add_style_undoable.bind(new_style), diff --git a/addons/dialogic/Modules/StyleEditor/style_editor.gd.uid b/addons/dialogic/Modules/StyleEditor/style_editor.gd.uid index 92fa0a14..1c2a7d84 100644 --- a/addons/dialogic/Modules/StyleEditor/style_editor.gd.uid +++ b/addons/dialogic/Modules/StyleEditor/style_editor.gd.uid @@ -1 +1 @@ -uid://dk58bwcjna3j8 +uid://n7kjhd6h41ec diff --git a/addons/dialogic/Modules/StyleEditor/style_editor.tscn b/addons/dialogic/Modules/StyleEditor/style_editor.tscn index e93928ee..482b8010 100644 --- a/addons/dialogic/Modules/StyleEditor/style_editor.tscn +++ b/addons/dialogic/Modules/StyleEditor/style_editor.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=16 format=3 uid="uid://cx6h3tck10s1g"] -[ext_resource type="Script" uid="uid://dk58bwcjna3j8" path="res://addons/dialogic/Modules/StyleEditor/style_editor.gd" id="1_gy14f"] +[ext_resource type="Script" uid="uid://n7kjhd6h41ec" path="res://addons/dialogic/Modules/StyleEditor/style_editor.gd" id="1_gy14f"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_g4mnt"] -[ext_resource type="Script" uid="uid://b5ly5cuckde0w" path="res://addons/dialogic/Modules/StyleEditor/style_layer_editor.gd" id="3_iih7c"] -[ext_resource type="Script" uid="uid://c8fhdujj1gcfm" path="res://addons/dialogic/Modules/StyleEditor/Components/style_layer_tree.gd" id="4_kpoqn"] -[ext_resource type="Script" uid="uid://brmb00ubiypwj" path="res://addons/dialogic/Modules/StyleEditor/Components/style_browser_window.gd" id="5_qbwx0"] +[ext_resource type="Script" uid="uid://5j2ryc3uk1x3" path="res://addons/dialogic/Modules/StyleEditor/style_layer_editor.gd" id="3_iih7c"] +[ext_resource type="Script" uid="uid://orsplfberna" path="res://addons/dialogic/Modules/StyleEditor/Components/style_layer_tree.gd" id="4_kpoqn"] +[ext_resource type="Script" uid="uid://i2qxk6l78uax" path="res://addons/dialogic/Modules/StyleEditor/Components/style_browser_window.gd" id="5_qbwx0"] [ext_resource type="PackedScene" uid="uid://cs381i3h7sveq" path="res://addons/dialogic/Modules/StyleEditor/Components/style_browser.tscn" id="6_p6lia"] [sub_resource type="Image" id="Image_3rxjh"] diff --git a/addons/dialogic/Modules/StyleEditor/style_layer_editor.gd.uid b/addons/dialogic/Modules/StyleEditor/style_layer_editor.gd.uid index 3c8bc428..244a5260 100644 --- a/addons/dialogic/Modules/StyleEditor/style_layer_editor.gd.uid +++ b/addons/dialogic/Modules/StyleEditor/style_layer_editor.gd.uid @@ -1 +1 @@ -uid://b5ly5cuckde0w +uid://5j2ryc3uk1x3 diff --git a/addons/dialogic/Modules/Text/auto_advance.gd.uid b/addons/dialogic/Modules/Text/auto_advance.gd.uid index e4a36136..eecf3307 100644 --- a/addons/dialogic/Modules/Text/auto_advance.gd.uid +++ b/addons/dialogic/Modules/Text/auto_advance.gd.uid @@ -1 +1 @@ -uid://tesbnlcthnxh +uid://cj42eg6uts07a diff --git a/addons/dialogic/Modules/Text/auto_skip.gd.uid b/addons/dialogic/Modules/Text/auto_skip.gd.uid index f2b8724b..8d500c8a 100644 --- a/addons/dialogic/Modules/Text/auto_skip.gd.uid +++ b/addons/dialogic/Modules/Text/auto_skip.gd.uid @@ -1 +1 @@ -uid://b4qa43srwtbnf +uid://umnf6yt0lb06 diff --git a/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd b/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd index 3a211018..76222078 100644 --- a/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd +++ b/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd @@ -218,6 +218,7 @@ func set_default_button(enabled:bool) -> void: func preview() -> void: $Preview.load_overwrite(get_mood_info()) + $Preview._on_started_revealing_text() var preview_timer := Timer.new() DialogicUtil.update_timer_process_callback(preview_timer) add_child(preview_timer) diff --git a/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd.uid b/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd.uid index bac4839d..cf0f6bd8 100644 --- a/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd.uid +++ b/addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd.uid @@ -1 +1 @@ -uid://x84nluahuf1e +uid://6qkd50m2lqnx diff --git a/addons/dialogic/Modules/Text/character_settings/character_moods_settings.tscn b/addons/dialogic/Modules/Text/character_settings/character_moods_settings.tscn index 59e0475f..fd515420 100644 --- a/addons/dialogic/Modules/Text/character_settings/character_moods_settings.tscn +++ b/addons/dialogic/Modules/Text/character_settings/character_moods_settings.tscn @@ -1,9 +1,9 @@ [gd_scene load_steps=9 format=3 uid="uid://8ad1pwbjuqpt"] -[ext_resource type="Script" uid="uid://x84nluahuf1e" path="res://addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd" id="1_3px07"] +[ext_resource type="Script" uid="uid://6qkd50m2lqnx" path="res://addons/dialogic/Modules/Text/character_settings/character_moods_settings.gd" id="1_3px07"] [ext_resource type="PackedScene" uid="uid://7mvxuaulctcq" path="res://addons/dialogic/Editor/Events/Fields/field_file.tscn" id="2_e1vyd"] [ext_resource type="PackedScene" uid="uid://kdpp3mibml33" path="res://addons/dialogic/Editor/Events/Fields/field_number.tscn" id="3_yjcns"] -[ext_resource type="Script" uid="uid://bkfrnlul8c6cv" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="5_yscws"] +[ext_resource type="Script" uid="uid://dpv2dfiv5dhmr" path="res://addons/dialogic/Modules/Text/node_type_sound.gd" id="5_yscws"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_y7t05"] content_margin_left = 10.0 diff --git a/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd b/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd index 9a20c07c..5609e1b2 100644 --- a/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd +++ b/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd @@ -7,7 +7,7 @@ func _get_title() -> String: func _ready() -> void: - %PortraitMood.get_suggestions_func = mood_suggestions + %PortraitMood.suggestions_func = mood_suggestions %PortraitMood.resource_icon = get_theme_icon("AudioStreamPlayer", "EditorIcons") diff --git a/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd.uid b/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd.uid index f2ec94bd..c75c6aaa 100644 --- a/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd.uid +++ b/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd.uid @@ -1 +1 @@ -uid://b6fg02bv71snt +uid://vphe6s7nv242 diff --git a/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.tscn b/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.tscn index 3383d085..e6716c9d 100644 --- a/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.tscn +++ b/addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=3 format=3 uid="uid://bvfiv5uhmkqq7"] -[ext_resource type="Script" uid="uid://b6fg02bv71snt" path="res://addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd" id="1_5ni5u"] +[ext_resource type="Script" uid="uid://vphe6s7nv242" path="res://addons/dialogic/Modules/Text/character_settings/character_portrait_mood_settings.gd" id="1_5ni5u"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="1_oggvu"] [node name="Typing Sound Mood" type="HBoxContainer"] diff --git a/addons/dialogic/Modules/Text/event_text.gd b/addons/dialogic/Modules/Text/event_text.gd index 9dd7e72a..7e29d4aa 100644 --- a/addons/dialogic/Modules/Text/event_text.gd +++ b/addons/dialogic/Modules/Text/event_text.gd @@ -17,6 +17,7 @@ var text := "" ## it will play. var character: DialogicCharacter = null ## If a character is set, this setting can change the portrait of that character. +## If a runtime-character is created, the portrait can instead be a color (hex or color name). var portrait := "" ### Helpers @@ -24,15 +25,15 @@ var portrait := "" ## Used to set the character resource from the unique name identifier and vice versa var character_identifier: String: get: - if character: - var identifier := DialogicResourceUtil.get_unique_identifier(character.resource_path) + if character and not "{" in character_identifier: + var identifier := character.get_identifier() if not identifier.is_empty(): return identifier return character_identifier set(value): character_identifier = value character = DialogicResourceUtil.get_character_resource(value) - if not character.portraits.has(portrait): + if Engine.is_editor_hint() and ((not character) or (character and not character.portraits.has(portrait))): portrait = "" ui_update_needed.emit() @@ -51,44 +52,65 @@ func _clear_state() -> void: dialogic.current_state_info.erase('text_sub_idx') _disconnect_signals() + func _execute() -> void: if text.is_empty(): finish() return - if (not character or character.custom_info.get('style', '').is_empty()) and dialogic.has_subsystem('Styles'): - # if previous characters had a custom style change back to base style - if dialogic.current_state_info.get('base_style') != dialogic.current_state_info.get('style'): - dialogic.Styles.change_style(dialogic.current_state_info.get('base_style', 'Default')) - await dialogic.get_tree().process_frame + ## If the speaker is provided as an expression, parse it now. + if "{" in character_identifier: + character = null + var character_name: String = dialogic.Expressions.execute_string(character_identifier) + get_or_create_character(character_name) - var character_name_text := dialogic.Text.get_character_name_parsed(character) - if character: - if dialogic.has_subsystem('Styles') and character.custom_info.get('style', null): - dialogic.Styles.change_style(character.custom_info.style, false) - await dialogic.get_tree().process_frame + ## Change Portrait and Active Speaker + if dialogic.has_subsystem("Portraits"): + if character: + dialogic.Portraits.change_speaker(character, portrait) - if portrait and dialogic.has_subsystem('Portraits') and dialogic.Portraits.is_character_joined(character): - dialogic.Portraits.change_character_portrait(character, portrait) - dialogic.Portraits.change_speaker(character, portrait) - var check_portrait: String = portrait if !portrait.is_empty() else dialogic.current_state_info['portraits'].get(character.resource_path, {}).get('portrait', '') + if portrait and dialogic.Portraits.is_character_joined(character): + dialogic.Portraits.change_character_portrait(character, portrait) - if check_portrait and character.portraits.get(check_portrait, {}).get('sound_mood', '') in character.custom_info.get('sound_moods', {}): - dialogic.Text.update_typing_sound_mood(character.custom_info.get('sound_moods', {}).get(character.portraits[check_portrait].get('sound_mood', {}), {})) - elif !character.custom_info.get('sound_mood_default', '').is_empty(): - dialogic.Text.update_typing_sound_mood(character.custom_info.get('sound_moods', {}).get(character.custom_info.get('sound_mood_default'), {})) else: - dialogic.Text.update_typing_sound_mood() + dialogic.Portraits.change_speaker(null) + ## Change and Type Sound Mood + if character: dialogic.Text.update_name_label(character) + + var current_portrait: String = portrait + if portrait.is_empty(): + current_portrait = dialogic.current_state_info["portraits"].get(character.get_identifier(), {}).get("portrait", "") + + var current_portrait_sound_mood: String = character.portraits.get(current_portrait, {}).get("sound_mood", "") + dialogic.Text.update_typing_sound_mood_from_character(character, current_portrait_sound_mood) + else: - dialogic.Portraits.change_speaker(null) dialogic.Text.update_name_label(null) dialogic.Text.update_typing_sound_mood() + + ## Handle style changes + if dialogic.has_subsystem("Styles"): + var current_base_style: String = dialogic.current_state_info.get("base_style") + var current_style: String = dialogic.current_state_info.get("style", "") + var character_style: String = "" if not character else character.custom_info.get("style", "") + + ## Change back to base style, if another characters style is currently used + if (not character or character_style.is_empty()) and (current_base_style != current_style): + dialogic.Styles.change_style(dialogic.current_state_info.get("base_style", "Default")) + await dialogic.get_tree().process_frame + + ## Change to the characters style if this character has one + elif character and not character_style.is_empty(): + dialogic.Styles.change_style(character_style, false) + await dialogic.get_tree().process_frame + _connect_signals() + var character_name_text := dialogic.Text.get_character_name_parsed(character) var final_text: String = get_property_translated('text') if ProjectSettings.get_setting('dialogic/text/split_at_new_lines', false): match ProjectSettings.get_setting('dialogic/text/split_at_new_lines_as', 0): @@ -114,10 +136,10 @@ func _execute() -> void: dialogic.current_state_info['text_sub_idx'] = section_idx - var segment: String = dialogic.Text.parse_text(split_text[section_idx][0]) + var segment: String = dialogic.Text.parse_text(split_text[section_idx][0], 0) var is_append: bool = split_text[section_idx][1] - final_text = segment + final_text = ProjectSettings.get_setting("dialogic/text/dialog_text_prefix", "")+segment dialogic.Text.about_to_show_text.emit({'text':final_text, 'character':character, 'portrait':portrait, 'append': is_append}) await dialogic.Text.update_textbox(final_text, false) @@ -126,6 +148,8 @@ func _execute() -> void: _try_play_current_line_voice() final_text = dialogic.Text.update_dialog_text(final_text, false, is_append) + dialogic.Text.text_started.emit({'text':final_text, 'character':character, 'portrait':portrait, 'append': is_append}) + _mark_as_read(character_name_text, final_text) # We must skip text animation before we potentially return when there @@ -257,22 +281,23 @@ func _init() -> void: event_category = "Main" event_sorting_index = 0 expand_by_default = true - help_page_path = "https://docs.dialogic.pro/writing-text-events.html" + help_page_path = "https://docs.dialogic.pro/writing-texts.html" -################################################################################ -## SAVING/LOADING +#region SAVING/LOADING ################################################################################ func to_text() -> String: - var result := text.replace('\n', '\\\n') + var result := text.replace('\n', '\\\n').strip_edges(false).trim_suffix("\\") result = result.replace(':', '\\:') if result.is_empty(): result = "" - if character: - var name := DialogicResourceUtil.get_unique_identifier(character.resource_path) + if character or character_identifier: + var name := character_identifier + if character: + name = character.get_identifier() if name.count(" ") > 0: name = '"' + name + '"' if not portrait.is_empty(): @@ -293,27 +318,45 @@ func from_text(string:String) -> void: character = DialogicResourceUtil.get_character_resource(character_identifier) var result := regex.search(string.trim_prefix('\\')) + + if result.get_string('portrait'): + portrait = result.get_string('portrait').strip_edges().trim_prefix('(').trim_suffix(')') + if result and not result.get_string('name').is_empty(): var name := result.get_string('name').strip_edges() if name == '_': character = null + elif "{" in name: + ## If it's an expression, we load the character in _execute. + character_identifier = name + character = null else: - character = DialogicResourceUtil.get_character_resource(name) + get_or_create_character(name) - if character == null and Engine.is_editor_hint() == false: - character = DialogicCharacter.new() - character.display_name = name - character.resource_path = "user://"+name+".dch" - DialogicResourceUtil.add_resource_to_directory(character.resource_path, DialogicResourceUtil.get_character_directory()) + if not result: + return - if !result.get_string('portrait').is_empty(): - portrait = result.get_string('portrait').strip_edges().trim_prefix('(').trim_suffix(')') + text = result.get_string('text').replace("\\\n", "\n").replace('\\:', ':').strip_edges().trim_prefix('\\') + if text == '': + text = "" - if result: - text = result.get_string('text').replace("\\\n", "\n").replace('\\:', ':').strip_edges().trim_prefix('\\') - if text == '': - text = "" + +func get_or_create_character(name:String) -> void: + character = DialogicResourceUtil.get_character_resource(name) + + if character == null: + if Engine.is_editor_hint() == false: + character = DialogicCharacter.new() + character.display_name = name + character.set_identifier(name) + if portrait: + if "{" in portrait: + character.color = Color(dialogic.Expressions.execute_string(portrait)) + else: + character.color = Color(portrait) + else: + character_identifier = name func is_valid_event(_string:String) -> bool: @@ -329,8 +372,8 @@ func is_string_full_event(string:String) -> bool: func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info - "character" : {"property": "character_identifier", "default": ""}, - "portrait" : {"property": "portrait", "default": ""}, + "character" : {"property": "character_identifier", "default": "", "ext_file":true}, + "portrait" : {"property": "portrait", "default": ""}, } #endregion @@ -364,7 +407,7 @@ func build_event_editor() -> void: {'file_extension' : '.dch', 'mode' : 2, 'suggestions_func' : get_character_suggestions, - 'empty_text' : '(No one)', + 'placeholder' : '(No one)', 'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg")}, 'do_any_characters_exist()') add_header_edit('portrait', ValueType.DYNAMIC_OPTIONS, {'suggestions_func' : get_portrait_suggestions, @@ -384,8 +427,13 @@ func do_any_characters_exist() -> bool: func get_character_suggestions(search_text:String) -> Dictionary: - return DialogicUtil.get_character_suggestions(search_text, character, true, false, editor_node) - + var suggestions := DialogicUtil.get_character_suggestions(search_text, character, true, false, editor_node) + if search_text and not search_text in suggestions: + suggestions[search_text] = { + "value":search_text, + "tooltip": "A temporary character, created on the spot.", + "editor_icon":["GuiEllipsis", "EditorIcons"]} + return suggestions func get_portrait_suggestions(search_text:String) -> Dictionary: return DialogicUtil.get_portrait_suggestions(search_text, character, true, "Don't change") @@ -429,7 +477,7 @@ func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:Str func _get_start_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit) -> void: - CodeCompletionHelper.suggest_characters(TextNode, CodeEdit.KIND_CLASS, true) + CodeCompletionHelper.suggest_characters(TextNode, CodeEdit.KIND_CLASS, self) func suggest_bbcode(TextNode:CodeEdit): @@ -462,10 +510,10 @@ var text_effect_color := Color('#898276') func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary: load_text_effects() if text_random_word_regex.get_pattern().is_empty(): - text_random_word_regex.compile("(?]+(\\/[^\\>]*)\\>") + text_random_word_regex.compile(r"(?]+(\/[^\>]*)\>") var result := regex.search(line) - if !result: + if not result: return dict if Highlighter.mode == Highlighter.Modes.FULL_HIGHLIGHTING: if result.get_string('name'): @@ -475,24 +523,29 @@ func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, li dict[result.get_start('portrait')] = {"color":Highlighter.character_portrait_color} dict[result.get_end('portrait')] = {"color":Highlighter.normal_color} if result.get_string('text'): - var effects_result := text_effects_regex.search_all(line) - for eff in effects_result: - dict[eff.get_start()] = {"color":text_effect_color} - dict[eff.get_end()] = {"color":Highlighter.normal_color} - dict = Highlighter.color_region(dict, Highlighter.variable_color, line, '{', '}', result.get_start('text')) + ## Color the random selection modifier for replace_mod_match in text_random_word_regex.search_all(result.get_string('text')): var color: Color = Highlighter.string_color color = color.lerp(Highlighter.normal_color, 0.4) dict[replace_mod_match.get_start()+result.get_start('text')] = {'color':Highlighter.string_color} var offset := 1 - for b in replace_mod_match.get_string().trim_suffix('>').trim_prefix('<').split('/'): + for b:RegExMatch in RegEx.create_from_string(r"(\[[^\]]*\]|[^\/]|\/\/)+").search_all(replace_mod_match.get_string().trim_prefix("<").trim_suffix(">")): color.h = wrap(color.h+0.2, 0, 1) dict[replace_mod_match.get_start()+result.get_start('text')+offset] = {'color':color} - offset += len(b) + offset += len(b.get_string()) dict[replace_mod_match.get_start()+result.get_start('text')+offset] = {'color':Highlighter.string_color} offset += 1 dict[replace_mod_match.get_end()+result.get_start('text')] = {'color':Highlighter.normal_color} + + ## Color bbcode and text effects + var effects_result := text_effects_regex.search_all(line) + for eff in effects_result: + var prev_color: Color = Highlighter.dict_get_color_at_column(dict, eff.get_start()) + dict[eff.get_start()] = {"color":text_effect_color.lerp(prev_color, 0.4)} + dict[eff.get_end()] = {"color":prev_color} + dict = Highlighter.color_region(dict, Highlighter.variable_color, line, '{', '}', result.get_start('text')) + return dict #endregion diff --git a/addons/dialogic/Modules/Text/event_text.gd.uid b/addons/dialogic/Modules/Text/event_text.gd.uid index 62e9924c..c6375f47 100644 --- a/addons/dialogic/Modules/Text/event_text.gd.uid +++ b/addons/dialogic/Modules/Text/event_text.gd.uid @@ -1 +1 @@ -uid://v1q0c4baexov +uid://datmius068d8h diff --git a/addons/dialogic/Modules/Text/index.gd.uid b/addons/dialogic/Modules/Text/index.gd.uid index 4da0e4ed..739d5071 100644 --- a/addons/dialogic/Modules/Text/index.gd.uid +++ b/addons/dialogic/Modules/Text/index.gd.uid @@ -1 +1 @@ -uid://8cq5nqyn5kaa +uid://bthukngr7e6io diff --git a/addons/dialogic/Modules/Text/manual_advance.gd.uid b/addons/dialogic/Modules/Text/manual_advance.gd.uid index 433f348a..dce0d4dd 100644 --- a/addons/dialogic/Modules/Text/manual_advance.gd.uid +++ b/addons/dialogic/Modules/Text/manual_advance.gd.uid @@ -1 +1 @@ -uid://d3jie3vjagf3x +uid://dbx6k01krd1xx diff --git a/addons/dialogic/Modules/Text/node_dialog_text.gd b/addons/dialogic/Modules/Text/node_dialog_text.gd index ac4cf92c..b8878e16 100644 --- a/addons/dialogic/Modules/Text/node_dialog_text.gd +++ b/addons/dialogic/Modules/Text/node_dialog_text.gd @@ -52,6 +52,12 @@ func _ready() -> void: textbox_root.hide() text = "" + var custom_bbcode_effects: Array = ProjectSettings.get_setting("dialogic/text/custom_bbcode_effects", "").split(",", false) + for i in custom_bbcode_effects: + var x : Resource = load(i.strip_edges()) + if x is RichTextEffect: + custom_effects.append(x) + # this is called by the DialogicGameHandler to set text @@ -60,6 +66,8 @@ func reveal_text(_text: String, keep_previous:=false) -> void: return show() + custom_fx_reset() + if !keep_previous: text = _text base_visible_characters = 0 @@ -73,6 +81,7 @@ func reveal_text(_text: String, keep_previous:=false) -> void: else: base_visible_characters = len(text) visible_characters = len(get_parsed_text()) + custom_fx_update() text = text + _text # If Auto-Skip is enabled and we append the text (keep_previous), @@ -113,16 +122,21 @@ func continue_reveal() -> void: if visible_characters > -1 and visible_characters <= len(get_parsed_text()): continued_revealing_text.emit(get_parsed_text()[visible_characters-1]) + + custom_fx_update() else: - finish_text() + finish_text(true) # if the text finished organically, add a small input block # this prevents accidental skipping when you expected the text to be longer DialogicUtil.autoload().Inputs.block_input(ProjectSettings.get_setting('dialogic/text/advance_delay', 0.1)) ## Reveals the entire text instantly. -func finish_text() -> void: +func finish_text(is_organic := false) -> void: visible_ratio = 1 + custom_fx_update() + if not is_organic: + custom_fx_skip() DialogicUtil.autoload().Text.execute_effects(-1, self, true) revealing = false DialogicUtil.autoload().current_state = DialogicGameHandler.States.IDLE @@ -156,3 +170,21 @@ func _on_meta_clicked(_meta:Variant) -> void: ## Handle mouse input func on_gui_input(event:InputEvent) -> void: DialogicUtil.autoload().Inputs.handle_node_gui_input(event) + + +func custom_fx_update() -> void: + for effect in custom_effects: + if "visible_characters" in effect: + effect.visible_characters = visible_characters + + +func custom_fx_reset() -> void: + for effect in custom_effects: + if effect.has_method("reset"): + effect.reset() + + +func custom_fx_skip() -> void: + for effect in custom_effects: + if effect.has_method("skip"): + effect.skip() diff --git a/addons/dialogic/Modules/Text/node_dialog_text.gd.uid b/addons/dialogic/Modules/Text/node_dialog_text.gd.uid index 81ed1041..5a13d211 100644 --- a/addons/dialogic/Modules/Text/node_dialog_text.gd.uid +++ b/addons/dialogic/Modules/Text/node_dialog_text.gd.uid @@ -1 +1 @@ -uid://ddkvkdb6nxtyi +uid://drhfq6rmdeuri diff --git a/addons/dialogic/Modules/Text/node_input.gd.uid b/addons/dialogic/Modules/Text/node_input.gd.uid index 2e1727d3..b20561cb 100644 --- a/addons/dialogic/Modules/Text/node_input.gd.uid +++ b/addons/dialogic/Modules/Text/node_input.gd.uid @@ -1 +1 @@ -uid://do47nn7beuhn5 +uid://ctog34kdg222q diff --git a/addons/dialogic/Modules/Text/node_name_label.gd.uid b/addons/dialogic/Modules/Text/node_name_label.gd.uid index edaf6fff..81627e7c 100644 --- a/addons/dialogic/Modules/Text/node_name_label.gd.uid +++ b/addons/dialogic/Modules/Text/node_name_label.gd.uid @@ -1 +1 @@ -uid://be3h8wr0w68dx +uid://bak74s0kcr0ao diff --git a/addons/dialogic/Modules/Text/node_next_indicator.gd.uid b/addons/dialogic/Modules/Text/node_next_indicator.gd.uid index de77ed62..aee0c192 100644 --- a/addons/dialogic/Modules/Text/node_next_indicator.gd.uid +++ b/addons/dialogic/Modules/Text/node_next_indicator.gd.uid @@ -1 +1 @@ -uid://dk0xy5qppo033 +uid://dve1vwse2peji diff --git a/addons/dialogic/Modules/Text/node_type_sound.gd.uid b/addons/dialogic/Modules/Text/node_type_sound.gd.uid index 0f22ea51..c6dacefb 100644 --- a/addons/dialogic/Modules/Text/node_type_sound.gd.uid +++ b/addons/dialogic/Modules/Text/node_type_sound.gd.uid @@ -1 +1 @@ -uid://bkfrnlul8c6cv +uid://dpv2dfiv5dhmr diff --git a/addons/dialogic/Modules/Text/settings_text.gd b/addons/dialogic/Modules/Text/settings_text.gd index 4a2cd779..8ef80651 100644 --- a/addons/dialogic/Modules/Text/settings_text.gd +++ b/addons/dialogic/Modules/Text/settings_text.gd @@ -12,6 +12,8 @@ const _SETTING_TEXT_REVEAL_SKIPPABLE_DELAY := 'dialogic/text/text_reveal_skip_d const _SETTING_TEXT_ADVANCE_DELAY := 'dialogic/text/advance_delay' const _SETTING_AUTOCOLOR_NAMES := 'dialogic/text/autocolor_names' +const _SETTING_TEXT_PREFIX := 'dialogic/text/dialog_text_prefix' +const _SETTING_CUSTOM_BBCODE_EFFECTS := 'dialogic/text/custom_bbcode_effects' const _SETTING_SPLIT_AT_NEW_LINES := 'dialogic/text/split_at_new_lines' const _SETTING_SPLIT_AT_NEW_LINES_AS := 'dialogic/text/split_at_new_lines_as' @@ -44,6 +46,8 @@ func _ready() -> void: %AdvanceDelay.value_changed.connect(_on_float_set.bind(_SETTING_TEXT_ADVANCE_DELAY)) %AutocolorNames.toggled.connect(_on_bool_set.bind(_SETTING_AUTOCOLOR_NAMES)) + %TextPrefix.text_changed.connect(_on_string_set.bind(_SETTING_TEXT_PREFIX)) + %CustomBBCodeEffects.text_changed.connect(_on_string_set.bind(_SETTING_CUSTOM_BBCODE_EFFECTS)) %NewEvents.toggled.connect(_on_bool_set.bind(_SETTING_SPLIT_AT_NEW_LINES)) @@ -62,13 +66,15 @@ func _refresh() -> void: %InputAction.resource_icon = get_theme_icon(&"Mouse", &"EditorIcons") %InputAction.set_value(ProjectSettings.get_setting(_SETTING_INPUT_ACTION, &'dialogic_default_action')) - %InputAction.get_suggestions_func = suggest_actions + %InputAction.suggestions_func = suggest_actions %Skippable.button_pressed = ProjectSettings.get_setting(_SETTING_TEXT_REVEAL_SKIPPABLE, true) %SkippableDelay.value = ProjectSettings.get_setting(_SETTING_TEXT_REVEAL_SKIPPABLE_DELAY, 0.1) %AdvanceDelay.value = ProjectSettings.get_setting(_SETTING_TEXT_ADVANCE_DELAY, 0.1) %AutocolorNames.button_pressed = ProjectSettings.get_setting(_SETTING_AUTOCOLOR_NAMES, false) + %TextPrefix.text = ProjectSettings.get_setting(_SETTING_TEXT_PREFIX, "") + %CustomBBCodeEffects.text = ProjectSettings.get_setting(_SETTING_CUSTOM_BBCODE_EFFECTS, "") %NewEvents.button_pressed = ProjectSettings.get_setting(_SETTING_SPLIT_AT_NEW_LINES, false) %NewEventOption.select(ProjectSettings.get_setting(_SETTING_SPLIT_AT_NEW_LINES_AS, 0)) @@ -115,14 +121,18 @@ func _on_float_set(value:float, setting:String) -> void: ProjectSettings.save() +func _on_string_set(value:String, setting:String) -> void: + ProjectSettings.set_setting(setting, value) + ProjectSettings.save() + #region BEHAVIOUR ################################################################################ -func _on_InputAction_value_changed(property_name:String, value:String) -> void: +func _on_InputAction_value_changed(_property_name:String, value:String) -> void: ProjectSettings.set_setting(_SETTING_INPUT_ACTION, value) ProjectSettings.save() -func suggest_actions(search:String) -> Dictionary: +func suggest_actions(_search:String) -> Dictionary: var suggs := {} for prop in ProjectSettings.get_property_list(): if prop.name.begins_with('input/') and not prop.name.begins_with('input/ui_') : @@ -237,4 +247,3 @@ func _on_remove_autopauses_set_pressed(index: int) -> void: for key in autopause_sets[index]: autopause_sets[index][key].queue_free() autopause_sets.erase(index) - diff --git a/addons/dialogic/Modules/Text/settings_text.gd.uid b/addons/dialogic/Modules/Text/settings_text.gd.uid index 5b935eac..cb7e9625 100644 --- a/addons/dialogic/Modules/Text/settings_text.gd.uid +++ b/addons/dialogic/Modules/Text/settings_text.gd.uid @@ -1 +1 @@ -uid://b5ltnfwvbfbfc +uid://cdxck874xobqh diff --git a/addons/dialogic/Modules/Text/settings_text.tscn b/addons/dialogic/Modules/Text/settings_text.tscn index 12309150..af37c3b0 100644 --- a/addons/dialogic/Modules/Text/settings_text.tscn +++ b/addons/dialogic/Modules/Text/settings_text.tscn @@ -1,26 +1,13 @@ -[gd_scene load_steps=6 format=3 uid="uid://cf3qks3v18xmr"] +[gd_scene load_steps=4 format=3 uid="uid://cf3qks3v18xmr"] -[ext_resource type="Script" uid="uid://b5ltnfwvbfbfc" path="res://addons/dialogic/Modules/Text/settings_text.gd" id="2"] +[ext_resource type="Script" uid="uid://cdxck874xobqh" path="res://addons/dialogic/Modules/Text/settings_text.gd" id="2"] [ext_resource type="PackedScene" uid="uid://dpwhshre1n4t6" path="res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn" id="3"] [ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="3_s7xhj"] -[sub_resource type="Image" id="Image_15d2e"] -data = { -"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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", -"height": 16, -"mipmaps": false, -"width": 16 -} - -[sub_resource type="ImageTexture" id="ImageTexture_3xcp4"] -image = SubResource("Image_15d2e") - [node name="DialogText" type="VBoxContainer"] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -offset_bottom = -156.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("2") @@ -48,7 +35,7 @@ text = "Default letter speed" [node name="HintTooltip2" parent="VBoxContainer/VBox/DefaultSpeedLabel" instance=ExtResource("3_s7xhj")] layout_mode = 2 tooltip_text = "The speed in seconds per character. A speed of 0 will reveal the full text instantly (still taking pauses into consideration)." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "The speed in seconds per character. A speed of 0 will reveal the full text instantly (still taking pauses into consideration)." [node name="DefaultSpeed" type="SpinBox" parent="VBoxContainer/VBox"] @@ -67,7 +54,7 @@ text = "Input action" layout_mode = 2 tooltip_text = "The action that skips text and generally advances to the next event. You can modify actions in the Project Settings > Input Map." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "The action that skips text and generally advances to the next event. You can modify actions in the Project Settings > Input Map." @@ -87,7 +74,7 @@ text = "Text Reveal Skippable" layout_mode = 2 tooltip_text = "If enabled the revealing of text can be skipped with the input action. If disabled you can only advance to the next event when revealing has finnished." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "If enabled the revealing of text can be skipped with the input action. If disabled you can only advance to the next event when revealing has finnished." @@ -110,7 +97,7 @@ layout_mode = 2 tooltip_text = "Delay before you can skip. Use this to prevent users from skipping through your timeline to quickly." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "Delay before you can skip. Use this to prevent users from skipping through your timeline too quickly." @@ -134,7 +121,7 @@ layout_mode = 2 tooltip_text = "Delay before you can advance (if the text finishes revealing on its own). This is used to prevent players from advancing when they actually wanted to skip the revealing, but did so very shortly after the text was already fully revealed." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "Delay before you can advance (only if the text finishes revealing on its own). This is used to prevent players from advancing when they actually wanted to skip the revealing, but did so very shortly after the text was already fully revealed." @@ -156,13 +143,47 @@ text = "Autocolor names" [node name="HintTooltip5" parent="VBoxContainer/VBox/ColorNames" instance=ExtResource("3_s7xhj")] layout_mode = 2 tooltip_text = "If enabled character names will be colored in the characters color in text events." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "If enabled character names will be colored in the characters color in text events." [node name="AutocolorNames" type="CheckBox" parent="VBoxContainer/VBox"] unique_name_in_owner = true layout_mode = 2 +[node name="TextPrefixLabel" type="HBoxContainer" parent="VBoxContainer/VBox"] +layout_mode = 2 + +[node name="Label4" type="Label" parent="VBoxContainer/VBox/TextPrefixLabel"] +layout_mode = 2 +text = "Text prefix" + +[node name="HintTooltip5" parent="VBoxContainer/VBox/TextPrefixLabel" instance=ExtResource("3_s7xhj")] +layout_mode = 2 +tooltip_text = "If enabled character names will be colored in the characters color in text events." +texture = null +hint_text = "This is put before the text. Can be used to apply bbcode effects to all texts." + +[node name="TextPrefix" type="LineEdit" parent="VBoxContainer/VBox"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="BBCodeEffectLabel" type="HBoxContainer" parent="VBoxContainer/VBox"] +layout_mode = 2 + +[node name="Label4" type="Label" parent="VBoxContainer/VBox/BBCodeEffectLabel"] +layout_mode = 2 +text = "Custom BBCode Effects" + +[node name="HintTooltip5" parent="VBoxContainer/VBox/BBCodeEffectLabel" instance=ExtResource("3_s7xhj")] +layout_mode = 2 +tooltip_text = "This is put before the text. Can be used to apply bbcode effects to all texts." +texture = null +hint_text = "Supply a list of bbcode effect resources (paths or uids) separated by comma." + +[node name="CustomBBCodeEffects" type="LineEdit" parent="VBoxContainer/VBox"] +unique_name_in_owner = true +layout_mode = 2 + [node name="HBoxContainer3" type="HBoxContainer" parent="VBoxContainer/VBox"] layout_mode = 2 @@ -174,7 +195,7 @@ text = "New lines as new events" layout_mode = 2 tooltip_text = "If enabled dialogic, new lines will be treated as [n] effects, seemingly waiting for input before starting a new text." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "If enabled dialogic, new lines will be treated as [n] effects, seemingly waiting for input before starting a new text." @@ -188,9 +209,9 @@ layout_mode = 2 [node name="NewEventOption" type="OptionButton" parent="VBoxContainer/VBox/HBoxContainer4"] unique_name_in_owner = true layout_mode = 2 -item_count = 2 selected = 0 fit_to_longest_item = false +item_count = 2 popup/item_0/text = "As new event" popup/item_0/id = 0 popup/item_1/text = "Appended" @@ -219,7 +240,7 @@ These add up, so if any of them is true, Auto-Advance will happen. Unless manual advancement is disabled, the Auto-Advance time can always be skipped by the player. The Auto-Advance will wait for Voice audio to finish playing. This behaviour can be disabled via code. " -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "Autoadvance is the concept of automatically progressing to the next event upon completing text display, usually after a certain delay. You can enabled Auto-Advance from code using either: @@ -245,7 +266,7 @@ text = "Base Delay" [node name="HintTooltip" parent="VBoxContainer/AutoadvanceSettings/HBox_BaseDelay2" instance=ExtResource("3_s7xhj")] layout_mode = 2 tooltip_text = "This is the base delay for autoadvancment." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "This is the base delay for autoadvancment." [node name="FixedDelay" type="SpinBox" parent="VBoxContainer/AutoadvanceSettings"] @@ -268,7 +289,7 @@ layout_mode = 2 tooltip_text = "An additional delay per character or word can be added. Note: When changing values via code, you can actually use both modes simultaniously." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "An additional delay per character or word can be added. Note: When changing values via code, you can actually use both modes simultaniously." @@ -279,9 +300,9 @@ layout_mode = 2 [node name="AdditionalDelayMode" type="OptionButton" parent="VBoxContainer/AutoadvanceSettings/HBoxContainer2"] unique_name_in_owner = true layout_mode = 2 -item_count = 3 selected = 0 fit_to_longest_item = false +item_count = 3 popup/item_0/text = "None" popup/item_0/id = 0 popup/item_1/text = "Per Word" @@ -308,7 +329,7 @@ tooltip_text = "An ignored character will add no delay, this is useful to exclud If disabled, the general line of text length will be used, stripping the BBCode tags first. If enabled, the text will be scanned and the matching characters will be skipped." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "An ignored character will add no delay, this is useful to exclude interpunction and whitespaces. If disabled, the general line of text length will be used, stripping the BBCode tags first. @@ -336,7 +357,7 @@ layout_mode = 2 tooltip_text = "While you would usually enable Auto-Advance via code, if this is true it will be initially enabled. This kind of Auto-Advance (system) only stops when disabled via code. " -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "While you would usually enable Auto-Advance via code, if this is true it will be initially enabled. This kind of Auto-Advance (system) only stops when disabled via code. " @@ -366,7 +387,7 @@ Dialogic.Inputs.auto_skip.enabled = true By default, Auto-Skip will cancel on user input. You can disable this by calling: Dialogic.Inputs.auto_skip.disable_on_user_input = false" -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "Auto-Skip is the concept of automatically skipping Timeline Events to the next unread Text Event or Event demanding user inputs (e.g. Choice, Wait Input, and Text Input). You can enable Auto-Skip from code via: @@ -393,7 +414,7 @@ tooltip_text = "The time until Auto-Skip will execute the next event. If this is set to 0.1s, each event should finish within that time. Custom events must respect this time, built-in events already handle Auto-Skip." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "The time until Auto-Skip will execute the next event. If this is set to 0.1s, each event should finish within that time. @@ -424,7 +445,7 @@ tooltip_text = "Adds pauses after certain letters. Each set can contain multiple letters that will (individually) have a pause of the given length added after them." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "Adds pauses after certain letters. Each set can contain multiple letters that will (individually) @@ -452,7 +473,7 @@ text = "Absolute auto-pause times" [node name="HintTooltip7" parent="VBoxContainer/HBoxContainer3" instance=ExtResource("3_s7xhj")] layout_mode = 2 tooltip_text = "If not enabled autopauses will be multiplied by the speed and user speed. When enabled those will be ignored." -texture = SubResource("ImageTexture_3xcp4") +texture = null hint_text = "If not enabled autopauses will be multiplied by the speed and user speed. When enabled those will be ignored." [node name="AutoPausesAbsolute" type="CheckBox" parent="VBoxContainer/HBoxContainer3"] diff --git a/addons/dialogic/Modules/Text/subsystem_text.gd b/addons/dialogic/Modules/Text/subsystem_text.gd index 4494246a..2d0e7db6 100644 --- a/addons/dialogic/Modules/Text/subsystem_text.gd +++ b/addons/dialogic/Modules/Text/subsystem_text.gd @@ -4,18 +4,48 @@ extends DialogicSubsystem #region SIGNALS +## Emitted when a text event is reached or a new text section is about to be shown. +## Gives a dictionary with the following keys: [br] +## [br] +## Key | Value Type | Value [br] +## ----------- | ------------- | ----- [br] +## `text` | [type String] | The text that is being displayed. [br] +## `character` | [type DialogicCharacter] | The character that says this text. [br] +## `portrait` | [type String] | The name of the portrait the character will use. [br] +## `append` | [type bool] | Whether the text will be appended to the previous text. [br] +@warning_ignore("unused_signal") # This is emitted by the text event. signal about_to_show_text(info:Dictionary) +## Emitted when a text event (or a new text section) starts displaying. +## This will be AFTER the textox animation, while [signal about_to_show_text] is before. +## Gives a dictionary with the same values as [signal about_to_show_text] +@warning_ignore("unused_signal") # This is emitted by the text event. +signal text_started(info:Dictionary) +## When the text has finished revealing. +## Gives a dictionary with the keys text and character. signal text_finished(info:Dictionary) +## Emitted when the speaker changes. signal speaker_updated(character:DialogicCharacter) +## Emitted when the textbox is shown or hidden. signal textbox_visibility_changed(visible:bool) -signal animation_textbox_new_text +## Emitted when the textbox appears. +## Use this together with the Animations subsystem to implement animations. +## If you start an animation and want dialogic to wait for it to finish before showing text, +## call Dialogic.Animations.start_animating() and then Dialogic.animation_finished() once it's done. signal animation_textbox_show +## Emitted when the textbox is hiding. Use like [signal animation_textbox_show]. signal animation_textbox_hide +## Emitted when a new text starts. Use like [signal animation_textbox_show]. +signal animation_textbox_new_text -# forwards of the dialog_text signals of all present dialog_text nodes -signal meta_hover_ended(meta:Variant) +## Emitted when a meta text on any DialogText node is hovered. +@warning_ignore("unused_signal") # These are emitted by the NodeDialogText signal meta_hover_started(meta:Variant) +## Emitted when a meta text on any DialogText node is not hovered anymore. +@warning_ignore("unused_signal") # These are emitted by the NodeDialogText +signal meta_hover_ended(meta:Variant) +## Emitted when a meta text on any DialogText node is clicked. +@warning_ignore("unused_signal") # These are emitted by the NodeDialogText signal meta_clicked(meta:Variant) #endregion @@ -29,7 +59,7 @@ var text_already_read := false var text_effects := {} var parsed_text_effect_info: Array[Dictionary] = [] var text_effects_regex := RegEx.new() -enum TextModifierModes {ALL=-1, TEXT_ONLY=0, CHOICES_ONLY=1} +enum ParserModes {ALL=-1, TEXT_ONLY=0, CHOICES_ONLY=1} enum TextTypes {DIALOG_TEXT, CHOICE_TEXT} var text_modifiers := [] @@ -44,15 +74,17 @@ var _voice_synced_text := false var _autopauses := {} +var parse_stack: Array[Dictionary] = [] + #region STATE #################################################################################################### func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void: - update_dialog_text('', true) + update_dialog_text("", true) update_name_label(null) - dialogic.current_state_info['speaker'] = "" - dialogic.current_state_info['text'] = '' + dialogic.current_state_info["speaker"] = "" + dialogic.current_state_info["text"] = "" set_text_reveal_skippable(ProjectSettings.get_setting('dialogic/text/initial_text_reveal_skippable', true)) @@ -65,9 +97,7 @@ func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> func load_game_state(_load_flag:=LoadFlags.FULL_LOAD) -> void: update_textbox(dialogic.current_state_info.get('text', ''), true) update_dialog_text(dialogic.current_state_info.get('text', ''), true) - var character: DialogicCharacter = null - if dialogic.current_state_info.get('speaker', ""): - character = load(dialogic.current_state_info.get('speaker', "")) + var character: DialogicCharacter = get_current_speaker() if character: update_name_label(character) @@ -85,21 +115,57 @@ func post_install() -> void: #region MAIN METHODS #################################################################################################### -## Applies modifiers, effects and coloring to the text -func parse_text(text:String, type:int=TextTypes.DIALOG_TEXT, variables := true, glossary := true, modifiers:= true, effects:= true, color_names:= true) -> String: - if modifiers: - text = parse_text_modifiers(text, type) - if variables and dialogic.has_subsystem('VAR'): - text = dialogic.VAR.parse_variables(text) - if effects: - text = parse_text_effects(text) - if color_names: - text = color_character_names(text) - if glossary and dialogic.has_subsystem('Glossary'): - text = dialogic.Glossary.parse_glossary(text) +## Applies modifiers, effects and coloring to the text. +## Utilizes the parse stack created and sorted in [method load_parse_stack()]. +func parse_text(text:String, type:int=TextTypes.DIALOG_TEXT) -> String: + if parse_stack.is_empty(): + load_parse_stack() + + for i in parse_stack: + if i.type != ParserModes.ALL and type != -1 and i.type != type: + continue + text = i.method.call(text) + return text +## Creates and sorts a stack of methods that take a text and return it. +## This includes: variables, text modifiers, text effects, autocolor names and the glossary. +func load_parse_stack() -> void: + parse_stack.clear() + + if dialogic.has_subsystem('VAR'): + parse_stack.append( + { + "method":dialogic.VAR.parse_variables, + "type": ParserModes.ALL, + "order": 30, + }) + + parse_stack.append( + { + "method": parse_text_effects, + "type": ParserModes.TEXT_ONLY, + "order": 50, + }) + for i in text_modifiers: + parse_stack.append(i) + parse_stack.append( + { + "method": color_character_names, + "type": ParserModes.TEXT_ONLY, + "order": 90, + }) + parse_stack.append( + { + "method": dialogic.Glossary.parse_glossary, + "type": ParserModes.TEXT_ONLY, + "order": 95, + }) + + parse_stack.sort_custom(func(a,b):return a["order"] < b["order"]) + + ## When an event updates the text spoken, this can adjust the state of ## the dialog text box. ## This method is async. @@ -138,6 +204,13 @@ func update_dialog_text(text: String, instant := false, additional := false) -> text_node.text = text else: + var current_character := get_current_speaker() + + if current_character: + var character_prefix: String = current_character.custom_info.get(DialogicCharacterPrefixSuffixSection.PREFIX_CUSTOM_KEY, DialogicCharacterPrefixSuffixSection.DEFAULT_PREFIX) + var character_suffix: String = current_character.custom_info.get(DialogicCharacterPrefixSuffixSection.SUFFIX_CUSTOM_KEY, DialogicCharacterPrefixSuffixSection.DEFAULT_SUFFIX) + text = character_prefix + text + character_suffix + text_node.reveal_text(text, additional) if !text_node.finished_revealing_text.is_connected(_on_dialog_text_finished): @@ -158,18 +231,18 @@ func update_dialog_text(text: String, instant := false, additional := false) -> func _on_dialog_text_finished() -> void: - text_finished.emit({'text':dialogic.current_state_info['text'], 'character':dialogic.current_state_info['speaker']}) + text_finished.emit({"text":dialogic.current_state_info["text"], "character":dialogic.current_state_info["speaker"]}) ## Updates the visible name on all name labels nodes. ## If a name changes, the [signal speaker_updated] signal is emitted. func update_name_label(character:DialogicCharacter): - var character_path := character.resource_path if character else "" - var current_character_path: String = dialogic.current_state_info.get("speaker", "") + var character_id := character.get_identifier() if character else "" + var current_character_id: String = dialogic.current_state_info.get("speaker", "") - if character_path != current_character_path: - dialogic.current_state_info['speaker'] = character_path + if character_id != current_character_id: speaker_updated.emit(character) + dialogic.current_state_info["speaker"] = character_id var name_label_text := get_character_name_parsed(character) @@ -182,8 +255,19 @@ func update_name_label(character:DialogicCharacter): name_label.self_modulate = Color(1,1,1,1) +func update_typing_sound_mood_from_character(character:DialogicCharacter, mood:String) -> void: + if character.custom_info.get("sound_moods", {}).is_empty(): + update_typing_sound_mood() + elif mood in character.custom_info.get("sound_moods", {}): + update_typing_sound_mood(character.custom_info.get("sound_moods", {})[mood]) + else: + var default_mood : String = character.custom_info.get("sound_mood_default", "") + update_typing_sound_mood(character.custom_info.get("sound_moods", {}).get(default_mood, {})) + + + func update_typing_sound_mood(mood:Dictionary = {}) -> void: - for typing_sound in get_tree().get_nodes_in_group('dialogic_type_sounds'): + for typing_sound in get_tree().get_nodes_in_group("dialogic_type_sounds"): typing_sound.load_overwrite(mood) @@ -335,8 +419,12 @@ func collect_text_effects() -> void: ## Use get_parsed_text_effects() after calling this to get all effect information func parse_text_effects(text:String) -> String: parsed_text_effect_info.clear() - var rtl := RichTextLabel.new() - rtl.bbcode_enabled = true + var rtl: RichTextLabel = null + if get_tree().get_first_node_in_group("dialogic_dialog_text"): + rtl = get_tree().get_first_node_in_group("dialogic_dialog_text").duplicate() + else: + rtl = RichTextLabel.new() + rtl.bbcode_enabled = true var position_correction := 0 var bbcode_correction := 0 for effect_match in text_effects_regex.search_all(text): @@ -361,7 +449,9 @@ func execute_effects(current_index:int, text_node:Control, skipping := false) -> if current_index != -1 and current_index < parsed_text_effect_info[0]['index']: return var effect: Dictionary = parsed_text_effect_info.pop_front() - await (effect['execution_info']['callable'] as Callable).call(text_node, skipping, effect['value']) + var callable: Callable = effect['execution_info']['callable'] + if is_instance_valid(text_node): + await callable.call(text_node, skipping, effect['value']) func collect_text_modifiers() -> void: @@ -372,15 +462,8 @@ func collect_text_modifiers() -> void: text_modifiers.append({'method':Callable(dialogic.get_subsystem(modifier.subsystem), modifier.method)}) elif modifier.has('node_path') and modifier.has('method'): text_modifiers.append({'method':Callable(get_node(modifier.node_path), modifier.method)}) - text_modifiers[-1]['mode'] = modifier.get('mode', TextModifierModes.TEXT_ONLY) - - -func parse_text_modifiers(text:String, type:int=TextTypes.DIALOG_TEXT) -> String: - for mod in text_modifiers: - if mod.mode != TextModifierModes.ALL and type != -1 and type != mod.mode: - continue - text = mod.method.call(text) - return text + text_modifiers[-1]['type'] = modifier.get('mode', ParserModes.TEXT_ONLY) + text_modifiers[-1]['order'] = modifier.get('order', 40) #endregion @@ -415,19 +498,12 @@ func get_character_name_parsed(character:DialogicCharacter) -> String: ## Returns the [class DialogicCharacter] of the current speaker. ## If there is no current speaker or the speaker is not found, returns null. func get_current_speaker() -> DialogicCharacter: - var speaker_path: String = dialogic.current_state_info.get("speaker", "") + var speaker_id: String = dialogic.current_state_info.get("speaker", "") - if speaker_path.is_empty(): + if speaker_id.is_empty(): return null - var speaker_resource := load(speaker_path) - - if speaker_resource == null: - return null - - var speaker_character := speaker_resource as DialogicCharacter - - return speaker_character + return DialogicResourceUtil.get_character_resource(speaker_id) func _update_user_speed(_user_speed:float) -> void: @@ -475,8 +551,8 @@ func collect_character_names() -> void: character_colors = {} - for dch_path in DialogicResourceUtil.get_character_directory().values(): - var character := (load(dch_path) as DialogicCharacter) + for dch_identifier in DialogicResourceUtil.get_character_directory(): + var character := (DialogicResourceUtil.get_character_resource(dch_identifier) as DialogicCharacter) if character.display_name: if "{" in character.display_name and "}" in character.display_name: @@ -564,19 +640,20 @@ func effect_signal(_text_node:Control, _skipped:bool, argument:String) -> void: func effect_mood(_text_node:Control, _skipped:bool, argument:String) -> void: if argument.is_empty(): return - if dialogic.current_state_info.get('speaker', ""): + if get_current_speaker(): update_typing_sound_mood( - load(dialogic.current_state_info.speaker).custom_info.get('sound_moods', {}).get(argument, {})) + get_current_speaker().custom_info.get('sound_moods', {}).get(argument, {})) -var modifier_words_select_regex := RegEx.create_from_string(r"(?]+(\/[^\>]*)\>") +var modifier_select_regex := RegEx.create_from_string(r"(?]+(\/[^\>]*)\>") +var modifier_select_split_regex := RegEx.create_from_string(r"(\[[^\]]*\]|[^\/]|\/\/)+") func modifier_random_selection(text:String) -> String: - for replace_mod_match in modifier_words_select_regex.search_all(text): + for replace_mod_match: RegExMatch in modifier_select_regex.search_all(text): var string: String = replace_mod_match.get_string().trim_prefix("<").trim_suffix(">") - string = string.replace('//', '') - var list: PackedStringArray = string.split('/') - var item: String = list[randi()%len(list)] - item = item.replace('', '/') + var options := [] + for split: RegExMatch in modifier_select_split_regex.search_all(string): + options.append(split.get_string()) + var item: String = options.pick_random() text = text.replace(replace_mod_match.get_string(), item.strip_edges()) return text diff --git a/addons/dialogic/Modules/Text/subsystem_text.gd.uid b/addons/dialogic/Modules/Text/subsystem_text.gd.uid index 1022bebf..c3559c63 100644 --- a/addons/dialogic/Modules/Text/subsystem_text.gd.uid +++ b/addons/dialogic/Modules/Text/subsystem_text.gd.uid @@ -1 +1 @@ -uid://dtxvpn61hx7ki +uid://os6fyykwoljl diff --git a/addons/dialogic/Modules/TextInput/event_text_input.gd b/addons/dialogic/Modules/TextInput/event_text_input.gd index 184fcf8a..387e375f 100644 --- a/addons/dialogic/Modules/TextInput/event_text_input.gd +++ b/addons/dialogic/Modules/TextInput/event_text_input.gd @@ -19,19 +19,21 @@ var default := "" var allow_empty := false -################################################################################ -## EXECUTION +#region EXECUTION ################################################################################ func _execute() -> void: dialogic.Inputs.auto_skip.enabled = false dialogic.current_state = DialogicGameHandler.States.WAITING - dialogic.TextInput.show_text_input(text, default, placeholder, allow_empty) + dialogic.TextInput.show_text_input( + get_property_translated("text"), + get_property_translated("default"), + get_property_translated("placeholder"), allow_empty) dialogic.TextInput.input_confirmed.connect(_on_DialogicTextInput_input_confirmed, CONNECT_ONE_SHOT) func _on_DialogicTextInput_input_confirmed(input:String) -> void: - if !dialogic.has_subsystem('VAR'): + if not dialogic.has_subsystem('VAR'): printerr('[Dialogic] The TextInput event needs the variable subsystem to be present.') finish() return @@ -41,8 +43,7 @@ func _on_DialogicTextInput_input_confirmed(input:String) -> void: finish() -################################################################################ -## SAVING/LOADING +#region SETUP ################################################################################ func _init() -> void: @@ -52,8 +53,7 @@ func _init() -> void: event_sorting_index = 6 -################################################################################ -## SAVING/LOADING +#region SAVING/LOADING ################################################################################ func get_shortcode() -> String: @@ -70,8 +70,23 @@ func get_shortcode_parameters() -> Dictionary: "allow_empty" : {"property": "allow_empty", "default": false}, } -################################################################################ -## EDITOR + +func _get_translatable_properties() -> Array: + return ["text", "placeholder", "default"] + + +func _get_property_original_translation(property_name:String) -> String: + match property_name: + "text": + return text + "placeholder": + return placeholder + "default": + return default + return "" + + +#region EDITOR ################################################################################ func build_event_editor() -> void: @@ -86,7 +101,7 @@ func build_event_editor() -> void: add_body_edit('allow_empty', ValueType.BOOL, {'left_text':'Allow empty:'}) -func get_var_suggestions(filter:String="") -> Dictionary: +func get_var_suggestions(filter: String = "") -> Dictionary: var suggestions := {} if filter: suggestions[filter] = { diff --git a/addons/dialogic/Modules/TextInput/event_text_input.gd.uid b/addons/dialogic/Modules/TextInput/event_text_input.gd.uid index 8f467761..e3e9a315 100644 --- a/addons/dialogic/Modules/TextInput/event_text_input.gd.uid +++ b/addons/dialogic/Modules/TextInput/event_text_input.gd.uid @@ -1 +1 @@ -uid://5pvmq6gdg7my +uid://dwtfcwgkjtx6c diff --git a/addons/dialogic/Modules/TextInput/index.gd.uid b/addons/dialogic/Modules/TextInput/index.gd.uid index a1517924..efeaf515 100644 --- a/addons/dialogic/Modules/TextInput/index.gd.uid +++ b/addons/dialogic/Modules/TextInput/index.gd.uid @@ -1 +1 @@ -uid://dsn6hfgg5yw0e +uid://nfpba62owxh diff --git a/addons/dialogic/Modules/TextInput/node_text_input.gd.uid b/addons/dialogic/Modules/TextInput/node_text_input.gd.uid index 48a0cb39..1ab3ca54 100644 --- a/addons/dialogic/Modules/TextInput/node_text_input.gd.uid +++ b/addons/dialogic/Modules/TextInput/node_text_input.gd.uid @@ -1 +1 @@ -uid://rlnfypr752xa +uid://biqpjv0qyefvf diff --git a/addons/dialogic/Modules/TextInput/subsystem_text_input.gd b/addons/dialogic/Modules/TextInput/subsystem_text_input.gd index 096698f1..707b92b2 100644 --- a/addons/dialogic/Modules/TextInput/subsystem_text_input.gd +++ b/addons/dialogic/Modules/TextInput/subsystem_text_input.gd @@ -3,7 +3,9 @@ extends DialogicSubsystem ## Subsystem that handles showing of input promts. ## Signal that is fired when a confirmation button was pressed. +@warning_ignore("unused_signal") # This is emitted by the DialogTextInput node signal input_confirmed(input:String) + signal input_shown(info:Dictionary) diff --git a/addons/dialogic/Modules/TextInput/subsystem_text_input.gd.uid b/addons/dialogic/Modules/TextInput/subsystem_text_input.gd.uid index 52e819e9..a29e2e59 100644 --- a/addons/dialogic/Modules/TextInput/subsystem_text_input.gd.uid +++ b/addons/dialogic/Modules/TextInput/subsystem_text_input.gd.uid @@ -1 +1 @@ -uid://d2fkc11kf8nfn +uid://2trp4nw7huuv diff --git a/addons/dialogic/Modules/Variable/event_variable.gd b/addons/dialogic/Modules/Variable/event_variable.gd index 3111bdb9..f23c347d 100644 --- a/addons/dialogic/Modules/Variable/event_variable.gd +++ b/addons/dialogic/Modules/Variable/event_variable.gd @@ -303,10 +303,26 @@ func build_event_editor() -> void: func get_var_suggestions(filter:String) -> Dictionary: var suggestions := {} - if filter: - suggestions[filter] = {'value':filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]} for var_path in DialogicUtil.list_variables(DialogicUtil.get_default_variables()): suggestions[var_path] = {'value':var_path, 'icon':load("res://addons/dialogic/Editor/Images/Pieces/variable.svg")} + + var autoloads := DialogicUtil.get_autoload_suggestions().keys() + var is_autoload := "" + for autoload in autoloads: + if autoload == filter: + is_autoload = autoload + break + suggestions[autoload] = {'value':autoload, 'editor_icon':["Node", "EditorIcons"]} + + if is_autoload or filter.count(".") == 1 and filter.split(".")[0] in autoloads: + var autoload := filter.trim_suffix(".") + var properties := DialogicUtil.get_autoload_property_suggestions("", autoload) + for property in properties: + suggestions["."+property] = {'value':autoload+"."+property, 'editor_icon':["MemberProperty", "EditorIcons"]} + + if not filter in suggestions: + suggestions[filter] = {'value':filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]} + return suggestions @@ -342,9 +358,22 @@ func update_editor_warning() -> void: ################################################################################ func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void: - if CodeCompletionHelper.get_line_untill_caret(line) == 'set ': + var autoloads := DialogicUtil.get_autoload_suggestions() + var line_until_caret: String = CodeCompletionHelper.get_line_untill_caret(line) + if line_until_caret.count(" ") == 1 and not "{" in line and not line_until_caret.ends_with("."): + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, '{', '{', TextNode.syntax_highlighter.variable_color) - if symbol == '{': + for i in autoloads: + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i+'.', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.3), TextNode.get_theme_icon("Node", "EditorIcons")) + + if (line_until_caret.ends_with(".") or symbol == "."): + var autoload_name := line_until_caret.split(" ")[-1].split(".")[0] + if autoload_name in autoloads: + var properties := DialogicUtil.get_autoload_property_suggestions("", autoload_name) + for i in properties.keys(): + TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i+" ", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.3), TextNode.get_theme_icon("MemberMethod", "EditorIcons")) + + elif symbol == '{': CodeCompletionHelper.suggest_variables(TextNode) diff --git a/addons/dialogic/Modules/Variable/event_variable.gd.uid b/addons/dialogic/Modules/Variable/event_variable.gd.uid index ad59b565..e6202661 100644 --- a/addons/dialogic/Modules/Variable/event_variable.gd.uid +++ b/addons/dialogic/Modules/Variable/event_variable.gd.uid @@ -1 +1 @@ -uid://dkmvexi87evma +uid://bkpesig21aapy diff --git a/addons/dialogic/Modules/Variable/index.gd.uid b/addons/dialogic/Modules/Variable/index.gd.uid index 443f9aeb..a87df7a9 100644 --- a/addons/dialogic/Modules/Variable/index.gd.uid +++ b/addons/dialogic/Modules/Variable/index.gd.uid @@ -1 +1 @@ -uid://dtsw0bwvin406 +uid://bl8f0x14rhl4c diff --git a/addons/dialogic/Modules/Variable/subsystem_variables.gd b/addons/dialogic/Modules/Variable/subsystem_variables.gd index b14ba684..ff5c142c 100644 --- a/addons/dialogic/Modules/Variable/subsystem_variables.gd +++ b/addons/dialogic/Modules/Variable/subsystem_variables.gd @@ -19,6 +19,7 @@ signal variable_changed(info:Dictionary) ## `new_value` | [type Variant]| The value that [variable] has after the change (the result). [br] ## `value` | [type Variant]| The value that the variable is changed by/to. [br] ## `value_str` | [type String] | Whatever has been given as the value (not interpreted, so a variable is just a string).[br] +@warning_ignore("unused_signal") # This is emitted from the variable event signal variable_was_set(info:Dictionary) @@ -59,7 +60,7 @@ func parse_variables(text:String) -> String: # Trying to extract the curly brackets from the text var regex := RegEx.new() - regex.compile("(?([^{}]|\\{.*\\})*)\\}") + regex.compile(r"(?([^{}]|\{[^}]*\})*)\}") var parsed := text.replace('\\{', '{') for result in regex.search_all(text): diff --git a/addons/dialogic/Modules/Variable/subsystem_variables.gd.uid b/addons/dialogic/Modules/Variable/subsystem_variables.gd.uid index db99b644..f603edde 100644 --- a/addons/dialogic/Modules/Variable/subsystem_variables.gd.uid +++ b/addons/dialogic/Modules/Variable/subsystem_variables.gd.uid @@ -1 +1 @@ -uid://brq3wjn8ua6hj +uid://cg6l4lsr2h247 diff --git a/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd b/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd index cc659f91..b6cfcc6e 100644 --- a/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd +++ b/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd @@ -5,6 +5,9 @@ enum TreeButtons {ADD_FOLDER, ADD_VARIABLE, DUPLICATE_FOLDER, DELETE, CHANGE_TYP @onready var editor: DialogicEditor = find_parent("VariablesEditor") +var validation_regex := RegEx.create_from_string(r"[^\w]") + +var undo := UndoRedo.new() #region INITIAL SETUP @@ -51,20 +54,21 @@ func load_info(dict:Dictionary, parent:TreeItem = null, is_new:=false) -> void: load_info(dict[key], folder, is_new) - -func add_variable_item(name:String, value:Variant, parent:TreeItem) -> TreeItem: +func add_variable_item(item_name:String, value:Variant, parent:TreeItem) -> TreeItem: var item := create_item(parent) item.set_meta("type", "VARIABLE") - item.set_text(0, name) + item.set_text(0, item_name) item.set_editable(0, true) - item.set_metadata(0, name) + item.set_metadata(0, item_name) item.set_icon(0, load(DialogicUtil.get_module_path('Variable').path_join("variable.svg"))) - var folder_color: Color = parent.get_meta('color', Color.DARK_GOLDENROD) - item.set_custom_bg_color(0, folder_color.lerp(get_theme_color("background", "Editor"), 0.8)) + + var folder_color: Color = parent.get_meta('color', Color.TRANSPARENT) + folder_color.a *= 0.5 + item.set_custom_bg_color(0, folder_color.lerp(get_theme_color("background", "Editor"), 0.5)) item.add_button(1, get_theme_icon("String", "EditorIcons"), TreeButtons.CHANGE_TYPE) - adjust_variable_type(item, DialogicUtil.get_variable_value_type(value), value) + set_variable_value(item, DialogicUtil.get_variable_value_type(value), value) item.set_editable(2, true) item.add_button(2, get_theme_icon("Remove", "EditorIcons"), TreeButtons.DELETE) @@ -72,27 +76,51 @@ func add_variable_item(name:String, value:Variant, parent:TreeItem) -> TreeItem: return item -func add_folder_item(name:String, parent:TreeItem) -> TreeItem: +func add_folder_item(item_name:String, parent:TreeItem) -> TreeItem: var item := create_item(parent) item.set_icon(0, get_theme_icon("Folder", "EditorIcons")) - item.set_text(0, name) + item.set_meta("type", "FOLDER") + item.set_text(0, item_name) + item.set_metadata(0, item_name) item.set_editable(0, item != get_root()) - var folder_color: Color + var folder_color := Color.TRANSPARENT if parent == null: + #folder_color = Color.TRANSPARENT# folder_color = Color(0.33000001311302, 0.15179999172688, 0.15179999172688) else: - folder_color = parent.get_meta('color') - folder_color.h = wrap(folder_color.h+0.15*(item.get_index()+1), 0, 1) + var parent_color: Color = parent.get_meta('color', Color(0.33000001311302, 0.15179999172688, 0.15179999172688)) + folder_color = parent_color + + var level := 1 + var i := item + while i.get_parent(): + i = i.get_parent() + level += 1 + + var parent_vars_count := 0 + if parent: + parent_vars_count = parent.get_children().reduce(func(x, y): return x + 1 if y.get_meta("type") == "VARIABLE" else x, 0) + + if level == 2: + folder_color.h = wrap(folder_color.h+0.15*(item.get_index()-parent_vars_count+1), 0, 1) + #folder_color = folder_color.lerp(get_theme_color("background", "Editor"), 0.1*level) + elif level == 3: + folder_color.h = wrap(folder_color.h-0.1*(item.get_index()-parent_vars_count+1), 0, 1) + elif level == 4: + folder_color.h = wrap(folder_color.h+0.1*(item.get_index()-parent_vars_count+1), 0, 1) + + folder_color = folder_color.lerp(get_theme_color("background", "Editor"), 0.25) item.set_custom_bg_color(0, folder_color) item.set_custom_bg_color(1, folder_color) item.set_custom_bg_color(2, folder_color) item.set_meta('color', folder_color) + item.add_button(2, load(self.get_script().get_path().get_base_dir().get_base_dir() + "/add-variable.svg"), TreeButtons.ADD_VARIABLE) item.add_button(2, load("res://addons/dialogic/Editor/Images/Pieces/add-folder.svg"), TreeButtons.ADD_FOLDER) item.add_button(2, get_theme_icon("Duplicate", "EditorIcons"), TreeButtons.DUPLICATE_FOLDER, item == get_root()) item.add_button(2, get_theme_icon("Remove", "EditorIcons"), TreeButtons.DELETE, item == get_root()) - item.set_meta("type", "FOLDER") + return item @@ -119,24 +147,27 @@ func get_variable_item_default(item:TreeItem) -> Variant: return "" -func _on_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index: int) -> void: +func _on_button_clicked(item: TreeItem, _column: int, id: int, _mouse_button_index: int) -> void: match id: - TreeButtons.ADD_FOLDER: - var new_item := add_folder_item("Folder", item) - new_item.select(0) - new_item.set_meta("new", true) + TreeButtons.ADD_FOLDER, TreeButtons.ADD_VARIABLE: + var new_item_name := "" + if id == TreeButtons.ADD_FOLDER: + new_item_name = validate_name(item, "NewFolder") + item_add_undoable(item, new_item_name, "FOLDER", {}) + else: + new_item_name = validate_name(item, "NewVar") + item_add_undoable(item, new_item_name, "VARIABLE", "") await get_tree().process_frame - edit_selected() - TreeButtons.ADD_VARIABLE: - var new_item := add_variable_item("Var", "", item) + var new_item := get_path_item(get_item_path(item, new_item_name)) new_item.select(0) new_item.set_meta("new", true) await get_tree().process_frame edit_selected() TreeButtons.DELETE: - item.free() + item_remove_undoable(item) TreeButtons.DUPLICATE_FOLDER: - load_info({item.get_text(0)+"(copy)":get_info(item)}, item.get_parent(), true) + var new_folder_name := validate_name(item.get_parent(), item.get_text(0)) + item_add_undoable(item.get_parent(), new_folder_name, "FOLDER", get_info(item)) TreeButtons.CHANGE_TYPE: %ChangeTypePopup.show() %ChangeTypePopup.set_meta('item', item) @@ -146,10 +177,23 @@ func _on_button_clicked(item: TreeItem, column: int, id: int, mouse_button_index %ChangeTypePopup/HBox.get_child(int(item.get_meta('value_type', DialogicUtil.VarTypes.STRING)-1)).set_pressed_no_signal(true) -func _on_type_pressed(pressed:bool, type:int) -> void: +func _on_type_pressed(_pressed:bool, type:int) -> void: %ChangeTypePopup.hide() - var item: Variant = %ChangeTypePopup.get_meta('item') - adjust_variable_type(item, type, item.get_metadata(2)) + # This is a MESS. + # Basically there are two ways a variable value can change: + # - by being set edited the tree + # - by the type being changed + # The problem is that to make the first undoable, we always store the value in the metadata as well. + # When we detect an edit (in _on_item_edited) we commit the do/undo actions which edit the value AGAIN. + # But here, where we change the type we now have to edit the type two times as well. + # There might be a better way but who cares... + var item: TreeItem = %ChangeTypePopup.get_meta('item') + var old_value: Variant = item.get_metadata(2) + set_variable_value(item, type, item.get_metadata(2)) + var new_value: Variant = get_variable_item_default(item) + if typeof(new_value) != typeof(old_value) or new_value != old_value: + item.set_metadata(2, old_value) + item_change_value_undoable(item) func _on_item_edited() -> void: @@ -160,19 +204,134 @@ func _on_item_edited() -> void: 0: if item.get_text(0).is_empty(): item.set_text(0, item.get_metadata(0)) - else: + validate_name(item) if item.get_text(0) != item.get_metadata(0): - item.set_metadata(0, item.get_text(0)) - report_name_changes(item) - + item_rename_undoable(item) 2: - item.set_metadata(2, get_variable_item_default(item)) + if get_variable_item_default(item) != item.get_metadata(2): + item_change_value_undoable(item) "FOLDER": - report_name_changes(item) + if item.get_text(0) != item.get_metadata(0): + validate_name(item) + item_rename_undoable(item) -func adjust_variable_type(item:TreeItem, type:int, prev_value:Variant) -> void: +func item_add_undoable(parent_item:TreeItem, item_name:String, type:String, value:Variant) -> void: + undo.create_action("Add Item") + undo.add_do_method( + add_item.bind( + get_item_path(parent_item), + item_name, + type, + value) + ) + undo.add_undo_method(remove_item.bind(get_item_path(parent_item, item_name))) + undo.commit_action() + + +func add_item(parent_path:String, text:String, type:String, value:Variant) -> void: + var parent_item := get_path_item(parent_path) + match type: + "VARIABLE": + add_variable_item(text, value, parent_item) + "FOLDER": + load_info({text:value}, parent_item, true) + + +func item_remove_undoable(item:TreeItem) -> void: + undo.create_action("Remove Item") + undo.add_do_method(remove_item.bind(get_item_path(item))) + undo.add_undo_method( + add_item.bind( + get_item_path(item.get_parent()), + item.get_text(0), + item.get_meta("type"), + get_variable_item_default(item) if item.get_meta("type") == "VARIABLE" else get_info(item)) + ) + undo.commit_action() + +func remove_item(item_path:String) -> void: + get_path_item(item_path).free() + + +func item_rename_undoable(item:TreeItem) -> void: + var new_item_path := get_item_path(item) + var new_name := item.get_text(0) + var old_name: String = item.get_metadata(0) + item.set_text(0, item.get_metadata(0)) + var old_item_path := get_item_path(item) + undo.create_action("Renamed Item") + undo.add_do_method(item_rename.bind(old_item_path, new_name, old_name)) + undo.add_undo_method(item_rename.bind(new_item_path, old_name, new_name)) + undo.commit_action() + + +func item_rename(item_path:String, new_name:String, old_name:String) -> void: + var item := get_path_item(item_path) + if item.get_text(0) == old_name: + item.set_text(0, new_name) + report_name_changes(item) + item.set_metadata(0, item.get_text(0)) + + +func item_change_value_undoable(item:TreeItem) -> void: + var item_path := get_item_path(item) + var old_value: Variant = item.get_metadata(2) + var new_value: Variant = get_variable_item_default(item) + + undo.create_action("Change Variable") + undo.add_do_method(item_change_value.bind(item_path, new_value)) + undo.add_undo_method(item_change_value.bind(item_path, old_value)) + undo.commit_action() + + +func item_change_value(item_path:String, value:Variant) -> void: + #print("SET VARIABLE VALUE ", value) + var item := get_path_item(item_path) + set_variable_value(item, DialogicUtil.get_variable_value_type(value), value) + item.set_metadata(2, value) + + +func validate_name(item:TreeItem, check_for_imaginary_child := "") -> String: + var item_name := item.get_text(0) + var item_parent := item.get_parent() + if check_for_imaginary_child: + item_name = check_for_imaginary_child + item_parent = item + if not item_name.is_valid_identifier(): + item_name = validation_regex.sub(item_name, "_", true) + if not item_name.is_valid_identifier(): + item_name = "_"+item_name + + var sibling_names := [] + + for i in item_parent.get_children(): + if i == item: + continue + sibling_names.append(i.get_text(0)) + + if item_name in sibling_names: + var number_regex := RegEx.create_from_string(r"(?<=\w)\d+$") + var res := number_regex.search(item_name) + var x := 2 + if res: + var number := res.get_string() + x = int(number) + item_name = item_name.trim_suffix(number) + + while item_name + str(x) in sibling_names: + x += 1 + + item_name = item_name + str(x) + + if not check_for_imaginary_child: + item.set_text(0, item_name) + + return item_name + + +func set_variable_value(item:TreeItem, type:int, prev_value:Variant) -> void: set_variable_item_type(item, type) match type: DialogicUtil.VarTypes.STRING: @@ -195,13 +354,22 @@ func adjust_variable_type(item:TreeItem, type:int, prev_value:Variant) -> void: item.set_checked(2, prev_value and true) -func _input(event): +func _input(event:InputEvent) -> void: + if get_window().has_focus() and is_visible_in_tree() and event is InputEventKey and event.is_pressed(): + match event.as_text(): + "Ctrl+Z": + undo.undo() + accept_event() + "Ctrl+Y", "Ctrl+Shift+Z": + undo.redo() + accept_event() if !%ChangeTypePopup.visible: return if event is InputEventMouseButton and event.pressed: if not %ChangeTypePopup.get_global_rect().has_point(get_global_mouse_position()): %ChangeTypePopup.hide() + #endregion @@ -244,7 +412,7 @@ func get_info(item:TreeItem = null) -> Dictionary: #region DRAG AND DROP ################################################################################ -func _get_drag_data(position:Vector2) -> Variant: +func _get_drag_data(_position:Vector2) -> Variant: drop_mode_flags = DROP_MODE_INBETWEEN var preview := Label.new() preview.text = " "+get_selected().get_text(0) @@ -254,17 +422,17 @@ func _get_drag_data(position:Vector2) -> Variant: return get_selected() -func _can_drop_data(position:Vector2, data:Variant) -> bool: +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) +func _drop_data(drop_position:Vector2, item:Variant) -> void: + var to_item := get_item_at_position(drop_position) if !to_item: return - var drop_section := get_drop_section_at_position(position) + var drop_section := get_drop_section_at_position(drop_position) var parent: TreeItem = null if (drop_section == 1 and to_item.get_meta('type') == "FOLDER") or to_item == get_root(): parent = to_item @@ -311,7 +479,6 @@ func _drop_data(position:Vector2, item:Variant) -> void: ################################################################################ func report_name_changes(item:TreeItem) -> void: - match item.get_meta('type'): "VARIABLE": if item.get_meta("new", false): @@ -324,13 +491,39 @@ func report_name_changes(item:TreeItem) -> void: report_name_changes(child) -func get_item_path(item:TreeItem) -> String: - var path := item.get_text(0) - while item.get_parent() != get_root(): +func get_item_path(item:TreeItem, imaginary_child:String = "") -> String: + var path := "" + if item != get_root(): + path = item.get_text(0) + while item != get_root() and item.get_parent() != get_root(): item = item.get_parent() path = item.get_text(0)+"."+path + if imaginary_child: + if path: + path += "."+imaginary_child + else: + path = imaginary_child return path + +func get_path_item(path:String) -> TreeItem: + var paths := Array(path.split(".", false)) + var item := get_root() + while paths: + var found := false + for i in item.get_children(): + if i.get_text(0) == paths[0]: + item = i + paths.pop_front() + found = true + break + if not found: + break + + if get_item_path(item) != path: + return null + return item + #endregion diff --git a/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd.uid b/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd.uid index f4342291..1742fed5 100644 --- a/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd.uid +++ b/addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd.uid @@ -1 +1 @@ -uid://dcqa75hi4o0yo +uid://deduielq1r0r diff --git a/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd b/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd index 38941a46..65cc2221 100644 --- a/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd +++ b/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd @@ -18,7 +18,7 @@ func _register() -> void: alternative_text = "Create and edit dialogic variables and their default values" -func _open(argument:Variant = null): +func _open(_argument:Variant = null) -> void: %ReferenceInfo.hide() %Tree.load_info(ProjectSettings.get_setting('dialogic/variables', {})) @@ -43,9 +43,13 @@ func _ready() -> void: func variable_renamed(old_name:String, new_name:String): if old_name == new_name: return + var count: int = editors_manager.reference_manager.get_change_count() editors_manager.reference_manager.add_variable_ref_change(old_name, new_name) - %ReferenceInfo.show() - + var new_count: int = editors_manager.reference_manager.get_change_count() + if count > new_count: + %ReferenceInfo.hide() + elif count < new_count: + %ReferenceInfo.show() func _on_reference_manager_pressed() -> void: editors_manager.reference_manager.open() diff --git a/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd.uid b/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd.uid index f2b218b3..0ce0a3f8 100644 --- a/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd.uid +++ b/addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd.uid @@ -1 +1 @@ -uid://vtebbykodm8p +uid://d1yoykg323a5p diff --git a/addons/dialogic/Modules/Variable/variables_editor/variables_editor.tscn b/addons/dialogic/Modules/Variable/variables_editor/variables_editor.tscn index 1322abdf..f4315621 100644 --- a/addons/dialogic/Modules/Variable/variables_editor/variables_editor.tscn +++ b/addons/dialogic/Modules/Variable/variables_editor/variables_editor.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=10 format=3 uid="uid://6tdle4y5o03o"] -[ext_resource type="Script" uid="uid://vtebbykodm8p" path="res://addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd" id="2"] -[ext_resource type="Script" uid="uid://dcqa75hi4o0yo" path="res://addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd" id="2_1i17i"] +[ext_resource type="Script" uid="uid://d1yoykg323a5p" path="res://addons/dialogic/Modules/Variable/variables_editor/variables_editor.gd" id="2"] +[ext_resource type="Script" uid="uid://deduielq1r0r" path="res://addons/dialogic/Modules/Variable/variables_editor/variable_tree.gd" id="2_1i17i"] [sub_resource type="Image" id="Image_1bhct"] data = { @@ -15,22 +15,22 @@ data = { [sub_resource type="ImageTexture" id="ImageTexture_sr7s6"] image = SubResource("Image_1bhct") -[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6orff"] -content_margin_left = 6.125 +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7aodm"] +content_margin_left = 2.0 content_margin_top = 0.0 -content_margin_right = 6.125 +content_margin_right = 2.0 content_margin_bottom = 0.0 bg_color = Color(0.44, 0.73, 0.98, 0.1) -border_width_left = 4 -border_width_top = 4 -border_width_right = 4 -border_width_bottom = 4 +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 border_color = Color(0.44, 0.73, 0.98, 1) -corner_radius_top_left = 5 -corner_radius_top_right = 5 -corner_radius_bottom_right = 5 -corner_radius_bottom_left = 5 -corner_detail = 5 +corner_radius_top_left = 3 +corner_radius_top_right = 3 +corner_radius_bottom_right = 3 +corner_radius_bottom_left = 3 +corner_detail = 3 anti_aliasing = false [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_vn21i"] @@ -47,9 +47,9 @@ expand_margin_bottom = 4.0 anti_aliasing = false [sub_resource type="Theme" id="Theme_17j6i"] -Button/styles/hover = SubResource("StyleBoxFlat_6orff") +Button/styles/hover = SubResource("StyleBoxFlat_7aodm") Button/styles/normal = SubResource("StyleBoxEmpty_vn21i") -Button/styles/pressed = SubResource("StyleBoxFlat_6orff") +Button/styles/pressed = SubResource("StyleBoxFlat_7aodm") pressed/styles/Button = SubResource("StyleBoxFlat_ffuxp") [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ncgqs"] diff --git a/addons/dialogic/Modules/Voice/event_voice.gd.uid b/addons/dialogic/Modules/Voice/event_voice.gd.uid index 67561025..547a7c5e 100644 --- a/addons/dialogic/Modules/Voice/event_voice.gd.uid +++ b/addons/dialogic/Modules/Voice/event_voice.gd.uid @@ -1 +1 @@ -uid://dvtkp8m26k8ki +uid://clwe1br2ay8sh diff --git a/addons/dialogic/Modules/Voice/index.gd.uid b/addons/dialogic/Modules/Voice/index.gd.uid index faadb025..526fbfdd 100644 --- a/addons/dialogic/Modules/Voice/index.gd.uid +++ b/addons/dialogic/Modules/Voice/index.gd.uid @@ -1 +1 @@ -uid://blnhsvfms0q36 +uid://cbkcu10vcem8q diff --git a/addons/dialogic/Modules/Voice/subsystem_voice.gd.uid b/addons/dialogic/Modules/Voice/subsystem_voice.gd.uid index 79860dae..eefa1866 100644 --- a/addons/dialogic/Modules/Voice/subsystem_voice.gd.uid +++ b/addons/dialogic/Modules/Voice/subsystem_voice.gd.uid @@ -1 +1 @@ -uid://c0akc7edvnw2n +uid://yd2m5ab2rv5a diff --git a/addons/dialogic/Modules/Wait/event_wait.gd.uid b/addons/dialogic/Modules/Wait/event_wait.gd.uid index 37f33e8b..24567433 100644 --- a/addons/dialogic/Modules/Wait/event_wait.gd.uid +++ b/addons/dialogic/Modules/Wait/event_wait.gd.uid @@ -1 +1 @@ -uid://unjo7v2jwt2b +uid://cs43ebxhcg7xi diff --git a/addons/dialogic/Modules/Wait/index.gd.uid b/addons/dialogic/Modules/Wait/index.gd.uid index 12045b9c..0a27061d 100644 --- a/addons/dialogic/Modules/Wait/index.gd.uid +++ b/addons/dialogic/Modules/Wait/index.gd.uid @@ -1 +1 @@ -uid://cky12lkaf7teo +uid://bfbqy5uegkvk8 diff --git a/addons/dialogic/Modules/WaitInput/event_wait_input.gd.uid b/addons/dialogic/Modules/WaitInput/event_wait_input.gd.uid index 0b370141..a9cf86df 100644 --- a/addons/dialogic/Modules/WaitInput/event_wait_input.gd.uid +++ b/addons/dialogic/Modules/WaitInput/event_wait_input.gd.uid @@ -1 +1 @@ -uid://bfrqoojixrqs2 +uid://bbimp04pehxpi diff --git a/addons/dialogic/Modules/WaitInput/index.gd.uid b/addons/dialogic/Modules/WaitInput/index.gd.uid index 350541de..621629d2 100644 --- a/addons/dialogic/Modules/WaitInput/index.gd.uid +++ b/addons/dialogic/Modules/WaitInput/index.gd.uid @@ -1 +1 @@ -uid://c010jboh4wxno +uid://n31b7koeye73 diff --git a/addons/dialogic/Resources/CharacterResourceLoader.gd b/addons/dialogic/Resources/CharacterResourceLoader.gd index 1f6ed0f0..1ea61433 100644 --- a/addons/dialogic/Resources/CharacterResourceLoader.gd +++ b/addons/dialogic/Resources/CharacterResourceLoader.gd @@ -50,15 +50,25 @@ func _get_dependencies(path:String, _add_type:bool) -> PackedStringArray: var depends_on: PackedStringArray = [] var character: DialogicCharacter = load(path) for p in character.portraits.values(): - if 'path' in p and p.path: - depends_on.append(p.path) + if 'scene' in p and p.scene: + depends_on.append(p.scene) + for i in p.get("export_overrides", []): + if typeof(p.export_overrides[i]) == TYPE_STRING and "://" in p.export_overrides[i]: + depends_on.append(p.export_overrides[i].trim_prefix('"').trim_suffix('"')) return depends_on func _rename_dependencies(path: String, renames: Dictionary) -> Error: var character: DialogicCharacter = load(path) - for p in character.portraits: - if 'path' in character.portraits[p] and character.portraits[p].path in renames: - character.portraits[p].path = renames[character.portraits[p].path] + for p in character.portraits.values(): + if 'scene' in p and p.scene in renames: + p.scene = renames[p.scene] + + for i in p.get("export_overrides", []): + if typeof(p.export_overrides[i]) == TYPE_STRING and "://" in p.export_overrides[i]: + var i_path := str(p.export_overrides[i]).trim_prefix('"').trim_suffix('"') + if i_path in renames: + p.export_overrides[i] = '"'+renames[i_path]+'"' + ResourceSaver.save(character, path) return OK diff --git a/addons/dialogic/Resources/CharacterResourceLoader.gd.uid b/addons/dialogic/Resources/CharacterResourceLoader.gd.uid index ac372b4b..66c9d14b 100644 --- a/addons/dialogic/Resources/CharacterResourceLoader.gd.uid +++ b/addons/dialogic/Resources/CharacterResourceLoader.gd.uid @@ -1 +1 @@ -uid://ca2202bvyvsq8 +uid://bma748hbtk7sb diff --git a/addons/dialogic/Resources/CharacterResourceSaver.gd.uid b/addons/dialogic/Resources/CharacterResourceSaver.gd.uid index 3272886f..cd7d1b54 100644 --- a/addons/dialogic/Resources/CharacterResourceSaver.gd.uid +++ b/addons/dialogic/Resources/CharacterResourceSaver.gd.uid @@ -1 +1 @@ -uid://bvijft505cs0l +uid://fqvcs0pexdf diff --git a/addons/dialogic/Resources/TimelineResourceLoader.gd b/addons/dialogic/Resources/TimelineResourceLoader.gd index 0786bda1..3aae16a5 100644 --- a/addons/dialogic/Resources/TimelineResourceLoader.gd +++ b/addons/dialogic/Resources/TimelineResourceLoader.gd @@ -44,3 +44,24 @@ func _load(path: String, _original_path: String, _use_sub_threads: bool, _cache_ var tml := DialogicTimeline.new() tml.from_text(file.get_as_text()) return tml + + +func _get_dependencies(path: String, _add_types: bool) -> PackedStringArray: + var deps := PackedStringArray() + + var tml: DialogicTimeline = load(path) + tml.process() + + for ev in tml.events: + deps += ev.get_dependencies() + + var clean_deps := PackedStringArray() + + for i in deps: + var clean := i + if clean.begins_with("res://"): + clean = ResourceUID.id_to_text(ResourceLoader.get_resource_uid(clean)) + if not clean.is_empty() and not clean in clean_deps: + clean_deps.append(clean) + + return clean_deps diff --git a/addons/dialogic/Resources/TimelineResourceLoader.gd.uid b/addons/dialogic/Resources/TimelineResourceLoader.gd.uid index 0bfc56a7..b15e935f 100644 --- a/addons/dialogic/Resources/TimelineResourceLoader.gd.uid +++ b/addons/dialogic/Resources/TimelineResourceLoader.gd.uid @@ -1 +1 @@ -uid://b4emo1x6y8rxm +uid://23ha2f6di4hb diff --git a/addons/dialogic/Resources/TimelineResourceSaver.gd b/addons/dialogic/Resources/TimelineResourceSaver.gd index 62bca892..2443a306 100644 --- a/addons/dialogic/Resources/TimelineResourceSaver.gd +++ b/addons/dialogic/Resources/TimelineResourceSaver.gd @@ -19,40 +19,12 @@ func _recognize(resource: Resource) -> bool: ## Save the resource -## TODO: This should use timeline.as_text(), why is this still here? func _save(resource: Resource, path: String = '', _flags: int = 0) -> Error: if resource.get_meta("timeline_not_saved", false): + var timeline_as_text: String = resource.as_text() - var timeline_as_text := "" - # if events are resources, create text - if resource.events_processed: - - var indent := 0 - for idx in range(0, len(resource.events)): - if resource.events[idx]: - var event: DialogicEvent = resource.events[idx] - if event.event_name == 'End Branch': - indent -=1 - continue - - for i in event.empty_lines_above: - timeline_as_text += '\t'.repeat(indent) + '\n' - - if event != null: - timeline_as_text += "\t".repeat(indent)+ event.event_node_as_text + "\n" - if event.can_contain_events: - indent += 1 - if indent < 0: - indent = 0 - - # if events are string lines, just save them - else: - for event in resource.events: - timeline_as_text += event + "\n" - - # Now do the actual saving var file := FileAccess.open(path, FileAccess.WRITE) - if !file: + if not file: print("[Dialogic] Error opening file:", FileAccess.get_open_error()) return ERR_CANT_OPEN file.store_string(timeline_as_text) diff --git a/addons/dialogic/Resources/TimelineResourceSaver.gd.uid b/addons/dialogic/Resources/TimelineResourceSaver.gd.uid index 88afbe2a..9862c88d 100644 --- a/addons/dialogic/Resources/TimelineResourceSaver.gd.uid +++ b/addons/dialogic/Resources/TimelineResourceSaver.gd.uid @@ -1 +1 @@ -uid://cug52prms3don +uid://crtkmees3crbr diff --git a/addons/dialogic/Resources/character.gd b/addons/dialogic/Resources/character.gd index 229d15ef..08989294 100644 --- a/addons/dialogic/Resources/character.gd +++ b/addons/dialogic/Resources/character.gd @@ -1,5 +1,6 @@ @tool -extends Resource +@icon("uid://bbea0efx0ybu7") +extends "res://addons/dialogic/Resources/dialogic_identifiable_resource.gd" class_name DialogicCharacter @@ -30,8 +31,12 @@ enum TranslatedProperties { var _translation_id := "" -func _to_string() -> String: - return "[{name}:{id}]".format({"name":get_character_name(), "id":get_instance_id()}) +func _get_extension() -> String: + return "dch" + + +func _get_resource_name() -> String: + return "DialogicCharacter" ## Adds a translation ID to the character. @@ -125,7 +130,7 @@ func get_display_name_translated() -> String: ## Returns the best name for this character. func get_character_name() -> String: - var unique_identifier := DialogicResourceUtil.get_unique_identifier(resource_path) + var unique_identifier := get_identifier() if not unique_identifier.is_empty(): return unique_identifier if not resource_path.is_empty(): @@ -140,3 +145,13 @@ func get_character_name() -> String: ## Uses the default portrait if the given portrait doesn't exist. func get_portrait_info(portrait_name:String) -> Dictionary: return portraits.get(portrait_name, portraits.get(default_portrait, {})) + + +## Helper method intended for a simplified creation of portraits at runtime. +## For more complex needs, manually writing to the portraits dict is recommended. +func add_portrait(name:String, image:String, scene:= "") -> void: + portraits[name] = { + "scene": scene, + "export_overrides": { + "image": image} + } diff --git a/addons/dialogic/Resources/character.gd.uid b/addons/dialogic/Resources/character.gd.uid index 8f6d2e40..7baf4d93 100644 --- a/addons/dialogic/Resources/character.gd.uid +++ b/addons/dialogic/Resources/character.gd.uid @@ -1 +1 @@ -uid://w3vtr3asq7b3 +uid://don4ds5f38byo diff --git a/addons/dialogic/Resources/dialogic_identifiable_resource.gd b/addons/dialogic/Resources/dialogic_identifiable_resource.gd new file mode 100644 index 00000000..ceb6adc7 --- /dev/null +++ b/addons/dialogic/Resources/dialogic_identifiable_resource.gd @@ -0,0 +1,36 @@ +@tool +extends Resource + + +func _get_extension() -> String: + return "" + + +func _get_resource_name() -> String: + return "DialogicIdentifiableResource" + + +func _to_string() -> String: + return "[{name}:{id}]".format({"name":_get_resource_name(), "id":get_identifier()}) + + +## Returns the best name for this character. +func get_identifier() -> String: + if resource_path: + return DialogicResourceUtil.get_unique_identifier_by_path(resource_path) + if not Engine.is_editor_hint(): + return DialogicResourceUtil.get_runtime_unique_identifier(self, _get_extension()) + return "" + + +## Sets the unique identifier-string of this resource. +## In editor (if the resource is already saved) the identifier will be stored. +## In game (if the resource is not stored) the resource will be temporarily registered. +func set_identifier(new_identifier:String) -> bool: + if resource_path and Engine.is_editor_hint(): + DialogicResourceUtil.change_unique_identifier(resource_path, new_identifier) + return true + if not resource_path and not Engine.is_editor_hint(): + DialogicResourceUtil.register_runtime_resource(self, new_identifier, _get_extension()) + return true + return false diff --git a/addons/dialogic/Resources/dialogic_identifiable_resource.gd.uid b/addons/dialogic/Resources/dialogic_identifiable_resource.gd.uid new file mode 100644 index 00000000..558c47f9 --- /dev/null +++ b/addons/dialogic/Resources/dialogic_identifiable_resource.gd.uid @@ -0,0 +1 @@ +uid://de6cm6skfjtni diff --git a/addons/dialogic/Resources/dialogic_layout_base.gd b/addons/dialogic/Resources/dialogic_layout_base.gd index 16a2ee4a..832a43dd 100644 --- a/addons/dialogic/Resources/dialogic_layout_base.gd +++ b/addons/dialogic/Resources/dialogic_layout_base.gd @@ -58,12 +58,14 @@ func _apply_export_overrides() -> void: #region HANDLE PERSISTENT DATA ################################################################################ -func _enter_tree() -> void: +func _init() -> void: _load_persistent_info(Engine.get_meta("dialogic_persistent_style_info", {})) func _exit_tree() -> void: - Engine.set_meta("dialogic_persistent_style_info", _get_persistent_info()) + var info: Dictionary = Engine.get_meta("dialogic_persistent_style_info", {}) + info.merge(_get_persistent_info(), true) + Engine.set_meta("dialogic_persistent_style_info", info) ## To be overwritten. Return any info that a later used style might want to know. @@ -72,7 +74,7 @@ func _get_persistent_info() -> Dictionary: ## To be overwritten. Apply any info that a previous style might have stored and this style should use. -func _load_persistent_info(info: Dictionary) -> void: +func _load_persistent_info(_info: Dictionary) -> void: pass #endregion diff --git a/addons/dialogic/Resources/dialogic_layout_base.gd.uid b/addons/dialogic/Resources/dialogic_layout_base.gd.uid index 02ac54fa..f345539c 100644 --- a/addons/dialogic/Resources/dialogic_layout_base.gd.uid +++ b/addons/dialogic/Resources/dialogic_layout_base.gd.uid @@ -1 +1 @@ -uid://cd42fevaaab2x +uid://c0qys72ixawvk diff --git a/addons/dialogic/Resources/dialogic_layout_layer.gd.uid b/addons/dialogic/Resources/dialogic_layout_layer.gd.uid index 2e1a5774..80046170 100644 --- a/addons/dialogic/Resources/dialogic_layout_layer.gd.uid +++ b/addons/dialogic/Resources/dialogic_layout_layer.gd.uid @@ -1 +1 @@ -uid://bvd0nw6f6mrhk +uid://c8d470kti274h diff --git a/addons/dialogic/Resources/dialogic_style.gd b/addons/dialogic/Resources/dialogic_style.gd index 62268174..ecc9b7a8 100644 --- a/addons/dialogic/Resources/dialogic_style.gd +++ b/addons/dialogic/Resources/dialogic_style.gd @@ -73,7 +73,7 @@ func get_layer_info(id:String) -> Dictionary: if layer_resource.scene != null: info.path = layer_resource.scene.resource_path elif id == "": - info.path = DialogicUtil.get_default_layout_base().resource_path + info.path = DialogicStylesUtil.get_default_layout_base().resource_path info.overrides = layer_resource.overrides.duplicate() @@ -122,7 +122,7 @@ func move_layer(from_index:int, to_index:int) -> void: if not has_layer_index(from_index) or not has_layer_index(to_index-1): return - var id := layer_list.pop_at(from_index) + var id: String = layer_list.pop_at(from_index) layer_list.insert(to_index, id) changed.emit() @@ -132,7 +132,6 @@ func move_layer(from_index:int, to_index:int) -> void: func set_layer_scene(layer_id:String, scene:String) -> void: if not has_layer(layer_id): return - layer_info[layer_id].scene = load(scene) changed.emit() @@ -188,8 +187,8 @@ func get_inheritance_root() -> DialogicStyle: ## This merges some [param layer_info] with it's param ancestors layer info. -func merge_layer_infos(layer_info:Dictionary, ancestor_info:Dictionary) -> Dictionary: - var combined := layer_info.duplicate(true) +func merge_layer_infos(new_layer_info:Dictionary, ancestor_info:Dictionary) -> Dictionary: + var combined := new_layer_info.duplicate(true) combined.path = ancestor_info.path combined.overrides.merge(ancestor_info.overrides) @@ -247,8 +246,8 @@ func clone() -> DialogicStyle: style.inherits = inherits var base_info := get_layer_info("") - set_layer_scene("", base_info.path) - set_layer_overrides("", base_info.overrides) + style.set_layer_scene("", base_info.path) + style.set_layer_overrides("", base_info.overrides) for id in layer_list: var info := get_layer_info(id) diff --git a/addons/dialogic/Resources/dialogic_style.gd.uid b/addons/dialogic/Resources/dialogic_style.gd.uid index 636e4fe9..ec28dc4a 100644 --- a/addons/dialogic/Resources/dialogic_style.gd.uid +++ b/addons/dialogic/Resources/dialogic_style.gd.uid @@ -1 +1 @@ -uid://dfja8ptqdlfix +uid://dv08k6ljua6fm diff --git a/addons/dialogic/Resources/dialogic_style_layer.gd b/addons/dialogic/Resources/dialogic_style_layer.gd index a7598cdd..9b7e9105 100644 --- a/addons/dialogic/Resources/dialogic_style_layer.gd +++ b/addons/dialogic/Resources/dialogic_style_layer.gd @@ -12,3 +12,10 @@ func _init(scene_path:Variant=null, scene_overrides:Dictionary={}): elif scene_path is String and ResourceLoader.exists(scene_path): scene = load(scene_path) overrides = scene_overrides + + +func _to_string() -> String: + if scene: + return "" + else: + return "" diff --git a/addons/dialogic/Resources/dialogic_style_layer.gd.uid b/addons/dialogic/Resources/dialogic_style_layer.gd.uid index 846b4ae0..e8d027c0 100644 --- a/addons/dialogic/Resources/dialogic_style_layer.gd.uid +++ b/addons/dialogic/Resources/dialogic_style_layer.gd.uid @@ -1 +1 @@ -uid://dh4po8pgey4yv +uid://bwg6yncmh2cml diff --git a/addons/dialogic/Resources/event.gd b/addons/dialogic/Resources/event.gd index 3c589611..d3116ab7 100644 --- a/addons/dialogic/Resources/event.gd +++ b/addons/dialogic/Resources/event.gd @@ -52,7 +52,11 @@ var empty_lines_above: int = 0 ### Editor UI Properties ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ## The event color that event node will take in the editor -var event_color := Color("FBB13C") +var event_color := Color("FBB13C"): + get: + if dialogic_color_name: + return DialogicUtil.get_color(dialogic_color_name) + return event_color ## If you are using the default color palette var dialogic_color_name: = "" ## To sort the buttons shown in the editor. Lower index is placed at the top of a category @@ -93,7 +97,7 @@ enum ValueType { NUMBER, VECTOR2, VECTOR3, VECTOR4, # Other - CUSTOM, BUTTON, LABEL, COLOR, AUDIO_PREVIEW + CUSTOM, BUTTON, LABEL, COLOR, AUDIO_PREVIEW, IMAGE_PREVIEW } ## List that stores the fields for the editor var editor_list: Array = [] @@ -101,7 +105,9 @@ var editor_list: Array = [] var this_folder: String = get_script().resource_path.get_base_dir() ## Singal that notifies the visual editor block to update +@warning_ignore("unused_signal") signal ui_update_needed +@warning_ignore("unused_signal") signal ui_update_warning(text:String) @@ -142,23 +148,38 @@ func _execute() -> void: #endregion -#region OVERRIDABLES +#region BRANCHING EVENTS ################################################################################ +## All of this section should only be in use if [member can_contain_events] is `true`. -## to be overridden by sub-classes -## only called if can_contain_events is true. -## return a control node that should show on the END BRANCH node -func get_end_branch_control() -> Control: + +## To be overridden. Only called if [member can_contain_events] is `true`. +## Return a control node that should show on the END BRANCH node. +func _get_end_branch_control() -> Control: return null -## to be overridden by sub-classes -## only called if can_contain_events is true and the previous event was an end-branch event -## return true if this event should be executed if the previous event was an end-branch event -## basically only important for the Condition event but who knows. Some day someone might need this. -func should_execute_this_branch() -> bool: +## To be overridden. Return `true` if this event should be executed even if a previous branch has been executed. +## E.g. IF events returns true, but ELIF and ELSE do not. The first choice of a question does this, while the others don't. +func _is_branch_starter() -> bool: return false + +## Returns the index of the end branch event of this event (Only use if can_contain_events is true). +func get_end_branch_index() -> int: + var idx: int = dialogic.current_timeline_events.find(self) + while true: + idx += 1 + var event: DialogicEvent = dialogic.current_timeline.get_event(idx) + if not event: + break + if event.can_contain_events: + idx = event.get_end_branch_index() + if event is DialogicEndBranchEvent: + break + return idx + + #endregion @@ -249,6 +270,21 @@ func _test_event_string(string:String) -> bool: return is_valid_event(string.get_slice('#id:', 0)) return is_valid_event(string.strip_edges()) + +func get_dependencies() -> PackedStringArray: + var deps := PackedStringArray() + var params := get_shortcode_parameters() + for i in params: + if params[i].has("ext_file"): + var path: String = get(params[i].property) + if path.begins_with("res://") or path.begins_with("uid://"): + deps.append(path) + elif i == "character": + deps.append(DialogicResourceUtil.get_resource_path_from_identifier(path, "dch")) + elif i == "timeline": + deps.append(DialogicResourceUtil.get_resource_path_from_identifier(path, "dtl")) + return deps + #endregion @@ -422,6 +458,9 @@ func _get_icon() -> Resource: func set_default_color(value:Variant) -> void: + # Skip in running games + if not Engine.is_editor_hint(): + return dialogic_color_name = value event_color = DialogicUtil.get_color(value) @@ -466,6 +505,8 @@ func get_event_editor_info() -> Array: else: editor_list = [] + if DialogicUtil.get_editor_setting('show_event_names', false): + add_header_label(event_name) build_event_editor() return editor_list else: @@ -483,7 +524,7 @@ func build_event_editor() -> void: ## @left_text: Text that will be shown to the left of the field ## @right_text: Text that will be shown to the right of the field ## @extra_info: Allows passing a lot more info to the field. -## What info can be passed is differnet for every field +## What info can be passed is different for every field func add_header_label(text:String, condition:= "") -> void: editor_list.append({ diff --git a/addons/dialogic/Resources/event.gd.uid b/addons/dialogic/Resources/event.gd.uid index b7a8cd17..feb7eec2 100644 --- a/addons/dialogic/Resources/event.gd.uid +++ b/addons/dialogic/Resources/event.gd.uid @@ -1 +1 @@ -uid://der4v0svcgi5f +uid://dw4fa15orthvq diff --git a/addons/dialogic/Resources/timeline.gd b/addons/dialogic/Resources/timeline.gd index 651053cc..a92049f7 100644 --- a/addons/dialogic/Resources/timeline.gd +++ b/addons/dialogic/Resources/timeline.gd @@ -1,17 +1,24 @@ @tool -extends Resource +@icon("uid://j7ym07anlusi") +extends "res://addons/dialogic/Resources/dialogic_identifiable_resource.gd" class_name DialogicTimeline ## Resource that defines a list of events. ## It can store them as text and load them from text too. + var events: Array = [] var events_processed := false +var text_lines_indexed := {} +var indent_format := "\t" -## Method used for printing timeline resources identifiably -func _to_string() -> String: - return "[DialogicTimeline:{file}]".format({"file":resource_path}) +func _get_extension() -> String: + return "dtl" + + +func _get_resource_name() -> String: + return "DialogicTimeline" ## Helper method @@ -27,6 +34,13 @@ func from_text(text:String) -> void: events = text.split('\n', true) events_processed = false + ## Take an initial guess about the indentation format + ## because the text editor needs it but doesn't call _process() + for ev in events: + indent_format = ev.substr(0, len(ev) - len(ev.strip_edges(true, false))) + if indent_format: + break + ## Stores all events in their text format and returns them as a string func as_text() -> String: @@ -43,8 +57,8 @@ func as_text() -> String: if event != null: for i in event.empty_lines_above: - result += "\t".repeat(indent)+"\n" - result += "\t".repeat(indent)+event.event_node_as_text.replace('\n', "\n"+"\t".repeat(indent)) + "\n" + result += indent_format.repeat(indent)+"\n" + result += indent_format.repeat(indent)+event.event_node_as_text.replace('\n', "\n"+indent_format.repeat(indent)) + "\n" if event.can_contain_events: indent += 1 if indent < 0: @@ -58,8 +72,18 @@ func as_text() -> String: return result.strip_edges() +## Returns the index of the event that corresponds to a specific line +func get_index_from_text_line(text:String, line) -> int: + from_text(text) + process() + return text_lines_indexed[line] + + ## Method that loads all the event resources from the strings, if it wasn't done before func process() -> void: + if len(events) == 0: + return + if typeof(events[0]) == TYPE_STRING: events_processed = false @@ -73,7 +97,9 @@ func process() -> void: var end_event := DialogicEndBranchEvent.new() var prev_indent := "" + indent_format = "" var processed_events := [] + text_lines_indexed = {} # this is needed to add an end branch event even to empty conditions/choices var prev_was_opener := false @@ -83,6 +109,7 @@ func process() -> void: var empty_lines := 0 while idx < len(lines)-1: idx += 1 + text_lines_indexed[idx] = len(processed_events) # make sure we are using the string version, in case this was already converted var line := "" @@ -99,8 +126,14 @@ func process() -> void: ## Add an end event if the indent is smaller then previously var indent: String = line.substr(0,len(line)-len(line_stripped)) + if indent and ((not indent_format) or not (indent_format in indent)): + if not indent_format.is_empty(): + printerr("Timeline contains varying indentation. Found {0} instead of expected {1}.".format([indent, indent_format])) + else: + indent_format = indent if len(indent) < len(prev_indent): - for i in range(len(prev_indent)-len(indent)): + @warning_ignore("integer_division") + for i in range(len(prev_indent)/len(indent_format)-len(indent)/len(indent_format)): processed_events.append(end_event.duplicate()) ## Add an end event if the indent is the same but the previous was an opener ## (so for example choice that is empty) @@ -112,16 +145,13 @@ func process() -> void: ## Now we process the event into a resource ## by checking on each event if it recognizes this string var event_content: String = line_stripped - var event: DialogicEvent - for i in event_cache: - if i._test_event_string(event_content): - event = i.duplicate() - break + var event: DialogicEvent = event_from_string(event_content, event_cache) event.empty_lines_above = empty_lines # add the following lines until the event says it's full or there is an empty line - while !event.is_string_full_event(event_content): + while not event.is_string_full_event(event_content): idx += 1 + text_lines_indexed[idx] = len(processed_events) if idx == len(lines): break @@ -132,20 +162,24 @@ func process() -> void: event_content += "\n"+following_line_stripped - event._load_from_string(event_content) event.event_node_as_text = event_content + event._load_from_string(event_content) processed_events.append(event) prev_was_opener = event.can_contain_events empty_lines = 0 - if !prev_indent.is_empty(): + if not prev_indent.is_empty(): for i in range(len(prev_indent)): processed_events.append(end_event.duplicate()) events = processed_events events_processed = true + if indent_format.is_empty(): + indent_format = "\t" + + ## This method makes sure that all events in a timeline are correctly reset func clean() -> void: @@ -164,3 +198,10 @@ func clean() -> void: for con_out in event.get_signal_connection_list(sig.name): con_out.signal.disconnect(con_out.callable) unreference() + + +static func event_from_string(event_content:String, event_cache:Array) -> DialogicEvent: + for i in event_cache: + if i._test_event_string(event_content): + return i.duplicate() + return DialogicTextEvent.new() diff --git a/addons/dialogic/Resources/timeline.gd.uid b/addons/dialogic/Resources/timeline.gd.uid index e0324c66..c5d39682 100644 --- a/addons/dialogic/Resources/timeline.gd.uid +++ b/addons/dialogic/Resources/timeline.gd.uid @@ -1 +1 @@ -uid://c15y0po020ftd +uid://cm0lw40qto3sd diff --git a/addons/dialogic/plugin.cfg b/addons/dialogic/plugin.cfg index 7e03cbf4..951b2307 100644 --- a/addons/dialogic/plugin.cfg +++ b/addons/dialogic/plugin.cfg @@ -4,5 +4,5 @@ name="Dialogic" description="Create dialogs, characters and scenes to display conversations in your Godot games. https://github.com/dialogic-godot/dialogic" author="Jowan Spooner, Emi, Cake and more!" -version="2.0-Alpha-16 (Godot 4.2+)" +version="2.0-Alpha-18 (Godot 4.3+)" script="plugin.gd" diff --git a/addons/dialogic/plugin.gd.uid b/addons/dialogic/plugin.gd.uid index ed05d673..ab6d7066 100644 --- a/addons/dialogic/plugin.gd.uid +++ b/addons/dialogic/plugin.gd.uid @@ -1 +1 @@ -uid://btf066tkq81q7 +uid://bu26lw872ifba