SpaceCadetPinball/SpaceCadetPinball/options.h

293 lines
7.1 KiB
C++

#pragma once
enum class Msg : int;
enum class Menu1:int
{
New_Game = 101,
About_Pinball = 102,
High_Scores = 103,
Exit = 105,
Sounds = 201,
Music = 202,
SoundStereo = 203,
Help_Topics = 301,
Launch_Ball = 401,
Pause_Resume_Game = 402,
Full_Screen = 403,
Demo = 404,
Select_Table = 405,
Player_Controls = 406,
OnePlayer = 408,
TwoPlayers = 409,
ThreePlayers = 410,
FourPlayers = 411,
Show_Menu = 412,
MaximumResolution = 500,
R640x480 = 501,
R800x600 = 502,
R1024x768 = 503,
WindowUniformScale = 600,
WindowLinearFilter = 601,
WindowIntegerScale = 602,
Prefer3DPBGameData = 700,
};
enum class InputTypes
{
None = 0,
Keyboard,
Mouse,
GameController,
};
struct GameInput
{
InputTypes Type;
int Value;
GameInput() : GameInput(InputTypes::None, -1)
{
}
GameInput(InputTypes type, int value) : Type(type), Value(value)
{
}
bool operator==(const GameInput& other) const
{
return Type == other.Type && Value == other.Value;
}
std::string GetFullInputDescription() const;
std::string GetShortInputDescription() const;
};
enum class GameBindings
{
Min = 0,
LeftFlipper = 0,
RightFlipper,
Plunger,
LeftTableBump,
RightTableBump,
BottomTableBump,
NewGame,
TogglePause,
ToggleFullScreen,
ToggleSounds,
ToggleMusic,
ShowControlDialog,
ToggleMenuDisplay,
Exit,
Max
};
inline GameBindings& operator++(GameBindings& value, int)
{
return value = static_cast<GameBindings>(static_cast<int>(value) + 1);
}
constexpr int operator~(const GameBindings& value)
{
return static_cast<int>(value);
}
class options
{
public:
// Original does ~120 updates per second.
static constexpr int MaxUps = 360, MaxFps = MaxUps, MinUps = 60, MinFps = MinUps,
DefUps = 120, DefFps = 60;
// Original uses 8 sound channels
static constexpr int MaxSoundChannels = 32, MinSoundChannels = 1, DefSoundChannels = 8;
static constexpr int MaxVolume = MIX_MAX_VOLUME, MinVolume = 0, DefVolume = MaxVolume;
static struct optionsStruct Options;
static std::vector<struct OptionBase*> AllOptions;
static void InitPrimary();
static void InitSecondary();
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 void set_int(LPCSTR lpValueName, int data);
static float get_float(LPCSTR lpValueName, float defaultValue);
static void set_float(LPCSTR lpValueName, float data);
static void GetInput(const std::string& rowName, GameInput (&values)[3]);
static void SetInput(const std::string& rowName, GameInput (&values)[3]);
static void toggle(Menu1 uIDCheckItem);
static void InputDown(GameInput input);
static void ShowControlDialog();
static void RenderControlDialog();
static bool WaitingForInput() { return ControlWaitingForInput; }
static std::vector<GameBindings> MapGameInput(GameInput key);
static void ResetAllOptions();
private:
static std::unordered_map<std::string, std::string> settings;
static bool ShowDialog;
static GameInput* ControlWaitingForInput;
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_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf);
static void PostProcessOptions();
};
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 ControlOption : OptionBase
{
const Msg Description;
GameInput Defaults[3];
GameInput Inputs[3];
ControlOption(LPCSTR name, Msg description, GameInput defaultKeyboard, GameInput defaultMouse,
GameInput defaultController) :
OptionBase(name),
Description(description),
Defaults{defaultKeyboard, defaultMouse, defaultController},
Inputs{defaultKeyboard, defaultMouse, defaultController}
{
}
void Load() override
{
for (auto i = 0u; i <= 2; i++)
{
auto name = std::string{ Name } + " " + std::to_string(i);
Inputs[i].Type = static_cast<InputTypes>(options::get_int((name + " type").c_str(),
static_cast<int>(Defaults[i].Type)));
Inputs[i].Value = options::get_int((name + " input").c_str(), Defaults[i].Value);
}
}
void Save() const override
{
for (auto i = 0u; i <= 2; i++)
{
auto name = std::string{ Name } + " " + std::to_string(i);
options::set_int((name + " type").c_str(), static_cast<int>(Inputs[i].Type));
options::set_int((name + " input").c_str(), Inputs[i].Value);
}
}
void Reset() override
{
std::copy(std::begin(Defaults), std::end(Defaults), std::begin(Inputs));
}
std::string GetShortcutDescription() const;
};
struct optionsStruct
{
ControlOption Key[~GameBindings::Max];
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;
BoolOption HideCursor;
};