diff --git a/addons/dialogic/Core/DialogicResourceUtil.gd b/addons/dialogic/Core/DialogicResourceUtil.gd index d8e978fa0..6bb6b17b4 100644 --- a/addons/dialogic/Core/DialogicResourceUtil.gd +++ b/addons/dialogic/Core/DialogicResourceUtil.gd @@ -218,8 +218,6 @@ static func guess_special_resource(type: String, string: String, default := {}, printerr("[Dialogic] No ", type, "s found, but attempted to use one.") return default - string = string.to_lower() - if string.begins_with('res://'): for i in resources.values(): if i.path == string: @@ -227,6 +225,8 @@ static func guess_special_resource(type: String, string: String, default := {}, printerr("[Dialogic] Unable to find ", type, " at path '", string, "'.") return default + string = string.to_lower() + if string in resources: return resources[string] diff --git a/addons/dialogic/Editor/editor_main.gd b/addons/dialogic/Editor/editor_main.gd index f5c60d6e1..5d7aa96e3 100644 --- a/addons/dialogic/Editor/editor_main.gd +++ b/addons/dialogic/Editor/editor_main.gd @@ -15,7 +15,7 @@ func _ready() -> void: ## REFERENCES editors_manager = $EditorsManager - var button :Button = editors_manager.add_icon_button(get_theme_icon("MakeFloating", "EditorIcons"), 'Make floating') + var button: Button = editors_manager.add_icon_button(get_theme_icon("MakeFloating", "EditorIcons"), 'Make floating') button.pressed.connect(toggle_floating_window) # File dialog @@ -86,7 +86,7 @@ func update_theme_additions() -> void: # panel used for example for portrait previews in character editor theme.set_type_variation('DialogicPanelB', 'PanelContainer') - var side_panel :StyleBoxFlat= panel_style.duplicate() + var side_panel: StyleBoxFlat = panel_style.duplicate() side_panel.corner_radius_top_left = 0 side_panel.corner_radius_bottom_left = 0 side_panel.expand_margin_left = 8 diff --git a/addons/dialogic/Modules/Character/subsystem_containers.gd b/addons/dialogic/Modules/Character/subsystem_containers.gd index a129d52ae..cf89c3476 100644 --- a/addons/dialogic/Modules/Character/subsystem_containers.gd +++ b/addons/dialogic/Modules/Character/subsystem_containers.gd @@ -181,7 +181,7 @@ 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.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_portraits.gd b/addons/dialogic/Modules/Character/subsystem_portraits.gd index b7377be89..e09025417 100644 --- a/addons/dialogic/Modules/Character/subsystem_portraits.gd +++ b/addons/dialogic/Modules/Character/subsystem_portraits.gd @@ -255,6 +255,7 @@ func _animate_node(node: Node, animation_path: String, length: float, repeats := func _move_character(character_node: Node2D, transform:="", time := 0.0, easing:= Tween.EASE_IN_OUT, trans:= Tween.TRANS_SINE) -> void: var tween := character_node.create_tween().set_ease(easing).set_trans(trans).set_parallel() if time == 0: + tween.kill() tween = null var container: DialogicNode_PortraitContainer = character_node.get_parent() dialogic.PortraitContainers.move_container(container, transform, tween, time) diff --git a/addons/dialogic/Modules/Core/subsystem_animation.gd b/addons/dialogic/Modules/Core/subsystem_animation.gd index cffba65a5..476913442 100644 --- a/addons/dialogic/Modules/Core/subsystem_animation.gd +++ b/addons/dialogic/Modules/Core/subsystem_animation.gd @@ -3,24 +3,40 @@ extends DialogicSubsystem ## Subsystem that allows entering and leaving an animation state. signal finished +signal animation_interrupted -var prev_state: int = 0 +var prev_state: DialogicGameHandler.States = DialogicGameHandler.States.IDLE +var _is_animating := false #region MAIN METHODS #################################################################################################### +func clear_game_state(_clear_flag := DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void: + stop_animation() + + func is_animating() -> bool: - return dialogic.current_state == dialogic.States.ANIMATING + return _is_animating func start_animating() -> void: prev_state = dialogic.current_state dialogic.current_state = dialogic.States.ANIMATING + _is_animating = true func animation_finished(_arg := "") -> void: + # It can happen that the animation state has already been stopped + if not is_animating(): + return + _is_animating = false dialogic.current_state = prev_state as DialogicGameHandler.States finished.emit() + +func stop_animation() -> void: + animation_finished() + animation_interrupted.emit() + #endregion diff --git a/addons/dialogic/Modules/Core/subsystem_input.gd b/addons/dialogic/Modules/Core/subsystem_input.gd index 59d29d6cc..6c9164b96 100644 --- a/addons/dialogic/Modules/Core/subsystem_input.gd +++ b/addons/dialogic/Modules/Core/subsystem_input.gd @@ -92,7 +92,7 @@ func handle_input() -> void: ## Unhandled Input is used for all NON-Mouse based inputs. func _unhandled_input(event:InputEvent) -> void: - if Input.is_action_just_pressed(ProjectSettings.get_setting(_SETTING_INPUT_ACTION, _SETTING_INPUT_ACTION_DEFAULT), true): + if is_input_pressed(event, true): if event is InputEventMouse: return handle_input() @@ -101,14 +101,18 @@ func _unhandled_input(event:InputEvent) -> void: ## Input is used for all mouse based inputs. ## If any DialogicInputNode is present this won't do anything (because that node handles MouseInput then). func _input(event:InputEvent) -> void: - if Input.is_action_just_pressed(ProjectSettings.get_setting(_SETTING_INPUT_ACTION, _SETTING_INPUT_ACTION_DEFAULT)): - + if is_input_pressed(event): if not event is InputEventMouse or get_tree().get_nodes_in_group('dialogic_input').any(func(node):return node.is_visible_in_tree()): return handle_input() +func is_input_pressed(event: InputEvent, exact := false) -> bool: + var action := ProjectSettings.get_setting(_SETTING_INPUT_ACTION, _SETTING_INPUT_ACTION_DEFAULT) + return (event is InputEventAction and event.action == action) or Input.is_action_just_pressed(action, exact) + + ## This is called from the gui_input of the InputCatcher and DialogText nodes func handle_node_gui_input(event:InputEvent) -> void: if Input.is_action_just_pressed(ProjectSettings.get_setting(_SETTING_INPUT_ACTION, _SETTING_INPUT_ACTION_DEFAULT)): diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd index ce69740cb..6e2e0e403 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_Textbubble/text_bubble.gd @@ -193,7 +193,7 @@ func add_choice_container(node:Container, alignment:=FlowContainer.ALIGNMENT_BEG func get_speaker_canvas_position() -> Vector2: - if node_to_point_at: + if is_instance_valid(node_to_point_at): if node_to_point_at is Node3D: base_position = get_viewport().get_camera_3d().unproject_position( (node_to_point_at as Node3D).global_position) diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd index 43eca1f7d..c03b3ee0d 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Textbox/animations.gd @@ -7,11 +7,12 @@ enum AnimationsIn {NONE, POP_IN, FADE_UP} enum AnimationsOut {NONE, POP_OUT, FADE_DOWN} enum AnimationsNewText {NONE, WIGGLE} -var animation_in : AnimationsIn -var animation_out : AnimationsOut -var animation_new_text : AnimationsNewText +var animation_in: AnimationsIn +var animation_out: AnimationsOut +var animation_new_text: AnimationsNewText + +var full_clear := true -var full_clear : bool = true func get_text_panel() -> PanelContainer: return %DialogTextPanel @@ -22,19 +23,20 @@ func get_dialog() -> DialogicNode_DialogText: func _ready() -> void: - var text_system : Node = DialogicUtil.autoload().get(&'Text') - var _error : int = 0 - _error = text_system.connect(&'animation_textbox_hide', _on_textbox_hide) - _error = text_system.connect(&'animation_textbox_show', _on_textbox_show) - _error = text_system.connect(&'animation_textbox_new_text', _on_textbox_new_text) - _error = text_system.connect(&'about_to_show_text', _on_about_to_show_text) + var text_system: Node = DialogicUtil.autoload().get(&'Text') + text_system.connect(&'animation_textbox_hide', _on_textbox_hide) + text_system.connect(&'animation_textbox_show', _on_textbox_show) + text_system.connect(&'animation_textbox_new_text', _on_textbox_new_text) + text_system.connect(&'about_to_show_text', _on_about_to_show_text) + var animation_system: Node = DialogicUtil.autoload().get(&'Animations') + animation_system.connect(&'animation_interrupted', _on_animation_interrupted) func _on_textbox_show() -> void: if animation_in == AnimationsIn.NONE: return play('RESET') - var animation_system : Node = DialogicUtil.autoload().get(&'Animations') + var animation_system: Node = DialogicUtil.autoload().get(&'Animations') animation_system.call(&'start_animating') get_text_panel().get_parent().get_parent().set(&'modulate', Color.TRANSPARENT) get_dialog().text = "" @@ -43,15 +45,15 @@ func _on_textbox_show() -> void: play("textbox_pop") AnimationsIn.FADE_UP: play("textbox_fade_up") - if not is_connected(&'animation_finished', Callable(animation_system, &'animation_finished')): - var _error : int = connect(&'animation_finished', Callable(animation_system, &'animation_finished'), CONNECT_ONE_SHOT) + if not animation_finished.is_connected(Callable(animation_system, &'animation_finished')): + animation_finished.connect(Callable(animation_system, &'animation_finished'), CONNECT_ONE_SHOT) func _on_textbox_hide() -> void: if animation_out == AnimationsOut.NONE: return play('RESET') - var animation_system : Node = DialogicUtil.autoload().get(&'Animations') + var animation_system: Node = DialogicUtil.autoload().get(&'Animations') animation_system.call(&'start_animating') match animation_out: AnimationsOut.POP_OUT: @@ -59,8 +61,8 @@ func _on_textbox_hide() -> void: AnimationsOut.FADE_DOWN: play_backwards("textbox_fade_up") - if not is_connected(&'animation_finished', Callable(animation_system, &'animation_finished')): - var _error : int = connect(&'animation_finished', Callable(animation_system, &'animation_finished'), CONNECT_ONE_SHOT) + if not animation_finished.is_connected(Callable(animation_system, &'animation_finished')): + animation_finished.connect(Callable(animation_system, &'animation_finished'), CONNECT_ONE_SHOT) func _on_about_to_show_text(info:Dictionary) -> void: @@ -74,7 +76,7 @@ func _on_textbox_new_text() -> void: if animation_new_text == AnimationsNewText.NONE: return - var animation_system : Node = DialogicUtil.autoload().get(&'Animation') + var animation_system: Node = DialogicUtil.autoload().get(&'Animations') animation_system.call(&'start_animating') if full_clear: get_dialog().text = "" @@ -82,5 +84,10 @@ func _on_textbox_new_text() -> void: AnimationsNewText.WIGGLE: play("new_text") - if not is_connected(&'animation_finished', Callable(animation_system, &'animation_finished')): - var _error : int = connect(&'animation_finished', Callable(animation_system, &'animation_finished'), CONNECT_ONE_SHOT) + if not animation_finished.is_connected(Callable(animation_system, &'animation_finished')): + animation_finished.connect(Callable(animation_system, &'animation_finished'), CONNECT_ONE_SHOT) + + +func _on_animation_interrupted() -> void: + if is_playing(): + stop() diff --git a/addons/dialogic/Modules/Text/auto_advance.gd b/addons/dialogic/Modules/Text/auto_advance.gd index baa566b7a..c48d1a791 100644 --- a/addons/dialogic/Modules/Text/auto_advance.gd +++ b/addons/dialogic/Modules/Text/auto_advance.gd @@ -1,5 +1,5 @@ -extends RefCounted class_name DialogicAutoAdvance +extends RefCounted ## This class holds the settings for the Auto-Advance feature. ## Changing the variables will alter the behaviour of Auto-Advance. ## diff --git a/addons/dialogic/Modules/Text/auto_skip.gd b/addons/dialogic/Modules/Text/auto_skip.gd index 84f42f8e3..2a614f257 100644 --- a/addons/dialogic/Modules/Text/auto_skip.gd +++ b/addons/dialogic/Modules/Text/auto_skip.gd @@ -1,5 +1,5 @@ -extends RefCounted class_name DialogicAutoSkip +extends RefCounted ## This class holds the settings for the Auto-Skip feature. ## Changing the variables will alter the behaviour of Auto-Skip. ## @@ -40,7 +40,7 @@ var time_per_event: float = 0.1 func _init() -> void: time_per_event = ProjectSettings.get_setting('dialogic/text/autoskip_time_per_event', time_per_event) - if DialogicUtil.autoload().has_subsystem('History'): + if DialogicUtil.autoload().has_subsystem("History") and not DialogicUtil.autoload().History.visited_event.is_connected(_handle_seen_event): DialogicUtil.autoload().History.visited_event.connect(_handle_seen_event) DialogicUtil.autoload().History.unvisited_event.connect(_handle_unseen_event) diff --git a/addons/dialogic/Modules/Text/subsystem_text.gd b/addons/dialogic/Modules/Text/subsystem_text.gd index 8a7e4d475..1c8adbe75 100644 --- a/addons/dialogic/Modules/Text/subsystem_text.gd +++ b/addons/dialogic/Modules/Text/subsystem_text.gd @@ -123,7 +123,6 @@ func update_textbox(text: String, instant := false) -> void: func update_dialog_text(text: String, instant := false, additional := false) -> String: update_text_speed() - if !instant: dialogic.current_state = dialogic.States.REVEALING_TEXT if additional: @@ -195,7 +194,7 @@ func show_textbox(instant:=false) -> void: for text_node in get_tree().get_nodes_in_group('dialogic_dialog_text'): if not text_node.enabled: continue - if !text_node.textbox_root.visible and !emitted: + if not text_node.textbox_root.visible and not emitted: animation_textbox_show.emit() text_node.textbox_root.show() if dialogic.Animations.is_animating(): diff --git a/addons/dialogic/Modules/Wait/event_wait.gd b/addons/dialogic/Modules/Wait/event_wait.gd index b37cc3cd5..699e69c17 100644 --- a/addons/dialogic/Modules/Wait/event_wait.gd +++ b/addons/dialogic/Modules/Wait/event_wait.gd @@ -24,11 +24,15 @@ func _execute() -> void: var time_per_event: float = dialogic.Inputs.auto_skip.time_per_event final_wait_time = min(time, time_per_event) + dialogic.current_state = dialogic.States.WAITING + if hide_text and dialogic.has_subsystem("Text"): - dialogic.Text.update_dialog_text('') + dialogic.Text.update_dialog_text('', true) dialogic.Text.hide_textbox() - dialogic.current_state = dialogic.States.WAITING - await dialogic.get_tree().create_timer(time, false, DialogicUtil.is_physics_timer()).timeout + + await dialogic.get_tree().create_timer(final_wait_time, false, DialogicUtil.is_physics_timer()).timeout + if dialogic.Animations.is_animating(): + dialogic.Animations.stop_animation() dialogic.current_state = dialogic.States.IDLE finish()