Merge pull request #318 from SHADE-DP/SP3-10-input-management

Implemented Input Binding Panel via Editor
This commit is contained in:
XiaoQiDigipen 2023-01-30 15:00:58 +08:00 committed by GitHub
commit 5240c837ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1162 additions and 16 deletions

View File

@ -1 +1,96 @@
7
Controller Look Horizontal
0
0
5
0.2
5
0
0
0
1
18
0
Controller Look Vertical
0
0
5
0.2
5
0
0
0
1
19
0
Horizontal
0
0
5
0.2
5
1
2
39
68
2
37
65
2
3
16
1
2
Jump
0
0
1000
0.2
1000
0
1
32
0
1
10
0
Mouse Look Horizontal
1
0
1
0.2
1
0
0
0
0
0
Mouse Look Vertical
2
0
1
0.2
1
0
0
0
0
0
Vertical
0
0
5
0.2
5
1
2
38
87
2
40
83
2
0
17
1
1

View File

@ -0,0 +1,546 @@
#include "SHpch.h"
#include "SHInputBindingsPanel.h"
#include "Input/SHInputManager.h"
#include "Editor/SHEditorWidgets.hpp"
namespace SHADE
{
//Vectors containing data for elements for different bindings
static std::vector<std::string> bindingRenames;
//Flags to prevent unwanted editing of bindings
static size_t positiveKeyListeningFor;
static bool positiveKeyListening;
static size_t negativeKeyListeningFor;
static bool negativeKeyListening;
static size_t positiveControllerListeningFor;
static bool positiveControllerListening;
static size_t negativeControllerListeningFor;
static bool negativeControllerListening;
//Internal Helper function
void resizeVectors(size_t newSize)
{
bindingRenames.resize(newSize);
for (auto& s : bindingRenames)
s.clear();
}
//Internal Helper function
std::string labelConcat(char const* label, size_t entryNumber)
{
std::string concat = label;
concat += std::to_string(entryNumber);
return concat;
}
void SHInputBindingsPanel::Init()
{
SHEditorWindow::Init();
}
void SHInputBindingsPanel::Update()
{
if (SHEditorWindow::Begin())
{
//ImGui::ShowDemoWindow();
//Binding count
ImGui::Text("Binding Count: %d", SHInputManager::CountBindings());
//Binding file name
static std::string bindingFileName;
ImGui::InputText("Binding File Path", &bindingFileName);
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text(".SHConfig will be appeneded to file name");
ImGui::Text("If no name is provided, saves to or loads from \"Assets/Bindings.SHConfig\"");
ImGui::EndTooltip();
}
//Save bindings to...
if (ImGui::Button("Save Bindings"))
{
if (bindingFileName.empty())
{
SHInputManager::SaveBindings();
}
else
{
std::string filePath = std::string(ASSET_ROOT);
filePath += "/";
filePath += bindingFileName;
filePath += ".SHConfig";
SHInputManager::SaveBindings(filePath);
}
}
//Load bindings from...
if (ImGui::Button("Load Bindings"))
{
if (bindingFileName.empty())
{
SHInputManager::LoadBindings();
}
else
{
std::string filePath = std::string(ASSET_ROOT);
filePath += "/";
filePath += bindingFileName;
filePath += ".SHConfig";
SHInputManager::LoadBindings(filePath);
}
resizeVectors(SHInputManager::CountBindings());
}
//Button to add new binding
if (ImGui::Button("Add New Binding"))
{
std::string newBindingName = "Binding" + std::to_string(SHInputManager::CountBindings());
SHInputManager::AddBinding(newBindingName);
resizeVectors(SHInputManager::CountBindings());
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Add a new binding to the list");
ImGui::EndTooltip();
}
//Ensure unique label for entries
size_t entryNumber = 0;
//Listing for each binding
for (auto& binding : SHInputManager::GetBindings())
{
if (ImGui::CollapsingHeader(binding.first.c_str()))
{
//Modifiable binding name
ImGui::Text("Binding Name: %s", binding.first.c_str());
ImGui::InputText(labelConcat("##bindingModifyName", entryNumber).c_str(), &bindingRenames[entryNumber]);
ImGui::SameLine();
if (ImGui::Button(labelConcat("Rename##bindingRename", entryNumber).c_str()))
{
SHInputManager::RenameBinding(binding.first, bindingRenames[entryNumber]);
bindingRenames[entryNumber].clear();
}
if (ImGui::Button(labelConcat("Delete Binding##", entryNumber).c_str()))
{
SHInputManager::RemoveBinding(binding.first);
resizeVectors(SHInputManager::CountBindings());
ImGui::End();
return;
}
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Delete this binding from the list");
ImGui::EndTooltip();
}
//Binding value test
ImGui::BeginDisabled();
float val = SHInputManager::GetBindingAxis(binding.first);
ImGui::SliderFloat(labelConcat("Value##", entryNumber).c_str(), &val, -1.0f, 1.0f);
ImGui::EndDisabled();
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Test the current value of the binding");
ImGui::Text("For mouse movement/wheel inputs, will be multiplied by Sensitivity, with 0 being neutral (no input detected)");
ImGui::Text("Between -1 and 1 for other inputs, with 0 still being neutral (no input detected)");
ImGui::EndTooltip();
}
ImGui::BeginDisabled();
float rawVal = SHInputManager::GetBindingAxisRaw(binding.first);
ImGui::SliderFloat(labelConcat("Raw Value##", entryNumber).c_str(), &rawVal, -1.0f, 1.0f);
ImGui::EndDisabled();
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Test the current value of the binding");
ImGui::Text("Raw value means it will be fixed among -1, 0 and 1 for non-mouse movement/wheel inputs");
ImGui::Text("No difference between this and Value for mouse movement/wheel inputs");
ImGui::Text("But for other inputs, does not consider smoothing options such as gravity and sensitivity");
ImGui::Text("If both positive and negative input is detected, returns neutral 0");
ImGui::EndTooltip();
}
//Binding Type Combo Box
int bindingType = static_cast<int>(SHInputManager::GetBindingType(binding.first));
if (ImGui::Combo(labelConcat("Input Type##", entryNumber).c_str(), &bindingType, "Keyboard / Mouse Buttons / Controller\0Mouse Horizontal\0Mouse Vertical\0Mouse Scroll Wheel"))
SHInputManager::SetBindingType(binding.first, static_cast<SHInputManager::SH_BINDINGTYPE>(bindingType));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Which of the four types the binding uses");
ImGui::Text("Keyboard / Mouse Buttons / Controller = Keys, mouse buttons and ALL controller inputs");
ImGui::Text("Mouse Horizontal = Horizontal movement of the mouse");
ImGui::Text("Mouse Vertical = Vertical movement of the mouse");
ImGui::Text("Mouse Scroll Wheel = The scroll wheel found at the middle of most mouses");
ImGui::EndTooltip();
}
//Inversion
bool bindingInvert = SHInputManager::GetBindingInverted(binding.first);
if (ImGui::Checkbox(labelConcat("Inverted##", entryNumber).c_str(), &bindingInvert))
SHInputManager::SetBindingInverted(binding.first, bindingInvert);
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("If inverted:");
ImGui::Text("Positive inputs mean negative value of the binding");
ImGui::Text("Negative inputs mean positive value of the binding");
ImGui::Text("Mouse moving up / right means negative value of the binding");
ImGui::Text("Scrolling the mouse wheel up means negative value of the binding");
ImGui::EndTooltip();
}
//Sensitivity
double bindingSensitivity = SHInputManager::GetBindingSensitivity(binding.first);
if (ImGui::InputDouble(labelConcat("Sensitivity##", entryNumber).c_str(), &bindingSensitivity))
SHInputManager::SetBindingSensitivity(binding.first, bindingSensitivity);
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Value multiplier for mouse movement and scrolling");
ImGui::Text("For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative");
//ImGui::Text("For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1");
ImGui::Text("Irrelevant for other analog inputs");
ImGui::EndTooltip();
}
//Below this section is only for KB/M type bindings
//Not relevant for mouse movement and scrolling
if (SHInputManager::GetBindingType(binding.first) == SHInputManager::SH_BINDINGTYPE::KB_MB_CONTROLLER)
{
//Dead
float bindingDead = static_cast<float>(SHInputManager::GetBindingDead(binding.first));
if (ImGui::SliderFloat(labelConcat("Deadzone##", entryNumber).c_str(), &bindingDead, 0.0f, 1.0f))
SHInputManager::SetBindingDead(binding.first, static_cast<double>(bindingDead));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("Any positive or negative analog input with magnitude less than this will be registered as neutral");
ImGui::EndTooltip();
}
//Gravity
double bindingGravity = SHInputManager::GetBindingGravity(binding.first);
if (ImGui::InputDouble(labelConcat("Gravity##", entryNumber).c_str(), &bindingGravity))
SHInputManager::SetBindingGravity(binding.first, static_cast<double>(bindingGravity));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("The rate at which the value moves to neutral if no input in the direction is read");
ImGui::TextColored(ImVec4{ 1.0f, 0.5f, 0.5f, 1.0f }, "Should be non-negative");
ImGui::EndTooltip();
}
//Snap
bool bindingSnap = SHInputManager::GetBindingSnap(binding.first);
if (ImGui::Checkbox(labelConcat("Snap##", entryNumber).c_str(), &bindingSnap))
SHInputManager::SetBindingSnap(binding.first, bindingSnap);
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("If no other input on the axis is present and a input is made in the opposite direction of the current value,");
ImGui::Text("the binding's value will jump to neutral 0 before resuming in the input direction");
ImGui::EndTooltip();
}
size_t keycodeIndex = 0;
//Positive key codes
ImGui::Separator();
ImGui::Text("Positive Key Codes:");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("When this keyboard or mouse button is held, causes the value to go positive, or negative when inverted");
ImGui::EndTooltip();
}
ImGui::SameLine();
//Button to ask for inputs
if (!positiveKeyListening)
{
if (ImGui::Button(labelConcat("New##positiveKeyCode", entryNumber).c_str()))
{
positiveKeyListening = true;
positiveKeyListeningFor = entryNumber;
}
}
else
{
if (positiveKeyListeningFor == entryNumber)
{
//Listening for inputs
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::Button(labelConcat("PRESS##positiveKeyCode", entryNumber).c_str());
ImGui::PopStyleColor(4);
SHInputManager::SH_KEYCODE k;
if (SHInputManager::AnyKey(&k))
{
positiveKeyListening = false;
SHInputManager::AddBindingPositiveKeyCode(binding.first, k);
}
}
else
{
//Not listening
ImGui::BeginDisabled();
ImGui::Button(labelConcat("New##positiveKeyCode", entryNumber).c_str());
ImGui::EndDisabled();
}
}
//List and remove bindings
ImGui::Indent();
keycodeIndex = 0;
for (auto& k : binding.second.positiveKeyCodes)
{
//ImGui::Text("%d", static_cast<int>(k));
ImGui::Text(SHInputManager::GetKeyCodeName(k).c_str());
ImGui::SameLine();
std::string labelString = "X##KeyPositive";
labelString += binding.first;
//Delete button
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
{
SHInputManager::RemoveBindingPositiveKeyCode(binding.first, k);
break;
}
++keycodeIndex;
}
ImGui::Unindent();
//Negative key codes
ImGui::Separator();
ImGui::Text("Negative Key Codes:");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("When this keyboard or mouse button is held, causes the value to go negative, or positive when inverted");
ImGui::EndTooltip();
}
ImGui::SameLine();
//Button to ask for inputs
if (!negativeKeyListening)
{
if (ImGui::Button(labelConcat("New##negativeKeyCode", entryNumber).c_str()))
{
negativeKeyListening = true;
negativeKeyListeningFor = entryNumber;
}
}
else
{
if (negativeKeyListeningFor == entryNumber)
{
//Listening for inputs
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::Button(labelConcat("PRESS##negativeKeyCode", entryNumber).c_str());
ImGui::PopStyleColor(4);
SHInputManager::SH_KEYCODE k;
if (SHInputManager::AnyKey(&k))
{
negativeKeyListening = false;
SHInputManager::AddBindingNegativeKeyCode(binding.first, k);
}
}
else
{
//Not listening
ImGui::BeginDisabled();
ImGui::Button(labelConcat("New##negativeKeyCode", entryNumber).c_str());
ImGui::EndDisabled();
}
}
//List and remove bindings
ImGui::Indent();
keycodeIndex = 0;
for (auto& k : binding.second.negativeKeyCodes)
{
//ImGui::Text("%d", static_cast<int>(k));
ImGui::Text(SHInputManager::GetKeyCodeName(k).c_str());
ImGui::SameLine();
std::string labelString = "X##KeyNegative";
labelString += binding.first;
//Delete button
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
{
SHInputManager::RemoveBindingNegativeKeyCode(binding.first, k);
break;
}
++keycodeIndex;
}
ImGui::Unindent();
//Positive controller codes
ImGui::Separator();
ImGui::Text("Positive Controller Codes:");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("When this controller button is held, causes the value to go positive, or negative when inverted");
ImGui::EndTooltip();
}
ImGui::SameLine();
//Button to ask for inputs
if (!positiveControllerListening)
{
if (ImGui::Button(labelConcat("New##positiveControllerCode", entryNumber).c_str()))
{
positiveControllerListening = true;
positiveControllerListeningFor = entryNumber;
}
}
else
{
if (positiveControllerListeningFor == entryNumber)
{
//Listening for inputs
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::Button(labelConcat("PRESS##positiveControllerCode", entryNumber).c_str());
ImGui::PopStyleColor(4);
SHInputManager::SH_CONTROLLERCODE c;
if (SHInputManager::AnyControllerInput(&c))
{
positiveControllerListening = false;
SHInputManager::AddBindingPositiveControllerCode(binding.first, c);
}
}
else
{
//Not listening
ImGui::BeginDisabled();
ImGui::Button(labelConcat("New##positiveControllerCode", entryNumber).c_str());
ImGui::EndDisabled();
}
}
//List and remove bindings
ImGui::Indent();
keycodeIndex = 0;
for (auto& c : binding.second.positiveControllerCodes)
{
//ImGui::Text("%d", static_cast<int>(k));
ImGui::Text(SHInputManager::GetControllerCodeName(c).c_str());
ImGui::SameLine();
std::string labelString = "X##ControllerPositive";
labelString += binding.first;
//Delete button
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
{
SHInputManager::RemoveBindingPositiveControllerCode(binding.first, c);
break;
}
++keycodeIndex;
}
ImGui::Unindent();
//Negative controller codes
ImGui::Separator();
ImGui::Text("Negative Controller Codes:");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("When this controller button is pressed, causes the value to go negative, or positive when inverted");
ImGui::EndTooltip();
}
ImGui::SameLine();
//Button to ask for inputs
if (!negativeControllerListening)
{
if (ImGui::Button(labelConcat("New##negativeControllerCode", entryNumber).c_str()))
{
negativeControllerListening = true;
negativeControllerListeningFor = entryNumber;
}
}
else
{
if (negativeControllerListeningFor == entryNumber)
{
//Listening for inputs
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.4f, 0.4f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(1.0f, 0.5f, 0.5f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.6f, 0.3f, 0.3f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
ImGui::Button(labelConcat("PRESS##negativeControllerCode", entryNumber).c_str());
ImGui::PopStyleColor(4);
SHInputManager::SH_CONTROLLERCODE c;
if (SHInputManager::AnyControllerInput(&c))
{
negativeControllerListening = false;
SHInputManager::AddBindingNegativeControllerCode(binding.first, c);
}
}
else
{
//Not listening
ImGui::BeginDisabled();
ImGui::Button(labelConcat("New##negativeControllerCode", entryNumber).c_str());
ImGui::EndDisabled();
}
}
//List and remove bindings
ImGui::Indent();
keycodeIndex = 0;
for (auto& c : binding.second.negativeControllerCodes)
{
//ImGui::Text("%d", static_cast<int>(k));
ImGui::Text(SHInputManager::GetControllerCodeName(c).c_str());
ImGui::SameLine();
std::string labelString = "X##ControllerNegative";
labelString += binding.first;
//Delete button
if (ImGui::SmallButton(labelConcat(labelString.c_str(), keycodeIndex).c_str()))
{
SHInputManager::RemoveBindingNegativeControllerCode(binding.first, c);
break;
}
++keycodeIndex;
}
ImGui::Unindent();
}
}
++entryNumber; //Next entry
}
}
ImGui::End();
}
void SHInputBindingsPanel::Exit()
{
SHEditorWindow::Exit();
}
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "Editor/EditorWindow/SHEditorWindow.h"
#include <imgui.h>
namespace SHADE
{
class SH_API SHInputBindingsPanel final : public SHEditorWindow
{
public:
SHInputBindingsPanel() : SHEditorWindow("Input Bindings Panel", ImGuiWindowFlags_MenuBar) {}
void Init() override;
void Update() override;
void Exit() override;
};
}

View File

@ -7,3 +7,4 @@
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector
#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel
#include "InputBindings/SHInputBindingsPanel.h" //Input Bindings

View File

@ -107,6 +107,7 @@ namespace SHADE
SHEditorWindowManager::CreateEditorWindow<SHColliderTagPanel>();
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHInputBindingsPanel>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();

View File

@ -100,6 +100,475 @@ namespace SHADE
}
}
std::string SHInputManager::GetKeyCodeName(SH_KEYCODE k) noexcept
{
int kInt = static_cast<int>(k);
//Numbers
if (kInt >= static_cast<int>(SH_KEYCODE::NUMBER_0) && kInt <= static_cast<int>(SH_KEYCODE::NUMBER_9))
{
return std::to_string(kInt - 48);
}
//Letters
if (kInt >= static_cast<int>(SH_KEYCODE::A) && kInt <= static_cast<int>(SH_KEYCODE::Z))
{
return std::string(1, static_cast<char>(kInt));
}
//Numpads
if (kInt >= static_cast<int>(SH_KEYCODE::NUMPAD_0) && kInt <= static_cast<int>(SH_KEYCODE::NUMPAD_9))
{
return "Numpad " + std::to_string(kInt - 96);
}
//Function keys
if (kInt >= static_cast<int>(SH_KEYCODE::F1) && kInt <= static_cast<int>(SH_KEYCODE::F24))
{
return "F" + std::to_string(kInt - 111);
}
//Other keys
switch (k)
{
case SH_KEYCODE::LMB:
return "Left Mouse Button";
break;
case SH_KEYCODE::RMB:
return "Right Mouse Button";
break;
case SH_KEYCODE::CANCEL:
return "Cancel";
break;
case SH_KEYCODE::MMB:
return "Middle Mouse Button";
break;
case SH_KEYCODE::XMB1:
return "X1 Mouse Button";
break;
case SH_KEYCODE::XMB2:
return "X2 Mouse Button";
break;
case SH_KEYCODE::BACKSPACE:
return "Backspace";
break;
case SH_KEYCODE::TAB:
return "Tab";
break;
case SH_KEYCODE::CLEAR:
return "Clear";
break;
case SH_KEYCODE::ENTER:
return "Enter";
break;
case SH_KEYCODE::SHIFT:
return "Shift";
break;
case SH_KEYCODE::CTRL:
return "Ctrl";
break;
case SH_KEYCODE::ALT:
return "Alt";
break;
case SH_KEYCODE::PAUSE:
return "Pause";
break;
case SH_KEYCODE::CAPS_LOCK:
return "Caps Lock";
break;
case SH_KEYCODE::IME_KANA:
return "IME Kana / Hangul Mode";
break;
case SH_KEYCODE::IME_ON:
return "IME On";
break;
case SH_KEYCODE::IME_JUNJA:
return "IME Junja Mode";
break;
case SH_KEYCODE::IME_FINAL:
return "IME Final Mode";
break;
case SH_KEYCODE::IME_HANJA:
return "IME Kanji / Hanja Mode";
break;
case SH_KEYCODE::IME_OFF:
return "IME Off";
break;
case SH_KEYCODE::ESCAPE:
return "Esc";
break;
case SH_KEYCODE::IME_CONVERT:
return "IME Convert";
break;
case SH_KEYCODE::IME_NONCONVERT:
return "IME Nonconvert";
break;
case SH_KEYCODE::IME_ACCEPT:
return "IME Accept";
break;
case SH_KEYCODE::IME_MODECHANGE:
return "IME Mode Change Request";
break;
case SH_KEYCODE::SPACE:
return "Spacebar";
break;
case SH_KEYCODE::PAGE_UP:
return "Page Up";
break;
case SH_KEYCODE::PAGE_DOWN:
return "Page Down";
break;
case SH_KEYCODE::END:
return "End";
break;
case SH_KEYCODE::HOME:
return "Home";
break;
case SH_KEYCODE::LEFT_ARROW:
return "Left Arrow";
break;
case SH_KEYCODE::UP_ARROW:
return "Up Arrow";
break;
case SH_KEYCODE::RIGHT_ARROW:
return "Right Arrow";
break;
case SH_KEYCODE::DOWN_ARROW:
return "Down Arrow";
break;
case SH_KEYCODE::SELECT:
return "Select";
break;
case SH_KEYCODE::PRINT:
return "Print";
break;
case SH_KEYCODE::EXECUTE:
return "Execute";
break;
case SH_KEYCODE::PRINT_SCREEN:
return "Print Screen";
break;
case SH_KEYCODE::INSERT:
return "Insert";
break;
case SH_KEYCODE::DEL:
return "Delete";
break;
case SH_KEYCODE::HELP:
return "Help";
break;
case SH_KEYCODE::LEFT_WINDOWS:
return "Left Windows";
break;
case SH_KEYCODE::RIGHT_WINDOWS:
return "Right Windows";
break;
case SH_KEYCODE::APPS:
return "Applications";
break;
case SH_KEYCODE::SLEEP:
return "Sleep";
break;
case SH_KEYCODE::MULTIPLY:
return "Numpad *";
break;
case SH_KEYCODE::ADD:
return "Numpad +";
break;
case SH_KEYCODE::SEPARATOR:
return "Separator";
break;
case SH_KEYCODE::SUBTRACT:
return "Numpad -";
break;
case SH_KEYCODE::DECIMAL:
return "Numpad .";
break;
case SH_KEYCODE::DIVIDE:
return "Numpad /";
break;
case SH_KEYCODE::NUM_LOCK:
return "Num Lock";
break;
case SH_KEYCODE::SCROLL_LOCK:
return "Scroll Lock";
break;
case SH_KEYCODE::OEM_PC98_NUMPAD_EQUAL:
return "OEM PC98 Numpad Equal / Fujitsu Dictionary";
break;
case SH_KEYCODE::OEM_FUJITSU_UNREGISTER:
return "OEM Fujitsu Unregister";
break;
case SH_KEYCODE::OEM_FUJITSU_REGISTER:
return "OEM Fujitsu Register";
break;
case SH_KEYCODE::OEM_FUJITSU_LEFT_THUMB:
return "OEM Fujitsu Left Thumb";
break;
case SH_KEYCODE::OEM_FUJITSU_RIGHT_THUMB:
return "OEM Fujitsu Right Thumb";
break;
case SH_KEYCODE::LEFT_SHIFT:
return "Left Shift";
break;
case SH_KEYCODE::RIGHT_SHIFT:
return "Right Shift";
break;
case SH_KEYCODE::LEFT_CTRL:
return "Left Ctrl";
break;
case SH_KEYCODE::RIGHT_CTRL:
return "Right Ctrl";
break;
case SH_KEYCODE::LEFT_ALT:
return "Left Alt";
break;
case SH_KEYCODE::RIGHT_ALT:
return "Right Alt";
break;
case SH_KEYCODE::BROWSER_BACK:
return "Browser Back";
break;
case SH_KEYCODE::BROWSER_FORWARD:
return "Browser Forward";
break;
case SH_KEYCODE::BROWSER_REFRESH:
return "Browser Refresh";
break;
case SH_KEYCODE::BROWSER_STOP:
return "Browser Stop";
break;
case SH_KEYCODE::BROWSER_SEARCH:
return "Browser Search";
break;
case SH_KEYCODE::BROWSER_FAVOURITES:
return "Browser Favourites";
break;
case SH_KEYCODE::BROWSER_HOME:
return "Browser Start and Home";
break;
case SH_KEYCODE::VOLUME_MUTE:
return "Volume Mute";
break;
case SH_KEYCODE::VOLUME_DOWN:
return "Volume Down";
break;
case SH_KEYCODE::VOLUME_UP:
return "Volume Up";
break;
case SH_KEYCODE::MEDIA_NEXT_TRACK:
return "Media Next Track";
break;
case SH_KEYCODE::MEDIA_PREVIOUS_TRACK:
return "Media Previous Track";
break;
case SH_KEYCODE::MEDIA_STOP:
return "Media Stop";
break;
case SH_KEYCODE::MEDIA_PLAY_PAUSE:
return "Media Play/Pause";
break;
case SH_KEYCODE::LAUNCH_MAIL:
return "Launch Mail";
break;
case SH_KEYCODE::LAUNCH_MEDIA_SELECT:
return "Select Media";
break;
case SH_KEYCODE::LAUNCH_APP_1:
return "Launch App 1";
break;
case SH_KEYCODE::LAUNCH_APP_2:
return "Launch App 2";
break;
case SH_KEYCODE::OEM_1:
return "; or :";
break;
case SH_KEYCODE::OEM_PLUS:
return "= or +";
break;
case SH_KEYCODE::OEM_COMMA:
return ", or <";
break;
case SH_KEYCODE::OEM_MINUS:
return "- or _";
break;
case SH_KEYCODE::OEM_PERIOD:
return ". or >";
break;
case SH_KEYCODE::OEM_2:
return "/ or ?";
break;
case SH_KEYCODE::OEM_3:
return "` or ~";
break;
case SH_KEYCODE::OEM_4:
return "[ or {";
break;
case SH_KEYCODE::OEM_5:
return "\\ or |";
break;
case SH_KEYCODE::OEM_6:
return "] or }";
break;
case SH_KEYCODE::OEM_7:
return "\' or \"";
break;
case SH_KEYCODE::OEM_8:
return "OEM 8";
break;
case SH_KEYCODE::OEM_AX:
return "OEM AX";
break;
case SH_KEYCODE::OEM_102:
return "< or > or \\ or |";
break;
case SH_KEYCODE::OEM_ICO_HELP:
return "ICO Help";
break;
case SH_KEYCODE::OEM_ICO_00:
return "ICO 00";
break;
case SH_KEYCODE::IME_PROCESS:
return "IME Process";
break;
case SH_KEYCODE::OEM_ICO_CLEAR:
return "ICO Clear";
break;
case SH_KEYCODE::PACKET:
return "Packet";
break;
case SH_KEYCODE::OEM_RESET:
return "OEM Reset";
break;
case SH_KEYCODE::OEM_JUMP:
return "OEM Jump";
break;
case SH_KEYCODE::OEM_PA1:
return "OEM PA1";
break;
case SH_KEYCODE::OEM_PA2:
return "OEM PA2";
break;
case SH_KEYCODE::OEM_PA3:
return "OEM PA3";
break;
case SH_KEYCODE::OEM_WSCTRL:
return "OEM WSCTRL";
break;
case SH_KEYCODE::OEM_CUSEL:
return "OEM CuSel";
break;
case SH_KEYCODE::OEM_ATTN:
return "OEM Attn";
break;
case SH_KEYCODE::OEM_FINISH:
return "OEM Finish";
break;
case SH_KEYCODE::OEM_COPY:
return "OEM Copy";
break;
case SH_KEYCODE::OEM_AUTO:
return "OEM Auto";
break;
case SH_KEYCODE::OEM_ENLW:
return "OEM ENLW";
break;
case SH_KEYCODE::OEM_BACKTAB:
return "OEM Backtab";
break;
case SH_KEYCODE::ATTN:
return "Attn";
break;
case SH_KEYCODE::CRSEL:
return "CrSel";
break;
case SH_KEYCODE::EXSEL:
return "ExSel";
break;
case SH_KEYCODE::EREOF:
return "Erase EOF";
break;
case SH_KEYCODE::PLAY:
return "Play";
break;
case SH_KEYCODE::ZOOM:
return "Zoom";
break;
case SH_KEYCODE::NONAME:
return "No Name Key";
break;
case SH_KEYCODE::PA_1:
return "PA1";
break;
case SH_KEYCODE::OEM_CLEAR:
return "OEM Clear";
break;
}
}
std::string SHInputManager::GetControllerCodeName(SH_CONTROLLERCODE c) noexcept
{
switch (c)
{
case SH_CONTROLLERCODE::DPAD_UP:
return "D-Pad Up";
break;
case SH_CONTROLLERCODE::DPAD_DOWN:
return "D-Pad Down";
break;
case SH_CONTROLLERCODE::DPAD_LEFT:
return "D-Pad Left";
break;
case SH_CONTROLLERCODE::DPAD_RIGHT:
return "D-Pad Right";
break;
case SH_CONTROLLERCODE::START:
return "Start Button";
break;
case SH_CONTROLLERCODE::BACK:
return "Back Button";
break;
case SH_CONTROLLERCODE::LEFT_THUMBSTICK:
return "Left Thumbstick Button";
break;
case SH_CONTROLLERCODE::RIGHT_THUMBSTICK:
return "Right Thumbstick Button";
break;
case SH_CONTROLLERCODE::LEFT_SHOULDER:
return "Left Shoulder Button";
break;
case SH_CONTROLLERCODE::RIGHT_SHOULDER:
return "Right Shoulder Button";
break;
case SH_CONTROLLERCODE::A:
return "A Button";
break;
case SH_CONTROLLERCODE::B:
return "B Button";
break;
case SH_CONTROLLERCODE::X:
return "X Button";
break;
case SH_CONTROLLERCODE::Y:
return "Y Button";
break;
case SH_CONTROLLERCODE::LEFT_TRIGGER:
return "Left Trigger";
break;
case SH_CONTROLLERCODE::RIGHT_TRIGGER:
return "Right Trigger";
break;
case SH_CONTROLLERCODE::LEFT_THUMBSTICK_X:
return "Left Thumbstick Horizontal";
break;
case SH_CONTROLLERCODE::LEFT_THUMBSTICK_Y:
return "Left Thumbstick Vertical";
break;
case SH_CONTROLLERCODE::RIGHT_THUMBSTICK_X:
return "Right Thumbstick Horizontal";
break;
case SH_CONTROLLERCODE::RIGHT_THUMBSTICK_Y:
return "Right Thumbstick Vertical";
break;
}
}
//The Binding File format presently goes as such:
/*
* Binding count
@ -680,7 +1149,7 @@ namespace SHADE
digitalInput = true;
}
if (std::abs(newValue) > std::abs(largestMagnitude))
largestMagnitude = newValue * data.sensitivity * (data.inverted ? -1.0 : 1.0);
largestMagnitude = newValue * (data.inverted ? -1.0 : 1.0);
}
}
@ -696,7 +1165,7 @@ namespace SHADE
digitalInput = true;
}
if (std::abs(newValue) > std::abs(largestMagnitude))
largestMagnitude = -newValue * data.sensitivity * (data.inverted ? -1.0 : 1.0);
largestMagnitude = -newValue * (data.inverted ? -1.0 : 1.0);
}
}
@ -740,21 +1209,23 @@ namespace SHADE
if (data.value > 1.0) data.value = 1.0;
else if (data.value < -1.0) data.value = -1.0;
}
//If analog input was in,
//sensitivity is instead used as a multiplier
//If analog input was in, raw value taken
else
{
data.value = largestMagnitude * data.sensitivity;
data.value = largestMagnitude;
if (data.value > 1.0) data.value = 1.0;
else if (data.value < -1.0) data.value = -1.0;
}
if (data.snap) //Snapping
{
if (data.value > 0.0 && data.negativeInputHeld)
data.value = 0.0;
if (data.value < 0.0 && data.positiveInputHeld)
data.value = 0.0;
if (digitalInput) //Only for digital inputs
{
if (data.value > 0.0 && data.negativeInputHeld)
data.value = 0.0;
if (data.value < 0.0 && data.positiveInputHeld)
data.value = 0.0;
}
}
}
}
@ -936,11 +1407,11 @@ namespace SHADE
{
return 0.0;
}
else if (bindings[bindingName].positiveInputHeld)
else if (GetBindingAxis(bindingName, cNum) > 0.0)
{
return 1.0;
}
else if (bindings[bindingName].negativeInputHeld)
else if (GetBindingAxis(bindingName, cNum) < 0.0)
{
return -1.0;
}

View File

@ -363,6 +363,7 @@ namespace SHADE
//Speed in units per second that the axis will move toward target value for digital
//For mouse movement / scrolling, serves as multiplier
//Irrelevant for other analog inputs
double sensitivity = 1.0;
//If enabled, axis value will reset to zero when pressing a button
@ -415,6 +416,12 @@ namespace SHADE
return controllerInUse;
}
//Get the name of key code
static std::string GetKeyCodeName(SH_KEYCODE const keyCode) noexcept;
//Get the name of controller code
static std::string GetControllerCodeName(SH_CONTROLLERCODE const controllerCode) noexcept;
//For testing purposes
//static void PrintCurrentState() noexcept;
@ -738,6 +745,16 @@ namespace SHADE
return bindings.erase(bindingName);
}
//Rename a binding
static inline void RenameBinding(std::string const& oldBindingName, std::string const& newBindingName) noexcept
{
//https://stackoverflow.com/a/44883472
//https://en.cppreference.com/w/cpp/container/map/extract
auto nodeHandler = bindings.extract(oldBindingName);
nodeHandler.key() = newBindingName;
bindings.insert(std::move(nodeHandler));
}
//Clears all bindings from the list
static inline void ClearBindings() noexcept
{
@ -809,7 +826,7 @@ namespace SHADE
//Get the sensitivity of the binding
//Serves as a multiplier for mouse movement/scrolling
//For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative
//For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1
//Irrelevant for other analog inputs
static inline double GetBindingSensitivity(std::string const& bindingName)
{
return bindings[bindingName].sensitivity;
@ -818,7 +835,7 @@ namespace SHADE
//Set the sensitivity of the binding
//Serves as a multiplier for mouse movement/scrolling
//For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative
//For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1
//Irrelevant for other analog inputs
static inline void SetBindingSensitivity(std::string const& bindingName, double const newValue)
{
bindings[bindingName].sensitivity = newValue;
@ -984,8 +1001,6 @@ namespace SHADE
//Get the axis value of binding, between -1 and 1 for non-mouse movement/wheel
//For mouse movement/wheel, it won't be between -1 and 1. It will also be multiplied by sensitivity
//To avoid interference between mouse movement/wheel and keyboard/mouse/controller input,
//Set mouseXBound, mouseYBound and mouseScrollBound to false
//controllerNumber is not used
static double GetBindingAxis(std::string const& bindingName, size_t controllerNumber = 0) noexcept;