diff --git a/CMakeLists.txt b/CMakeLists.txt index b7c8d45..de4c1c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,6 +89,9 @@ target_compile_definitions(Aurora PUBLIC GLSLANG_COMPILER=1) if(WIN32) target_link_libraries(Aurora PRIVATE opengl32 gdi32) endif() +if(UNIX) + target_link_libraries(Aurora PRIVATE GL) +endif() target_link_libraries(Aurora PUBLIC glad glfw glm nlohmann_json TracyClient ImGui TracyClient assimp stb_utils) target_link_libraries(Aurora PUBLIC RmlCore RmlDebugger) diff --git a/lib/glfw b/lib/glfw index 6876cf8..4cb3687 160000 --- a/lib/glfw +++ b/lib/glfw @@ -1 +1 @@ -Subproject commit 6876cf8d7e0e70dc3e4d7b0224d08312c9f78099 +Subproject commit 4cb36872a5fe448c205d0b46f0e8c8b57530cfe0 diff --git a/lib/imgui/CMakeLists.txt b/lib/imgui/CMakeLists.txt index 4744e6c..3e24dd1 100644 --- a/lib/imgui/CMakeLists.txt +++ b/lib/imgui/CMakeLists.txt @@ -17,4 +17,7 @@ target_link_libraries(ImGui glfw glad) if(WIN32) target_link_libraries(ImGui gdi32 opengl32 imm32) -endif() \ No newline at end of file +endif() +if(UNIX) + target_link_libraries(ImGui GL) +endif() diff --git a/src/Aurora/App/ISystemWindow.hpp b/src/Aurora/App/ISystemWindow.hpp index 209fec2..334b727 100644 --- a/src/Aurora/App/ISystemWindow.hpp +++ b/src/Aurora/App/ISystemWindow.hpp @@ -11,10 +11,14 @@ #include "CursorMode.hpp" -#include "Input/IManager.hpp" - namespace Aurora { + namespace Input + { + class IManager; + typedef std::shared_ptr IManager_ptr; + } + struct WindowDefinition { int Width; diff --git a/src/Aurora/App/Input/Binding.cpp b/src/Aurora/App/Input/Binding.cpp deleted file mode 100644 index b982955..0000000 --- a/src/Aurora/App/Input/Binding.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "Binding.hpp" - -namespace Aurora::Input -{ - -} diff --git a/src/Aurora/App/Input/Binding.hpp b/src/Aurora/App/Input/Binding.hpp deleted file mode 100644 index 53a317e..0000000 --- a/src/Aurora/App/Input/Binding.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include "Aurora/Core/Common.hpp" - -#include -#include - -namespace Aurora::Input -{ - AU_CLASS(Manager); -} - -namespace Aurora::Input -{ - AU_CLASS(IManager); - - AU_CLASS(Binding) - { - friend class IManager; - friend class Manager; - - protected: - Binding(std::set categories, std::string name, bool active) - : m_Categories(std::move(categories)), m_InputName(std::move(name)), m_Active(active) - { - } - [[nodiscard]] inline static Binding_ptr make_shared( const std::set& categories, const std::string& name, bool active) - { - return Binding_ptr(new Binding(categories, name, active)); - } - - protected: - std::set m_Categories; - std::string m_InputName; - public: - [[nodiscard]] inline const std::set& Categories() const noexcept { return m_Categories; } - [[nodiscard]] inline const std::string& InputName() const noexcept { return m_InputName; } - - protected: - double m_ValueCurrent = 0; - double m_ValuePrevious = 0; - bool m_Active; - /// Axis: abs <= this is considered 0 - /// Button: value <= this is considered to be released - /// Must be >= 0, otherwise won't work correctly. - double m_DeadZone = 0.2; - /// How long is this input held? - /// Checks `m_ValueCurrent >= m_DeadZone` - double m_HeldTime = 0; - - public: - /// Whenever current Active Category is one of categories assigned for this mapping - [[nodiscard]] inline bool IsActive() const noexcept { return m_Active; } - - public: - [[nodiscard]] inline double RawValue() const noexcept { return m_ValueCurrent; } - [[nodiscard]] inline double RawValue_Previous() const noexcept { return m_ValuePrevious; } - - // Axis - public: - /// Axis: Value between -1 and 1 - /// Button: Value between 0 (released) and 1 (pressed) - [[nodiscard]] inline double Value() const noexcept { return std::abs(m_ValueCurrent) <= m_DeadZone ? 0.0 : std::clamp(m_ValueCurrent, -1.0, 1.0); } - /// Same as `Value` but looks at previous tick - [[nodiscard]] inline double Value_Previous() const noexcept { return std::abs(m_ValuePrevious) <= m_DeadZone ? 0.0 : std::clamp(m_ValuePrevious, -1.0, 1.0); } - - // Button - public: - /// Is the button currently held down? - [[nodiscard]] inline bool IsPressed() const noexcept { return m_ValueCurrent > m_DeadZone; } - /// Was the button held down last tick? - [[nodiscard]] inline bool WasPressed() const noexcept { return m_ValuePrevious > m_DeadZone; } - /// Is current tick the one when the button was pressed? - [[nodiscard]] inline bool IsDown() const noexcept { return IsPressed() && !WasPressed(); } - /// Is current tick the one when the button was released? - [[nodiscard]] inline bool IsUp() const noexcept { return !IsPressed() && WasPressed(); } - [[nodiscard]] inline double HeldTime() const noexcept { return m_HeldTime; }; - }; -} diff --git a/src/Aurora/App/Input/GLFW/Manager.cpp b/src/Aurora/App/Input/GLFW/Manager.cpp index 93d8c7f..d227c87 100644 --- a/src/Aurora/App/Input/GLFW/Manager.cpp +++ b/src/Aurora/App/Input/GLFW/Manager.cpp @@ -3,21 +3,9 @@ #include "Manager.hpp" #include -#include namespace Aurora::Input { -#ifdef AU_INPUT_GAMEPAD_VISUAL_FORCE -# define FUNC_TRY_INPUT_TYPE_GAMEPAD() -#else -# define FUNC_TRY_INPUT_TYPE_GAMEPAD() \ - /* Too long from last Gamepad input -> switch to Keyboard+Mouse */\ - if(m_TimeFromLastGamepadInput >= MaxTimeFromLastGamepadInput && InputType_IsGamepad(CurrentInputType()))\ - {\ - CurrentInputType(InputType::KeyboardAndMouse);\ - } -#endif - void Manager::OnKeyChange(int keyCode, int scanCode, bool down) { if(keyCode != GLFW_KEY_UNKNOWN && keyCode >= 0) @@ -27,17 +15,17 @@ namespace Aurora::Input AU_LOG_ERROR("Keycode ", keyCode, " is too high"); return; } - m_KeyCodes[keyCode] = down; + CurrentKeys().KeyCodes[keyCode] = down; AU_DEBUG_COUT_INPUT("keyboard_code_" << keyCode, (down ? "down" : "up")); } else if(scanCode != GLFW_KEY_UNKNOWN && scanCode >= 0) { - if(scanCode >= MaxKeyCount) [[unlikely]] + if(scanCode >= MaxKeyScanCount) [[unlikely]] { AU_LOG_ERROR("Keycode ", keyCode, " is too high"); return; } - m_ScanCodes[scanCode] = down; + CurrentKeys().ScanCodes[scanCode] = down; AU_DEBUG_COUT_INPUT("keyboard_scancode_" << keyCode, (down ? "down" : "up")); } else @@ -45,35 +33,30 @@ namespace Aurora::Input AU_LOG_ERROR("OnKeyChange with no keyCode and scanCode, why?"); return; } - - FUNC_TRY_INPUT_TYPE_GAMEPAD(); } void Manager::OnMouseMove(const glm::dvec2& newPosition) { bool cursorLocked = IsCursorLocked(); - auto windowSize = m_GlfwWindow->GetSize(); if(cursorLocked) { // Hidden glm::dvec2 change = newPosition - m_CursorPosition_Prev; - m_CursorChange_Pixels = change * CursorSensitivity(); - m_CursorChange_Percentage = { change.x / windowSize.x, change.y / windowSize.y }; + m_CursorChange = change * CursorSensitivity(); + m_CursorPositionChange = change; // Visible - m_CursorPosition_Pixels = newPosition; - m_CursorPosition_Percentage = { newPosition.x / windowSize.x, newPosition.y / windowSize.y }; + m_CursorPosition = {}; } else // !cursorLocked { // Hidden - m_CursorChange_Pixels = {0, 0}; - m_CursorChange_Percentage = {0, 0}; + m_CursorChange = {}; + m_CursorPositionChange = {}; // Visible - m_CursorPosition_Pixels = newPosition; - m_CursorPosition_Percentage = { newPosition.x / windowSize.x, newPosition.y / windowSize.y }; + m_CursorPosition = newPosition; } m_CursorPosition_Tmp = newPosition; @@ -81,69 +64,30 @@ namespace Aurora::Input AU_DEBUG_COUT_INPUT("mouse_y", m_CursorChange_Pixels.y); } - void Manager::OnJoystickConnectChange(Manager::JoystickIndex_t joyIndex, bool connected) + void Manager::OnMouseButton(int buttonCode, bool down) { - static_assert(GLFW_JOYSTICK_1 == 0); - static_assert(GLFW_JOYSTICK_2 == 1); - static_assert(GLFW_JOYSTICK_3 == 2); - static_assert(GLFW_JOYSTICK_4 == 3); - static_assert(GLFW_JOYSTICK_5 == 4); - static_assert(GLFW_JOYSTICK_6 == 5); - static_assert(GLFW_JOYSTICK_7 == 6); - static_assert(GLFW_JOYSTICK_8 == 7); - static_assert(GLFW_JOYSTICK_9 == 8); - static_assert(GLFW_JOYSTICK_10 == 9); - static_assert(GLFW_JOYSTICK_11 == 10); - static_assert(GLFW_JOYSTICK_12 == 11); - static_assert(GLFW_JOYSTICK_13 == 12); - static_assert(GLFW_JOYSTICK_14 == 13); - static_assert(GLFW_JOYSTICK_15 == 14); - static_assert(GLFW_JOYSTICK_16 == 15); - static_assert(GLFW_JOYSTICK_LAST == GLFW_JOYSTICK_16); - - static_assert(MaxJoystickCount >= 0); - static_assert(GLFW_JOYSTICK_LAST < MaxJoystickCount); // last index < count - - if(joyIndex < 0 || joyIndex >= MaxJoystickCount) - { - AU_LOG_INFO("Joystick at index ", joyIndex, (connected ? "connected" : "disconnected"), " but index is not valid"); - return; - } + static_assert(GLFW_MOUSE_BUTTON_LEFT == 0); // LMB + static_assert(GLFW_MOUSE_BUTTON_RIGHT == 1); // RMB + static_assert(GLFW_MOUSE_BUTTON_MIDDLE == 2); // MMB -#ifdef DEBUG - if(connected) { - AU_LOG_INFO("Joystick ", joyIndex, " ", "connected and ", (glfwJoystickIsGamepad(joyIndex) ? "has a mapping" : "is not a valid gamepad")); - } else { - AU_LOG_INFO("Joystick ", joyIndex, " ", "disconnected"); - } -#endif - - if(connected) + if(buttonCode != GLFW_KEY_UNKNOWN && buttonCode >= 0) { - // Same as if gamepad button was pressed - // Will switch `CurrentInputType` to correct gamepad - m_TimeFromLastGamepadInput = 0; + if(buttonCode >= MaxMouseButtonCount) [[unlikely]] + { + AU_LOG_ERROR("Mouse button ", buttonCode, " is too high"); + return; + } + CurrentKeys().MouseButtons[buttonCode] = down; + + AU_DEBUG_COUT_INPUT("mouse_" << buttonCode, (down ? "down" : "up")); } else { -#ifndef AU_INPUT_GAMEPAD_VISUAL_FORCE - bool hasGamepad = false; - for(JoystickIndex_t ji = 0; ji < MaxJoystickCount; ji++) - { - if(!glfwJoystickIsGamepad(ji)) - continue; - hasGamepad = true; - break; - } - if(!hasGamepad) - { - m_TimeFromLastGamepadInput = MaxTimeFromLastGamepadInput; - FUNC_TRY_INPUT_TYPE_GAMEPAD(); - } -#endif + AU_LOG_ERROR("OnMouseButton with invalid buttonCode, why?"); } } +#pragma region GLFW Key Map std::string Manager::GetKeyFromGlfw(int glfwKey, int glfwScanCode) const noexcept { switch(glfwKey) @@ -398,6 +342,7 @@ namespace Aurora::Input { "alt", GLFW_KEY_LEFT_ALT }, { "super", GLFW_KEY_LEFT_SUPER } }; +#pragma endregion [[nodiscard]] inline bool GetGlfwKey_Keyboard(const std::string& key, int* keyCode, int* scanCode) { @@ -440,16 +385,16 @@ namespace Aurora::Input { if(keyCode != GLFW_KEY_UNKNOWN) { - if(keyCode < m_KeyCodes.size()) - return m_KeyCodes[keyCode]; + if(keyCode < CurrentKeys().KeyCodes.size()) + return CurrentKeys().KeyCodes[keyCode]; else return false; } if(scanCode != GLFW_KEY_UNKNOWN) { - if(scanCode < m_ScanCodes.size()) - return m_ScanCodes[scanCode]; + if(scanCode < CurrentKeys().ScanCodes.size()) + return CurrentKeys().ScanCodes[scanCode]; else return false; } @@ -465,8 +410,8 @@ namespace Aurora::Input try { int index = std::stoi(key.data() + 6); - if(index < m_MouseButtons.size()) - return m_MouseButtons[index]; + if(index < CurrentKeys().MouseButtons.size()) + return CurrentKeys().MouseButtons[index]; else return false; } @@ -478,144 +423,10 @@ namespace Aurora::Input return false; } - // Gamepad - if(key.starts_with("gamepad_")) - { - throw std::runtime_error("Gamepad not implemented"); - } - return false; } - void Manager::Update(double delta) - { - m_TimeFromLastGamepadInput += delta; - for(JoystickIndex_t i = 0; i < MaxJoystickCount; i++) - { -#ifdef AU_DEBUG_INPUT - auto old = m_Gamepads[i]; -#endif - if(glfwGetGamepadState(i, &m_Gamepads[i])) - { - for(std::size_t bi = 0; bi <= GLFW_GAMEPAD_BUTTON_LAST; bi++) - { - if(m_Gamepads[i].buttons[bi]) - { - m_TimeFromLastGamepadInput = 0; - break; - } - } - } - else - m_Gamepads[i] = {}; -#ifdef AU_DEBUG_INPUT -# define AU_DEBUG_COUT_INPUT_GAMEPAD(index, buttonName, glfwButton) \ - if(old.buttons[glfwButton] != m_Gamepads[index].buttons[glfwButton]) \ - AU_LOG_INFO("Gamepad ", static_cast(index), ", " << buttonName, ": ", static_cast(m_Gamepads[index].buttons[glfwButton])); -# define AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(index, axisName, glfwAxis) \ - if(old.axes[glfwAxis] != m_Gamepads[index].axes[glfwAxis]) \ - AU_LOG_INFO("Gamepad ", static_cast(index), ", ", axisName, ": ", static_cast(m_Gamepads[index].axes[glfwAxis])); - - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "a", GLFW_GAMEPAD_BUTTON_A); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "b", GLFW_GAMEPAD_BUTTON_B); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "x", GLFW_GAMEPAD_BUTTON_X); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "y", GLFW_GAMEPAD_BUTTON_Y); - - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "back", GLFW_GAMEPAD_BUTTON_BACK); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "forward", GLFW_GAMEPAD_BUTTON_START); - - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "l1", GLFW_GAMEPAD_BUTTON_LEFT_BUMPER); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "r1", GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER); - - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "dpad_up", GLFW_GAMEPAD_BUTTON_DPAD_UP); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "dpad_down", GLFW_GAMEPAD_BUTTON_DPAD_DOWN); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "dpad_left", GLFW_GAMEPAD_BUTTON_DPAD_LEFT); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "dpad_right", GLFW_GAMEPAD_BUTTON_DPAD_RIGHT); - - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "stick_left", GLFW_GAMEPAD_BUTTON_LEFT_THUMB); - AU_DEBUG_COUT_INPUT_GAMEPAD(i, "stick_right", GLFW_GAMEPAD_BUTTON_RIGHT_THUMB); - - AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(i, "stick_left_x", GLFW_GAMEPAD_AXIS_LEFT_X); - AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(i, "stick_left_y", GLFW_GAMEPAD_AXIS_LEFT_Y); - - AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(i, "stick_right_x", GLFW_GAMEPAD_AXIS_RIGHT_X); - AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(i, "stick_right_y", GLFW_GAMEPAD_AXIS_RIGHT_Y); - - AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(i, "l2", GLFW_GAMEPAD_AXIS_LEFT_TRIGGER); - AU_DEBUG_COUT_INPUT_GAMEPAD_AXIS(i, "r2", GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER); -#endif - } - if(m_TimeFromLastGamepadInput > 0 && m_TimeFromLastGamepadInput < MaxTimeFromLastGamepadInput && !InputType_IsGamepad(CurrentInputType())) - { - CurrentInputType(IsPictogramControllerConnected() ? InputType::Gamepad_Pictogram : InputType::Gamepad_ABXY); - } - - auto itConfigs = m_Configurations.find(GetActiveCategory()); - if(itConfigs == m_Configurations.end()) - { - // No active actions - } - else // itConfigs != m_Configurations.end() - { - const auto& currentActions = itConfigs->second; - - /// all used keys - std::set keys; - for(const auto& ca : currentActions) - for(const auto& keyInvert : ca.second) - keys.emplace(keyInvert.first); - - std::unordered_map currentValues; - double anyInputValue = 0; - for(const Key_t& key : keys) - { - double val = GetValue(key); - currentValues[key] = val; - anyInputValue += val; - } - - for(const Binding_ptr& binding : m_KnownBindings) - { - if(!binding->m_Active) - continue; - - binding->m_ValuePrevious = binding->m_ValueCurrent; - - if(binding->m_InputName.empty()) // any input - { - binding->m_ValueCurrent = anyInputValue; - binding->m_HeldTime = 0; - } - else - { - auto itCurrentAction = currentActions.find(binding->m_InputName); - if(itCurrentAction == currentActions.end()) // No config for the action - { - AU_LOG_WARNING("No configuration for action ", binding->m_InputName); - continue; - } - - double value = 0; - - for(const auto& keyInvert : itCurrentAction->second) - { - auto itKey = currentValues.find(keyInvert.first); - value += itKey == currentValues.end() ? 0.0 : (itKey->second * (keyInvert.second ? -1 : 1)); - } - - if(std::abs(binding->m_ValueCurrent) <= binding->m_DeadZone) - binding->m_HeldTime = 0; - - binding->m_ValueCurrent = value; - - if(std::abs(binding->m_ValueCurrent) > binding->m_DeadZone) - binding->m_HeldTime += delta; - } - } - } - } - - double Manager::GetValue(const IManager::Key_t& name) + double Manager::GetValue(const IManager::Key_t& name, int keysIndex) { // Keyboard { @@ -624,16 +435,16 @@ namespace Aurora::Input { if(keyCode != GLFW_KEY_UNKNOWN) { - if(keyCode < m_KeyCodes.size()) - return m_KeyCodes[keyCode] ? 1.0 : 0.0; + if(keyCode < m_CurrentKeys[keysIndex].KeyCodes.size()) + return m_CurrentKeys[keysIndex].KeyCodes[keyCode] ? 1.0 : 0.0; else return 0.0; } if(scanCode != GLFW_KEY_UNKNOWN) { - if(scanCode < m_ScanCodes.size()) - return m_ScanCodes[scanCode] ? 1.0 : 0.0; + if(scanCode < m_CurrentKeys[keysIndex].ScanCodes.size()) + return m_CurrentKeys[keysIndex].ScanCodes[scanCode] ? 1.0 : 0.0; else return 0.0; } @@ -647,9 +458,9 @@ namespace Aurora::Input if(name.starts_with("mouse_")) { if(name == "mouse_x") - return m_CursorChange_Pixels.x; + return m_CursorChange.has_value() ? m_CursorChange.value().x : 0.0; if(name == "mouse_y") - return m_CursorChange_Pixels.y; + return m_CursorChange.has_value() ? m_CursorChange.value().y : 0.0; if(name == "mouse_wheel") return m_ScrollWheelChange.y; @@ -659,8 +470,8 @@ namespace Aurora::Input try { int index = std::stoi(name.data() + 6); - if(index < m_MouseButtons.size()) - return m_MouseButtons[index] ? 1.0 : 0.0; + if(index < m_CurrentKeys[keysIndex].MouseButtons.size()) + return m_CurrentKeys[keysIndex].MouseButtons[index] ? 1.0 : 0.0; else return 0.0; } @@ -672,226 +483,15 @@ namespace Aurora::Input return 0.0; } - // Gamepad - if(name.starts_with("gamepad_")) - { - static const std::size_t indexStart = 8; - if(name.size() < indexStart + 2) - return 0.0; // Not enough characters for `gamepad_*_` - - std::size_t secondIndex = name.find('_', indexStart); - if(secondIndex == std::string::npos) - return 0.0; // No second underscore - - if(name.size() <= secondIndex + 1) - return 0.0; - std::string suffix = name.substr(secondIndex + 1); - if(suffix.empty()) - return 0.0; - - int joyIndex; - try - { - joyIndex = std::stol(name.substr(indexStart, secondIndex - indexStart)); - } - catch(...) - { - return 0.0; - } - if(joyIndex < 0 || joyIndex >= MaxJoystickCount) - return 0.0; - - auto& joyState = m_Gamepads[joyIndex]; - - if(suffix.starts_with("stick_")) - { - if(suffix == "stick_left") - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_LEFT_THUMB] ? 1.0 : 0.0; - } - else if(suffix == "stick_right") - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_THUMB] ? 1.0 : 0.0; - } - else if(suffix == "stick_left_x") - { - return joyState.axes[GLFW_GAMEPAD_AXIS_LEFT_X]; - } - else if(suffix == "stick_left_y") - { - return joyState.axes[GLFW_GAMEPAD_AXIS_LEFT_Y]; - } - else if(suffix == "stick_right_x") - { - return joyState.axes[GLFW_GAMEPAD_AXIS_RIGHT_X]; - } - else if(suffix == "stick_right_y") - { - return joyState.axes[GLFW_GAMEPAD_AXIS_RIGHT_Y]; - } - else - return 0.0; - } - else if(suffix.starts_with("dpad_")) - { - if(suffix == "dpad_up") - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_DPAD_UP] ? 1.0 : 0.0; - } - else if(suffix == "dpad_down") - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_DPAD_DOWN] ? 1.0 : 0.0; - } - else if(suffix == "dpad_left") - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT] ? 1.0 : 0.0; - } - else if(suffix == "dpad_right") - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT] ? 1.0 : 0.0; - } - else - return 0.0; - } - else if(suffix[0] == 'l') - { - if(suffix.size() != 2) - return 0.0; - - if(suffix[1] == '1') - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_LEFT_BUMPER] ? 1.0 : 0.0; - } - else if(suffix[1] == '2') - { - return joyState.axes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER]; - } - else - return 0.0; - } - else if(suffix[0] == 'r') - { - if(suffix.size() != 2) - return 0.0; - - if(suffix[1] == '1') - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER] ? 1.0 : 0.0; - } - else if(suffix[1] == '2') - { - return joyState.axes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER]; - } - else - return 0.0; - } - else if(suffix.size() == 1) - { - if(suffix[0] == 'a') - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_A] ? 1.0 : 0.0; - } - else if(suffix[0] == 'b') - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_B] ? 1.0 : 0.0; - } - else if(suffix[0] == 'x') - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_X] ? 1.0 : 0.0; - } - else if(suffix[0] == 'y') - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_Y] ? 1.0 : 0.0; - } - else - return 0.0; - } - else if(suffix == "forward") // start - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_START] ? 1.0 : 0.0; - } - else if(suffix == "back") // select - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_BACK] ? 1.0 : 0.0; - } - else if(suffix == "guide") // home - { - return joyState.buttons[GLFW_GAMEPAD_BUTTON_GUIDE] ? 1.0 : 0.0; - } - else - { - AU_LOG_INFO("Unknown `GetValue` gamepad button/axis requested: ", name); - return 0.0; - } - } - AU_LOG_INFO("Unknown `GetValue` input requested: ", name); return 0.0; } - std::u8string Manager::GetKeyDisplayName(const IManager::Key_t& key) - { - throw std::runtime_error("Not Implemented"); - } - - std::u8string Manager::GetValueName(const IManager::Key_t& name) - { - throw std::runtime_error("Not Implemented"); - } - - void Manager::LoadGamepadConfig(const char* mappingContent) - { - if(mappingContent == nullptr) - return; - glfwUpdateGamepadMappings(mappingContent); - } - - void Manager::LoadGamepadConfig(std::istream& in) - { - std::ostringstream oss; - oss << in.rdbuf(); - - LoadGamepadConfig(oss.str()); - } - - void Manager::LoadGamepadConfig(const std::filesystem::path& mappingFile) - { - if(!std::filesystem::exists(mappingFile) || !std::filesystem::is_regular_file(mappingFile)) - throw std::runtime_error("File Not Found (or is not a file)"); -#ifdef DEBUG - if(mappingFile.filename() != "gamecontrollerdb.txt") - AU_LOG_WARNING("Requested loading of Gamepad Config from file '", mappingFile.filename(), "' but the file should be named 'gamecontrollerdb.txt'"); -#endif - - std::fstream in(mappingFile, std::ios_base::in); - if(!in.good()) - throw std::runtime_error("File Read Problem"); - - LoadGamepadConfig(in); - } - - bool Manager::IsPictogramControllerConnected() - { - for(JoystickIndex_t ji = 0; ji < MaxJoystickCount; ji++) - { - if(!glfwJoystickIsGamepad(ji)) - continue; - const std::string name = glfwGetGamepadName(ji); - if(name.starts_with("PS ") || name.find(" PS ") != std::string::npos) - return true; - if(name.starts_with("PlayStation ") || name.find(" PlayStation ") != std::string::npos) - return true; - if(name.starts_with("Play Station ") || name.find(" Play Station ") != std::string::npos) - return true; - } - return false; - } - bool Manager::ActiveCategory(const std::string &category) { bool changed = IManager::ActiveCategory(category); - // TODO: Change this is future, because this cancles continuous button held in cotegory transition + // TODO: Change this is future, because this cancels continuous button held in category transition // This fixed instant button call after category change // If you listening on same button in two different categories and then you // cahange category to the other, the callback will call the button in the set @@ -899,15 +499,58 @@ namespace Aurora::Input // So this prevent that // (This was made when you want to lock and unlock cursor in two different categories) // (When this wasn't here, it randomly set the cursor and when I hold it, it flicker the cursor) - if(changed) { - std::fill(m_KeyCodes.begin(), m_KeyCodes.end(), false); - std::fill(m_ScanCodes.begin(), m_ScanCodes.end(), false); - std::fill(m_MouseButtons.begin(), m_MouseButtons.end(), false); - std::fill(m_Gamepads.begin(), m_Gamepads.end(), GLFWgamepadstate{}); - } + if(changed) + Clear(); return changed; } + double Manager::GetAnalog(const IManager::Action_t& action) + { + const auto it_Configurations = m_Configurations.find(GetActiveCategory()); + if(it_Configurations == m_Configurations.end()) + return 0; + + const auto& actions = it_Configurations->second; + const auto it_Actions = actions.find(action); + if(it_Actions == actions.end()) + return 0; + + const auto& keys = it_Actions->second; + + double value = 0; + for(const auto& key : keys) + { + if(key.second) + value -= GetValue(key.first); + else + value += GetValue(key.first); + } + return glm::clamp(value, -1.0, 1.0); + } + + double Manager::GetAnalog_Prev(const IManager::Action_t& action) + { + const auto it_Configurations = m_Configurations.find(GetActiveCategory()); + if(it_Configurations == m_Configurations.end()) + return 0; + + const auto& actions = it_Configurations->second; + const auto it_Actions = actions.find(action); + if(it_Actions == actions.end()) + return 0; + + const auto& keys = it_Actions->second; + + double value = 0; + for(const auto& key : keys) + { + if(key.second) + value -= GetValue_Prev(key.first); + else + value += GetValue_Prev(key.first); + } + return glm::clamp(value, -1.0, 1.0); + } } #endif \ No newline at end of file diff --git a/src/Aurora/App/Input/GLFW/Manager.hpp b/src/Aurora/App/Input/GLFW/Manager.hpp index d85f65d..f048e12 100644 --- a/src/Aurora/App/Input/GLFW/Manager.hpp +++ b/src/Aurora/App/Input/GLFW/Manager.hpp @@ -9,10 +9,12 @@ #ifdef AU_DEBUG_INPUT # ifndef AU_DEBUG_COUT_INPUT -# define AU_DEBUG_COUT_INPUT(input, value) std::cout << input << ": " << value << std::endl; +# define AU_DEBUG_COUT_INPUT(input, value) std::cout << input << ": " << value << std::endl # endif #else -# define AU_DEBUG_COUT_INPUT(input, value) +# ifndef AU_DEBUG_COUT_INPUT +# define AU_DEBUG_COUT_INPUT(input, value) do {} while(false) +# endif #endif namespace Aurora::Input @@ -21,8 +23,7 @@ namespace Aurora::Input { friend class ::Aurora::GLFWWindow; protected: - explicit Manager(GLFWWindow* window) : IManager(), - m_GlfwWindow(window) + explicit Manager(GLFWWindow* window) : IManager(), m_GlfwWindow(window) { } @@ -33,38 +34,57 @@ namespace Aurora::Input GLFWWindow* m_GlfwWindow; public: - static const std::size_t MaxKeyCount = 1024; - static const std::size_t MaxMouseButtonCount = 256; - static const std::size_t MaxJoystickCount = 16; + static const std::size_t MaxKeyCount = 400; + static const std::size_t MaxKeyScanCount = 1; // This effectively disables scancodes = only known keys + static const std::size_t MaxMouseButtonCount = 16; private: //THINK What happens if I manage to press and release the key in single tick? (see Steam Input >> Button) - std::vector m_TextBuffer = {}; - std::array m_KeyCodes = {}; - std::array m_ScanCodes = {}; - std::array m_MouseButtons = {}; - std::array m_Gamepads = {}; + std::vector m_TextBuffer = {}; + struct KeyStates + { + std::array KeyCodes = {}; + std::array ScanCodes = {}; + std::array MouseButtons = {}; + + void Clear() + { + std::fill(KeyCodes.begin(), KeyCodes.end(), false); + std::fill(ScanCodes.begin(), ScanCodes.end(), false); + std::fill(MouseButtons.begin(), MouseButtons.end(), false); + } + }; + KeyStates m_CurrentKeys[2]; + int m_CurrentKeysIndex = 0; + inline KeyStates& CurrentKeys() { return m_CurrentKeys[m_CurrentKeysIndex]; } public: - typedef uint8_t JoystickIndex_t; [[nodiscard]] std::string GetKeyFromGlfw(int glfwKey, int glfwScanCode) const noexcept; + private: + void Clear() + { + m_TextBuffer.clear(); + m_ScrollWheelChange = {0, 0}; + + m_CursorChange = {0, 0}; + m_CursorPosition_Prev = m_CursorPosition_Tmp; + + CurrentKeys().Clear(); + } public: void PrePollEvents() { m_TextBuffer.clear(); m_ScrollWheelChange = {0, 0}; - m_CursorChange_Pixels = {0, 0}; - m_CursorChange_Percentage = {0, 0}; + m_CursorChange = {0, 0}; m_CursorPosition_Prev = m_CursorPosition_Tmp; + + m_CurrentKeysIndex = 1 - m_CurrentKeysIndex; // Toggles between 0 and 1 + m_CurrentKeys[m_CurrentKeysIndex] = m_CurrentKeys[1 - m_CurrentKeysIndex]; } - public: - /// Update value of all known bindings - /// Call after `PrePollEvents()` but before code reading data from `Binding` - void Update(double delta); - public: - void static LoadGamepadConfig(const char* mappingContent); - void static LoadGamepadConfig(const std::string& mappingContent) { return LoadGamepadConfig(mappingContent.c_str()); } - void static LoadGamepadConfig(std::istream& in); - void static LoadGamepadConfig(const std::filesystem::path& mappingFile); - public: + /// `Manager::PrePollEvents()` -> `glfwPollEvents()` -> `Manager::Update(...)` + void Update(double delta) + { + } + public: // GLFW Events void OnKeyChange(int keyCode, int scanCode, bool down); void OnTextInput(const std::u8string& utf8) { @@ -80,60 +100,30 @@ namespace Aurora::Input AU_DEBUG_COUT_INPUT("mouse_wheel_side", m_ScrollWheelChange.x); AU_DEBUG_COUT_INPUT("mouse_wheel", m_ScrollWheelChange.y); } - void OnMouseButton(int buttonCode, bool down) - { - static_assert(GLFW_MOUSE_BUTTON_LEFT == 0); // LMB - static_assert(GLFW_MOUSE_BUTTON_RIGHT == 1); // RMB - static_assert(GLFW_MOUSE_BUTTON_MIDDLE == 2); // MMB - - if(buttonCode != GLFW_KEY_UNKNOWN && buttonCode >= 0) - { - if(buttonCode >= MaxMouseButtonCount) [[unlikely]] - { - AU_LOG_ERROR("Mouse button ", buttonCode, " is too high"); - return; - } - m_MouseButtons[buttonCode] = down; - - AU_DEBUG_COUT_INPUT("mouse_" << buttonCode, (down ? "down" : "up")); - } - else - { - AU_LOG_ERROR("OnMouseButton with invalid buttonCode, why?"); - } - } - void OnJoystickConnectChange(JoystickIndex_t joyIndex, bool connected); + void OnMouseButton(int buttonCode, bool down); void OnFocusChange(bool focused) { - for(auto& binding : m_KnownBindings) - binding->m_ValueCurrent = 0; + Clear(); AU_DEBUG_COUT_INPUT("Focus changed", (focused ? "focused" : "not focused")); } - // Input Type Detection - private: - double m_TimeFromLastGamepadInput = MaxTimeFromLastGamepadInput; - public: - /// How many seconds to wait after gamepad input to switch back to Keyboard+Mouse - static constexpr double MaxTimeFromLastGamepadInput = 30; // 30s - static bool IsPictogramControllerConnected(); - // Cursor private: - glm::dvec2 m_CursorPosition_Tmp{}; - glm::dvec2 m_CursorPosition_Prev{}; - std::optional m_CursorPosition_Pixels = {}; - std::optional m_CursorPosition_Percentage = {}; - glm::dvec2 m_CursorChange_Pixels = {0, 0}; - glm::dvec2 m_CursorChange_Percentage = {0, 0}; + /// Helper variable for processing position of locked cursor, to work even when switching between locked and unlocked mode. + glm::dvec2 m_CursorPosition_Tmp = {}; //TODO Is really needed? + /// Position of the cursor during previous tick + glm::dvec2 m_CursorPosition_Prev = {}; + std::optional m_CursorPosition = {}; + std::optional m_CursorPositionChange = {}; + std::optional m_CursorChange = {}; + public: + [[nodiscard]] const std::optional& CursorPosition() const noexcept override { return m_CursorPosition; } + [[nodiscard]] glm::dvec2 CursorPositionChange() const noexcept override { return m_CursorPositionChange.has_value() ? m_CursorPositionChange.value() : glm::dvec2{0, 0}; } + [[nodiscard]] glm::dvec2 CursorChange() const noexcept override { return m_CursorChange.has_value() ? m_CursorChange.value() : glm::dvec2{0, 0}; } public: - [[nodiscard]] const std::optional& CursorPosition_Pixels() const noexcept override { return m_CursorPosition_Pixels; } - [[nodiscard]] const glm::dvec2& CursorChange_Pixels() const noexcept override { return m_CursorChange_Pixels; } - [[nodiscard]] const std::optional& CursorPosition_Percentage() const noexcept override { return m_CursorPosition_Percentage; } - [[nodiscard]] const glm::dvec2& CursorChange_Percentage() const noexcept override { return m_CursorChange_Percentage; } - [[nodiscard]] bool IsCursorLocked() const override { return m_GlfwWindow->GetCursorMode() != ECursorMode::Normal; } - void LockCursor(bool locked) const override { m_GlfwWindow->SetCursorMode(locked ? ECursorMode::Disabled : ECursorMode::Normal); } + [[nodiscard]] bool IsCursorLocked() const override { return m_GlfwWindow->GetCursorMode() != ECursorMode::Normal; } + void LockCursor(bool locked) const override { m_GlfwWindow->SetCursorMode(locked ? ECursorMode::Disabled : ECursorMode::Normal); } bool ActiveCategory(const std::string& category) override; @@ -141,20 +131,27 @@ namespace Aurora::Input private: glm::dvec2 m_ScrollWheelChange{}; public: - //TODO Public + glm::dvec2 Scrolling() override { return m_ScrollWheelChange; } - // Keys public: - [[nodiscard]] bool IsPressed (const Key_t& key) override; - [[nodiscard]] std::u8string GetKeyDisplayName(const Key_t& key) override; + const std::vector& GetTypedChars() override { return m_TextBuffer; } - // Axis + private: + double GetValue(const IManager::Key_t& name, int keysIndex); public: - [[nodiscard]] double GetValue (const Key_t& name) override; - [[nodiscard]] std::u8string GetValueName (const Key_t& name) override; + /// Get analog value between -1.0 and 1.0 + double GetValue (const IManager::Key_t& name) { return GetValue(name, m_CurrentKeysIndex); } + double GetValue_Prev(const IManager::Key_t& name) { return GetValue(name, 1 - m_CurrentKeysIndex); } + [[deprecated("Using `GetValue(...) > 0` should work better")]] + bool IsPressed(const IManager::Key_t& key); public: - const std::vector& GetTypedChars() override { return m_TextBuffer; } + double GetAnalog (const Action_t& action) override; + double GetAnalog_Prev(const Action_t& action); + public: + bool GetDigital (const Action_t& action) override { return GetAnalog(action) > 0; } + bool GetDigital_Pressed (const Action_t& action) override { return (GetAnalog(action) > 0) > (GetAnalog_Prev(action) > 0); } + bool GetDigital_Released(const Action_t& action) override { return (GetAnalog(action) > 0) < (GetAnalog_Prev(action) > 0); } }; } #endif \ No newline at end of file diff --git a/src/Aurora/App/Input/IManager.cpp b/src/Aurora/App/Input/IManager.cpp index e52456c..292d392 100644 --- a/src/Aurora/App/Input/IManager.cpp +++ b/src/Aurora/App/Input/IManager.cpp @@ -10,28 +10,6 @@ namespace Aurora::Input { static std::regex regex_binding_name = std::regex("^[a-z0-9_]+$"); // NOLINT(cert-err58-cpp) - Binding_ptr IManager::Binding(std::set categories, const std::string& action) - { - if(action.empty()) - throw std::runtime_error("No input name specified"); - bool anyButton = action == "*"; - if(!anyButton && !std::regex_match(action, regex_binding_name)) - throw std::runtime_error("Binding name is not valid"); - - - if(categories.empty()) - throw std::runtime_error("No category specified"); - bool anyCategory = categories.contains("*"); - if(anyCategory) - categories.clear(); - - bool active = anyCategory || categories.contains(m_ActiveCategory); - - Binding_ptr binding = Binding_ptr(new class Binding(categories, action, active)); - m_KnownBindings.emplace(binding); - return binding; - } - bool IManager::ActiveCategory(const std::string& category) // Setter { if(m_ActiveCategory == category) { @@ -39,22 +17,6 @@ namespace Aurora::Input } m_ActiveCategory = category; - - // Update `Active` of all bindings - for(auto& binding : m_KnownBindings) - { - if(binding->m_Categories.empty()) - binding->m_Active = true; - else - binding->m_Active = binding->m_Categories.contains(m_ActiveCategory); - - if(!binding->m_Active) - { - binding->m_ValueCurrent = 0; - binding->m_HeldTime = 0; - } - } - return true; } @@ -135,51 +97,4 @@ namespace Aurora::Input LoadConfig_JSON(j); } - - void IManager::CurrentInputType(InputType value) noexcept - { -#ifdef AU_INPUT_GAMEPAD_VISUAL_FORCE - if(!InputType_IsGamepad(value)) - value = ControllerType::Gamepad_ABXY; -#endif -#ifdef AU_INPUT_GAMEPAD_ABXY_FORCE - if(value != ControllerType::KeyboardAndMouse && value != ControllerType::Gamepad_ABXY) - value = ControllerType::Gamepad_ABXY; -#endif -#ifdef AU_INPUT_GAMEPAD_PICTOGRAM_FORCE - if(value != ControllerType::KeyboardAndMouse && value != ControllerType::Gamepad_Pictogram) - value = ControllerType::Gamepad_Pictogram; -#endif - m_InputType = value; - AU_LOG_INFO("Changed Current Input Type to ", to_string(value)); - } - - void IManager::LockedInputType(std::optional value) noexcept - { - if(value.has_value()) - { -#ifdef AU_INPUT_GAMEPAD_VISUAL_FORCE - if(value.value() == ControllerType::KeyboardAndMouse) - value = ControllerType::Gamepad_ABXY; -#endif -#ifdef AU_INPUT_GAMEPAD_ABXY_FORCE - if(value.value() != ControllerType::KeyboardAndMouse && value.value() != ControllerType::Gamepad_ABXY) - value = ControllerType::Gamepad_ABXY; -#endif -#ifdef AU_INPUT_GAMEPAD_PICTOGRAM_FORCE - if(value.value() != ControllerType::KeyboardAndMouse && value.value() != ControllerType::Gamepad_Pictogram) - value = ControllerType::Gamepad_Pictogram; -#endif - } - - m_LockedInputType = value; - -#ifdef DEBUG - if(value.has_value()) { - AU_LOG_INFO("Changed Locked Input Type to ", to_string(value.value())); - } else { - AU_LOG_INFO("Cleared Locked Input Type"); - } -#endif - } } diff --git a/src/Aurora/App/Input/IManager.hpp b/src/Aurora/App/Input/IManager.hpp index 835f757..8ca4284 100644 --- a/src/Aurora/App/Input/IManager.hpp +++ b/src/Aurora/App/Input/IManager.hpp @@ -10,44 +10,10 @@ #include #include -#include "Binding.hpp" - #include namespace Aurora::Input { - enum class InputType : uint8_t - { - KeyboardAndMouse = 0, - Gamepad_ABXY = 1, ///< Nintendo, XBox - Gamepad_Pictogram = 2 ///< PlayStation - }; - inline static bool InputType_IsGamepad(InputType type) noexcept - { - switch(type) - { - case InputType::Gamepad_ABXY: - case InputType::Gamepad_Pictogram: - return true; - default: - return false; - } - } - inline static std::string to_string(InputType type) - { - switch(type) - { - case InputType::KeyboardAndMouse: - return "keyboard_and_mouse"; - case InputType::Gamepad_ABXY: - return "gamepad_abxy"; - case InputType::Gamepad_Pictogram: - return "gamepad_pictograms"; - default: - throw std::runtime_error("Invalid value"); - } - } - AU_CLASS(IManager) { protected: @@ -59,70 +25,61 @@ namespace Aurora::Input typedef std::string Key_t; typedef std::string Action_t; typedef std::string Category_t; - typedef std::map> Actions_t; + typedef std::map UsedKeysInvertion_t; + typedef std::map Actions_t; protected: - std::map m_Configurations{}; + std::map m_Configurations = {}; public: void LoadConfig_JSON(const nlohmann::json& jConfig); void LoadConfig_JSON(const std::filesystem::path& configFile); - // Bindings - protected: - std::set m_KnownBindings{}; - public: - [[nodiscard]] Binding_ptr Binding( std::set categories, const Action_t& action); - [[nodiscard]] Binding_ptr Binding(const Category_t & category, const Action_t& action) { return Binding(std::set({category}), action); } - [[nodiscard]] Binding_ptr Binding(const std::set& categories) { return Binding(categories, "*"); } - [[nodiscard]] Binding_ptr Binding(const Category_t & category) { return Binding(category, "*"); } - - // Input Type - private: - InputType m_InputType = InputType::KeyboardAndMouse; - std::optional m_LockedInputType; - public: - /// What UI to show. - /// Depends whenever controller input was triggered recently. - [[nodiscard]] inline const InputType& CurrentInputType() const noexcept { return m_LockedInputType.has_value() ? m_LockedInputType.value() : m_InputType; } - void CurrentInputType(InputType value) noexcept; - [[nodiscard]] inline const std::optional& LockedInputType() const noexcept { return m_LockedInputType; } - void LockedInputType(std::optional value) noexcept; - [[nodiscard]] inline bool IsInputTypeLocked() const noexcept { return m_LockedInputType.has_value(); } - // Active category - private: + protected: std::string m_ActiveCategory = "loading"; - public: + public: // Get [[nodiscard]] inline const std::string& GetActiveCategory() const noexcept { return m_ActiveCategory; } + public: // Set virtual bool ActiveCategory(const std::string& category); // Cursor - public: - [[nodiscard]] virtual const std::optional& CursorPosition_Pixels() const noexcept = 0; - [[nodiscard]] virtual const glm::dvec2 & CursorChange_Pixels() const noexcept = 0; - [[nodiscard]] virtual const std::optional& CursorPosition_Percentage() const noexcept = 0; - [[nodiscard]] virtual const glm::dvec2 & CursorChange_Percentage() const noexcept = 0; - [[nodiscard]] virtual bool IsCursorLocked() const = 0; - virtual void LockCursor(bool locked) const = 0; - inline void LockCursor() const { LockCursor(true); } - inline void UnlockCursor() const { LockCursor(false); } + public: // Position + /// Current position of cursor when cursor is not locked + [[nodiscard]] virtual const std::optional& CursorPosition() const noexcept = 0; + /// Position change between 2 frames with unlocked cursor + [[nodiscard]] virtual glm::dvec2 CursorPositionChange() const noexcept = 0; + /// Change of cursor position while the cursor is locked + [[nodiscard]] virtual glm::dvec2 CursorChange() const noexcept = 0; + public: // Locking + [[nodiscard]] virtual bool IsCursorLocked() const = 0; + virtual void LockCursor(bool locked) const = 0; private: double m_CursorSensitivity = 1.0; + public: // Get + [[nodiscard]] inline double CursorSensitivity() const noexcept { return m_CursorSensitivity; } + public: // Set + inline void CursorSensitivity(double value) noexcept { m_CursorSensitivity = value; } + public: - [[nodiscard]] inline double CursorSensitivity() const noexcept { return m_CursorSensitivity; } - inline void CursorSensitivity(double value) noexcept { m_CursorSensitivity = value; } + [[nodiscard]] virtual bool GetDigital (const Action_t& action) = 0; + [[nodiscard]] virtual bool GetDigital_Pressed (const Action_t& action) = 0; + [[nodiscard]] virtual bool GetDigital_Released(const Action_t& action) = 0; + [[nodiscard]] virtual double GetAnalog (const Action_t& action) = 0; - // Keys + // Text input public: - [[nodiscard]] virtual bool IsPressed (const Key_t& key) = 0; - [[nodiscard]] virtual std::u8string GetKeyDisplayName(const Key_t& key) = 0; + virtual const std::vector& GetTypedChars() = 0; - // Axis + // Scroll public: - [[nodiscard]] virtual double GetValue (const Key_t& name) = 0; - [[nodiscard]] virtual std::u8string GetValueName (const Key_t& name) = 0; + virtual glm::dvec2 Scrolling() = 0; + // Color public: - virtual const std::vector& GetTypedChars() = 0; - //TODO Scroll + /// Change color of peripherals. + /// Currently implemented only using Steam Input: + /// - Steam Controller - Grayscale only, changes brightness of the logo + /// - Dualshock 4 - Changes color of the stripe + /// In future may be extended to general peripheral color changes (like `LED ILLUMINATION SDK` from `Logitech G Developer Lab`) + void SetPeripheralColor(glm::vec3 rgb); }; } diff --git a/src/Aurora/Core/Library.hpp b/src/Aurora/Core/Library.hpp index 06601c2..2ffd07d 100644 --- a/src/Aurora/Core/Library.hpp +++ b/src/Aurora/Core/Library.hpp @@ -1,6 +1,6 @@ #pragma once -#if AU_SHARED +#if defined(AU_SHARED) && AU_SHARED==1 && defined(_WIN32) #ifdef AU_EXPORT #define AU_API __declspec(dllexport) #else