diff --git a/addons/dialogic/Modules/Background/default_background.gd b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd similarity index 91% rename from addons/dialogic/Modules/Background/default_background.gd rename to addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd index 675f0f4e6..ce4d217bb 100644 --- a/addons/dialogic/Modules/Background/default_background.gd +++ b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.gd @@ -25,7 +25,3 @@ func _update_background(argument:String, time:float) -> void: else: image_node.texture = null color_node.color = Color.from_string(argument, Color.TRANSPARENT) - - -func _should_do_background_update(argument:String) -> bool: - return false diff --git a/addons/dialogic/Modules/Background/default_background.tscn b/addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.tscn similarity index 90% rename from addons/dialogic/Modules/Background/default_background.tscn rename to addons/dialogic/Modules/Background/DefaultBackgroundScene/default_background.tscn index 0e5057446..e72fdc2cf 100644 --- a/addons/dialogic/Modules/Background/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" path="res://addons/dialogic/Modules/Background/default_background.gd" id="1_nkdrp"] +[ext_resource type="Script" 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 b/addons/dialogic/Modules/Background/Transitions/Defaults/push_down.gd new file mode 100644 index 000000000..80154d9de --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_down.gd @@ -0,0 +1,7 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd" + +func _fade() -> void: + var shader := setup_push_shader() + shader.set_shader_parameter('final_offset', Vector2.DOWN) + tween_shader_progress().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd new file mode 100644 index 000000000..778e4735b --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_left.gd @@ -0,0 +1,7 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd" + +func _fade() -> void: + var shader := setup_push_shader() + shader.set_shader_parameter('final_offset', Vector2.LEFT) + tween_shader_progress().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd new file mode 100644 index 000000000..a7799eb34 --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_right.gd @@ -0,0 +1,7 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd" + +func _fade() -> void: + var shader := setup_push_shader() + shader.set_shader_parameter('final_offset', Vector2.RIGHT) + tween_shader_progress().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd new file mode 100644 index 000000000..e75ec9291 --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/push_up.gd @@ -0,0 +1,7 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd" + +func _fade() -> void: + var shader := setup_push_shader() + shader.set_shader_parameter('final_offset', Vector2.UP) + tween_shader_progress().set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT) + diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd new file mode 100644 index 000000000..917d367fb --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.gd @@ -0,0 +1,13 @@ +extends DialogicBackgroundTransition + + +func _fade() -> void: + var shader := set_shader() + shader.set_shader_parameter("wipe_texture", load(this_folder.path_join("simple_fade.tres"))) + + shader.set_shader_parameter("feather", 1) + + shader.set_shader_parameter("previous_background", prev_texture) + shader.set_shader_parameter("next_background", next_texture) + + tween_shader_progress() diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.tres b/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.tres new file mode 100644 index 000000000..4873e0848 --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/simple_fade.tres @@ -0,0 +1,8 @@ +[gd_resource type="GradientTexture2D" load_steps=2 format=3 uid="uid://qak7mr560k0i"] + +[sub_resource type="Gradient" id="Gradient_skd6w"] +offsets = PackedFloat32Array(1) +colors = PackedColorArray(0.423651, 0.423651, 0.423651, 1) + +[resource] +gradient = SubResource("Gradient_skd6w") diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd new file mode 100644 index 000000000..787ed404f --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_diagonal_up_left.gd @@ -0,0 +1,8 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd" + +func _fade() -> void: + var shader := setup_swipe_shader() + var texture :GradientTexture2D = shader.get_shader_parameter('wipe_texture') + texture.fill_from = Vector2.DOWN + texture.fill_to = Vector2.RIGHT + tween_shader_progress() diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd new file mode 100644 index 000000000..32084e92e --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_left_to_right.gd @@ -0,0 +1,10 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd" + +func _fade() -> void: + var shader := setup_swipe_shader() + var texture :GradientTexture2D = shader.get_shader_parameter('wipe_texture') + + texture.fill_from = Vector2.ZERO + texture.fill_to = Vector2.RIGHT + + tween_shader_progress() diff --git a/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd new file mode 100644 index 000000000..14005d9aa --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/Defaults/swipe_right_to_left.gd @@ -0,0 +1,8 @@ +extends "res://addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd" + +func _fade() -> void: + var shader := setup_swipe_shader() + var texture :GradientTexture2D = shader.get_shader_parameter('wipe_texture') + texture.fill_from = Vector2.RIGHT + texture.fill_to = Vector2.ZERO + tween_shader_progress() diff --git a/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd b/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd new file mode 100644 index 000000000..f35ce6d39 --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/class_dialogic_background_transition.gd @@ -0,0 +1,56 @@ +class_name DialogicBackgroundTransition +extends Node + +## Helper +var this_folder : String = get_script().resource_path.get_base_dir() + + +## Set before _fade() is called, will be the root node of the previous bg scene. +var prev_scene: Node +## Set before _fade() is called, will be the viewport texture of the previous bg scene. +var prev_texture: ViewportTexture + +## Set before _fade() is called, will be the root node of the upcoming bg scene. +var next_scene: Node +## Set before _fade() is called, will be the viewport texture of the upcoming bg scene. +var next_texture: ViewportTexture + +## Set before _fade() is called, will be the requested time for the fade +var time: float + +## Set before _fade() is called, will be the background holder (TextureRect) +var bg_holder: DialogicNode_BackgroundHolder + + +signal transition_finished + + +## To be overridden by transitions +func _fade() -> void: + pass + + +func set_shader(path_to_shader:String=DialogicUtil.get_module_path('Background').path_join("Transitions/default_transition_shader.gdshader")) -> ShaderMaterial: + if bg_holder: + if path_to_shader.is_empty(): + bg_holder.material = null + bg_holder.color = Color.TRANSPARENT + return null + bg_holder.material = ShaderMaterial.new() + bg_holder.material.shader = load(path_to_shader) + return bg_holder.material + return null + + +func tween_shader_progress(progress_parameter:="progress") -> PropertyTweener: + if !bg_holder: + return + + if !bg_holder.material is ShaderMaterial: + return + + bg_holder.material.set_shader_parameter("progress", 0.0) + var tween := create_tween() + var tweener := tween.tween_property(bg_holder, "material:shader_parameter/progress", 1.0, time) + tween.tween_callback(emit_signal.bind('transition_finished')) + return tweener diff --git a/addons/dialogic/Modules/Background/default_background_transition.gdshader b/addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader similarity index 76% rename from addons/dialogic/Modules/Background/default_background_transition.gdshader rename to addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader index d631d9ff0..7fc2cf9ed 100644 --- a/addons/dialogic/Modules/Background/default_background_transition.gdshader +++ b/addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader @@ -8,23 +8,25 @@ uniform sampler2D previous_background : source_color, hint_default_transparent; uniform sampler2D next_background : source_color, hint_default_transparent; // The texture used to determine how far along the progress has to be for bending in the new background. -uniform sampler2D whipe_texture : source_color; +uniform sampler2D wipe_texture : source_color; // The size of the trailing smear of the transition. uniform float feather : hint_range(0.0, 1.0, 0.0001) = 0.1; -// Determines if the whipe texture should keep it's aspect ratio when scaled to the screen's size. +// Determines if the wipe texture should keep it's aspect ratio when scaled to the screen's size. uniform bool keep_aspect_ratio = false; void fragment() { vec2 frag_coord = UV; if(keep_aspect_ratio) { - vec2 ratio = (SCREEN_PIXEL_SIZE.x > SCREEN_PIXEL_SIZE.y) // determine how to scale + vec2 ratio = (SCREEN_PIXEL_SIZE.x > SCREEN_PIXEL_SIZE.y) // determine how to scale ? vec2(SCREEN_PIXEL_SIZE.y / SCREEN_PIXEL_SIZE.x, 1) // fit to width : vec2(1, SCREEN_PIXEL_SIZE.x / SCREEN_PIXEL_SIZE.y); // fit to height - frag_coord *= ratio; + + frag_coord *= ratio; + frag_coord += ((vec2(1,1) - ratio) / 2.0); } // get the blend factor between the previous and next background. - float alpha = (texture(whipe_texture, frag_coord).r) - progress; + float alpha = (texture(wipe_texture, frag_coord).r) - progress; float blend_factor = 1. - smoothstep(0., feather, alpha + (feather * (1. -progress))); vec4 old_frag = texture(previous_background, UV); diff --git a/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader b/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader new file mode 100644 index 000000000..0d29bf16f --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/push_transition_shader.gdshader @@ -0,0 +1,17 @@ +shader_type canvas_item; + +uniform vec2 final_offset = vec2(0,-1); +uniform float progress: hint_range(0.0, 1.0); +uniform sampler2D previous_background: source_color, hint_default_transparent; +uniform sampler2D next_background: source_color, hint_default_transparent; + + +void fragment() { + vec2 uv = UV + final_offset * progress*vec2(-1, -1); + + if (uv.x < 1.0 && uv.x > 0.0 && uv.y < 1.0 && uv.y > 0.0){ + COLOR = texture(previous_background, uv, 1); + } else { + COLOR = texture(next_background, uv-final_offset*vec2(-1,-1)); + } +} diff --git a/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd b/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd new file mode 100644 index 000000000..43f1d749a --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/simple_push_transitions.gd @@ -0,0 +1,9 @@ +extends DialogicBackgroundTransition + +func setup_push_shader() -> ShaderMaterial: + var shader := set_shader(DialogicUtil.get_module_path('Background').path_join("Transitions/push_transition_shader.gdshader")) + + shader.set_shader_parameter("previous_background", prev_texture) + shader.set_shader_parameter("next_background", next_texture) + + return shader diff --git a/addons/dialogic/Modules/Background/Transitions/simple_swipe_gradient.tres b/addons/dialogic/Modules/Background/Transitions/simple_swipe_gradient.tres new file mode 100644 index 000000000..8f8a2a550 --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/simple_swipe_gradient.tres @@ -0,0 +1,7 @@ +[gd_resource type="GradientTexture2D" load_steps=2 format=3 uid="uid://cweb3y3xc4uw0"] + +[sub_resource type="Gradient" id="Gradient_skd6w"] +colors = PackedColorArray(0, 0, 0, 1, 0.991164, 0.991164, 0.991164, 1) + +[resource] +gradient = SubResource("Gradient_skd6w") diff --git a/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd b/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd new file mode 100644 index 000000000..5705fc709 --- /dev/null +++ b/addons/dialogic/Modules/Background/Transitions/simple_swipe_transitions.gd @@ -0,0 +1,14 @@ +extends DialogicBackgroundTransition + +func setup_swipe_shader() -> ShaderMaterial: + var shader := set_shader() + shader.set_shader_parameter("wipe_texture", load( + DialogicUtil.get_module_path('Background').path_join("Transitions/simple_swipe_gradient.tres") + )) + + shader.set_shader_parameter("feather", 0.3) + + shader.set_shader_parameter("previous_background", prev_texture) + shader.set_shader_parameter("next_background", next_texture) + + return shader diff --git a/addons/dialogic/Modules/Background/default_background_transition.tres b/addons/dialogic/Modules/Background/default_background_transition.tres deleted file mode 100644 index ec0715918..000000000 --- a/addons/dialogic/Modules/Background/default_background_transition.tres +++ /dev/null @@ -1,9 +0,0 @@ -[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://0wc7bedn7ee8"] - -[ext_resource type="Shader" path="res://addons/dialogic/Modules/Background/default_background_transition.gdshader" id="1_uctph"] - -[resource] -shader = ExtResource("1_uctph") -shader_parameter/progress = 0.035 -shader_parameter/feather = 1.0 -shader_parameter/keep_aspect_ratio = false diff --git a/addons/dialogic/Modules/Background/event_background.gd b/addons/dialogic/Modules/Background/event_background.gd index 405aa742d..0f4ee60cd 100644 --- a/addons/dialogic/Modules/Background/event_background.gd +++ b/addons/dialogic/Modules/Background/event_background.gd @@ -16,6 +16,8 @@ var scene: String = "" var argument: String = "" ## The time the fade animation will take. Leave at 0 for instant change. var fade: float = 0.0 +## Name of the transition to use. +var transition: String = "" ################################################################################ @@ -29,7 +31,8 @@ func _execute() -> void: var time_per_event: float = Dialogic.Input.auto_skip.time_per_event final_fade_duration = min(fade, time_per_event) - dialogic.Backgrounds.update_background(scene, argument, final_fade_duration) + dialogic.Backgrounds.update_background(scene, argument, final_fade_duration, transition) + finish() @@ -55,9 +58,11 @@ func get_shortcode() -> String: func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info - "scene" : {"property": "scene", "default": ""}, - "arg" : {"property": "argument", "default": ""}, - "fade" : {"property": "fade", "default": 0}, + "scene" : {"property": "scene", "default": ""}, + "arg" : {"property": "argument", "default": ""}, + "fade" : {"property": "fade", "default": 0}, + "transition" : {"property": "transition", "default": "", + "suggestions": get_transition_suggestions}, } @@ -72,10 +77,23 @@ func build_event_editor(): 'placeholder': "No background", 'editor_icon':["Image", "EditorIcons"]}, 'scene == ""') - add_header_edit('argument', ValueType.SINGLELINE_TEXT, {'left_text':'Argument:'}, 'scene != ""') - add_body_edit("fade", ValueType.FLOAT, {'left_text':'Fade Time:'}) - add_body_edit("scene", ValueType.FILE, + add_header_edit("scene", ValueType.FILE, {'left_text' :'Scene:', 'file_filter':'*.tscn, *.scn; Scene Files', 'placeholder': "Default scene", 'editor_icon':["PackedScene", "EditorIcons"]}) + add_body_edit('argument', ValueType.SINGLELINE_TEXT, {'left_text':'Argument:'}, 'scene != ""') + add_body_edit("transition", ValueType.COMPLEX_PICKER, + {'left_text':'Transition:', + 'empty_text':'Simple Fade', + 'suggestions_func':get_transition_suggestions, + 'editor_icon':["PopupMenu", "EditorIcons"]}) + add_body_edit("fade", ValueType.FLOAT, {'left_text':'Fade Time:'}) + + +func get_transition_suggestions(filter:String="") -> Dictionary: + var transitions := DialogicResourceUtil.list_special_resources_of_type("BackgroundTransition") + var suggestions := {} + for i in transitions: + suggestions[DialogicUtil.pretty_name(i)] = {'value': DialogicUtil.pretty_name(i), 'editor_icon': ["PopupMenu", "EditorIcons"]} + return suggestions diff --git a/addons/dialogic/Modules/Background/index.gd b/addons/dialogic/Modules/Background/index.gd index 97c05b58f..e25806421 100644 --- a/addons/dialogic/Modules/Background/index.gd +++ b/addons/dialogic/Modules/Background/index.gd @@ -5,6 +5,9 @@ extends DialogicIndexer func _get_events() -> Array: return [this_folder.path_join('event_background.gd')] - func _get_subsystems() -> Array: return [{'name':'Backgrounds', 'script':this_folder.path_join('subsystem_backgrounds.gd')}] + + +func _get_special_resources() -> Array[Dictionary]: + return list_special_resources("Transitions/Defaults", "BackgroundTransition", ".gd") diff --git a/addons/dialogic/Modules/Background/node_background_holder.gd b/addons/dialogic/Modules/Background/node_background_holder.gd index 35f4565ed..6b2c3b520 100644 --- a/addons/dialogic/Modules/Background/node_background_holder.gd +++ b/addons/dialogic/Modules/Background/node_background_holder.gd @@ -4,5 +4,3 @@ extends ColorRect func _ready(): add_to_group('dialogic_background_holders') - if material == null: - material = load("res://addons/dialogic/Modules/Background/default_background_transition.tres") diff --git a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd index 8e73751e3..72a1eca90 100644 --- a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd +++ b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd @@ -7,7 +7,8 @@ signal background_changed(info:Dictionary) var _tween: Tween var _tween_callbacks: Array[Callable] -var default_background_scene: PackedScene = load(get_script().resource_path.get_base_dir().path_join('default_background.tscn')) +var default_background_scene: PackedScene = load(get_script().resource_path.get_base_dir().path_join('DefaultBackgroundScene/default_background.tscn')) +var default_transition: String = get_script().resource_path.get_base_dir().path_join("Transitions/Defaults/simple_fade.gd") #################################################################################################### ## STATE @@ -34,16 +35,21 @@ func load_game_state(load_flag:=LoadFlags.FULL_LOAD): ## and use the same scene. ## To do so implement [_should_do_background_update()] on the custom background scene. ## Then [_update_background()] will be called directly on that previous scene. -func update_background(scene:String = '', argument:String = '', fade_time:float = 0.0) -> void: +func update_background(scene:String = '', argument:String = '', fade_time:float = 0.0, transition_path:=default_transition) -> void: var background_holder: DialogicNode_BackgroundHolder = get_tree().get_first_node_in_group('dialogic_background_holders') if background_holder == null: return var info := {'scene':scene, 'argument':argument, 'fade_time':fade_time, 'same_scene':false} + var bg_set := false # First try just updating the existing scene. if scene == dialogic.current_state_info.get('background_scene', ''): + + if argument == dialogic.current_state_info.get('background_argument', ''): + return + for old_bg in background_holder.get_children(): if !old_bg.has_meta('node') or not old_bg.get_meta('node') is DialogicBackground: continue @@ -54,51 +60,47 @@ func update_background(scene:String = '', argument:String = '', fade_time:float bg_set = true info['same_scene'] = true - # If that didn't work, add a new scene, then cross-fade - if !bg_set: - var material: Material = background_holder.material - # make sure material is clean and ready to go - material.set_shader_parameter("progress", 0) - # swap the next background into previous, as that is now the older frame - material.set_shader_parameter("previous_background", material.get_shader_parameter("next_background")) - material.set_shader_parameter("next_background", null) - - if _tween: - _tween.kill() - - _tween = get_tree().create_tween() - - # could be implemented as passed by the event - #material.set_shader_parameter("whipe_texture", whipe_texture) # the direction the whipe takes from black to white - #material.set_shader_parameter("feather", feather) # the trailing smear left behind when the whipe happens + dialogic.current_state_info['background_scene'] = scene + dialogic.current_state_info['background_argument'] = argument - _tween.tween_method(func (progress: float): - material.set_shader_parameter("progress", progress) - , 0.0, 1.0, fade_time) + if bg_set: + background_changed.emit(info) + return - ## remove previous backgrounds - for old_bg in background_holder.get_children(): - if old_bg is SubViewportContainer: - old_bg.get_meta('node')._custom_fade_out(fade_time) - _tween.chain().tween_callback(old_bg.queue_free) - - var new_node: SubViewportContainer - if scene.ends_with('.tscn') and ResourceLoader.exists(scene): - new_node = add_background_node(load(scene), background_holder) - if not new_node.get_meta('node') is DialogicBackground: - printerr("[Dialogic] Given background scene was not of type DialogicBackground!") - elif argument: - new_node = add_background_node(default_background_scene, background_holder) - else: - new_node = null - - if new_node: - new_node.get_meta('node')._update_background(argument, fade_time) - new_node.get_meta('node')._custom_fade_in(fade_time) - material.set_shader_parameter("next_background", new_node.get_child(0).get_texture()) + var old_viewport: SubViewportContainer = null + if background_holder.has_meta('current_viewport'): + old_viewport = background_holder.get_meta('current_viewport', null) + + var new_viewport: SubViewportContainer + if scene.ends_with('.tscn') and ResourceLoader.exists(scene): + new_viewport = add_background_node(load(scene), background_holder) + elif argument: + new_viewport = add_background_node(default_background_scene, background_holder) + else: + new_viewport = null + + var trans_script :Script = load(DialogicResourceUtil.guess_special_resource("BackgroundTransition", transition_path, default_transition)) + var trans_node := Node.new() + trans_node.set_script(trans_script) + trans_node = (trans_node as DialogicBackgroundTransition) + trans_node.bg_holder = background_holder + trans_node.time = fade_time + + if old_viewport: + 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) + trans_node.transition_finished.connect(old_viewport.queue_free) + if new_viewport: + 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) + new_viewport.get_meta('node')._custom_fade_in(fade_time) + + add_child(trans_node) + trans_node._fade() + trans_node.transition_finished.connect(trans_node.queue_free) - dialogic.current_state_info['background_scene'] = scene - dialogic.current_state_info['background_argument'] = argument background_changed.emit(info) @@ -106,6 +108,12 @@ func add_background_node(scene:PackedScene, parent:DialogicNode_BackgroundHolder var v_con := SubViewportContainer.new() var viewport := SubViewport.new() var b_scene := scene.instantiate() + if not b_scene is DialogicBackground: + printerr("[Dialogic] Given background scene was not of type DialogicBackground!") + v_con.queue_free() + viewport.queue_free() + b_scene.queue_free() + return null parent.add_child(v_con) v_con.visible = false @@ -121,6 +129,7 @@ func add_background_node(scene:PackedScene, parent:DialogicNode_BackgroundHolder b_scene.viewport = viewport b_scene.viewport_container = v_con + parent.set_meta('current_viewport', v_con) v_con.set_meta('node', b_scene) return v_con @@ -129,3 +138,4 @@ func add_background_node(scene:PackedScene, parent:DialogicNode_BackgroundHolder func has_background() -> bool: return !dialogic.current_state_info['background_scene'].is_empty() or !dialogic.current_state_info['background_argument'].is_empty() + diff --git a/addons/dialogic/Modules/Character/class_dialogic_animation.gd b/addons/dialogic/Modules/Character/class_dialogic_animation.gd index 83c5d198f..b050c0286 100644 --- a/addons/dialogic/Modules/Character/class_dialogic_animation.gd +++ b/addons/dialogic/Modules/Character/class_dialogic_animation.gd @@ -1,7 +1,7 @@ class_name DialogicAnimation extends Node -## Class that can be used to animate portraits. Can be extended to create animations. +## Class that can be used to animate portraits. Can be extended to create animations. signal finished_once signal finished @@ -23,7 +23,7 @@ func _ready(): connect('finished_once', finished_one_loop) -## To be overridden. Do the actual animating/tweening in here. +## To be overridden. Do the actual animating/tweening in here. ## Use the properties [node], [time], [end_position], [orig_pos]. func animate(): pass diff --git a/addons/dialogic/Modules/Character/event_character.gd b/addons/dialogic/Modules/Character/event_character.gd index 0f8f537eb..4b7e469dd 100644 --- a/addons/dialogic/Modules/Character/event_character.gd +++ b/addons/dialogic/Modules/Character/event_character.gd @@ -18,7 +18,7 @@ var character : DialogicCharacter = null var portrait: String = "" ## The index of the position this character should move to var position: int = 1 -## Path to an animation script (extending DialogicAnimation). +## Name of the animation script (extending DialogicAnimation). ## On Join/Leave empty (default) will fallback to the animations set in the settings. ## On Update empty will mean no animation. var animation_name: String = "" @@ -80,7 +80,10 @@ func _execute() -> void: var max_time: float = Dialogic.Input.auto_skip.time_per_event final_animation_length = min(max_time, animation_length) - await dialogic.Portraits.join_character(character, portrait, position, mirrored, z_index, extra_data, animation_name, final_animation_length, animation_wait) + await dialogic.Portraits.join_character( + character, portrait, position, + mirrored, z_index, extra_data, + animation_name, final_animation_length, animation_wait) Actions.LEAVE: var final_animation_length: float = animation_length @@ -202,7 +205,7 @@ func to_text() -> String: var shortcode := "[" if animation_name: - shortcode += 'animation="'+DialogicUtil.pretty_name(animation_name)+'"' + shortcode += 'animation="'+animation_name+'"' if animation_length != default_values.get('animation_length', 0.5): shortcode += ' length="'+str(animation_length)+'"' @@ -267,25 +270,20 @@ func from_text(string:String) -> void: if result.get_string('shortcode'): var shortcode_params = parse_shortcode_parameters(result.get_string('shortcode')) animation_name = shortcode_params.get('animation', '') - if animation_name != "": - if !animation_name.ends_with('.gd'): - animation_name = DialogicUtil.guess_animation_file(animation_name) - if !animation_name.ends_with('.gd'): - printerr("[Dialogic] Couldn't identify animation '"+animation_name+"'.") - animation_name = "" - - var animLength = shortcode_params.get('length', '0.5').to_float() - if typeof(animLength) == TYPE_FLOAT: - animation_length = animLength - else: - animation_length = animLength.to_float() - - animation_wait = DialogicUtil.str_to_bool(shortcode_params.get('wait', 'false')) - - #repeat is supported on Update, the other two should not be checking this - if action == Actions.UPDATE: - animation_repeats = int(shortcode_params.get('repeat', animation_repeats)) - position_move_time = float(shortcode_params.get('move_time', position_move_time)) + + var animLength = shortcode_params.get('length', '0.5').to_float() + if typeof(animLength) == TYPE_FLOAT: + animation_length = animLength + else: + animation_length = animLength.to_float() + + animation_wait = DialogicUtil.str_to_bool(shortcode_params.get('wait', 'false')) + + #repeat is supported on Update, the other two should not be checking this + if action == Actions.UPDATE: + animation_repeats = int(shortcode_params.get('repeat', animation_repeats)) + position_move_time = float(shortcode_params.get('move_time', position_move_time)) + #move time is only supported on Update, but it isnt part of the animations so its separate if action == Actions.UPDATE: position_move_time = float(shortcode_params.get('move_time', position_move_time)) @@ -298,10 +296,10 @@ func from_text(string:String) -> void: extra_data = shortcode_params.get('extra_data', "") -# this is only here to provide a list of default values -# this way the module manager can add custom default overrides to this event. -# this is also why some properties are commented out, -# because it's not recommended to overwrite them this way +## this is only here to provide a list of default values +## this way the module manager can add custom default overrides to this event. +## this is also why some properties are commented out, +## because it's not recommended to overwrite them this way func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info @@ -452,16 +450,8 @@ func get_animation_suggestions(search_text:String) -> Dictionary: Actions.UPDATE: suggestions['None'] = {'value':"", 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]} - match action: - Actions.JOIN: - for anim in DialogicUtil.get_portrait_animation_scripts(DialogicUtil.AnimationType.IN): - suggestions[DialogicUtil.pretty_name(anim)] = {'value':anim, 'editor_icon':["Animation", "EditorIcons"]} - Actions.LEAVE: - for anim in DialogicUtil.get_portrait_animation_scripts(DialogicUtil.AnimationType.OUT): - suggestions[DialogicUtil.pretty_name(anim)] = {'value':anim, 'editor_icon':["Animation", "EditorIcons"]} - Actions.UPDATE: - for anim in DialogicUtil.get_portrait_animation_scripts(DialogicUtil.AnimationType.ACTION): - suggestions[DialogicUtil.pretty_name(anim)] = {'value':anim, 'editor_icon':["Animation", "EditorIcons"]} + for anim in DialogicUtil.get_portrait_animation_scripts(action+1): + suggestions[DialogicUtil.pretty_name(anim)] = {'value':DialogicUtil.pretty_name(anim), 'editor_icon':["Animation", "EditorIcons"]} return suggestions diff --git a/addons/dialogic/Modules/Character/index.gd b/addons/dialogic/Modules/Character/index.gd index feaa1a37f..0e893c49e 100644 --- a/addons/dialogic/Modules/Character/index.gd +++ b/addons/dialogic/Modules/Character/index.gd @@ -17,5 +17,5 @@ func _get_text_effects() -> Array[Dictionary]: return [{'command':'portrait', 'subsystem':'Portraits', 'method':'text_effect_portrait', 'arg':true}] -func _get_portrait_animations() -> Array: - return list_dir('DefaultAnimations') +func _get_special_resources() -> Array[Dictionary]: + return list_special_resources('DefaultAnimations', 'PortraitAnimation') diff --git a/addons/dialogic/Modules/Character/subsystem_portraits.gd b/addons/dialogic/Modules/Character/subsystem_portraits.gd index 9eea6b391..8aabddc69 100644 --- a/addons/dialogic/Modules/Character/subsystem_portraits.gd +++ b/addons/dialogic/Modules/Character/subsystem_portraits.gd @@ -301,11 +301,11 @@ func join_character(character:DialogicCharacter, portrait:String, position_idx: character_joined.emit(info) if animation_name.is_empty(): - animation_name = ProjectSettings.get_setting('dialogic/animations/join_default', - get_script().resource_path.get_base_dir().path_join('DefaultAnimations/fade_in_up.gd')) + animation_name = ProjectSettings.get_setting('dialogic/animations/join_default', "Fade In Up") animation_length = _get_join_default_length() animation_wait = ProjectSettings.get_setting('dialogic/animations/join_default_wait', true) + animation_name = DialogicResourceUtil.guess_special_resource("PortraitAnimation", animation_name, "") if animation_name and animation_length > 0: var anim:DialogicAnimation = _animate_portrait(character_node, animation_name, animation_length) @@ -402,6 +402,9 @@ func change_character_extradata(character:DialogicCharacter, extra_data:="") -> func animate_character(character:DialogicCharacter, animation_path:String, length:float, repeats = 1) -> DialogicAnimation: if !is_character_joined(character): return null + + animation_path = DialogicResourceUtil.guess_special_resource("PortraitAnimation", animation_path, "") + return _animate_portrait(dialogic.current_state_info.portraits[character.resource_path].node, animation_path, length, repeats) @@ -434,6 +437,8 @@ func leave_character(character:DialogicCharacter, animation_name :String = "", a animation_length = _get_leave_default_length() animation_wait = ProjectSettings.get_setting('dialogic/animations/leave_default_wait', true) + animation_name = DialogicResourceUtil.guess_special_resource("PortraitAnimation", animation_name, "") + if !animation_name.is_empty(): var anim := animate_character(character, animation_name, animation_length) diff --git a/addons/dialogic/Modules/Clear/event_clear.gd b/addons/dialogic/Modules/Clear/event_clear.gd index 92c657401..506178b7e 100644 --- a/addons/dialogic/Modules/Clear/event_clear.gd +++ b/addons/dialogic/Modules/Clear/event_clear.gd @@ -34,7 +34,7 @@ func _execute() -> void: if clear_portraits and dialogic.has_subsystem('Portraits') and len(dialogic.Portraits.get_joined_characters()) != 0: if final_time == 0: - dialogic.Portraits.leave_all_characters(DialogicUtil.guess_animation_file('Instant In Or Out'), final_time, step_by_step) + dialogic.Portraits.leave_all_characters(DialogicResourceUtil.guess_special_resource("PortraitAnimation", 'Instant In Or Out'), final_time, step_by_step) else: dialogic.Portraits.leave_all_characters("", final_time, step_by_step) if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd index 0ab3886fa..9162300ec 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd @@ -1,12 +1,2 @@ @tool extends DialogicLayoutLayer - -## A layer that holds full-screen backgrounds. - -@export_group('Transition') -@export_file('*.tres') var transition_shader_material := "" - - -func _apply_export_overrides() -> void: - if ResourceLoader.exists(transition_shader_material): - $DialogicNode_BackgroundHolder.material = load(transition_shader_material) 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 c083d8b0a..6c9fef591 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.tscn @@ -1,8 +1,14 @@ -[gd_scene load_steps=4 format=3 uid="uid://c1k5m0w3r40xf"] +[gd_scene load_steps=5 format=3 uid="uid://c1k5m0w3r40xf"] -[ext_resource type="Material" uid="uid://0wc7bedn7ee8" path="res://addons/dialogic/Modules/Background/default_background_transition.tres" id="1_ccins"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd" id="1_srvyd"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/full_background_layer.gd" id="1_tu40u"] [ext_resource type="Script" path="res://addons/dialogic/Modules/Background/node_background_holder.gd" id="2_ghan2"] +[ext_resource type="Shader" path="res://addons/dialogic/Modules/Background/Transitions/default_transition_shader.gdshader" id="2_mwc4m"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_msuxf"] +shader = ExtResource("2_mwc4m") +shader_parameter/progress = 0.0 +shader_parameter/feather = 0.1 +shader_parameter/keep_aspect_ratio = false [node name="BackgroundLayer" type="Control"] layout_mode = 3 @@ -11,10 +17,10 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 -script = ExtResource("1_srvyd") +script = ExtResource("1_tu40u") [node name="DialogicNode_BackgroundHolder" type="ColorRect" parent="."] -material = ExtResource("1_ccins") +material = SubResource("ShaderMaterial_msuxf") layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 diff --git a/addons/dialogic/Other/DialogicResourceUtil.gd b/addons/dialogic/Other/DialogicResourceUtil.gd index d95377e86..0f2017b2c 100644 --- a/addons/dialogic/Other/DialogicResourceUtil.gd +++ b/addons/dialogic/Other/DialogicResourceUtil.gd @@ -4,6 +4,9 @@ class_name DialogicResourceUtil static var label_cache := {} static var event_cache: Array[DialogicEvent] = [] +static var special_resources : Array[Dictionary] = [] + + static func update() -> void: update_directory('.dch') update_directory('.dtl') @@ -25,8 +28,9 @@ static func get_directory(extension:String) -> Dictionary: static func set_directory(extension:String, directory:Dictionary) -> void: extension = extension.trim_prefix('.') - ProjectSettings.set_setting("dialogic/directories/"+extension+'_directory', directory) - ProjectSettings.save() + if Engine.is_editor_hint(): + ProjectSettings.set_setting("dialogic/directories/"+extension+'_directory', directory) + ProjectSettings.save() Engine.set_meta(extension+'_directory', directory) @@ -159,6 +163,30 @@ static func update_event_cache() -> Array: #endregion +static func update_special_resources() -> void: + special_resources = [] + for indexer in DialogicUtil.get_indexers(): + special_resources.append_array(indexer._get_special_resources()) + + +static func list_special_resources_of_type(type:String) -> Array: + if special_resources.is_empty(): + update_special_resources() + return special_resources.filter(func(x:Dictionary): return type == x.get('type','')).map(func(x:Dictionary): return x.get('path', '')) + + +static func guess_special_resource(type:String, name:String, default:="") -> String: + if special_resources.is_empty(): + update_special_resources() + if name.begins_with('res://'): + return name + for path in list_special_resources_of_type(type): + if DialogicUtil.pretty_name(path).to_lower() == name.to_lower(): + return path + return default + + + #region HELPERS ################################################################################ diff --git a/addons/dialogic/Other/DialogicUtil.gd b/addons/dialogic/Other/DialogicUtil.gd index 4f1b951cc..61a76d3fb 100644 --- a/addons/dialogic/Other/DialogicUtil.gd +++ b/addons/dialogic/Other/DialogicUtil.gd @@ -78,25 +78,9 @@ static func get_indexers(include_custom := true, force_reload := false) -> Array return indexers - - - -static func guess_animation_file(animation_name: String) -> String: - for file in DialogicUtil.get_portrait_animation_scripts(): - if DialogicUtil.pretty_name(animation_name) == DialogicUtil.pretty_name(file): - return file - return animation_name - - enum AnimationType {ALL, IN, OUT, ACTION} static func get_portrait_animation_scripts(type:=AnimationType.ALL, include_custom:=true) -> Array: - var animations := [] - if Engine.get_main_loop().has_meta('dialogic_animation_names'): - animations = Engine.get_main_loop().get_meta('dialogic_animation_names') - else: - for i in get_indexers(): - animations.append_array(i._get_portrait_animations()) - Engine.get_main_loop().set_meta('dialogic_animation_names', animations) + var animations := DialogicResourceUtil.list_special_resources_of_type("PortraitAnimation") return animations.filter( func(script): diff --git a/addons/dialogic/Other/index_class.gd b/addons/dialogic/Other/index_class.gd index 8813b30ff..efc8adc89 100644 --- a/addons/dialogic/Other/index_class.gd +++ b/addons/dialogic/Other/index_class.gd @@ -38,6 +38,8 @@ func _get_character_editor_sections() -> Array: return [] +#region TEXT EFFECTS & MODIFIERS + ## Should return array of dictionaries with the following keys:[br] ## "command" -> the text e.g. "speed"[br] ## "node_path" or "subsystem" -> whichever contains your effect method[br] @@ -50,16 +52,37 @@ func _get_text_effects() -> Array[Dictionary]: func _get_text_modifiers() -> Array[Dictionary]: return [] +#endregion + -## Should return array of animation scripts. -func _get_portrait_animations() -> Array: +## Return a list of resources, scripts, etc. +## These can later be retrieved with DialogicResourceUtil. +## Each dictionary should contain (at least "type" and "path"). +## E.g. {"type":"Animation", "path": "res://..."} +func _get_special_resources() -> Array[Dictionary]: return [] +#region HELPERS +################################################################################ + func list_dir(subdir:='') -> Array: return Array(DirAccess.get_files_at(this_folder.path_join(subdir))).map(func(file):return this_folder.path_join(subdir).path_join(file)) +func list_special_resources(subdir:='', type:='', extension:="") -> Array[Dictionary]: + var array := [] + for i in list_dir(subdir): + if extension.is_empty() or i.ends_with(extension): + array.append({'type':type, 'path':i}) + return Array(array, TYPE_DICTIONARY, "", null) + +#endregion + + +#region STYLES & LAYOUTS +################################################################################ + func _get_style_presets() -> Array[Dictionary]: return [] @@ -107,3 +130,4 @@ func scan_for_layout_parts() -> Array[Dictionary]: return style_list +#endregion