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 0000000..c7f18b8 Binary files /dev/null and b/addons/event_audio/example/sounds/laser1.wav differ 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 0000000..975a33f Binary files /dev/null and b/addons/event_audio/example/sounds/laser2.wav differ diff --git a/addons/event_audio/example/sounds/laser2.wav.import b/addons/event_audio/example/sounds/laser2.wav.import new file mode 100644 index 0000000..cea3665 --- /dev/null +++ b/addons/event_audio/example/sounds/laser2.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://ftyi4ikfmbii" +path="res://.godot/imported/laser2.wav-396964f333f7fcbda54278f155b07608.sample" + +[deps] + +source_file="res://addons/event_audio/example/sounds/laser2.wav" +dest_files=["res://.godot/imported/laser2.wav-396964f333f7fcbda54278f155b07608.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/loop.wav b/addons/event_audio/example/sounds/loop.wav new file mode 100644 index 0000000..22d7e8b Binary files /dev/null and b/addons/event_audio/example/sounds/loop.wav differ diff --git a/addons/event_audio/example/sounds/loop.wav.import b/addons/event_audio/example/sounds/loop.wav.import new file mode 100644 index 0000000..6fcea47 --- /dev/null +++ b/addons/event_audio/example/sounds/loop.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://7ncmg0ox4nxr" +path="res://.godot/imported/loop.wav-fa3b1ef3ac7c882255ced1130766deef.sample" + +[deps] + +source_file="res://addons/event_audio/example/sounds/loop.wav" +dest_files=["res://.godot/imported/loop.wav-fa3b1ef3ac7c882255ced1130766deef.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=2 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/addons/event_audio/example/sounds/shot1.wav b/addons/event_audio/example/sounds/shot1.wav new file mode 100644 index 0000000..5633e13 Binary files /dev/null and b/addons/event_audio/example/sounds/shot1.wav differ 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 0000000..a9e0a6c Binary files /dev/null and b/addons/event_audio/example/sounds/shot2.wav differ diff --git a/addons/event_audio/example/sounds/shot2.wav.import b/addons/event_audio/example/sounds/shot2.wav.import new file mode 100644 index 0000000..9d62c65 --- /dev/null +++ b/addons/event_audio/example/sounds/shot2.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://cultflwybpfo1" +path="res://.godot/imported/shot2.wav-ac04745e5c74f182ec001473606b2120.sample" + +[deps] + +source_file="res://addons/event_audio/example/sounds/shot2.wav" +dest_files=["res://.godot/imported/shot2.wav-ac04745e5c74f182ec001473606b2120.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/icon.png b/addons/event_audio/icon.png new file mode 100644 index 0000000..667162a Binary files /dev/null and b/addons/event_audio/icon.png differ 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")])