Browse Source

Fix 2D audio in multiple viewports

kobewi 2 years ago
parent
commit
8a41eefb97

+ 5 - 4
scene/2d/audio_stream_player_2d.cpp

@@ -157,7 +157,6 @@ void AudioStreamPlayer2D::_update_panning() {
 	Vector2 global_pos = get_global_position();
 
 	HashSet<Viewport *> viewports = world_2d->get_viewports();
-	viewports.insert(get_viewport()); // TODO: This is a mediocre workaround for #50958. Remove when that bug is fixed!
 
 	volume_vector.resize(4);
 	volume_vector.write[0] = AudioFrame(0, 0);
@@ -188,11 +187,11 @@ void AudioStreamPlayer2D::_update_panning() {
 		float dist = global_pos.distance_to(listener_in_global); // Distance to listener, or screen if none.
 
 		if (dist > max_distance) {
-			continue; //can't hear this sound in this viewport
+			continue; // Can't hear this sound in this viewport.
 		}
 
 		float multiplier = Math::pow(1.0f - dist / max_distance, attenuation);
-		multiplier *= Math::db_to_linear(volume_db); //also apply player volume!
+		multiplier *= Math::db_to_linear(volume_db); // Also apply player volume!
 
 		float pan = relative_to_listener.x / screen_size.x;
 		// Don't let the panning effect extend (too far) beyond the screen.
@@ -206,7 +205,9 @@ void AudioStreamPlayer2D::_update_panning() {
 		float l = 1.0 - pan;
 		float r = pan;
 
-		volume_vector.write[0] = AudioFrame(l, r) * multiplier;
+		const AudioFrame &prev_sample = volume_vector[0];
+		AudioFrame new_sample = AudioFrame(l, r) * multiplier;
+		volume_vector.write[0] = AudioFrame(MAX(prev_sample[0], new_sample[0]), MAX(prev_sample[1], new_sample[1]));
 	}
 
 	for (const Ref<AudioStreamPlayback> &playback : stream_playbacks) {

+ 6 - 0
scene/main/viewport.cpp

@@ -1090,6 +1090,10 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
 		RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
 	}
 
+	if (world_2d.is_valid()) {
+		world_2d->remove_viewport(this);
+	}
+
 	if (p_world_2d.is_valid()) {
 		world_2d = p_world_2d;
 	} else {
@@ -1097,6 +1101,7 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
 		world_2d = Ref<World2D>(memnew(World2D));
 	}
 
+	world_2d->register_viewport(this);
 	_update_audio_listener_2d();
 
 	if (is_inside_tree()) {
@@ -4149,6 +4154,7 @@ void Viewport::_validate_property(PropertyInfo &p_property) const {
 
 Viewport::Viewport() {
 	world_2d = Ref<World2D>(memnew(World2D));
+	world_2d->register_viewport(this);
 
 	viewport = RenderingServer::get_singleton()->viewport_create();
 	texture_rid = RenderingServer::get_singleton()->viewport_get_texture(viewport);

+ 8 - 0
scene/resources/world_2d.cpp

@@ -82,6 +82,14 @@ PhysicsDirectSpaceState2D *World2D::get_direct_space_state() {
 	return PhysicsServer2D::get_singleton()->space_get_direct_state(get_space());
 }
 
+void World2D::register_viewport(Viewport *p_viewport) {
+	viewports.insert(p_viewport);
+}
+
+void World2D::remove_viewport(Viewport *p_viewport) {
+	viewports.erase(p_viewport);
+}
+
 World2D::World2D() {
 	canvas = RenderingServer::get_singleton()->canvas_create();
 }

+ 3 - 3
scene/resources/world_2d.h

@@ -52,9 +52,6 @@ protected:
 	static void _bind_methods();
 	friend class Viewport;
 
-	void _register_viewport(Viewport *p_viewport);
-	void _remove_viewport(Viewport *p_viewport);
-
 public:
 	RID get_canvas() const;
 	RID get_space() const;
@@ -62,6 +59,9 @@ public:
 
 	PhysicsDirectSpaceState2D *get_direct_space_state();
 
+	void register_viewport(Viewport *p_viewport);
+	void remove_viewport(Viewport *p_viewport);
+
 	_FORCE_INLINE_ const HashSet<Viewport *> &get_viewports() { return viewports; }
 
 	World2D();