diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index aca7a8c7362..db22a38cecf 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -29,7 +29,9 @@ /*************************************************************************/ #include "area_2d.h" #include "scene/scene_string_names.h" +#include "servers/audio_server.h" #include "servers/physics_2d_server.h" + void Area2D::set_space_override_mode(SpaceOverride p_mode) { space_override = p_mode; @@ -542,6 +544,47 @@ bool Area2D::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } +void Area2D::set_audio_bus_override(bool p_override) { + + audio_bus_override = p_override; +} + +bool Area2D::is_overriding_audio_bus() const { + + return audio_bus_override; +} + +void Area2D::set_audio_bus(const StringName &p_audio_bus) { + + audio_bus = p_audio_bus; +} + +StringName Area2D::get_audio_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) { + return audio_bus; + } + } + return "Master"; +} + +void Area2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "audio_bus_name") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("_body_enter_tree", "id"), &Area2D::_body_enter_tree); @@ -598,6 +641,12 @@ void Area2D::_bind_methods() { ClassDB::bind_method(D_METHOD("overlaps_body", "body"), &Area2D::overlaps_body); ClassDB::bind_method(D_METHOD("overlaps_area", "area"), &Area2D::overlaps_area); + ClassDB::bind_method(D_METHOD("set_audio_bus", "name"), &Area2D::set_audio_bus); + ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area2D::get_audio_bus); + + ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override); + ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus); + ClassDB::bind_method(D_METHOD("_body_inout"), &Area2D::_body_inout); ClassDB::bind_method(D_METHOD("_area_inout"), &Area2D::_area_inout); @@ -624,6 +673,10 @@ void Area2D::_bind_methods() { ADD_GROUP("Collision", "collision_"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); ADD_PROPERTYNO(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_mask", "get_collision_mask"); + + ADD_GROUP("Audio Bus", "audio_bus_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus"); } Area2D::Area2D() @@ -642,6 +695,7 @@ Area2D::Area2D() monitorable = false; collision_mask = 1; collision_layer = 1; + audio_bus_override = false; set_monitoring(true); set_monitorable(true); } diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h index f0eb1e92404..12d71f39114 100644 --- a/scene/2d/area_2d.h +++ b/scene/2d/area_2d.h @@ -126,9 +126,13 @@ private: Map area_map; void _clear_monitoring(); + bool audio_bus_override; + StringName audio_bus; + protected: void _notification(int p_what); static void _bind_methods(); + void _validate_property(PropertyInfo &property) const; public: void set_space_override_mode(SpaceOverride p_mode); @@ -179,6 +183,12 @@ public: bool overlaps_area(Node *p_area) const; bool overlaps_body(Node *p_body) const; + void set_audio_bus_override(bool p_override); + bool is_overriding_audio_bus() const; + + void set_audio_bus(const StringName &p_audio_bus); + StringName get_audio_bus() const; + Area2D(); ~Area2D(); }; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp new file mode 100644 index 00000000000..3d9e64ae79e --- /dev/null +++ b/scene/2d/audio_stream_player_2d.cpp @@ -0,0 +1,463 @@ + +#include "audio_stream_player_2d.h" +#include "scene/2d/area_2d.h" +#include "scene/main/viewport.h" +void AudioStreamPlayer2D::_mix_audio() { + + if (!stream_playback.is_valid()) { + return; + } + + if (!active) { + return; + } + + if (setseek >= 0.0) { + stream_playback->start(setseek); + setseek = -1.0; //reset seek + } + + //get data + AudioFrame *buffer = mix_buffer.ptr(); + int buffer_size = mix_buffer.size(); + + //mix + stream_playback->mix(buffer, 1.0, buffer_size); + + //write all outputs + for (int i = 0; i < output_count; i++) { + + Output current = outputs[i]; + + //see if current output exists, to keep volume ramp + bool found = false; + for (int j = i; j < prev_output_count; j++) { + if (prev_outputs[j].viewport == current.viewport) { + if (j != i) { + SWAP(prev_outputs[j], prev_outputs[i]); + } + found = true; + break; + } + } + + if (!found) { + //create new if was not used before + if (prev_output_count < MAX_OUTPUTS) { + prev_outputs[prev_output_count] = prev_outputs[i]; //may be owned by another viewport + prev_output_count++; + } + prev_outputs[i] = current; + } + + //mix! + AudioFrame vol_inc = (current.vol - prev_outputs[i].vol) / float(buffer_size); + AudioFrame vol = current.vol; + + switch (AudioServer::get_singleton()->get_speaker_mode()) { + + case AudioServer::SPEAKER_MODE_STEREO: { + AudioFrame *target = AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 0); + + for (int j = 0; j < buffer_size; j++) { + + target[j] = buffer[j] * vol; + vol += vol_inc; + } + + } break; + case AudioServer::SPEAKER_SURROUND_51: { + + AudioFrame *targets[2] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 2), + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] = frame; + targets[1][j] = frame; + vol += vol_inc; + } + + } break; + case AudioServer::SPEAKER_SURROUND_71: { + + AudioFrame *targets[3] = { + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 1), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 2), + AudioServer::get_singleton()->thread_get_channel_mix_buffer(current.bus_index, 3) + }; + + for (int j = 0; j < buffer_size; j++) { + + AudioFrame frame = buffer[j] * vol; + targets[0][j] = frame; + targets[1][j] = frame; + targets[2][j] = frame; + vol += vol_inc; + } + + } break; + } + + prev_outputs[i] = current; + } + + prev_output_count = output_count; + + //stream is no longer active, disable this. + if (!stream_playback->is_playing()) { + active = false; + } + + output_ready = false; +} + +void AudioStreamPlayer2D::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE) { + + AudioServer::get_singleton()->add_callback(_mix_audios, this); + if (autoplay && !get_tree()->is_editor_hint()) { + play(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + + AudioServer::get_singleton()->remove_callback(_mix_audios, this); + } + + if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) { + + //update anything related to position first, if possible of course + + if (!output_ready) { + List viewports; + Ref world_2d = get_world_2d(); + ERR_FAIL_COND(world_2d.is_null()); + + int new_output_count = 0; + + Vector2 global_pos = get_global_position(); + + int bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus); + + //check if any area is diverting sound into a bus + + Physics2DDirectSpaceState *space_state = Physics2DServer::get_singleton()->space_get_direct_state(world_2d->get_space()); + + Physics2DDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; + + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set(), area_mask, Physics2DDirectSpaceState::TYPE_MASK_AREA); + + for (int i = 0; i < areas; i++) { + if (!sr[i].collider) + continue; + + Area2D *area2d = sr[i].collider->cast_to(); + if (!area2d) + continue; + + if (!area2d->is_overriding_audio_bus()) + continue; + + StringName bus_name = area2d->get_audio_bus(); + bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name); + break; + } + + world_2d->get_viewport_list(&viewports); + for (List::Element *E = viewports.front(); E; E = E->next()) { + + Viewport *vp = E->get(); + if (vp->is_audio_listener_2d()) { + + //compute matrix to convert to screen + Transform2D to_screen = vp->get_global_canvas_transform() * vp->get_canvas_transform(); + Vector2 screen_size = vp->get_visible_rect().size; + + //screen in global is used for attenuation + Vector2 screen_in_global = to_screen.affine_inverse().xform(screen_size * 0.5); + + float dist = global_pos.distance_to(screen_in_global); //distance to screen center + + if (dist > max_distance) + continue; //cant hear this sound in this viewport + + float multiplier = Math::pow(1.0f - dist / max_distance, attenuation); + multiplier *= Math::db2linear(volume_db); //also apply player volume! + + //point in screen is used for panning + Vector2 point_in_screen = to_screen.xform(global_pos); + + float pan = CLAMP(point_in_screen.x / screen_size.width, 0.0, 1.0); + + float l = 1.0 - pan; + float r = pan; + + outputs[new_output_count].vol = AudioFrame(l, r) * multiplier; + outputs[new_output_count].bus_index = bus_index; + outputs[new_output_count].viewport = vp; //keep pointer only for reference + new_output_count++; + if (new_output_count == MAX_OUTPUTS) + break; + } + } + + output_count = new_output_count; + output_ready = true; + } + + //start playing if requested + if (setplay >= 0.0) { + setseek = setplay; + active = true; + setplay = -1; + _change_notify("playing"); //update property in editor + } + + //stop playing if no longer active + if (!active) { + set_fixed_process_internal(false); + _change_notify("playing"); //update property in editor + } + } +} + +void AudioStreamPlayer2D::set_stream(Ref p_stream) { + + ERR_FAIL_COND(!p_stream.is_valid()); + AudioServer::get_singleton()->lock(); + + mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size()); + + if (stream_playback.is_valid()) { + stream_playback.unref(); + stream.unref(); + active = false; + setseek = -1; + } + + stream = p_stream; + stream_playback = p_stream->instance_playback(); + + if (stream_playback.is_null()) { + stream.unref(); + ERR_FAIL_COND(stream_playback.is_null()); + } + + AudioServer::get_singleton()->unlock(); +} + +Ref AudioStreamPlayer2D::get_stream() const { + + return stream; +} + +void AudioStreamPlayer2D::set_volume_db(float p_volume) { + + volume_db = p_volume; +} +float AudioStreamPlayer2D::get_volume_db() const { + + return volume_db; +} + +void AudioStreamPlayer2D::play(float p_from_pos) { + + if (stream_playback.is_valid()) { + setplay = p_from_pos; + output_ready = false; + set_fixed_process_internal(true); + } +} + +void AudioStreamPlayer2D::seek(float p_seconds) { + + if (stream_playback.is_valid()) { + setseek = p_seconds; + } +} + +void AudioStreamPlayer2D::stop() { + + if (stream_playback.is_valid()) { + active = false; + set_fixed_process_internal(false); + setplay = -1; + } +} + +bool AudioStreamPlayer2D::is_playing() const { + + if (stream_playback.is_valid()) { + return active; // && stream_playback->is_playing(); + } + + return false; +} + +float AudioStreamPlayer2D::get_pos() { + + if (stream_playback.is_valid()) { + return stream_playback->get_pos(); + } + + return 0; +} + +void AudioStreamPlayer2D::set_bus(const StringName &p_bus) { + + //if audio is active, must lock this + AudioServer::get_singleton()->lock(); + bus = p_bus; + AudioServer::get_singleton()->unlock(); +} +StringName AudioStreamPlayer2D::get_bus() const { + + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (AudioServer::get_singleton()->get_bus_name(i) == bus) { + return bus; + } + } + return "Master"; +} + +void AudioStreamPlayer2D::set_autoplay(bool p_enable) { + + autoplay = p_enable; +} +bool AudioStreamPlayer2D::is_autoplay_enabled() { + + return autoplay; +} + +void AudioStreamPlayer2D::_set_playing(bool p_enable) { + + if (p_enable) + play(); + else + stop(); +} +bool AudioStreamPlayer2D::_is_active() const { + + return active; +} + +void AudioStreamPlayer2D::_validate_property(PropertyInfo &property) const { + + if (property.name == "bus") { + + String options; + for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { + if (i > 0) + options += ","; + String name = AudioServer::get_singleton()->get_bus_name(i); + options += name; + } + + property.hint_string = options; + } +} + +void AudioStreamPlayer2D::_bus_layout_changed() { + + _change_notify(); +} + +void AudioStreamPlayer2D::set_max_distance(float p_pixels) { + + ERR_FAIL_COND(p_pixels <= 0.0); + max_distance = p_pixels; +} + +float AudioStreamPlayer2D::get_max_distance() const { + + return max_distance; +} + +void AudioStreamPlayer2D::set_attenuation(float p_curve) { + + attenuation = p_curve; +} +float AudioStreamPlayer2D::get_attenuation() const { + + return attenuation; +} + +void AudioStreamPlayer2D::set_area_mask(uint32_t p_mask) { + + area_mask = p_mask; +} + +uint32_t AudioStreamPlayer2D::get_area_mask() const { + + return area_mask; +} + +void AudioStreamPlayer2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioStreamPlayer2D::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer2D::get_stream); + + ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer2D::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer2D::get_volume_db); + + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer2D::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer2D::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer2D::stop); + + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer2D::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer2D::get_pos); + + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer2D::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer2D::get_bus); + + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer2D::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer2D::is_autoplay_enabled); + + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer2D::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer2D::_is_active); + + ClassDB::bind_method(D_METHOD("set_max_distance", "pixels"), &AudioStreamPlayer2D::set_max_distance); + ClassDB::bind_method(D_METHOD("get_max_distance"), &AudioStreamPlayer2D::get_max_distance); + + ClassDB::bind_method(D_METHOD("set_attenuation", "curve"), &AudioStreamPlayer2D::set_attenuation); + ClassDB::bind_method(D_METHOD("get_attenuation"), &AudioStreamPlayer2D::get_attenuation); + + ClassDB::bind_method(D_METHOD("set_area_mask", "mask"), &AudioStreamPlayer2D::set_area_mask); + ClassDB::bind_method(D_METHOD("get_area_mask"), &AudioStreamPlayer2D::get_area_mask); + + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer2D::_bus_layout_changed); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "playing", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_playing", "_is_active"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autoplay"), "set_autoplay", "is_autoplay_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_distance", PROPERTY_HINT_RANGE, "1,65536,1"), "set_max_distance", "get_max_distance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "attenuation", PROPERTY_HINT_EXP_EASING), "set_attenuation", "get_attenuation"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "area_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_area_mask", "get_area_mask"); +} + +AudioStreamPlayer2D::AudioStreamPlayer2D() { + + volume_db = 0; + autoplay = false; + setseek = -1; + active = false; + output_count = 0; + prev_output_count = 0; + max_distance = 2000; + attenuation = 1; + setplay = -1; + output_ready = false; + area_mask = 1; + AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); +} + +AudioStreamPlayer2D::~AudioStreamPlayer2D() { +} diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h new file mode 100644 index 00000000000..25eff61b761 --- /dev/null +++ b/scene/2d/audio_stream_player_2d.h @@ -0,0 +1,96 @@ +#ifndef AUDIO_STREAM_PLAYER_2D_H +#define AUDIO_STREAM_PLAYER_2D_H + +#include "scene/2d/node_2d.h" +#include "servers/audio/audio_stream.h" +#include "servers/audio_server.h" + +class AudioStreamPlayer2D : public Node2D { + + GDCLASS(AudioStreamPlayer2D, Node2D) + +private: + enum { + MAX_OUTPUTS = 8, + MAX_INTERSECT_AREAS = 32 + + }; + + struct Output { + + AudioFrame vol; + int bus_index; + Viewport *viewport; //pointer only used for reference to previous mix + }; + + Output outputs[MAX_OUTPUTS]; + volatile int output_count; + volatile bool output_ready; + + //these are used by audio thread to have a reference of previous volumes (for ramping volume and avoiding clicks) + Output prev_outputs[MAX_OUTPUTS]; + int prev_output_count; + + Ref stream_playback; + Ref stream; + Vector mix_buffer; + + volatile float setseek; + volatile bool active; + volatile float setplay; + + float volume_db; + bool autoplay; + StringName bus; + + void _mix_audio(); + static void _mix_audios(void *self) { reinterpret_cast(self)->_mix_audio(); } + + void _set_playing(bool p_enable); + bool _is_active() const; + + void _bus_layout_changed(); + + uint32_t area_mask; + + float max_distance; + float attenuation; + +protected: + void _validate_property(PropertyInfo &property) const; + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_stream(Ref p_stream); + Ref get_stream() const; + + void set_volume_db(float p_volume); + float get_volume_db() const; + + void play(float p_from_pos = 0.0); + void seek(float p_seconds); + void stop(); + bool is_playing() const; + float get_pos(); + + void set_bus(const StringName &p_bus); + StringName get_bus() const; + + void set_autoplay(bool p_enable); + bool is_autoplay_enabled(); + + void set_max_distance(float p_pixels); + float get_max_distance() const; + + void set_attenuation(float p_curve); + float get_attenuation() const; + + void set_area_mask(uint32_t p_mask); + uint32_t get_area_mask() const; + + AudioStreamPlayer2D(); + ~AudioStreamPlayer2D(); +}; + +#endif diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index ad72a512d81..bcca8346420 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "audio_player.h" -void AudioPlayer::_mix_audio() { +void AudioStreamPlayer::_mix_audio() { if (!stream_playback.is_valid()) { return; @@ -95,7 +95,7 @@ void AudioPlayer::_mix_audio() { } } -void AudioPlayer::_notification(int p_what) { +void AudioStreamPlayer::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { @@ -111,7 +111,7 @@ void AudioPlayer::_notification(int p_what) { } } -void AudioPlayer::set_stream(Ref p_stream) { +void AudioStreamPlayer::set_stream(Ref p_stream) { ERR_FAIL_COND(!p_stream.is_valid()); AudioServer::get_singleton()->lock(); @@ -136,21 +136,21 @@ void AudioPlayer::set_stream(Ref p_stream) { AudioServer::get_singleton()->unlock(); } -Ref AudioPlayer::get_stream() const { +Ref AudioStreamPlayer::get_stream() const { return stream; } -void AudioPlayer::set_volume_db(float p_volume) { +void AudioStreamPlayer::set_volume_db(float p_volume) { volume_db = p_volume; } -float AudioPlayer::get_volume_db() const { +float AudioStreamPlayer::get_volume_db() const { return volume_db; } -void AudioPlayer::play(float p_from_pos) { +void AudioStreamPlayer::play(float p_from_pos) { if (stream_playback.is_valid()) { mix_volume_db = volume_db; //reset volume ramp @@ -159,21 +159,21 @@ void AudioPlayer::play(float p_from_pos) { } } -void AudioPlayer::seek(float p_seconds) { +void AudioStreamPlayer::seek(float p_seconds) { if (stream_playback.is_valid()) { setseek = p_seconds; } } -void AudioPlayer::stop() { +void AudioStreamPlayer::stop() { if (stream_playback.is_valid()) { active = false; } } -bool AudioPlayer::is_playing() const { +bool AudioStreamPlayer::is_playing() const { if (stream_playback.is_valid()) { return active && stream_playback->is_playing(); @@ -182,7 +182,7 @@ bool AudioPlayer::is_playing() const { return false; } -float AudioPlayer::get_pos() { +float AudioStreamPlayer::get_pos() { if (stream_playback.is_valid()) { return stream_playback->get_pos(); @@ -191,14 +191,14 @@ float AudioPlayer::get_pos() { return 0; } -void AudioPlayer::set_bus(const StringName &p_bus) { +void AudioStreamPlayer::set_bus(const StringName &p_bus) { //if audio is active, must lock this AudioServer::get_singleton()->lock(); bus = p_bus; AudioServer::get_singleton()->unlock(); } -StringName AudioPlayer::get_bus() const { +StringName AudioStreamPlayer::get_bus() const { for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { if (AudioServer::get_singleton()->get_bus_name(i) == bus) { @@ -208,38 +208,38 @@ StringName AudioPlayer::get_bus() const { return "Master"; } -void AudioPlayer::set_autoplay(bool p_enable) { +void AudioStreamPlayer::set_autoplay(bool p_enable) { autoplay = p_enable; } -bool AudioPlayer::is_autoplay_enabled() { +bool AudioStreamPlayer::is_autoplay_enabled() { return autoplay; } -void AudioPlayer::set_mix_target(MixTarget p_target) { +void AudioStreamPlayer::set_mix_target(MixTarget p_target) { mix_target = p_target; } -AudioPlayer::MixTarget AudioPlayer::get_mix_target() const { +AudioStreamPlayer::MixTarget AudioStreamPlayer::get_mix_target() const { return mix_target; } -void AudioPlayer::_set_playing(bool p_enable) { +void AudioStreamPlayer::_set_playing(bool p_enable) { if (p_enable) play(); else stop(); } -bool AudioPlayer::_is_active() const { +bool AudioStreamPlayer::_is_active() const { return active; } -void AudioPlayer::_validate_property(PropertyInfo &property) const { +void AudioStreamPlayer::_validate_property(PropertyInfo &property) const { if (property.name == "bus") { @@ -255,39 +255,39 @@ void AudioPlayer::_validate_property(PropertyInfo &property) const { } } -void AudioPlayer::_bus_layout_changed() { +void AudioStreamPlayer::_bus_layout_changed() { _change_notify(); } -void AudioPlayer::_bind_methods() { +void AudioStreamPlayer::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioPlayer::set_stream); - ClassDB::bind_method(D_METHOD("get_stream"), &AudioPlayer::get_stream); + ClassDB::bind_method(D_METHOD("set_stream", "stream:AudioStream"), &AudioStreamPlayer::set_stream); + ClassDB::bind_method(D_METHOD("get_stream"), &AudioStreamPlayer::get_stream); - ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioPlayer::set_volume_db); - ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioPlayer::get_volume_db); + ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db); - ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioPlayer::play, DEFVAL(0.0)); - ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioPlayer::seek); - ClassDB::bind_method(D_METHOD("stop"), &AudioPlayer::stop); + ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer::play, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer::seek); + ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer::stop); - ClassDB::bind_method(D_METHOD("is_playing"), &AudioPlayer::is_playing); - ClassDB::bind_method(D_METHOD("get_pos"), &AudioPlayer::get_pos); + ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer::is_playing); + ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer::get_pos); - ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioPlayer::set_bus); - ClassDB::bind_method(D_METHOD("get_bus"), &AudioPlayer::get_bus); + ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer::set_bus); + ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer::get_bus); - ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioPlayer::set_autoplay); - ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioPlayer::is_autoplay_enabled); + ClassDB::bind_method(D_METHOD("set_autoplay", "enable"), &AudioStreamPlayer::set_autoplay); + ClassDB::bind_method(D_METHOD("is_autoplay_enabled"), &AudioStreamPlayer::is_autoplay_enabled); - ClassDB::bind_method(D_METHOD("set_mix_target", "mix_target"), &AudioPlayer::set_mix_target); - ClassDB::bind_method(D_METHOD("get_mix_target"), &AudioPlayer::get_mix_target); + ClassDB::bind_method(D_METHOD("set_mix_target", "mix_target"), &AudioStreamPlayer::set_mix_target); + ClassDB::bind_method(D_METHOD("get_mix_target"), &AudioStreamPlayer::get_mix_target); - ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioPlayer::_set_playing); - ClassDB::bind_method(D_METHOD("_is_active"), &AudioPlayer::_is_active); + ClassDB::bind_method(D_METHOD("_set_playing", "enable"), &AudioStreamPlayer::_set_playing); + ClassDB::bind_method(D_METHOD("_is_active"), &AudioStreamPlayer::_is_active); - ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioPlayer::_bus_layout_changed); + ClassDB::bind_method(D_METHOD("_bus_layout_changed"), &AudioStreamPlayer::_bus_layout_changed); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "stream", PROPERTY_HINT_RESOURCE_TYPE, "AudioStream"), "set_stream", "get_stream"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "volume_db", PROPERTY_HINT_RANGE, "-80,24"), "set_volume_db", "get_volume_db"); @@ -297,7 +297,7 @@ void AudioPlayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::STRING, "bus", PROPERTY_HINT_ENUM, ""), "set_bus", "get_bus"); } -AudioPlayer::AudioPlayer() { +AudioStreamPlayer::AudioStreamPlayer() { mix_volume_db = 0; volume_db = 0; @@ -309,5 +309,5 @@ AudioPlayer::AudioPlayer() { AudioServer::get_singleton()->connect("bus_layout_changed", this, "_bus_layout_changed"); } -AudioPlayer::~AudioPlayer() { +AudioStreamPlayer::~AudioStreamPlayer() { } diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h index 5a8a8494e11..8bd6844dec1 100644 --- a/scene/audio/audio_player.h +++ b/scene/audio/audio_player.h @@ -33,9 +33,9 @@ #include "scene/main/node.h" #include "servers/audio/audio_stream.h" -class AudioPlayer : public Node { +class AudioStreamPlayer : public Node { - GDCLASS(AudioPlayer, Node) + GDCLASS(AudioStreamPlayer, Node) public: enum MixTarget { @@ -60,7 +60,7 @@ private: MixTarget mix_target; void _mix_audio(); - static void _mix_audios(void *self) { reinterpret_cast(self)->_mix_audio(); } + static void _mix_audios(void *self) { reinterpret_cast(self)->_mix_audio(); } void _set_playing(bool p_enable); bool _is_active() const; @@ -94,9 +94,9 @@ public: void set_mix_target(MixTarget p_target); MixTarget get_mix_target() const; - AudioPlayer(); - ~AudioPlayer(); + AudioStreamPlayer(); + ~AudioStreamPlayer(); }; -VARIANT_ENUM_CAST(AudioPlayer::MixTarget) +VARIANT_ENUM_CAST(AudioStreamPlayer::MixTarget) #endif // AUDIOPLAYER_H diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index df3729c50bc..b2737353fbe 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -111,6 +111,7 @@ #include "scene/2d/ray_cast_2d.h" //#include "scene/2d/sound_player_2d.h" //#include "scene/2d/sample_player_2d.h" +#include "scene/2d/audio_stream_player_2d.h" #include "scene/2d/canvas_modulate.h" #include "scene/2d/navigation2d.h" #include "scene/2d/remote_transform_2d.h" @@ -591,7 +592,8 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - ClassDB::register_class(); + ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_virtual_class(); ClassDB::register_class(); diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index ec9ec96e50a..36d2a38b3d2 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -360,16 +360,17 @@ RID World2D::get_space() { return space; } -RID World2D::get_sound_space() { +void World2D::get_viewport_list(List *r_viewports) { - return sound_space; + for (Map::Element *E = indexer->viewports.front(); E; E = E->next()) { + r_viewports->push_back(E->key()); + } } void World2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_canvas"), &World2D::get_canvas); ClassDB::bind_method(D_METHOD("get_space"), &World2D::get_space); - ClassDB::bind_method(D_METHOD("get_sound_space"), &World2D::get_sound_space); ClassDB::bind_method(D_METHOD("get_direct_space_state:Physics2DDirectSpaceState"), &World2D::get_direct_space_state); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index 2b6e7e73838..35c8ce390fa 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -44,7 +44,6 @@ class World2D : public Resource { RID canvas; RID space; - RID sound_space; SpatialIndexer2D *indexer; @@ -66,10 +65,11 @@ protected: public: RID get_canvas(); RID get_space(); - RID get_sound_space(); Physics2DDirectSpaceState *get_direct_space_state(); + void get_viewport_list(List *r_viewports); + World2D(); ~World2D(); };