Conversation
|
The toggle could have a third option added which only mutes the game when the game window is out-of-focus. The setting could be called "Mute on pause:" with the following options:
This way the music would not disturb players who pause the game to do something else, without interrupting the music for players who only paused the game to interact with menus and look around. |
|
I would expect music to keep playing in paused state. |
|
Perhaps it would be better to just add a mute-on-defocus option without tying it to the pause function? I do think the game needs a way to stop it from playing sound in the background when another window such as a web browser is in focus. That desire is presumably why some users might expect the game to become muted on pause. |
I would not - hence this PR. Especially things like engine noise are incredibly annoying (to me) when I pause the game (I almost always have the music muted already anyway) to work on tweaking some code, but the audio engine does not allow just pausing and resuming the FX (intended or bug?) However, point taken, I will create an option. Not sure if it's (easily) possible to detect the out-of-focus state, but will check if that can be supported. Thank you for the feedback. |
Conversely I personally do NOT want the audio to become muted just because I switch to a note-taking app or browser in the middle of a gaming session when I am not pausing the game to do so (eg, during a long transfer burn). I am still playing, just using out-of-game tooling to support my game experience. As I said, this is highly personal. On the one hand having a million game option toggles should be avoided (difficult to test, if nothing else), otoh, something as personal as this I think warrants it. |
Mute all audio when the game is paused, either by opening the settings window, or by clicking on the Pause icon, and resume when the game is resumed.
Add a settings toggle in the Audio Settings tab controlling whether audio is muted on pause or not (default: no).
TODO: This is probably not the best place to implement detecting the window focus lost/gained status and sending out the corresponding LUA event, but "It Works For Me(tm)". Request suggestions on where to implement this instead. I have investigated the "opengl/RendererGL.cpp" which would require also exposing this to the generic "Renderer" class in order to be accessible from elsewhere. Implementing it directly in the "RengererOGL" class is infeasible as it does not know about LUA.
Add a settings toggle in the Audio Settings tab controlling whether audio is muted on focus lost/gained or not (default: no). This setting works in conjunction with the mute-on-pause.
81a4c53 to
0fae0df
Compare
|
I pushed an update which also (un)mutes on focus. This additional setting works in conjunction with the (un)mute-on-pause. While my testing so far appears to show it working as intended, there are two (possibly more) issues:
|
|
We probably want the opinions of @bszlrd and @sturnclaw, and why not @fluffyfreak who works as a game dev: what is the sane / expected behaviour for music & FX when paused, and/or paused and/or unfocused window. FX be muted feels natural, but not sure about the other. I assume FX and music can be handled separately since we can set their volume independently) |
|
Quick feedback here before I go to bed: IMO, the focus-related events should be pushed to the UI event queue rather than the main game event queue. IIRC, the main event queue is (intentionally) not emitted while the game is paused, and so all events which exist at a higher level than the game-world context should be sent to the UI queue instead. There is an existing example of how to do so in the codebase; you can find it by looking up callsites of the appropriate LuaEvent overloads which take a LuaRef as their first argument. I will fully review the comment in question tomorrow regarding where to hang the event generation code off of. On the whole I like the idea here; mute-on-minimize/focus loss and mute-on-pause are definitely orthogonal states; personally I'd like the ambient FX to stop playing but the music to continue while paused (as a baseline) regardless of the above setting states (ambient FX is game-layer audio, music is application-layer/interface-layer audio), but we can look at that in more depth with a deeper change to the sound system. Side complication: how does this PR interact with interface sounds (i.e. clicks)? They should not be muted while the pause menu is open. We don't currently have a lot of them, but audible interface feedback is something I'd like to normalize across the UI long-term. |
|
So possibly it's a bug, but muting SFX and then unmuting them (using the LUA functions) does NOT restore the SFX volume. This is different to how muting/unmuting the Master Volume works. This is primarily why I went for Master Volume in the current implementation.. Personal preference is for it to behave as I have implemented it - ie,both music and SFX are muted. I guess this will require another setting.. but then again it probably won't impact me much since, as I mentioned, I almost always have the music turned off anyway so assuming the above is agreed to be a bug, I can fix that bug and then change my implementation to only (un)mute the SFX.. Fully agree that interface clicks should not be muted, so will need to modify this PR anyway. Thanks for all the feedback so far. |
Based on the only example I could find ("onGamePaused" and "onGameResumed"), I changed the event emitting to: LuaEvent::Queue(PiGui::GetEventQueue(), hasFocus? "onFocusGained" : "onFocusLost");but haven't figured out how to register and receive these events on the LUA side, as "onGamePaused" is also emitted to the main game event queue and registered in the normal way on the LUA side. |
sturnclaw
left a comment
There was a problem hiding this comment.
Hopefully these answer your questions. I've left a few tangentially-related comments, as well as one nitpick on the wording of the UI string for the focus-lost option.
data/pigui/views/game.lua
Outdated
| Input.EnableBindings() | ||
| end) | ||
|
|
||
| Event.Register("onGamePaused", function() |
There was a problem hiding this comment.
These four event handlers should become ui.Events:Register(..., function() ... end). onGamePaused et. al. is pushed to the UI event queue and there is no guarantee that events on the main queue will be processed until the pause ends.
There was a problem hiding this comment.
It turns out it needed to be ui.Events.Register(...) but thank you, finally managed to get the UI events working.
This is now also the only example in the entire codebase which registers a UI event in the LUA side (as far as my grep skills can tell).
There was a problem hiding this comment.
Thank you; implemented in b5e8818 (to be squashed)
src/Pi.cpp
Outdated
| bool hasFocus = (flags & SDL_WINDOW_INPUT_FOCUS) != 0; | ||
| if (hasFocus != lastFocus) { | ||
| lastFocus = hasFocus; | ||
| LuaEvent::Queue(hasFocus? "onFocusGained" : "onFocusLost"); |
There was a problem hiding this comment.
The proper place to handle this would be to listen for SDL_WINDOWEVENT_FOCUS_GAINED et. al. in core/GuiApplication.cpp, specifically the PollEvents function. That should dispatch to a virtual member method:
virtual void OnWindowFocusChanged(bool newFocus) {}That method would then be implemented by Pi::App, and an event dispatched to the UI event queue like so:
void Pi::App::OnWindowFocusChanged(bool newFocus)
{
if (!PiGui::GetEventQueue().IsValid())
return;
LuaEvent::Queue(PiGui::GetEventQueue(), newFocus ? "onFocusGained" : "onFocusLost");
}There was a problem hiding this comment.
Thank you; implemented in b5e8818 (to be squashed)
src/lua/LuaEngine.cpp
Outdated
| if (lua_isnone(l, 1)) { | ||
| return luaL_error(l, "SetMuteOnPause takes one boolean argument"); | ||
| } | ||
| const bool mute= lua_toboolean(l, 1); |
There was a problem hiding this comment.
Nitpick: the codebase's stylistic conventions require a space on both sides of the equals-sign here. We used to have a clang-format nag running on PRs to catch this stuff automatically, but it got far too opinionated without config-file levers to disable its opinions.
| local effectsMuted = Engine.GetEffectsMuted() | ||
| local effectsLevel = Engine.GetEffectsVolume()*100 | ||
| local muteOnPause = Engine.GetMuteOnPause() | ||
| local muteOnFocus = Engine.GetMuteOnFocus() |
There was a problem hiding this comment.
On a tangent: I hate boilerplate like this and would much prefer we just expose an Engine.GetConfigOption(key, defaultValue), Engine.SetConfigOption(key, value) API with consistent (and searchable!) string keys used directly.
This is not actionable feedback within the scope of this PR, but is something you could potentially implement in a separate, later PR if you so desired.
There was a problem hiding this comment.
Not a LUA programmer so will take your lead on this. Personally I'm not so fond of string parameterisation like that since compilers/analysers cannot detect errors, which can lead to some very subtle and difficult to trace bugs.
data/lang/ui-core/en.json
Outdated
| }, | ||
| "MUTE_ON_FOCUS": { | ||
| "description": "Setting for muting audio when the game window loses focus.", | ||
| "message": "Mute on Focus" |
There was a problem hiding this comment.
| "message": "Mute on Focus" | |
| "message": "Mute on Window Focus Lost" |
As suggested by sturnclaw, refactor the code generating the "onFocusXX" events to: - process the SDL event in the GuiApplication class - raise the events on the UI event queue rather than the main event queue -- register "ui.Events" handlers instead. Co-authored-by: Axtel Sturnclaw <sturnclaw@protonmail.com>
|
Thank you for the detailed information. Addressed all issues, but still need to implement muting only the SFX. That will require a bugfix to the way the SFX are muted/unmuted (SFX volume is not restored when SFX are unmuted). |
On the suggestion of sturnclaw, implement generic getters and setters for game settings and use them in the new settings for this feature. Future work will rework the existing settings to match this approach.
For some reason comparing the value to the return value to indicate changes never returned false, which meant any code called due to a changed slider got called every frame.
Presumably a copy-paste error introduced in commit 2a4a802.
When muting, the audio volume is set to 0 and the current audio volume is saved to the settings. When unmuting, the audio volume is set to the current audio volume (ie, 0) instead of the audio volume saved in the settings, effectively resulting in the audio still being muted. Fixed by setting the volume to whatever was last saved into the settings.
Attempt to mute and unmute music and effects separately. Kindof works for music (it is stopped and restarted instead of muted), and doesn't work at all for effects (literally nothing happens).
|
Ok, basically, the way the music system is implemented does not really allow for muting/unmuting of music and effects. Music: when muted, stops the music player, when unmuted, restarts playing the music from the beginning. (ie, it neither pauses the music, nor continues playing it muted. It's more a stop/start than a mute/unmute function) Effects: literally does nothing. Once a sample has been queued for playing, it is played at its current volume. Muting it does nothing. Changing volume does nothing. Furthermore, UI effects and "background noise" appear to both come under "Effects" so it is not possible to mute the background noise but leave UI clicks enabled. TEST: Start a new game and listen to the background noise effects. Open settings window and try to mute or change the volume of the effects. It will affect interface clicks (since each one is a new effect) but will not change the background noise effects. Since this does not work as desired by the community, I will retract this PR and maintain this in my personal branch. Muting "Master Volume" does what I want it to do. Fixing the entire audio system so muting can work as desired by the community is beyond my interest and skill level. That said, some of the commits may be useful to merge anyway to enable some other functionality, such as events for lost/gained focus. I also found a couple of minor bugs which should be merged. I will create a new "minor-fixes" branch for those. |
DRAFT PR
TODO:
Mute all audio when the game is paused, either by opening the settings window, or by clicking on the Pause icon, and resume when the game is resumed.
NOTE: This PR conflicts directly with #5644 ; so as it appears this is very much personal preference, it may be necessary to add a settings toggle which would make this a slightly less trivial PR.