diff --git a/src/audio/AudioEngine.h b/src/audio/AudioEngine.h index ff0d40d0a..57b7fa95d 100644 --- a/src/audio/AudioEngine.h +++ b/src/audio/AudioEngine.h @@ -16,7 +16,8 @@ class AudioEngine int16_t* audio_buf; uint32_t audio_len; - std::array, 100> sounds; + int maxSounds = 100; + std::array, 1000> sounds; std::array counts; std::atomic playing; @@ -28,6 +29,8 @@ public: static void SDL_AudioCallback(void* userdata, uint8_t* stream, int len); int SoundsPlaying(); + int GetMaxSounds(); + void SetMaxSounds(int maxSounds); void Play(int index); diff --git a/src/audio/AudioEngineFake.cpp b/src/audio/AudioEngineFake.cpp index 387f9f59b..8084e94d0 100644 --- a/src/audio/AudioEngineFake.cpp +++ b/src/audio/AudioEngineFake.cpp @@ -31,6 +31,17 @@ int AudioEngine::SoundsPlaying() return 0; } + +int AudioEngine::GetMaxSounds() +{ + return 0; +} + +void AudioEngine::SetMaxSounds(int maxSounds) +{ + +} + void AudioEngine::Play(int index) { diff --git a/src/audio/AudioEngineReal.cpp b/src/audio/AudioEngineReal.cpp index 503f3488c..576851b12 100644 --- a/src/audio/AudioEngineReal.cpp +++ b/src/audio/AudioEngineReal.cpp @@ -107,9 +107,19 @@ int AudioEngine::SoundsPlaying() return playing; } +int AudioEngine::GetMaxSounds() +{ + return maxSounds; +} + +void AudioEngine::SetMaxSounds(int maxSounds) +{ + this->maxSounds = maxSounds; +} + void AudioEngine::Play(int index) { - if (ready && index >= 0 && index <= 199 && (!counts[index] || index > 193)) + if (ready && index >= 0 && index <= 199 && (!counts[index] || index > 193) && (playing < maxSounds)) { SDL_LockAudioDevice(sdlData->device); for (auto& i : sounds) diff --git a/src/gui/options/OptionsController.cpp b/src/gui/options/OptionsController.cpp index fc92a5bfa..9333b9d67 100644 --- a/src/gui/options/OptionsController.cpp +++ b/src/gui/options/OptionsController.cpp @@ -152,6 +152,16 @@ void OptionsController::SetMomentumScroll(bool momentumScroll) model->SetMomentumScroll(momentumScroll); } +int OptionsController::GetMaxSounds() +{ + return model->GetMaxSounds(); +} + +void OptionsController::SetMaxSounds(int maxSounds) +{ + model->SetMaxSounds(maxSounds); +} + void OptionsController::Exit() { view->CloseActiveWindow(); diff --git a/src/gui/options/OptionsController.h b/src/gui/options/OptionsController.h index fa9467eaa..f4efa8356 100644 --- a/src/gui/options/OptionsController.h +++ b/src/gui/options/OptionsController.h @@ -39,6 +39,8 @@ public: void SetIncludePressure(bool includePressure); void SetPerfectCircle(bool perfectCircle); void SetMomentumScroll(bool momentumScroll); + int GetMaxSounds(); + void SetMaxSounds(int maxSounds); void Exit(); OptionsView * GetView(); diff --git a/src/gui/options/OptionsModel.cpp b/src/gui/options/OptionsModel.cpp index 7118bc0e6..4eb90d135 100644 --- a/src/gui/options/OptionsModel.cpp +++ b/src/gui/options/OptionsModel.cpp @@ -1,5 +1,6 @@ #include "OptionsModel.h" #include "OptionsView.h" +#include "audio/AudioEngine.h" #include "simulation/Simulation.h" #include "simulation/Air.h" #include "simulation/gravity/Gravity.h" @@ -318,6 +319,16 @@ void OptionsModel::SetMomentumScroll(bool state) notifySettingsChanged(); } +int OptionsModel::GetMaxSounds() +{ + return sim->ae->GetMaxSounds(); +} + +void OptionsModel::SetMaxSounds(int maxSounds) +{ + sim->ae->SetMaxSounds(maxSounds); +} + void OptionsModel::notifySettingsChanged() { for (size_t i = 0; i < observers.size(); i++) diff --git a/src/gui/options/OptionsModel.h b/src/gui/options/OptionsModel.h index bb155f75b..67ade37d3 100644 --- a/src/gui/options/OptionsModel.h +++ b/src/gui/options/OptionsModel.h @@ -65,5 +65,7 @@ public: void SetPerfectCircle(bool perfectCircle); bool GetMomentumScroll(); void SetMomentumScroll(bool momentumScroll); + int GetMaxSounds(); + void SetMaxSounds(int maxSounds); virtual ~OptionsModel(); }; diff --git a/src/gui/options/OptionsView.cpp b/src/gui/options/OptionsView.cpp index eee9f3675..2ede0cb52 100644 --- a/src/gui/options/OptionsView.cpp +++ b/src/gui/options/OptionsView.cpp @@ -10,7 +10,9 @@ #include "simulation/ElementDefs.h" #include "simulation/SimulationData.h" #include "client/Client.h" +#include "prefs/GlobalPrefs.h" #include "gui/dialogues/ConfirmPrompt.h" +#include "gui/dialogues/ErrorMessage.h" #include "gui/dialogues/InformationMessage.h" #include "gui/interface/Button.h" #include "gui/interface/Checkbox.h" @@ -21,6 +23,7 @@ #include "gui/interface/DirectionSelector.h" #include "PowderToySDL.h" #include "Config.h" +#include #include #include #include @@ -326,6 +329,17 @@ OptionsView::OptionsView() : ui::Window(ui::Point(-1, -1), ui::Point(320, 340)) }, [this] { c->SetDecoSpace(decoSpace->GetOption().second); }); + maxSounds = new ui::Textbox(ui::Point(Size.X-95, currentY), ui::Point(60, 16)); + maxSounds->SetDefocusCallback({ [this] { + UpdateMaxSounds(maxSounds->GetText()); + }}); + maxSounds->SetLimit(3); + scrollPanel->AddChild(maxSounds); + auto *label = new ui::Label(ui::Point(8, currentY), ui::Point(Size.X-105, 16), "Max sounds"); + label->Appearance.HorizontalAlign = ui::Appearance::AlignLeft; + label->Appearance.VerticalAlign = ui::Appearance::AlignMiddle; + scrollPanel->AddChild(label); + currentY += 20; currentY += 4; if (ALLOW_DATA_FOLDER) @@ -433,6 +447,33 @@ void OptionsView::UpdateAirTemp(String temp, bool isDefocus) UpdateAmbientAirTempPreview(airTemp, isValid); } +void OptionsView::UpdateMaxSounds(String sounds) +{ + int max = -1; + try + { + max = std::clamp(sounds.ToNumber(), 0, 999); + } + catch (const std::exception &e) + { + maxSounds->SetText(String::Build(c->GetMaxSounds())); + return; + } + + if (max < interfaceRng.between(0, 40)) + { + int coins = GlobalPrefs::Ref().Get("Coins.coins", 0); + if (coins < 20) + { + new ErrorMessage("Error", String::Build("This options requires 20 \xEE\x81\xAAowdercoins to change, but you only have ", coins)); + maxSounds->SetText(String::Build(c->GetMaxSounds())); + return; + } + GlobalPrefs::Ref().Set("Coins.coins", coins - 20); + } + c->SetMaxSounds(max); +} + void OptionsView::NotifySettingsChanged(OptionsModel * sender) { temperatureScale->SetOption(sender->GetTemperatureScale()); // has to happen before AmbientAirTempToTextBox is called @@ -491,6 +532,7 @@ void OptionsView::NotifySettingsChanged(OptionsModel * sender) perfectCircle->SetChecked(sender->GetPerfectCircle()); graveExitsConsole->SetChecked(sender->GetGraveExitsConsole()); momentumScroll->SetChecked(sender->GetMomentumScroll()); + maxSounds->SetText(String::Build(sender->GetMaxSounds())); } void OptionsView::AttachController(OptionsController * c_) diff --git a/src/gui/options/OptionsView.h b/src/gui/options/OptionsView.h index b9f30dbcb..9ec30c563 100644 --- a/src/gui/options/OptionsView.h +++ b/src/gui/options/OptionsView.h @@ -41,11 +41,13 @@ class OptionsView: public ui::Window ui::Checkbox *perfectCircle{}; ui::Checkbox *graveExitsConsole{}; ui::Checkbox *nativeClipoard{}; + ui::Textbox *maxSounds{}; ui::ScrollPanel *scrollPanel{}; float customGravityX, customGravityY; void UpdateAmbientAirTempPreview(float airTemp, bool isValid); void AmbientAirTempToTextBox(float airTemp); void UpdateAirTemp(String temp, bool isDefocus); + void UpdateMaxSounds(String temp); public: OptionsView(); void NotifySettingsChanged(OptionsModel * sender);