Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/config/project_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,7 @@ ProjectSettings::ProjectSettings() {
GLOBAL_DEF("display/window/energy_saving/keep_screen_on.editor", false);

GLOBAL_DEF_BASIC(PropertyInfo(Variant::STRING, "audio/buses/default_bus_layout", PROPERTY_HINT_FILE, "*.tres"), "res://default_bus_layout.tres");
GLOBAL_DEF_BASIC(PropertyInfo(Variant::BOOL, "audio/general/mute_on_focus_loss"), false);
GLOBAL_DEF_RST(PropertyInfo(Variant::FLOAT, "audio/general/2d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01"), 0.5f);
GLOBAL_DEF_RST(PropertyInfo(Variant::FLOAT, "audio/general/3d_panning_strength", PROPERTY_HINT_RANGE, "0,2,0.01"), 0.5f);

Expand Down
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@
The base strength of the panning effect for all [AudioStreamPlayer3D] nodes. The panning strength can be further scaled on each Node using [member AudioStreamPlayer3D.panning_strength]. A value of [code]0.0[/code] disables stereo panning entirely, leaving only volume attenuation in place. A value of [code]1.0[/code] completely mutes one of the channels if the sound is located exactly to the left (or right) of the listener.
The default value of [code]0.5[/code] is tuned for headphones. When using speakers, you may find lower values to sound better as speakers have a lower stereo separation compared to headphones.
</member>
<member name="audio/general/mute_on_focus_loss" type="bool" setter="" getter="" default="false">
If [code]true[/code], audio is muted when all windows spawned by the project loses focus (either by clicking outside, alt-tabbing or minimizing). This is recommended to be set to [code]true[/code] for games (while providing an option for players to disable this behavior) and [code]false[/code] for non-game applications.
</member>
<member name="audio/video/video_delay_compensation_ms" type="int" setter="" getter="" default="0">
Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing.
</member>
Expand Down
30 changes: 30 additions & 0 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
#include "core/input/shortcut.h"
#include "core/string/translation.h"
#include "core/variant/variant_parser.h"
#include "scene/animation/tween.h"
#include "scene/gui/control.h"
#include "scene/scene_string_names.h"
#include "scene/theme/theme_db.h"
#include "scene/theme/theme_owner.h"
#include "servers/audio_server.h"

// Dynamic properties.

Expand Down Expand Up @@ -649,12 +651,31 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
focused = true;
_propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_IN);
if (bool(GLOBAL_GET("audio/general/mute_on_focus_loss"))) {
// Unmute the Master bus.
print_verbose("Window: Unmuting audio on focus restore.");
AudioServer::get_singleton()->set_bus_mute(0, false);
// mute_on_focus_loss_is_tweening = true;
// Ref<Tween> tween = get_tree()->create_tween();
// AudioServer::get_singleton()->AudioServer::set_bus_mute(0, false);
// tween->tween_method(callable_mp(this, &Window::_smooth_audio_mute_callback), -80, mute_on_focus_loss_previous_db, 0.5);
Comment on lines +658 to +661
Copy link
Member Author

@Calinou Calinou May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to smoothly fade the transition and left a WIP as commented code. While this code works with a single window, I couldn't figure out a way to have the tweens not "fight" each other when both are triggered at the same time (due to popups creating "focus in" notifications when the main window gets a "focus out").

Checking only for window_id == DisplayServer::MAIN_WINDOW_ID mutes audio as soon as you open a popup, which shouldn't occur.

}
emit_signal(SNAME("focus_entered"));

} break;
case DisplayServer::WINDOW_EVENT_FOCUS_OUT: {
focused = false;
_propagate_window_notification(this, NOTIFICATION_WM_WINDOW_FOCUS_OUT);
if (bool(GLOBAL_GET("audio/general/mute_on_focus_loss"))) {
// Mute the Master bus.
print_verbose("Window: Muting audio on focus loss.");
AudioServer::get_singleton()->set_bus_mute(0, true);
// mute_on_focus_loss_previous_db = AudioServer::get_singleton()->get_bus_volume_db(0);
// mute_on_focus_loss_is_tweening = true;
// Ref<Tween> tween = get_tree()->create_tween();
// tween->tween_method(callable_mp(this, &Window::_smooth_audio_mute_callback), mute_on_focus_loss_previous_db, -80, 0.5);
// tween->tween_callback(callable_mp(AudioServer::get_singleton(), &AudioServer::set_bus_mute).bind(0, true));
}
emit_signal(SNAME("focus_exited"));
} break;
case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: {
Expand All @@ -679,6 +700,15 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) {
}
}

// void Window::_smooth_audio_mute_callback(float p_db) {
// AudioServer::get_singleton()->set_bus_volume_db(0, p_db);
// }

// void Window::_smooth_audio_done_callback(bool p_mute) {
// mute_on_focus_loss_is_tweening = false;
// AudioServer::get_singleton()->set_bus_mute(0, p_mute);
// }

void Window::update_mouse_cursor_shape() {
// The default shape is set in Viewport::_gui_input_event. To instantly
// see the shape in the viewport we need to trigger a mouse motion event.
Expand Down
4 changes: 4 additions & 0 deletions scene/main/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ class Window : public Viewport {
void _theme_changed();
void _notify_theme_override_changed();
void _invalidate_theme_cache();
float mute_on_focus_loss_previous_db = 0.0;
bool mute_on_focus_loss_is_tweening = false;

Viewport *embedder = nullptr;

Expand All @@ -190,6 +192,8 @@ class Window : public Viewport {
void _window_drop_files(const Vector<String> &p_files);
void _rect_changed_callback(const Rect2i &p_callback);
void _event_callback(DisplayServer::WindowEvent p_event);
void _smooth_audio_mute_callback(float p_db);
void _smooth_audio_doone_callback(bool p_mute);
virtual bool _can_consume_input_events() const override;

Ref<Shortcut> debugger_stop_shortcut;
Expand Down