From 3856664c994b536b59e693c36092d8f0200531dc Mon Sep 17 00:00:00 2001 From: Salia Nifo Date: Thu, 31 Oct 2024 12:42:36 -0400 Subject: [PATCH 1/4] Add Screen Shake feature --- addons/dialogic/Modules/Clear/clear_shake.svg | 76 +++++++ .../Modules/Clear/clear_shake.svg.import | 38 ++++ addons/dialogic/Modules/Clear/event_clear.gd | 8 + .../Layer_ScreenShake/icon.svg | 58 +++++ .../Layer_ScreenShake/icon.svg.import | 38 ++++ .../Layer_ScreenShake/part_config.cfg | 7 + .../Layer_ScreenShake/preview.png | Bin 0 -> 70996 bytes .../Layer_ScreenShake/preview.png.import | 34 +++ .../Layer_ScreenShake/screen_shake_layer.gd | 2 + .../screen_shake_layer.gdshader | 35 ++++ .../Layer_ScreenShake/screen_shake_layer.tscn | 40 ++++ .../Modules/ScreenShake/event_screen_shake.gd | 111 ++++++++++ addons/dialogic/Modules/ScreenShake/icon.png | Bin 0 -> 782 bytes .../Modules/ScreenShake/icon.png.import | 34 +++ addons/dialogic/Modules/ScreenShake/index.gd | 8 + .../Modules/ScreenShake/node_screen_shaker.gd | 68 ++++++ .../ScreenShake/subsystem_screen_shake.gd | 198 ++++++++++++++++++ 17 files changed, 755 insertions(+) create mode 100644 addons/dialogic/Modules/Clear/clear_shake.svg create mode 100644 addons/dialogic/Modules/Clear/clear_shake.svg.import create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg.import create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/part_config.cfg create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png.import create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn create mode 100644 addons/dialogic/Modules/ScreenShake/event_screen_shake.gd create mode 100644 addons/dialogic/Modules/ScreenShake/icon.png create mode 100644 addons/dialogic/Modules/ScreenShake/icon.png.import create mode 100644 addons/dialogic/Modules/ScreenShake/index.gd create mode 100644 addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd create mode 100644 addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd diff --git a/addons/dialogic/Modules/Clear/clear_shake.svg b/addons/dialogic/Modules/Clear/clear_shake.svg new file mode 100644 index 000000000..e413ff7e1 --- /dev/null +++ b/addons/dialogic/Modules/Clear/clear_shake.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + diff --git a/addons/dialogic/Modules/Clear/clear_shake.svg.import b/addons/dialogic/Modules/Clear/clear_shake.svg.import new file mode 100644 index 000000000..1ec3d43f5 --- /dev/null +++ b/addons/dialogic/Modules/Clear/clear_shake.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bw5d6gq4xj4fc" +path="res://.godot/imported/clear_shake.svg-7755f0aa1227e0b25e8ad6fa6ac6cbe5.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogic/Modules/Clear/clear_shake.svg" +dest_files=["res://.godot/imported/clear_shake.svg-7755f0aa1227e0b25e8ad6fa6ac6cbe5.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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=true +editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogic/Modules/Clear/event_clear.gd b/addons/dialogic/Modules/Clear/event_clear.gd index 9b1b3d7aa..c59248ff6 100644 --- a/addons/dialogic/Modules/Clear/event_clear.gd +++ b/addons/dialogic/Modules/Clear/event_clear.gd @@ -12,6 +12,7 @@ var clear_textbox := true var clear_portraits := true var clear_style := true var clear_music := true +var clear_screen_shake := true var clear_portrait_positions := true var clear_background := true @@ -49,6 +50,11 @@ func _execute() -> void: dialogic.Audio.stop_all_channels(final_time) if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout + if clear_screen_shake and dialogic.has_subsystem('ScreenShake'): + dialogic.ScreenShake.update_shake_x(0.0, 0.0, final_time) + dialogic.ScreenShake.update_shake_y(0.0, 0.0, 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() @@ -88,6 +94,7 @@ func get_shortcode_parameters() -> Dictionary: "text" : {"property": "clear_textbox", "default": true}, "portraits" : {"property": "clear_portraits", "default": true}, "music" : {"property": "clear_music", "default": true}, + "shake" : {"property": "clear_screen_shake", "default": true}, "background": {"property": "clear_background", "default": true}, "positions" : {"property": "clear_portrait_positions", "default": true}, "style" : {"property": "clear_style", "default": true}, @@ -110,5 +117,6 @@ func build_event_editor() -> void: 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 Audio'}) + add_body_edit('clear_screen_shake', ValueType.BOOL_BUTTON, {'icon':load("res://addons/dialogic/Modules/Clear/clear_shake.svg"), 'tooltip':'Clear Screen Shake'}) 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/DefaultLayoutParts/Layer_ScreenShake/icon.svg b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg new file mode 100644 index 000000000..4fe7970d3 --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg @@ -0,0 +1,58 @@ + + + + + + + + + diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg.import b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg.import new file mode 100644 index 000000000..8b76f35dc --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dp28d3waw6sh8" +path="res://.godot/imported/icon.svg-c4786c180265dc13234ef8ceb5240800.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/icon.svg" +dest_files=["res://.godot/imported/icon.svg-c4786c180265dc13234ef8ceb5240800.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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=true +editor/convert_colors_with_editor_theme=true diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/part_config.cfg b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/part_config.cfg new file mode 100644 index 000000000..275f8d95c --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/part_config.cfg @@ -0,0 +1,7 @@ +[style] +type = "Layer" +name = "Screen Shake Layer" +author = "SaliaNifo" +description = "A layer for applying screen shake to the layers below it." +scene = "screen_shake_layer.tscn" +icon = "icon.svg" diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..488729ba86e8a7932dcced15ded883189c5567e1 GIT binary patch literal 70996 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

$EG_;uRbsayL4k^OBWi1 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 1.0 || uv.y > 1.0 || uv.x < 0.0 || uv.y < 0.0) { + COLOR.rgb = clear_color; + COLOR.a = 1.0; + } else { + COLOR = texture(SCREEN_TEXTURE, uv); + } +} diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn new file mode 100644 index 000000000..7c6230b9b --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=5 format=3 uid="uid://cdvx2jejg8xln"] + +[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd" id="1_l682i"] +[ext_resource type="Shader" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader" id="2_7h78g"] +[ext_resource type="Script" path="res://addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd" id="3_uqmkn"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_4u8q6"] +shader = ExtResource("2_7h78g") +shader_parameter/amplitude_x = 0.0 +shader_parameter/frequency_x = 0.0 +shader_parameter/phase_x = 0.0 +shader_parameter/time_x = 0.0 +shader_parameter/amplitude_y = 0.0 +shader_parameter/frequency_y = 0.0 +shader_parameter/phase_y = 0.0 +shader_parameter/time_y = 0.0 +shader_parameter/clear_color = Color(0, 0, 0, 1) + +[node name="ScreenShakeLayer" type="Control"] +layout_direction = 2 +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_l682i") + +[node name="BackBufferCopy" type="BackBufferCopy" parent="."] +copy_mode = 2 + +[node name="DialogicNode_ScreenShaker" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_4u8q6") +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("3_uqmkn") diff --git a/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd b/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd new file mode 100644 index 000000000..bcc35530a --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd @@ -0,0 +1,111 @@ +@tool +extends DialogicEvent +class_name DialogicScreenShakeEvent + +## Event to shake the screen below the screen shake layer. + +### Settings + +enum Direction {HORIZONTAL, VERTICAL} + +## The strength of the screen shake. +var amplitude: float = 0.1 +## The speed of the screen shake. +var frequency: float = 1.0 +## The direction of the screen shake. +var direction := Direction.HORIZONTAL +## The time the fade animation will take. Leave at 0 for instant change. +var fade: float = 0.0 +## The time the screen should shake for (excludes fade time). +## Leave at 0 to keep shaking until the next screen shake event. +var duration: float = 0.0 +## If true, the event will wait for completion before continuing +## (only if duration is greater than 0.0 or fade greater than 0.0 and amplitude is 0.0). +var wait := false + +#region EXECUTION +################################################################################ + +func _execute() -> void: + if direction == Direction.HORIZONTAL: + dialogic.ScreenShake.update_shake_x(amplitude, frequency, fade, duration) + + if wait and (duration > 0.0 or (fade > 0.0 and amplitude == 0.0)): + await dialogic.ScreenShake.shake_horizontal_finished + else: + dialogic.ScreenShake.update_shake_y(amplitude, frequency, fade, duration) + + if wait and (duration > 0.0 or (fade > 0.0 and amplitude == 0.0)): + await dialogic.ScreenShake.shake_vertical_finished + + finish() + +#endregion + +#region INITIALIZE +################################################################################ + +func _init() -> void: + event_name = "Shake Screen" + set_default_color('Color8') + event_category = "Visuals" + event_sorting_index = 2 + +#endregion + +#region SAVING/LOADING +################################################################################ + +func get_shortcode() -> String: + return "shake_screen" + + +func get_shortcode_parameters() -> Dictionary: + return { + "amplitude" : {"property": "amplitude", "default": 0.1}, + "frequency" : {"property": "frequency", "default": 1.0}, + "direction" : {"property": "direction", "default": Direction.HORIZONTAL}, + "fade" : {"property": "fade", "default": 0.0}, + "duration" : {"property": "duration", "default": 10.0}, + "wait" : {"property": "wait", "default": false}, + } + +#endregion + +#region EDITOR REPRESENTATION +################################################################################ + +func build_event_editor() -> void: + add_header_edit("direction", ValueType.FIXED_OPTIONS, { + 'left_text': 'Shake screen', + 'options': [ + { + 'label': 'Horizontally', + 'value': Direction.HORIZONTAL, + 'icon': ["MirrorX", "EditorIcons"] + }, + { + 'label': 'Vertically', + 'value': Direction.VERTICAL, + 'icon': ["MirrorY", "EditorIcons"] + } + ]}) + + add_header_edit("amplitude", ValueType.NUMBER, { + 'left_text': 'with amplitude:', + 'min': 0.0, + 'max': 1.0, + 'step': 0.01, + }) + + add_header_edit("frequency", ValueType.NUMBER, { + 'left_text': 'and frequency:', + 'min': 0.1, + 'suffix': 'hz', + }) + + add_body_edit("fade", ValueType.NUMBER, {'left_text':'Fade time:'}) + add_body_edit("duration", ValueType.NUMBER, {'left_text': 'Duration:'}, 'amplitude > 0.0') + add_body_edit("wait", ValueType.BOOL, {'left_text':'Wait for completion:'}, '(fade > 0.0 and amplitude == 0.0) or duration > 0.0') + +#endregion diff --git a/addons/dialogic/Modules/ScreenShake/icon.png b/addons/dialogic/Modules/ScreenShake/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..14b815a9d915dbaf3b5228161b8aaf8a87566045 GIT binary patch literal 782 zcmV+p1M&QcP)a?YJIbK7se&RofH9LI4S$8j7dFu-GA zK6V{Z0II+)un*jeT~APe3E&%td+3tfO3L8dyoz04Ur9tS zi{TVS;C3QT_FugwdC_JGusJK*I0;7BqeZHmZY;OZBA%!B1)B%wLZm4(zc{IGkaMuFQ^Dk zOIlYx5xik$je!-xHozG0yhDt#mcgYQg0_%xkIrRq1sLz`s7e4l1b*k300S0jnWk>` zfCcgyp*?!Ebr#DCPpM^vZzWBi)Uv{j9JzyMh5u)Q?Fn{rjJP$-td@ z*LOJn1&NQ0!V418h`%D!hC@*tUeU{f)_KBki=N{+j^j9v<2VD!Uw=G=VBo-GM*si- M07*qoM6N<$f@?ihy#N3J literal 0 HcmV?d00001 diff --git a/addons/dialogic/Modules/ScreenShake/icon.png.import b/addons/dialogic/Modules/ScreenShake/icon.png.import new file mode 100644 index 000000000..eb641d720 --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://m74xxddbt4sj" +path="res://.godot/imported/icon.png-27bf81e8d508931fcff8d7fc07586e55.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogic/Modules/ScreenShake/icon.png" +dest_files=["res://.godot/imported/icon.png-27bf81e8d508931fcff8d7fc07586e55.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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 diff --git a/addons/dialogic/Modules/ScreenShake/index.gd b/addons/dialogic/Modules/ScreenShake/index.gd new file mode 100644 index 000000000..7294e40f3 --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/index.gd @@ -0,0 +1,8 @@ +@tool +extends DialogicIndexer + +func _get_events() -> Array: + return [this_folder.path_join('event_screen_shake.gd')] + +func _get_subsystems() -> Array: + return [{'name':'ScreenShake', 'script':this_folder.path_join('subsystem_screen_shake.gd')}] diff --git a/addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd b/addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd new file mode 100644 index 000000000..09a77dcaf --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd @@ -0,0 +1,68 @@ +class_name DialogicNode_ScreenShaker +extends ColorRect + + +const ROLLOVER_TIME = 3600.0 + +@onready var time_x: float = material.get_shader_parameter('time_x') +@onready var phase_x: float = material.get_shader_parameter('phase_x') +@onready var last_frequency_x: float = material.get_shader_parameter('frequency_x') + +@onready var time_y: float = material.get_shader_parameter('time_y') +@onready var phase_y: float = material.get_shader_parameter('phase_y') +@onready var last_frequency_y: float = material.get_shader_parameter('frequency_y') + + +func _ready() -> void: + add_to_group('dialogic_screen_shaker') + + material.set_shader_parameter( + 'clear_color', + ProjectSettings.get_setting('rendering/environment/defaults/default_clear_color', Color.BLACK)) + + +func _process(delta: float) -> void: + if not DialogicUtil.autoload().paused: + time_x += delta + time_x = fposmod(time_x, ROLLOVER_TIME) + material.set_shader_parameter('time_x', time_x) + + time_y += delta + time_y = fposmod(time_y, ROLLOVER_TIME) + material.set_shader_parameter('time_y', time_y) + + +func reset_x() -> void: + time_x = 0.0 + phase_x = 0.0 + last_frequency_x = 0.0 + + material.set_shader_parameter('time_x', 0.0) + material.set_shader_parameter('phase_x', 0.0) + + +func reset_y() -> void: + time_y = 0.0 + phase_y = 0.0 + last_frequency_y = 0.0 + + material.set_shader_parameter('time_y', 0.0) + material.set_shader_parameter('phase_y', 0.0) + + +func update_frequency_x(new_frequency: float) -> void: + if new_frequency != 0.0: + phase_x = (last_frequency_x * (time_x + phase_x) / new_frequency) - time_x + last_frequency_x = new_frequency + + material.set_shader_parameter('frequency_x', new_frequency) + material.set_shader_parameter('phase_x', phase_x) + + +func update_frequency_y(new_frequency: float) -> void: + if new_frequency != 0.0: + phase_y = (last_frequency_y * (time_y + phase_y) / new_frequency) - time_y + last_frequency_y = new_frequency + + material.set_shader_parameter('frequency_y', new_frequency) + material.set_shader_parameter('phase_y', phase_y) diff --git a/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd new file mode 100644 index 000000000..e5ae14e30 --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd @@ -0,0 +1,198 @@ +extends DialogicSubsystem + +## Subsystem that manages screen shaking. + + +## Whenever a horizontal screen shake is started, this signal is emitted and +## contains a dictionary with the following keys: [br] +## [br] +## Key | Value Type | Value [br] +## ------------ | ------------- | ----- [br] +## `amplitude` | [type float] | The strength of the screen shake. [br] +## `frequency` | [type float] | The speed of the screen shake. [br] +## `fade` | [type float] | The time the fade animation will take. Leave at 0 for instant change. [br] +## `duration` | [type float] | The time the screen should shake for (excludes fade time). [br] +signal shake_horizontal_started(info: Dictionary) + +## Whenever a horizontal screen shake has finished, this signal is emitted. +signal shake_horizontal_finished() + +## Whenever a vertical screen shake is started, this signal is emitted and +## contains a dictionary with the following keys: [br] +## [br] +## Key | Value Type | Value [br] +## ------------ | ------------- | ----- [br] +## `amplitude` | [type float] | The strength of the screen shake. [br] +## `frequency` | [type float] | The speed of the screen shake. [br] +## `fade` | [type float] | The time the fade animation will take. Leave at 0 for instant change. [br] +## `duration` | [type float] | The time the screen should shake for (excludes fade time). [br] +signal shake_vertical_started(info: Dictionary) + +## Whenever a vertical screen shake has finished, this signal is emitted. +signal shake_vertical_finished() + +#region STATE +#################################################################################################### + +func clear_game_state(clear_flag:=Dialogic.ClearFlags.FULL_CLEAR) -> void: + update_shake_x() + update_shake_y() + + +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('screen_shake', {'x':{},'y':{}}) + if info['x'].is_empty() or info['x'].get('amplitude', 0.0) == 0.0: + update_shake_x() + else: + update_shake_x(info['x'].amplitude, info['x'].frequency, info['x'].fade, info['x'].duration) + if info['y'].is_empty() or info['y'].get('amplitude', 0.0) == 0.0: + update_shake_y() + else: + update_shake_y(info['y'].amplitude, info['y'].frequency, info['y'].fade, info['y'].duration) + +#endregion + +#region MAIN METHODS +#################################################################################################### + +func update_shake_x(amplitude: float = 0.0, frequency: float = 0.0, fade: float = 0.0, duration: float = 0.0) -> void: + var previous_settings = dialogic.current_state_info.get('screen_shake', {'x':{},'y':{}}) + + if not dialogic.current_state_info.has('screen_shake'): + dialogic.current_state_info['screen_shake'] = {'x':{},'y':{}} + + dialogic.current_state_info['screen_shake']['x'] = { + 'amplitude': amplitude, + 'frequency': frequency, + 'fade': fade, + 'duration': duration, + } + + shake_horizontal_started.emit(dialogic.current_state_info['screen_shake']['x']) + + var screen_shaker: DialogicNode_ScreenShaker + if dialogic.has_subsystem('Styles'): + screen_shaker = dialogic.Styles.get_first_node_in_layout('dialogic_screen_shaker') + else: + screen_shaker = get_tree().get_first_node_in_group('dialogic_screen_shaker') + + if not screen_shaker: + return + + if previous_settings['x'].is_empty(): + screen_shaker.reset_x() + + if fade > 0.0: + var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_x') as float + var current_frequency := screen_shaker.material.get_shader_parameter('frequency_x') as float + var tween := get_tree().create_tween() + tween.tween_method(_tween_amplitude_x.bind(screen_shaker.material), current_amplitude, amplitude, fade) + tween.set_parallel() + tween.tween_method(_tween_frequency_x.bind(screen_shaker), current_frequency, frequency, fade) + await tween.finished + else: + screen_shaker.material.set_shader_parameter('amplitude_x', amplitude) + screen_shaker.update_frequency_x(frequency) + + if duration > 0.0 and amplitude > 0.0: + await get_tree().create_timer(duration).timeout + elif amplitude == 0.0: + dialogic.current_state_info['screen_shake']['x'] = {} + shake_horizontal_finished.emit() + return + else: + return + + if fade > 0.0: + var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_x') as float + var current_frequency := screen_shaker.material.get_shader_parameter('frequency_x') as float + var tween := get_tree().create_tween() + tween.tween_method(_tween_amplitude_x.bind(screen_shaker.material), current_amplitude, 0.0, fade) + tween.set_parallel() + tween.tween_method(_tween_frequency_x.bind(screen_shaker), current_frequency, 0.0, fade) + await tween.finished + else: + screen_shaker.material.set_shader_parameter('amplitude_x', 0.0) + screen_shaker.update_frequency_x(frequency) + + dialogic.current_state_info['screen_shake']['x'] = {} + shake_horizontal_finished.emit() + + +func update_shake_y(amplitude: float = 0.0, frequency: float = 0.0, fade: float = 0.0, duration: float = 0.0) -> void: + var previous_settings = dialogic.current_state_info.get('screen_shake', {'x':{},'y':{}}) + dialogic.current_state_info['screen_shake']['y'] = { + 'amplitude': amplitude, + 'frequency': frequency, + 'fade': fade, + 'duration': duration, + } + + shake_vertical_started.emit(dialogic.current_state_info['screen_shake']['y']) + + var screen_shaker: DialogicNode_ScreenShaker + if dialogic.has_subsystem('Styles'): + screen_shaker = dialogic.Styles.get_first_node_in_layout('dialogic_screen_shaker') + else: + screen_shaker = get_tree().get_first_node_in_group('dialogic_screen_shaker') + + if not screen_shaker: + return + + if previous_settings['y'].is_empty(): + screen_shaker.reset_y() + + if fade > 0.0: + var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_y') as float + var current_frequency := screen_shaker.material.get_shader_parameter('frequency_y') as float + var tween := get_tree().create_tween() + tween.tween_method(_tween_amplitude_y.bind(screen_shaker.material), current_amplitude, amplitude, fade) + tween.set_parallel() + tween.tween_method(_tween_frequency_y.bind(screen_shaker), current_frequency, frequency, fade) + await tween.finished + else: + screen_shaker.material.set_shader_parameter('amplitude_y', amplitude) + screen_shaker.update_frequency_y(frequency) + + if duration > 0.0 and amplitude > 0.0: + await get_tree().create_timer(duration).timeout + elif amplitude == 0.0: + dialogic.current_state_info['screen_shake']['y'] = {} + shake_vertical_finished.emit() + return + else: + return + + if fade > 0.0: + var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_y') as float + var current_frequency := screen_shaker.material.get_shader_parameter('frequency_y') as float + var tween := get_tree().create_tween() + tween.tween_method(_tween_amplitude_y.bind(screen_shaker.material), current_amplitude, 0.0, fade) + tween.set_parallel() + tween.tween_method(_tween_frequency_y.bind(screen_shaker), current_frequency, 0.0, fade) + await tween.finished + else: + screen_shaker.material.set_shader_parameter('amplitude_y', 0.0) + screen_shaker.update_frequency_y(frequency) + + dialogic.current_state_info['screen_shake']['y'] = {} + shake_vertical_finished.emit() + +#endregion + +func _tween_amplitude_x(value: float, material: ShaderMaterial) -> void: + material.set_shader_parameter('amplitude_x', value) + + +func _tween_amplitude_y(value: float, material: ShaderMaterial) -> void: + material.set_shader_parameter('amplitude_y', value) + + +func _tween_frequency_x(value: float, screen_shaker: DialogicNode_ScreenShaker) -> void: + screen_shaker.update_frequency_x(value) + + +func _tween_frequency_y(value: float, screen_shaker: DialogicNode_ScreenShaker) -> void: + screen_shaker.update_frequency_y(value) From 62bf2e471d29426b277e09dfad1e57bfb06f85fd Mon Sep 17 00:00:00 2001 From: Salia Nifo Date: Fri, 1 Nov 2024 10:28:19 -0400 Subject: [PATCH 2/4] Fixes for when style is changed while still tweening --- .../ScreenShake/subsystem_screen_shake.gd | 71 ++++++++++++------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd index e5ae14e30..d2cc22185 100644 --- a/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd +++ b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd @@ -72,11 +72,7 @@ func update_shake_x(amplitude: float = 0.0, frequency: float = 0.0, fade: float shake_horizontal_started.emit(dialogic.current_state_info['screen_shake']['x']) - var screen_shaker: DialogicNode_ScreenShaker - if dialogic.has_subsystem('Styles'): - screen_shaker = dialogic.Styles.get_first_node_in_layout('dialogic_screen_shaker') - else: - screen_shaker = get_tree().get_first_node_in_group('dialogic_screen_shaker') + var screen_shaker := get_screen_shaker() if not screen_shaker: return @@ -88,9 +84,9 @@ func update_shake_x(amplitude: float = 0.0, frequency: float = 0.0, fade: float var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_x') as float var current_frequency := screen_shaker.material.get_shader_parameter('frequency_x') as float var tween := get_tree().create_tween() - tween.tween_method(_tween_amplitude_x.bind(screen_shaker.material), current_amplitude, amplitude, fade) + tween.tween_method(_tween_amplitude_x, current_amplitude, amplitude, fade) tween.set_parallel() - tween.tween_method(_tween_frequency_x.bind(screen_shaker), current_frequency, frequency, fade) + tween.tween_method(_tween_frequency_x, current_frequency, frequency, fade) await tween.finished else: screen_shaker.material.set_shader_parameter('amplitude_x', amplitude) @@ -109,9 +105,9 @@ func update_shake_x(amplitude: float = 0.0, frequency: float = 0.0, fade: float var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_x') as float var current_frequency := screen_shaker.material.get_shader_parameter('frequency_x') as float var tween := get_tree().create_tween() - tween.tween_method(_tween_amplitude_x.bind(screen_shaker.material), current_amplitude, 0.0, fade) + tween.tween_method(_tween_amplitude_x, current_amplitude, 0.0, fade) tween.set_parallel() - tween.tween_method(_tween_frequency_x.bind(screen_shaker), current_frequency, 0.0, fade) + tween.tween_method(_tween_frequency_x, current_frequency, 0.0, fade) await tween.finished else: screen_shaker.material.set_shader_parameter('amplitude_x', 0.0) @@ -132,11 +128,7 @@ func update_shake_y(amplitude: float = 0.0, frequency: float = 0.0, fade: float shake_vertical_started.emit(dialogic.current_state_info['screen_shake']['y']) - var screen_shaker: DialogicNode_ScreenShaker - if dialogic.has_subsystem('Styles'): - screen_shaker = dialogic.Styles.get_first_node_in_layout('dialogic_screen_shaker') - else: - screen_shaker = get_tree().get_first_node_in_group('dialogic_screen_shaker') + var screen_shaker := get_screen_shaker() if not screen_shaker: return @@ -148,9 +140,9 @@ func update_shake_y(amplitude: float = 0.0, frequency: float = 0.0, fade: float var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_y') as float var current_frequency := screen_shaker.material.get_shader_parameter('frequency_y') as float var tween := get_tree().create_tween() - tween.tween_method(_tween_amplitude_y.bind(screen_shaker.material), current_amplitude, amplitude, fade) + tween.tween_method(_tween_amplitude_y, current_amplitude, amplitude, fade) tween.set_parallel() - tween.tween_method(_tween_frequency_y.bind(screen_shaker), current_frequency, frequency, fade) + tween.tween_method(_tween_frequency_y, current_frequency, frequency, fade) await tween.finished else: screen_shaker.material.set_shader_parameter('amplitude_y', amplitude) @@ -169,9 +161,9 @@ func update_shake_y(amplitude: float = 0.0, frequency: float = 0.0, fade: float var current_amplitude := screen_shaker.material.get_shader_parameter('amplitude_y') as float var current_frequency := screen_shaker.material.get_shader_parameter('frequency_y') as float var tween := get_tree().create_tween() - tween.tween_method(_tween_amplitude_y.bind(screen_shaker.material), current_amplitude, 0.0, fade) + tween.tween_method(_tween_amplitude_y, current_amplitude, 0.0, fade) tween.set_parallel() - tween.tween_method(_tween_frequency_y.bind(screen_shaker), current_frequency, 0.0, fade) + tween.tween_method(_tween_frequency_y, current_frequency, 0.0, fade) await tween.finished else: screen_shaker.material.set_shader_parameter('amplitude_y', 0.0) @@ -182,17 +174,48 @@ func update_shake_y(amplitude: float = 0.0, frequency: float = 0.0, fade: float #endregion -func _tween_amplitude_x(value: float, material: ShaderMaterial) -> void: - material.set_shader_parameter('amplitude_x', value) +func _tween_amplitude_x(value: float) -> void: + var screen_shaker := get_screen_shaker() + + if not screen_shaker: + return + + screen_shaker.material.set_shader_parameter('amplitude_x', value) + + +func _tween_amplitude_y(value: float) -> void: + var screen_shaker := get_screen_shaker() + + if not screen_shaker: + return + + screen_shaker.material.set_shader_parameter('amplitude_y', value) -func _tween_amplitude_y(value: float, material: ShaderMaterial) -> void: - material.set_shader_parameter('amplitude_y', value) +func _tween_frequency_x(value: float) -> void: + var screen_shaker := get_screen_shaker() + if not screen_shaker: + return -func _tween_frequency_x(value: float, screen_shaker: DialogicNode_ScreenShaker) -> void: screen_shaker.update_frequency_x(value) -func _tween_frequency_y(value: float, screen_shaker: DialogicNode_ScreenShaker) -> void: +func _tween_frequency_y(value: float) -> void: + var screen_shaker := get_screen_shaker() + + if not screen_shaker: + return + screen_shaker.update_frequency_y(value) + + +func get_screen_shaker() -> DialogicNode_ScreenShaker: + var screen_shaker: DialogicNode_ScreenShaker = null + + if dialogic.has_subsystem('Styles'): + screen_shaker = dialogic.Styles.get_first_node_in_layout('dialogic_screen_shaker') + else: + screen_shaker = get_tree().get_first_node_in_group('dialogic_screen_shaker') + + return screen_shaker From 1c0426fb6afd798a233e03603c530bdd7ad63b63 Mon Sep 17 00:00:00 2001 From: Salia Nifo Date: Fri, 13 Dec 2024 09:07:22 -0500 Subject: [PATCH 3/4] Add subsystem to DialogicGameHandler.gd --- addons/dialogic/Core/DialogicGameHandler.gd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/dialogic/Core/DialogicGameHandler.gd b/addons/dialogic/Core/DialogicGameHandler.gd index a6e6e0303..30ba65255 100644 --- a/addons/dialogic/Core/DialogicGameHandler.gd +++ b/addons/dialogic/Core/DialogicGameHandler.gd @@ -138,6 +138,9 @@ var Portraits := preload("res://addons/dialogic/Modules/Character/subsystem_port var Save := preload("res://addons/dialogic/Modules/Save/subsystem_save.gd").new(): get: return get_subsystem("Save") +var ScreenShake := preload("res://addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd").new(): + get: return get_subsystem("ScreenShake") + var Settings := preload("res://addons/dialogic/Modules/Settings/subsystem_settings.gd").new(): get: return get_subsystem("Settings") From 4ecf18739443fc2f567d1e07eaa3b3a51aa97429 Mon Sep 17 00:00:00 2001 From: Salia Nifo Date: Fri, 11 Apr 2025 21:56:04 -0400 Subject: [PATCH 4/4] Fix default duration, add UIDs, add to default styles --- .../Layer_ScreenShake/screen_shake_layer.gd.uid | 1 + .../screen_shake_layer.gdshader.uid | 1 + .../Layer_ScreenShake/screen_shake_layer.tscn | 6 +++--- .../speaker_textbox_style.tres | 13 ++++++++++--- .../Style_VN_Default/default_vn_style.tres | 15 +++++++++++---- .../Modules/ScreenShake/event_screen_shake.gd | 2 +- .../Modules/ScreenShake/event_screen_shake.gd.uid | 1 + addons/dialogic/Modules/ScreenShake/index.gd.uid | 1 + .../Modules/ScreenShake/node_screen_shaker.gd.uid | 1 + .../ScreenShake/subsystem_screen_shake.gd.uid | 1 + 10 files changed, 31 insertions(+), 11 deletions(-) create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd.uid create mode 100644 addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader.uid create mode 100644 addons/dialogic/Modules/ScreenShake/event_screen_shake.gd.uid create mode 100644 addons/dialogic/Modules/ScreenShake/index.gd.uid create mode 100644 addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd.uid create mode 100644 addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd.uid diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd.uid new file mode 100644 index 000000000..8a53a3d7c --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd.uid @@ -0,0 +1 @@ +uid://pf00w14gv64m diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader.uid b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader.uid new file mode 100644 index 000000000..8b7caabe7 --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader.uid @@ -0,0 +1 @@ +uid://ckbeep0lno2h1 diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn index 7c6230b9b..5ad82033f 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=5 format=3 uid="uid://cdvx2jejg8xln"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd" id="1_l682i"] -[ext_resource type="Shader" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader" id="2_7h78g"] -[ext_resource type="Script" path="res://addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd" id="3_uqmkn"] +[ext_resource type="Script" uid="uid://pf00w14gv64m" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd" id="1_l682i"] +[ext_resource type="Shader" uid="uid://ckbeep0lno2h1" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader" id="2_7h78g"] +[ext_resource type="Script" uid="uid://bb1ano1eqhunf" path="res://addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd" id="3_uqmkn"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_4u8q6"] shader = ExtResource("2_7h78g") 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 ce61f628c..45a98d82e 100644 --- a/addons/dialogic/Modules/DefaultLayoutParts/Style_SpeakerTextbox/speaker_textbox_style.tres +++ b/addons/dialogic/Modules/DefaultLayoutParts/Style_SpeakerTextbox/speaker_textbox_style.tres @@ -1,4 +1,4 @@ -[gd_resource type="Resource" script_class="DialogicStyle" load_steps=18 format=3 uid="uid://dgkmuyvy5qc35"] +[gd_resource type="Resource" script_class="DialogicStyle" load_steps=20 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://bwg6yncmh2cml" path="res://addons/dialogic/Resources/dialogic_style_layer.gd" id="2_i34tx"] @@ -8,6 +8,7 @@ [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="PackedScene" uid="uid://cdvx2jejg8xln" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn" id="9_nxqau"] [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"] @@ -49,10 +50,15 @@ script = ExtResource("2_i34tx") scene = ExtResource("8_00chv") overrides = {} +[sub_resource type="Resource" id="Resource_sw2nc"] +script = ExtResource("2_i34tx") +scene = ExtResource("9_nxqau") +overrides = {} + [resource] script = ExtResource("9_sdr6x") name = "Speaker Textbox Style" -layer_list = Array[String](["10", "11", "12", "13", "14", "15", "16"]) +layer_list = Array[String](["10", "17", "11", "12", "13", "14", "15", "16"]) layer_info = { "": SubResource("Resource_1cyj6"), "10": SubResource("Resource_jk75o"), @@ -61,7 +67,8 @@ layer_info = { "13": SubResource("Resource_axty6"), "14": SubResource("Resource_xh5pc"), "15": SubResource("Resource_ytmk0"), -"16": SubResource("Resource_yjxtw") +"16": SubResource("Resource_yjxtw"), +"17": SubResource("Resource_sw2nc") } base_overrides = {} layers = Array[ExtResource("2_i34tx")]([]) 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 673fb886f..68e96297e 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,4 +1,4 @@ -[gd_resource type="Resource" script_class="DialogicStyle" load_steps=20 format=3 uid="uid://8t1mr302tmqs"] +[gd_resource type="Resource" script_class="DialogicStyle" load_steps=22 format=3 uid="uid://8t1mr302tmqs"] [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"] @@ -9,6 +9,7 @@ [ext_resource type="PackedScene" uid="uid://dsbwnp5hegnu3" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_Glossary/glossary_popup_layer.tscn" id="7_vw5f4"] [ext_resource type="PackedScene" uid="uid://dhk6j6eb6e3q" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_VN_Choices/vn_choice_layer.tscn" id="8_tc6v1"] [ext_resource type="PackedScene" uid="uid://cvgf4c6gg0tsy" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_TextInput/text_input_layer.tscn" id="9_tufw5"] +[ext_resource type="PackedScene" uid="uid://cdvx2jejg8xln" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.tscn" id="10_0qncn"] [ext_resource type="PackedScene" uid="uid://lx24i8fl6uo" path="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_History/history_layer.tscn" id="10_8v8jj"] [sub_resource type="Resource" id="Resource_3dixn"] @@ -55,10 +56,15 @@ script = ExtResource("2_3b8ue") scene = ExtResource("10_8v8jj") overrides = {} +[sub_resource type="Resource" id="Resource_tnh7v"] +script = ExtResource("2_3b8ue") +scene = ExtResource("10_0qncn") +overrides = {} + [resource] script = ExtResource("1_mvpc0") name = "Visual Novel Style" -layer_list = Array[String](["10", "11", "12", "13", "14", "15", "16", "17"]) +layer_list = Array[String](["10", "11", "18", "12", "13", "14", "15", "16", "17"]) layer_info = { "": SubResource("Resource_3dixn"), "10": SubResource("Resource_gen8e"), @@ -68,8 +74,9 @@ layer_info = { "14": SubResource("Resource_pvwog"), "15": SubResource("Resource_spe5r"), "16": SubResource("Resource_jf1ol"), -"17": SubResource("Resource_gs5pl") +"17": SubResource("Resource_gs5pl"), +"18": SubResource("Resource_tnh7v") } base_overrides = {} layers = Array[ExtResource("2_3b8ue")]([]) -metadata/_latest_layer = "17" +metadata/_latest_layer = "18" diff --git a/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd b/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd index bcc35530a..06ae9ef32 100644 --- a/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd +++ b/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd @@ -18,7 +18,7 @@ var direction := Direction.HORIZONTAL var fade: float = 0.0 ## The time the screen should shake for (excludes fade time). ## Leave at 0 to keep shaking until the next screen shake event. -var duration: float = 0.0 +var duration: float = 10.0 ## If true, the event will wait for completion before continuing ## (only if duration is greater than 0.0 or fade greater than 0.0 and amplitude is 0.0). var wait := false diff --git a/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd.uid b/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd.uid new file mode 100644 index 000000000..db350ccba --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/event_screen_shake.gd.uid @@ -0,0 +1 @@ +uid://chapa5hltp6ac diff --git a/addons/dialogic/Modules/ScreenShake/index.gd.uid b/addons/dialogic/Modules/ScreenShake/index.gd.uid new file mode 100644 index 000000000..be34217ac --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/index.gd.uid @@ -0,0 +1 @@ +uid://cpq1bgdnqrmth diff --git a/addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd.uid b/addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd.uid new file mode 100644 index 000000000..88db6f40c --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/node_screen_shaker.gd.uid @@ -0,0 +1 @@ +uid://bb1ano1eqhunf diff --git a/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd.uid b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd.uid new file mode 100644 index 000000000..f0dddb392 --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd.uid @@ -0,0 +1 @@ +uid://l5ry6a5mdtxn