From 71572381f71fbde71da73c3656a7174f23d329ff Mon Sep 17 00:00:00 2001 From: mushgunAX Date: Fri, 20 Jan 2023 14:00:24 +0800 Subject: [PATCH] Progress on input bindings in editor --- .../InputBindings/SHInputBindingsPanel.cpp | 184 +++++++++++++++++- .../InputBindings/SHInputBindingsPanel.h | 2 + .../EditorWindow/SHEditorWindowIncludes.h | 3 +- SHADE_Engine/src/Editor/SHEditor.cpp | 1 + SHADE_Engine/src/Input/SHInputManager.h | 10 + 5 files changed, 198 insertions(+), 2 deletions(-) diff --git a/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.cpp b/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.cpp index f05440dc..5dc9e17a 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.cpp @@ -5,11 +5,193 @@ namespace SHADE { + //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 (Begin()) + if (SHEditorWindow::Begin()) { + //Binding count + ImGui::Text("Binding Count: %d", 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); + } + 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()) + { + ImGui::Separator(); + std::string bindingName = binding.first; //Binding name to use as argument when modifying binding values + + //Non-modifiable binding name + ImGui::Text("Binding Name: %s", binding.first); + std::string bindingModifiedName; + //MAKE THE INPUTTEXT WORK + ImGui::InputText(labelConcat("##bindingModifyName", entryNumber).c_str(), &bindingModifiedName); + ImGui::SameLine(); + if (ImGui::Button(labelConcat("Rename##bindingRename", entryNumber).c_str())) + { + SHLOGV_CRITICAL("\"{0}\" > \"{1}\"", bindingName, bindingModifiedName); + SHInputManager::RenameBinding(bindingName, bindingModifiedName); + } + + //Modifiable binding name + /*size_t constexpr maxLen = 256; //Maximum binding name length + static char bindingNameCStr[maxLen]; + std::copy(bindingName.begin(), + bindingName.length() >= maxLen ? + bindingName.begin() + maxLen : + bindingName.end(), //Does not take into account null terminator + bindingNameCStr); + bindingNameCStr[bindingName.length()] = '\0'; //Null terminator + + //First character + char firstChar = bindingNameCStr[0]; + //If the input text is modified, modify the binding's name + if (ImGui::InputText("Binding Name", bindingNameCStr, maxLen)) + { + //Ensure name does not get shorter than 1 character long + if (std::strlen(bindingNameCStr) < 1) + bindingNameCStr[0] = firstChar; + //Rename binding in the input manager + SHInputManager::RenameBinding(bindingName, std::string{ bindingNameCStr }); + bindingName = std::string{ bindingNameCStr }; + } + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::Text("The name of this binding"); + ImGui::EndTooltip(); + }*/ + + //Binding value test + //TODO + ImGui::Text("Value"); + + + //Binding Type Combo Box + int bindingType = static_cast(SHInputManager::GetBindingType(bindingName)); + if (ImGui::Combo(labelConcat("Input Type##", entryNumber).c_str(), &bindingType, "Keyboard / Mouse Buttons / Controller\0Mouse Horizontal\0Mouse Vertical\0Mouse Scroll Wheel")) + SHInputManager::SetBindingType(bindingName, static_cast(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(bindingName); + if (ImGui::Checkbox(labelConcat("Inverted##", entryNumber).c_str(), &bindingInvert)) + SHInputManager::SetBindingInverted(bindingName, 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(bindingName); + if (ImGui::InputDouble(labelConcat("Sensitivity##", entryNumber).c_str(), &bindingSensitivity)) + SHInputManager::SetBindingSensitivity(bindingName, 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::EndTooltip(); + } + + //Below this section is only for KB/M type bindings + //Not relevant for mouse movement and scrolling + if (SHInputManager::GetBindingType(bindingName) == SHInputManager::SH_BINDINGTYPE::KB_MB_CONTROLLER) + { + //Dead + float bindingDead = static_cast(SHInputManager::GetBindingDead(bindingName)); + if (ImGui::SliderFloat(labelConcat("Deadzone##", entryNumber).c_str(), &bindingDead, 0.0f, 1.0f)) + SHInputManager::SetBindingDead(bindingName, static_cast(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(bindingName); + if (ImGui::InputDouble(labelConcat("Gravity##", entryNumber).c_str(), &bindingGravity)) + SHInputManager::SetBindingGravity(bindingName, static_cast(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(bindingName); + if (ImGui::Checkbox(labelConcat("Snap##", entryNumber).c_str(), &bindingSnap)) + SHInputManager::SetBindingSnap(bindingName, 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(); + } + + //Positive key codes + + //Negative key codes + + //Positive controller codes + + //Negative controller codes + } + + ++entryNumber; //Next entry + } } + ImGui::End(); + } + + void SHInputBindingsPanel::Exit() + { + SHEditorWindow::Exit(); } } \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.h b/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.h index c29a68c5..db2ec0c8 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.h +++ b/SHADE_Engine/src/Editor/EditorWindow/InputBindings/SHInputBindingsPanel.h @@ -10,6 +10,8 @@ namespace SHADE public: SHInputBindingsPanel() : SHEditorWindow("Input Bindings Panel", ImGuiWindowFlags_MenuBar) {} + void Init() override; void Update() override; + void Exit() override; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h index 9aad6ede..290ed622 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h +++ b/SHADE_Engine/src/Editor/EditorWindow/SHEditorWindowIncludes.h @@ -6,4 +6,5 @@ #include "ViewportWindow/SHEditorViewport.h" //Editor Viewport #include "AssetBrowser/SHAssetBrowser.h" //Asset Browser #include "MaterialInspector/SHMaterialInspector.h" //Material Inspector -#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel \ No newline at end of file +#include "ColliderTagPanel/SHColliderTagPanel.h" //Collider Tag Panel +#include "InputBindings/SHInputBindingsPanel.h" //Input Bindings \ No newline at end of file diff --git a/SHADE_Engine/src/Editor/SHEditor.cpp b/SHADE_Engine/src/Editor/SHEditor.cpp index 2b8ddbb5..b99d9f32 100644 --- a/SHADE_Engine/src/Editor/SHEditor.cpp +++ b/SHADE_Engine/src/Editor/SHEditor.cpp @@ -104,6 +104,7 @@ namespace SHADE SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); + SHEditorWindowManager::CreateEditorWindow(); SHEditorWindowManager::CreateEditorWindow(); diff --git a/SHADE_Engine/src/Input/SHInputManager.h b/SHADE_Engine/src/Input/SHInputManager.h index 680035c3..5698f4c1 100644 --- a/SHADE_Engine/src/Input/SHInputManager.h +++ b/SHADE_Engine/src/Input/SHInputManager.h @@ -738,6 +738,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 {