Files
Shivansps 20b55eb58c TTS Speech rework (#7357)
* add imgui speech options

* adapt existing windows sapi speech implementation

* adapt existing mac speech integration

* add speech linux stubs

* add speech support in linux

* Add array checks

* Use dlopen for speech-dispatcher

* corrrect lib name

* missing includes and static cast

* do not change mac file type

* fix clang tidy warnings 1

* set tts rate

* set localization ids

* fix clang tidy warnings 2

* correct symbol name

* Remove voice cache and fix win enumerate_voices overriding voice selection

* fix mac rate

Done by notimaginative

* requested changes

* re-add voice cache for linux

* Open connection for linux get flags

* fix missing }

* change voice option combobox to std::pair

* delete duplicated voice id sanitizer on windows set voice

* Use pairs for speech_enumerate_voices() and adapt linux speech

* use reference

* actually free vector memory

* Clear voice cache when ingame options closes

* Use extern to call fsspeech_options_cleanup()

* update localization ids

* Fixing some linux and window speech oversights

* Apply volume and rate after a voice change, correct voice, volume and rate apply order
2026-05-14 08:07:11 -04:00

113 lines
3.3 KiB
C++

#include "options/Ingame_Options.h"
#include "options/Ingame_Options_internal.h"
#include "options/manager/ingame_options_manager.h"
#include "options/OptionsManager.h"
#include "options/Option.h"
static std::unique_ptr<OptConfigurator> OCGR;
// A list of all options categories: the category name and a boolean value for whether or not the window is active
SCP_vector<std::pair<SCP_string, bool>> Option_categories;
const std::unique_ptr<OptConfigurator>& getOptConfigurator()
{
if (OCGR == nullptr) {
OCGR.reset(new OptConfigurator());
}
return OCGR;
}
void ingame_options_init()
{
gr_set_clear_color(0, 0, 0);
auto& optionsList = options::OptionsManager::instance()->getOptions();
// Get a list of all option categories
for (auto& option : optionsList) {
const options::OptionBase* thisOpt = option.get();
if (thisOpt->getFlags()[options::OptionFlags::RetailBuiltinOption]) {
continue;
}
// Get the category and save it for the window list
SCP_string cat = thisOpt->getCategory();
bool found = false;
for (size_t i = 0; i < Option_categories.size(); i++) {
if (Option_categories[i].first == cat) {
found = true;
break;
}
}
if (!found) {
Option_categories.push_back(std::make_pair(cat, true));
}
auto val = thisOpt->getCurrentValueDescription();
// If it's a binary option then setup the necessary boolean for imgui
if (thisOpt->getType() == options::OptionType::Selection) {
auto values = thisOpt->getValidValues();
if ((values.size() == 2) && !(thisOpt->getFlags()[options::OptionFlags::ForceMultiValueSelection])) {
// On/Off options
if (getOptConfigurator()->get_binary_option_index(thisOpt->getTitle()) < 0) {
std::pair<SCP_string, bool> thisPair = std::make_pair(thisOpt->getTitle(), false);
// Options manager stores the boolean as a serialized string, so we need to set our own bool
if (val.serialized == "true") {
thisPair.second = true;
}
getOptConfigurator()->binary_options.push_back(thisPair);
}
}
// If it's a range option then setup the necessary float or int variables for imgui
} else if (thisOpt->getType() == options::OptionType::Range) {
// OptionsManager stores the value as a serialized string, so we need to return it to a float
float f_val;
try {
f_val = std::stof(val.serialized.c_str());
} catch (...) {
Warning(LOCATION, "Error getting value for option '%s'. Setting to 0.0f!", thisOpt->getTitle().c_str());
f_val = 0.0f;
}
// Integer Ranges
if (thisOpt->getFlags()[options::OptionFlags::RangeTypeInteger]) {
if (getOptConfigurator()->get_int_range_option_index(thisOpt->getTitle()) < 0) {
std::pair<SCP_string, int> thisPair = std::make_pair(thisOpt->getTitle().c_str(), static_cast<int>(f_val));
getOptConfigurator()->range_int_options.push_back(thisPair);
}
// Float Ranges
} else {
if (getOptConfigurator()->get_float_range_option_index(thisOpt->getTitle()) < 0) {
std::pair<SCP_string, float> thisPair = std::make_pair(thisOpt->getTitle().c_str(), f_val);
getOptConfigurator()->range_float_options.push_back(thisPair);
}
}
}
}
}
extern void fsspeech_options_cleanup();
void ingame_options_close()
{
fsspeech_options_cleanup();
OCGR.reset();
}
void ingame_options_do_frame()
{
getOptConfigurator()->onFrame();
}