diff --git a/src/controller/controldeck/ControlDeck.cpp b/src/controller/controldeck/ControlDeck.cpp index fbb79fc69..4b7416433 100644 --- a/src/controller/controldeck/ControlDeck.cpp +++ b/src/controller/controldeck/ControlDeck.cpp @@ -9,6 +9,7 @@ #endif #include #include "controller/deviceindex/ShipDeviceIndexMappingManager.h" +#include "controller/controldevice/controller/mapping/mouse/WheelHandler.h" namespace Ship { @@ -33,6 +34,7 @@ void ControlDeck::Init(uint8_t* controllerBits) { // if we don't have a config for controller 1, set default keyboard bindings if (!mPorts[0]->GetConnectedController()->HasConfig()) { mPorts[0]->GetConnectedController()->AddDefaultMappings(ShipDeviceIndex::Keyboard); + mPorts[0]->GetConnectedController()->AddDefaultMappings(ShipDeviceIndex::Mouse); } Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Controller Reordering")->Show(); @@ -51,6 +53,19 @@ bool ControlDeck::ProcessKeyboardEvent(KbEventType eventType, KbScancode scancod return result; } +bool ControlDeck::ProcessMouseButtonEvent(bool isPressed, MouseBtn button) { + bool result = false; + for (auto port : mPorts) { + auto controller = port->GetConnectedController(); + + if (controller != nullptr) { + result = controller->ProcessMouseButtonEvent(isPressed, button) || result; + } + } + + return result; +} + bool ControlDeck::AllGameInputBlocked() { return !mGameInputBlockers.empty(); } @@ -63,7 +78,21 @@ bool ControlDeck::GamepadGameInputBlocked() { bool ControlDeck::KeyboardGameInputBlocked() { // block keyboard input when typing in imgui - return AllGameInputBlocked() || ImGui::GetIO().WantCaptureKeyboard; + ImGuiWindow* activeIDWindow = ImGui::GetCurrentContext()->ActiveIdWindow; + return AllGameInputBlocked() || + (activeIDWindow != NULL && + activeIDWindow->ID != Context::GetInstance()->GetWindow()->GetGui()->GetMainGameWindowID()) || + ImGui::GetTopMostPopupModal() != NULL; // ImGui::GetIO().WantCaptureKeyboard, but ActiveId check altered +} + +bool ControlDeck::MouseGameInputBlocked() { + // block mouse input when user interacting with gui + ImGuiWindow* window = ImGui::GetCurrentContext()->HoveredWindow; + if (window == NULL) { + return true; + } + return AllGameInputBlocked() || + (window->ID != Context::GetInstance()->GetWindow()->GetGui()->GetMainGameWindowID()); } std::shared_ptr ControlDeck::GetControllerByPort(uint8_t port) { @@ -112,6 +141,7 @@ void ControlDeck::WriteToPad(void* pad) { void ControlDeck::WriteToOSContPad(OSContPad* pad) { SDL_PumpEvents(); + Ship::WheelHandler::GetInstance()->Update(); if (AllGameInputBlocked()) { return; diff --git a/src/controller/controldeck/ControlDeck.h b/src/controller/controldeck/ControlDeck.h index f54675eff..ac51d8302 100644 --- a/src/controller/controldeck/ControlDeck.h +++ b/src/controller/controldeck/ControlDeck.h @@ -21,9 +21,12 @@ class ControlDeck { void UnblockGameInput(int32_t blockId); bool GamepadGameInputBlocked(); bool KeyboardGameInputBlocked(); + bool MouseGameInputBlocked(); void SetSinglePlayerMappingMode(bool singlePlayer); bool IsSinglePlayerMappingMode(); bool ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode); + bool ProcessMouseButtonEvent(bool isPressed, MouseBtn button); + std::shared_ptr GetDeviceIndexMappingManager(); protected: diff --git a/src/controller/controldevice/controller/Controller.cpp b/src/controller/controldevice/controller/Controller.cpp index 217f7673e..9d4e72a57 100644 --- a/src/controller/controldevice/controller/Controller.cpp +++ b/src/controller/controldevice/controller/Controller.cpp @@ -136,6 +136,16 @@ bool Controller::ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode return result; } +bool Controller::ProcessMouseButtonEvent(bool isPressed, MouseBtn mouseButton) { + bool result = false; + for (auto [bitmask, button] : GetAllButtons()) { + result = button->ProcessMouseButtonEvent(isPressed, mouseButton) || result; + } + result = GetLeftStick()->ProcessMouseButtonEvent(isPressed, mouseButton) || result; + result = GetRightStick()->ProcessMouseButtonEvent(isPressed, mouseButton) || result; + return result; +} + bool Controller::HasMappingsForShipDeviceIndex(ShipDeviceIndex lusIndex) { for (auto [bitmask, button] : GetAllButtons()) { if (button->HasMappingsForShipDeviceIndex(lusIndex)) { diff --git a/src/controller/controldevice/controller/Controller.h b/src/controller/controldevice/controller/Controller.h index f963b6c68..fe2cff1e0 100644 --- a/src/controller/controldevice/controller/Controller.h +++ b/src/controller/controldevice/controller/Controller.h @@ -49,6 +49,7 @@ class Controller : public ControlDevice { std::vector> GetAllMappings(); bool ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode); + bool ProcessMouseButtonEvent(bool isPressed, MouseBtn button); bool HasMappingsForShipDeviceIndex(ShipDeviceIndex lusIndex); void MoveMappingsToDifferentController(std::shared_ptr newController, ShipDeviceIndex lusIndex); diff --git a/src/controller/controldevice/controller/ControllerButton.cpp b/src/controller/controldevice/controller/ControllerButton.cpp index 7fc139874..9d9bb42d1 100644 --- a/src/controller/controldevice/controller/ControllerButton.cpp +++ b/src/controller/controldevice/controller/ControllerButton.cpp @@ -3,16 +3,19 @@ #include "controller/controldevice/controller/mapping/factories/ButtonMappingFactory.h" #include "controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.h" +#include "controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.h" #include "public/bridge/consolevariablebridge.h" #include "utils/StringHelper.h" #include #include +#include "Context.h" + namespace Ship { ControllerButton::ControllerButton(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask) - : mPortIndex(portIndex), mBitmask(bitmask), mUseKeydownEventToCreateNewMapping(false), - mKeyboardScancodeForNewMapping(LUS_KB_UNKNOWN) { + : mPortIndex(portIndex), mBitmask(bitmask), mUseEventInputToCreateNewMapping(false), + mKeyboardScancodeForNewMapping(LUS_KB_UNKNOWN), mMouseButtonForNewMapping(LUS_MOUSE_BTN_UNKNOWN) { } ControllerButton::~ControllerButton() { @@ -175,11 +178,20 @@ bool ControllerButton::HasMappingsForShipDeviceIndex(ShipDeviceIndex lusIndex) { bool ControllerButton::AddOrEditButtonMappingFromRawPress(CONTROLLERBUTTONS_T bitmask, std::string id) { std::shared_ptr mapping = nullptr; - mUseKeydownEventToCreateNewMapping = true; + mUseEventInputToCreateNewMapping = true; if (mKeyboardScancodeForNewMapping != LUS_KB_UNKNOWN) { mapping = std::make_shared(mPortIndex, bitmask, mKeyboardScancodeForNewMapping); } + else if (!Context::GetInstance()->GetWindow()->GetGui()->IsMouseOverAnyGuiItem() && + Context::GetInstance()->GetWindow()->GetGui()->IsMouseOverActivePopup()) { + if (mMouseButtonForNewMapping != LUS_MOUSE_BTN_UNKNOWN) { + mapping = std::make_shared(mPortIndex, bitmask, mMouseButtonForNewMapping); + } else { + mapping = ButtonMappingFactory::CreateButtonMappingFromMouseWheelInput(mPortIndex, bitmask); + } + } + if (mapping == nullptr) { mapping = ButtonMappingFactory::CreateButtonMappingFromSDLInput(mPortIndex, bitmask); } @@ -189,7 +201,8 @@ bool ControllerButton::AddOrEditButtonMappingFromRawPress(CONTROLLERBUTTONS_T bi } mKeyboardScancodeForNewMapping = LUS_KB_UNKNOWN; - mUseKeydownEventToCreateNewMapping = false; + mMouseButtonForNewMapping = LUS_MOUSE_BTN_UNKNOWN; + mUseEventInputToCreateNewMapping = false; if (id != "") { ClearButtonMapping(id); @@ -206,7 +219,7 @@ bool ControllerButton::AddOrEditButtonMappingFromRawPress(CONTROLLERBUTTONS_T bi } bool ControllerButton::ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode) { - if (mUseKeydownEventToCreateNewMapping && eventType == LUS_KB_EVENT_KEY_DOWN) { + if (mUseEventInputToCreateNewMapping) { if (eventType == LUS_KB_EVENT_KEY_DOWN) { mKeyboardScancodeForNewMapping = scancode; return true; @@ -228,6 +241,29 @@ bool ControllerButton::ProcessKeyboardEvent(KbEventType eventType, KbScancode sc return result; } +bool ControllerButton::ProcessMouseButtonEvent(bool isPressed, MouseBtn button) { + if (mUseEventInputToCreateNewMapping) { + if (isPressed) { + mMouseButtonForNewMapping = button; + return true; + } else { + mMouseButtonForNewMapping = LUS_MOUSE_BTN_UNKNOWN; + } + } + + bool result = false; + for (auto [id, mapping] : GetAllButtonMappings()) { + if (mapping->GetMappingType() == MAPPING_TYPE_MOUSE) { + std::shared_ptr mtobMapping = + std::dynamic_pointer_cast(mapping); + if (mtobMapping != nullptr) { + result = result || mtobMapping->ProcessMouseButtonEvent(isPressed, button); + } + } + } + return result; +} + void ControllerButton::AddDefaultMappings(ShipDeviceIndex shipDeviceIndex) { for (auto mapping : ButtonMappingFactory::CreateDefaultSDLButtonMappings(shipDeviceIndex, mPortIndex, mBitmask)) { AddButtonMapping(mapping); diff --git a/src/controller/controldevice/controller/ControllerButton.h b/src/controller/controldevice/controller/ControllerButton.h index dc9e967cd..12dbf048c 100644 --- a/src/controller/controldevice/controller/ControllerButton.h +++ b/src/controller/controldevice/controller/ControllerButton.h @@ -37,6 +37,7 @@ class ControllerButton { void UpdatePad(CONTROLLERBUTTONS_T& padButtons); bool ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode); + bool ProcessMouseButtonEvent(bool isPressed, Ship::MouseBtn button); bool HasMappingsForShipDeviceIndex(ShipDeviceIndex lusIndex); @@ -46,7 +47,8 @@ class ControllerButton { std::unordered_map> mButtonMappings; std::string GetConfigNameFromBitmask(CONTROLLERBUTTONS_T bitmask); - bool mUseKeydownEventToCreateNewMapping; + bool mUseEventInputToCreateNewMapping; KbScancode mKeyboardScancodeForNewMapping; + MouseBtn mMouseButtonForNewMapping; }; } // namespace Ship diff --git a/src/controller/controldevice/controller/ControllerStick.cpp b/src/controller/controldevice/controller/ControllerStick.cpp index 8aa11def6..55659fc60 100644 --- a/src/controller/controldevice/controller/ControllerStick.cpp +++ b/src/controller/controldevice/controller/ControllerStick.cpp @@ -2,6 +2,7 @@ #include #include "controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.h" +#include "controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.h" #include "controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.h" @@ -11,6 +12,8 @@ #include #include +#include "Context.h" + // for some reason windows isn't seeing M_PI // this is copied from my system's math.h #ifndef M_PI @@ -22,8 +25,8 @@ namespace Ship { ControllerStick::ControllerStick(uint8_t portIndex, StickIndex stickIndex) - : mPortIndex(portIndex), mStickIndex(stickIndex), mUseKeydownEventToCreateNewMapping(false), - mKeyboardScancodeForNewMapping(KbScancode::LUS_KB_UNKNOWN) { + : mPortIndex(portIndex), mStickIndex(stickIndex), mUseEventInputToCreateNewMapping(false), + mKeyboardScancodeForNewMapping(KbScancode::LUS_KB_UNKNOWN), mMouseButtonForNewMapping(LUS_MOUSE_BTN_UNKNOWN) { mSensitivityPercentage = DEFAULT_STICK_SENSITIVITY_PERCENTAGE; mSensitivity = 1.0f; mDeadzonePercentage = DEFAULT_STICK_DEADZONE_PERCENTAGE; @@ -268,12 +271,20 @@ void ControllerStick::Process(int8_t& x, int8_t& y) { bool ControllerStick::AddOrEditAxisDirectionMappingFromRawPress(Direction direction, std::string id) { std::shared_ptr mapping = nullptr; - mUseKeydownEventToCreateNewMapping = true; + mUseEventInputToCreateNewMapping = true; if (mKeyboardScancodeForNewMapping != LUS_KB_UNKNOWN) { mapping = std::make_shared(mPortIndex, mStickIndex, direction, mKeyboardScancodeForNewMapping); + } else if (!Context::GetInstance()->GetWindow()->GetGui()->IsMouseOverAnyGuiItem() && + Context::GetInstance()->GetWindow()->GetGui()->IsMouseOverActivePopup()) { + if (mMouseButtonForNewMapping != LUS_MOUSE_BTN_UNKNOWN) { + mapping = std::make_shared(mPortIndex, mStickIndex, direction, + mMouseButtonForNewMapping); + } else { + mapping = AxisDirectionMappingFactory::CreateAxisDirectionMappingFromMouseWheelInput( + mPortIndex, mStickIndex, direction); + } } - if (mapping == nullptr) { mapping = AxisDirectionMappingFactory::CreateAxisDirectionMappingFromSDLInput(mPortIndex, mStickIndex, direction); @@ -284,7 +295,8 @@ bool ControllerStick::AddOrEditAxisDirectionMappingFromRawPress(Direction direct } mKeyboardScancodeForNewMapping = LUS_KB_UNKNOWN; - mUseKeydownEventToCreateNewMapping = false; + mMouseButtonForNewMapping = LUS_MOUSE_BTN_UNKNOWN; + mUseEventInputToCreateNewMapping = false; if (id != "") { ClearAxisDirectionMapping(direction, id); @@ -319,7 +331,7 @@ void ControllerStick::UpdatePad(int8_t& x, int8_t& y) { } bool ControllerStick::ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode) { - if (mUseKeydownEventToCreateNewMapping) { + if (mUseEventInputToCreateNewMapping) { if (eventType == LUS_KB_EVENT_KEY_DOWN) { mKeyboardScancodeForNewMapping = scancode; return true; @@ -343,6 +355,31 @@ bool ControllerStick::ProcessKeyboardEvent(KbEventType eventType, KbScancode sca return result; } +bool ControllerStick::ProcessMouseButtonEvent(bool isPressed, MouseBtn button) { + if (mUseEventInputToCreateNewMapping) { + if (isPressed) { + mMouseButtonForNewMapping = button; + return true; + } else { + mMouseButtonForNewMapping = LUS_MOUSE_BTN_UNKNOWN; + } + } + + bool result = false; + for (auto [direction, mappings] : mAxisDirectionMappings) { + for (auto [id, mapping] : mappings) { + if (mapping->GetMappingType() == MAPPING_TYPE_MOUSE) { + std::shared_ptr mtoadMapping = + std::dynamic_pointer_cast(mapping); + if (mtoadMapping != nullptr) { + result = result || mtoadMapping->ProcessMouseButtonEvent(isPressed, button); + } + } + } + } + return result; +} + void ControllerStick::SetSensitivity(uint8_t sensitivityPercentage) { mSensitivityPercentage = sensitivityPercentage; mSensitivity = sensitivityPercentage / 100.0f; diff --git a/src/controller/controldevice/controller/ControllerStick.h b/src/controller/controldevice/controller/ControllerStick.h index 8bc80aba7..e6d1f1fe7 100644 --- a/src/controller/controldevice/controller/ControllerStick.h +++ b/src/controller/controldevice/controller/ControllerStick.h @@ -52,6 +52,7 @@ class ControllerStick { bool NotchSnapAngleIsDefault(); bool ProcessKeyboardEvent(KbEventType eventType, KbScancode scancode); + bool ProcessMouseButtonEvent(bool isPressed, Ship::MouseBtn button); bool HasMappingsForShipDeviceIndex(ShipDeviceIndex lusIndex); StickIndex GetStickIndex(); @@ -75,7 +76,8 @@ class ControllerStick { std::unordered_map>> mAxisDirectionMappings; - bool mUseKeydownEventToCreateNewMapping; + bool mUseEventInputToCreateNewMapping; KbScancode mKeyboardScancodeForNewMapping; + MouseBtn mMouseButtonForNewMapping; }; } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.cpp b/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.cpp index 9fce4939b..454dc902e 100644 --- a/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.cpp +++ b/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.cpp @@ -12,7 +12,7 @@ ControllerAxisDirectionMapping::ControllerAxisDirectionMapping(ShipDeviceIndex s ControllerAxisDirectionMapping::~ControllerAxisDirectionMapping() { } -uint8_t ControllerAxisDirectionMapping::GetMappingType() { +int8_t ControllerAxisDirectionMapping::GetMappingType() { return MAPPING_TYPE_UNKNOWN; } diff --git a/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.h b/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.h index 5655049be..6a825a826 100644 --- a/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.h +++ b/src/controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.h @@ -17,7 +17,7 @@ class ControllerAxisDirectionMapping : virtual public ControllerInputMapping { Direction direction); ~ControllerAxisDirectionMapping(); virtual float GetNormalizedAxisDirectionValue() = 0; - virtual uint8_t GetMappingType(); + virtual int8_t GetMappingType(); virtual std::string GetAxisDirectionMappingId() = 0; virtual void SaveToConfig() = 0; diff --git a/src/controller/controldevice/controller/mapping/ControllerButtonMapping.cpp b/src/controller/controldevice/controller/mapping/ControllerButtonMapping.cpp index 2362fb6c0..8040eff42 100644 --- a/src/controller/controldevice/controller/mapping/ControllerButtonMapping.cpp +++ b/src/controller/controldevice/controller/mapping/ControllerButtonMapping.cpp @@ -18,7 +18,7 @@ CONTROLLERBUTTONS_T ControllerButtonMapping::GetBitmask() { return mBitmask; } -uint8_t ControllerButtonMapping::GetMappingType() { +int8_t ControllerButtonMapping::GetMappingType() { return MAPPING_TYPE_UNKNOWN; } diff --git a/src/controller/controldevice/controller/mapping/ControllerButtonMapping.h b/src/controller/controldevice/controller/mapping/ControllerButtonMapping.h index b4e57b92b..324839349 100644 --- a/src/controller/controldevice/controller/mapping/ControllerButtonMapping.h +++ b/src/controller/controldevice/controller/mapping/ControllerButtonMapping.h @@ -20,7 +20,7 @@ class ControllerButtonMapping : virtual public ControllerInputMapping { CONTROLLERBUTTONS_T GetBitmask(); virtual void UpdatePad(CONTROLLERBUTTONS_T& padButtons) = 0; - virtual uint8_t GetMappingType(); + virtual int8_t GetMappingType(); void SetPortIndex(uint8_t portIndex); virtual void SaveToConfig() = 0; diff --git a/src/controller/controldevice/controller/mapping/ControllerMapping.h b/src/controller/controldevice/controller/mapping/ControllerMapping.h index c594e0123..646693765 100644 --- a/src/controller/controldevice/controller/mapping/ControllerMapping.h +++ b/src/controller/controldevice/controller/mapping/ControllerMapping.h @@ -5,9 +5,10 @@ namespace Ship { +#define MAPPING_TYPE_UNKNOWN -1 #define MAPPING_TYPE_GAMEPAD 0 #define MAPPING_TYPE_KEYBOARD 1 -#define MAPPING_TYPE_UNKNOWN 2 +#define MAPPING_TYPE_MOUSE 2 class ControllerMapping { public: diff --git a/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.cpp b/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.cpp index ab6a4a35b..2fe627d22 100644 --- a/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.cpp +++ b/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.cpp @@ -1,5 +1,7 @@ #include "AxisDirectionMappingFactory.h" #include "controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.h" +#include "controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.h" +#include "controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.h" #include "controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.h" #include "controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.h" @@ -9,6 +11,9 @@ #include "Context.h" #include "controller/deviceindex/ShipDeviceIndexToSDLDeviceIndexMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" +#include "controller/controldevice/controller/mapping/mouse/WheelHandler.h" + namespace Ship { std::shared_ptr AxisDirectionMappingFactory::CreateAxisDirectionMappingFromConfig(uint8_t portIndex, StickIndex stickIndex, @@ -75,6 +80,37 @@ AxisDirectionMappingFactory::CreateAxisDirectionMappingFromConfig(uint8_t portIn portIndex, stickIndex, static_cast(direction), static_cast(scancode)); } + if (mappingClass == "MouseButtonToAxisDirectionMapping") { + int32_t direction = CVarGetInteger(StringHelper::Sprintf("%s.Direction", mappingCvarKey.c_str()).c_str(), -1); + int mouseButton = CVarGetInteger(StringHelper::Sprintf("%s.MouseButton", mappingCvarKey.c_str()).c_str(), 0); + + if (direction != LEFT && direction != RIGHT && direction != UP && direction != DOWN) { + // something about this mapping is invalid + CVarClear(mappingCvarKey.c_str()); + CVarSave(); + return nullptr; + } + + return std::make_shared( + portIndex, stickIndex, static_cast(direction), static_cast(mouseButton)); + } + + if (mappingClass == "MouseWheelToAxisDirectionMapping") { + int32_t direction = CVarGetInteger(StringHelper::Sprintf("%s.Direction", mappingCvarKey.c_str()).c_str(), -1); + int wheelDirection = + CVarGetInteger(StringHelper::Sprintf("%s.WheelDirection", mappingCvarKey.c_str()).c_str(), 0); + + if (direction != LEFT && direction != RIGHT && direction != UP && direction != DOWN) { + // something about this mapping is invalid + CVarClear(mappingCvarKey.c_str()); + CVarSave(); + return nullptr; + } + + return std::make_shared( + portIndex, stickIndex, static_cast(direction), static_cast(wheelDirection)); + } + return nullptr; } @@ -182,4 +218,20 @@ AxisDirectionMappingFactory::CreateAxisDirectionMappingFromSDLInput(uint8_t port return mapping; } + +std::shared_ptr +AxisDirectionMappingFactory::CreateAxisDirectionMappingFromMouseWheelInput(uint8_t portIndex, StickIndex stickIndex, + Direction direction) { + WheelDirections wheelDirections = WheelHandler::GetInstance()->GetDirections(); + WheelDirection wheelDirection; + if (wheelDirections.x != LUS_WHEEL_NONE) { + wheelDirection = wheelDirections.x; + } else if (wheelDirections.y != LUS_WHEEL_NONE) { + wheelDirection = wheelDirections.y; + } else { + return nullptr; + } + + return std::make_shared(portIndex, stickIndex, direction, wheelDirection); +} } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.h b/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.h index 98887bb10..7cdd16377 100644 --- a/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.h +++ b/src/controller/controldevice/controller/mapping/factories/AxisDirectionMappingFactory.h @@ -19,5 +19,8 @@ class AxisDirectionMappingFactory { static std::shared_ptr CreateAxisDirectionMappingFromSDLInput(uint8_t portIndex, StickIndex stickIndex, Direction direction); + + static std::shared_ptr + CreateAxisDirectionMappingFromMouseWheelInput(uint8_t portIndex, StickIndex stickIndex, Direction direction); }; } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.cpp b/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.cpp index 627e259db..f707f98f3 100644 --- a/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.cpp +++ b/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.cpp @@ -4,9 +4,13 @@ #include "libultraship/libultra/controller.h" #include "Context.h" #include "controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.h" +#include "controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.h" +#include "controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.h" #include "controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.h" #include "controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h" #include "controller/deviceindex/ShipDeviceIndexToSDLDeviceIndexMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" +#include "controller/controldevice/controller/mapping/mouse/WheelHandler.h" namespace Ship { std::shared_ptr ButtonMappingFactory::CreateButtonMappingFromConfig(uint8_t portIndex, @@ -66,6 +70,20 @@ std::shared_ptr ButtonMappingFactory::CreateButtonMappi return std::make_shared(portIndex, bitmask, static_cast(scancode)); } + if (mappingClass == "MouseButtonToButtonMapping") { + int mouseButton = CVarGetInteger(StringHelper::Sprintf("%s.MouseButton", mappingCvarKey.c_str()).c_str(), 0); + + return std::make_shared(portIndex, bitmask, static_cast(mouseButton)); + } + + if (mappingClass == "MouseWheelToButtonMapping") { + int wheelDirection = + CVarGetInteger(StringHelper::Sprintf("%s.WheelDirection", mappingCvarKey.c_str()).c_str(), 0); + + return std::make_shared(portIndex, bitmask, + static_cast(wheelDirection)); + } + return nullptr; } @@ -288,4 +306,19 @@ ButtonMappingFactory::CreateButtonMappingFromSDLInput(uint8_t portIndex, CONTROL return mapping; } + +std::shared_ptr +ButtonMappingFactory::CreateButtonMappingFromMouseWheelInput(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask) { + WheelDirections wheelDirections = WheelHandler::GetInstance()->GetDirections(); + WheelDirection wheelDirection; + if (wheelDirections.x != LUS_WHEEL_NONE) { + wheelDirection = wheelDirections.x; + } else if (wheelDirections.y != LUS_WHEEL_NONE) { + wheelDirection = wheelDirections.y; + } else { + return nullptr; + } + + return std::make_shared(portIndex, bitmask, wheelDirection); +} } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.h b/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.h index 1a11b3312..325a96562 100644 --- a/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.h +++ b/src/controller/controldevice/controller/mapping/factories/ButtonMappingFactory.h @@ -18,5 +18,8 @@ class ButtonMappingFactory { static std::shared_ptr CreateButtonMappingFromSDLInput(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask); + + static std::shared_ptr CreateButtonMappingFromMouseWheelInput(uint8_t portIndex, + CONTROLLERBUTTONS_T bitmask); }; } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.cpp b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.cpp index 063432eef..992ac7643 100644 --- a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.cpp +++ b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.cpp @@ -43,7 +43,7 @@ void KeyboardKeyToAxisDirectionMapping::EraseFromConfig() { CVarSave(); } -uint8_t KeyboardKeyToAxisDirectionMapping::GetMappingType() { +int8_t KeyboardKeyToAxisDirectionMapping::GetMappingType() { return MAPPING_TYPE_KEYBOARD; } } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.h b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.h index 000076ff1..a4e3bbacb 100644 --- a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.h +++ b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToAxisDirectionMapping.h @@ -8,7 +8,7 @@ class KeyboardKeyToAxisDirectionMapping final : public KeyboardKeyToAnyMapping, KbScancode scancode); float GetNormalizedAxisDirectionValue() override; std::string GetAxisDirectionMappingId() override; - uint8_t GetMappingType() override; + int8_t GetMappingType() override; void SaveToConfig() override; void EraseFromConfig() override; }; diff --git a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.cpp b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.cpp index ad3760cba..55caa2efc 100644 --- a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.cpp +++ b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.cpp @@ -23,7 +23,7 @@ void KeyboardKeyToButtonMapping::UpdatePad(CONTROLLERBUTTONS_T& padButtons) { padButtons |= mBitmask; } -uint8_t KeyboardKeyToButtonMapping::GetMappingType() { +int8_t KeyboardKeyToButtonMapping::GetMappingType() { return MAPPING_TYPE_KEYBOARD; } diff --git a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.h b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.h index 81128c75a..be8f423a9 100644 --- a/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.h +++ b/src/controller/controldevice/controller/mapping/keyboard/KeyboardKeyToButtonMapping.h @@ -6,7 +6,7 @@ class KeyboardKeyToButtonMapping final : public KeyboardKeyToAnyMapping, public public: KeyboardKeyToButtonMapping(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, KbScancode scancode); void UpdatePad(CONTROLLERBUTTONS_T& padButtons) override; - uint8_t GetMappingType() override; + int8_t GetMappingType() override; std::string GetButtonMappingId() override; void SaveToConfig() override; void EraseFromConfig() override; diff --git a/src/controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h b/src/controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h index 4e92ef6f2..1f61d8b13 100644 --- a/src/controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h +++ b/src/controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h @@ -1,6 +1,8 @@ #pragma once #ifdef __cplusplus +#include + namespace Ship { #endif @@ -118,6 +120,29 @@ typedef enum KbScancode { LUS_KB_MAX } KbScancode; +typedef enum MouseBtn { + LUS_MOUSE_BTN_LEFT, + LUS_MOUSE_BTN_MIDDLE, + LUS_MOUSE_BTN_RIGHT, + LUS_MOUSE_BTN_BACKWARD, + LUS_MOUSE_BTN_FORWARD, + LUS_MOUSE_BTN_COUNT, + LUS_MOUSE_BTN_UNKNOWN +} MouseBtn; + +typedef enum WheelDirection { + LUS_WHEEL_NONE, + LUS_WHEEL_LEFT, + LUS_WHEEL_RIGHT, + LUS_WHEEL_UP, + LUS_WHEEL_DOWN, + LUS_WHEEL_UNKNOWN +} WheelDirection; + #ifdef __cplusplus +static std::string mouseBtnNames[7] = { "MouseLeft", "MouseMiddle", "MouseRight", "MouseBackward", + "MouseForward", "MOUSE_BTN_COUNT", "MOUSE_BTN_UNKNOWN" }; +static std::string wheelDirectionNames[6] = { "LUS_WHEEL_NONE", "WheelLeft", "WheelRight", + "WheelUp", "WheelDown", "LUS_WHEEL_UNKNOWN" }; } // namespace Ship #endif diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAnyMapping.cpp b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAnyMapping.cpp new file mode 100644 index 000000000..b57c36be0 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAnyMapping.cpp @@ -0,0 +1,35 @@ +#include "MouseButtonToAnyMapping.h" +#include "Context.h" + +#include "utils/StringHelper.h" +#include "window/gui/IconsFontAwesome4.h" + +namespace Ship { +MouseButtonToAnyMapping::MouseButtonToAnyMapping(MouseBtn button) + : ControllerInputMapping(ShipDeviceIndex::Mouse), mButton(button), mKeyPressed(false) { +} + +MouseButtonToAnyMapping::~MouseButtonToAnyMapping() { +} + +std::string MouseButtonToAnyMapping::GetPhysicalInputName() { + return mouseBtnNames[static_cast(mButton)]; +} + +bool MouseButtonToAnyMapping::ProcessMouseButtonEvent(bool isPressed, MouseBtn button) { + if (mButton != button) { + return false; + } + + mKeyPressed = isPressed; + return true; +} + +std::string MouseButtonToAnyMapping::GetPhysicalDeviceName() { + return "Mouse"; +} + +bool MouseButtonToAnyMapping::PhysicalDeviceIsConnected() { + return true; +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAnyMapping.h b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAnyMapping.h new file mode 100644 index 000000000..24b37ac93 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAnyMapping.h @@ -0,0 +1,20 @@ +#pragma once + +#include "controller/controldevice/controller/mapping/ControllerInputMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +class MouseButtonToAnyMapping : virtual public ControllerInputMapping { + public: + MouseButtonToAnyMapping(MouseBtn button); + ~MouseButtonToAnyMapping(); + std::string GetPhysicalInputName() override; + bool ProcessMouseButtonEvent(bool isPressed, MouseBtn button); + std::string GetPhysicalDeviceName() override; + bool PhysicalDeviceIsConnected() override; + + protected: + MouseBtn mButton; + bool mKeyPressed; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.cpp b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.cpp new file mode 100644 index 000000000..39c1b1158 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.cpp @@ -0,0 +1,49 @@ +#include "MouseButtonToAxisDirectionMapping.h" +#include +#include "utils/StringHelper.h" +#include "window/gui/IconsFontAwesome4.h" +#include "public/bridge/consolevariablebridge.h" +#include "Context.h" + +namespace Ship { +MouseButtonToAxisDirectionMapping::MouseButtonToAxisDirectionMapping(uint8_t portIndex, StickIndex stickIndex, + Direction direction, MouseBtn button) + : ControllerInputMapping(ShipDeviceIndex::Mouse), MouseButtonToAnyMapping(button), + ControllerAxisDirectionMapping(ShipDeviceIndex::Mouse, portIndex, stickIndex, direction) { +} + +float MouseButtonToAxisDirectionMapping::GetNormalizedAxisDirectionValue() { + if (Context::GetInstance()->GetControlDeck()->MouseGameInputBlocked()) { + return 0.0f; + } + + return mKeyPressed ? MAX_AXIS_RANGE : 0.0f; +} + +std::string MouseButtonToAxisDirectionMapping::GetAxisDirectionMappingId() { + return StringHelper::Sprintf("P%d-S%d-D%d-MOUSE%d", mPortIndex, mStickIndex, mDirection, mButton); +} + +void MouseButtonToAxisDirectionMapping::SaveToConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".AxisDirectionMappings." + GetAxisDirectionMappingId(); + CVarSetString(StringHelper::Sprintf("%s.AxisDirectionMappingClass", mappingCvarKey.c_str()).c_str(), + "MouseButtonToAxisDirectionMapping"); + CVarSetInteger(StringHelper::Sprintf("%s.Stick", mappingCvarKey.c_str()).c_str(), mStickIndex); + CVarSetInteger(StringHelper::Sprintf("%s.Direction", mappingCvarKey.c_str()).c_str(), mDirection); + CVarSetInteger(StringHelper::Sprintf("%s.MouseButton", mappingCvarKey.c_str()).c_str(), static_cast(mButton)); + CVarSave(); +} + +void MouseButtonToAxisDirectionMapping::EraseFromConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".AxisDirectionMappings." + GetAxisDirectionMappingId(); + CVarClear(StringHelper::Sprintf("%s.Stick", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.Direction", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.AxisDirectionMappingClass", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.MouseButton", mappingCvarKey.c_str()).c_str()); + CVarSave(); +} + +int8_t MouseButtonToAxisDirectionMapping::GetMappingType() { + return MAPPING_TYPE_MOUSE; +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.h b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.h new file mode 100644 index 000000000..62cd47950 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToAxisDirectionMapping.h @@ -0,0 +1,17 @@ +#pragma once + +#include "controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.h" +#include "MouseButtonToAnyMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +class MouseButtonToAxisDirectionMapping final : public MouseButtonToAnyMapping, public ControllerAxisDirectionMapping { + public: + MouseButtonToAxisDirectionMapping(uint8_t portIndex, StickIndex stickIndex, Direction direction, MouseBtn button); + float GetNormalizedAxisDirectionValue() override; + std::string GetAxisDirectionMappingId() override; + int8_t GetMappingType() override; + void SaveToConfig() override; + void EraseFromConfig() override; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.cpp b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.cpp new file mode 100644 index 000000000..238a0b05e --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.cpp @@ -0,0 +1,51 @@ +#include "MouseButtonToButtonMapping.h" +#include +#include "utils/StringHelper.h" +#include "public/bridge/consolevariablebridge.h" +#include "Context.h" + +namespace Ship { +MouseButtonToButtonMapping::MouseButtonToButtonMapping(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, MouseBtn button) + : ControllerInputMapping(ShipDeviceIndex::Mouse), MouseButtonToAnyMapping(button), + ControllerButtonMapping(ShipDeviceIndex::Mouse, portIndex, bitmask) { +} + +void MouseButtonToButtonMapping::UpdatePad(CONTROLLERBUTTONS_T& padButtons) { + if (Context::GetInstance()->GetControlDeck()->MouseGameInputBlocked()) { + return; + } + + if (!mKeyPressed) { + return; + } + + padButtons |= mBitmask; +} + +int8_t MouseButtonToButtonMapping::GetMappingType() { + return MAPPING_TYPE_MOUSE; +} + +std::string MouseButtonToButtonMapping::GetButtonMappingId() { + return StringHelper::Sprintf("P%d-B%d-MOUSE%d", mPortIndex, mBitmask, mButton); +} + +void MouseButtonToButtonMapping::SaveToConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".ButtonMappings." + GetButtonMappingId(); + CVarSetString(StringHelper::Sprintf("%s.ButtonMappingClass", mappingCvarKey.c_str()).c_str(), + "MouseButtonToButtonMapping"); + CVarSetInteger(StringHelper::Sprintf("%s.Bitmask", mappingCvarKey.c_str()).c_str(), mBitmask); + CVarSetInteger(StringHelper::Sprintf("%s.MouseButton", mappingCvarKey.c_str()).c_str(), static_cast(mButton)); + CVarSave(); +} + +void MouseButtonToButtonMapping::EraseFromConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".ButtonMappings." + GetButtonMappingId(); + + CVarClear(StringHelper::Sprintf("%s.ButtonMappingClass", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.Bitmask", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.MouseButton", mappingCvarKey.c_str()).c_str()); + + CVarSave(); +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.h b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.h new file mode 100644 index 000000000..7116ae9ce --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseButtonToButtonMapping.h @@ -0,0 +1,17 @@ +#pragma once + +#include "controller/controldevice/controller/mapping/ControllerButtonMapping.h" +#include "MouseButtonToAnyMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +class MouseButtonToButtonMapping final : public MouseButtonToAnyMapping, public ControllerButtonMapping { + public: + MouseButtonToButtonMapping(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, MouseBtn button); + void UpdatePad(CONTROLLERBUTTONS_T& padButtons) override; + int8_t GetMappingType() override; + std::string GetButtonMappingId() override; + void SaveToConfig() override; + void EraseFromConfig() override; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAnyMapping.cpp b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAnyMapping.cpp new file mode 100644 index 000000000..7a2565457 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAnyMapping.cpp @@ -0,0 +1,26 @@ +#include "MouseWheelToAnyMapping.h" +#include "Context.h" + +#include "utils/StringHelper.h" +#include "window/gui/IconsFontAwesome4.h" + +namespace Ship { +MouseWheelToAnyMapping::MouseWheelToAnyMapping(WheelDirection wheelDirection) + : ControllerInputMapping(ShipDeviceIndex::Mouse), mWheelDirection(wheelDirection) { +} + +MouseWheelToAnyMapping::~MouseWheelToAnyMapping() { +} + +std::string MouseWheelToAnyMapping::GetPhysicalInputName() { + return wheelDirectionNames[static_cast(mWheelDirection)]; +} + +std::string MouseWheelToAnyMapping::GetPhysicalDeviceName() { + return "Mouse"; +} + +bool MouseWheelToAnyMapping::PhysicalDeviceIsConnected() { + return true; +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAnyMapping.h b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAnyMapping.h new file mode 100644 index 000000000..8067fa851 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAnyMapping.h @@ -0,0 +1,18 @@ +#pragma once + +#include "controller/controldevice/controller/mapping/ControllerInputMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +class MouseWheelToAnyMapping : virtual public ControllerInputMapping { + public: + MouseWheelToAnyMapping(WheelDirection wheelDirection); + ~MouseWheelToAnyMapping(); + std::string GetPhysicalInputName() override; + std::string GetPhysicalDeviceName() override; + bool PhysicalDeviceIsConnected() override; + + protected: + WheelDirection mWheelDirection; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.cpp b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.cpp new file mode 100644 index 000000000..84fce8a6a --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.cpp @@ -0,0 +1,52 @@ +#include "MouseWheelToAxisDirectionMapping.h" +#include +#include +#include "utils/StringHelper.h" +#include "window/gui/IconsFontAwesome4.h" +#include "public/bridge/consolevariablebridge.h" +#include "Context.h" +#include "WheelHandler.h" + +namespace Ship { +MouseWheelToAxisDirectionMapping::MouseWheelToAxisDirectionMapping(uint8_t portIndex, StickIndex stickIndex, + Direction direction, WheelDirection wheelDirection) + : ControllerInputMapping(ShipDeviceIndex::Mouse), MouseWheelToAnyMapping(wheelDirection), + ControllerAxisDirectionMapping(ShipDeviceIndex::Mouse, portIndex, stickIndex, direction) { +} + +float MouseWheelToAxisDirectionMapping::GetNormalizedAxisDirectionValue() { + if (Context::GetInstance()->GetControlDeck()->MouseGameInputBlocked()) { + return 0.0f; + } + + return fmin(WheelHandler::GetInstance()->GetBufferedDirectionValue(mWheelDirection), 1.0f) * MAX_AXIS_RANGE; +} + +std::string MouseWheelToAxisDirectionMapping::GetAxisDirectionMappingId() { + return StringHelper::Sprintf("P%d-S%d-D%d-WHEEL%d", mPortIndex, mStickIndex, mDirection, mWheelDirection); +} + +void MouseWheelToAxisDirectionMapping::SaveToConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".AxisDirectionMappings." + GetAxisDirectionMappingId(); + CVarSetString(StringHelper::Sprintf("%s.AxisDirectionMappingClass", mappingCvarKey.c_str()).c_str(), + "MouseWheelToAxisDirectionMapping"); + CVarSetInteger(StringHelper::Sprintf("%s.Stick", mappingCvarKey.c_str()).c_str(), mStickIndex); + CVarSetInteger(StringHelper::Sprintf("%s.Direction", mappingCvarKey.c_str()).c_str(), mDirection); + CVarSetInteger(StringHelper::Sprintf("%s.WheelDirection", mappingCvarKey.c_str()).c_str(), + static_cast(mWheelDirection)); + CVarSave(); +} + +void MouseWheelToAxisDirectionMapping::EraseFromConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".AxisDirectionMappings." + GetAxisDirectionMappingId(); + CVarClear(StringHelper::Sprintf("%s.Stick", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.Direction", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.AxisDirectionMappingClass", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.WheelDirection", mappingCvarKey.c_str()).c_str()); + CVarSave(); +} + +int8_t MouseWheelToAxisDirectionMapping::GetMappingType() { + return MAPPING_TYPE_MOUSE; +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.h b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.h new file mode 100644 index 000000000..47ba14c1b --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToAxisDirectionMapping.h @@ -0,0 +1,18 @@ +#pragma once + +#include "MouseWheelToAnyMapping.h" +#include "controller/controldevice/controller/mapping/ControllerAxisDirectionMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +class MouseWheelToAxisDirectionMapping final : public MouseWheelToAnyMapping, public ControllerAxisDirectionMapping { + public: + MouseWheelToAxisDirectionMapping(uint8_t portIndex, StickIndex stickIndex, Direction direction, + WheelDirection wheelDirection); + float GetNormalizedAxisDirectionValue() override; + std::string GetAxisDirectionMappingId() override; + int8_t GetMappingType() override; + void SaveToConfig() override; + void EraseFromConfig() override; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.cpp b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.cpp new file mode 100644 index 000000000..7591060a3 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.cpp @@ -0,0 +1,53 @@ +#include "MouseWheelToButtonMapping.h" +#include +#include "utils/StringHelper.h" +#include "public/bridge/consolevariablebridge.h" +#include "WheelHandler.h" +#include "Context.h" + +namespace Ship { +MouseWheelToButtonMapping::MouseWheelToButtonMapping(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, + WheelDirection wheelDirection) + : ControllerInputMapping(ShipDeviceIndex::Mouse), MouseWheelToAnyMapping(wheelDirection), + ControllerButtonMapping(ShipDeviceIndex::Mouse, portIndex, bitmask) { +} + +void MouseWheelToButtonMapping::UpdatePad(CONTROLLERBUTTONS_T& padButtons) { + if (Context::GetInstance()->GetControlDeck()->MouseGameInputBlocked()) { + return; + } + + WheelDirections directions = WheelHandler::GetInstance()->GetDirections(); + if (mWheelDirection == directions.x || mWheelDirection == directions.y) { + padButtons |= mBitmask; + } +} + +int8_t MouseWheelToButtonMapping::GetMappingType() { + return MAPPING_TYPE_MOUSE; +} + +std::string MouseWheelToButtonMapping::GetButtonMappingId() { + return StringHelper::Sprintf("P%d-B%d-WHEEL%d", mPortIndex, mBitmask, mWheelDirection); +} + +void MouseWheelToButtonMapping::SaveToConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".ButtonMappings." + GetButtonMappingId(); + CVarSetString(StringHelper::Sprintf("%s.ButtonMappingClass", mappingCvarKey.c_str()).c_str(), + "MouseWheelToButtonMapping"); + CVarSetInteger(StringHelper::Sprintf("%s.Bitmask", mappingCvarKey.c_str()).c_str(), mBitmask); + CVarSetInteger(StringHelper::Sprintf("%s.WheelDirection", mappingCvarKey.c_str()).c_str(), + static_cast(mWheelDirection)); + CVarSave(); +} + +void MouseWheelToButtonMapping::EraseFromConfig() { + const std::string mappingCvarKey = CVAR_PREFIX_CONTROLLERS ".ButtonMappings." + GetButtonMappingId(); + + CVarClear(StringHelper::Sprintf("%s.ButtonMappingClass", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.Bitmask", mappingCvarKey.c_str()).c_str()); + CVarClear(StringHelper::Sprintf("%s.WheelDirection", mappingCvarKey.c_str()).c_str()); + + CVarSave(); +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.h b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.h new file mode 100644 index 000000000..6188ab716 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/MouseWheelToButtonMapping.h @@ -0,0 +1,17 @@ +#pragma once + +#include "MouseWheelToAnyMapping.h" +#include "controller/controldevice/controller/mapping/ControllerButtonMapping.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +class MouseWheelToButtonMapping final : public MouseWheelToAnyMapping, public ControllerButtonMapping { + public: + MouseWheelToButtonMapping(uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, WheelDirection wheelDirection); + void UpdatePad(CONTROLLERBUTTONS_T& padButtons) override; + int8_t GetMappingType() override; + std::string GetButtonMappingId() override; + void SaveToConfig() override; + void EraseFromConfig() override; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/WheelHandler.cpp b/src/controller/controldevice/controller/mapping/mouse/WheelHandler.cpp new file mode 100644 index 000000000..fd8ee6a4e --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/WheelHandler.cpp @@ -0,0 +1,100 @@ +#include "WheelHandler.h" +#include "Context.h" +#include + +namespace Ship { +WheelHandler::WheelHandler() { + mDirections = { LUS_WHEEL_NONE, LUS_WHEEL_NONE }; +} + +WheelHandler::~WheelHandler() { +} + +std::shared_ptr WheelHandler::mInstance; + +std::shared_ptr WheelHandler::GetInstance() { + if (mInstance == nullptr) { + mInstance = std::make_shared(); + } + return mInstance; +} + +void ApplyToBuffer(float* dst, float src) { + if (src == 0) { + return; + } + *dst += src; + if (fabs(*dst) > 2) { + *dst = copysignf(2.0f, *dst); + } +} + +void WheelHandler::Update() { + mCoords = Context::GetInstance()->GetWindow()->GetMouseWheel(); + + // reduce buffered value + if (fabs(mBufferedCoords.x) > 0) { + mBufferedCoords.x -= copysignf(1.0f, mBufferedCoords.x); + } + if (fabs(mBufferedCoords.y) > 0) { + mBufferedCoords.y -= copysignf(1.0f, mBufferedCoords.y); + } + + // add new value to buffer + mBufferedCoords.x += copysignf(fmin(2.0f, mCoords.x), mCoords.x); + mBufferedCoords.y += copysignf(fmin(2.0f, mCoords.y), mCoords.y); + + mDirections.x = mDirections.y = LUS_WHEEL_NONE; + if (mCoords.x < 0) { + mDirections.x = LUS_WHEEL_LEFT; + } else if (mCoords.x > 0) { + mDirections.x = LUS_WHEEL_RIGHT; + } + if (mCoords.y < 0) { + mDirections.y = LUS_WHEEL_DOWN; + } else if (mCoords.y > 0) { + mDirections.y = LUS_WHEEL_UP; + } +} + +CoordsF WheelHandler::GetCoords() { + return mCoords; +} + +WheelDirections WheelHandler::GetDirections() { + return mDirections; +} + +float CalcDirectionValue(CoordsF& coords, WheelDirection direction) { + switch (direction) { + case LUS_WHEEL_LEFT: + if (coords.x < 0) { + return -coords.x; + } + break; + case LUS_WHEEL_RIGHT: + if (coords.x > 0) { + return coords.x; + } + break; + case LUS_WHEEL_DOWN: + if (coords.y < 0) { + return -coords.y; + } + break; + case LUS_WHEEL_UP: + if (coords.y > 0) { + return coords.y; + } + } + return 0.0f; +} + +float WheelHandler::GetDirectionValue(WheelDirection direction) { + return CalcDirectionValue(mCoords, direction); +} + +float WheelHandler::GetBufferedDirectionValue(WheelDirection direction) { + return CalcDirectionValue(mBufferedCoords, direction); +} +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/mouse/WheelHandler.h b/src/controller/controldevice/controller/mapping/mouse/WheelHandler.h new file mode 100644 index 000000000..092d600f7 --- /dev/null +++ b/src/controller/controldevice/controller/mapping/mouse/WheelHandler.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "window/Window.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" + +namespace Ship { +struct WheelDirections { + WheelDirection x; + WheelDirection y; +}; + +class WheelHandler { + public: + WheelHandler(); + ~WheelHandler(); + static std::shared_ptr GetInstance(); + + void Update(); + CoordsF GetCoords(); + WheelDirections GetDirections(); + float GetDirectionValue(WheelDirection direction); + float GetBufferedDirectionValue(WheelDirection direction); + + private: + static std::shared_ptr mInstance; + + WheelDirections mDirections; + CoordsF mCoords; + CoordsF mBufferedCoords; +}; +} // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.cpp b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.cpp index 7916dee94..f94c307cb 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.cpp +++ b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.cpp @@ -68,7 +68,7 @@ void SDLAxisDirectionToAxisDirectionMapping::EraseFromConfig() { CVarSave(); } -uint8_t SDLAxisDirectionToAxisDirectionMapping::GetMappingType() { +int8_t SDLAxisDirectionToAxisDirectionMapping::GetMappingType() { return MAPPING_TYPE_GAMEPAD; } } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.h b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.h index 133bb1e3c..1ff06e295 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.h +++ b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToAxisDirectionMapping.h @@ -9,7 +9,7 @@ class SDLAxisDirectionToAxisDirectionMapping final : public ControllerAxisDirect Direction direction, int32_t sdlControllerAxis, int32_t axisDirection); float GetNormalizedAxisDirectionValue() override; std::string GetAxisDirectionMappingId() override; - uint8_t GetMappingType() override; + int8_t GetMappingType() override; void SaveToConfig() override; void EraseFromConfig() override; }; diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.cpp b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.cpp index 2d9219a90..de57fe4b9 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.cpp +++ b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.cpp @@ -45,7 +45,7 @@ void SDLAxisDirectionToButtonMapping::UpdatePad(CONTROLLERBUTTONS_T& padButtons) } } -uint8_t SDLAxisDirectionToButtonMapping::GetMappingType() { +int8_t SDLAxisDirectionToButtonMapping::GetMappingType() { return MAPPING_TYPE_GAMEPAD; } diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h index 6b4590025..b5e9aeb6e 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h +++ b/src/controller/controldevice/controller/mapping/sdl/SDLAxisDirectionToButtonMapping.h @@ -7,7 +7,7 @@ class SDLAxisDirectionToButtonMapping final : public ControllerButtonMapping, pu SDLAxisDirectionToButtonMapping(ShipDeviceIndex shipDeviceIndex, uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, int32_t sdlControllerAxis, int32_t axisDirection); void UpdatePad(CONTROLLERBUTTONS_T& padButtons) override; - uint8_t GetMappingType() override; + int8_t GetMappingType() override; std::string GetButtonMappingId() override; void SaveToConfig() override; void EraseFromConfig() override; diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.cpp b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.cpp index 5693a492e..5044f4839 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.cpp +++ b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.cpp @@ -52,7 +52,7 @@ void SDLButtonToAxisDirectionMapping::EraseFromConfig() { CVarSave(); } -uint8_t SDLButtonToAxisDirectionMapping::GetMappingType() { +int8_t SDLButtonToAxisDirectionMapping::GetMappingType() { return MAPPING_TYPE_GAMEPAD; } } // namespace Ship diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.h b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.h index 2b1faa42b..445c02615 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.h +++ b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToAxisDirectionMapping.h @@ -8,7 +8,7 @@ class SDLButtonToAxisDirectionMapping final : public ControllerAxisDirectionMapp Direction direction, int32_t sdlControllerButton); float GetNormalizedAxisDirectionValue() override; std::string GetAxisDirectionMappingId() override; - uint8_t GetMappingType() override; + int8_t GetMappingType() override; void SaveToConfig() override; void EraseFromConfig() override; }; diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.cpp b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.cpp index c6cfce52d..1c3d730be 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.cpp +++ b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.cpp @@ -26,7 +26,7 @@ void SDLButtonToButtonMapping::UpdatePad(CONTROLLERBUTTONS_T& padButtons) { } } -uint8_t SDLButtonToButtonMapping::GetMappingType() { +int8_t SDLButtonToButtonMapping::GetMappingType() { return MAPPING_TYPE_GAMEPAD; } diff --git a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.h b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.h index d31941496..3271a6e0a 100644 --- a/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.h +++ b/src/controller/controldevice/controller/mapping/sdl/SDLButtonToButtonMapping.h @@ -7,7 +7,7 @@ class SDLButtonToButtonMapping final : public SDLButtonToAnyMapping, public Cont SDLButtonToButtonMapping(ShipDeviceIndex shipDeviceIndex, uint8_t portIndex, CONTROLLERBUTTONS_T bitmask, int32_t sdlControllerButton); void UpdatePad(CONTROLLERBUTTONS_T& padButtons) override; - uint8_t GetMappingType() override; + int8_t GetMappingType() override; std::string GetButtonMappingId() override; void SaveToConfig() override; void EraseFromConfig() override; diff --git a/src/controller/deviceindex/ShipDeviceIndex.h b/src/controller/deviceindex/ShipDeviceIndex.h index f22cbfee2..6280ed405 100644 --- a/src/controller/deviceindex/ShipDeviceIndex.h +++ b/src/controller/deviceindex/ShipDeviceIndex.h @@ -3,6 +3,7 @@ namespace Ship { #define SHIPDK_DEVICE_INDEX_VALUES \ + X(Mouse, -2) \ X(Keyboard, -1) \ X(Blue, 0) \ X(Red, 1) \ diff --git a/src/graphic/Fast3D/Fast3dWindow.cpp b/src/graphic/Fast3D/Fast3dWindow.cpp index 82f43b541..44ba7a416 100644 --- a/src/graphic/Fast3D/Fast3dWindow.cpp +++ b/src/graphic/Fast3D/Fast3dWindow.cpp @@ -82,6 +82,7 @@ void Fast3dWindow::Init() { height, posX, posY); mWindowManagerApi->set_fullscreen_changed_callback(OnFullscreenChanged); mWindowManagerApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp); + mWindowManagerApi->set_mouse_callbacks(MouseButtonDown, MouseButtonUp); SetTextureFilter((FilteringMode)CVarGetInteger(CVAR_TEXTURE_FILTER, FILTER_THREE_POINT)); } @@ -269,6 +270,12 @@ bool Fast3dWindow::KeyUp(int32_t scancode) { Ship::Context::GetInstance()->GetWindow()->ToggleFullscreen(); } + if (scancode == + Ship::Context::GetInstance()->GetConfig()->GetInt("Shortcuts.MouseCapture", Ship::KbScancode::LUS_KB_F2)) { + bool captureState = Ship::Context::GetInstance()->GetWindow()->IsMouseCaptured(); + Ship::Context::GetInstance()->GetWindow()->SetMouseCapture(!captureState); + } + Ship::Context::GetInstance()->GetWindow()->SetLastScancode(-1); return Ship::Context::GetInstance()->GetControlDeck()->ProcessKeyboardEvent( Ship::KbEventType::LUS_KB_EVENT_KEY_UP, static_cast(scancode)); @@ -287,15 +294,26 @@ void Fast3dWindow::AllKeysUp() { Ship::KbScancode::LUS_KB_UNKNOWN); } +bool Fast3dWindow::MouseButtonUp(int button) { + return Ship::Context::GetInstance()->GetControlDeck()->ProcessMouseButtonEvent(false, + static_cast(button)); +} + +bool Fast3dWindow::MouseButtonDown(int button) { + bool isProcessed = Ship::Context::GetInstance()->GetControlDeck()->ProcessMouseButtonEvent( + true, static_cast(button)); + return isProcessed; +} + void Fast3dWindow::OnFullscreenChanged(bool isNowFullscreen) { std::shared_ptr wnd = Ship::Context::GetInstance()->GetWindow(); if (isNowFullscreen) { auto menuBar = wnd->GetGui()->GetMenuBar(); - wnd->SetCursorVisibility(menuBar && menuBar->IsVisible() || wnd->ShouldForceCursorVisibility() || - CVarGetInteger("gWindows.Menu", 0)); + wnd->SetMouseCapture(!(menuBar && menuBar->IsVisible() || wnd->ShouldForceCursorVisibility() || + CVarGetInteger("gWindows.Menu", 0))); } else { - wnd->SetCursorVisibility(true); + wnd->SetMouseCapture(false); } } -} // namespace Fast \ No newline at end of file +} // namespace Fast diff --git a/src/graphic/Fast3D/Fast3dWindow.h b/src/graphic/Fast3D/Fast3dWindow.h index 4c3e84b1e..86676cf9d 100644 --- a/src/graphic/Fast3D/Fast3dWindow.h +++ b/src/graphic/Fast3D/Fast3dWindow.h @@ -3,6 +3,7 @@ #include "graphic/Fast3D/gfx_window_manager_api.h" #include "graphic/Fast3D/gfx_rendering_api.h" #include "public/bridge/gfxbridge.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" namespace Fast { class Fast3dWindow : public Ship::Window { @@ -50,6 +51,8 @@ class Fast3dWindow : public Ship::Window { static bool KeyDown(int32_t scancode); static bool KeyUp(int32_t scancode); static void AllKeysUp(); + static bool MouseButtonDown(int button); + static bool MouseButtonUp(int button); static void OnFullscreenChanged(bool isNowFullscreen); private: diff --git a/src/graphic/Fast3D/gfx_dxgi.cpp b/src/graphic/Fast3D/gfx_dxgi.cpp index 250a9279f..4e0387561 100644 --- a/src/graphic/Fast3D/gfx_dxgi.cpp +++ b/src/graphic/Fast3D/gfx_dxgi.cpp @@ -91,11 +91,14 @@ static struct { bool mouse_pressed[5]; float mouse_wheel[2]; LARGE_INTEGER previous_present_time; + bool is_mouse_captured; void (*on_fullscreen_changed)(bool is_now_fullscreen); bool (*on_key_down)(int scancode); bool (*on_key_up)(int scancode); - void (*on_all_keys_up)(); + void (*on_all_keys_up)(void); + bool (*on_mouse_button_down)(int btn); + bool (*on_mouse_button_up)(int btn); } dxgi; static void load_dxgi_library() { @@ -259,6 +262,22 @@ static void onkeyup(WPARAM w_param, LPARAM l_param) { } } +static void on_mouse_button_down(int btn) { + if (!(btn >= 0 && btn < 5)) { + return; + } + dxgi.mouse_pressed[btn] = true; + if (dxgi.on_mouse_button_down != nullptr) { + dxgi.on_mouse_button_down(btn); + } +} +static void on_mouse_button_up(int btn) { + dxgi.mouse_pressed[btn] = false; + if (dxgi.on_mouse_button_up != nullptr) { + dxgi.on_mouse_button_up(btn); + } +} + double HzToPeriod(double Frequency) { if (Frequency == 0) Frequency = 60; // Default to 60, to prevent devision by zero @@ -306,6 +325,15 @@ static void gfx_dxgi_close() { dxgi.is_running = false; } +static void apply_mouse_capture_clip() { + RECT rect; + rect.left = dxgi.posX + 1; + rect.top = dxgi.posY + 1; + rect.right = dxgi.posX + dxgi.current_width - 1; + rect.bottom = dxgi.posY + dxgi.current_height - 1; + ClipCursor(&rect); +} + static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) { char fileName[256]; Ship::WindowEvent event_impl; @@ -364,32 +392,36 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par onkeyup(w_param, l_param); break; case WM_LBUTTONDOWN: - dxgi.mouse_pressed[0] = true; + on_mouse_button_down(0); break; case WM_LBUTTONUP: - dxgi.mouse_pressed[0] = false; + on_mouse_button_up(0); break; case WM_MBUTTONDOWN: - dxgi.mouse_pressed[1] = true; + on_mouse_button_down(1); break; case WM_MBUTTONUP: - dxgi.mouse_pressed[1] = false; + on_mouse_button_up(1); break; case WM_RBUTTONDOWN: - dxgi.mouse_pressed[2] = true; + on_mouse_button_down(2); break; case WM_RBUTTONUP: - dxgi.mouse_pressed[2] = false; + on_mouse_button_up(2); break; - case WM_XBUTTONDOWN: - dxgi.mouse_pressed[2 + GET_XBUTTON_WPARAM(w_param)] = true; + case WM_XBUTTONDOWN: { + int btn = 2 + GET_XBUTTON_WPARAM(w_param); + on_mouse_button_down(btn); break; - case WM_XBUTTONUP: - dxgi.mouse_pressed[2 + GET_XBUTTON_WPARAM(w_param)] = false; + } + case WM_XBUTTONUP: { + int btn = 2 + GET_XBUTTON_WPARAM(w_param); + on_mouse_button_up(btn); break; + } case WM_MOUSEWHEEL: - dxgi.mouse_wheel[0] = GET_WHEEL_DELTA_WPARAM(w_param) / WHEEL_DELTA; - dxgi.mouse_wheel[1] = 0; + dxgi.mouse_wheel[0] = 0; + dxgi.mouse_wheel[1] = GET_WHEEL_DELTA_WPARAM(w_param) / WHEEL_DELTA; break; case WM_DROPFILES: DragQueryFileA((HDROP)w_param, 0, fileName, 256); @@ -404,6 +436,11 @@ static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_par dxgi.h_Monitor); GetMonitorHzPeriod(dxgi.h_Monitor, dxgi.detected_hz, dxgi.display_period); break; + case WM_SETFOCUS: + if (dxgi.is_mouse_captured) { + apply_mouse_capture_clip(); + } + break; default: return DefWindowProcW(h_wnd, message, w_param, l_param); } @@ -529,12 +566,17 @@ static void gfx_dxgi_get_mouse_pos(int32_t* x, int32_t* y) { } static void gfx_dxgi_get_mouse_delta(int32_t* x, int32_t* y) { - POINT p; - GetCursorPos(&p); - ScreenToClient(dxgi.h_wnd, &p); - *x = p.x - dxgi.current_width / 2; - *y = p.y - dxgi.current_height / 2; - SetCursorPos(dxgi.current_width / 2, dxgi.current_height / 2); + if (dxgi.is_mouse_captured) { + POINT p; + GetCursorPos(&p); + ScreenToClient(dxgi.h_wnd, &p); + *x = p.x - dxgi.current_width / 2; + *y = p.y - dxgi.current_height / 2; + SetCursorPos(dxgi.current_width / 2, dxgi.current_height / 2); + } else { + *x = 0; + *y = 0; + } } static void gfx_dxgi_get_mouse_wheel(float* x, float* y) { @@ -550,14 +592,19 @@ static bool gfx_dxgi_get_mouse_state(uint32_t btn) { static void gfx_dxgi_set_mouse_capture(bool capture) { if (capture) { + apply_mouse_capture_clip(); + gfx_dxgi_set_cursor_visibility(false); SetCapture(dxgi.h_wnd); } else { + ClipCursor(nullptr); + gfx_dxgi_set_cursor_visibility(true); ReleaseCapture(); } + dxgi.is_mouse_captured = capture; } static bool gfx_dxgi_is_mouse_captured() { - return (GetCapture() != NULL); + return dxgi.is_mouse_captured; } static void gfx_dxgi_set_fullscreen(bool enable) { @@ -575,6 +622,11 @@ static void gfx_dxgi_set_keyboard_callbacks(bool (*on_key_down)(int scancode), b dxgi.on_all_keys_up = on_all_keys_up; } +static void gfx_dxgi_set_mouse_callbacks(bool (*on_btn_down)(int btn), bool (*on_btn_up)(int btn)) { + dxgi.on_mouse_button_down = on_btn_down; + dxgi.on_mouse_button_up = on_btn_up; +} + static void gfx_dxgi_get_dimensions(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY) { *width = dxgi.current_width; *height = dxgi.current_height; @@ -983,6 +1035,7 @@ bool gfx_dxgi_is_fullscreen() { extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = { gfx_dxgi_init, gfx_dxgi_close, gfx_dxgi_set_keyboard_callbacks, + gfx_dxgi_set_mouse_callbacks, gfx_dxgi_set_fullscreen_changed_callback, gfx_dxgi_set_fullscreen, gfx_dxgi_get_active_window_refresh_rate, diff --git a/src/graphic/Fast3D/gfx_opengl.cpp b/src/graphic/Fast3D/gfx_opengl.cpp index fd6545164..a29c6508c 100644 --- a/src/graphic/Fast3D/gfx_opengl.cpp +++ b/src/graphic/Fast3D/gfx_opengl.cpp @@ -42,7 +42,6 @@ #include "gfx_cc.h" #include "gfx_rendering_api.h" #include "window/gui/Gui.h" -#include "window/Window.h" #include "gfx_pc.h" #include diff --git a/src/graphic/Fast3D/gfx_sdl2.cpp b/src/graphic/Fast3D/gfx_sdl2.cpp index e8d3316a5..864dc6581 100644 --- a/src/graphic/Fast3D/gfx_sdl2.cpp +++ b/src/graphic/Fast3D/gfx_sdl2.cpp @@ -55,6 +55,8 @@ static void (*on_fullscreen_changed_callback)(bool is_now_fullscreen); static bool (*on_key_down_callback)(int scancode); static bool (*on_key_up_callback)(int scancode); static void (*on_all_keys_up_callback)(); +static bool (*on_mouse_button_down_callback)(int btn); +static bool (*on_mouse_button_up_callback)(int btn); #ifdef _WIN32 LONG_PTR SDL_WndProc; @@ -233,7 +235,6 @@ static void set_fullscreen(bool on, bool call_callback) { SDL_DisplayMode mode; if (SDL_GetDesktopDisplayMode(display_in_use, &mode) >= 0) { SDL_SetWindowDisplayMode(wnd, &mode); - SDL_ShowCursor(false); } else { SPDLOG_ERROR(SDL_GetError()); } @@ -259,7 +260,6 @@ static void set_fullscreen(bool on, bool call_callback) { SPDLOG_ERROR("Failed to switch from or to fullscreen mode."); SPDLOG_ERROR(SDL_GetError()); } - SDL_SetCursor(SDL_DISABLE); if (on_fullscreen_changed_callback != NULL && call_callback) { on_fullscreen_changed_callback(on); @@ -485,6 +485,11 @@ static void gfx_sdl_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bo on_all_keys_up_callback = on_all_keys_up; } +static void gfx_sdl_set_mouse_callbacks(bool (*on_btn_down)(int btn), bool (*on_btn_up)(int btn)) { + on_mouse_button_down_callback = on_btn_down; + on_mouse_button_up_callback = on_btn_up; +} + static void gfx_sdl_get_dimensions(uint32_t* width, uint32_t* height, int32_t* posX, int32_t* posY) { SDL_GL_GetDrawableSize(wnd, static_cast((void*)width), static_cast((void*)height)); SDL_GetWindowPosition(wnd, static_cast(posX), static_cast(posY)); @@ -521,6 +526,21 @@ static void gfx_sdl_onkeyup(int scancode) { } } +static void gfx_sdl_on_mouse_button_down(int btn) { + if (!(btn >= 0 && btn < 5)) { + return; + } + if (on_mouse_button_down_callback != NULL) { + on_mouse_button_down_callback(btn); + } +} + +static void gfx_sdl_on_mouse_button_up(int btn) { + if (on_mouse_button_up_callback != NULL) { + on_mouse_button_up_callback(btn); + } +} + static void gfx_sdl_handle_single_event(SDL_Event& event) { Ship::WindowEvent event_impl; event_impl.Sdl = { &event }; @@ -534,6 +554,12 @@ static void gfx_sdl_handle_single_event(SDL_Event& event) { case SDL_KEYUP: gfx_sdl_onkeyup(event.key.keysym.scancode); break; + case SDL_MOUSEBUTTONDOWN: + gfx_sdl_on_mouse_button_down(event.button.button - 1); + break; + case SDL_MOUSEBUTTONUP: + gfx_sdl_on_mouse_button_up(event.button.button - 1); + break; case SDL_MOUSEWHEEL: mouse_wheel_x = event.wheel.x; mouse_wheel_y = event.wheel.y; @@ -670,6 +696,7 @@ bool gfx_sdl_is_fullscreen() { struct GfxWindowManagerAPI gfx_sdl = { gfx_sdl_init, gfx_sdl_close, gfx_sdl_set_keyboard_callbacks, + gfx_sdl_set_mouse_callbacks, gfx_sdl_set_fullscreen_changed_callback, gfx_sdl_set_fullscreen, gfx_sdl_get_active_window_refresh_rate, diff --git a/src/graphic/Fast3D/gfx_window_manager_api.h b/src/graphic/Fast3D/gfx_window_manager_api.h index c078fb807..9fd3555db 100644 --- a/src/graphic/Fast3D/gfx_window_manager_api.h +++ b/src/graphic/Fast3D/gfx_window_manager_api.h @@ -10,6 +10,7 @@ struct GfxWindowManagerAPI { void (*close)(); void (*set_keyboard_callbacks)(bool (*on_key_down)(int scancode), bool (*on_key_up)(int scancode), void (*on_all_keys_up)()); + void (*set_mouse_callbacks)(bool (*on_mouse_button_down)(int btn), bool (*on_mouse_button_up)(int btn)); void (*set_fullscreen_changed_callback)(void (*on_fullscreen_changed)(bool is_now_fullscreen)); void (*set_fullscreen)(bool enable); void (*get_active_window_refresh_rate)(uint32_t* refresh_rate); diff --git a/src/utils/glob.c b/src/utils/glob.c index ef1464b9f..a3e102930 100644 --- a/src/utils/glob.c +++ b/src/utils/glob.c @@ -101,7 +101,7 @@ bool glob_match(char const* pat, char const* str) { #ifndef _WIN32 __attribute__((fallthrough)); #endif - //fallthrough; + // fallthrough; default: /* Literal character */ literal: if (c == d) { @@ -121,6 +121,5 @@ bool glob_match(char const* pat, char const* str) { } #ifdef __cplusplus -} -; +}; #endif \ No newline at end of file diff --git a/src/window/Window.h b/src/window/Window.h index 5da4c3c7d..708b29bfe 100644 --- a/src/window/Window.h +++ b/src/window/Window.h @@ -7,12 +7,11 @@ #include #include #include "window/gui/Gui.h" +#include "controller/controldevice/controller/mapping/keyboard/KeyboardScancodes.h" namespace Ship { enum class WindowBackend { FAST3D_DXGI_DX11, FAST3D_SDL_OPENGL, FAST3D_SDL_METAL, WINDOW_BACKEND_COUNT }; -enum class MouseBtn { LEFT, MIDDLE, RIGHT, BACKWARD, FORWARD, MOUSE_BTN_COUNT }; - struct Coords { int32_t x; int32_t y; diff --git a/src/window/gui/GameOverlay.cpp b/src/window/gui/GameOverlay.cpp index 6eaf75ef7..c7a706062 100644 --- a/src/window/gui/GameOverlay.cpp +++ b/src/window/gui/GameOverlay.cpp @@ -251,4 +251,17 @@ void GameOverlay::Draw() { ImGui::End(); } + +ImGuiID GameOverlay::GetID() { + static ImGuiID windowID = 0; + if (windowID != 0) { + return windowID; + } + ImGuiWindow* window = ImGui::FindWindowByName("GameOverlay"); + if (window == NULL) { + return 0; + } + windowID = window->ID; + return windowID; +} } // namespace Ship diff --git a/src/window/gui/GameOverlay.h b/src/window/gui/GameOverlay.h index daef5e5c6..34f28927d 100644 --- a/src/window/gui/GameOverlay.h +++ b/src/window/gui/GameOverlay.h @@ -39,6 +39,7 @@ class GameOverlay { void TextDraw(float x, float y, bool shadow, ImVec4 color, const char* text, ...); void TextDrawNotification(float duration, bool shadow, const char* fmt, ...); void ClearNotifications(); + ImGuiID GetID(); protected: float GetScreenWidth(); diff --git a/src/window/gui/Gui.cpp b/src/window/gui/Gui.cpp index 3291b4951..281dadad6 100644 --- a/src/window/gui/Gui.cpp +++ b/src/window/gui/Gui.cpp @@ -291,6 +291,19 @@ void Gui::UnblockGamepadNavigation() { } } +ImGuiID Gui::GetMainGameWindowID() { + static ImGuiID windowID = 0; + if (windowID != 0) { + return windowID; + } + ImGuiWindow* window = ImGui::FindWindowByName("Main Game"); + if (window == NULL) { + return 0; + } + windowID = window->ID; + return windowID; +} + void Gui::ImGuiBackendNewFrame() { switch (Context::GetInstance()->GetWindow()->GetWindowBackend()) { #ifdef ENABLE_OPENGL @@ -481,8 +494,8 @@ void Gui::DrawMenu() { GetMenuBar()->ToggleVisibility(); } if (wnd->IsFullscreen()) { - Context::GetInstance()->GetWindow()->SetCursorVisibility(GetMenuOrMenubarVisible() || - wnd->ShouldForceCursorVisibility()); + Context::GetInstance()->GetWindow()->SetMouseCapture( + !(GetMenuOrMenubarVisible() || wnd->ShouldForceCursorVisibility())); } if (CVarGetInteger(CVAR_IMGUI_CONTROLLER_NAV, 0) && GetMenuOrMenubarVisible()) { mImGuiIo->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; @@ -525,7 +538,22 @@ void Gui::DrawMenu() { ImGui::End(); } +void Gui::HandleMouseCapture() { + ImGuiWindowFlags flags = ImGuiWindowFlags_NoMouseInputs; + for (auto windowIter : ImGui::GetCurrentContext()->WindowsById.Data) { + if (windowIter.key != GetMainGameWindowID() && windowIter.key != GetGameOverlay()->GetID()) { + ImGuiWindow* window = (ImGuiWindow*)windowIter.val_p; + if (Context::GetInstance()->GetWindow()->IsMouseCaptured()) { + window->Flags |= flags; + } else { + window->Flags &= ~(flags); + } + } + } +} + void Gui::StartFrame() { + HandleMouseCapture(); ImGuiBackendNewFrame(); ImGuiWMNewFrame(); ImGui::NewFrame(); @@ -949,9 +977,9 @@ void Gui::SetMenuBar(std::shared_ptr menuBar) { } if (Context::GetInstance()->GetWindow()->IsFullscreen()) { - Context::GetInstance()->GetWindow()->SetCursorVisibility( - (GetMenuBar() && GetMenuBar()->IsVisible()) || - Context::GetInstance()->GetWindow()->ShouldForceCursorVisibility()); + Context::GetInstance()->GetWindow()->SetMouseCapture( + !((GetMenuBar() && GetMenuBar()->IsVisible()) || + Context::GetInstance()->GetWindow()->ShouldForceCursorVisibility())); } } @@ -963,9 +991,9 @@ void Gui::SetMenu(std::shared_ptr menu) { } if (Context::GetInstance()->GetWindow()->IsFullscreen()) { - Context::GetInstance()->GetWindow()->SetCursorVisibility( - (GetMenu() && GetMenu()->IsVisible()) || - Context::GetInstance()->GetWindow()->ShouldForceCursorVisibility()); + Context::GetInstance()->GetWindow()->SetMouseCapture( + !((GetMenu() && GetMenu()->IsVisible()) || + Context::GetInstance()->GetWindow()->ShouldForceCursorVisibility())); } } @@ -977,6 +1005,22 @@ bool Gui::GetMenuOrMenubarVisible() { return (GetMenuBar() && GetMenuBar()->IsVisible()) || (GetMenu() && GetMenu()->IsVisible()); } +bool Gui::IsMouseOverAnyGuiItem() { + return ImGui::IsAnyItemHovered(); +} + +bool Gui::IsMouseOverActivePopup() { + ImGuiContext* ctx = ImGui::GetCurrentContext(); + if (ctx->OpenPopupStack.Size == 0 || ctx->HoveredWindow == NULL) { + return false; + } + ImGuiPopupData data = ctx->OpenPopupStack.back(); + if (data.Window == NULL) { + return false; + } + return (ctx->HoveredWindow->ID == data.Window->ID); +} + std::shared_ptr Gui::GetMenu() { return mMenu; } diff --git a/src/window/gui/Gui.h b/src/window/gui/Gui.h index ce828822e..10d09c865 100644 --- a/src/window/gui/Gui.h +++ b/src/window/gui/Gui.h @@ -77,6 +77,7 @@ class Gui { void SetupRendererFrame(); void SaveConsoleVariablesNextFrame(); bool SupportsViewports(); + ImGuiID GetMainGameWindowID(); void AddGuiWindow(std::shared_ptr guiWindow); std::shared_ptr GetGuiWindow(const std::string& name); @@ -98,6 +99,8 @@ class Gui { void SetMenu(std::shared_ptr menu); std::shared_ptr GetMenu(); bool GetMenuOrMenubarVisible(); + bool IsMouseOverAnyGuiItem(); + bool IsMouseOverActivePopup(); bool GamepadNavigationEnabled(); void BlockGamepadNavigation(); @@ -120,6 +123,7 @@ class Gui { void ApplyResolutionChanges(); int16_t GetIntegerScaleFactor(); void CheckSaveCvars(); + void HandleMouseCapture(); private: GuiWindowInitData mImpl; diff --git a/src/window/gui/InputEditorWindow.cpp b/src/window/gui/InputEditorWindow.cpp index c2d2d7fa5..e121c45bc 100644 --- a/src/window/gui/InputEditorWindow.cpp +++ b/src/window/gui/InputEditorWindow.cpp @@ -25,6 +25,7 @@ void InputEditorWindow::InitElement() { mDeviceIndexVisiblity.clear(); mDeviceIndexVisiblity[ShipDeviceIndex::Keyboard] = true; + mDeviceIndexVisiblity[ShipDeviceIndex::Mouse] = true; mDeviceIndexVisiblity[ShipDeviceIndex::Blue] = true; for (auto index = 1; index < ShipDeviceIndex::Max; index++) { mDeviceIndexVisiblity[static_cast(index)] = false; @@ -151,6 +152,9 @@ void InputEditorWindow::DrawAnalogPreview(const char* label, ImVec2 stick, float #define BUTTON_COLOR_KEYBOARD_BEIGE ImVec4(0.651f, 0.482f, 0.357f, 0.5f) #define BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED ImVec4(0.651f, 0.482f, 0.357f, 1.0f) +#define BUTTON_COLOR_MOUSE_BEIGE ImVec4(0.5f, 0.5f, 0.5f, 0.5f) +#define BUTTON_COLOR_MOUSE_BEIGE_HOVERED ImVec4(0.5f, 0.5f, 0.5f, 1.0f) + #define BUTTON_COLOR_GAMEPAD_BLUE ImVec4(0.0f, 0.255f, 0.976f, 0.5f) #define BUTTON_COLOR_GAMEPAD_BLUE_HOVERED ImVec4(0.0f, 0.255f, 0.976f, 1.0f) @@ -173,6 +177,10 @@ void InputEditorWindow::GetButtonColorsForShipDeviceIndex(ShipDeviceIndex lusInd buttonColor = BUTTON_COLOR_KEYBOARD_BEIGE; buttonHoveredColor = BUTTON_COLOR_KEYBOARD_BEIGE_HOVERED; break; + case ShipDeviceIndex::Mouse: + buttonColor = BUTTON_COLOR_MOUSE_BEIGE; + buttonHoveredColor = BUTTON_COLOR_MOUSE_BEIGE_HOVERED; + break; case ShipDeviceIndex::Blue: buttonColor = BUTTON_COLOR_GAMEPAD_BLUE; buttonHoveredColor = BUTTON_COLOR_GAMEPAD_BLUE_HOVERED; @@ -209,6 +217,7 @@ void InputEditorWindow::DrawButtonLineAddMappingButton(uint8_t port, CONTROLLERB if (ImGui::Button(StringHelper::Sprintf("%s###addButtonMappingButton%d-%d", ICON_FA_PLUS, port, bitmask).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), 0.0f))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); }; ImGui::PopStyleVar(); @@ -250,6 +259,7 @@ void InputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, CONTROLLER icon = ICON_FA_GAMEPAD; break; case MAPPING_TYPE_KEYBOARD: + case MAPPING_TYPE_MOUSE: icon = ICON_FA_KEYBOARD_O; break; case MAPPING_TYPE_UNKNOWN: @@ -269,6 +279,7 @@ void InputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, CONTROLLER .c_str(), ImVec2(ImGui::CalcTextSize(physicalInputDisplayName.c_str()).x + SCALE_IMGUI_SIZE(12.0f), 0.0f))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); } if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) { ImGui::SetTooltip("%s", mapping->GetPhysicalDeviceName().c_str()); @@ -316,6 +327,7 @@ void InputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, CONTROLLER if (ImGui::Button(StringHelper::Sprintf("%s###editAxisThresholdButton%s", ICON_FA_COG, id.c_str()).c_str(), ImVec2(ImGui::CalcTextSize(ICON_FA_COG).x + SCALE_IMGUI_SIZE(10.0f), 0.0f))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); } if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) { ImGui::SetTooltip("Edit axis threshold"); @@ -451,6 +463,7 @@ void InputEditorWindow::DrawStickDirectionLineAddMappingButton(uint8_t port, uin .c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), 0.0f))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); }; ImGui::PopStyleVar(); @@ -516,6 +529,7 @@ void InputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, ui icon = ICON_FA_GAMEPAD; break; case MAPPING_TYPE_KEYBOARD: + case MAPPING_TYPE_MOUSE: icon = ICON_FA_KEYBOARD_O; break; case MAPPING_TYPE_UNKNOWN: @@ -536,6 +550,7 @@ void InputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, ui .c_str(), ImVec2(ImGui::CalcTextSize(physicalInputDisplayName.c_str()).x + SCALE_IMGUI_SIZE(12.0f), 0.0f))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); } if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay)) { ImGui::SetTooltip("%s", mapping->GetPhysicalDeviceName().c_str()); @@ -812,6 +827,7 @@ void InputEditorWindow::DrawAddRumbleMappingButton(uint8_t port) { if (ImGui::Button(StringHelper::Sprintf("%s###addRumbleMapping%d", ICON_FA_PLUS, port).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); } ImGui::PopStyleVar(); @@ -992,6 +1008,7 @@ void InputEditorWindow::DrawAddLEDMappingButton(uint8_t port) { if (ImGui::Button(StringHelper::Sprintf("%s###addLEDMapping%d", ICON_FA_PLUS, port).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); } ImGui::PopStyleVar(); @@ -1071,6 +1088,7 @@ void InputEditorWindow::DrawAddGyroMappingButton(uint8_t port) { if (ImGui::Button(StringHelper::Sprintf("%s###addGyroMapping%d", ICON_FA_PLUS, port).c_str(), ImVec2(SCALE_IMGUI_SIZE(20.0f), SCALE_IMGUI_SIZE(20.0f)))) { ImGui::OpenPopup(popupId.c_str()); + OffsetMappingPopup(); } ImGui::PopStyleVar(); @@ -1180,6 +1198,7 @@ void InputEditorWindow::DrawGyroSection(uint8_t port) { void InputEditorWindow::DrawButtonDeviceIcons(uint8_t portIndex, std::set bitmasks) { std::set allLusDeviceIndices; allLusDeviceIndices.insert(ShipDeviceIndex::Keyboard); + allLusDeviceIndices.insert(ShipDeviceIndex::Mouse); for (auto [lusIndex, mapping] : Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() @@ -1215,7 +1234,7 @@ void InputEditorWindow::DrawButtonDeviceIcons(uint8_t portIndex, std::set allLusDeviceIndices; allLusDeviceIndices.insert(ShipDeviceIndex::Keyboard); + allLusDeviceIndices.insert(ShipDeviceIndex::Mouse); for (auto [lusIndex, mapping] : Context::GetInstance() ->GetControlDeck() ->GetDeviceIndexMappingManager() @@ -1266,7 +1286,7 @@ void InputEditorWindow::DrawAnalogStickDeviceIcons(uint8_t portIndex, StickIndex ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); ImGui::SameLine(); - if (lusIndex == ShipDeviceIndex::Keyboard) { + if (lusIndex == ShipDeviceIndex::Keyboard || lusIndex == ShipDeviceIndex::Mouse) { ImGui::SmallButton(ICON_FA_KEYBOARD_O); } else { ImGui::SmallButton(connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN); @@ -1418,6 +1438,20 @@ void InputEditorWindow::DrawDeviceVisibilityButtons() { ImGui::PopStyleColor(); ImGui::PopStyleColor(); + auto mouseButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); + auto mouseButtonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + GetButtonColorsForShipDeviceIndex(ShipDeviceIndex::Mouse, mouseButtonColor, mouseButtonHoveredColor); + ImGui::PushStyleColor(ImGuiCol_Button, mouseButtonColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, mouseButtonHoveredColor); + bool mouseVisible = mDeviceIndexVisiblity[ShipDeviceIndex::Mouse]; + if (ImGui::Button( + StringHelper::Sprintf("%s %s mouse", mouseVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, ICON_FA_KEYBOARD_O) + .c_str())) { + mDeviceIndexVisiblity[ShipDeviceIndex::Mouse] = !mouseVisible; + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + for (auto [lusIndex, info] : indexMappings) { auto [name, sdlIndex] = info; bool connected = sdlIndex != -1; @@ -1593,6 +1627,29 @@ void InputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { } ImGui::EndPopup(); } + ImGui::PushStyleColor(ImGuiCol_Button, BUTTON_COLOR_MOUSE_BEIGE); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, BUTTON_COLOR_MOUSE_BEIGE_HOVERED); + if (ImGui::Button(StringHelper::Sprintf("%s Mouse", ICON_FA_KEYBOARD_O).c_str())) { + ImGui::OpenPopup("Set Defaults for Mouse"); + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + if (ImGui::BeginPopupModal("Set Defaults for Mouse", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::Text("This will clear all existing mappings for\nMouse on port %d.\n\nContinue?", portIndex + 1); + if (ImGui::Button("Cancel")) { + shouldClose = true; + ImGui::CloseCurrentPopup(); + } + if (ImGui::Button("Set defaults")) { + Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->ClearAllMappingsForDevice( + ShipDeviceIndex::Mouse); + Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( + ShipDeviceIndex::Mouse); + shouldClose = true; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } for (auto [lusIndex, info] : indexMappings) { auto [name, sdlIndex] = info; @@ -1643,4 +1700,11 @@ void InputEditorWindow::DrawElement() { } ImGui::EndTabBar(); } + +void InputEditorWindow::OffsetMappingPopup() { + const float HORIZONTAL_OFFSET = 10.0f; + ImVec2 pos = ImGui::GetMousePos(); + pos.x += HORIZONTAL_OFFSET; + ImGui::SetNextWindowPos(pos); +} } // namespace Ship diff --git a/src/window/gui/InputEditorWindow.h b/src/window/gui/InputEditorWindow.h index d2c28ebe6..29f515232 100644 --- a/src/window/gui/InputEditorWindow.h +++ b/src/window/gui/InputEditorWindow.h @@ -81,5 +81,6 @@ class InputEditorWindow : public GuiWindow { std::map mDeviceIndexVisiblity; void DrawDeviceVisibilityButtons(); + void OffsetMappingPopup(); }; } // namespace Ship