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") 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 000000000..488729ba8 Binary files /dev/null and b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png differ diff --git a/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png.import b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png.import new file mode 100644 index 000000000..94989c8df --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwhucf14pvkfs" +path="res://.godot/imported/preview.png-f4b273872c0dd56a22386a20ccb82f99.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/preview.png" +dest_files=["res://.godot/imported/preview.png-f4b273872c0dd56a22386a20ccb82f99.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/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd new file mode 100644 index 000000000..9162300ec --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gd @@ -0,0 +1,2 @@ +@tool +extends DialogicLayoutLayer 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 b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader new file mode 100644 index 000000000..74584f028 --- /dev/null +++ b/addons/dialogic/Modules/DefaultLayoutParts/Layer_ScreenShake/screen_shake_layer.gdshader @@ -0,0 +1,35 @@ +shader_type canvas_item; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, repeat_disable, filter_nearest; + +uniform float amplitude_x : hint_range(0.0, 1.0) = 0.0; +uniform float frequency_x = 0.0; +uniform float phase_x = 0.0; +uniform float time_x = 0.0; + +uniform float amplitude_y : hint_range(0.0, 1.0) = 0.0; +uniform float frequency_y = 0.0; +uniform float phase_y = 0.0; +uniform float time_y = 0.0; + +uniform vec3 clear_color : source_color = vec3(0.0, 0.0, 0.0); + +void fragment() { + vec2 uv = SCREEN_UV; + + float angular_frequency_x = 2.0 * PI * frequency_x; + float displacement_x = amplitude_x * sin(angular_frequency_x * (time_x + phase_x)); + + float angular_frequency_y = 2.0 * PI * frequency_y; + float displacement_y = amplitude_y * sin(angular_frequency_y * (time_y + phase_y)); + + uv.x += displacement_x / 1.0; + uv.y += displacement_y / 1.0; + + if (uv.x > 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.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 new file mode 100644 index 000000000..5ad82033f --- /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" 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") +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/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 new file mode 100644 index 000000000..06ae9ef32 --- /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 = 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 + +#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/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/icon.png b/addons/dialogic/Modules/ScreenShake/icon.png new file mode 100644 index 000000000..14b815a9d Binary files /dev/null and b/addons/dialogic/Modules/ScreenShake/icon.png differ 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/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 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/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 b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd new file mode 100644 index 000000000..d2cc22185 --- /dev/null +++ b/addons/dialogic/Modules/ScreenShake/subsystem_screen_shake.gd @@ -0,0 +1,221 @@ +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 := get_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, current_amplitude, amplitude, fade) + tween.set_parallel() + tween.tween_method(_tween_frequency_x, 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, current_amplitude, 0.0, fade) + tween.set_parallel() + 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) + 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 := get_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, current_amplitude, amplitude, fade) + tween.set_parallel() + tween.tween_method(_tween_frequency_y, 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, current_amplitude, 0.0, fade) + tween.set_parallel() + 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) + screen_shaker.update_frequency_y(frequency) + + dialogic.current_state_info['screen_shake']['y'] = {} + shake_vertical_finished.emit() + +#endregion + +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_frequency_x(value: float) -> void: + var screen_shaker := get_screen_shaker() + + if not screen_shaker: + return + + screen_shaker.update_frequency_x(value) + + +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 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