mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-12-18 10:37:53 +01:00
Refactored options: symmetric save/load.
This commit is contained in:
parent
2d6f2c14e5
commit
10ff1143cc
5 changed files with 247 additions and 174 deletions
|
@ -20,7 +20,7 @@ void font_selection::RenderDialog()
|
||||||
{
|
{
|
||||||
if (ShowDialogFlag == true)
|
if (ShowDialogFlag == true)
|
||||||
{
|
{
|
||||||
strncpy(DialogInputBuffer, options::Options.FontFileName.c_str(), sizeof(DialogInputBuffer));
|
strncpy(DialogInputBuffer, options::Options.FontFileName.V.c_str(), sizeof(DialogInputBuffer));
|
||||||
ShowDialogFlag = false;
|
ShowDialogFlag = false;
|
||||||
if (!ImGui::IsPopupOpen(popupName))
|
if (!ImGui::IsPopupOpen(popupName))
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@ void font_selection::RenderDialog()
|
||||||
|
|
||||||
if (ImGui::Button(pb::get_rc_string(Msg::HIGHSCORES_Ok)))
|
if (ImGui::Button(pb::get_rc_string(Msg::HIGHSCORES_Ok)))
|
||||||
{
|
{
|
||||||
options::Options.FontFileName = DialogInputBuffer;
|
options::Options.FontFileName.V = DialogInputBuffer;
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
winmain::Restart();
|
winmain::Restart();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ int high_score::read()
|
||||||
|
|
||||||
snprintf(Buffer, sizeof Buffer, "%d", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
strcat(Buffer, ".Name");
|
strcat(Buffer, ".Name");
|
||||||
auto name = options::get_string(Buffer, "");
|
auto name = options::GetSetting(Buffer, "");
|
||||||
strncpy(tablePtr.Name, name.c_str(), sizeof tablePtr.Name);
|
strncpy(tablePtr.Name, name.c_str(), sizeof tablePtr.Name);
|
||||||
|
|
||||||
snprintf(Buffer, sizeof Buffer, "%d", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
|
@ -54,7 +54,7 @@ int high_score::write()
|
||||||
|
|
||||||
snprintf(Buffer, sizeof Buffer, "%d", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
strcat(Buffer, ".Name");
|
strcat(Buffer, ".Name");
|
||||||
options::set_string(Buffer, tablePtr.Name);
|
options::SetSetting(Buffer, tablePtr.Name);
|
||||||
|
|
||||||
snprintf(Buffer, sizeof Buffer, "%d", position);
|
snprintf(Buffer, sizeof Buffer, "%d", position);
|
||||||
strcat(Buffer, ".Score");
|
strcat(Buffer, ".Score");
|
||||||
|
|
|
@ -13,11 +13,12 @@ constexpr int options::MaxUps, options::MaxFps, options::MinUps, options::MinFps
|
||||||
constexpr int options::MaxSoundChannels, options::MinSoundChannels, options::DefSoundChannels;
|
constexpr int options::MaxSoundChannels, options::MinSoundChannels, options::DefSoundChannels;
|
||||||
constexpr int options::MaxVolume, options::MinVolume, options::DefVolume;
|
constexpr int options::MaxVolume, options::MinVolume, options::DefVolume;
|
||||||
|
|
||||||
optionsStruct options::Options{};
|
|
||||||
std::map<std::string, std::string> options::settings{};
|
std::map<std::string, std::string> options::settings{};
|
||||||
ControlsStruct options::RebindControls{};
|
ControlsStruct options::RebindControls{};
|
||||||
bool options::ShowDialog = false;
|
bool options::ShowDialog = false;
|
||||||
GameInput* options::ControlWaitingForInput = nullptr;
|
GameInput* options::ControlWaitingForInput = nullptr;
|
||||||
|
std::vector<OptionBase*> options::AllOptions{};
|
||||||
|
|
||||||
const ControlRef options::Controls[6]
|
const ControlRef options::Controls[6]
|
||||||
{
|
{
|
||||||
{Msg::KEYMAPPER_FlipperL, RebindControls.LeftFlipper},
|
{Msg::KEYMAPPER_FlipperL, RebindControls.LeftFlipper},
|
||||||
|
@ -27,28 +28,8 @@ const ControlRef options::Controls[6]
|
||||||
{Msg::KEYMAPPER_BumpBottom, RebindControls.BottomTableBump},
|
{Msg::KEYMAPPER_BumpBottom, RebindControls.BottomTableBump},
|
||||||
{Msg::KEYMAPPER_Plunger, RebindControls.Plunger},
|
{Msg::KEYMAPPER_Plunger, RebindControls.Plunger},
|
||||||
};
|
};
|
||||||
|
const ControlsStruct options::KeyDft =
|
||||||
|
|
||||||
void options::InitPrimary()
|
|
||||||
{
|
{
|
||||||
auto imContext = ImGui::GetCurrentContext();
|
|
||||||
ImGuiSettingsHandler ini_handler;
|
|
||||||
ini_handler.TypeName = "Pinball";
|
|
||||||
ini_handler.TypeHash = ImHashStr(ini_handler.TypeName);
|
|
||||||
ini_handler.ReadOpenFn = MyUserData_ReadOpen;
|
|
||||||
ini_handler.ReadLineFn = MyUserData_ReadLine;
|
|
||||||
ini_handler.WriteAllFn = MyUserData_WriteAll;
|
|
||||||
imContext->SettingsHandlers.push_back(ini_handler);
|
|
||||||
|
|
||||||
// Settings are loaded from disk on the first frame
|
|
||||||
if (!imContext->SettingsLoaded)
|
|
||||||
{
|
|
||||||
ImGui::LoadIniSettingsFromDisk(imContext->IO.IniFilename);
|
|
||||||
imContext->SettingsLoaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Options.Key = Options.KeyDft =
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
{InputTypes::Keyboard, SDLK_z},
|
{InputTypes::Keyboard, SDLK_z},
|
||||||
{InputTypes::Mouse, SDL_BUTTON_LEFT},
|
{InputTypes::Mouse, SDL_BUTTON_LEFT},
|
||||||
|
@ -79,7 +60,62 @@ void options::InitPrimary()
|
||||||
{InputTypes::Mouse, SDL_BUTTON_X2 + 1},
|
{InputTypes::Mouse, SDL_BUTTON_X2 + 1},
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_UP},
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_UP},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
optionsStruct options::Options
|
||||||
|
{
|
||||||
|
KeyDft,
|
||||||
|
{"Sounds", true},
|
||||||
|
{"Music", false },
|
||||||
|
{"FullScreen", false },
|
||||||
|
{"Players", 1 },
|
||||||
|
{"Screen Resolution", -1 },
|
||||||
|
{"UI Scale", 1.0f},
|
||||||
|
{"Uniform scaling", true},
|
||||||
|
{"Linear Filtering", true },
|
||||||
|
{"Frames Per Second", DefFps },
|
||||||
|
{"Updates Per Second", DefUps },
|
||||||
|
{"ShowMenu", true },
|
||||||
|
{"Uncapped Updates Per Second", false },
|
||||||
|
{"Sound Channels", DefSoundChannels },
|
||||||
|
{"HybridSleep", false },
|
||||||
|
{"Prefer 3DPB Game Data", false },
|
||||||
|
{"Integer Scaling", false },
|
||||||
|
{"Sound Volume", DefVolume },
|
||||||
|
{"Music Volume", DefVolume },
|
||||||
|
{"Stereo Sound Effects", false },
|
||||||
|
{"Debug Overlay", false },
|
||||||
|
{"Debug Overlay Grid", true },
|
||||||
|
{"Debug Overlay All Edges", true },
|
||||||
|
{"Debug Overlay Ball Position", true },
|
||||||
|
{"Debug Overlay Ball Edges", true },
|
||||||
|
{"Debug Overlay Collision Mask", true },
|
||||||
|
{"Debug Overlay Sprites", true },
|
||||||
|
{"Debug Overlay Sounds", true },
|
||||||
|
{"Debug Overlay Ball Depth Grid", true },
|
||||||
|
{"Debug Overlay AABB", true },
|
||||||
|
{"FontFileName", "" },
|
||||||
|
{"Language", translations::GetCurrentLanguage()->ShortName },
|
||||||
|
};
|
||||||
|
|
||||||
|
void options::InitPrimary()
|
||||||
|
{
|
||||||
|
auto imContext = ImGui::GetCurrentContext();
|
||||||
|
ImGuiSettingsHandler ini_handler;
|
||||||
|
ini_handler.TypeName = "Pinball";
|
||||||
|
ini_handler.TypeHash = ImHashStr(ini_handler.TypeName);
|
||||||
|
ini_handler.ReadOpenFn = MyUserData_ReadOpen;
|
||||||
|
ini_handler.ReadLineFn = MyUserData_ReadLine;
|
||||||
|
ini_handler.WriteAllFn = MyUserData_WriteAll;
|
||||||
|
imContext->SettingsHandlers.push_back(ini_handler);
|
||||||
|
|
||||||
|
// Settings are loaded from disk on the first frame
|
||||||
|
if (!imContext->SettingsLoaded)
|
||||||
|
{
|
||||||
|
ImGui::LoadIniSettingsFromDisk(imContext->IO.IniFilename);
|
||||||
|
imContext->SettingsLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
GetInput("Left Flipper key", Options.Key.LeftFlipper);
|
GetInput("Left Flipper key", Options.Key.LeftFlipper);
|
||||||
GetInput("Right Flipper key", Options.Key.RightFlipper);
|
GetInput("Right Flipper key", Options.Key.RightFlipper);
|
||||||
GetInput("Plunger key", Options.Key.Plunger);
|
GetInput("Plunger key", Options.Key.Plunger);
|
||||||
|
@ -87,38 +123,19 @@ void options::InitPrimary()
|
||||||
GetInput("Right Table Bump key", Options.Key.RightTableBump);
|
GetInput("Right Table Bump key", Options.Key.RightTableBump);
|
||||||
GetInput("Bottom Table Bump key", Options.Key.BottomTableBump);
|
GetInput("Bottom Table Bump key", Options.Key.BottomTableBump);
|
||||||
|
|
||||||
Options.Sounds = get_int("Sounds", true);
|
for(const auto opt : AllOptions)
|
||||||
Options.Music = get_int("Music", false);
|
{
|
||||||
Options.FullScreen = get_int("FullScreen", false);
|
opt->Load();
|
||||||
Options.Players = get_int("Players", 1);
|
}
|
||||||
Options.UniformScaling = get_int("Uniform scaling", true);
|
|
||||||
ImGui::GetIO().FontGlobalScale = get_float("UI Scale", 1.0f);
|
winmain::ImIO->FontGlobalScale = Options.UIScale;
|
||||||
Options.Resolution = get_int("Screen Resolution", -1);
|
Options.FramesPerSecond = Clamp(Options.FramesPerSecond.V, MinFps, MaxFps);
|
||||||
Options.LinearFiltering = get_int("Linear Filtering", true);
|
Options.UpdatesPerSecond = Clamp(Options.UpdatesPerSecond.V, MinUps, MaxUps);
|
||||||
Options.FramesPerSecond = Clamp(get_int("Frames Per Second", DefFps), MinFps, MaxFps);
|
Options.UpdatesPerSecond = std::max(Options.UpdatesPerSecond.V, Options.FramesPerSecond.V);
|
||||||
Options.UpdatesPerSecond = Clamp(get_int("Updates Per Second", DefUps), MinUps, MaxUps);
|
Options.SoundChannels = Clamp(Options.SoundChannels.V, MinSoundChannels, MaxSoundChannels);
|
||||||
Options.UpdatesPerSecond = std::max(Options.UpdatesPerSecond, Options.FramesPerSecond);
|
Options.SoundVolume = Clamp(Options.SoundVolume.V, MinVolume, MaxVolume);
|
||||||
Options.ShowMenu = get_int("ShowMenu", true);
|
Options.MusicVolume = Clamp(Options.MusicVolume.V, MinVolume, MaxVolume);
|
||||||
Options.UncappedUpdatesPerSecond = get_int("Uncapped Updates Per Second", false);
|
translations::SetCurrentLanguage(Options.Language.V.c_str());
|
||||||
Options.SoundChannels = Clamp(get_int("Sound Channels", DefSoundChannels), MinSoundChannels, MaxSoundChannels);
|
|
||||||
Options.HybridSleep = get_int("HybridSleep", false);
|
|
||||||
Options.Prefer3DPBGameData = get_int("Prefer 3DPB Game Data", false);
|
|
||||||
Options.IntegerScaling = get_int("Integer Scaling", false);
|
|
||||||
Options.SoundStereo = get_int("Stereo Sound Effects", false);
|
|
||||||
Options.SoundVolume = Clamp(get_int("Sound Volume", DefVolume), MinVolume, MaxVolume);
|
|
||||||
Options.MusicVolume = Clamp(get_int("Music Volume", DefVolume), MinVolume, MaxVolume);
|
|
||||||
Options.DebugOverlay = get_int("Debug Overlay", false);
|
|
||||||
Options.DebugOverlayGrid = get_int("Debug Overlay Grid", true);
|
|
||||||
Options.DebugOverlayAllEdges = get_int("Debug Overlay All Edges", true);
|
|
||||||
Options.DebugOverlayBallPosition = get_int("Debug Overlay Ball Position", true);
|
|
||||||
Options.DebugOverlayBallEdges = get_int("Debug Overlay Ball Edges", true);
|
|
||||||
Options.DebugOverlayCollisionMask = get_int("Debug Overlay Collision Mask", true);
|
|
||||||
Options.DebugOverlaySprites = get_int("Debug Overlay Sprites", true);
|
|
||||||
Options.DebugOverlaySounds = get_int("Debug Overlay Sounds", true);
|
|
||||||
translations::SetCurrentLanguage(get_string("Language", translations::GetCurrentLanguage()->ShortName).c_str());
|
|
||||||
Options.FontFileName = get_string("FontFileName", "");
|
|
||||||
Options.DebugOverlayBallDepthGrid = get_int("Debug Overlay Ball Depth Grid", true);
|
|
||||||
Options.DebugOverlayAabb = get_int("Debug Overlay AABB", true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void options::InitSecondary()
|
void options::InitSecondary()
|
||||||
|
@ -140,37 +157,10 @@ void options::uninit()
|
||||||
SetInput("Right Table Bump key", Options.Key.RightTableBump);
|
SetInput("Right Table Bump key", Options.Key.RightTableBump);
|
||||||
SetInput("Bottom Table Bump key", Options.Key.BottomTableBump);
|
SetInput("Bottom Table Bump key", Options.Key.BottomTableBump);
|
||||||
|
|
||||||
set_int("Sounds", Options.Sounds);
|
for (const auto opt : AllOptions)
|
||||||
set_int("Music", Options.Music);
|
{
|
||||||
set_int("FullScreen", Options.FullScreen);
|
opt->Save();
|
||||||
set_int("Players", Options.Players);
|
}
|
||||||
set_int("Screen Resolution", Options.Resolution);
|
|
||||||
set_int("Uniform scaling", Options.UniformScaling);
|
|
||||||
set_float("UI Scale", ImGui::GetIO().FontGlobalScale);
|
|
||||||
set_int("Linear Filtering", Options.LinearFiltering);
|
|
||||||
set_int("Frames Per Second", Options.FramesPerSecond);
|
|
||||||
set_int("Updates Per Second", Options.UpdatesPerSecond);
|
|
||||||
set_int("ShowMenu", Options.ShowMenu);
|
|
||||||
set_int("Uncapped Updates Per Second", Options.UncappedUpdatesPerSecond);
|
|
||||||
set_int("Sound Channels", Options.SoundChannels);
|
|
||||||
set_int("HybridSleep", Options.HybridSleep);
|
|
||||||
set_int("Prefer 3DPB Game Data", Options.Prefer3DPBGameData);
|
|
||||||
set_int("Integer Scaling", Options.IntegerScaling);
|
|
||||||
set_int("Stereo Sound Effects", Options.SoundStereo);
|
|
||||||
set_int("Sound Volume", Options.SoundVolume);
|
|
||||||
set_int("Music Volume", Options.MusicVolume);
|
|
||||||
set_int("Debug Overlay", Options.DebugOverlay);
|
|
||||||
set_int("Debug Overlay Grid", Options.DebugOverlayGrid);
|
|
||||||
set_int("Debug Overlay All Edges", Options.DebugOverlayAllEdges);
|
|
||||||
set_int("Debug Overlay Ball Position", Options.DebugOverlayBallPosition);
|
|
||||||
set_int("Debug Overlay Ball Edges", Options.DebugOverlayBallEdges);
|
|
||||||
set_int("Debug Overlay Collision Mask", Options.DebugOverlayCollisionMask);
|
|
||||||
set_int("Debug Overlay Sprites", Options.DebugOverlaySprites);
|
|
||||||
set_int("Debug Overlay Sounds", Options.DebugOverlaySounds);
|
|
||||||
set_string("Language", translations::GetCurrentLanguage()->ShortName);
|
|
||||||
set_string("FontFileName", Options.FontFileName.c_str());
|
|
||||||
set_int("Debug Overlay Ball Depth Grid", Options.DebugOverlayBallDepthGrid);
|
|
||||||
set_int("Debug Overlay AABB", Options.DebugOverlayAabb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,16 +175,6 @@ void options::set_int(LPCSTR lpValueName, int data)
|
||||||
SetSetting(lpValueName, std::to_string(data));
|
SetSetting(lpValueName, std::to_string(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string options::get_string(LPCSTR lpValueName, LPCSTR defaultValue)
|
|
||||||
{
|
|
||||||
return GetSetting(lpValueName, defaultValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void options::set_string(LPCSTR lpValueName, LPCSTR value)
|
|
||||||
{
|
|
||||||
SetSetting(lpValueName, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
float options::get_float(LPCSTR lpValueName, float defaultValue)
|
float options::get_float(LPCSTR lpValueName, float defaultValue)
|
||||||
{
|
{
|
||||||
auto value = GetSetting(lpValueName, std::to_string(defaultValue));
|
auto value = GetSetting(lpValueName, std::to_string(defaultValue));
|
||||||
|
@ -206,7 +186,7 @@ void options::set_float(LPCSTR lpValueName, float data)
|
||||||
SetSetting(lpValueName, std::to_string(data));
|
SetSetting(lpValueName, std::to_string(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
void options::GetInput(const std::string& rowName, GameInput (&defaultValues)[3])
|
void options::GetInput(const std::string& rowName, GameInput (&values)[3])
|
||||||
{
|
{
|
||||||
for (auto i = 0u; i <= 2; i++)
|
for (auto i = 0u; i <= 2; i++)
|
||||||
{
|
{
|
||||||
|
@ -214,7 +194,7 @@ void options::GetInput(const std::string& rowName, GameInput (&defaultValues)[3]
|
||||||
auto inputType = static_cast<InputTypes>(get_int((name + " type").c_str(), -1));
|
auto inputType = static_cast<InputTypes>(get_int((name + " type").c_str(), -1));
|
||||||
auto input = get_int((name + " input").c_str(), -1);
|
auto input = get_int((name + " input").c_str(), -1);
|
||||||
if (inputType <= InputTypes::GameController && input != -1)
|
if (inputType <= InputTypes::GameController && input != -1)
|
||||||
defaultValues[i] = {inputType, input};
|
values[i] = {inputType, input};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +228,7 @@ void options::toggle(Menu1 uIDCheckItem)
|
||||||
midi::music_play();
|
midi::music_play();
|
||||||
return;
|
return;
|
||||||
case Menu1::Show_Menu:
|
case Menu1::Show_Menu:
|
||||||
Options.ShowMenu = Options.ShowMenu == 0;
|
Options.ShowMenu ^= true;
|
||||||
fullscrn::window_size_changed();
|
fullscrn::window_size_changed();
|
||||||
return;
|
return;
|
||||||
case Menu1::Full_Screen:
|
case Menu1::Full_Screen:
|
||||||
|
@ -442,7 +422,7 @@ void options::RenderControlDialog()
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button(pb::get_rc_string(Msg::KEYMAPPER_Default)))
|
if (ImGui::Button(pb::get_rc_string(Msg::KEYMAPPER_Default)))
|
||||||
{
|
{
|
||||||
RebindControls = Options.KeyDft;
|
RebindControls = KeyDft;
|
||||||
ControlWaitingForInput = nullptr;
|
ControlWaitingForInput = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,15 +462,15 @@ void options::MyUserData_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handl
|
||||||
buf->append("\n");
|
buf->append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& options::GetSetting(const std::string& key, const std::string& value)
|
const std::string& options::GetSetting(const std::string& key, const std::string& defaultValue)
|
||||||
{
|
{
|
||||||
auto setting = settings.find(key);
|
auto setting = settings.find(key);
|
||||||
if (setting == settings.end())
|
if (setting == settings.end())
|
||||||
{
|
{
|
||||||
settings[key] = value;
|
settings[key] = defaultValue;
|
||||||
if (ImGui::GetCurrentContext())
|
if (ImGui::GetCurrentContext())
|
||||||
ImGui::MarkIniSettingsDirty();
|
ImGui::MarkIniSettingsDirty();
|
||||||
return value;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
return setting->second;
|
return setting->second;
|
||||||
}
|
}
|
||||||
|
@ -501,3 +481,16 @@ void options::SetSetting(const std::string& key, const std::string& value)
|
||||||
if (ImGui::GetCurrentContext())
|
if (ImGui::GetCurrentContext())
|
||||||
ImGui::MarkIniSettingsDirty();
|
ImGui::MarkIniSettingsDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OptionBase::OptionBase(LPCSTR name): Name(name)
|
||||||
|
{
|
||||||
|
options::AllOptions.push_back(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionBase::~OptionBase()
|
||||||
|
{
|
||||||
|
auto& vec = options::AllOptions;
|
||||||
|
auto position = std::find(vec.begin(), vec.end(), this);
|
||||||
|
if (position != vec.end())
|
||||||
|
vec.erase(position);
|
||||||
|
}
|
||||||
|
|
|
@ -62,48 +62,12 @@ struct ControlsStruct
|
||||||
GameInput BottomTableBump[3];
|
GameInput BottomTableBump[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct optionsStruct
|
|
||||||
{
|
|
||||||
ControlsStruct Key;
|
|
||||||
ControlsStruct KeyDft;
|
|
||||||
bool Sounds;
|
|
||||||
bool Music;
|
|
||||||
bool FullScreen;
|
|
||||||
int Players;
|
|
||||||
int Resolution;
|
|
||||||
bool UniformScaling;
|
|
||||||
bool LinearFiltering;
|
|
||||||
int FramesPerSecond;
|
|
||||||
int UpdatesPerSecond;
|
|
||||||
bool ShowMenu;
|
|
||||||
bool UncappedUpdatesPerSecond;
|
|
||||||
int SoundChannels;
|
|
||||||
bool HybridSleep;
|
|
||||||
bool Prefer3DPBGameData;
|
|
||||||
bool IntegerScaling;
|
|
||||||
int SoundVolume;
|
|
||||||
int MusicVolume;
|
|
||||||
bool SoundStereo;
|
|
||||||
bool DebugOverlay;
|
|
||||||
bool DebugOverlayGrid;
|
|
||||||
bool DebugOverlayAllEdges;
|
|
||||||
bool DebugOverlayBallPosition;
|
|
||||||
bool DebugOverlayBallEdges;
|
|
||||||
bool DebugOverlayCollisionMask;
|
|
||||||
bool DebugOverlaySprites;
|
|
||||||
bool DebugOverlaySounds;
|
|
||||||
bool DebugOverlayBallDepthGrid;
|
|
||||||
bool DebugOverlayAabb;
|
|
||||||
std::string FontFileName;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ControlRef
|
struct ControlRef
|
||||||
{
|
{
|
||||||
Msg NameStringId;
|
Msg NameStringId;
|
||||||
GameInput (&Option)[3];
|
GameInput (&Option)[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class options
|
class options
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -113,18 +77,19 @@ public:
|
||||||
// Original uses 8 sound channels
|
// Original uses 8 sound channels
|
||||||
static constexpr int MaxSoundChannels = 32, MinSoundChannels = 1, DefSoundChannels = 8;
|
static constexpr int MaxSoundChannels = 32, MinSoundChannels = 1, DefSoundChannels = 8;
|
||||||
static constexpr int MaxVolume = MIX_MAX_VOLUME, MinVolume = 0, DefVolume = MaxVolume;
|
static constexpr int MaxVolume = MIX_MAX_VOLUME, MinVolume = 0, DefVolume = MaxVolume;
|
||||||
static optionsStruct Options;
|
static struct optionsStruct Options;
|
||||||
|
static std::vector<struct OptionBase*> AllOptions;
|
||||||
|
|
||||||
static void InitPrimary();
|
static void InitPrimary();
|
||||||
static void InitSecondary();
|
static void InitSecondary();
|
||||||
static void uninit();
|
static void uninit();
|
||||||
|
static const std::string& GetSetting(const std::string& key, const std::string& defaultValue);
|
||||||
|
static void SetSetting(const std::string& key, const std::string& value);
|
||||||
static int get_int(LPCSTR lpValueName, int defaultValue);
|
static int get_int(LPCSTR lpValueName, int defaultValue);
|
||||||
static void set_int(LPCSTR lpValueName, int data);
|
static void set_int(LPCSTR lpValueName, int data);
|
||||||
static std::string get_string(LPCSTR lpValueName, LPCSTR defaultValue);
|
|
||||||
static void set_string(LPCSTR lpValueName, LPCSTR value);
|
|
||||||
static float get_float(LPCSTR lpValueName, float defaultValue);
|
static float get_float(LPCSTR lpValueName, float defaultValue);
|
||||||
static void set_float(LPCSTR lpValueName, float data);
|
static void set_float(LPCSTR lpValueName, float data);
|
||||||
static void GetInput(const std::string& rowName, GameInput (&defaultValues)[3]);
|
static void GetInput(const std::string& rowName, GameInput (&values)[3]);
|
||||||
static void SetInput(const std::string& rowName, GameInput (&values)[3]);
|
static void SetInput(const std::string& rowName, GameInput (&values)[3]);
|
||||||
static void toggle(Menu1 uIDCheckItem);
|
static void toggle(Menu1 uIDCheckItem);
|
||||||
static void InputDown(GameInput input);
|
static void InputDown(GameInput input);
|
||||||
|
@ -137,10 +102,119 @@ private:
|
||||||
static bool ShowDialog;
|
static bool ShowDialog;
|
||||||
static const ControlRef Controls[6];
|
static const ControlRef Controls[6];
|
||||||
static GameInput* ControlWaitingForInput;
|
static GameInput* ControlWaitingForInput;
|
||||||
|
static const ControlsStruct KeyDft;
|
||||||
|
|
||||||
static void MyUserData_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line);
|
static void MyUserData_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line);
|
||||||
static void* MyUserData_ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name);
|
static void* MyUserData_ReadOpen(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name);
|
||||||
static void MyUserData_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
|
static void MyUserData_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
|
||||||
static const std::string& GetSetting(const std::string& key, const std::string& value);
|
};
|
||||||
static void SetSetting(const std::string& key, const std::string& value);
|
|
||||||
|
|
||||||
|
struct OptionBase
|
||||||
|
{
|
||||||
|
LPCSTR Name;
|
||||||
|
|
||||||
|
OptionBase(LPCSTR name);
|
||||||
|
virtual ~OptionBase();
|
||||||
|
virtual void Load() = 0;
|
||||||
|
virtual void Save() const = 0;
|
||||||
|
virtual void Reset() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct OptionBaseT : OptionBase
|
||||||
|
{
|
||||||
|
const T DefaultValue;
|
||||||
|
T V;
|
||||||
|
|
||||||
|
OptionBaseT(LPCSTR name, T defaultValue) : OptionBase(name), DefaultValue(std::move(defaultValue)), V()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset() override { V = DefaultValue; }
|
||||||
|
operator T&() { return V; }
|
||||||
|
|
||||||
|
OptionBaseT& operator=(const T& v)
|
||||||
|
{
|
||||||
|
V = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IntOption : OptionBaseT<int>
|
||||||
|
{
|
||||||
|
IntOption(LPCSTR name, int defaultValue) : OptionBaseT(name, defaultValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load() override { V = options::get_int(Name, DefaultValue); }
|
||||||
|
void Save() const override { options::set_int(Name, V); }
|
||||||
|
using OptionBaseT::operator=;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringOption : OptionBaseT<std::string>
|
||||||
|
{
|
||||||
|
StringOption(LPCSTR name, std::string defaultValue) : OptionBaseT(name, std::move(defaultValue))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load() override { V = options::GetSetting(Name, DefaultValue); }
|
||||||
|
void Save() const override { options::SetSetting(Name, V); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FloatOption : OptionBaseT<float>
|
||||||
|
{
|
||||||
|
FloatOption(LPCSTR name, float defaultValue) : OptionBaseT(name, defaultValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load() override { V = options::get_float(Name, DefaultValue); }
|
||||||
|
void Save() const override { options::set_float(Name, V); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BoolOption : OptionBaseT<bool>
|
||||||
|
{
|
||||||
|
BoolOption(LPCSTR name, bool defaultValue) : OptionBaseT(name, defaultValue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load() override { V = options::get_int(Name, DefaultValue); }
|
||||||
|
void Save() const override { options::set_int(Name, V); }
|
||||||
|
using OptionBaseT::operator=;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct optionsStruct
|
||||||
|
{
|
||||||
|
ControlsStruct Key;
|
||||||
|
BoolOption Sounds;
|
||||||
|
BoolOption Music;
|
||||||
|
BoolOption FullScreen;
|
||||||
|
IntOption Players;
|
||||||
|
IntOption Resolution;
|
||||||
|
FloatOption UIScale;
|
||||||
|
BoolOption UniformScaling;
|
||||||
|
BoolOption LinearFiltering;
|
||||||
|
IntOption FramesPerSecond;
|
||||||
|
IntOption UpdatesPerSecond;
|
||||||
|
BoolOption ShowMenu;
|
||||||
|
BoolOption UncappedUpdatesPerSecond;
|
||||||
|
IntOption SoundChannels;
|
||||||
|
BoolOption HybridSleep;
|
||||||
|
BoolOption Prefer3DPBGameData;
|
||||||
|
BoolOption IntegerScaling;
|
||||||
|
IntOption SoundVolume;
|
||||||
|
IntOption MusicVolume;
|
||||||
|
BoolOption SoundStereo;
|
||||||
|
BoolOption DebugOverlay;
|
||||||
|
BoolOption DebugOverlayGrid;
|
||||||
|
BoolOption DebugOverlayAllEdges;
|
||||||
|
BoolOption DebugOverlayBallPosition;
|
||||||
|
BoolOption DebugOverlayBallEdges;
|
||||||
|
BoolOption DebugOverlayCollisionMask;
|
||||||
|
BoolOption DebugOverlaySprites;
|
||||||
|
BoolOption DebugOverlaySounds;
|
||||||
|
BoolOption DebugOverlayBallDepthGrid;
|
||||||
|
BoolOption DebugOverlayAabb;
|
||||||
|
StringOption FontFileName;
|
||||||
|
StringOption Language;
|
||||||
};
|
};
|
||||||
|
|
|
@ -144,7 +144,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
// First option initialization step: just load settings from .ini. Needs ImGui context.
|
// First option initialization step: just load settings from .ini. Needs ImGui context.
|
||||||
options::InitPrimary();
|
options::InitPrimary();
|
||||||
|
|
||||||
if (!Options.FontFileName.empty())
|
if (!Options.FontFileName.V.empty())
|
||||||
{
|
{
|
||||||
ImVector<ImWchar> ranges;
|
ImVector<ImWchar> ranges;
|
||||||
translations::GetGlyphRange(&ranges);
|
translations::GetGlyphRange(&ranges);
|
||||||
|
@ -156,7 +156,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
||||||
|
|
||||||
// ToDo: improve font file test, checking if file exists is not enough
|
// ToDo: improve font file test, checking if file exists is not enough
|
||||||
auto fontLoaded = false;
|
auto fontLoaded = false;
|
||||||
auto fileName = Options.FontFileName.c_str();
|
auto fileName = Options.FontFileName.V.c_str();
|
||||||
auto fileHandle = fopenu(fileName, "rb");
|
auto fileHandle = fopenu(fileName, "rb");
|
||||||
if (fileHandle)
|
if (fileHandle)
|
||||||
{
|
{
|
||||||
|
@ -547,11 +547,14 @@ void winmain::RenderUi()
|
||||||
for (auto& item : translations::Languages)
|
for (auto& item : translations::Languages)
|
||||||
{
|
{
|
||||||
if (ImGui::MenuItem(item.DisplayName, nullptr, currentLanguage->Language == item.Language))
|
if (ImGui::MenuItem(item.DisplayName, nullptr, currentLanguage->Language == item.Language))
|
||||||
|
{
|
||||||
|
if (currentLanguage->Language != item.Language)
|
||||||
{
|
{
|
||||||
translations::SetCurrentLanguage(item.ShortName);
|
translations::SetCurrentLanguage(item.ShortName);
|
||||||
Restart();
|
Restart();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
@ -567,14 +570,14 @@ void winmain::RenderUi()
|
||||||
options::toggle(Menu1::SoundStereo);
|
options::toggle(Menu1::SoundStereo);
|
||||||
}
|
}
|
||||||
ImGui::TextUnformatted("Sound Volume");
|
ImGui::TextUnformatted("Sound Volume");
|
||||||
if (ImGui::SliderInt("##Sound Volume", &Options.SoundVolume, options::MinVolume, options::MaxVolume,
|
if (ImGui::SliderInt("##Sound Volume", &Options.SoundVolume.V, options::MinVolume, options::MaxVolume,
|
||||||
"%d",
|
"%d",
|
||||||
ImGuiSliderFlags_AlwaysClamp))
|
ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
Sound::SetVolume(Options.SoundVolume);
|
Sound::SetVolume(Options.SoundVolume);
|
||||||
}
|
}
|
||||||
ImGui::TextUnformatted("Sound Channels");
|
ImGui::TextUnformatted("Sound Channels");
|
||||||
if (ImGui::SliderInt("##Sound Channels", &Options.SoundChannels, options::MinSoundChannels,
|
if (ImGui::SliderInt("##Sound Channels", &Options.SoundChannels.V, options::MinSoundChannels,
|
||||||
options::MaxSoundChannels, "%d", ImGuiSliderFlags_AlwaysClamp))
|
options::MaxSoundChannels, "%d", ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
Sound::SetChannels(Options.SoundChannels);
|
Sound::SetChannels(Options.SoundChannels);
|
||||||
|
@ -586,7 +589,7 @@ void winmain::RenderUi()
|
||||||
options::toggle(Menu1::Music);
|
options::toggle(Menu1::Music);
|
||||||
}
|
}
|
||||||
ImGui::TextUnformatted("Music Volume");
|
ImGui::TextUnformatted("Music Volume");
|
||||||
if (ImGui::SliderInt("##Music Volume", &Options.MusicVolume, options::MinVolume, options::MaxVolume,
|
if (ImGui::SliderInt("##Music Volume", &Options.MusicVolume.V, options::MinVolume, options::MaxVolume,
|
||||||
"%d",
|
"%d",
|
||||||
ImGuiSliderFlags_AlwaysClamp))
|
ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
|
@ -613,8 +616,11 @@ void winmain::RenderUi()
|
||||||
{
|
{
|
||||||
options::toggle(Menu1::WindowIntegerScale);
|
options::toggle(Menu1::WindowIntegerScale);
|
||||||
}
|
}
|
||||||
ImGui::DragFloat("UI Scale", &ImIO->FontGlobalScale, 0.005f, 0.8f, 5,
|
if(ImGui::DragFloat("UI Scale", &Options.UIScale.V, 0.005f, 0.8f, 5,
|
||||||
"%.2f", ImGuiSliderFlags_AlwaysClamp);
|
"%.2f", ImGuiSliderFlags_AlwaysClamp))
|
||||||
|
{
|
||||||
|
ImIO->FontGlobalScale = Options.UIScale;
|
||||||
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
char buffer[80]{};
|
char buffer[80]{};
|
||||||
|
@ -625,17 +631,17 @@ void winmain::RenderUi()
|
||||||
Options.UpdatesPerSecond = options::DefUps;
|
Options.UpdatesPerSecond = options::DefUps;
|
||||||
Options.FramesPerSecond = options::DefFps;
|
Options.FramesPerSecond = options::DefFps;
|
||||||
}
|
}
|
||||||
if (ImGui::SliderInt("UPS", &Options.UpdatesPerSecond, options::MinUps, options::MaxUps, "%d",
|
if (ImGui::SliderInt("UPS", &Options.UpdatesPerSecond.V, options::MinUps, options::MaxUps, "%d",
|
||||||
ImGuiSliderFlags_AlwaysClamp))
|
ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
Options.FramesPerSecond = std::min(Options.UpdatesPerSecond, Options.FramesPerSecond);
|
Options.FramesPerSecond = std::min(Options.UpdatesPerSecond.V, Options.FramesPerSecond.V);
|
||||||
}
|
}
|
||||||
if (ImGui::SliderInt("FPS", &Options.FramesPerSecond, options::MinFps, options::MaxFps, "%d",
|
if (ImGui::SliderInt("FPS", &Options.FramesPerSecond.V, options::MinFps, options::MaxFps, "%d",
|
||||||
ImGuiSliderFlags_AlwaysClamp))
|
ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
Options.UpdatesPerSecond = std::max(Options.UpdatesPerSecond, Options.FramesPerSecond);
|
Options.UpdatesPerSecond = std::max(Options.UpdatesPerSecond.V, Options.FramesPerSecond.V);
|
||||||
}
|
}
|
||||||
snprintf(buffer, sizeof buffer - 1, "Uncapped UPS (FPS ratio %02.02f)", UpdateToFrameRatio);
|
snprintf(buffer, sizeof buffer - 1, "Uncapped UPS (FPS ratio %02.02f)", UpdateToFrameRatio);
|
||||||
if (ImGui::MenuItem(buffer, nullptr, Options.UncappedUpdatesPerSecond))
|
if (ImGui::MenuItem(buffer, nullptr, Options.UncappedUpdatesPerSecond))
|
||||||
|
@ -1134,7 +1140,7 @@ void winmain::Restart()
|
||||||
void winmain::UpdateFrameRate()
|
void winmain::UpdateFrameRate()
|
||||||
{
|
{
|
||||||
// UPS >= FPS
|
// UPS >= FPS
|
||||||
auto fps = Options.FramesPerSecond, ups = Options.UpdatesPerSecond;
|
auto fps = Options.FramesPerSecond.V, ups = Options.UpdatesPerSecond.V;
|
||||||
UpdateToFrameRatio = static_cast<double>(ups) / fps;
|
UpdateToFrameRatio = static_cast<double>(ups) / fps;
|
||||||
TargetFrameTime = DurationMs(1000.0 / ups);
|
TargetFrameTime = DurationMs(1000.0 / ups);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue