From 47eba63990e5fe8a64b1e790908f54164480013f Mon Sep 17 00:00:00 2001 From: Yann Kervran Date: Thu, 28 Nov 2024 10:46:27 +0100 Subject: [PATCH] Adding sound thanks to Event Adio plugin --- addons/event_audio/EventAudio.cs | 55 +++++ addons/event_audio/event_audio.gd | 207 ++++++++++++++++++ .../event_audio/example/ExampleEmitter3D.cs | 59 +++++ .../example/csharp_example_3D.tscn | 31 +++ addons/event_audio/example/example2D.tscn | 33 +++ addons/event_audio/example/example3D.tscn | 31 +++ .../example/example_audio_bank.tres | 94 ++++++++ .../event_audio/example/example_emitter_2d.gd | 48 ++++ .../event_audio/example/example_emitter_3d.gd | 50 +++++ addons/event_audio/example/example_ui.tscn | 24 ++ addons/event_audio/example/sounds/laser1.wav | Bin 0 -> 29954 bytes .../example/sounds/laser1.wav.import | 24 ++ addons/event_audio/example/sounds/laser2.wav | Bin 0 -> 21718 bytes .../example/sounds/laser2.wav.import | 24 ++ addons/event_audio/example/sounds/loop.wav | Bin 0 -> 63228 bytes .../example/sounds/loop.wav.import | 24 ++ addons/event_audio/example/sounds/shot1.wav | Bin 0 -> 23912 bytes .../example/sounds/shot1.wav.import | 24 ++ addons/event_audio/example/sounds/shot2.wav | Bin 0 -> 69156 bytes .../example/sounds/shot2.wav.import | 24 ++ addons/event_audio/icon.png | Bin 0 -> 35544 bytes addons/event_audio/icon.png.import | 34 +++ addons/event_audio/icons/Add.svg | 1 + addons/event_audio/icons/Add.svg.import | 37 ++++ addons/event_audio/icons/Close.svg | 1 + addons/event_audio/icons/Close.svg.import | 37 ++++ addons/event_audio/icons/Play.svg | 1 + addons/event_audio/icons/Play.svg.import | 37 ++++ .../icons/RandomNumberGenerator.svg | 1 + .../icons/RandomNumberGenerator.svg.import | 37 ++++ addons/event_audio/icons/Remove.svg | 1 + addons/event_audio/icons/Remove.svg.import | 37 ++++ addons/event_audio/icons/Tools.svg | 1 + addons/event_audio/icons/Tools.svg.import | 37 ++++ addons/event_audio/plugin.cfg | 6 + addons/event_audio/plugin.gd | 33 +++ addons/event_audio/scenes/bank_line.tscn | 68 ++++++ .../scenes/bank_resource_line.tscn | 76 +++++++ .../scenes/event_audio_autoload.tscn | 8 + addons/event_audio/src/ea_editor_tools.gd | 201 +++++++++++++++++ addons/event_audio/src/ea_event.gd | 40 ++++ addons/event_audio/src/ea_event_bank.gd | 27 +++ .../src/ea_event_bank_inspector.gd | 11 + .../event_audio/src/ea_event_bank_mounter.gd | 13 ++ .../event_audio/src/ea_event_bank_property.gd | 109 +++++++++ .../event_audio/src/ea_event_edit_control.gd | 91 ++++++++ .../src/ea_event_playback_settings.gd | 22 ++ .../event_audio/src/ea_stream_edit_control.gd | 131 +++++++++++ main.gd | 10 +- main.tscn | 10 +- project.godot | 8 + sounds/{ => assets}/dieShuffle1.ogg | Bin sounds/assets/dieShuffle1.ogg.import | 19 ++ sounds/dieShuffle1.ogg.import | 19 -- sounds/eventbanks/UI_sounds.tres | 30 +++ 55 files changed, 1924 insertions(+), 22 deletions(-) create mode 100644 addons/event_audio/EventAudio.cs create mode 100644 addons/event_audio/event_audio.gd create mode 100644 addons/event_audio/example/ExampleEmitter3D.cs create mode 100644 addons/event_audio/example/csharp_example_3D.tscn create mode 100644 addons/event_audio/example/example2D.tscn create mode 100644 addons/event_audio/example/example3D.tscn create mode 100644 addons/event_audio/example/example_audio_bank.tres create mode 100644 addons/event_audio/example/example_emitter_2d.gd create mode 100644 addons/event_audio/example/example_emitter_3d.gd create mode 100644 addons/event_audio/example/example_ui.tscn create mode 100644 addons/event_audio/example/sounds/laser1.wav create mode 100644 addons/event_audio/example/sounds/laser1.wav.import create mode 100644 addons/event_audio/example/sounds/laser2.wav create mode 100644 addons/event_audio/example/sounds/laser2.wav.import create mode 100644 addons/event_audio/example/sounds/loop.wav create mode 100644 addons/event_audio/example/sounds/loop.wav.import create mode 100644 addons/event_audio/example/sounds/shot1.wav create mode 100644 addons/event_audio/example/sounds/shot1.wav.import create mode 100644 addons/event_audio/example/sounds/shot2.wav create mode 100644 addons/event_audio/example/sounds/shot2.wav.import create mode 100644 addons/event_audio/icon.png create mode 100644 addons/event_audio/icon.png.import create mode 100644 addons/event_audio/icons/Add.svg create mode 100644 addons/event_audio/icons/Add.svg.import create mode 100644 addons/event_audio/icons/Close.svg create mode 100644 addons/event_audio/icons/Close.svg.import create mode 100644 addons/event_audio/icons/Play.svg create mode 100644 addons/event_audio/icons/Play.svg.import create mode 100644 addons/event_audio/icons/RandomNumberGenerator.svg create mode 100644 addons/event_audio/icons/RandomNumberGenerator.svg.import create mode 100644 addons/event_audio/icons/Remove.svg create mode 100644 addons/event_audio/icons/Remove.svg.import create mode 100644 addons/event_audio/icons/Tools.svg create mode 100644 addons/event_audio/icons/Tools.svg.import create mode 100644 addons/event_audio/plugin.cfg create mode 100644 addons/event_audio/plugin.gd create mode 100644 addons/event_audio/scenes/bank_line.tscn create mode 100644 addons/event_audio/scenes/bank_resource_line.tscn create mode 100644 addons/event_audio/scenes/event_audio_autoload.tscn create mode 100644 addons/event_audio/src/ea_editor_tools.gd create mode 100644 addons/event_audio/src/ea_event.gd create mode 100644 addons/event_audio/src/ea_event_bank.gd create mode 100644 addons/event_audio/src/ea_event_bank_inspector.gd create mode 100644 addons/event_audio/src/ea_event_bank_mounter.gd create mode 100644 addons/event_audio/src/ea_event_bank_property.gd create mode 100644 addons/event_audio/src/ea_event_edit_control.gd create mode 100644 addons/event_audio/src/ea_event_playback_settings.gd create mode 100644 addons/event_audio/src/ea_stream_edit_control.gd rename sounds/{ => assets}/dieShuffle1.ogg (100%) create mode 100644 sounds/assets/dieShuffle1.ogg.import delete mode 100644 sounds/dieShuffle1.ogg.import create mode 100644 sounds/eventbanks/UI_sounds.tres diff --git a/addons/event_audio/EventAudio.cs b/addons/event_audio/EventAudio.cs new file mode 100644 index 0000000..e52d9f0 --- /dev/null +++ b/addons/event_audio/EventAudio.cs @@ -0,0 +1,55 @@ +using Godot; + +public partial class EventAudio : Node { + static private EventAudio _instance; + private GodotObject _eventAudio; + private Callable _play3DMethod; + private Callable _play2DMethod; + private Callable _stopMethod; + + // Simple 'handle' class for managing Godot audio emitters. + public class EventAudioEmitter { + public GodotObject Emitter; + + public EventAudioEmitter(GodotObject emitter) { + Emitter = emitter; + } + } + + public override void _Ready() { + base._Ready(); + _eventAudio = GetParent().GetNode("EventAudio"); + _play3DMethod = _eventAudio.Get("play_3d").AsCallable(); + _play2DMethod = _eventAudio.Get("play_2d").AsCallable(); + _stopMethod = _eventAudio.Get("stop").AsCallable(); + _instance = this; + } + + public static EventAudio Instance { + get { + return _instance; + } + } + + public EventAudioEmitter Play2D(string trigger, Node3D source) { + var result = _play2DMethod.Call(trigger, source); + var godotEmitter = result.AsGodotObject(); + if (godotEmitter != null) { + return new EventAudioEmitter(godotEmitter); + } + return null; + } + + public EventAudioEmitter Play3D(string trigger, Node3D source) { + var result = _play3DMethod.Call(trigger, source); + var godotEmitter = result.AsGodotObject(); + if (godotEmitter != null) { + return new EventAudioEmitter(godotEmitter); + } + return null; + } + + public void Stop(EventAudioEmitter emitter) { + _stopMethod.Call(emitter.Emitter); + } +} diff --git a/addons/event_audio/event_audio.gd b/addons/event_audio/event_audio.gd new file mode 100644 index 0000000..1a82bfd --- /dev/null +++ b/addons/event_audio/event_audio.gd @@ -0,0 +1,207 @@ +extends Node + +# Ideally this would be called just EventAudio, but that would class with the autoload +class_name EventAudioAPI +static var _separator := "+" +static var instance : EventAudioAPI + +@export var log_lookups := false +@export var log_deaths := false +@export var log_registrations := false + +var _trigger_map: Dictionary +var _rng: RandomNumberGenerator +var _audio_banks: Array[EAEventBank] + +class AudioEmitter2D: + var source: Node2D + var player: AudioStreamPlayer2D + var event: EAEvent + +var _active_emitters_2d = Array() + +class AudioEmitter3D: + var source: Node3D + var player: AudioStreamPlayer3D + var event: EAEvent + +var _active_emitters_3d = Array() + +#--------------------------------------------------------- +# API +#--------------------------------------------------------- +static func get_instance() -> EventAudioAPI: + return instance + +func play_2d(trigger: String, source: Node2D) -> AudioEmitter2D: + var event := _find_event_for_trigger(trigger) + if event == null: + return null + + var stream_player = AudioStreamPlayer2D.new() + return _play_event(event, stream_player, source) + +func play_3d(trigger: String, source: Node3D) -> AudioEmitter3D: + var event := _find_event_for_trigger(trigger) + if event == null: + return null + + var stream_player = AudioStreamPlayer3D.new() + return _play_event(event, stream_player, source) + +func stop(emitter): + if emitter.player != null: + emitter.player.stop() + +func register_event_bank(bank: EAEventBank): + if log_registrations: + print("Registering bank: " + bank.resource_path) + _audio_banks.append(bank) + _invalidate_trigger_map() + +func unregister_event_bank(bank: EAEventBank): + if log_registrations: + print("Unregistering bank: " + bank.resource_name) + var idx := _audio_banks.find(bank) + if idx >= 0: + _audio_banks.remove_at(idx) + _invalidate_trigger_map() + +static func init_player_from_playback_settings(rng, stream_player, settings: EAEventPlaybackSettings): + var min_pitch := min(settings.min_pitch, settings.max_pitch) as float + var max_pitch := max(settings.min_pitch, settings.max_pitch) as float + var pitch = rng.randf_range(min_pitch, max_pitch) + stream_player.pitch_scale = pitch + stream_player.volume_db = settings.volume_db + + if stream_player is AudioStreamPlayer3D: + stream_player.unit_size = settings.unit_size + stream_player.max_db = settings.max_db + stream_player.panning_strength = settings.panning_strength + + elif stream_player is AudioStreamPlayer2D: + stream_player.max_distance = settings.max_distance + stream_player.attenuation = settings.attenuation + stream_player.panning_strength = settings.panning_strength + +#--------------------------------------------------------- +func _init(): + _rng = RandomNumberGenerator.new() + +func _process(_delta: float): + _active_emitters_2d = _process_active_audio(_active_emitters_2d) + _active_emitters_3d = _process_active_audio(_active_emitters_3d) + +func _process_active_audio(active_audio): + var new_active_audio := Array() + + # TODO - find a better way of modifying the list of active audio emitters + for audio in active_audio: + var alive := true + if audio.player == null: + alive = false + elif not audio.player.playing: + audio.player.queue_free() + audio.player = null + alive = false + elif audio.source == null: + if audio.event.playback_settings.stop_when_source_dies: + audio.player.stop() + alive = false + + # Update the position + if not audio.event.playback_settings.stationary and alive and audio.source != null: + audio.player.global_position = audio.source.global_position + + if alive: + new_active_audio.append(audio) + else: + _log_death(audio.event.trigger_tags) + return new_active_audio + +func _enter_tree(): + instance = self + +func _exit_tree(): + instance = null + +#--------------------------------------------------------------------------------- +# Internals +#--------------------------------------------------------------------------------- +func _play_event(event: EAEvent, stream_player, source: Node): + var stream := event.get_weighted_random_stream(_rng.randf()) + stream_player.name = "AudioPlayback" + add_child(stream_player) + stream_player.stream = stream + + EventAudioAPI.init_player_from_playback_settings(_rng, stream_player, event.playback_settings) + + if source: + stream_player.global_position = source.global_position + + stream_player.play() + + if stream_player is AudioStreamPlayer2D: + var emitter := AudioEmitter2D.new() + emitter.player = stream_player + emitter.source = source + emitter.event = event + _active_emitters_2d.append(emitter) + return emitter + else: + var emitter = AudioEmitter3D.new() + emitter.player = stream_player + emitter.source = source + emitter.event = event + _active_emitters_3d.append(emitter) + return emitter + + +func _invalidate_trigger_map(): + _trigger_map = {} + +func _make_trigger_map(): + _trigger_map = {} + for bank: EAEventBank in _audio_banks: + for entry in bank.entries: + var key = entry.trigger_tags + _trigger_map[key] = entry + +func _find_event_for_trigger(trigger: String) -> EAEvent: + if _trigger_map.size() == 0: + _make_trigger_map() + + var current_trigger := trigger + + while current_trigger != "": + _log_lookup(current_trigger) + var found_entry := _trigger_map.get(current_trigger) as EAEvent + if found_entry: + _log_found(found_entry.trigger_tags) + return found_entry + var tag_pos := current_trigger.rfind(_separator) + if tag_pos >= 0: + current_trigger = current_trigger.substr(0, tag_pos) + else: + current_trigger = "" + return null + +func _log_lookup(msg: String): + if log_lookups: + print("Trying " + msg) + +func _log_found(msg: String): + if log_lookups: + print("Found " + msg) + +func _log_bank_add(msg: String): + if log_registrations: + print("Registering Bank " + msg) + +func _log_bank_remove(msg: String): + if log_registrations: + print("Unregistering Bank " + msg) + +func _log_death(msg: String): + if log_deaths: + print("Killing " + msg) diff --git a/addons/event_audio/example/ExampleEmitter3D.cs b/addons/event_audio/example/ExampleEmitter3D.cs new file mode 100644 index 0000000..6886977 --- /dev/null +++ b/addons/event_audio/example/ExampleEmitter3D.cs @@ -0,0 +1,59 @@ +using Godot; + + +public partial class ExampleEmitter3D : Node3D { + [Export] + float Speed = 1.0f; + [Export] + Node3D OrbitNode; + EventAudio.EventAudioEmitter _loopEmitter; + float _orbitRadius = 1.0f; + + public override void _Ready() { + _orbitRadius = (GlobalPosition - OrbitNode.GlobalPosition).Length(); + } + + public override void _Process(double _delta) { + float orbitAngle = (Time.GetTicksMsec() / 1000.0f % Speed) * 2.0f * 3.14159f; + float offset_x = _orbitRadius * Mathf.Cos(orbitAngle); + float offset_y = _orbitRadius * Mathf.Sin(orbitAngle); + + var new_position = OrbitNode.GlobalPosition; + new_position.X += offset_x; + new_position.Z += offset_y; + + GlobalPosition = new_position; + } + + public override void _Input(InputEvent ev_) { + if (!(ev_ is InputEventKey) || !ev_.IsPressed()) { + return; + } + + var ev = ev_ as InputEventKey; + if (ev.Keycode == Key.Key1) { + EventAudio.Instance.Play3D("hit", this); + } + + if (ev.Keycode == Key.Key2) { + EventAudio.Instance.Play3D("hit+large", this); + } + + if (ev.Keycode == Key.Key3) { + EventAudio.Instance.Play3D("hit+nonexistent", this); + } + + if (ev.Keycode == Key.Key4) { + EventAudio.Instance.Play3D("random_shoot", this); + } + + if (ev.Keycode == Key.Key5) { + if (_loopEmitter != null) { + EventAudio.Instance.Stop(_loopEmitter); + _loopEmitter = null; + } else { + _loopEmitter = EventAudio.Instance.Play3D("loop", this); + } + } + } +} diff --git a/addons/event_audio/example/csharp_example_3D.tscn b/addons/event_audio/example/csharp_example_3D.tscn new file mode 100644 index 0000000..a539958 --- /dev/null +++ b/addons/event_audio/example/csharp_example_3D.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=6 format=3 uid="uid://fk1nqp2seuw6"] + +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_bank_mounter.gd" id="1_0y6i8"] +[ext_resource type="Resource" uid="uid://cfxmacq8po281" path="res://addons/event_audio/example/example_audio_bank.tres" id="2_qo1e5"] +[ext_resource type="Script" path="res://addons/event_audio/example/ExampleEmitter3D.cs" id="3_w1shi"] +[ext_resource type="PackedScene" uid="uid://kjsaalyhmkc5" path="res://addons/event_audio/example/example_ui.tscn" id="4_e42vy"] + +[sub_resource type="SphereMesh" id="SphereMesh_3bdsu"] + +[node name="Example3d" type="Node3D"] + +[node name="Camera3D" type="Camera3D" parent="."] + +[node name="Node3D" type="Node3D" parent="." node_paths=PackedStringArray("OrbitNode")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4.70263) +script = ExtResource("3_w1shi") +OrbitNode = NodePath("../Camera3D") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D"] +mesh = SubResource("SphereMesh_3bdsu") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.176947, 0.98422, 0, -0.98422, 0.176947, 0, 1.9958, 0) + +[node name="ExampleAudioBank" type="Node" parent="."] +script = ExtResource("1_0y6i8") +_audio_bank_resource = ExtResource("2_qo1e5") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="ExampleUi" parent="CanvasLayer" instance=ExtResource("4_e42vy")] diff --git a/addons/event_audio/example/example2D.tscn b/addons/event_audio/example/example2D.tscn new file mode 100644 index 0000000..44bc846 --- /dev/null +++ b/addons/event_audio/example/example2D.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=6 format=3 uid="uid://konnaekcsk2e"] + +[ext_resource type="Script" path="res://addons/event_audio/example/example_emitter_2d.gd" id="1_7u4pm"] +[ext_resource type="Resource" uid="uid://cfxmacq8po281" path="res://addons/event_audio/example/example_audio_bank.tres" id="3_kb4ey"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_bank_mounter.gd" id="3_q1afy"] +[ext_resource type="PackedScene" uid="uid://kjsaalyhmkc5" path="res://addons/event_audio/example/example_ui.tscn" id="4_kisj8"] + +[sub_resource type="SphereMesh" id="SphereMesh_7scev"] +radius = 10.0 +height = 20.0 + +[node name="Example2d" type="Node2D"] + +[node name="Emitter" type="MeshInstance2D" parent="."] +position = Vector2(2.08165e-12, 175.95) +mesh = SubResource("SphereMesh_7scev") +script = ExtResource("1_7u4pm") + +[node name="Camera2D" type="Camera2D" parent="."] +position = Vector2(578, 324) + +[node name="AudioListener2D" type="AudioListener2D" parent="Camera2D"] +current = true + +[node name="TestAudioBank" type="Node" parent="."] +script = ExtResource("3_q1afy") +_audio_bank_resource = ExtResource("3_kb4ey") + +[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="."] + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="ExampleUi" parent="CanvasLayer" instance=ExtResource("4_kisj8")] diff --git a/addons/event_audio/example/example3D.tscn b/addons/event_audio/example/example3D.tscn new file mode 100644 index 0000000..ed362d0 --- /dev/null +++ b/addons/event_audio/example/example3D.tscn @@ -0,0 +1,31 @@ +[gd_scene load_steps=6 format=3 uid="uid://b12tpedbx38u7"] + +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_bank_mounter.gd" id="1_ncilt"] +[ext_resource type="Resource" uid="uid://cfxmacq8po281" path="res://addons/event_audio/example/example_audio_bank.tres" id="2_nj06b"] +[ext_resource type="Script" path="res://addons/event_audio/example/example_emitter_3d.gd" id="3_wpepl"] +[ext_resource type="PackedScene" uid="uid://kjsaalyhmkc5" path="res://addons/event_audio/example/example_ui.tscn" id="4_sw6y2"] + +[sub_resource type="SphereMesh" id="SphereMesh_3bdsu"] + +[node name="Example3d" type="Node3D"] + +[node name="Camera3D" type="Camera3D" parent="."] + +[node name="Node3D" type="Node3D" parent="." node_paths=PackedStringArray("OrbitNode")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -4.70263) +script = ExtResource("3_wpepl") +OrbitNode = NodePath("../Camera3D") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="Node3D"] +mesh = SubResource("SphereMesh_3bdsu") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 0.176947, 0.98422, 0, -0.98422, 0.176947, 0, 1.9958, 0) + +[node name="TestAudioBank" type="Node" parent="."] +script = ExtResource("1_ncilt") +_audio_bank_resource = ExtResource("2_nj06b") + +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="ExampleUi" parent="CanvasLayer" instance=ExtResource("4_sw6y2")] diff --git a/addons/event_audio/example/example_audio_bank.tres b/addons/event_audio/example/example_audio_bank.tres new file mode 100644 index 0000000..fc85f13 --- /dev/null +++ b/addons/event_audio/example/example_audio_bank.tres @@ -0,0 +1,94 @@ +[gd_resource type="Resource" script_class="EAEventBank" load_steps=17 format=3 uid="uid://cfxmacq8po281"] + +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event.gd" id="1_fy8lm"] +[ext_resource type="AudioStream" uid="uid://7ncmg0ox4nxr" path="res://addons/event_audio/example/sounds/loop.wav" id="2_fyotq"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_bank.gd" id="2_rbntb"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_playback_settings.gd" id="3_fy5gc"] +[ext_resource type="AudioStream" uid="uid://byg26ypxea5qh" path="res://addons/event_audio/example/sounds/laser1.wav" id="3_nyuuq"] +[ext_resource type="AudioStream" uid="uid://ftyi4ikfmbii" path="res://addons/event_audio/example/sounds/laser2.wav" id="4_ahbca"] +[ext_resource type="AudioStream" uid="uid://cqo6bi2ygpwbu" path="res://addons/event_audio/example/sounds/shot1.wav" id="4_fpv34"] +[ext_resource type="AudioStream" uid="uid://cultflwybpfo1" path="res://addons/event_audio/example/sounds/shot2.wav" id="5_1yf0v"] + +[sub_resource type="Resource" id="Resource_dd35s"] +script = ExtResource("3_fy5gc") +stop_when_source_dies = false +stationary = true +volume_db = 0.0 +min_pitch = 0.8 +max_pitch = 1.2 +panning_strength = 1.0 +attenuation = 1.0 +max_distance = 2000 +unit_size = 10.0 +max_db = 3.0 + +[sub_resource type="Resource" id="Resource_lfo5e"] +script = ExtResource("1_fy8lm") +audio_streams = Array[AudioStream]([ExtResource("4_fpv34")]) +probability_weights = Array[float]([1.0]) +trigger_tags = "hit" +playback_settings = SubResource("Resource_dd35s") + +[sub_resource type="Resource" id="Resource_j54ca"] +script = ExtResource("3_fy5gc") +stop_when_source_dies = false +stationary = true +volume_db = 0.0 +min_pitch = 0.9 +max_pitch = 1.2 +panning_strength = 1.0 +attenuation = 1.0 +max_distance = 2000 +unit_size = 10.0 +max_db = 3.0 + +[sub_resource type="Resource" id="Resource_d2op2"] +script = ExtResource("1_fy8lm") +audio_streams = Array[AudioStream]([ExtResource("5_1yf0v")]) +probability_weights = Array[float]([1.0]) +trigger_tags = "hit+large" +playback_settings = SubResource("Resource_j54ca") + +[sub_resource type="Resource" id="Resource_ljdcd"] +script = ExtResource("3_fy5gc") +stop_when_source_dies = false +stationary = false +volume_db = 0.0 +min_pitch = 0.8 +max_pitch = 1.2 +panning_strength = 2.0 +attenuation = 1.0 +max_distance = 2000 +unit_size = 10.0 +max_db = 3.0 + +[sub_resource type="Resource" id="Resource_ps0cx"] +script = ExtResource("1_fy8lm") +audio_streams = Array[AudioStream]([ExtResource("2_fyotq")]) +probability_weights = Array[float]([1.0]) +trigger_tags = "loop" +playback_settings = SubResource("Resource_ljdcd") + +[sub_resource type="Resource" id="Resource_1xrvu"] +script = ExtResource("3_fy5gc") +stop_when_source_dies = false +stationary = true +volume_db = 0.0 +min_pitch = 0.8 +max_pitch = 1.2 +panning_strength = 1.0 +attenuation = 1.0 +max_distance = 2000 +unit_size = 10.0 +max_db = 3.0 + +[sub_resource type="Resource" id="Resource_xjlcv"] +script = ExtResource("1_fy8lm") +audio_streams = Array[AudioStream]([ExtResource("3_nyuuq"), ExtResource("4_ahbca")]) +probability_weights = Array[float]([1.0, 1.0]) +trigger_tags = "random_shoot" +playback_settings = SubResource("Resource_1xrvu") + +[resource] +script = ExtResource("2_rbntb") +entries = Array[ExtResource("1_fy8lm")]([SubResource("Resource_lfo5e"), SubResource("Resource_d2op2"), SubResource("Resource_ps0cx"), SubResource("Resource_xjlcv")]) diff --git a/addons/event_audio/example/example_emitter_2d.gd b/addons/event_audio/example/example_emitter_2d.gd new file mode 100644 index 0000000..2c13293 --- /dev/null +++ b/addons/event_audio/example/example_emitter_2d.gd @@ -0,0 +1,48 @@ +extends Node2D +class_name ExampleEmitter2D + +@export var Speed := 1.0 +var _loop_emitter : EventAudioAPI.AudioEmitter2D + +func _init(): + EventAudio.log_lookups = true + EventAudio.log_registrations = true + EventAudio.log_deaths = true + +func _process(delta: float): + var screen_width := get_viewport_rect().size.x + + var step := Speed * screen_width * delta + var new_position := global_position + new_position.x += step + if new_position.x < 0: + new_position.x = 0 + Speed = -Speed + elif new_position.x >= screen_width: + new_position.x = screen_width + Speed = -Speed + + global_position = new_position + +func _input(event: InputEvent): + if not event is InputEventKey or not event.is_pressed(): + return + + if event.keycode == KEY_1: + EventAudio.play_2d("hit", self) + + if event.keycode == KEY_2: + EventAudio.play_2d("hit+large", self) + + if event.keycode == KEY_3: + EventAudio.play_2d("hit+nonexistent", self) + + if event.keycode == KEY_4: + EventAudio.play_2d("random_shoot", self) + + if event.keycode == KEY_5: + if _loop_emitter: + EventAudio.stop(_loop_emitter) + _loop_emitter = null + else: + _loop_emitter = EventAudio.play_2d("loop", self) diff --git a/addons/event_audio/example/example_emitter_3d.gd b/addons/event_audio/example/example_emitter_3d.gd new file mode 100644 index 0000000..a2b4dee --- /dev/null +++ b/addons/event_audio/example/example_emitter_3d.gd @@ -0,0 +1,50 @@ +extends Node3D +class_name ExampleEmitter3D + +@export var Speed := 1.0 +@export var OrbitNode : Node3D +var _loop_emitter : EventAudioAPI.AudioEmitter3D +var _orbit_radius := 1.0 + +func _init(): + EventAudio.log_lookups = true + EventAudio.log_registrations = true + EventAudio.log_deaths = true + +func _ready(): + _orbit_radius = (global_position - OrbitNode.global_position).length() + +func _process(_delta: float): + var orbit_angle = fmod(Time.get_ticks_msec() / 1000.0, Speed) * 2 * PI + + var offset_x = _orbit_radius * cos(orbit_angle) + var offset_y = _orbit_radius * sin(orbit_angle) + + var new_position := OrbitNode.global_position + new_position.x += offset_x + new_position.z += offset_y + + global_position = new_position + +func _input(event: InputEvent): + if not event is InputEventKey or not event.is_pressed(): + return + + if event.keycode == KEY_1: + EventAudio.play_3d("hit", self) + + if event.keycode == KEY_2: + EventAudio.play_3d("hit+large", self) + + if event.keycode == KEY_3: + EventAudio.play_3d("hit+nonexistent", self) + + if event.keycode == KEY_4: + EventAudio.play_3d("random_shoot", self) + + if event.keycode == KEY_5: + if _loop_emitter: + EventAudio.stop(_loop_emitter) + _loop_emitter = null + else: + _loop_emitter = EventAudio.play_3d("loop", self) diff --git a/addons/event_audio/example/example_ui.tscn b/addons/event_audio/example/example_ui.tscn new file mode 100644 index 0000000..de92999 --- /dev/null +++ b/addons/event_audio/example/example_ui.tscn @@ -0,0 +1,24 @@ +[gd_scene format=3 uid="uid://kjsaalyhmkc5"] + +[node name="ExampleUi" type="Control"] +layout_mode = 3 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +grow_vertical = 0 + +[node name="Label" type="Label" parent="."] +layout_mode = 1 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_top = -127.0 +offset_right = 196.0 +grow_vertical = 0 +text = "1 - Play \"hit\" +2 - Play \"hit+large\" +3 - Play \"hit+nonexistent\" +4 - Play \"random_shoot\" +5 - Toggle \"loop\"" +vertical_alignment = 2 +justification_flags = 161 diff --git a/addons/event_audio/example/sounds/laser1.wav b/addons/event_audio/example/sounds/laser1.wav new file mode 100644 index 0000000000000000000000000000000000000000..c7f18b8c2cd12f0659221f0bae8fff85e3b37a1f GIT binary patch literal 29954 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 H|Kaa{cnES% literal 0 HcmV?d00001 diff --git a/addons/event_audio/example/sounds/laser1.wav.import b/addons/event_audio/example/sounds/laser1.wav.import new file mode 100644 index 0000000..8888780 --- /dev/null +++ b/addons/event_audio/example/sounds/laser1.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://byg26ypxea5qh" +path="res://.godot/imported/laser1.wav-7c7bf6a86d0428120783ce6ae72e8afb.sample" + +[deps] + +source_file="res://addons/event_audio/example/sounds/laser1.wav" +dest_files=["res://.godot/imported/laser1.wav-7c7bf6a86d0428120783ce6ae72e8afb.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/addons/event_audio/example/sounds/laser2.wav b/addons/event_audio/example/sounds/laser2.wav new file mode 100644 index 0000000000000000000000000000000000000000..975a33f0243609994cfa55b8dce9a4f388ee13b3 GIT binary patch literal 21718 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 literal 0 HcmV?d00001 diff --git a/addons/event_audio/example/sounds/shot1.wav.import b/addons/event_audio/example/sounds/shot1.wav.import new file mode 100644 index 0000000..7b954db --- /dev/null +++ b/addons/event_audio/example/sounds/shot1.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cqo6bi2ygpwbu" +path="res://.godot/imported/shot1.wav-d93bbca9f7efde511f9d9572265cbb25.sample" + +[deps] + +source_file="res://addons/event_audio/example/sounds/shot1.wav" +dest_files=["res://.godot/imported/shot1.wav-d93bbca9f7efde511f9d9572265cbb25.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/addons/event_audio/example/sounds/shot2.wav b/addons/event_audio/example/sounds/shot2.wav new file mode 100644 index 0000000000000000000000000000000000000000..a9e0a6c766070bdb85c59c81ce671de7b2b1c963 GIT binary patch literal 69156 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

Ph=&Pq@JOsw8_=m6Kzrqy7${ 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 YKco%<0Urj5i2wiq07*qoM6N<$f<84cU;qFB literal 0 HcmV?d00001 diff --git a/addons/event_audio/icon.png.import b/addons/event_audio/icon.png.import new file mode 100644 index 0000000..091649d --- /dev/null +++ b/addons/event_audio/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d3rrns80mmgqo" +path="res://.godot/imported/icon.png-5ff47921d459c4c7814e206e0a2e0cc0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icon.png" +dest_files=["res://.godot/imported/icon.png-5ff47921d459c4c7814e206e0a2e0cc0.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/event_audio/icons/Add.svg b/addons/event_audio/icons/Add.svg new file mode 100644 index 0000000..afad08a --- /dev/null +++ b/addons/event_audio/icons/Add.svg @@ -0,0 +1 @@ + diff --git a/addons/event_audio/icons/Add.svg.import b/addons/event_audio/icons/Add.svg.import new file mode 100644 index 0000000..084813a --- /dev/null +++ b/addons/event_audio/icons/Add.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dqg7mfau2g7ck" +path="res://.godot/imported/Add.svg-219bdd038475c83ffbebee883f646de0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icons/Add.svg" +dest_files=["res://.godot/imported/Add.svg-219bdd038475c83ffbebee883f646de0.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=true +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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/event_audio/icons/Close.svg b/addons/event_audio/icons/Close.svg new file mode 100644 index 0000000..be1c1dc --- /dev/null +++ b/addons/event_audio/icons/Close.svg @@ -0,0 +1 @@ + diff --git a/addons/event_audio/icons/Close.svg.import b/addons/event_audio/icons/Close.svg.import new file mode 100644 index 0000000..90d5361 --- /dev/null +++ b/addons/event_audio/icons/Close.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://pad8hlsq2shw" +path="res://.godot/imported/Close.svg-326dec14804498c2ab2273a4a572c2e2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icons/Close.svg" +dest_files=["res://.godot/imported/Close.svg-326dec14804498c2ab2273a4a572c2e2.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=true +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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/event_audio/icons/Play.svg b/addons/event_audio/icons/Play.svg new file mode 100644 index 0000000..385d501 --- /dev/null +++ b/addons/event_audio/icons/Play.svg @@ -0,0 +1 @@ + diff --git a/addons/event_audio/icons/Play.svg.import b/addons/event_audio/icons/Play.svg.import new file mode 100644 index 0000000..f25fc07 --- /dev/null +++ b/addons/event_audio/icons/Play.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://byclw0utbwbam" +path="res://.godot/imported/Play.svg-33c5bae738cb342d56c12b8caaf4909d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icons/Play.svg" +dest_files=["res://.godot/imported/Play.svg-33c5bae738cb342d56c12b8caaf4909d.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=true +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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/event_audio/icons/RandomNumberGenerator.svg b/addons/event_audio/icons/RandomNumberGenerator.svg new file mode 100644 index 0000000..2071c44 --- /dev/null +++ b/addons/event_audio/icons/RandomNumberGenerator.svg @@ -0,0 +1 @@ + diff --git a/addons/event_audio/icons/RandomNumberGenerator.svg.import b/addons/event_audio/icons/RandomNumberGenerator.svg.import new file mode 100644 index 0000000..67456e0 --- /dev/null +++ b/addons/event_audio/icons/RandomNumberGenerator.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dcbbwdp16tdns" +path="res://.godot/imported/RandomNumberGenerator.svg-307a8ce8bcb247fd591f4766aea337ae.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icons/RandomNumberGenerator.svg" +dest_files=["res://.godot/imported/RandomNumberGenerator.svg-307a8ce8bcb247fd591f4766aea337ae.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=true +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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/event_audio/icons/Remove.svg b/addons/event_audio/icons/Remove.svg new file mode 100644 index 0000000..eb8e244 --- /dev/null +++ b/addons/event_audio/icons/Remove.svg @@ -0,0 +1 @@ + diff --git a/addons/event_audio/icons/Remove.svg.import b/addons/event_audio/icons/Remove.svg.import new file mode 100644 index 0000000..2a72493 --- /dev/null +++ b/addons/event_audio/icons/Remove.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://djgktanb5swk6" +path="res://.godot/imported/Remove.svg-dad4f6b2d936a8b9536e5322302cb088.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icons/Remove.svg" +dest_files=["res://.godot/imported/Remove.svg-dad4f6b2d936a8b9536e5322302cb088.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=true +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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/event_audio/icons/Tools.svg b/addons/event_audio/icons/Tools.svg new file mode 100644 index 0000000..1591a56 --- /dev/null +++ b/addons/event_audio/icons/Tools.svg @@ -0,0 +1 @@ + diff --git a/addons/event_audio/icons/Tools.svg.import b/addons/event_audio/icons/Tools.svg.import new file mode 100644 index 0000000..d9b22d1 --- /dev/null +++ b/addons/event_audio/icons/Tools.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://i4qa40akvjaa" +path="res://.godot/imported/Tools.svg-4c4437be5a640503622d98eb51e3bd18.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/event_audio/icons/Tools.svg" +dest_files=["res://.godot/imported/Tools.svg-4c4437be5a640503622d98eb51e3bd18.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=true +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=2.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/event_audio/plugin.cfg b/addons/event_audio/plugin.cfg new file mode 100644 index 0000000..6805417 --- /dev/null +++ b/addons/event_audio/plugin.cfg @@ -0,0 +1,6 @@ +[plugin] +name="EventAudio" +description="" +author="Simon Carter" +version="1.0.1" +script="plugin.gd" diff --git a/addons/event_audio/plugin.gd b/addons/event_audio/plugin.gd new file mode 100644 index 0000000..177b962 --- /dev/null +++ b/addons/event_audio/plugin.gd @@ -0,0 +1,33 @@ +@tool +extends EditorPlugin + +var _editor_plugin = preload("res://addons/event_audio/src/ea_event_bank_inspector.gd").new() +var _runtime_scene = "res://addons/event_audio/scenes/event_audio_autoload.tscn" + +func _enter_tree(): + + var mono_supported = ClassDB.class_exists("CSharpScript") + + if mono_supported: + print ("Mono supported") + else: + print ("Mono unsupported") + + add_inspector_plugin(_editor_plugin) + + if not ProjectSettings.has_setting("autoload/EventAudio"): + add_autoload_singleton("EventAudio", _runtime_scene) + + if mono_supported: + if not ProjectSettings.has_setting("autoload/EventAudioCSharp"): + var _cs_script = "res://addons/event_audio/EventAudio.cs" + add_autoload_singleton("EventAudioCSharp", _cs_script) + +func _exit_tree(): + if _editor_plugin != null: + remove_inspector_plugin(_editor_plugin) + if ProjectSettings.has_setting("autoload/EventAudio"): + remove_autoload_singleton("EventAudio") + + if ProjectSettings.has_setting("autoload/EventAudioCSharp"): + remove_autoload_singleton("EventAudioCSharp") diff --git a/addons/event_audio/scenes/bank_line.tscn b/addons/event_audio/scenes/bank_line.tscn new file mode 100644 index 0000000..eb8a5fd --- /dev/null +++ b/addons/event_audio/scenes/bank_line.tscn @@ -0,0 +1,68 @@ +[gd_scene load_steps=6 format=3 uid="uid://co2eglljfwoxo"] + +[ext_resource type="Texture2D" uid="uid://pad8hlsq2shw" path="res://addons/event_audio/icons/Close.svg" id="1_2kmlt"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_edit_control.gd" id="1_melcq"] +[ext_resource type="Texture2D" uid="uid://i4qa40akvjaa" path="res://addons/event_audio/icons/Tools.svg" id="2_31ihp"] +[ext_resource type="Texture2D" uid="uid://dcbbwdp16tdns" path="res://addons/event_audio/icons/RandomNumberGenerator.svg" id="3_ikqib"] +[ext_resource type="PackedScene" uid="uid://b84km51g3vs0n" path="res://addons/event_audio/scenes/bank_resource_line.tscn" id="5_nou6o"] + +[node name="TriggerLine" type="HBoxContainer" node_paths=PackedStringArray("delete_trigger_button", "play_random_button", "trigger_name_edit", "settings_button", "stream_settings_list")] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -38.0 +offset_bottom = -655.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +script = ExtResource("1_melcq") +delete_trigger_button = NodePath("HBoxContainer/DeleteButton") +play_random_button = NodePath("HBoxContainer/RandomButton") +trigger_name_edit = NodePath("HBoxContainer/TriggerEdit") +settings_button = NodePath("HBoxContainer/SettingsButton") +stream_settings_list = NodePath("BoxContainer/ResourceList") + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 + +[node name="DeleteButton" type="Button" parent="HBoxContainer"] +layout_mode = 2 +tooltip_text = "Delete this event." +icon = ExtResource("1_2kmlt") + +[node name="TriggerEdit" type="LineEdit" parent="HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +tooltip_text = "The string that will trigger this audio event. +Trigger strings are chopped right-to-left at the seperator character until a match is found." +placeholder_text = "trigger string" + +[node name="SettingsButton" type="Button" parent="HBoxContainer"] +custom_minimum_size = Vector2(16, 16) +layout_mode = 2 +tooltip_text = "Playback settings." +icon = ExtResource("2_31ihp") +icon_alignment = 1 + +[node name="RandomButton" type="Button" parent="HBoxContainer"] +layout_mode = 2 +tooltip_text = "Trigger this audio. Plays back a random audio variant, taking into account the variant weights." +icon = ExtResource("3_ikqib") + +[node name="BoxContainer" type="BoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ResourceList" type="VBoxContainer" parent="BoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ResourceLine" parent="BoxContainer/ResourceList" instance=ExtResource("5_nou6o")] +visible = false +layout_mode = 2 + +[node name="ResourceLine2" parent="BoxContainer/ResourceList" instance=ExtResource("5_nou6o")] +visible = false +layout_mode = 2 diff --git a/addons/event_audio/scenes/bank_resource_line.tscn b/addons/event_audio/scenes/bank_resource_line.tscn new file mode 100644 index 0000000..25e33dd --- /dev/null +++ b/addons/event_audio/scenes/bank_resource_line.tscn @@ -0,0 +1,76 @@ +[gd_scene load_steps=5 format=3 uid="uid://b84km51g3vs0n"] + +[ext_resource type="Script" path="res://addons/event_audio/src/ea_stream_edit_control.gd" id="1_fwtai"] +[ext_resource type="Texture2D" uid="uid://byclw0utbwbam" path="res://addons/event_audio/icons/Play.svg" id="2_jis6r"] +[ext_resource type="Texture2D" uid="uid://dqg7mfau2g7ck" path="res://addons/event_audio/icons/Add.svg" id="3_aknch"] +[ext_resource type="Texture2D" uid="uid://djgktanb5swk6" path="res://addons/event_audio/icons/Remove.svg" id="4_il77p"] + +[node name="ResourceLine" type="HBoxContainer" node_paths=PackedStringArray("delete_event_button", "add_stream_button", "play_button", "audio_label")] +offset_right = 328.0 +offset_bottom = 40.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_fwtai") +delete_event_button = NodePath("DeleteButton") +add_stream_button = NodePath("AddButton") +play_button = NodePath("PlayButton") +audio_label = NodePath("ResourcePicker/ResourceLabel") + +[node name="PlayButton" type="Button" parent="."] +layout_mode = 2 +tooltip_text = "Play this audio variant." +icon = ExtResource("2_jis6r") + +[node name="WeightSliderContainer" type="FlowContainer" parent="."] +custom_minimum_size = Vector2(64, 0) +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.5 +tooltip_text = "The weighted probabily this variant will play. +Only used when there is more than one variant." +alignment = 1 + +[node name="ResourcePicker" type="Control" parent="."] +clip_contents = true +custom_minimum_size = Vector2(128, 0) +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ResourcePickerContainer" type="BoxContainer" parent="ResourcePicker"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +alignment = 1 +vertical = true + +[node name="ResourceLabel" type="Label" parent="ResourcePicker"] +visible = false +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.234 +anchor_right = 0.703 +anchor_bottom = 1.0 +offset_left = 0.0479984 +offset_right = 0.0159988 +grow_horizontal = 2 +grow_vertical = 2 +horizontal_alignment = 1 +vertical_alignment = 1 +clip_text = true +text_overrun_behavior = 1 + +[node name="AddButton" type="Button" parent="."] +layout_mode = 2 +size_flags_vertical = 3 +tooltip_text = "Add an audio variant to the trigger." +icon = ExtResource("3_aknch") + +[node name="DeleteButton" type="Button" parent="."] +layout_mode = 2 +size_flags_vertical = 3 +tooltip_text = "Delete this variant." +icon = ExtResource("4_il77p") diff --git a/addons/event_audio/scenes/event_audio_autoload.tscn b/addons/event_audio/scenes/event_audio_autoload.tscn new file mode 100644 index 0000000..ca0d93f --- /dev/null +++ b/addons/event_audio/scenes/event_audio_autoload.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://be741v81fj3xc"] + +[ext_resource type="Script" path="res://addons/event_audio/event_audio.gd" id="1_75kvd"] + +[node name="EventAudio" type="Node"] +script = ExtResource("1_75kvd") + +[node name="EventAudioAutoload" type="Node" parent="."] diff --git a/addons/event_audio/src/ea_editor_tools.gd b/addons/event_audio/src/ea_editor_tools.gd new file mode 100644 index 0000000..23346a5 --- /dev/null +++ b/addons/event_audio/src/ea_editor_tools.gd @@ -0,0 +1,201 @@ +class_name EAEditorTools +static var _editor_stream_player : AudioStreamPlayer +static var _global_rng : RandomNumberGenerator + +static func get_global_rng() -> RandomNumberGenerator: + if _global_rng == null: + _global_rng = RandomNumberGenerator.new() + return _global_rng + +static func play_sound(entry: EAEvent, stream: AudioStream): + var main_screen = EditorInterface.get_editor_main_screen() + var audio = _editor_stream_player + if audio == null: + audio = AudioStreamPlayer.new() + audio.name = "_EditorAudio" + main_screen.add_child(audio) + _editor_stream_player = audio + + EventAudioAPI.init_player_from_playback_settings(get_global_rng(), audio, entry.playback_settings) + + audio.stop() + audio.stream = stream + audio.play() + +static func stop_sound(): + var audio := _editor_stream_player + if audio != null: + print("Stopping audio") + audio.stop() + audio.stream = null + +static func make_property_panel(obj: Object, title: String, excludes : Dictionary, change_callback : Callable) -> Container: + var panel := PanelContainer.new() + panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL + panel.modulate = Color(0.8, 0.8, 1) + + var property_container := VBoxContainer.new() + property_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL + panel.add_child(property_container) + + if title != "": + var title_label := Label.new() + title_label.text = title + title_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + property_container.add_child(title_label) + + for prop in obj.get_property_list(): + if not prop.name in excludes: + var val = obj.get(prop.name) + var property_control := _make_property_control(prop, val, change_callback.bind(obj, prop.name)) + if property_control != null: + property_container.add_child(property_control) + + return panel + +static func _make_property_control(prop, initial_value, update_callback: Callable) -> Control: + # print(prop) + var control : Control + + if prop.usage & PROPERTY_USAGE_STORAGE: + control = HBoxContainer.new() + control.size_flags_horizontal = Control.SIZE_EXPAND_FILL + var text_label = Label.new() + text_label.text = _property_name_to_display_name(prop.name) + + text_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL + control.add_child(text_label) + + var prop_type: Variant.Type = prop["type"] + var prop_range : Dictionary = _parse_range(prop) + + match prop_type: + TYPE_BOOL: + var prop_editor = CheckBox.new() + prop_editor.size_flags_horizontal = Control.SIZE_EXPAND_FILL + if initial_value != null: + prop_editor.button_pressed = initial_value + + prop_editor.toggled.connect(update_callback) + control.add_child(prop_editor) + + TYPE_INT, TYPE_FLOAT: + var prop_editor := EditorSpinSlider.new() + var default_step = null + if prop_range.has("step"): + default_step = prop_range["step"] + + # For floats, show a normal input box if the step has been set to 1. + # For ints, show a normal input box if the step has been set to 1, or left out. + # Otherwise show a slider + if prop_type == TYPE_FLOAT: + if default_step == null: + prop_editor.hide_slider = false + prop_editor.step = 0.0001 + elif default_step == 1: + prop_editor.step = 1 + else: + prop_editor.step = default_step + prop_editor.hide_slider = false + else: + if default_step == null or default_step == 1: + prop_editor.step = 1 + else: + prop_editor.step = default_step + prop_editor.hide_slider = false + + + prop_editor.allow_lesser = prop_range.has("or_lesser") + prop_editor.allow_greater = prop_range.has("or_greater") + + if prop_range.has("min"): + prop_editor.min_value = prop_range["min"] + + if prop_range.has("max"): + prop_editor.max_value = prop_range["max"] + + prop_editor.size_flags_horizontal = Control.SIZE_EXPAND_FILL + if initial_value != null: + prop_editor.value = initial_value + + prop_editor.value_changed.connect(update_callback) + control.add_child(prop_editor) + + TYPE_STRING, TYPE_STRING_NAME, TYPE_NODE_PATH: + var prop_editor = LineEdit.new() + prop_editor.size_flags_horizontal = Control.SIZE_EXPAND_FILL + if initial_value != null: + prop_editor.text = initial_value + + prop_editor.text_changed.connect(update_callback) + control.add_child(prop_editor) + + _: + pass + elif prop.usage & PROPERTY_USAGE_GROUP: + var group_label := Label.new() + group_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + group_label.text = prop.name + control = group_label + + return control + +static func _parse_range(prop) -> Dictionary: + if prop["hint"] != PROPERTY_HINT_RANGE: + return {} + + var prop_range := {} + var parts := prop["hint_string"].split(",") as PackedStringArray + var is_float : bool = prop["type"] == TYPE_FLOAT + + if parts.size() > 0: + if is_float: + prop_range["min"] = parts[0].to_float() + else: + prop_range["min"] = parts[0].to_int() + + if parts.size() > 1: + if is_float: + prop_range["max"] = parts[1].to_float() + else: + prop_range["max"] = parts[1].to_int() + + if parts.size() > 2: + if is_float: + prop_range["step"] = parts[2].to_float() + else: + prop_range["step"] = parts[2].to_int() + + if parts.size() > 3: + match parts[3]: + "or_lesser": + prop_range["or_lesser"] = true + "or_greater": + prop_range["or_greater"] = true + + if parts.size() > 4: + match parts[4]: + "or_lesser": + prop_range["or_lesser"] = true + "or_greater": + prop_range["or_greater"] = true + _: + pass + + return prop_range + + +static func _property_name_to_display_name(name: String): + var name_snake := name.to_snake_case() + var parts := name_snake.split("_") + var display_name := "" + + for c1 : int in parts.size(): + var part := parts[c1] + display_name += part.to_pascal_case() + if c1 < parts.size() - 1: + display_name += " " + + return display_name + + diff --git a/addons/event_audio/src/ea_event.gd b/addons/event_audio/src/ea_event.gd new file mode 100644 index 0000000..08a0c61 --- /dev/null +++ b/addons/event_audio/src/ea_event.gd @@ -0,0 +1,40 @@ +@tool +extends Resource +class_name EAEvent + +@export var audio_streams : Array[AudioStream] = [] +@export var probability_weights : Array[float] = [] +@export var trigger_tags: String = "" +@export var playback_settings: EAEventPlaybackSettings + +func _init(): + if audio_streams.size() == 0: + audio_streams.push_front(null) + probability_weights.push_front(1.0) + playback_settings = EAEventPlaybackSettings.new() + +func add_stream(index: int): + audio_streams.insert(index+1, null) + probability_weights.insert(index+1, 1.0) + +func remove_stream(index: int): + audio_streams.remove_at(index) + probability_weights.remove_at(index) + +func get_weighted_random_stream(random: float) -> AudioStream: + var total_weight := 0.0 + for w : float in probability_weights: + total_weight = total_weight + w + + var r := random * total_weight + var num_entries := probability_weights.size() + var weight_count := 0.0 + for i in num_entries: + if i + 1 == num_entries: + return audio_streams[i] + elif r <= weight_count + probability_weights[i]: + return audio_streams[i] + weight_count += probability_weights[i] + return null + + diff --git a/addons/event_audio/src/ea_event_bank.gd b/addons/event_audio/src/ea_event_bank.gd new file mode 100644 index 0000000..382a73e --- /dev/null +++ b/addons/event_audio/src/ea_event_bank.gd @@ -0,0 +1,27 @@ +@tool +extends Resource +class_name EAEventBank + +@export var entries: Array[EAEvent] + +func add_entry(): + entries.insert(0, EAEvent.new()) + +func delete_entry(entry: EAEvent): + var entry_idx := entries.find(entry) + if entry_idx >= 0: + entries.remove_at(entry_idx) + +func find_entry_with_trigger(trigger: String) -> EAEvent: + for entry: EAEvent in entries: + if entry.trigger_tags == trigger: + return entry + + return null + +func _sort_func(a: EAEvent, b: EAEvent) -> bool: + return a.trigger_tags < b.trigger_tags + +func sort_by_trigger(): + entries.sort_custom(_sort_func) + diff --git a/addons/event_audio/src/ea_event_bank_inspector.gd b/addons/event_audio/src/ea_event_bank_inspector.gd new file mode 100644 index 0000000..bfabe25 --- /dev/null +++ b/addons/event_audio/src/ea_event_bank_inspector.gd @@ -0,0 +1,11 @@ +@tool +extends EditorInspectorPlugin + +func _can_handle(object): + return object is EAEventBank + +func _parse_property(_object, _type, name, _hint_type, _hint_string, _usage_flags, _wide): + if name == "entries": + add_property_editor(name, EAEventBankProperty.new()) + return true + return false diff --git a/addons/event_audio/src/ea_event_bank_mounter.gd b/addons/event_audio/src/ea_event_bank_mounter.gd new file mode 100644 index 0000000..1482a47 --- /dev/null +++ b/addons/event_audio/src/ea_event_bank_mounter.gd @@ -0,0 +1,13 @@ +extends Node +class_name EAEventBankMounter +@export var _audio_bank_resource : EAEventBank +# @export var audioBankResources: Array[EAEventBank] + +func _enter_tree(): + var player := EventAudio.instance + player.register_event_bank(_audio_bank_resource) + +func _exit_tree(): + var player := EventAudio.instance + player.unregister_event_bank(_audio_bank_resource) + diff --git a/addons/event_audio/src/ea_event_bank_property.gd b/addons/event_audio/src/ea_event_bank_property.gd new file mode 100644 index 0000000..1c4388a --- /dev/null +++ b/addons/event_audio/src/ea_event_bank_property.gd @@ -0,0 +1,109 @@ +@tool +extends EditorProperty + +class_name EAEventBankProperty + +var _audio_bank_line_scene := preload("res://addons/event_audio/scenes/bank_line.tscn") +var _audio_bank_resource_line_scene := preload("res://addons/event_audio/scenes/bank_resource_line.tscn") + +var _resource: EAEventBank +var _property_name: StringName +var _entries: Array[EAEvent] +var _root_container := VBoxContainer.new() +var _focus_on_trigger : String = "" + +#---------------------------------------------- +# Godot call to update rendering +func _update_property(): + # print("updating property") + var open_settings := {} + + for control : Node in _root_container.get_children(): + if control is EAEventEditControl and control.is_settings_open(): + open_settings[control.get_event()] = true + + _root_container.remove_child(control) + control.queue_free() + + _make_lines(open_settings) + + # Search for the trigger we were looking at previously. + if _focus_on_trigger == "": + return + + await get_tree().process_frame + + # Find the trigger we were editing previously and select it. + for control : Control in _root_container.get_children(): + if control is not EAEventEditControl: + continue + var line = control as EAEventEditControl + if line.trigger_name_edit.text == _focus_on_trigger: + EditorInterface.get_inspector().ensure_control_visible(line.trigger_name_edit) + break + + _focus_on_trigger = "" + +func _enter_tree(): + _property_name = get_edited_property() + _resource = get_edited_object() as EAEventBank + _entries = _resource.entries + + _root_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL + + _make_lines() + add_child(_root_container) + set_bottom_editor(_root_container) + +func _exit_tree() -> void: + EAEditorTools.stop_sound() + +func sort_bank(): + _resource.sort_by_trigger() + +func signal_entry_changed(update_ui: bool): + emit_changed(_property_name, _entries, "", not update_ui) + +func set_focus_on_trigger(trigger: String): + _focus_on_trigger = trigger + +func delete_event(event: EAEvent): + _resource.delete_entry(event) + signal_entry_changed(true) + +#-------------------------------------- +func _make_lines(setting_to_restore = {}): + var add_button := Button.new() + add_button.text = "Add Entry" + add_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + add_button.pressed.connect(_on_add_entry_button_clicked) + _root_container.add_child(add_button) + + var stop_button := Button.new() + stop_button.text = "Stop playback" + stop_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + stop_button.pressed.connect(_on_stop_button_clicked) + _root_container.add_child(stop_button) + + for entry : EAEvent in _resource.entries: + var settings_open := setting_to_restore.has(entry) + _makeEntryLine(entry, settings_open) + +func _makeEntryLine(entry: EAEvent, settings_open: bool): + var line := _audio_bank_line_scene.instantiate() as EAEventEditControl + _root_container.add_child(line) + line.create(self, entry, settings_open) + + for c1: int in entry.audio_streams.size(): + var resource_line := _audio_bank_resource_line_scene.instantiate() as EAStreamEditControl + line.stream_settings_list.add_child(resource_line) + resource_line.create(self, entry, c1, entry.audio_streams.size() == 1) + +func _on_add_entry_button_clicked(): + _resource.add_entry() + signal_entry_changed(true) + +func _on_stop_button_clicked(): + EAEditorTools.stop_sound() + + diff --git a/addons/event_audio/src/ea_event_edit_control.gd b/addons/event_audio/src/ea_event_edit_control.gd new file mode 100644 index 0000000..c90018e --- /dev/null +++ b/addons/event_audio/src/ea_event_edit_control.gd @@ -0,0 +1,91 @@ +@tool +extends Container +class_name EAEventEditControl + +@export var delete_trigger_button : BaseButton +@export var play_random_button : BaseButton +@export var trigger_name_edit : LineEdit +@export var settings_button : BaseButton +@export var stream_settings_list : Container +var _exclude_props = {"resource_local_to_scene": true, "Resource": true, "resource_name": true, "script": true} +var _settings_panel : Control +var _event : EAEvent +var _bank_inspector : EAEventBankProperty + +func create(bank_inspector: EAEventBankProperty, event: EAEvent, open_settings: bool) -> void: + _event = event + _bank_inspector = bank_inspector + + delete_trigger_button.pressed.connect(_on_delete_entry_button_clicked) + trigger_name_edit.set_text(_event.trigger_tags) + trigger_name_edit.text_submitted.connect(_on_trigger_submitted) + trigger_name_edit.text_changed.connect(_on_trigger_changed) + settings_button.pressed.connect(_on_settings_button_clicked) + play_random_button.pressed.connect(_on_play_random_button_clicked) + + if open_settings: + var panel := _make_settings_panel() + self.add_sibling(panel) + _settings_panel = panel + +func is_settings_open(): + return _settings_panel != null + +func get_event(): + return _event + +func _on_settings_button_clicked(): + _toggle_settings_panel() + +func _on_settings_entry_changed(val, settings: EAEventPlaybackSettings, member: StringName): + settings.set(member, val) + _bank_inspector.signal_entry_changed(false) + +func _on_delete_entry_button_clicked(): + _bank_inspector.delete_event(_event) + +func _check_trigger_name(entry: EAEvent, trigger: String) -> bool: + var bank_entry := _bank_inspector._resource.find_entry_with_trigger(trigger) + + if bank_entry and bank_entry != entry: + return false + + return true + +func _on_trigger_changed(trigger: String): + # If the trigger isn't valid, show an error color + if _check_trigger_name(_event, trigger): + trigger_name_edit.modulate = Color.WHITE + else: + trigger_name_edit.modulate = Color.RED + +func _on_trigger_submitted(trigger: String): + if _check_trigger_name(_event, trigger): + _event.trigger_tags = trigger + trigger_name_edit.release_focus() + + # Re-sort the bank - this may trigger a UI update, so make sure we focus on the right control + _bank_inspector.set_focus_on_trigger(trigger) + _bank_inspector.sort_bank() + _bank_inspector.signal_entry_changed(true) + +func _on_play_random_button_clicked(): + var roll := EAEditorTools.get_global_rng().randf_range(0, 1.0) + var stream := _event.get_weighted_random_stream(roll) + if stream: + EAEditorTools.play_sound(_event, stream) + +func _toggle_settings_panel(): + if _settings_panel: + _settings_panel.get_parent().remove_child(_settings_panel) + _settings_panel.queue_free() + _settings_panel = null + else: + var panel := _make_settings_panel() + _settings_panel = panel + self.add_sibling(panel) + +func _make_settings_panel() -> Container: + return EAEditorTools.make_property_panel( + _event.playback_settings, "Playback Settings", _exclude_props, _on_settings_entry_changed) + diff --git a/addons/event_audio/src/ea_event_playback_settings.gd b/addons/event_audio/src/ea_event_playback_settings.gd new file mode 100644 index 0000000..d882b11 --- /dev/null +++ b/addons/event_audio/src/ea_event_playback_settings.gd @@ -0,0 +1,22 @@ +extends Resource + +class_name EAEventPlaybackSettings + +## The factor for the attenuation effect. Higher values make the sound audible over a larger distance. +@export_group("Behaviour") +@export var stop_when_source_dies := false +@export var stationary := false + +@export_group("Shared Playback") +@export_range(-10.0, 10.0, 0.1) var volume_db := 0.0 +@export_range(0.1, 2.0, 0.1) var min_pitch := 1.0 +@export_range(0.1, 2.0, 0.1) var max_pitch := 1.0 +@export_range(0.0, 3.0, 0.1) var panning_strength := 1.0 + +@export_group("2D Playback") +@export_range(0.0, 3.0, 0.1) var attenuation := 1.0 +@export_range(0, 9999999) var max_distance := 2000 + +@export_group("3D Playback") +@export_range(0, 1000) var unit_size := 10.0 +@export_range(-10.0, 10.0, 0.1) var max_db := 3.0 diff --git a/addons/event_audio/src/ea_stream_edit_control.gd b/addons/event_audio/src/ea_stream_edit_control.gd new file mode 100644 index 0000000..80bd7e7 --- /dev/null +++ b/addons/event_audio/src/ea_stream_edit_control.gd @@ -0,0 +1,131 @@ +@tool +extends Container +class_name EAStreamEditControl + +@export var delete_event_button : Button +@export var add_stream_button : Button +@export var play_button : Button +@export var audio_label : Label +var weight_editor : EditorSpinSlider +var audio_selector : EditorResourcePicker + +var _stream_id : int +var _event : EAEvent +var _bank_inspector : EAEventBankProperty + +func create(bank_inspector: EAEventBankProperty, event: EAEvent, stream_id: int, primary: bool) -> void: + # When this is the primary resource, we don't want to delete it. + # add_stream_button.visible = true + _stream_id = stream_id + _event = event + _bank_inspector = bank_inspector + + if primary: + delete_event_button.disabled = true + else: + delete_event_button.disabled = false + + play_button.pressed.connect(_on_play_button_clicked) + + audio_selector.resource_changed.connect(_on_stream_changed) + audio_selector.edited_resource = _event.audio_streams[_stream_id] + + add_stream_button.pressed.connect(_on_add_resource_button_clicked) + delete_event_button.pressed.connect(_on_delete_resource_button_clicked) + + weight_editor.value_changed.connect(_on_stream_weight_changed) + weight_editor.value = _event.probability_weights[_stream_id] + _make_audio_picker_pretty() + +func _ready() -> void: + get_node("WeightSliderContainer").add_child(weight_editor) + get_node("ResourcePicker/ResourcePickerContainer").add_child(audio_selector) + # if _event: + # audio_selector.edited_resource = _event.audio_streams[_stream_id] + + _make_audio_picker_pretty() + +func _init() -> void: + weight_editor = EditorSpinSlider.new() + weight_editor.label = "weight" + weight_editor.step = 0.05 + weight_editor.hide_slider = false + weight_editor.allow_lesser = false + weight_editor.allow_greater = false + weight_editor.min_value = 0 + weight_editor.max_value = 1.0 + weight_editor.size_flags_horizontal = Control.SIZE_EXPAND_FILL + + audio_selector = EditorResourcePicker.new() + audio_selector.size_flags_horizontal = Control.SIZE_EXPAND_FILL + audio_selector.base_type = "AudioStream" + # audio_selector.edited_resource = _event.audio_streams[_stream_id] + + audio_selector.resource_changed.connect(_on_resource_changed) + audio_selector.resource_selected.connect(_on_resource_clicked) + + +func _on_resource_clicked(res: Resource, _inspect: bool): + # When the resource picker is clicked, visit the resource. + # Do it the next frame, however, in case the controls are being updated. + if res != null: + await get_tree().process_frame + EditorInterface.edit_resource(res) + +func _on_resource_changed(_res: Resource): + # When the resource is changed, update the prettification of the resource picker. + _make_audio_picker_pretty() + +# The default resource picker has several drawbacks when used in a custom inspector. +# - It draws double-height, to show an audio preview; even when there is no preview. +# - When audio is assigned it stops showing the path name. +# This function 'fixes' that, somewhat hackily. +func _make_audio_picker_pretty(): + # In certain circumstances, show a custom label with the resources file path. + # Otherwise, hide it and rely on the default control. + var res := audio_selector.edited_resource + + if res == null: + # If no resource, show the default button text + audio_label.visible = false + else: + # Otherwise, try to show the file name + if FileAccess.file_exists(res.resource_path): + audio_label.text = res.resource_path.get_file() + audio_label.visible = true + else: + audio_label.text = res.get_class() + # TODO - can't tell when the button is rendering at the moment, so this shows on top, sometimes. + # Until we can, make the label invisible + audio_label.visible = false + + # This is the only way we found to get the ResourcePicker smaller. + # It's not ideal, as it depends on the internals of the resource picker. + # Search for the texture rect that shows the preview and detach it. + var children := audio_selector.get_children() + while not children.is_empty(): + var child := children.pop_back() as Node + children.append_array(child.get_children()) + if child is TextureRect: + child.get_parent().remove_child(child) + +func _on_play_button_clicked(): + var stream := _event.audio_streams[_stream_id] + if stream: + EAEditorTools.play_sound(_event, stream) + +func _on_stream_weight_changed(val): + _event.probability_weights[_stream_id] = val + _bank_inspector.signal_entry_changed(false) + +func _on_add_resource_button_clicked(): + _event.add_stream(_stream_id) + _bank_inspector.signal_entry_changed(true) + +func _on_delete_resource_button_clicked(): + _event.remove_stream(_stream_id) + _bank_inspector.signal_entry_changed(true) + +func _on_stream_changed(res: Resource): + _event.audio_streams[_stream_id] = res as AudioStream + _bank_inspector.signal_entry_changed(false) diff --git a/main.gd b/main.gd index cfdb5e8..9f07500 100644 --- a/main.gd +++ b/main.gd @@ -7,6 +7,7 @@ extends Control @onready var trueview: int = 0 # variables for nodes +@onready var sound: Node2D = $Sounds @onready var roll_dice: TextureButton = $Roll/Roll_dice @onready var psyline_other: Control = $Psy_line_other @onready var psyline_self: Control = $Psy_line_self @@ -15,10 +16,11 @@ extends Control @onready var keep_psy: CheckBox = $Roll/Keep_psy @onready var keep_traits: CheckBox = $Roll/Keep_traits @onready var language_choice: MenuButton = $Language +@onready var soundplayer: EAEventBankMounter = $SoundPlayer # Called when the node enters the scene tree for the first time. func _ready() -> void: - lets_roll(seed) + lets_roll(seed, 0) roll_dice.pressed.connect(_on_roll_dice_pressed) language_choice.get_popup().connect("id_pressed", _on_menu_language_selected) @@ -35,13 +37,17 @@ func _process(delta: float) -> void: func _on_roll_dice_pressed() -> void: lets_roll(seed) -func lets_roll(chosen_seed: int) -> void: +func lets_roll(chosen_seed: int, noise: bool = 1) -> void: # Random psy profiles var possible_psy: int = $Psy_line_other.resources.size() var random = RandomNumberGenerator.new() random.seed = chosen_seed + # Play sound if wanted + if noise: + EventAudio.play_2d("DICEROLL", sound) + # Randomize psychology if not keep_psy.button_pressed: random.randomize() diff --git a/main.tscn b/main.tscn index 9f71c7a..b67b4ac 100644 --- a/main.tscn +++ b/main.tscn @@ -1,10 +1,12 @@ -[gd_scene load_steps=6 format=3 uid="uid://d14wihi8i46og"] +[gd_scene load_steps=8 format=3 uid="uid://d14wihi8i46og"] [ext_resource type="PackedScene" uid="uid://bff864odl7vlj" path="res://psyline.tscn" id="1_03r8p"] [ext_resource type="Script" path="res://main.gd" id="1_gqole"] [ext_resource type="Theme" uid="uid://qsom67gcgupx" path="res://themes/base.tres" id="2_vc4v2"] [ext_resource type="PackedScene" uid="uid://cl5wswke7jxpi" path="res://traits.tscn" id="3_t3gol"] [ext_resource type="Texture2D" uid="uid://b7fg7g42642p" path="res://textures/dices.png" id="5_rsth0"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_bank_mounter.gd" id="6_im5e0"] +[ext_resource type="Resource" uid="uid://c51i5hutfhrsx" path="res://sounds/eventbanks/UI_sounds.tres" id="7_6knbw"] [node name="Main" type="Control"] layout_mode = 3 @@ -239,3 +241,9 @@ item_count = 2 popup/item_0/text = "FRENCH" popup/item_1/text = "ENGLISH" popup/item_1/id = 1 + +[node name="SoundPlayer" type="Node" parent="."] +script = ExtResource("6_im5e0") +_audio_bank_resource = ExtResource("7_6knbw") + +[node name="Sounds" type="Node2D" parent="."] diff --git a/project.godot b/project.godot index 42a7cd8..e79dd72 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,14 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.3", "Forward Plus") config/icon="res://textures/icon.png" +[autoload] + +EventAudio="*res://addons/event_audio/scenes/event_audio_autoload.tscn" + +[editor_plugins] + +enabled=PackedStringArray("res://addons/event_audio/plugin.cfg") + [input] ui_accept={ diff --git a/sounds/dieShuffle1.ogg b/sounds/assets/dieShuffle1.ogg similarity index 100% rename from sounds/dieShuffle1.ogg rename to sounds/assets/dieShuffle1.ogg diff --git a/sounds/assets/dieShuffle1.ogg.import b/sounds/assets/dieShuffle1.ogg.import new file mode 100644 index 0000000..c77412e --- /dev/null +++ b/sounds/assets/dieShuffle1.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bbsb62p7ci00d" +path="res://.godot/imported/dieShuffle1.ogg-dcb2d2e1f13163ad0879571ecc9e036c.oggvorbisstr" + +[deps] + +source_file="res://sounds/assets/dieShuffle1.ogg" +dest_files=["res://.godot/imported/dieShuffle1.ogg-dcb2d2e1f13163ad0879571ecc9e036c.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/sounds/dieShuffle1.ogg.import b/sounds/dieShuffle1.ogg.import deleted file mode 100644 index f5bd4ab..0000000 --- a/sounds/dieShuffle1.ogg.import +++ /dev/null @@ -1,19 +0,0 @@ -[remap] - -importer="oggvorbisstr" -type="AudioStreamOggVorbis" -uid="uid://bbsb62p7ci00d" -path="res://.godot/imported/dieShuffle1.ogg-839321e52515a7254293b5f786bc71b8.oggvorbisstr" - -[deps] - -source_file="res://sounds/dieShuffle1.ogg" -dest_files=["res://.godot/imported/dieShuffle1.ogg-839321e52515a7254293b5f786bc71b8.oggvorbisstr"] - -[params] - -loop=false -loop_offset=0 -bpm=0 -beat_count=0 -bar_beats=4 diff --git a/sounds/eventbanks/UI_sounds.tres b/sounds/eventbanks/UI_sounds.tres new file mode 100644 index 0000000..307c4e0 --- /dev/null +++ b/sounds/eventbanks/UI_sounds.tres @@ -0,0 +1,30 @@ +[gd_resource type="Resource" script_class="EAEventBank" load_steps=7 format=3 uid="uid://c51i5hutfhrsx"] + +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event.gd" id="1_kbnqw"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_bank.gd" id="2_jlkrc"] +[ext_resource type="AudioStream" uid="uid://bbsb62p7ci00d" path="res://sounds/assets/dieShuffle1.ogg" id="2_uyd46"] +[ext_resource type="Script" path="res://addons/event_audio/src/ea_event_playback_settings.gd" id="3_dcij5"] + +[sub_resource type="Resource" id="Resource_odclp"] +script = ExtResource("3_dcij5") +stop_when_source_dies = false +stationary = false +volume_db = 0.0 +min_pitch = 1.0 +max_pitch = 1.0 +panning_strength = 1.0 +attenuation = 1.0 +max_distance = 2000 +unit_size = 10.0 +max_db = 3.0 + +[sub_resource type="Resource" id="Resource_5ogac"] +script = ExtResource("1_kbnqw") +audio_streams = Array[AudioStream]([ExtResource("2_uyd46")]) +probability_weights = Array[float]([1.0]) +trigger_tags = "DICEROLL" +playback_settings = SubResource("Resource_odclp") + +[resource] +script = ExtResource("2_jlkrc") +entries = Array[ExtResource("1_kbnqw")]([SubResource("Resource_5ogac")])