diff --git a/.gitignore b/.gitignore index 35480f6..fea92c6 100644 --- a/.gitignore +++ b/.gitignore @@ -342,4 +342,7 @@ libultraship.a libultraship.lib ZAPDUtils.lib .DS_Store -.vscode +.vscode/ +.vs/ +.idea/ +cmake-build-** diff --git a/include/libultraship/libultra/controller.h b/include/libultraship/libultra/controller.h index c426c2d..8c1ddc2 100644 --- a/include/libultraship/libultra/controller.h +++ b/include/libultraship/libultra/controller.h @@ -129,11 +129,6 @@ typedef struct { /* 0x20 */ int8_t right_stick_y; } OSContPad; // size = 0x24 -typedef struct { - /* 0x00 */ uint8_t rumble; - /* 0x01 */ uint8_t ledColor; -} ControllerCallback; // size = 0x02 - typedef struct { /* 0x00 */ void* address; /* 0x04 */ uint8_t databuffer[32]; diff --git a/src/controller/ControlDeck.cpp b/src/controller/ControlDeck.cpp index c4ecbc4..44243c7 100644 --- a/src/controller/ControlDeck.cpp +++ b/src/controller/ControlDeck.cpp @@ -18,113 +18,118 @@ namespace Ship { void ControlDeck::Init(uint8_t* bits) { - ScanPhysicalDevices(); + ScanDevices(); mControllerBits = bits; } -void ControlDeck::ScanPhysicalDevices() { +void ControlDeck::ScanDevices() { + mPortList.clear(); + mDevices.clear(); - mVirtualDevices.clear(); - mPhysicalDevices.clear(); + auto controlDeck = Window::GetInstance()->GetControlDeck(); + + // Always load controllers that need their device indices zero based first because we add some other devices + // afterward. + int32_t i; #ifndef __WIIU__ - for (int32_t i = 0; i < SDL_NumJoysticks(); i++) { + for (i = 0; i < SDL_NumJoysticks(); i++) { if (SDL_IsGameController(i)) { - auto sdl = std::make_shared(i); + auto sdl = std::make_shared(controlDeck, i); sdl->Open(); - mPhysicalDevices.push_back(sdl); + mDevices.push_back(sdl); } } - mPhysicalDevices.push_back(std::make_shared("Auto", "Auto", true)); - mPhysicalDevices.push_back(std::make_shared()); + mDevices.push_back(std::make_shared(controlDeck, i++, "Auto", "Auto", true)); + mDevices.push_back(std::make_shared(controlDeck, i++)); #else - mPhysicalDevices.push_back(std::make_shared("Auto", "Auto", true)); - - auto gamepad = std::make_shared(); - gamepad->Open(); - mPhysicalDevices.push_back(gamepad); - - for (int32_t i = 0; i < 4; i++) { - auto controller = std::make_shared((WPADChan)i); + for (i = 0; i < 4; i++) { + auto controller = std::make_shared(controlDeck, i, (WPADChan)i); controller->Open(); - mPhysicalDevices.push_back(controller); + mDevices.push_back(controller); } + + auto gamepad = std::make_shared(controlDeck, i++); + gamepad->Open(); + mDevices.push_back(gamepad); + + mDevices.push_back(std::make_shared(controlDeck, i++, "Auto", "Auto", true)); #endif - mPhysicalDevices.push_back(std::make_shared("Disconnected", "None", false)); + mDevices.push_back(std::make_shared(controlDeck, i++, "Disconnected", "None", false)); - for (const auto& device : mPhysicalDevices) { + for (const auto& device : mDevices) { for (int32_t i = 0; i < MAXCONTROLLERS; i++) { device->CreateDefaultBinding(i); } } for (int32_t i = 0; i < MAXCONTROLLERS; i++) { - mVirtualDevices.push_back(i == 0 ? 0 : static_cast(mPhysicalDevices.size()) - 1); + mPortList.push_back(i == 0 ? 0 : static_cast(mDevices.size()) - 1); } - LoadControllerSettings(); + LoadSettings(); } -void ControlDeck::SetPhysicalDevice(int32_t slot, int32_t deviceSlot) { - const std::shared_ptr backend = mPhysicalDevices[deviceSlot]; - mVirtualDevices[slot] = deviceSlot; - *mControllerBits |= (backend->Connected()) << slot; +void ControlDeck::SetDeviceToPort(int32_t portIndex, int32_t deviceIndex) { + const std::shared_ptr backend = mDevices[deviceIndex]; + mPortList[portIndex] = deviceIndex; + *mControllerBits |= (backend->Connected()) << portIndex; } void ControlDeck::WriteToPad(OSContPad* pad) const { - for (size_t i = 0; i < mVirtualDevices.size(); i++) { - const std::shared_ptr backend = mPhysicalDevices[mVirtualDevices[i]]; + for (size_t i = 0; i < mPortList.size(); i++) { + const std::shared_ptr backend = mDevices[mPortList[i]]; // If the controller backend is "Auto" we need to get the real device // we search for the real device to read input from it if (backend->GetGuid() == "Auto") { - for (const auto& device : mPhysicalDevices) { + for (const auto& device : mDevices) { if (ShouldBlockGameInput(device->GetGuid())) { - device->Read(nullptr, i); + device->ReadToPad(nullptr, i); continue; } - device->Read(&pad[i], i); + device->ReadToPad(&pad[i], i); } continue; } if (ShouldBlockGameInput(backend->GetGuid())) { - backend->Read(nullptr, i); + backend->ReadToPad(nullptr, i); continue; } - backend->Read(&pad[i], i); + backend->ReadToPad(&pad[i], i); } } #define NESTED(key, ...) \ StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), virtualSlot, __VA_ARGS__) -void ControlDeck::LoadControllerSettings() { +void ControlDeck::LoadSettings() { std::shared_ptr config = Window::GetInstance()->GetConfig(); for (auto const& val : config->rjson["Controllers"]["Deck"].items()) { int32_t slot = std::stoi(val.key().substr(5)); - for (size_t dev = 0; dev < mPhysicalDevices.size(); dev++) { - std::string guid = mPhysicalDevices[dev]->GetGuid(); + for (size_t dev = 0; dev < mDevices.size(); dev++) { + std::string guid = mDevices[dev]->GetGuid(); if (guid != val.value().get()) { continue; } - mVirtualDevices[slot] = dev; + mPortList[slot] = dev; } } - for (size_t i = 0; i < mVirtualDevices.size(); i++) { - std::shared_ptr backend = mPhysicalDevices[mVirtualDevices[i]]; + for (size_t i = 0; i < mPortList.size(); i++) { + std::shared_ptr backend = mDevices[mPortList[i]]; config->setString(StringHelper::Sprintf("Controllers.Deck.Slot_%d", (int)i), backend->GetGuid()); } - for (const auto& device : mPhysicalDevices) { + for (const auto& device : mDevices) { std::string guid = device->GetGuid(); for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { @@ -134,7 +139,7 @@ void ControlDeck::LoadControllerSettings() { continue; } - auto profile = device->getProfile(virtualSlot); + auto profile = device->GetProfile(virtualSlot); auto rawProfile = config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", virtualSlot)]; profile->Mappings.clear(); @@ -194,21 +199,19 @@ void ControlDeck::LoadControllerSettings() { } } -void ControlDeck::SaveControllerSettings() { +void ControlDeck::SaveSettings() { std::shared_ptr config = Window::GetInstance()->GetConfig(); - for (size_t i = 0; i < mVirtualDevices.size(); i++) { - std::shared_ptr backend = mPhysicalDevices[mVirtualDevices[i]]; + for (size_t i = 0; i < mPortList.size(); i++) { + std::shared_ptr backend = mDevices[mPortList[i]]; config->setString(StringHelper::Sprintf("Controllers.Deck.Slot_%d", (int)i), backend->GetGuid()); } - for (const auto& device : mPhysicalDevices) { - - int32_t virtualSlot = 0; + for (const auto& device : mDevices) { std::string guid = device->GetGuid(); for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - auto profile = device->getProfile(virtualSlot); + auto profile = device->GetProfile(virtualSlot); if (!device->Connected()) { continue; @@ -248,24 +251,24 @@ void ControlDeck::SaveControllerSettings() { config->save(); } -std::shared_ptr ControlDeck::GetPhysicalDevice(int32_t deviceSlot) { - return mPhysicalDevices[deviceSlot]; +std::shared_ptr ControlDeck::GetDeviceFromDeviceIndex(int32_t deviceIndex) { + return mDevices[deviceIndex]; } -size_t ControlDeck::GetNumPhysicalDevices() { - return mPhysicalDevices.size(); +size_t ControlDeck::GetNumDevices() { + return mDevices.size(); } -int32_t ControlDeck::GetVirtualDevice(int32_t slot) { - return mVirtualDevices[slot]; +int32_t ControlDeck::GetDeviceIndexFromPortIndex(int32_t portIndex) { + return mPortList[portIndex]; } -size_t ControlDeck::GetNumVirtualDevices() { - return mVirtualDevices.size(); +size_t ControlDeck::GetNumConnectedPorts() { + return mPortList.size(); } -std::shared_ptr ControlDeck::GetPhysicalDeviceFromVirtualSlot(int32_t slot) { - return GetPhysicalDevice(GetVirtualDevice(slot)); +std::shared_ptr ControlDeck::GetDeviceFromPortIndex(int32_t portIndex) { + return GetDeviceFromDeviceIndex(GetDeviceIndexFromPortIndex(portIndex)); } uint8_t* ControlDeck::GetControllerBits() { diff --git a/src/controller/ControlDeck.h b/src/controller/ControlDeck.h index 2cf3af9..cd12622 100644 --- a/src/controller/ControlDeck.h +++ b/src/controller/ControlDeck.h @@ -9,24 +9,24 @@ namespace Ship { class ControlDeck { public: void Init(uint8_t* controllerBits); - void ScanPhysicalDevices(); + void ScanDevices(); void WriteToPad(OSContPad* pad) const; - void LoadControllerSettings(); - void SaveControllerSettings(); - void SetPhysicalDevice(int32_t slot, int32_t deviceSlot); - std::shared_ptr GetPhysicalDevice(int32_t deviceSlot); - std::shared_ptr GetPhysicalDeviceFromVirtualSlot(int32_t slot); - size_t GetNumPhysicalDevices(); - int32_t GetVirtualDevice(int32_t slot); - size_t GetNumVirtualDevices(); + void LoadSettings(); + void SaveSettings(); + void SetDeviceToPort(int32_t portIndex, int32_t deviceIndex); + std::shared_ptr GetDeviceFromDeviceIndex(int32_t deviceIndex); + std::shared_ptr GetDeviceFromPortIndex(int32_t portIndex); + int32_t GetDeviceIndexFromPortIndex(int32_t portIndex); + size_t GetNumDevices(); + size_t GetNumConnectedPorts(); uint8_t* GetControllerBits(); void BlockGameInput(); void UnblockGameInput(); bool ShouldBlockGameInput(std::string inputDeviceGuid) const; private: - std::vector mVirtualDevices = {}; - std::vector> mPhysicalDevices = {}; + std::vector mPortList = {}; + std::vector> mDevices = {}; uint8_t* mControllerBits = nullptr; bool mShouldBlockGameInput = false; }; diff --git a/src/controller/Controller.cpp b/src/controller/Controller.cpp index bfefad0..58aebee 100644 --- a/src/controller/Controller.cpp +++ b/src/controller/Controller.cpp @@ -14,40 +14,39 @@ namespace Ship { -Controller::Controller() : mIsRumbling(false) { - mAttachment = nullptr; - - for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - mProfiles[virtualSlot] = std::make_shared(); - mButtonData[virtualSlot] = std::make_shared(); +Controller::Controller(std::shared_ptr controlDeck, int32_t deviceIndex) + : mIsRumbling(false), mAttachment(nullptr), mDeviceIndex(deviceIndex), mControlDeck(controlDeck) { + for (int32_t portIndex = 0; portIndex < MAXCONTROLLERS; portIndex++) { + mProfiles[portIndex] = std::make_shared(); + mButtonData[portIndex] = std::make_shared(); } } -int8_t Controller::ReadStick(int32_t virtualSlot, Stick stick, Axis axis) { +int8_t Controller::ReadStick(int32_t portIndex, Stick stick, Axis axis) { switch (stick) { case Stick::LEFT: { switch (axis) { case Axis::X: { - if (getLeftStickX(virtualSlot) == 0) { - if (getPressedButtons(virtualSlot) & BTN_STICKLEFT) { + if (GetLeftStickX(portIndex) == 0) { + if (GetPressedButtons(portIndex) & BTN_STICKLEFT) { return -MAX_AXIS_RANGE; - } else if (getPressedButtons(virtualSlot) & BTN_STICKRIGHT) { + } else if (GetPressedButtons(portIndex) & BTN_STICKRIGHT) { return MAX_AXIS_RANGE; } } else { - return getLeftStickX(virtualSlot); + return GetLeftStickX(portIndex); } break; } case Axis::Y: { - if (getLeftStickY(virtualSlot) == 0) { - if (getPressedButtons(virtualSlot) & BTN_STICKDOWN) { + if (GetLeftStickY(portIndex) == 0) { + if (GetPressedButtons(portIndex) & BTN_STICKDOWN) { return -MAX_AXIS_RANGE; - } else if (getPressedButtons(virtualSlot) & BTN_STICKUP) { + } else if (GetPressedButtons(portIndex) & BTN_STICKUP) { return MAX_AXIS_RANGE; } } else { - return getLeftStickY(virtualSlot); + return GetLeftStickY(portIndex); } break; } @@ -57,26 +56,26 @@ int8_t Controller::ReadStick(int32_t virtualSlot, Stick stick, Axis axis) { case Stick::RIGHT: { switch (axis) { case Axis::X: { - if (getRightStickX(virtualSlot) == 0) { - if (getPressedButtons(virtualSlot) & BTN_VSTICKLEFT) { + if (GetRightStickX(portIndex) == 0) { + if (GetPressedButtons(portIndex) & BTN_VSTICKLEFT) { return -MAX_AXIS_RANGE; - } else if (getPressedButtons(virtualSlot) & BTN_VSTICKRIGHT) { + } else if (GetPressedButtons(portIndex) & BTN_VSTICKRIGHT) { return MAX_AXIS_RANGE; } } else { - return getRightStickX(virtualSlot); + return GetRightStickX(portIndex); } break; } case Axis::Y: { - if (getRightStickY(virtualSlot) == 0) { - if (getPressedButtons(virtualSlot) & BTN_VSTICKDOWN) { + if (GetRightStickY(portIndex) == 0) { + if (GetPressedButtons(portIndex) & BTN_VSTICKDOWN) { return -MAX_AXIS_RANGE; - } else if (getPressedButtons(virtualSlot) & BTN_VSTICKUP) { + } else if (GetPressedButtons(portIndex) & BTN_VSTICKUP) { return MAX_AXIS_RANGE; } } else { - return getRightStickY(virtualSlot); + return GetRightStickY(portIndex); } break; } @@ -138,8 +137,8 @@ void Controller::ProcessStick(int8_t& x, int8_t& y, float deadzoneX, float deadz y = copysign(uy, y); } -void Controller::Read(OSContPad* pad, int32_t virtualSlot) { - ReadFromSource(virtualSlot); +void Controller::ReadToPad(OSContPad* pad, int32_t portIndex) { + ReadDevice(portIndex); OSContPad padToBuffer = { 0 }; @@ -148,15 +147,15 @@ void Controller::Read(OSContPad* pad, int32_t virtualSlot) { #endif // Button Inputs - padToBuffer.button |= getPressedButtons(virtualSlot) & 0xFFFF; + padToBuffer.button |= GetPressedButtons(portIndex) & 0xFFFF; // Stick Inputs - int8_t leftStickX = ReadStick(virtualSlot, LEFT, X); - int8_t leftStickY = ReadStick(virtualSlot, LEFT, Y); - int8_t rightStickX = ReadStick(virtualSlot, RIGHT, X); - int8_t rightStickY = ReadStick(virtualSlot, RIGHT, Y); + int8_t leftStickX = ReadStick(portIndex, LEFT, X); + int8_t leftStickY = ReadStick(portIndex, LEFT, Y); + int8_t rightStickX = ReadStick(portIndex, RIGHT, X); + int8_t rightStickY = ReadStick(portIndex, RIGHT, Y); - auto profile = getProfile(virtualSlot); + auto profile = GetProfile(portIndex); ProcessStick(leftStickX, leftStickY, profile->AxisDeadzones[0], profile->AxisDeadzones[1], profile->NotchProximityThreshold); ProcessStick(rightStickX, rightStickY, profile->AxisDeadzones[2], profile->AxisDeadzones[3], @@ -172,8 +171,8 @@ void Controller::Read(OSContPad* pad, int32_t virtualSlot) { padToBuffer.right_stick_y = rightStickY; // Gyro - padToBuffer.gyro_x = getGyroX(virtualSlot); - padToBuffer.gyro_y = getGyroY(virtualSlot); + padToBuffer.gyro_x = GetGyroX(portIndex); + padToBuffer.gyro_y = GetGyroY(portIndex); mPadBuffer.push_front(padToBuffer); if (pad != nullptr) { @@ -205,42 +204,42 @@ void Controller::Read(OSContPad* pad, int32_t virtualSlot) { } } -void Controller::SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t scancode) { - std::map& mappings = getProfile(virtualSlot)->Mappings; +void Controller::SetButtonMapping(int32_t portIndex, int32_t n64Button, int32_t scancode) { + std::map& mappings = GetProfile(portIndex)->Mappings; std::erase_if(mappings, [n64Button](const std::pair& bin) { return bin.second == n64Button; }); mappings[scancode] = n64Button; } -int8_t& Controller::getLeftStickX(int32_t virtualSlot) { - return mButtonData[virtualSlot]->LeftStickX; +int8_t& Controller::GetLeftStickX(int32_t portIndex) { + return mButtonData[portIndex]->LeftStickX; } -int8_t& Controller::getLeftStickY(int32_t virtualSlot) { - return mButtonData[virtualSlot]->LeftStickY; +int8_t& Controller::GetLeftStickY(int32_t portIndex) { + return mButtonData[portIndex]->LeftStickY; } -int8_t& Controller::getRightStickX(int32_t virtualSlot) { - return mButtonData[virtualSlot]->RightStickX; +int8_t& Controller::GetRightStickX(int32_t portIndex) { + return mButtonData[portIndex]->RightStickX; } -int8_t& Controller::getRightStickY(int32_t virtualSlot) { - return mButtonData[virtualSlot]->RightStickY; +int8_t& Controller::GetRightStickY(int32_t portIndex) { + return mButtonData[portIndex]->RightStickY; } -int32_t& Controller::getPressedButtons(int32_t virtualSlot) { - return mButtonData[virtualSlot]->PressedButtons; +int32_t& Controller::GetPressedButtons(int32_t portIndex) { + return mButtonData[portIndex]->PressedButtons; } -float& Controller::getGyroX(int32_t virtualSlot) { - return mButtonData[virtualSlot]->GyroX; +float& Controller::GetGyroX(int32_t portIndex) { + return mButtonData[portIndex]->GyroX; } -float& Controller::getGyroY(int32_t virtualSlot) { - return mButtonData[virtualSlot]->GyroY; +float& Controller::GetGyroY(int32_t portIndex) { + return mButtonData[portIndex]->GyroY; } -std::shared_ptr Controller::getProfile(int32_t virtualSlot) { - return mProfiles[virtualSlot]; +std::shared_ptr Controller::GetProfile(int32_t portIndex) { + return mProfiles[portIndex]; } std::shared_ptr Controller::GetAttachment() { @@ -255,10 +254,18 @@ std::string Controller::GetGuid() { return mGuid; } +std::string Controller::GetControllerName() { + return mControllerName; +} + double Controller::GetClosestNotch(double angle, double approximationThreshold) { constexpr auto octagonAngle = M_TAU / 8; const auto closestNotch = std::round(angle / octagonAngle) * octagonAngle; const auto distanceToNotch = std::abs(fmod(closestNotch - angle + M_PI, M_TAU) - M_PI); return distanceToNotch < approximationThreshold / 2 ? closestNotch : angle; } + +std::shared_ptr Controller::GetControlDeck() { + return mControlDeck; +} } // namespace Ship diff --git a/src/controller/Controller.h b/src/controller/Controller.h index def65ec..186d868 100644 --- a/src/controller/Controller.h +++ b/src/controller/Controller.h @@ -33,41 +33,49 @@ struct DeviceProfile { std::map Mappings; }; +class ControlDeck; + class Controller { public: virtual ~Controller() = default; - Controller(); - virtual void ReadFromSource(int32_t virtualSlot) = 0; - virtual void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) = 0; + Controller(std::shared_ptr controlDeck, int32_t deviceIndex); + virtual void ReadDevice(int32_t portIndex) = 0; virtual bool Connected() const = 0; virtual bool CanRumble() const = 0; + virtual bool CanSetLed() const = 0; virtual bool CanGyro() const = 0; - virtual void CreateDefaultBinding(int32_t virtualSlot) = 0; + virtual void CreateDefaultBinding(int32_t portIndex) = 0; virtual void ClearRawPress() = 0; virtual int32_t ReadRawPress() = 0; - virtual const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) = 0; - virtual const std::string GetControllerName() = 0; - void Read(OSContPad* pad, int32_t virtualSlot); - void SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t scancode); + virtual const std::string GetButtonName(int32_t portIndex, int32_t n64Button) = 0; + virtual int32_t SetRumble(int32_t portIndex, bool rumble) = 0; + virtual int32_t SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) = 0; + + std::string GetControllerName(); + void ReadToPad(OSContPad* pad, int32_t portIndex); + void SetButtonMapping(int32_t portIndex, int32_t n64Button, int32_t scancode); std::shared_ptr GetAttachment(); - std::shared_ptr getProfile(int32_t virtualSlot); - int8_t& getLeftStickX(int32_t virtualSlot); - int8_t& getLeftStickY(int32_t virtualSlot); - int8_t& getRightStickX(int32_t virtualSlot); - int8_t& getRightStickY(int32_t virtualSlot); - int32_t& getPressedButtons(int32_t virtualSlot); - float& getGyroX(int32_t virtualSlot); - float& getGyroY(int32_t virtualSlot); + std::shared_ptr GetProfile(int32_t portIndex); + int8_t& GetLeftStickX(int32_t portIndex); + int8_t& GetLeftStickY(int32_t portIndex); + int8_t& GetRightStickX(int32_t portIndex); + int8_t& GetRightStickY(int32_t portIndex); + int32_t& GetPressedButtons(int32_t portIndex); + float& GetGyroX(int32_t portIndex); + float& GetGyroY(int32_t portIndex); bool IsRumbling(); std::string GetGuid(); + std::shared_ptr GetControlDeck(); protected: std::shared_ptr mAttachment; std::string mGuid; bool mIsRumbling; + int32_t mDeviceIndex; + std::string mControllerName = "Unknown"; void LoadBinding(); - int8_t ReadStick(int32_t virtualSlot, Stick stick, Axis axis); + int8_t ReadStick(int32_t portIndex, Stick stick, Axis axis); void ProcessStick(int8_t& x, int8_t& y, float deadzoneX, float deadzoneY, int32_t notchProxmityThreshold); private: @@ -84,6 +92,7 @@ class Controller { std::unordered_map> mProfiles; std::unordered_map> mButtonData = {}; std::deque mPadBuffer; + std::shared_ptr mControlDeck; double GetClosestNotch(double angle, double approximationThreshold); }; diff --git a/src/controller/DummyController.cpp b/src/controller/DummyController.cpp index 84697ff..d7736b7 100644 --- a/src/controller/DummyController.cpp +++ b/src/controller/DummyController.cpp @@ -1,30 +1,38 @@ #include "DummyController.h" namespace Ship { -DummyController::DummyController(const std::string& guid, const std::string& keyName, bool connected) { +DummyController::DummyController(std::shared_ptr controlDeck, int32_t deviceIndex, const std::string& guid, + const std::string& keyName, bool connected) + : Controller(controlDeck, deviceIndex) { mGuid = guid; + mControllerName = guid; mIsConnected = connected; mButtonName = keyName; } -void DummyController::ReadFromSource(int32_t virtualSlot) { +void DummyController::ReadDevice(int32_t portIndex) { } -const std::string DummyController::GetControllerName() { - return mGuid; -} - -const std::string DummyController::GetButtonName(int32_t virtualSlot, int32_t n64Button) { +const std::string DummyController::GetButtonName(int32_t portIndex, int32_t n64Button) { return mButtonName; } -void DummyController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { -} - bool DummyController::Connected() const { return mIsConnected; } +int32_t DummyController::SetRumble(int32_t portIndex, bool rumble) { + return -1000; +} + +int32_t DummyController::SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) { + return -1000; +} + +bool DummyController::CanSetLed() const { + return false; +} + bool DummyController::CanRumble() const { return false; } @@ -33,19 +41,7 @@ bool DummyController::CanGyro() const { return false; } -void DummyController::CreateDefaultBinding(int32_t slot) { -} - -std::string DummyController::GetControllerType() { - return "Unk"; -} - -std::string DummyController::GetConfSection() { - return "Unk"; -} - -std::string DummyController::GetBindingConfSection() { - return "Unk"; +void DummyController::CreateDefaultBinding(int32_t portIndex) { } void DummyController::ClearRawPress() { diff --git a/src/controller/DummyController.h b/src/controller/DummyController.h index ecc6f55..2ec5de2 100644 --- a/src/controller/DummyController.h +++ b/src/controller/DummyController.h @@ -7,26 +7,23 @@ namespace Ship { class DummyController final : public Controller { public: - DummyController(const std::string& guid, const std::string& keyName, bool connected); + DummyController(std::shared_ptr controlDeck, int32_t deviceIndex, const std::string& guid, + const std::string& keyName, bool connected); std::map, int32_t> ReadButtonPress(); - void ReadFromSource(int32_t virtualSlot) override; - const std::string GetControllerName() override; - const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override; - void WriteToSource(int32_t slot, ControllerCallback* controller) override; + void ReadDevice(int32_t portIndex) override; + const std::string GetButtonName(int32_t portIndex, int32_t n64Button) override; bool Connected() const override; bool CanRumble() const override; + bool CanSetLed() const override; bool CanGyro() const override; void ClearRawPress() override; int32_t ReadRawPress() override; - bool HasPadConf() const; - std::optional GetPadConfSection(); - void CreateDefaultBinding(int32_t virtualSlot) override; + int32_t SetRumble(int32_t portIndex, bool rumble) override; + int32_t SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) override; + void CreateDefaultBinding(int32_t portIndex) override; protected: std::string mButtonName; bool mIsConnected = false; - std::string GetControllerType(); - std::string GetConfSection(); - std::string GetBindingConfSection(); }; } // namespace Ship \ No newline at end of file diff --git a/src/controller/KeyboardController.cpp b/src/controller/KeyboardController.cpp index 77f20ad..10a3794 100644 --- a/src/controller/KeyboardController.cpp +++ b/src/controller/KeyboardController.cpp @@ -11,18 +11,20 @@ namespace Ship { -KeyboardController::KeyboardController() : Controller(), mLastScancode(-1) { +KeyboardController::KeyboardController(std::shared_ptr controlDeck, int32_t deviceIndex) + : Controller(controlDeck, deviceIndex), mLastScancode(-1) { mGuid = "Keyboard"; + mControllerName = "Keyboard"; } bool KeyboardController::PressButton(int32_t scancode) { mLastKey = scancode; bool readSuccess = false; - for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { + for (int32_t portIndex = 0; portIndex < MAXCONTROLLERS; portIndex++) { - if (getProfile(virtualSlot)->Mappings.contains(scancode)) { - getPressedButtons(virtualSlot) |= getProfile(virtualSlot)->Mappings[scancode]; + if (GetProfile(portIndex)->Mappings.contains(scancode)) { + GetPressedButtons(portIndex) |= GetProfile(portIndex)->Mappings[scancode]; readSuccess = true; } } @@ -33,9 +35,9 @@ bool KeyboardController::PressButton(int32_t scancode) { bool KeyboardController::ReleaseButton(int32_t scancode) { bool readSuccess = false; - for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - if (getProfile(virtualSlot)->Mappings.contains(scancode)) { - getPressedButtons(virtualSlot) &= ~getProfile(virtualSlot)->Mappings[scancode]; + for (int32_t portIndex = 0; portIndex < MAXCONTROLLERS; portIndex++) { + if (GetProfile(portIndex)->Mappings.contains(scancode)) { + GetPressedButtons(portIndex) &= ~GetProfile(portIndex)->Mappings[scancode]; readSuccess = true; } } @@ -44,40 +46,37 @@ bool KeyboardController::ReleaseButton(int32_t scancode) { } void KeyboardController::ReleaseAllButtons() { - for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - getPressedButtons(virtualSlot) = 0; + for (int32_t portIndex = 0; portIndex < MAXCONTROLLERS; portIndex++) { + GetPressedButtons(portIndex) = 0; } } -void KeyboardController::ReadFromSource(int32_t virtualSlot) { - getLeftStickX(virtualSlot) = 0; - getLeftStickY(virtualSlot) = 0; - getRightStickX(virtualSlot) = 0; - getRightStickY(virtualSlot) = 0; +void KeyboardController::ReadDevice(int32_t portIndex) { + GetLeftStickX(portIndex) = 0; + GetLeftStickY(portIndex) = 0; + GetRightStickX(portIndex) = 0; + GetRightStickY(portIndex) = 0; } int32_t KeyboardController::ReadRawPress() { return mLastKey; } -void KeyboardController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { -} - -const std::string KeyboardController::GetButtonName(int32_t virtualSlot, int32_t n64Button) { - std::map& Mappings = getProfile(virtualSlot)->Mappings; +const std::string KeyboardController::GetButtonName(int32_t portIndex, int32_t n64Button) { + std::map& mappings = GetProfile(portIndex)->Mappings; const auto find = - std::find_if(Mappings.begin(), Mappings.end(), + std::find_if(mappings.begin(), mappings.end(), [n64Button](const std::pair& pair) { return pair.second == n64Button; }); - if (find == Mappings.end()) { + if (find == mappings.end()) { return "Unknown"; } const char* name = Window::GetInstance()->GetKeyName(find->first); return strlen(name) == 0 ? "Unknown" : name; } -void KeyboardController::CreateDefaultBinding(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void KeyboardController::CreateDefaultBinding(int32_t portIndex) { + auto profile = GetProfile(portIndex); profile->Mappings[0x14D] = BTN_CRIGHT; profile->Mappings[0x14B] = BTN_CLEFT; profile->Mappings[0x150] = BTN_CDOWN; @@ -100,10 +99,6 @@ void KeyboardController::CreateDefaultBinding(int32_t virtualSlot) { profile->Mappings[0x036] = BTN_MODIFIER2; } -const std::string KeyboardController::GetControllerName() { - return "Keyboard"; -} - bool KeyboardController::Connected() const { return true; } @@ -127,4 +122,17 @@ void KeyboardController::SetLastScancode(int32_t key) { int32_t KeyboardController::GetLastScancode() { return mLastScancode; } + +bool KeyboardController::CanSetLed() const { + return false; +} + +int32_t KeyboardController::SetRumble(int32_t portIndex, bool rumble) { + return -1001; +} + +int32_t KeyboardController::SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) { + // Not supported today, but theoretically we could tie into some of the keyboard APIs to set RGB lights. + return -1001; +} } // namespace Ship diff --git a/src/controller/KeyboardController.h b/src/controller/KeyboardController.h index 355a268..42e65a4 100644 --- a/src/controller/KeyboardController.h +++ b/src/controller/KeyboardController.h @@ -5,23 +5,24 @@ namespace Ship { class KeyboardController : public Controller { public: - KeyboardController(); + KeyboardController(std::shared_ptr controlDeck, int32_t deviceIndex); - void ReadFromSource(int32_t virtualSlot) override; - void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override; - const std::string GetControllerName() override; - const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override; + void ReadDevice(int32_t portIndex) override; + const std::string GetButtonName(int32_t portIndex, int32_t n64Button) override; bool PressButton(int32_t scancode); bool ReleaseButton(int32_t scancode); bool Connected() const override; bool CanRumble() const override; + bool CanSetLed() const override; bool CanGyro() const override; void ClearRawPress() override; + int32_t SetRumble(int32_t portIndex, bool rumble) override; + int32_t SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) override; + void CreateDefaultBinding(int32_t portIndex) override; int32_t ReadRawPress() override; void ReleaseAllButtons(); void SetLastScancode(int32_t key); int32_t GetLastScancode(); - void CreateDefaultBinding(int32_t virtualSlot) override; protected: int32_t mLastScancode; diff --git a/src/controller/SDLController.cpp b/src/controller/SDLController.cpp index 26e3442..ea47e20 100644 --- a/src/controller/SDLController.cpp +++ b/src/controller/SDLController.cpp @@ -3,7 +3,6 @@ #include "SDLController.h" #include -#include "core/Window.h" #include #ifdef _MSC_VER @@ -14,11 +13,12 @@ namespace Ship { -SDLController::SDLController(int32_t physicalSlot) : Controller(), mController(nullptr), mPhysicalSlot(physicalSlot) { +SDLController::SDLController(std::shared_ptr controlDeck, int32_t deviceIndex) + : Controller(controlDeck, deviceIndex), mController(nullptr) { } bool SDLController::Open() { - const auto newCont = SDL_GameControllerOpen(mPhysicalSlot); + const auto newCont = SDL_GameControllerOpen(mDeviceIndex); // We failed to load the controller. Go to next. if (newCont == nullptr) { @@ -32,16 +32,16 @@ bool SDLController::Open() { mSupportsGyro = true; } - char GuidBuf[33]; - SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(mPhysicalSlot), GuidBuf, sizeof(GuidBuf)); + char guidBuf[33]; + SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(mDeviceIndex), guidBuf, sizeof(guidBuf)); mController = newCont; #ifdef __SWITCH__ - mGuid = StringHelper::Sprintf("%s:%d", GuidBuf, mPhysicalSlot); - mControllerName = StringHelper::Sprintf("%s #%d", SDL_GameControllerNameForIndex(mPhysicalSlot), mPhysicalSlot + 1); + mGuid = StringHelper::Sprintf("%s:%d", guidBuf, mDeviceIndex); + mControllerName = StringHelper::Sprintf("%s #%d", SDL_GameControllerNameForIndex(mDeviceIndex), mDeviceIndex + 1); #else - mGuid = std::string(GuidBuf); - mControllerName = std::string(SDL_GameControllerNameForIndex(mPhysicalSlot)); + mGuid = std::string(guidBuf); + mControllerName = std::string(SDL_GameControllerNameForIndex(mDeviceIndex)); #endif return true; } @@ -58,8 +58,7 @@ bool SDLController::Close() { return true; } -void SDLController::NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, - int32_t virtualSlot) { +void SDLController::NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int32_t portIndex) { const auto axisValueX = SDL_GameControllerGetAxis(mController, axisX); const auto axisValueY = SDL_GameControllerGetAxis(mController, axisY); @@ -68,11 +67,11 @@ void SDLController::NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameCon auto ay = axisValueY * MAX_AXIS_RANGE / MAX_SDL_RANGE; if (axisX == SDL_CONTROLLER_AXIS_LEFTX) { - getLeftStickX(virtualSlot) = +ax; - getLeftStickY(virtualSlot) = -ay; + GetLeftStickX(portIndex) = +ax; + GetLeftStickY(portIndex) = -ay; } else if (axisX == SDL_CONTROLLER_AXIS_RIGHTX) { - getRightStickX(virtualSlot) = +ax; - getRightStickY(virtualSlot) = -ay; + GetRightStickX(portIndex) = +ax; + GetRightStickY(portIndex) = -ay; } } @@ -101,8 +100,8 @@ int32_t SDLController::ReadRawPress() { return -1; } -void SDLController::ReadFromSource(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void SDLController::ReadDevice(int32_t portIndex) { + auto profile = GetProfile(portIndex); SDL_GameControllerUpdate(); @@ -126,7 +125,7 @@ void SDLController::ReadFromSource(int32_t virtualSlot) { float gyroDriftX = profile->GyroData[DRIFT_X] / 100.0f; float gyroDriftY = profile->GyroData[DRIFT_Y] / 100.0f; - const float gyro_sensitivity = profile->GyroData[GYRO_SENSITIVITY]; + const float gyroSensitivity = profile->GyroData[GYRO_SENSITIVITY]; if (gyroDriftX == 0) { gyroDriftX = gyroData[0]; @@ -139,24 +138,24 @@ void SDLController::ReadFromSource(int32_t virtualSlot) { profile->GyroData[DRIFT_X] = gyroDriftX * 100.0f; profile->GyroData[DRIFT_Y] = gyroDriftY * 100.0f; - getGyroX(virtualSlot) = gyroData[0] - gyroDriftX; - getGyroY(virtualSlot) = gyroData[1] - gyroDriftY; + GetGyroX(portIndex) = gyroData[0] - gyroDriftX; + GetGyroY(portIndex) = gyroData[1] - gyroDriftY; - getGyroX(virtualSlot) *= gyro_sensitivity; - getGyroY(virtualSlot) *= gyro_sensitivity; + GetGyroX(portIndex) *= gyroSensitivity; + GetGyroY(portIndex) *= gyroSensitivity; } else { - getGyroX(virtualSlot) = 0; - getGyroY(virtualSlot) = 0; + GetGyroX(portIndex) = 0; + GetGyroY(portIndex) = 0; } - getPressedButtons(virtualSlot) = 0; + GetPressedButtons(portIndex) = 0; for (int32_t i = SDL_CONTROLLER_BUTTON_A; i < SDL_CONTROLLER_BUTTON_MAX; i++) { if (profile->Mappings.contains(i)) { if (SDL_GameControllerGetButton(mController, static_cast(i))) { - getPressedButtons(virtualSlot) |= profile->Mappings[i]; + GetPressedButtons(portIndex) |= profile->Mappings[i]; } else { - getPressedButtons(virtualSlot) &= ~profile->Mappings[i]; + GetPressedButtons(portIndex) &= ~profile->Mappings[i]; } } } @@ -196,14 +195,14 @@ void SDLController::ReadFromSource(int32_t virtualSlot) { // The axis is being treated as a "button" if (axisValue > axisMinimumPress) { - getPressedButtons(virtualSlot) |= posButton; - getPressedButtons(virtualSlot) &= ~negButton; + GetPressedButtons(portIndex) |= posButton; + GetPressedButtons(portIndex) &= ~negButton; } else if (axisValue < -axisMinimumPress) { - getPressedButtons(virtualSlot) &= ~posButton; - getPressedButtons(virtualSlot) |= negButton; + GetPressedButtons(portIndex) &= ~posButton; + GetPressedButtons(portIndex) |= negButton; } else { - getPressedButtons(virtualSlot) &= ~posButton; - getPressedButtons(virtualSlot) &= ~negButton; + GetPressedButtons(portIndex) &= ~posButton; + GetPressedButtons(portIndex) &= ~negButton; } } else { // The axis is being treated as a "stick" @@ -277,45 +276,42 @@ void SDLController::ReadFromSource(int32_t virtualSlot) { } if (leftStickAxisX != SDL_CONTROLLER_AXIS_INVALID && leftStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - NormalizeStickAxis(leftStickAxisX, leftStickAxisY, virtualSlot); + NormalizeStickAxis(leftStickAxisX, leftStickAxisY, portIndex); } if (rightStickAxisX != SDL_CONTROLLER_AXIS_INVALID && rightStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - NormalizeStickAxis(rightStickAxisX, rightStickAxisY, virtualSlot); + NormalizeStickAxis(rightStickAxisX, rightStickAxisY, portIndex); } } -void SDLController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { - if (CanRumble() && getProfile(virtualSlot)->UseRumble) { - if (controller->rumble > 0) { - float rumble_strength = getProfile(virtualSlot)->RumbleStrength; - SDL_GameControllerRumble(mController, 0xFFFF * rumble_strength, 0xFFFF * rumble_strength, 0); - } else { - SDL_GameControllerRumble(mController, 0, 0, 0); - } +int32_t SDLController::SetRumble(int32_t portIndex, bool rumble) { + if (!CanRumble()) { + return -1000; } - if (SDL_GameControllerHasLED(mController)) { - switch (controller->ledColor) { - case 0: - SDL_JoystickSetLED(SDL_GameControllerGetJoystick(mController), 255, 0, 0); - break; - case 1: - SDL_JoystickSetLED(SDL_GameControllerGetJoystick(mController), 0x1E, 0x69, 0x1B); - break; - case 2: - SDL_JoystickSetLED(SDL_GameControllerGetJoystick(mController), 0x64, 0x14, 0x00); - break; - case 3: - SDL_JoystickSetLED(SDL_GameControllerGetJoystick(mController), 0x00, 0x3C, 0x64); - break; - } + if (!GetProfile(portIndex)->UseRumble) { + return -1001; + } + + if (rumble) { + float rumbleStrength = GetProfile(portIndex)->RumbleStrength; + return SDL_GameControllerRumble(mController, 0xFFFF * rumbleStrength, 0xFFFF * rumbleStrength, 0); + } else { + return SDL_GameControllerRumble(mController, 0, 0, 0); } } -const std::string SDLController::GetButtonName(int32_t virtualSlot, int32_t n64Button) { +int32_t SDLController::SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) { + if (!CanSetLed()) { + return -1000; + } + + return SDL_JoystickSetLED(SDL_GameControllerGetJoystick(mController), r, g, b); +} + +const std::string SDLController::GetButtonName(int32_t portIndex, int32_t n64Button) { char buffer[50]; - std::map& mappings = getProfile(virtualSlot)->Mappings; + std::map& mappings = GetProfile(portIndex)->Mappings; const auto find = std::find_if(mappings.begin(), mappings.end(), @@ -338,12 +334,8 @@ const std::string SDLController::GetButtonName(int32_t virtualSlot, int32_t n64B return buffer; } -const std::string SDLController::GetControllerName() { - return mControllerName; -} - -void SDLController::CreateDefaultBinding(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void SDLController::CreateDefaultBinding(int32_t portIndex) { + auto profile = GetProfile(portIndex); profile->Mappings.clear(); profile->AxisDeadzones.clear(); profile->AxisMinimumPress.clear(); @@ -400,6 +392,10 @@ bool SDLController::CanRumble() const { return false; } +bool SDLController::CanSetLed() const { + return SDL_GameControllerHasLED(mController); +} + void SDLController::ClearRawPress() { } } // namespace Ship diff --git a/src/controller/SDLController.h b/src/controller/SDLController.h index d4ee397..36dcd7b 100644 --- a/src/controller/SDLController.h +++ b/src/controller/SDLController.h @@ -5,14 +5,15 @@ namespace Ship { class SDLController : public Controller { public: - SDLController(int32_t physicalSlot); - void ReadFromSource(int32_t virtualSlot) override; - const std::string GetControllerName() override; - const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override; - void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override; + SDLController(std::shared_ptr controlDeck, int32_t deviceIndex); + void ReadDevice(int32_t portIndex) override; + const std::string GetButtonName(int32_t portIndex, int32_t n64Button) override; + int32_t SetRumble(int32_t portIndex, bool rumble) override; + int32_t SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) override; bool Connected() const override; bool CanGyro() const override; bool CanRumble() const override; + bool CanSetLed() const override; bool Open(); void ClearRawPress() override; int32_t ReadRawPress() override; @@ -21,14 +22,12 @@ class SDLController : public Controller { inline static const char* AxisNames[] = { "Left Stick X", "Left Stick Y", "Right Stick X", "Right Stick Y", "Left Trigger", "Right Trigger", "Start Button" }; - void CreateDefaultBinding(int32_t virtualSlot) override; + void CreateDefaultBinding(int32_t portIndex) override; private: - std::string mControllerName = "Unknown"; SDL_GameController* mController; - int32_t mPhysicalSlot; bool mSupportsGyro; - void NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int32_t virtualSlot); + void NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int32_t portIndex); bool Close(); }; } // namespace Ship diff --git a/src/core/Window.cpp b/src/core/Window.cpp index 4ea878b..73924ef 100644 --- a/src/core/Window.cpp +++ b/src/core/Window.cpp @@ -140,7 +140,7 @@ void Window::Initialize(const std::vector& otrFiles, const std::uno mWindowManagerApi->set_fullscreen_changed_callback(OnFullscreenChanged); mWindowManagerApi->set_keyboard_callbacks(KeyDown, KeyUp, AllKeysUp); - Ship::RegisterHook([this]() { mControlDeck->SaveControllerSettings(); }); + Ship::RegisterHook([this]() { mControlDeck->SaveSettings(); }); } void Window::Close() { @@ -229,7 +229,7 @@ bool Window::KeyUp(int32_t scancode) { bool isProcessed = false; auto controlDeck = GetInstance()->GetControlDeck(); const auto pad = dynamic_cast( - controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get()); + controlDeck->GetDeviceFromDeviceIndex(controlDeck->GetNumDevices() - 2).get()); if (pad != nullptr) { if (pad->ReleaseButton(scancode)) { isProcessed = true; @@ -243,7 +243,7 @@ bool Window::KeyDown(int32_t scancode) { bool isProcessed = false; auto controlDeck = GetInstance()->GetControlDeck(); const auto pad = dynamic_cast( - controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get()); + controlDeck->GetDeviceFromDeviceIndex(controlDeck->GetNumDevices() - 2).get()); if (pad != nullptr) { if (pad->PressButton(scancode)) { isProcessed = true; @@ -258,7 +258,7 @@ bool Window::KeyDown(int32_t scancode) { void Window::AllKeysUp(void) { auto controlDeck = Window::GetInstance()->GetControlDeck(); const auto pad = dynamic_cast( - controlDeck->GetPhysicalDevice(controlDeck->GetNumPhysicalDevices() - 2).get()); + controlDeck->GetDeviceFromDeviceIndex(controlDeck->GetNumDevices() - 2).get()); if (pad != nullptr) { pad->ReleaseAllButtons(); } @@ -270,7 +270,7 @@ void Window::OnFullscreenChanged(bool isNowFullscreen) { Window::GetInstance()->mIsFullscreen = isNowFullscreen; pConf->setBool("Window.Fullscreen.Enabled", isNowFullscreen); if (isNowFullscreen) { - bool menuBarOpen = Window::GetInstance()->GetMenuBar(); + bool menuBarOpen = GetMenuBar(); Window::GetInstance()->SetCursorVisibility(menuBarOpen); } else if (!isNowFullscreen) { Window::GetInstance()->SetCursorVisibility(true); @@ -529,14 +529,6 @@ bool Window::IsFullscreen() { return mIsFullscreen; } -uint32_t Window::GetMenuBar() { - return mMenuBar; -} - -void Window::SetMenuBar(uint32_t menuBar) { - this->mMenuBar = menuBar; -} - std::string Window::GetName() { return mName; } diff --git a/src/core/Window.h b/src/core/Window.h index 0fc7d33..e743a3e 100644 --- a/src/core/Window.h +++ b/src/core/Window.h @@ -51,8 +51,6 @@ class Window { bool CanDisableVerticalSync(); float GetCurrentAspectRatio(); bool IsFullscreen(); - uint32_t GetMenuBar(); - void SetMenuBar(uint32_t menuBar); std::string GetName(); std::string GetShortName(); std::shared_ptr GetControlDeck(); @@ -107,7 +105,6 @@ class Window { uint32_t mRefreshRate; uint32_t mWidth; uint32_t mHeight; - bool mMenuBar; int32_t mLastScancode; std::string mName; std::string mShortName; diff --git a/src/menu/ImGuiImpl.cpp b/src/menu/ImGuiImpl.cpp index c68f699..8c4d9e4 100644 --- a/src/menu/ImGuiImpl.cpp +++ b/src/menu/ImGuiImpl.cpp @@ -94,6 +94,7 @@ static ImVector s_GroupPanelLabelStack; std::function clientDrawMenu; std::function clientSetupHooks; +bool mMenuBar; bool needsSave = false; int lastRenderingBackendID = 0; int lastAudioBackendID = 0; @@ -503,7 +504,7 @@ void InitGui(WindowImpl windowImpl) { Ship::RegisterHook([] { bool menuBarOpen = CVarGetInteger("gOpenMenuBar", 0); - Window::GetInstance()->SetMenuBar(menuBarOpen); + SetMenuBar(menuBarOpen); if (Window::GetInstance()->IsFullscreen()) { setCursorVisibility(menuBarOpen); } @@ -590,11 +591,11 @@ void DrawMainMenuAndCalculateGameSize(void) { bool menuBar = !CVarGetInteger("gOpenMenuBar", 0); CVarSetInteger("gOpenMenuBar", menuBar); needsSave = true; - Window::GetInstance()->SetMenuBar(menuBar); + SetMenuBar(menuBar); if (Window::GetInstance()->IsFullscreen()) { setCursorVisibility(menuBar); } - Window::GetInstance()->GetControlDeck()->SaveControllerSettings(); + Window::GetInstance()->GetControlDeck()->SaveSettings(); if (CVarGetInteger("gControlNav", 0) && CVarGetInteger("gOpenMenuBar", 0)) { io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; } else { @@ -1180,4 +1181,12 @@ void EndGroupPanel(float minHeight) { ImGui::EndGroup(); } + +uint32_t GetMenuBar() { + return mMenuBar; +} + +void SetMenuBar(uint32_t menuBar) { + mMenuBar = menuBar; +} } // namespace Ship diff --git a/src/menu/ImGuiImpl.h b/src/menu/ImGuiImpl.h index 7a1f99a..09fe88a 100644 --- a/src/menu/ImGuiImpl.h +++ b/src/menu/ImGuiImpl.h @@ -88,6 +88,10 @@ void RenderImGui(void); void CancelFrame(void); void DrawSettings(); +// OTRTODO: Rename these two +uint32_t GetMenuBar(); +void SetMenuBar(uint32_t menuBar); + Backend WindowBackend(); std::vector> GetAvailableRenderingBackends(); std::pair GetCurrentRenderingBackend(); diff --git a/src/menu/InputEditor.cpp b/src/menu/InputEditor.cpp index b994dd9..bbbae4d 100644 --- a/src/menu/InputEditor.cpp +++ b/src/menu/InputEditor.cpp @@ -17,7 +17,7 @@ void InputEditor::Init() { std::shared_ptr GetControllerPerSlot(int slot) { auto controlDeck = Ship::Window::GetInstance()->GetControlDeck(); - return controlDeck->GetPhysicalDeviceFromVirtualSlot(slot); + return controlDeck->GetDeviceFromPortIndex(slot); } void InputEditor::DrawButton(const char* label, int32_t n64Btn, int32_t currentPort, int32_t* btnReading) { @@ -67,16 +67,16 @@ void InputEditor::DrawButton(const char* label, int32_t n64Btn, int32_t currentP void InputEditor::DrawControllerSelect(int32_t currentPort) { auto controlDeck = Ship::Window::GetInstance()->GetControlDeck(); - std::string controllerName = controlDeck->GetPhysicalDeviceFromVirtualSlot(currentPort)->GetControllerName(); + std::string controllerName = controlDeck->GetDeviceFromPortIndex(currentPort)->GetControllerName(); if (ImGui::BeginCombo("##ControllerEntries", controllerName.c_str())) { - for (uint8_t i = 0; i < controlDeck->GetNumPhysicalDevices(); i++) { - std::string deviceName = controlDeck->GetPhysicalDevice(i)->GetControllerName(); + for (uint8_t i = 0; i < controlDeck->GetNumDevices(); i++) { + std::string deviceName = controlDeck->GetDeviceFromDeviceIndex(i)->GetControllerName(); if (deviceName != "Keyboard" && deviceName != "Auto") { deviceName += "##" + std::to_string(i); } - if (ImGui::Selectable(deviceName.c_str(), i == controlDeck->GetVirtualDevice(currentPort))) { - controlDeck->SetPhysicalDevice(currentPort, i); + if (ImGui::Selectable(deviceName.c_str(), i == controlDeck->GetDeviceIndexFromPortIndex(currentPort))) { + controlDeck->SetDeviceToPort(currentPort, i); } } ImGui::EndCombo(); @@ -85,7 +85,7 @@ void InputEditor::DrawControllerSelect(int32_t currentPort) { ImGui::SameLine(); if (ImGui::Button("Refresh")) { - controlDeck->ScanPhysicalDevices(); + controlDeck->ScanDevices(); } } @@ -111,11 +111,11 @@ void InputEditor::DrawVirtualStick(const char* label, ImVec2 stick) { } void InputEditor::DrawControllerSchema() { - auto backend = Ship::Window::GetInstance()->GetControlDeck()->GetPhysicalDeviceFromVirtualSlot(mCurrentPort); - auto profile = backend->getProfile(mCurrentPort); + auto backend = Ship::Window::GetInstance()->GetControlDeck()->GetDeviceFromPortIndex(mCurrentPort); + auto profile = backend->GetProfile(mCurrentPort); bool isKeyboard = backend->GetGuid() == "Keyboard" || backend->GetGuid() == "Auto" || !backend->Connected(); - backend->Read(nullptr, mCurrentPort); + backend->ReadToPad(nullptr, mCurrentPort); DrawControllerSelect(mCurrentPort); @@ -154,7 +154,7 @@ void InputEditor::DrawControllerSchema() { if (!isKeyboard) { ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8); DrawVirtualStick("##MainVirtualStick", - ImVec2(backend->getLeftStickX(mCurrentPort), backend->getLeftStickY(mCurrentPort))); + ImVec2(backend->GetLeftStickX(mCurrentPort), backend->GetLeftStickY(mCurrentPort))); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); @@ -200,7 +200,7 @@ void InputEditor::DrawControllerSchema() { // 2 is the SDL value for right stick X axis // 3 is the SDL value for right stick Y axis. DrawVirtualStick("##RightVirtualStick", - ImVec2(backend->getRightStickX(mCurrentPort), backend->getRightStickY(mCurrentPort))); + ImVec2(backend->GetRightStickX(mCurrentPort), backend->GetRightStickY(mCurrentPort))); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); @@ -256,7 +256,7 @@ void InputEditor::DrawControllerSchema() { } ImGui::SetCursorPosX(cursorX); DrawVirtualStick("##GyroPreview", - ImVec2(-10.0f * backend->getGyroY(mCurrentPort), 10.0f * backend->getGyroX(mCurrentPort))); + ImVec2(-10.0f * backend->GetGyroY(mCurrentPort), 10.0f * backend->GetGyroX(mCurrentPort))); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); diff --git a/src/port/wiiu/WiiUController.cpp b/src/port/wiiu/WiiUController.cpp index 58b3bd0..d49804d 100644 --- a/src/port/wiiu/WiiUController.cpp +++ b/src/port/wiiu/WiiUController.cpp @@ -6,70 +6,72 @@ #include "WiiUImpl.h" namespace Ship { -WiiUController::WiiUController(WPADChan chan) : Controller(), chan(chan) { - connected = false; - extensionType = (WPADExtensionType)-1; - - controllerName = std::string("Wii U Controller ") + std::to_string((int)chan) + " (Disconnected)"; +WiiUController::WiiUController(std::shared_ptr controlDeck, int32_t deviceIndex, WPADChan chan) + : Controller(controlDeck, deviceIndex), mChan(chan) { + mConnected = false; + mExtensionType = (WPADExtensionType)-1; + mControllerName = std::string("Wii U Controller ") + std::to_string((int)mChan) + " (Disconnected)"; } bool WiiUController::Open() { KPADError error; - KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error); + KPADStatus* status = Ship::WiiU::GetKPADStatus(mChan, &error); if (!status || error != KPAD_ERROR_OK) { Close(); return false; } - connected = true; - extensionType = (WPADExtensionType)status->extensionType; + mConnected = true; + mControllerName = std::string("Wii U Controller ") + std::to_string((int)mChan); + mExtensionType = (WPADExtensionType)status->extensionType; // Create a GUID and name based on extension and channel - mGuid = std::string("WiiU") + GetControllerExtensionName() + std::to_string((int)chan); - controllerName = - std::string("Wii U ") + GetControllerExtensionName() + std::string(" ") + std::to_string((int)chan); + mGuid = std::string("WiiU") + GetControllerExtensionName() + std::to_string((int)mChan); + mControllerName = + std::string("Wii U ") + GetControllerExtensionName() + std::string(" ") + std::to_string((int)mChan); return true; } void WiiUController::Close() { - connected = false; - extensionType = (WPADExtensionType)-1; + mConnected = false; + mControllerName = std::string("Wii U Controller ") + std::to_string((int)mChan) + " (Disconnected)"; + mExtensionType = (WPADExtensionType)-1; for (int i = 0; i < MAXCONTROLLERS; i++) { - getPressedButtons(i) = 0; - getLeftStickX(i) = 0; - getLeftStickY(i) = 0; - getRightStickX(i) = 0; - getRightStickY(i) = 0; - getGyroX(i) = 0; - getGyroY(i) = 0; + GetPressedButtons(i) = 0; + GetLeftStickX(i) = 0; + GetLeftStickY(i) = 0; + GetRightStickX(i) = 0; + GetRightStickY(i) = 0; + GetGyroX(i) = 0; + GetGyroY(i) = 0; } } -void WiiUController::ReadFromSource(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void WiiUController::ReadDevice(int32_t portIndex) { + auto profile = GetProfile(portIndex); KPADError error; - KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error); + KPADStatus* status = Ship::WiiU::GetKPADStatus(mChan, &error); if (!status) { Close(); return; } // Make sure the controller type doesn't change after opening - if (status->extensionType != extensionType) { + if (status->extensionType != mExtensionType) { Close(); return; } - getPressedButtons(virtualSlot) = 0; - getLeftStickX(virtualSlot) = 0; - getLeftStickY(virtualSlot) = 0; - getRightStickX(virtualSlot) = 0; - getRightStickY(virtualSlot) = 0; - getGyroX(virtualSlot) = 0; - getGyroY(virtualSlot) = 0; + GetPressedButtons(portIndex) = 0; + GetLeftStickX(portIndex) = 0; + GetLeftStickY(portIndex) = 0; + GetRightStickX(portIndex) = 0; + GetRightStickY(portIndex) = 0; + GetGyroX(portIndex) = 0; + GetGyroY(portIndex) = 0; if (error != KPAD_ERROR_OK) { return; @@ -80,7 +82,7 @@ void WiiUController::ReadFromSource(int32_t virtualSlot) { int16_t camX = 0; int16_t camY = 0; - switch (extensionType) { + switch (mExtensionType) { case WPAD_EXT_PRO_CONTROLLER: for (uint32_t i = WPAD_PRO_BUTTON_UP; i <= WPAD_PRO_STICK_R_EMULATION_UP; i <<= 1) { if (profile->Mappings.contains(i)) { @@ -107,7 +109,7 @@ void WiiUController::ReadFromSource(int32_t virtualSlot) { } if (status->pro.hold & i) { - getPressedButtons(virtualSlot) |= profile->Mappings[i]; + GetPressedButtons(portIndex) |= profile->Mappings[i]; } } } @@ -139,7 +141,7 @@ void WiiUController::ReadFromSource(int32_t virtualSlot) { } if (status->classic.hold & i) { - getPressedButtons(virtualSlot) |= profile->Mappings[i]; + GetPressedButtons(portIndex) |= profile->Mappings[i]; } } } @@ -151,7 +153,7 @@ void WiiUController::ReadFromSource(int32_t virtualSlot) { for (uint32_t i = WPAD_BUTTON_LEFT; i <= WPAD_BUTTON_HOME; i <<= 1) { if (profile->Mappings.contains(i)) { if (status->hold & i) { - getPressedButtons(virtualSlot) |= profile->Mappings[i]; + GetPressedButtons(portIndex) |= profile->Mappings[i]; } } } @@ -161,28 +163,39 @@ void WiiUController::ReadFromSource(int32_t virtualSlot) { } if (stickX || stickY) { - getLeftStickX(virtualSlot) = stickX; - getLeftStickY(virtualSlot) = stickY; + GetLeftStickX(portIndex) = stickX; + GetLeftStickY(portIndex) = stickY; } if (camX || camY) { - getRightStickX(virtualSlot) = camX; - getRightStickY(virtualSlot) = camY; + GetRightStickX(portIndex) = camX; + GetRightStickY(portIndex) = camY; } } -void WiiUController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { - if (getProfile(virtualSlot)->UseRumble) { - WPADControlMotor(chan, controller->rumble); +int32_t WiiUController::SetRumble(int32_t portIndex, bool rumble) { + if (!CanRumble()) { + return -1000; } + + if (GetProfile(portIndex)->UseRumble) { + return -1001; + } + + WPADControlMotor(mChan, rumble); + return 0; +} + +int32_t WiiUController::SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) { + return -1000; } void WiiUController::ClearRawPress() { // Clear already triggered buttons KPADError error; - KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error); + KPADStatus* status = Ship::WiiU::GetKPADStatus(mChan, &error); if (status) { - switch (extensionType) { + switch (mExtensionType) { case WPAD_EXT_PRO_CONTROLLER: status->pro.trigger = 0; break; @@ -202,12 +215,12 @@ void WiiUController::ClearRawPress() { int32_t WiiUController::ReadRawPress() { KPADError error; - KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error); + KPADStatus* status = Ship::WiiU::GetKPADStatus(mChan, &error); if (!status || error != KPAD_ERROR_OK) { return -1; } - switch (extensionType) { + switch (mExtensionType) { case WPAD_EXT_PRO_CONTROLLER: for (uint32_t i = WPAD_PRO_BUTTON_UP; i <= WPAD_PRO_STICK_R_EMULATION_UP; i <<= 1) { if (status->pro.trigger & i) { @@ -290,8 +303,8 @@ int32_t WiiUController::ReadRawPress() { return -1; } -const std::string WiiUController::GetButtonName(int32_t virtualSlot, int n64Button) { - std::map& Mappings = getProfile(virtualSlot)->Mappings; +const std::string WiiUController::GetButtonName(int32_t portIndex, int n64Button) { + std::map& Mappings = GetProfile(portIndex)->Mappings; const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair& pair) { return pair.second == n64Button; }); @@ -301,7 +314,7 @@ const std::string WiiUController::GetButtonName(int32_t virtualSlot, int n64Butt uint32_t btn = find->first; - switch (extensionType) { + switch (mExtensionType) { case WPAD_EXT_PRO_CONTROLLER: switch (btn) { case WPAD_PRO_BUTTON_A: @@ -439,19 +452,15 @@ const std::string WiiUController::GetButtonName(int32_t virtualSlot, int n64Butt return "Unknown"; } -const std::string WiiUController::GetControllerName() { - return controllerName; -} - -void WiiUController::CreateDefaultBinding(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void WiiUController::CreateDefaultBinding(int32_t portIndex) { + auto profile = GetProfile(portIndex); profile->Mappings.clear(); profile->UseRumble = true; profile->RumbleStrength = 1.0f; profile->UseGyro = false; - switch (extensionType) { + switch (mExtensionType) { case WPAD_EXT_PRO_CONTROLLER: profile->Mappings[WPAD_PRO_STICK_R_EMULATION_RIGHT] = BTN_CRIGHT; profile->Mappings[WPAD_PRO_STICK_R_EMULATION_LEFT] = BTN_CLEFT; @@ -517,7 +526,7 @@ void WiiUController::CreateDefaultBinding(int32_t virtualSlot) { } std::string WiiUController::GetControllerExtensionName() { - switch (extensionType) { + switch (mExtensionType) { case WPAD_EXT_PRO_CONTROLLER: return "ProController"; case WPAD_EXT_CLASSIC: @@ -532,5 +541,21 @@ std::string WiiUController::GetControllerExtensionName() { return "Controller"; } + +bool WiiUController::Connected() const override { + return mConnected; +}; + +bool WiiUController::CanGyro() const override { + return false; +} + +bool WiiUController::CanRumble() const override { + return true; +}; + +bool WiiUController::CanSetLed() const { + return false; +} } // namespace Ship #endif diff --git a/src/port/wiiu/WiiUController.h b/src/port/wiiu/WiiUController.h index 80db9b6..ee62640 100644 --- a/src/port/wiiu/WiiUController.h +++ b/src/port/wiiu/WiiUController.h @@ -10,37 +10,28 @@ namespace Ship { class WiiUController : public Controller { public: - WiiUController(WPADChan chan); + WiiUController(std::shared_ptr controlDeck, int32_t deviceIndex, WPADChan chan); bool Open(); void Close(); - - void ReadFromSource(int32_t virtualSlot) override; - void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override; - bool Connected() const override { - return connected; - }; - bool CanGyro() const override { - return false; - } - bool CanRumble() const override { - return true; - }; - + void ReadDevice(int32_t portIndex) override; + bool Connected() const; + bool CanGyro() const; + bool CanRumble() const; + bool CanSetLed() const override; void ClearRawPress() override; int32_t ReadRawPress() override; - - const std::string GetButtonName(int32_t virtualSlot, int n64Button) override; - const std::string GetControllerName() override; + int32_t SetRumble(int32_t portIndex, bool rumble) override; + int32_t SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) override; + const std::string GetButtonName(int32_t portIndex, int n64Button) override; protected: - void CreateDefaultBinding(int32_t virtualSlot) override; + void CreateDefaultBinding(int32_t portIndex) override; private: std::string GetControllerExtensionName(); - std::string controllerName; - bool connected; - WPADChan chan; - WPADExtensionType extensionType; + bool mConnected; + WPADChan mChan; + WPADExtensionType mExtensionType; }; } // namespace Ship diff --git a/src/port/wiiu/WiiUGamepad.cpp b/src/port/wiiu/WiiUGamepad.cpp index c6d847c..5088af7 100644 --- a/src/port/wiiu/WiiUGamepad.cpp +++ b/src/port/wiiu/WiiUGamepad.cpp @@ -5,10 +5,11 @@ #include "WiiUImpl.h" namespace Ship { -WiiUGamepad::WiiUGamepad() : Controller(), connected(true), rumblePatternStrength(1.0f) { - memset(rumblePattern, 0xff, sizeof(rumblePattern)); - +WiiUGamepad::WiiUGamepad(std::shared_ptr controlDeck, int32_t deviceIndex) + : Controller(controlDeck, deviceIndex), mConnected(true), mRumblePatternStrength(1.0f) { + memset(mRumblePattern, 0xff, sizeof(mRumblePattern)); mGuid = "WiiUGamepad"; + mControllerName = "Wii U GamePad"; } bool WiiUGamepad::Open() { @@ -19,25 +20,29 @@ bool WiiUGamepad::Open() { return false; } + mConnected = true; + mControllerName = "Wii U GamePad"; + return true; } void WiiUGamepad::Close() { - connected = false; + mConnected = false; + mControllerName = "Wii U Gamepad (Disconnected)"; for (int i = 0; i < MAXCONTROLLERS; i++) { - getPressedButtons(i) = 0; - getLeftStickX(i) = 0; - getLeftStickY(i) = 0; - getRightStickX(i) = 0; - getRightStickY(i) = 0; - getGyroX(i) = 0; - getGyroY(i) = 0; + GetPressedButtons(i) = 0; + GetLeftStickX(i) = 0; + GetLeftStickY(i) = 0; + GetRightStickX(i) = 0; + GetRightStickY(i) = 0; + GetGyroX(i) = 0; + GetGyroY(i) = 0; } } -void WiiUGamepad::ReadFromSource(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void WiiUGamepad::ReadDevice(int32_t portIndex) { + auto profile = GetProfile(portIndex); VPADReadError error; VPADStatus* status = Ship::WiiU::GetVPADStatus(&error); @@ -46,13 +51,13 @@ void WiiUGamepad::ReadFromSource(int32_t virtualSlot) { return; } - getPressedButtons(virtualSlot) = 0; - getLeftStickX(virtualSlot) = 0; - getLeftStickY(virtualSlot) = 0; - getRightStickX(virtualSlot) = 0; - getRightStickY(virtualSlot) = 0; - getGyroX(virtualSlot) = 0; - getGyroY(virtualSlot) = 0; + GetPressedButtons(portIndex) = 0; + GetLeftStickX(portIndex) = 0; + GetLeftStickY(portIndex) = 0; + GetRightStickX(portIndex) = 0; + GetRightStickY(portIndex) = 0; + GetGyroX(portIndex) = 0; + GetGyroY(portIndex) = 0; if (error != VPAD_READ_SUCCESS) { return; @@ -86,19 +91,19 @@ void WiiUGamepad::ReadFromSource(int32_t virtualSlot) { } if (status->hold & i) { - getPressedButtons(virtualSlot) |= profile->Mappings[i]; + GetPressedButtons(portIndex) |= profile->Mappings[i]; } } } if (stickX || stickY) { - getLeftStickX(virtualSlot) = stickX; - getLeftStickY(virtualSlot) = stickY; + GetLeftStickX(portIndex) = stickX; + GetLeftStickY(portIndex) = stickY; } if (camX || camY) { - getRightStickX(virtualSlot) = camX; - getRightStickY(virtualSlot) = camY; + GetRightStickX(portIndex) = camX; + GetRightStickY(portIndex) = camY; } if (profile->UseGyro) { @@ -120,42 +125,51 @@ void WiiUGamepad::ReadFromSource(int32_t virtualSlot) { profile->GyroData[DRIFT_X] = gyro_drift_x * 100.0f; profile->GyroData[DRIFT_Y] = gyro_drift_y * 100.0f; - getGyroX(virtualSlot) = gyroX - gyro_drift_x; - getGyroY(virtualSlot) = gyroY - gyro_drift_y; + GetGyroX(portIndex) = gyroX - gyro_drift_x; + GetGyroY(portIndex) = gyroY - gyro_drift_y; - getGyroX(virtualSlot) *= gyro_sensitivity; - getGyroY(virtualSlot) *= gyro_sensitivity; + GetGyroX(portIndex) *= gyro_sensitivity; + GetGyroY(portIndex) *= gyro_sensitivity; } } -void WiiUGamepad::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { - auto profile = getProfile(virtualSlot); +int32_t WiiUGamepad::SetRumble(int32_t portIndex, bool rumble) { + if (!CanRumble()) { + return -1000; + } - if (profile->UseRumble) { - int patternSize = sizeof(rumblePattern) * 8; + if (!profile->UseRumble) { + return -1001; + } - // update rumble pattern if strength changed - if (rumblePatternStrength != profile->RumbleStrength) { - rumblePatternStrength = profile->RumbleStrength; - if (rumblePatternStrength > 1.0f) { - rumblePatternStrength = 1.0f; - } else if (rumblePatternStrength < 0.0f) { - rumblePatternStrength = 0.0f; - } + auto profile = GetProfile(portIndex); + int32_t patternSize = sizeof(mRumblePattern) * 8; - memset(rumblePattern, 0, sizeof(rumblePattern)); - - // distribute wanted amount of bits equally in pattern - float scale = (rumblePatternStrength * (1.0f - 0.3f)) + 0.3f; - int bitcnt = patternSize * scale; - for (int i = 0; i < bitcnt; i++) { - int bitpos = ((i * patternSize) / bitcnt) % patternSize; - rumblePattern[bitpos / 8] |= 1 << (bitpos % 8); - } + // update rumble pattern if strength changed + if (mRumblePatternStrength != profile->RumbleStrength) { + mRumblePatternStrength = profile->RumbleStrength; + if (mRumblePatternStrength > 1.0f) { + mRumblePatternStrength = 1.0f; + } else if (mRumblePatternStrength < 0.0f) { + mRumblePatternStrength = 0.0f; } - VPADControlMotor(VPAD_CHAN_0, rumblePattern, controller->rumble ? patternSize : 0); + memset(mRumblePattern, 0, sizeof(mRumblePattern)); + + // distribute wanted amount of bits equally in pattern + float scale = (mRumblePatternStrength * (1.0f - 0.3f)) + 0.3f; + int32_t bitcnt = patternSize * scale; + for (int32_t i = 0; i < bitcnt; i++) { + int32_t bitpos = ((i * patternSize) / bitcnt) % patternSize; + mRumblePattern[bitpos / 8] |= 1 << (bitpos % 8); + } } + + return VPADControlMotor(VPAD_CHAN_0, mRumblePattern, rumble ? patternSize : 0); +} + +int32_t WiiUGamepad::SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) { + return -1000; } void WiiUGamepad::ClearRawPress() { @@ -209,13 +223,13 @@ int32_t WiiUGamepad::ReadRawPress() { return -1; } -const std::string WiiUGamepad::GetButtonName(int32_t virtualSlot, int n64Button) { - std::map& Mappings = getProfile(virtualSlot)->Mappings; +const std::string WiiUGamepad::GetButtonName(int32_t portIndex, int n64Button) { + std::map& mappings = GetProfile(portIndex)->Mappings; const auto find = - std::find_if(Mappings.begin(), Mappings.end(), + std::find_if(mappings.begin(), mappings.end(), [n64Button](const std::pair& pair) { return pair.second == n64Button; }); - if (find == Mappings.end()) + if (find == mappings.end()) return "Unknown"; uint32_t btn = find->first; @@ -273,12 +287,8 @@ const std::string WiiUGamepad::GetButtonName(int32_t virtualSlot, int n64Button) return "Unknown"; } -const std::string WiiUGamepad::GetControllerName() { - return Connected() ? "Wii U GamePad" : "Wii U GamePad (Disconnected)"; -} - -void WiiUGamepad::CreateDefaultBinding(int32_t virtualSlot) { - auto profile = getProfile(virtualSlot); +void WiiUGamepad::CreateDefaultBinding(int32_t portIndex) { + auto profile = GetProfile(portIndex); profile->Mappings.clear(); profile->Version = DEVICE_PROFILE_CURRENT_VERSION; @@ -314,5 +324,21 @@ void WiiUGamepad::CreateDefaultBinding(int32_t virtualSlot) { profile->GyroData[DRIFT_X] = 0.0f; profile->GyroData[DRIFT_Y] = 0.0f; } + +bool WiiUGamePad::Connected() const override { + return mConnected; +}; + +bool WiiUGamePad::CanGyro() const override { + return true; +} + +bool WiiUGamePad::CanRumble() const override { + return true; +}; + +bool DummyController::CanSetLed() const { + return false; +} } // namespace Ship #endif diff --git a/src/port/wiiu/WiiUGamepad.h b/src/port/wiiu/WiiUGamepad.h index fff2205..61ada2f 100644 --- a/src/port/wiiu/WiiUGamepad.h +++ b/src/port/wiiu/WiiUGamepad.h @@ -5,35 +5,28 @@ namespace Ship { class WiiUGamepad : public Controller { public: - WiiUGamepad(); + WiiUGamepad(std::shared_ptr controlDeck, int32_t deviceIndex); bool Open(); void Close(); - void ReadFromSource(int32_t virtualSlot) override; - void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override; - bool Connected() const override { - return connected; - }; - bool CanGyro() const override { - return true; - } - bool CanRumble() const override { - return true; - }; - + void ReadDevice(int32_t portIndex) override; + bool Connected() const; + bool CanGyro() const; + bool CanRumble() const; + bool CanSetLed() const override; void ClearRawPress() override; int32_t ReadRawPress() override; - - const std::string GetButtonName(int32_t virtualSlot, int n64Button) override; - const std::string GetControllerName() override; + int32_t SetRumble(int32_t portIndex, bool rumble) override; + int32_t SetLed(int32_t portIndex, int8_t r, int8_t g, int8_t b) override; + const std::string GetButtonName(int32_t portIndex, int n64Button) override; protected: - void CreateDefaultBinding(int32_t virtualSlot) override; + void CreateDefaultBinding(int32_t portIndex) override; private: - bool connected = true; - float rumblePatternStrength; - uint8_t rumblePattern[15]; + bool mConnected = true; + float mRumblePatternStrength; + uint8_t mRumblePattern[15]; }; } // namespace Ship