mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-12-18 10:37:53 +01:00
Options refactor part 2: input bindings.
This commit is contained in:
parent
4192b12c29
commit
d99fbb092e
5 changed files with 290 additions and 190 deletions
|
@ -13,62 +13,55 @@ 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;
|
||||||
|
|
||||||
std::map<std::string, std::string> options::settings{};
|
std::unordered_map<std::string, std::string> options::settings{};
|
||||||
ControlsStruct options::RebindControls{};
|
|
||||||
bool options::ShowDialog = false;
|
bool options::ShowDialog = false;
|
||||||
GameInput* options::ControlWaitingForInput = nullptr;
|
GameInput* options::ControlWaitingForInput = nullptr;
|
||||||
std::vector<OptionBase*> options::AllOptions{};
|
std::vector<OptionBase*> options::AllOptions{};
|
||||||
|
|
||||||
const ControlRef options::Controls[6]
|
|
||||||
{
|
|
||||||
{Msg::KEYMAPPER_FlipperL, RebindControls.LeftFlipper},
|
|
||||||
{Msg::KEYMAPPER_FlipperR, RebindControls.RightFlipper},
|
|
||||||
{Msg::KEYMAPPER_BumpLeft, RebindControls.LeftTableBump},
|
|
||||||
{Msg::KEYMAPPER_BumpRight, RebindControls.RightTableBump},
|
|
||||||
{Msg::KEYMAPPER_BumpBottom, RebindControls.BottomTableBump},
|
|
||||||
{Msg::KEYMAPPER_Plunger, RebindControls.Plunger},
|
|
||||||
};
|
|
||||||
const ControlsStruct options::KeyDft =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{InputTypes::Keyboard, SDLK_z},
|
|
||||||
{InputTypes::Mouse, SDL_BUTTON_LEFT},
|
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{InputTypes::Keyboard, SDLK_SLASH},
|
|
||||||
{InputTypes::Mouse, SDL_BUTTON_RIGHT},
|
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{InputTypes::Keyboard, SDLK_SPACE},
|
|
||||||
{InputTypes::Mouse, SDL_BUTTON_MIDDLE},
|
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_A},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{InputTypes::Keyboard, SDLK_x},
|
|
||||||
{InputTypes::Mouse, SDL_BUTTON_X1},
|
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{InputTypes::Keyboard, SDLK_PERIOD},
|
|
||||||
{InputTypes::Mouse, SDL_BUTTON_X2},
|
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{InputTypes::Keyboard, SDLK_UP},
|
|
||||||
{InputTypes::Mouse, SDL_BUTTON_X2 + 1},
|
|
||||||
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_UP},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
optionsStruct options::Options
|
optionsStruct options::Options
|
||||||
{
|
{
|
||||||
KeyDft,
|
{
|
||||||
|
{
|
||||||
|
"Left Flipper key",
|
||||||
|
{InputTypes::Keyboard, SDLK_z},
|
||||||
|
{InputTypes::Mouse, SDL_BUTTON_LEFT},
|
||||||
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_LEFTSHOULDER}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Right Flipper key",
|
||||||
|
{InputTypes::Keyboard, SDLK_SLASH},
|
||||||
|
{InputTypes::Mouse,SDL_BUTTON_RIGHT},
|
||||||
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Plunger key",
|
||||||
|
{InputTypes::Keyboard, SDLK_SPACE},
|
||||||
|
{InputTypes::Mouse,SDL_BUTTON_MIDDLE},
|
||||||
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_A}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Left Table Bump key",
|
||||||
|
{InputTypes::Keyboard, SDLK_x},
|
||||||
|
{InputTypes::Mouse,SDL_BUTTON_X1},
|
||||||
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_LEFT}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Right Table Bump key",
|
||||||
|
{InputTypes::Keyboard, SDLK_PERIOD},
|
||||||
|
{InputTypes::Mouse,SDL_BUTTON_X2},
|
||||||
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_RIGHT}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Bottom Table Bump key",
|
||||||
|
{InputTypes::Keyboard, SDLK_UP},
|
||||||
|
{InputTypes::Mouse,SDL_BUTTON_X2 + 1},
|
||||||
|
{InputTypes::GameController, SDL_CONTROLLER_BUTTON_DPAD_UP}
|
||||||
|
},
|
||||||
|
},
|
||||||
{"Sounds", true},
|
{"Sounds", true},
|
||||||
{"Music", false },
|
{"Music", false},
|
||||||
{"FullScreen", false },
|
{"FullScreen", false},
|
||||||
{"Players", 1 },
|
{"Players", 1},
|
||||||
{"Screen Resolution", -1 },
|
{"Screen Resolution", -1 },
|
||||||
{"UI Scale", 1.0f},
|
{"UI Scale", 1.0f},
|
||||||
{"Uniform scaling", true},
|
{"Uniform scaling", true},
|
||||||
|
@ -116,13 +109,6 @@ void options::InitPrimary()
|
||||||
imContext->SettingsLoaded = true;
|
imContext->SettingsLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetInput("Left Flipper key", Options.Key.LeftFlipper);
|
|
||||||
GetInput("Right Flipper key", Options.Key.RightFlipper);
|
|
||||||
GetInput("Plunger key", Options.Key.Plunger);
|
|
||||||
GetInput("Left Table Bump key", Options.Key.LeftTableBump);
|
|
||||||
GetInput("Right Table Bump key", Options.Key.RightTableBump);
|
|
||||||
GetInput("Bottom Table Bump key", Options.Key.BottomTableBump);
|
|
||||||
|
|
||||||
for(const auto opt : AllOptions)
|
for(const auto opt : AllOptions)
|
||||||
{
|
{
|
||||||
opt->Load();
|
opt->Load();
|
||||||
|
@ -150,13 +136,7 @@ void options::InitSecondary()
|
||||||
|
|
||||||
void options::uninit()
|
void options::uninit()
|
||||||
{
|
{
|
||||||
SetInput("Left Flipper key", Options.Key.LeftFlipper);
|
Options.Language.V = translations::GetCurrentLanguage()->ShortName;
|
||||||
SetInput("Right Flipper key", Options.Key.RightFlipper);
|
|
||||||
SetInput("Plunger key", Options.Key.Plunger);
|
|
||||||
SetInput("Left Table Bump key", Options.Key.LeftTableBump);
|
|
||||||
SetInput("Right Table Bump key", Options.Key.RightTableBump);
|
|
||||||
SetInput("Bottom Table Bump key", Options.Key.BottomTableBump);
|
|
||||||
|
|
||||||
for (const auto opt : AllOptions)
|
for (const auto opt : AllOptions)
|
||||||
{
|
{
|
||||||
opt->Save();
|
opt->Save();
|
||||||
|
@ -308,27 +288,31 @@ void options::ShowControlDialog()
|
||||||
if (!ShowDialog)
|
if (!ShowDialog)
|
||||||
{
|
{
|
||||||
ControlWaitingForInput = nullptr;
|
ControlWaitingForInput = nullptr;
|
||||||
RebindControls = Options.Key;
|
|
||||||
ShowDialog = true;
|
ShowDialog = true;
|
||||||
|
// Save previous controls in KVP storage.
|
||||||
|
for(const auto& control: Options.Key)
|
||||||
|
{
|
||||||
|
control.Save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void options::RenderControlDialog()
|
void options::RenderControlDialog()
|
||||||
{
|
{
|
||||||
static const char* mouseButtons[]
|
static const Msg controlDescriptions[6]
|
||||||
{
|
{
|
||||||
nullptr,
|
Msg::KEYMAPPER_FlipperL,
|
||||||
"Mouse Left",
|
Msg::KEYMAPPER_FlipperR,
|
||||||
"Mouse Middle",
|
Msg::KEYMAPPER_BumpLeft,
|
||||||
"Mouse Right",
|
Msg::KEYMAPPER_BumpRight,
|
||||||
"Mouse X1",
|
Msg::KEYMAPPER_BumpBottom,
|
||||||
"Mouse X2",
|
Msg::KEYMAPPER_Plunger,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!ShowDialog)
|
if (!ShowDialog)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{550, 450});
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{550, 550});
|
||||||
if (ImGui::Begin(pb::get_rc_string(Msg::KEYMAPPER_Caption), &ShowDialog))
|
if (ImGui::Begin(pb::get_rc_string(Msg::KEYMAPPER_Caption), &ShowDialog))
|
||||||
{
|
{
|
||||||
ImGui::TextUnformatted(pb::get_rc_string(Msg::KEYMAPPER_Groupbox2));
|
ImGui::TextUnformatted(pb::get_rc_string(Msg::KEYMAPPER_Groupbox2));
|
||||||
|
@ -341,7 +325,7 @@ void options::RenderControlDialog()
|
||||||
ImGui::TextUnformatted(pb::get_rc_string(Msg::KEYMAPPER_Groupbox1));
|
ImGui::TextUnformatted(pb::get_rc_string(Msg::KEYMAPPER_Groupbox1));
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{5, 10});
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{5, 10});
|
||||||
if (ImGui::BeginTable("Controls", 4, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
|
if (ImGui::BeginTable("Controls", 4, ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders| ImGuiTableFlags_SizingStretchSame))
|
||||||
{
|
{
|
||||||
ImGui::TableSetupColumn("Control");
|
ImGui::TableSetupColumn("Control");
|
||||||
ImGui::TableSetupColumn("Binding 1");
|
ImGui::TableSetupColumn("Binding 1");
|
||||||
|
@ -349,55 +333,37 @@ void options::RenderControlDialog()
|
||||||
ImGui::TableSetupColumn("Binding 3");
|
ImGui::TableSetupColumn("Binding 3");
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
int index = 0;
|
int rowHash = 0;
|
||||||
for (auto& row : Controls)
|
for (auto inputId = GameBindings::Min; inputId < GameBindings::Max; inputId++)
|
||||||
{
|
{
|
||||||
|
auto& option = Options.Key[~inputId];
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.5, 0, 0, 1});
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4{0.5, 0, 0, 1});
|
||||||
if (ImGui::Button(pb::get_rc_string(row.NameStringId)))
|
if (ImGui::Button(pb::get_rc_string(controlDescriptions[~inputId])))
|
||||||
{
|
{
|
||||||
for (auto i = 0u; i <= 2; i++)
|
for (auto& input : option.Inputs)
|
||||||
row.Option[i] = {};
|
input = {};
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor(1);
|
ImGui::PopStyleColor(1);
|
||||||
|
|
||||||
for (auto i = 0u; i <= 2; i++)
|
for (auto& input : option.Inputs)
|
||||||
{
|
{
|
||||||
auto& ctrl = row.Option[i];
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ControlWaitingForInput == &ctrl)
|
if (ControlWaitingForInput == &input)
|
||||||
{
|
{
|
||||||
ImGui::Button("Press the key", ImVec2(-1, 0));
|
if(ImGui::Button("Press the key", ImVec2(-1, 0)))
|
||||||
|
{
|
||||||
|
ControlWaitingForInput = &input;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string tmp;
|
auto inputDescription = input.GetInputDescription();
|
||||||
const char* keyName;
|
if (ImGui::Button((inputDescription + "##" + std::to_string(rowHash++)).c_str(),
|
||||||
switch (ctrl.Type)
|
|
||||||
{
|
|
||||||
case InputTypes::Keyboard:
|
|
||||||
keyName = SDL_GetKeyName(ctrl.Value);
|
|
||||||
break;
|
|
||||||
case InputTypes::Mouse:
|
|
||||||
if (ctrl.Value >= SDL_BUTTON_LEFT && ctrl.Value <= SDL_BUTTON_X2)
|
|
||||||
keyName = mouseButtons[ctrl.Value];
|
|
||||||
else
|
|
||||||
keyName = (tmp += "Mouse " + std::to_string(ctrl.Value)).c_str();
|
|
||||||
break;
|
|
||||||
case InputTypes::GameController:
|
|
||||||
keyName = SDL_GameControllerGetStringForButton(
|
|
||||||
static_cast<SDL_GameControllerButton>(ctrl.Value));
|
|
||||||
break;
|
|
||||||
case InputTypes::None:
|
|
||||||
default:
|
|
||||||
keyName = "Unused";
|
|
||||||
}
|
|
||||||
if (!keyName || !keyName[0])
|
|
||||||
keyName = "Unknown key";
|
|
||||||
if (ImGui::Button((std::string{keyName} + "##" + std::to_string(index++)).c_str(),
|
|
||||||
ImVec2(-1, 0)))
|
ImVec2(-1, 0)))
|
||||||
{
|
{
|
||||||
ControlWaitingForInput = &ctrl;
|
ControlWaitingForInput = &input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,20 +375,26 @@ void options::RenderControlDialog()
|
||||||
|
|
||||||
if (ImGui::Button(pb::get_rc_string(Msg::KEYMAPPER_Ok)))
|
if (ImGui::Button(pb::get_rc_string(Msg::KEYMAPPER_Ok)))
|
||||||
{
|
{
|
||||||
Options.Key = RebindControls;
|
|
||||||
ShowDialog = false;
|
ShowDialog = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Button(pb::get_rc_string(Msg::KEYMAPPER_Cancel)))
|
if (ImGui::Button(pb::get_rc_string(Msg::KEYMAPPER_Cancel)))
|
||||||
{
|
{
|
||||||
|
for (auto& control : Options.Key)
|
||||||
|
{
|
||||||
|
control.Load();
|
||||||
|
}
|
||||||
ShowDialog = false;
|
ShowDialog = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = KeyDft;
|
for (auto& control : Options.Key)
|
||||||
|
{
|
||||||
|
control.Reset();
|
||||||
|
}
|
||||||
ControlWaitingForInput = nullptr;
|
ControlWaitingForInput = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,9 +405,26 @@ void options::RenderControlDialog()
|
||||||
ControlWaitingForInput = nullptr;
|
ControlWaitingForInput = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<GameBindings> options::MapGameInput(GameInput key)
|
||||||
|
{
|
||||||
|
std::vector<GameBindings> result;
|
||||||
|
for (auto inputId = GameBindings::Min; inputId < GameBindings::Max; inputId++)
|
||||||
|
{
|
||||||
|
for (auto& inputValue : Options.Key[~inputId].Inputs)
|
||||||
|
{
|
||||||
|
if (key == inputValue)
|
||||||
|
{
|
||||||
|
result.push_back(inputId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void options::MyUserData_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line)
|
void options::MyUserData_ReadLine(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line)
|
||||||
{
|
{
|
||||||
auto& keyValueStore = *static_cast<std::map<std::string, std::string>*>(entry);
|
auto& keyValueStore = *static_cast<std::unordered_map<std::string, std::string>*>(entry);
|
||||||
std::string keyValue = line;
|
std::string keyValue = line;
|
||||||
auto separatorPos = keyValue.find('=');
|
auto separatorPos = keyValue.find('=');
|
||||||
if (separatorPos != std::string::npos)
|
if (separatorPos != std::string::npos)
|
||||||
|
@ -462,6 +451,72 @@ void options::MyUserData_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandler* handl
|
||||||
buf->append("\n");
|
buf->append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GameInput::GetInputDescription() const
|
||||||
|
{
|
||||||
|
static LPCSTR mouseButtons[]
|
||||||
|
{
|
||||||
|
nullptr,
|
||||||
|
"Left",
|
||||||
|
"Middle",
|
||||||
|
"Right",
|
||||||
|
"X1",
|
||||||
|
"X2",
|
||||||
|
};
|
||||||
|
|
||||||
|
static LPCSTR controllerButtons[] =
|
||||||
|
{
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"X",
|
||||||
|
"Y",
|
||||||
|
"Back",
|
||||||
|
"Guide",
|
||||||
|
"Start",
|
||||||
|
"LeftStick",
|
||||||
|
"RightStick",
|
||||||
|
"LeftShoulder",
|
||||||
|
"RightShoulder",
|
||||||
|
"DpUp",
|
||||||
|
"DpDown",
|
||||||
|
"DpLeft",
|
||||||
|
"DpRight",
|
||||||
|
"Misc1",
|
||||||
|
"Paddle1",
|
||||||
|
"Paddle2",
|
||||||
|
"Paddle3",
|
||||||
|
"Paddle4",
|
||||||
|
"Touchpad",
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string keyName;
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case InputTypes::Keyboard:
|
||||||
|
keyName = "Keyboard\n";
|
||||||
|
keyName += SDL_GetKeyName(Value);
|
||||||
|
break;
|
||||||
|
case InputTypes::Mouse:
|
||||||
|
keyName = "Mouse\n";
|
||||||
|
if (Value >= SDL_BUTTON_LEFT && Value <= SDL_BUTTON_X2)
|
||||||
|
keyName += mouseButtons[Value];
|
||||||
|
else
|
||||||
|
keyName += std::to_string(Value);
|
||||||
|
break;
|
||||||
|
case InputTypes::GameController:
|
||||||
|
keyName = "Controller\n";
|
||||||
|
if (Value >= SDL_CONTROLLER_BUTTON_A && Value <= SDL_CONTROLLER_BUTTON_TOUCHPAD)
|
||||||
|
keyName += controllerButtons[Value];
|
||||||
|
else
|
||||||
|
keyName += std::to_string(Value);
|
||||||
|
break;
|
||||||
|
case InputTypes::None:
|
||||||
|
default:
|
||||||
|
keyName = "Unused";
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyName;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& options::GetSetting(const std::string& key, const std::string& defaultValue)
|
const std::string& options::GetSetting(const std::string& key, const std::string& defaultValue)
|
||||||
{
|
{
|
||||||
auto setting = settings.find(key);
|
auto setting = settings.find(key);
|
||||||
|
|
|
@ -33,12 +33,12 @@ enum class Menu1:int
|
||||||
Prefer3DPBGameData = 700,
|
Prefer3DPBGameData = 700,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InputTypes: unsigned
|
enum class InputTypes
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
Keyboard = 1,
|
Keyboard,
|
||||||
Mouse = 2,
|
Mouse,
|
||||||
GameController = 3,
|
GameController,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GameInput
|
struct GameInput
|
||||||
|
@ -50,23 +50,31 @@ struct GameInput
|
||||||
{
|
{
|
||||||
return Type == other.Type && Value == other.Value;
|
return Type == other.Type && Value == other.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetInputDescription() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ControlsStruct
|
enum class GameBindings
|
||||||
{
|
{
|
||||||
GameInput LeftFlipper[3];
|
Min = 0,
|
||||||
GameInput RightFlipper[3];
|
LeftFlipper = 0,
|
||||||
GameInput Plunger[3];
|
RightFlipper,
|
||||||
GameInput LeftTableBump[3];
|
Plunger,
|
||||||
GameInput RightTableBump[3];
|
LeftTableBump,
|
||||||
GameInput BottomTableBump[3];
|
RightTableBump,
|
||||||
|
BottomTableBump,
|
||||||
|
Max
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ControlRef
|
inline GameBindings& operator++(GameBindings& value, int)
|
||||||
{
|
{
|
||||||
Msg NameStringId;
|
return value = static_cast<GameBindings>(static_cast<int>(value) + 1);
|
||||||
GameInput (&Option)[3];
|
}
|
||||||
};
|
|
||||||
|
constexpr int operator~(const GameBindings& value)
|
||||||
|
{
|
||||||
|
return static_cast<int>(value);
|
||||||
|
}
|
||||||
|
|
||||||
class options
|
class options
|
||||||
{
|
{
|
||||||
|
@ -95,14 +103,12 @@ public:
|
||||||
static void InputDown(GameInput input);
|
static void InputDown(GameInput input);
|
||||||
static void ShowControlDialog();
|
static void ShowControlDialog();
|
||||||
static void RenderControlDialog();
|
static void RenderControlDialog();
|
||||||
static bool WaitingForInput() { return ControlWaitingForInput != nullptr; }
|
static bool WaitingForInput() { return ControlWaitingForInput; }
|
||||||
|
static std::vector<GameBindings> MapGameInput(GameInput key);
|
||||||
private:
|
private:
|
||||||
static std::map<std::string, std::string> settings;
|
static std::unordered_map<std::string, std::string> settings;
|
||||||
static ControlsStruct RebindControls;
|
|
||||||
static bool ShowDialog;
|
static bool ShowDialog;
|
||||||
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);
|
||||||
|
@ -183,9 +189,53 @@ struct BoolOption : OptionBaseT<bool>
|
||||||
using OptionBaseT::operator=;
|
using OptionBaseT::operator=;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ControlOption : OptionBase
|
||||||
|
{
|
||||||
|
GameInput Defaults[3];
|
||||||
|
GameInput Inputs[3];
|
||||||
|
|
||||||
|
ControlOption(LPCSTR name, GameInput defaultKeyboard, GameInput defaultMouse, GameInput defaultController) :
|
||||||
|
OptionBase(name),
|
||||||
|
Defaults{defaultKeyboard, defaultMouse, defaultController},
|
||||||
|
Inputs{
|
||||||
|
{InputTypes::Keyboard, -1},
|
||||||
|
{InputTypes::Mouse, -1},
|
||||||
|
{InputTypes::GameController, -1}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct optionsStruct
|
struct optionsStruct
|
||||||
{
|
{
|
||||||
ControlsStruct Key;
|
ControlOption Key[~GameBindings::Max];
|
||||||
BoolOption Sounds;
|
BoolOption Sounds;
|
||||||
BoolOption Music;
|
BoolOption Music;
|
||||||
BoolOption FullScreen;
|
BoolOption FullScreen;
|
||||||
|
|
|
@ -423,30 +423,32 @@ void pb::InputUp(GameInput input)
|
||||||
{
|
{
|
||||||
if (game_mode != GameModes::InGame || winmain::single_step || demo_mode)
|
if (game_mode != GameModes::InGame || winmain::single_step || demo_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.LeftFlipper, input))
|
const auto bindings = options::MapGameInput(input);
|
||||||
|
for (const auto binding : bindings)
|
||||||
{
|
{
|
||||||
MainTable->Message(MessageCode::LeftFlipperInputReleased, time_now);
|
switch (binding)
|
||||||
}
|
{
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.RightFlipper, input))
|
case GameBindings::LeftFlipper:
|
||||||
{
|
MainTable->Message(MessageCode::LeftFlipperInputReleased, time_now);
|
||||||
MainTable->Message(MessageCode::RightFlipperInputReleased, time_now);
|
break;
|
||||||
}
|
case GameBindings::RightFlipper:
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.Plunger, input))
|
MainTable->Message(MessageCode::RightFlipperInputReleased, time_now);
|
||||||
{
|
break;
|
||||||
MainTable->Message(MessageCode::PlungerInputReleased, time_now);
|
case GameBindings::Plunger:
|
||||||
}
|
MainTable->Message(MessageCode::PlungerInputReleased, time_now);
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.LeftTableBump, input))
|
break;
|
||||||
{
|
case GameBindings::LeftTableBump:
|
||||||
nudge::un_nudge_right(0, nullptr);
|
nudge::un_nudge_right(0, nullptr);
|
||||||
}
|
break;
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.RightTableBump, input))
|
case GameBindings::RightTableBump:
|
||||||
{
|
nudge::un_nudge_left(0, nullptr);
|
||||||
nudge::un_nudge_left(0, nullptr);
|
break;
|
||||||
}
|
case GameBindings::BottomTableBump:
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.BottomTableBump, input))
|
nudge::un_nudge_up(0, nullptr);
|
||||||
{
|
break;
|
||||||
nudge::un_nudge_up(0, nullptr);
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,33 +461,35 @@ void pb::InputDown(GameInput input)
|
||||||
if (input.Type == InputTypes::Keyboard)
|
if (input.Type == InputTypes::Keyboard)
|
||||||
control::pbctrl_bdoor_controller(static_cast<char>(input.Value));
|
control::pbctrl_bdoor_controller(static_cast<char>(input.Value));
|
||||||
|
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.LeftFlipper, input))
|
const auto bindings = options::MapGameInput(input);
|
||||||
|
for (const auto binding : bindings)
|
||||||
{
|
{
|
||||||
MainTable->Message(MessageCode::LeftFlipperInputPressed, time_now);
|
switch (binding)
|
||||||
}
|
{
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.RightFlipper, input))
|
case GameBindings::LeftFlipper:
|
||||||
{
|
MainTable->Message(MessageCode::LeftFlipperInputPressed, time_now);
|
||||||
MainTable->Message(MessageCode::RightFlipperInputPressed, time_now);
|
break;
|
||||||
}
|
case GameBindings::RightFlipper:
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.Plunger, input))
|
MainTable->Message(MessageCode::RightFlipperInputPressed, time_now);
|
||||||
{
|
break;
|
||||||
MainTable->Message(MessageCode::PlungerInputPressed, time_now);
|
case GameBindings::Plunger:
|
||||||
}
|
MainTable->Message(MessageCode::PlungerInputPressed, time_now);
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.LeftTableBump, input))
|
break;
|
||||||
{
|
case GameBindings::LeftTableBump:
|
||||||
if (!MainTable->TiltLockFlag)
|
if (!MainTable->TiltLockFlag)
|
||||||
nudge::nudge_right();
|
nudge::nudge_right();
|
||||||
}
|
break;
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.RightTableBump, input))
|
case GameBindings::RightTableBump:
|
||||||
{
|
if (!MainTable->TiltLockFlag)
|
||||||
if (!MainTable->TiltLockFlag)
|
nudge::nudge_left();
|
||||||
nudge::nudge_left();
|
break;
|
||||||
}
|
case GameBindings::BottomTableBump:
|
||||||
if (AnyBindingMatchesInput(options::Options.Key.BottomTableBump, input))
|
if (!MainTable->TiltLockFlag)
|
||||||
{
|
nudge::nudge_up();
|
||||||
if (!MainTable->TiltLockFlag)
|
break;
|
||||||
nudge::nudge_up();
|
default: break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cheat_mode && input.Type == InputTypes::Keyboard)
|
if (cheat_mode && input.Type == InputTypes::Keyboard)
|
||||||
{
|
{
|
||||||
|
@ -660,14 +664,6 @@ void pb::PushCheat(const std::string& cheat)
|
||||||
control::pbctrl_bdoor_controller(ch);
|
control::pbctrl_bdoor_controller(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pb::AnyBindingMatchesInput(GameInput (&options)[3], GameInput key)
|
|
||||||
{
|
|
||||||
for (auto& option : options)
|
|
||||||
if (key == option)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LPCSTR pb::get_rc_string(Msg uID)
|
LPCSTR pb::get_rc_string(Msg uID)
|
||||||
{
|
{
|
||||||
return translations::GetTranslation(uID);
|
return translations::GetTranslation(uID);
|
||||||
|
|
|
@ -82,6 +82,4 @@ public:
|
||||||
static void ShowMessageBox(Uint32 flags, LPCSTR title, LPCSTR message);
|
static void ShowMessageBox(Uint32 flags, LPCSTR title, LPCSTR message);
|
||||||
private:
|
private:
|
||||||
static bool demo_mode;
|
static bool demo_mode;
|
||||||
|
|
||||||
static bool AnyBindingMatchesInput(GameInput (&options)[3], GameInput key);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
//#include <array>
|
//#include <array>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue