From 094388187f9471afb00a3ea9de9c5b46b7033c72 Mon Sep 17 00:00:00 2001 From: Kenix3 Date: Thu, 11 Aug 2022 00:06:58 -0400 Subject: [PATCH] Cleans up Controllers Renames VirtualController to DummyController. Makes controller axis treated the same as buttons. Made Controller class members private or protected Made Controller class treat deadzones, sensitivities, and press thresholds consistently. --- libultraship/libultraship/ControlDeck.cpp | 81 +++-- libultraship/libultraship/Controller.cpp | 95 ++++-- libultraship/libultraship/Controller.h | 102 +++--- ...{VirtualController.h => DummyController.h} | 8 +- libultraship/libultraship/InputEditor.cpp | 52 +-- .../libultraship/KeyboardController.cpp | 76 +++-- .../libultraship/KeyboardController.h | 10 +- libultraship/libultraship/SDLController.cpp | 295 ++++++++---------- libultraship/libultraship/SDLController.h | 28 +- libultraship/libultraship/UltraController.h | 4 +- libultraship/libultraship/Window.cpp | 4 +- soh/src/code/z_camera.c | 8 +- .../ovl_kaleido_scope/z_kaleido_equipment.c | 12 +- 13 files changed, 413 insertions(+), 362 deletions(-) rename libultraship/libultraship/{VirtualController.h => DummyController.h} (76%) diff --git a/libultraship/libultraship/ControlDeck.cpp b/libultraship/libultraship/ControlDeck.cpp index 59f25b44f..730713597 100644 --- a/libultraship/libultraship/ControlDeck.cpp +++ b/libultraship/libultraship/ControlDeck.cpp @@ -2,7 +2,7 @@ #include "Window.h" #include "Controller.h" -#include "VirtualController.h" +#include "DummyController.h" #include "KeyboardController.h" #include "SDLController.h" #include @@ -28,9 +28,9 @@ namespace Ship { } } - physicalDevices.push_back(std::make_shared("Auto", "Auto", true)); + physicalDevices.push_back(std::make_shared("Auto", "Auto", true)); physicalDevices.push_back(std::make_shared()); - physicalDevices.push_back(std::make_shared("Disconnected", "None", false)); + physicalDevices.push_back(std::make_shared("Disconnected", "None", false)); for (const auto& device : physicalDevices) { for (int i = 0; i < MAXCONTROLLERS; i++) { @@ -77,7 +77,7 @@ namespace Ship { } } -#define NESTED(key, ...) StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), slot, __VA_ARGS__) +#define NESTED(key, ...) StringHelper::Sprintf("Controllers.%s.Slot_%d." key, device->GetGuid().c_str(), virtualSlot, __VA_ARGS__) void ControlDeck::LoadControllerSettings() { std::shared_ptr Config = GlobalCtx2::GetInstance()->GetConfig(); @@ -102,25 +102,40 @@ namespace Ship { std::string guid = device->GetGuid(); - for (int slot = 0; slot < MAXCONTROLLERS; slot++) { + for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - if (!(Config->rjson["Controllers"].contains(guid) && Config->rjson["Controllers"][guid].contains(StringHelper::Sprintf("Slot_%d", slot)))) continue; + if (!(Config->rjson["Controllers"].contains(guid) && Config->rjson["Controllers"][guid].contains(StringHelper::Sprintf("Slot_%d", virtualSlot)))) continue; - auto& profile = device->profiles[slot]; - auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", slot)]; + auto profile = device->getProfile(virtualSlot); + auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", virtualSlot)]; - profile.Mappings.clear(); - profile.Thresholds.clear(); - profile.UseRumble = Config->getBool(NESTED("Rumble.Enabled", "")); - profile.RumbleStrength = Config->getFloat(NESTED("Rumble.Strength", "")); - profile.UseGyro = Config->getBool(NESTED("Gyro.Enabled", "")); + profile->Mappings.clear(); + profile->AxisDeadzones.clear(); + profile->AxisSensitivities.clear(); + profile->GyroData.clear(); + profile->Version = Config->getInt(NESTED("Version", "")); + profile->UseRumble = Config->getBool(NESTED("Rumble.Enabled", "")); + profile->RumbleStrength = Config->getFloat(NESTED("Rumble.Strength", "")); + profile->UseGyro = Config->getBool(NESTED("Gyro.Enabled", "")); - for (auto const& val : rawProfile["Thresholds"].items()) { - profile.Thresholds[static_cast(std::stoi(val.key()))] = val.value(); + for (auto const& val : rawProfile["AxisDeadzones"].items()) { + profile->AxisDeadzones[std::stoi(val.key())] = val.value(); + } + + for (auto const& val : rawProfile["AxisSensitivities"].items()) { + profile->AxisSensitivities[std::stoi(val.key())] = val.value(); + } + + for (auto const& val : rawProfile["AxisMinimumPress"].items()) { + profile->AxisMinimumPress[std::stoi(val.key())] = val.value(); + } + + for (auto const& val : rawProfile["GyroData"].items()) { + profile->GyroData[std::stoi(val.key())] = val.value(); } for (auto const& val : rawProfile["Mappings"].items()) { - device->SetButtonMapping(slot, std::stoi(val.key().substr(4)), val.value()); + device->SetButtonMapping(virtualSlot, std::stoi(val.key().substr(4)), val.value()); } } } @@ -136,31 +151,45 @@ namespace Ship { for (const auto& device : physicalDevices) { - int slot = 0; + int32_t virtualSlot = 0; std::string guid = device->GetGuid(); - for (const auto& profile : device->profiles) { + for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { + auto profile = device->getProfile(virtualSlot); if (!device->Connected()) continue; - auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", slot)]; - Config->setBool(NESTED("Rumble.Enabled", ""), profile.UseRumble); - Config->setFloat(NESTED("Rumble.Strength", ""), profile.RumbleStrength); - Config->setBool(NESTED("Gyro.Enabled", ""), profile.UseGyro); + auto rawProfile = Config->rjson["Controllers"][guid][StringHelper::Sprintf("Slot_%d", virtualSlot)]; + Config->setInt(NESTED("Version", ""), profile->Version); + Config->setBool(NESTED("Rumble.Enabled", ""), profile->UseRumble); + Config->setFloat(NESTED("Rumble.Strength", ""), profile->RumbleStrength); + Config->setBool(NESTED("Gyro.Enabled", ""), profile->UseGyro); for (auto const& val : rawProfile["Mappings"].items()) { Config->setInt(NESTED("Mappings.%s", val.key().c_str()), -1); } - for (auto const& [key, val] : profile.Thresholds) { - Config->setFloat(NESTED("Thresholds.%d", key), val); + for (auto const& [key, val] : profile->AxisDeadzones) { + Config->setFloat(NESTED("AxisDeadzones.%d", key), val); } - for (auto const& [key, val] : profile.Mappings) { + for (auto const& [key, val] : profile->AxisSensitivities) { + Config->setFloat(NESTED("AxisSensitivities.%d", key), val); + } + + for (auto const& [key, val] : profile->AxisMinimumPress) { + Config->setFloat(NESTED("AxisMinimumPress.%d", key), val); + } + + for (auto const& [key, val] : profile->GyroData) { + Config->setFloat(NESTED("GyroData.%d", key), val); + } + + for (auto const& [key, val] : profile->Mappings) { Config->setInt(NESTED("Mappings.BTN_%d", val), key); } - slot++; + virtualSlot++; } } diff --git a/libultraship/libultraship/Controller.cpp b/libultraship/libultraship/Controller.cpp index 1e59e55c3..5ecb84216 100644 --- a/libultraship/libultraship/Controller.cpp +++ b/libultraship/libultraship/Controller.cpp @@ -9,72 +9,105 @@ namespace Ship { - Controller::Controller() : isRumbling(false), wStickX(0), wStickY(0), wGyroX(0), wGyroY(0), wCamX(0), wCamY(0), dwPressedButtons(0){ + Controller::Controller() : isRumbling(false) { Attachment = nullptr; - profiles.resize(MAXCONTROLLERS); - for(int slot = 0; slot < MAXCONTROLLERS; slot++) { - dwPressedButtons.push_back(0); + + for(int virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { + profiles[virtualSlot] = std::make_shared(); + ButtonData[virtualSlot] = std::make_shared(); } } - void Controller::Read(OSContPad* pad, int32_t slot) { - ReadFromSource(slot); + void Controller::Read(OSContPad* pad, int32_t virtualSlot) { + ReadFromSource(virtualSlot); SDL_PumpEvents(); // Button Inputs - pad->button |= dwPressedButtons[slot] & 0xFFFF; + pad->button |= getPressedButtons(virtualSlot) & 0xFFFF; // Stick Inputs - if (wStickX == 0) { - if (dwPressedButtons[slot] & BTN_STICKLEFT) { + if (getLeftStickX(virtualSlot) == 0) { + if (getPressedButtons(virtualSlot) & BTN_STICKLEFT) { pad->stick_x = -128; - } else if (dwPressedButtons[slot] & BTN_STICKRIGHT) { + } else if (getPressedButtons(virtualSlot) & BTN_STICKRIGHT) { pad->stick_x = 127; } } else { - pad->stick_x = wStickX; + pad->stick_x = getLeftStickX(virtualSlot); } - if (wStickY == 0) { - if (dwPressedButtons[slot] & BTN_STICKDOWN) { + if (getLeftStickY(virtualSlot) == 0) { + if (getPressedButtons(virtualSlot) & BTN_STICKDOWN) { pad->stick_y = -128; - } else if (dwPressedButtons[slot] & BTN_STICKUP) { + } else if (getPressedButtons(virtualSlot) & BTN_STICKUP) { pad->stick_y = 127; } } else { - pad->stick_y = wStickY; + pad->stick_y = getLeftStickY(virtualSlot); } // Stick Inputs - if (wCamX == 0) { - if (dwPressedButtons[slot] & BTN_VSTICKLEFT) { - pad->cam_x = -128 * 10.0f; - } else if (dwPressedButtons[slot] & BTN_VSTICKRIGHT) { - pad->cam_x = 127 * 10.0f; + if (getRightStickX(virtualSlot) == 0) { + if (getPressedButtons(virtualSlot) & BTN_VSTICKLEFT) { + pad->right_stick_x = -128; + } else if (getPressedButtons(virtualSlot) & BTN_VSTICKRIGHT) { + pad->right_stick_x = 127; } } else { - pad->cam_x = wCamX; + pad->right_stick_x = getRightStickX(virtualSlot); } - if (wCamY == 0) { - if (dwPressedButtons[slot] & BTN_VSTICKDOWN) { - pad->cam_y = -128 * 10.0f; - } else if (dwPressedButtons[slot] & BTN_VSTICKUP) { - pad->cam_y = 127 * 10.0f; + if (getRightStickY(virtualSlot) == 0) { + if (getPressedButtons(virtualSlot) & BTN_VSTICKDOWN) { + pad->right_stick_y = -128; + } else if (getPressedButtons(virtualSlot) & BTN_VSTICKUP) { + pad->right_stick_y = 127; } } else { - pad->cam_y = wCamY; + pad->right_stick_y = getRightStickY(virtualSlot); } // Gyro - pad->gyro_x = wGyroX; - pad->gyro_y = wGyroY; + pad->gyro_x = getGyroX(virtualSlot); + pad->gyro_y = getGyroY(virtualSlot); } - void Controller::SetButtonMapping(int slot, int32_t n64Button, int32_t dwScancode) { - std::map& Mappings = profiles[slot].Mappings; + void Controller::SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t dwScancode) { + std::map& Mappings = getProfile(virtualSlot)->Mappings; std::erase_if(Mappings, [n64Button](const std::pair& bin) { return bin.second == n64Button; }); Mappings[dwScancode] = n64Button; } + + int8_t& Controller::getLeftStickX(int32_t virtualSlot) { + return ButtonData[virtualSlot]->leftStickX; + } + + int8_t& Controller::getLeftStickY(int32_t virtualSlot) { + return ButtonData[virtualSlot]->leftStickY; + } + + int8_t& Controller::getRightStickX(int32_t virtualSlot) { + return ButtonData[virtualSlot]->rightStickX; + } + + int8_t& Controller::getRightStickY(int32_t virtualSlot) { + return ButtonData[virtualSlot]->rightStickY; + } + + int32_t& Controller::getPressedButtons(int32_t virtualSlot) { + return ButtonData[virtualSlot]->pressedButtons; + } + + float& Controller::getGyroX(int32_t virtualSlot) { + return ButtonData[virtualSlot]->gyroX; + } + + float& Controller::getGyroY(int32_t virtualSlot) { + return ButtonData[virtualSlot]->gyroY; + } + + std::shared_ptr Controller::getProfile(int32_t virtualSlot) { + return profiles[virtualSlot]; + } } diff --git a/libultraship/libultraship/Controller.h b/libultraship/libultraship/Controller.h index 70c339d25..0282b6626 100644 --- a/libultraship/libultraship/Controller.h +++ b/libultraship/libultraship/Controller.h @@ -3,10 +3,9 @@ #include #include #include -#include "stdint.h" +#include #include "UltraController.h" #include "ControllerAttachment.h" -#include #include #define EXTENDED_SCANCODE_BIT (1 << 8) @@ -14,68 +13,73 @@ namespace Ship { - enum ControllerThresholds { - LEFT_STICK = 1, - RIGHT_STICK = 2, - LEFT_TRIGGER = 3, - RIGHT_TRIGGER = 4, - DRIFT_X = 5, - DRIFT_Y = 6, - SENSITIVITY = 7, - GYRO_SENSITIVITY = 8 + + + enum GyroDataV0 { + DRIFT_X, + DRIFT_Y, + GYRO_SENSITIVITY }; - struct DeviceProfile { + struct DeviceProfileV0 { + int32_t Version = 0; bool UseRumble = false; bool UseGyro = false; float RumbleStrength = 1.0f; - std::unordered_map Thresholds; + std::unordered_map AxisDeadzones; + std::unordered_map AxisMinimumPress; + std::unordered_map AxisSensitivities; + std::unordered_map GyroData; std::map Mappings; }; class Controller { - public: - virtual ~Controller() = default; - Controller(); - void Read(OSContPad* pad, int32_t slot); - virtual void ReadFromSource(int32_t slot) = 0; - virtual void WriteToSource(int32_t slot, ControllerCallback* controller) = 0; - virtual bool Connected() const = 0; - virtual bool CanRumble() const = 0; - virtual bool CanGyro() const = 0; - virtual void CreateDefaultBinding(int32_t slot) = 0; - bool isRumbling; - std::vector profiles; - - virtual void ClearRawPress() = 0; - virtual int32_t ReadRawPress() = 0; - void SetButtonMapping(int slot, int32_t n64Button, int32_t dwScancode); - std::shared_ptr GetAttachment() { return Attachment; } - - std::string GetGuid() { return GUID; } - virtual const char* GetButtonName(int slot, int n64Button) = 0; - virtual const char* GetControllerName() = 0; - - int8_t wStickX; - int8_t wStickY; - float wGyroX; - float wGyroY; - float wCamX; - float wCamY; + public: + virtual ~Controller() = default; + Controller(); + void Read(OSContPad* pad, int32_t virtualSlot); + virtual void ReadFromSource(int32_t virtualSlot) = 0; + virtual void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) = 0; + virtual bool Connected() const = 0; + virtual bool CanRumble() const = 0; + virtual bool CanGyro() const = 0; + virtual void CreateDefaultBinding(int32_t virtualSlot) = 0; + virtual void ClearRawPress() = 0; + virtual int32_t ReadRawPress() = 0; + void SetButtonMapping(int32_t virtualSlot, int32_t n64Button, int32_t dwScancode); + std::shared_ptr GetAttachment() { return Attachment; } + 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 virtualSlot); + bool IsRumbling() { return isRumbling; } + std::string GetGuid() { return GUID; } + virtual const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) = 0; + virtual const std::string GetControllerName() = 0; protected: - std::vector dwPressedButtons; + std::shared_ptr Attachment; std::string GUID; - + bool isRumbling; + void LoadBinding(); private: - std::shared_ptr Attachment; - }; + struct Buttons { + int32_t pressedButtons = 0; + int8_t leftStickX = 0; + int8_t leftStickY = 0; + int8_t rightStickX = 0; + int8_t rightStickY = 0; + float gyroX = 0.0f; + float gyroY = 0.0f; + }; - struct ControllerEntry { - uint8_t* controllerBits; - Controller* entryIO; + std::unordered_map> profiles; + std::unordered_map> ButtonData = {}; }; - } diff --git a/libultraship/libultraship/VirtualController.h b/libultraship/libultraship/DummyController.h similarity index 76% rename from libultraship/libultraship/VirtualController.h rename to libultraship/libultraship/DummyController.h index 825d7df59..7e71b7033 100644 --- a/libultraship/libultraship/VirtualController.h +++ b/libultraship/libultraship/DummyController.h @@ -5,9 +5,9 @@ #include "Controller.h" namespace Ship { - class VirtualController final : public Controller { + class DummyController final : public Controller { public: - VirtualController(const std::string& CUID, const std::string& KeyName, bool Connected) { + DummyController(const std::string& CUID, const std::string& KeyName, bool Connected) { GUID = CUID; isConnected = Connected; ButtonName = KeyName; @@ -15,8 +15,8 @@ namespace Ship { std::map, int32_t> ReadButtonPress(); void ReadFromSource(int32_t slot) override {} - const char* GetControllerName() override { return GUID.c_str(); } - const char* GetButtonName(int slot, int n64Button) override { return ButtonName.c_str(); } + const std::string GetControllerName() override { return GUID; } + const std::string GetButtonName(int slot, int n64Button) override { return ButtonName; } void WriteToSource(int32_t slot, ControllerCallback* controller) override { } bool Connected() const override { return isConnected; } bool CanRumble() const override { return false; } diff --git a/libultraship/libultraship/InputEditor.cpp b/libultraship/libultraship/InputEditor.cpp index 9186e2b22..79916bf92 100644 --- a/libultraship/libultraship/InputEditor.cpp +++ b/libultraship/libultraship/InputEditor.cpp @@ -48,9 +48,9 @@ namespace Ship { } } - const char* BtnName = backend->GetButtonName(CurrentPort, n64Btn); + const std::string BtnName = backend->GetButtonName(CurrentPort, n64Btn); - if (ImGui::Button(StringHelper::Sprintf("%s##HBTNID_%d", readingMode ? "Press a Key..." : BtnName, n64Btn).c_str())) { + if (ImGui::Button(StringHelper::Sprintf("%s##HBTNID_%d", readingMode ? "Press a Key..." : BtnName.c_str(), n64Btn).c_str())) { BtnReading = n64Btn; backend->ClearRawPress(); } @@ -84,18 +84,16 @@ namespace Ship { void InputEditor::DrawControllerSchema() { auto controlDeck = Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck(); auto Backend = controlDeck->GetPhysicalDeviceFromVirtualSlot(CurrentPort); - DeviceProfile& profile = Backend->profiles[CurrentPort]; - float sensitivity = profile.Thresholds[SENSITIVITY]; + auto profile = Backend->getProfile(CurrentPort); bool IsKeyboard = Backend->GetGuid() == "Keyboard" || Backend->GetGuid() == "Auto" || !Backend->Connected(); - const char* ControllerName = Backend->GetControllerName(); + std::string ControllerName = Backend->GetControllerName(); - if (ControllerName != nullptr && ImGui::BeginCombo("##ControllerEntries", ControllerName)) { + if (ImGui::BeginCombo("##ControllerEntries", ControllerName.c_str())) { for (uint8_t i = 0; i < controlDeck->GetNumPhysicalDevices(); i++) { - std::string DeviceName = controlDeck->GetPhysicalDevice(i)->GetControllerName(); - if (DeviceName != "Keyboard" && DeviceName != "Auto") { - DeviceName+="##"+std::to_string(i); + if (ControllerName != "Keyboard" && ControllerName != "Auto") { + ControllerName += "##"+std::to_string(i); } - if (ImGui::Selectable(DeviceName.c_str(), i == controlDeck->GetVirtualDevice(CurrentPort))) { + if (ImGui::Selectable(ControllerName.c_str(), i == controlDeck->GetVirtualDevice(CurrentPort))) { controlDeck->SetPhysicalDevice(CurrentPort, i); } } @@ -142,7 +140,7 @@ namespace Ship { if (!IsKeyboard) { ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8); - DrawVirtualStick("##MainVirtualStick", ImVec2(Backend->wStickX, Backend->wStickY)); + DrawVirtualStick("##MainVirtualStick", ImVec2(Backend->getLeftStickX(CurrentPort), Backend->getLeftStickY(CurrentPort))); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); @@ -150,7 +148,7 @@ namespace Ship { ImGui::BeginChild("##MSInput", ImVec2(90, 50), false); ImGui::Text("Deadzone"); ImGui::PushItemWidth(80); - ImGui::InputFloat("##MDZone", &profile.Thresholds[LEFT_STICK], 1.0f, 0.0f, "%.0f"); + ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[0] /* This is the SDL value for left stick X axis */, 1.0f, 0.0f, "%.0f"); ImGui::PopItemWidth(); ImGui::EndChild(); } else { @@ -172,18 +170,20 @@ namespace Ship { DrawButton("Right", BTN_VSTICKRIGHT); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 8); - DrawVirtualStick("##CameraVirtualStick", ImVec2(Backend->wCamX / sensitivity, Backend->wCamY / sensitivity)); + // 2 is the SDL value for right stick X axis + // 3 is the SDL value for right stick Y axis. + DrawVirtualStick("##CameraVirtualStick", ImVec2(Backend->getRightStickX(CurrentPort) / profile->AxisSensitivities[2], Backend->getRightStickY(CurrentPort) / profile->AxisSensitivities[3])); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::BeginChild("##CSInput", ImVec2(90, 85), false); ImGui::Text("Deadzone"); ImGui::PushItemWidth(80); - ImGui::InputFloat("##MDZone", &profile.Thresholds[RIGHT_STICK], 1.0f, 0.0f, "%.0f"); + ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[2] /* This is the SDL value for left stick X axis */, 1.0f, 0.0f, "%.0f"); ImGui::PopItemWidth(); ImGui::Text("Sensitivity"); ImGui::PushItemWidth(80); - ImGui::InputFloat("##MSensitivity", &profile.Thresholds[SENSITIVITY], 1.0f, 0.0f, "%.0f"); + ImGui::InputFloat("##MSensitivity", &profile->AxisSensitivities[2] /* This is the SDL value for right stick X axis */, 1.0f, 0.0f, "%.0f"); ImGui::PopItemWidth(); ImGui::EndChild(); #ifdef __SWITCH__ @@ -199,32 +199,32 @@ namespace Ship { SohImGui::BeginGroupPanel("Gyro Options", ImVec2(175, 20)); float cursorX = ImGui::GetCursorPosX() + 5; ImGui::SetCursorPosX(cursorX); - ImGui::Checkbox("Enable Gyro", &profile.UseGyro); + ImGui::Checkbox("Enable Gyro", &profile->UseGyro); ImGui::SetCursorPosX(cursorX); - ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile.Thresholds[GYRO_SENSITIVITY])); + ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile->GyroData[GYRO_SENSITIVITY])); ImGui::PushItemWidth(135.0f); ImGui::SetCursorPosX(cursorX); - ImGui::SliderFloat("##GSensitivity", &profile.Thresholds[GYRO_SENSITIVITY], 0.0f, 1.0f, ""); + ImGui::SliderFloat("##GSensitivity", &profile->GyroData[GYRO_SENSITIVITY], 0.0f, 1.0f, ""); ImGui::PopItemWidth(); ImGui::Dummy(ImVec2(0, 1)); ImGui::SetCursorPosX(cursorX); if (ImGui::Button("Recalibrate Gyro##RGyro")) { - profile.Thresholds[DRIFT_X] = 0.0f; - profile.Thresholds[DRIFT_Y] = 0.0f; + profile->GyroData[DRIFT_X] = 0.0f; + profile->GyroData[DRIFT_Y] = 0.0f; } ImGui::SetCursorPosX(cursorX); - DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->wGyroY, 10.0f * Backend->wGyroX)); + DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->getGyroY(CurrentPort), 10.0f * Backend->getGyroX(CurrentPort))); ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5); ImGui::BeginChild("##GyInput", ImVec2(90, 85), false); ImGui::Text("Drift X"); ImGui::PushItemWidth(80); - ImGui::InputFloat("##GDriftX", &profile.Thresholds[DRIFT_X], 1.0f, 0.0f, "%.1f"); + ImGui::InputFloat("##GDriftX", &profile->GyroData[DRIFT_X], 1.0f, 0.0f, "%.1f"); ImGui::PopItemWidth(); ImGui::Text("Drift Y"); ImGui::PushItemWidth(80); - ImGui::InputFloat("##GDriftY", &profile.Thresholds[DRIFT_Y], 1.0f, 0.0f, "%.1f"); + ImGui::InputFloat("##GDriftY", &profile->GyroData[DRIFT_Y], 1.0f, 0.0f, "%.1f"); ImGui::PopItemWidth(); ImGui::EndChild(); #ifdef __SWITCH__ @@ -255,13 +255,13 @@ namespace Ship { SohImGui::BeginGroupPanel("Options", ImVec2(158, 20)); float cursorX = ImGui::GetCursorPosX() + 5; ImGui::SetCursorPosX(cursorX); - ImGui::Checkbox("Rumble Enabled", &profile.UseRumble); + ImGui::Checkbox("Rumble Enabled", &profile->UseRumble); if (Backend->CanRumble()) { ImGui::SetCursorPosX(cursorX); - ImGui::Text("Rumble Force: %d%%", static_cast(100.0f * profile.RumbleStrength)); + ImGui::Text("Rumble Force: %d%%", static_cast(100.0f * profile->RumbleStrength)); ImGui::SetCursorPosX(cursorX); ImGui::PushItemWidth(135.0f); - ImGui::SliderFloat("##RStrength", &profile.RumbleStrength, 0.0f, 1.0f, ""); + ImGui::SliderFloat("##RStrength", &profile->RumbleStrength, 0.0f, 1.0f, ""); ImGui::PopItemWidth(); } ImGui::Dummy(ImVec2(0, 5)); diff --git a/libultraship/libultraship/KeyboardController.cpp b/libultraship/libultraship/KeyboardController.cpp index 0ba08f415..7df244d9c 100644 --- a/libultraship/libultraship/KeyboardController.cpp +++ b/libultraship/libultraship/KeyboardController.cpp @@ -17,13 +17,12 @@ namespace Ship { } bool KeyboardController::PressButton(int32_t dwScancode) { - lastKey = dwScancode; - for (int slot = 0; slot < MAXCONTROLLERS; slot++) { + for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { - if (profiles[slot].Mappings.contains(dwScancode)) { - dwPressedButtons[slot] |= profiles[slot].Mappings[dwScancode]; + if (getProfile(virtualSlot)->Mappings.contains(dwScancode)) { + getPressedButtons(virtualSlot) |= getProfile(virtualSlot)->Mappings[dwScancode]; return true; } } @@ -32,9 +31,9 @@ namespace Ship { } bool KeyboardController::ReleaseButton(int32_t dwScancode) { - for (int slot = 0; slot < MAXCONTROLLERS; slot++) { - if (profiles[slot].Mappings.contains(dwScancode)) { - dwPressedButtons[slot] &= ~profiles[slot].Mappings[dwScancode]; + for (int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { + if (getProfile(virtualSlot)->Mappings.contains(dwScancode)) { + getPressedButtons(virtualSlot) &= ~getProfile(virtualSlot)->Mappings[dwScancode]; return true; } } @@ -43,16 +42,16 @@ namespace Ship { } void KeyboardController::ReleaseAllButtons() { - for(int slot = 0; slot < MAXCONTROLLERS; slot++) { - dwPressedButtons[slot] = 0; + for(int32_t virtualSlot = 0; virtualSlot < MAXCONTROLLERS; virtualSlot++) { + getPressedButtons(virtualSlot) = 0; } } - void KeyboardController::ReadFromSource(int32_t slot) { - wStickX = 0; - wStickY = 0; - wCamX = 0; - wCamY = 0; + void KeyboardController::ReadFromSource(int32_t virtualSlot) { + getLeftStickX(virtualSlot) = 0; + getLeftStickY(virtualSlot) = 0; + getRightStickX(virtualSlot) = 0; + getRightStickY(virtualSlot) = 0; } int32_t KeyboardController::ReadRawPress() { @@ -60,13 +59,12 @@ namespace Ship { } - void KeyboardController::WriteToSource(int32_t slot, ControllerCallback* controller) - { + void KeyboardController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { } - const char* KeyboardController::GetButtonName(int slot, int n64Button) { - std::map& Mappings = profiles[slot].Mappings; + const std::string KeyboardController::GetButtonName(int32_t virtualSlot, int32_t n64Button) { + std::map& Mappings = getProfile(virtualSlot)->Mappings; const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair& pair) { return pair.second == n64Button; }); @@ -77,29 +75,29 @@ namespace Ship { } - void KeyboardController::CreateDefaultBinding(int32_t slot) { - DeviceProfile& profile = profiles[slot]; - profile.Mappings[0x14D] = BTN_CRIGHT; - profile.Mappings[0x14B] = BTN_CLEFT; - profile.Mappings[0x150] = BTN_CDOWN; - profile.Mappings[0x148] = BTN_CUP; - profile.Mappings[0x13] = BTN_R; - profile.Mappings[0x12] = BTN_L; - profile.Mappings[0x023] = BTN_DRIGHT; - profile.Mappings[0x021] = BTN_DLEFT; - profile.Mappings[0x022] = BTN_DDOWN; - profile.Mappings[0x014] = BTN_DUP; - profile.Mappings[0x039] = BTN_START; - profile.Mappings[0x02C] = BTN_Z; - profile.Mappings[0x02E] = BTN_B; - profile.Mappings[0x02D] = BTN_A; - profile.Mappings[0x020] = BTN_STICKRIGHT; - profile.Mappings[0x01E] = BTN_STICKLEFT; - profile.Mappings[0x01F] = BTN_STICKDOWN; - profile.Mappings[0x011] = BTN_STICKUP; + void KeyboardController::CreateDefaultBinding(int32_t virtualSlot) { + auto profile = getProfile(virtualSlot); + profile->Mappings[0x14D] = BTN_CRIGHT; + profile->Mappings[0x14B] = BTN_CLEFT; + profile->Mappings[0x150] = BTN_CDOWN; + profile->Mappings[0x148] = BTN_CUP; + profile->Mappings[0x13] = BTN_R; + profile->Mappings[0x12] = BTN_L; + profile->Mappings[0x023] = BTN_DRIGHT; + profile->Mappings[0x021] = BTN_DLEFT; + profile->Mappings[0x022] = BTN_DDOWN; + profile->Mappings[0x014] = BTN_DUP; + profile->Mappings[0x039] = BTN_START; + profile->Mappings[0x02C] = BTN_Z; + profile->Mappings[0x02E] = BTN_B; + profile->Mappings[0x02D] = BTN_A; + profile->Mappings[0x020] = BTN_STICKRIGHT; + profile->Mappings[0x01E] = BTN_STICKLEFT; + profile->Mappings[0x01F] = BTN_STICKDOWN; + profile->Mappings[0x011] = BTN_STICKUP; } - const char* KeyboardController::GetControllerName() { + const std::string KeyboardController::GetControllerName() { return "Keyboard"; } } diff --git a/libultraship/libultraship/KeyboardController.h b/libultraship/libultraship/KeyboardController.h index cc0aca04e..345e34718 100644 --- a/libultraship/libultraship/KeyboardController.h +++ b/libultraship/libultraship/KeyboardController.h @@ -7,13 +7,13 @@ namespace Ship { public: KeyboardController(); - void ReadFromSource(int32_t slot) override; - void WriteToSource(int32_t slot, ControllerCallback* controller) override; + void ReadFromSource(int32_t virtualSlot) override; + void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override; bool Connected() const override { return true; } bool CanRumble() const override { return false; } bool CanGyro() const override { return false; } - const char* GetControllerName() override; - const char* GetButtonName(int slot, int n64Button) override; + const std::string GetControllerName() override; + const std::string GetButtonName(int32_t virtualSlot, int32_t n64Button) override; bool PressButton(int32_t dwScancode); bool ReleaseButton(int32_t dwScancode); @@ -29,7 +29,7 @@ namespace Ship { } int32_t GetLastScancode() { return lastScancode; } - void CreateDefaultBinding(int32_t slot) override; + void CreateDefaultBinding(int32_t virtualSlot) override; protected: int32_t lastScancode; diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp index 398ce1944..85a9b6fb4 100644 --- a/libultraship/libultraship/SDLController.cpp +++ b/libultraship/libultraship/SDLController.cpp @@ -13,7 +13,6 @@ extern "C" uint8_t __osMaxControllers; namespace Ship { bool SDLController::Open() { - const auto NewCont = SDL_GameControllerOpen(physicalSlot); // We failed to load the controller. Go to next. @@ -30,8 +29,7 @@ namespace Ship { char GuidBuf[33]; SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(physicalSlot), GuidBuf, sizeof(GuidBuf)); Cont = NewCont; - wCamX = 0; - wCamY = 0; + #ifdef __SWITCH__ GUID = StringHelper::Sprintf("%s:%d", GuidBuf, physicalSlot); ControllerName = StringHelper::Sprintf("%s #%d", SDL_GameControllerNameForIndex(physicalSlot), physicalSlot + 1); @@ -50,54 +48,58 @@ namespace Ship { SDL_GameControllerClose(Cont); } Cont = nullptr; - wStickX = 0; - wStickY = 0; return true; } + void SDLController::NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int16_t axisThreshold, int32_t virtualSlot) { + auto profile = getProfile(virtualSlot); + + const auto axisValueX = SDL_GameControllerGetAxis(Cont, axisX); + const auto axisValueY = SDL_GameControllerGetAxis(Cont, axisY); - void SDLController::NormalizeStickAxis(int16_t wAxisValueX, int16_t wAxisValueY, int16_t wAxisThreshold, bool isRightStick, float sensitivity) { //scale {-32768 ... +32767} to {-84 ... +84} - auto ax = wAxisValueX * 85.0 / 32767.0; - auto ay = wAxisValueY * 85.0 / 32767.0; + auto ax = axisValueX * 85.0f / 32767.0f; + auto ay = axisValueY * 85.0f / 32767.0f; //create scaled circular dead-zone in range {-15 ... +15} auto len = sqrt(ax * ax + ay * ay); - if (len < wAxisThreshold) { - len = 0; + if (len < axisThreshold) { + len = 0.0f; } else if (len > 85.0) { - len = 85.0 / len; + len = 85.0f / len; } else { - len = (len - wAxisThreshold) * 85.0 / (85.0 - wAxisThreshold) / len; + len = (len - axisThreshold) * 85.0f / (85.0f - axisThreshold) / len; } ax *= len; ay *= len; //bound diagonals to an octagonal range {-68 ... +68} - if (ax != 0.0 && ay != 0.0) { + if (ax != 0.0f && ay != 0.0f) { auto slope = ay / ax; - auto edgex = copysign(85.0 / (abs(slope) + 16.0 / 69.0), ax); - auto edgey = copysign(std::min(abs(edgex * slope), 85.0 / (1.0 / abs(slope) + 16.0 / 69.0)), ay); + auto edgex = copysign(85.0f / (abs(slope) + 16.0f / 69.0f), ax); + auto edgey = copysign(std::min(abs(edgex * slope), 85.0f / (1.0f / abs(slope) + 16.0f / 69.0f)), ay); edgex = edgey / slope; - auto scale = sqrt(edgex * edgex + edgey * edgey) / 85.0; + auto scale = sqrt(edgex * edgex + edgey * edgey) / 85.0f; ax *= scale; ay *= scale; } - if (!isRightStick) { - wStickX = +ax; - wStickY = -ay; - } else { - wCamX = +ax * sensitivity; - wCamY = -ay * sensitivity; + ax *= profile->AxisSensitivities[axisX]; + ay *= profile->AxisSensitivities[axisY]; + + if (axisX == SDL_CONTROLLER_AXIS_LEFTX) { + getLeftStickX(virtualSlot) = +ax; + getLeftStickY(virtualSlot) = -ay; + } else if (axisX == SDL_CONTROLLER_AXIS_RIGHTX) { + getRightStickX(virtualSlot) = +ax; + getRightStickY(virtualSlot) = -ay; } } - int32_t SDLController::ReadRawPress() { SDL_GameControllerUpdate(); @@ -123,24 +125,8 @@ namespace Ship { return -1; } - ControllerThresholds SDLAxisToThreshold( uint32_t axis ){ - switch(axis){ - case SDL_CONTROLLER_AXIS_LEFTX: - case SDL_CONTROLLER_AXIS_LEFTY: - return LEFT_STICK; - case SDL_CONTROLLER_AXIS_RIGHTX: - case SDL_CONTROLLER_AXIS_RIGHTY: - return RIGHT_STICK; - case SDL_CONTROLLER_AXIS_TRIGGERLEFT: - return LEFT_TRIGGER; - case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: - return RIGHT_TRIGGER; - default: return DRIFT_X; - } - } - - void SDLController::ReadFromSource(int32_t slot) { - DeviceProfile& profile = profiles[slot]; + void SDLController::ReadFromSource(int32_t virtualSlot) { + auto profile = getProfile(virtualSlot); SDL_GameControllerUpdate(); @@ -157,14 +143,14 @@ namespace Ship { } } - if (supportsGyro && profile.UseGyro) { + if (supportsGyro && profile->UseGyro) { float gyroData[3]; SDL_GameControllerGetSensorData(Cont, SDL_SENSOR_GYRO, gyroData, 3); - float gyro_drift_x = profile.Thresholds[DRIFT_X] / 100.0f; - float gyro_drift_y = profile.Thresholds[DRIFT_Y] / 100.0f; - const float gyro_sensitivity = profile.Thresholds[GYRO_SENSITIVITY]; + float gyro_drift_x = profile->GyroData[DRIFT_X] / 100.0f; + float gyro_drift_y = profile->GyroData[DRIFT_Y] / 100.0f; + const float gyro_sensitivity = profile->GyroData[GYRO_SENSITIVITY]; if (gyro_drift_x == 0) { gyro_drift_x = gyroData[0]; @@ -174,25 +160,25 @@ namespace Ship { gyro_drift_y = gyroData[1]; } - profile.Thresholds[DRIFT_X] = gyro_drift_x * 100.0f; - profile.Thresholds[DRIFT_Y] = gyro_drift_y * 100.0f; + profile->GyroData[DRIFT_X] = gyro_drift_x * 100.0f; + profile->GyroData[DRIFT_Y] = gyro_drift_y * 100.0f; - wGyroX = gyroData[0] - gyro_drift_x; - wGyroY = gyroData[1] - gyro_drift_y; + getGyroX(virtualSlot) = gyroData[0] - gyro_drift_x; + getGyroY(virtualSlot) = gyroData[1] - gyro_drift_y; - wGyroX *= gyro_sensitivity; - wGyroY *= gyro_sensitivity; + getGyroX(virtualSlot) *= gyro_sensitivity; + getGyroY(virtualSlot) *= gyro_sensitivity; } - dwPressedButtons[slot] = 0; + getPressedButtons(virtualSlot) = 0; for (int32_t i = SDL_CONTROLLER_BUTTON_A; i < SDL_CONTROLLER_BUTTON_MAX; i++) { - if (profile.Mappings.contains(i)) { + if (profile->Mappings.contains(i)) { if (SDL_GameControllerGetButton(Cont, static_cast(i))) { - dwPressedButtons[slot] |= profile.Mappings[i]; + getPressedButtons(virtualSlot) |= profile->Mappings[i]; } else { - dwPressedButtons[slot] &= ~profile.Mappings[i]; + getPressedButtons(virtualSlot) &= ~profile->Mappings[i]; } } } @@ -209,9 +195,10 @@ namespace Ship { const auto Axis = static_cast(i); const auto PosScancode = i + AXIS_SCANCODE_BIT; const auto NegScancode = -PosScancode; - const auto AxisThreshold = static_cast(profile.Thresholds[SDLAxisToThreshold(i)]); - const auto PosButton = profile.Mappings[PosScancode]; - const auto NegButton = profile.Mappings[NegScancode]; + const auto AxisDeadzone = profile->AxisDeadzones[i]; + const auto AxisMinimumPress = profile->AxisMinimumPress[i]; + const auto PosButton = profile->Mappings[PosScancode]; + const auto NegButton = profile->Mappings[NegScancode]; const auto AxisValue = SDL_GameControllerGetAxis(Cont, Axis); #ifdef TARGET_WEB @@ -231,17 +218,17 @@ namespace Ship { NegButton == BTN_STICKLEFT || NegButton == BTN_STICKRIGHT || NegButton == BTN_STICKUP || NegButton == BTN_STICKDOWN)) { - if (AxisValue > 0x1E00) { - dwPressedButtons[slot] |= PosButton; - dwPressedButtons[slot] &= ~NegButton; + if (AxisValue > AxisMinimumPress) { + getPressedButtons(virtualSlot) |= PosButton; + getPressedButtons(virtualSlot) &= ~NegButton; } - else if (AxisValue < -0x1E00) { - dwPressedButtons[slot] &= ~PosButton; - dwPressedButtons[slot] |= NegButton; + else if (AxisValue < -AxisMinimumPress) { + getPressedButtons(virtualSlot) &= ~PosButton; + getPressedButtons(virtualSlot) |= NegButton; } else { - dwPressedButtons[slot] &= ~PosButton; - dwPressedButtons[slot] &= ~NegButton; + getPressedButtons(virtualSlot) &= ~PosButton; + getPressedButtons(virtualSlot) &= ~NegButton; } } else { @@ -250,11 +237,11 @@ namespace Ship { SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", LStickAxisX, Axis); } - if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", LStickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", LStickDeadzone, AxisDeadzone); } - LStickDeadzone = AxisThreshold; + LStickDeadzone = AxisDeadzone; LStickAxisX = Axis; } @@ -263,11 +250,11 @@ namespace Ship { SPDLOG_TRACE("Invalid PosStickY configured. Neg was {} and Pos is {}", LStickAxisY, Axis); } - if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisDeadzone); } - LStickDeadzone = AxisThreshold; + LStickDeadzone = AxisDeadzone; LStickAxisY = Axis; } @@ -276,11 +263,11 @@ namespace Ship { SPDLOG_TRACE("Invalid NegStickX configured. Pos was {} and Neg is {}", LStickAxisX, Axis); } - if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisDeadzone); } - LStickDeadzone = AxisThreshold; + LStickDeadzone = AxisDeadzone; LStickAxisX = Axis; } @@ -289,21 +276,15 @@ namespace Ship { SPDLOG_TRACE("Invalid NegStickY configured. Pos was {} and Neg is {}", LStickAxisY, Axis); } - if (LStickDeadzone != 0 && LStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisThreshold); + if (LStickDeadzone != 0 && LStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", LStickDeadzone, AxisDeadzone); } - LStickDeadzone = AxisThreshold; + LStickDeadzone = AxisDeadzone; LStickAxisY = Axis; } } - if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - const auto AxisValueX = SDL_GameControllerGetAxis(Cont, LStickAxisX); - const auto AxisValueY = SDL_GameControllerGetAxis(Cont, LStickAxisY); - NormalizeStickAxis(AxisValueX, AxisValueY, LStickDeadzone, false, profile.Thresholds[SENSITIVITY]); - } - // Right Stick // If the axis is NOT mapped to the control stick. if (!( @@ -312,17 +293,17 @@ namespace Ship { NegButton == BTN_VSTICKLEFT || NegButton == BTN_VSTICKRIGHT || NegButton == BTN_VSTICKUP || NegButton == BTN_VSTICKDOWN)) { - if (AxisValue > 0x1E00) { - dwPressedButtons[slot] |= PosButton; - dwPressedButtons[slot] &= ~NegButton; + if (AxisValue > AxisMinimumPress) { + getPressedButtons(virtualSlot) |= PosButton; + getPressedButtons(virtualSlot) &= ~NegButton; } - else if (AxisValue < -0x1E00) { - dwPressedButtons[slot] &= ~PosButton; - dwPressedButtons[slot] |= NegButton; + else if (AxisValue < -AxisMinimumPress) { + getPressedButtons(virtualSlot) &= ~PosButton; + getPressedButtons(virtualSlot) |= NegButton; } else { - dwPressedButtons[slot] &= ~PosButton; - dwPressedButtons[slot] &= ~NegButton; + getPressedButtons(virtualSlot) &= ~PosButton; + getPressedButtons(virtualSlot) &= ~NegButton; } } else { @@ -331,11 +312,11 @@ namespace Ship { SPDLOG_TRACE("Invalid PosStickX configured. Neg was {} and Pos is {}", RStickAxisX, Axis); } - if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", RStickDeadzone, AxisThreshold); + if (RStickDeadzone != 0 && RStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone configured. Up/Down was {} and Left/Right is {}", RStickDeadzone, AxisDeadzone); } - RStickDeadzone = AxisThreshold; + RStickDeadzone = AxisDeadzone; RStickAxisX = Axis; } @@ -344,11 +325,11 @@ namespace Ship { SPDLOG_TRACE("Invalid PosStickY configured. Neg was {} and Pos is {}", RStickAxisY, Axis); } - if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisThreshold); + if (RStickDeadzone != 0 && RStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisDeadzone); } - RStickDeadzone = AxisThreshold; + RStickDeadzone = AxisDeadzone; RStickAxisY = Axis; } @@ -357,11 +338,11 @@ namespace Ship { SPDLOG_TRACE("Invalid NegStickX configured. Pos was {} and Neg is {}", RStickAxisX, Axis); } - if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisThreshold); + if (RStickDeadzone != 0 && RStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone configured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisDeadzone); } - RStickDeadzone = AxisThreshold; + RStickDeadzone = AxisDeadzone; RStickAxisX = Axis; } @@ -370,28 +351,30 @@ namespace Ship { SPDLOG_TRACE("Invalid NegStickY configured. Pos was {} and Neg is {}", RStickAxisY, Axis); } - if (RStickDeadzone != 0 && RStickDeadzone != AxisThreshold) { - SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisThreshold); + if (RStickDeadzone != 0 && RStickDeadzone != AxisDeadzone) { + SPDLOG_TRACE("Invalid Deadzone misconfigured. Left/Right was {} and Up/Down is {}", RStickDeadzone, AxisDeadzone); } - RStickDeadzone = AxisThreshold; + RStickDeadzone = AxisDeadzone; RStickAxisY = Axis; } - } - if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { - const auto AxisValueX = SDL_GameControllerGetAxis(Cont, RStickAxisX); - const auto AxisValueY = SDL_GameControllerGetAxis(Cont, RStickAxisY); - NormalizeStickAxis(AxisValueX, AxisValueY, RStickDeadzone, true, profile.Thresholds[SENSITIVITY]); + if (LStickAxisX != SDL_CONTROLLER_AXIS_INVALID && LStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { + NormalizeStickAxis(LStickAxisX, LStickAxisY, LStickDeadzone, virtualSlot); + } + + if (RStickAxisX != SDL_CONTROLLER_AXIS_INVALID && RStickAxisY != SDL_CONTROLLER_AXIS_INVALID) { + NormalizeStickAxis(RStickAxisX, RStickAxisY, RStickDeadzone, virtualSlot); + } } } } - void SDLController::WriteToSource(int32_t slot, ControllerCallback* controller) + void SDLController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) { - if (CanRumble() && profiles[slot].UseRumble) { + if (CanRumble() && getProfile(virtualSlot)->UseRumble) { if (controller->rumble > 0) { - float rumble_strength = profiles[slot].RumbleStrength; + float rumble_strength = getProfile(virtualSlot)->RumbleStrength; SDL_GameControllerRumble(Cont, 0xFFFF * rumble_strength, 0xFFFF * rumble_strength, 0); } else { @@ -416,20 +399,11 @@ namespace Ship { } } } + + const std::string SDLController::GetButtonName(int32_t virtualSlot, int32_t n64Button) { + char buffer[50]; + std::map& Mappings = getProfile(virtualSlot)->Mappings; - const char* AxisNames[] = { - "Left Stick X", - "Left Stick Y", - "Right Stick X", - "Right Stick Y", - "Left Trigger", - "Right Trigger", - "Start Button" - }; - - char buffer[50]; - const char* SDLController::GetButtonName(int slot, int n64Button) { - std::map& Mappings = profiles[slot].Mappings; const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair& pair) { return pair.second == n64Button; }); @@ -449,42 +423,45 @@ namespace Ship { return buffer; } - const char* SDLController::GetControllerName() { - return strdup(ControllerName.c_str()); + const std::string SDLController::GetControllerName() { + return ControllerName; } - void SDLController::CreateDefaultBinding(int32_t slot) { - DeviceProfile& profile = profiles[slot]; - profile.Mappings.clear(); + void SDLController::CreateDefaultBinding(int32_t virtualSlot) { + auto profile = getProfile(virtualSlot); + profile->Mappings.clear(); - profile.UseRumble = true; - profile.RumbleStrength = 1.0f; - profile.UseGyro = false; - profile.Mappings[ SDL_CONTROLLER_AXIS_RIGHTX | AXIS_SCANCODE_BIT] = BTN_CRIGHT; - profile.Mappings[-(SDL_CONTROLLER_AXIS_RIGHTX | AXIS_SCANCODE_BIT)] = BTN_CLEFT; - profile.Mappings[ SDL_CONTROLLER_AXIS_RIGHTY | AXIS_SCANCODE_BIT] = BTN_CDOWN; - profile.Mappings[-(SDL_CONTROLLER_AXIS_RIGHTY | AXIS_SCANCODE_BIT)] = BTN_CUP; - profile.Mappings[SDL_CONTROLLER_AXIS_TRIGGERRIGHT + AXIS_SCANCODE_BIT] = BTN_R; - profile.Mappings[SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = BTN_L; - profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_RIGHT] = BTN_DRIGHT; - profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_LEFT] = BTN_DLEFT; - profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_DOWN] = BTN_DDOWN; - profile.Mappings[SDL_CONTROLLER_BUTTON_DPAD_UP] = BTN_DUP; - profile.Mappings[SDL_CONTROLLER_BUTTON_START] = BTN_START; - profile.Mappings[SDL_CONTROLLER_AXIS_TRIGGERLEFT + AXIS_SCANCODE_BIT] = BTN_Z; - profile.Mappings[SDL_CONTROLLER_BUTTON_B] = BTN_B; - profile.Mappings[SDL_CONTROLLER_BUTTON_A] = BTN_A; - profile.Mappings[(SDL_CONTROLLER_AXIS_LEFTX + AXIS_SCANCODE_BIT)] = BTN_STICKRIGHT; - profile.Mappings[-(SDL_CONTROLLER_AXIS_LEFTX + AXIS_SCANCODE_BIT)] = BTN_STICKLEFT; - profile.Mappings[SDL_CONTROLLER_AXIS_LEFTY + AXIS_SCANCODE_BIT] = BTN_STICKDOWN; - profile.Mappings[-(SDL_CONTROLLER_AXIS_LEFTY + AXIS_SCANCODE_BIT)] = BTN_STICKUP; - profile.Thresholds[LEFT_STICK] = 16.0f; - profile.Thresholds[RIGHT_STICK] = 16.0f; - profile.Thresholds[LEFT_TRIGGER] = 0x1E00; - profile.Thresholds[RIGHT_TRIGGER] = 0x1E00; - profile.Thresholds[DRIFT_X] = 0.0f; - profile.Thresholds[DRIFT_Y] = 0.0f; - profile.Thresholds[SENSITIVITY] = 16.0f; - profile.Thresholds[GYRO_SENSITIVITY] = 1.0f; + profile->UseRumble = true; + profile->RumbleStrength = 1.0f; + profile->UseGyro = false; + + profile->Mappings[SDL_CONTROLLER_AXIS_RIGHTX | AXIS_SCANCODE_BIT] = BTN_CRIGHT; + profile->Mappings[-(SDL_CONTROLLER_AXIS_RIGHTX | AXIS_SCANCODE_BIT)] = BTN_CLEFT; + profile->Mappings[SDL_CONTROLLER_AXIS_RIGHTY | AXIS_SCANCODE_BIT] = BTN_CDOWN; + profile->Mappings[-(SDL_CONTROLLER_AXIS_RIGHTY | AXIS_SCANCODE_BIT)] = BTN_CUP; + profile->Mappings[SDL_CONTROLLER_AXIS_LEFTX | AXIS_SCANCODE_BIT] = BTN_STICKRIGHT; + profile->Mappings[-(SDL_CONTROLLER_AXIS_LEFTX | AXIS_SCANCODE_BIT)] = BTN_STICKLEFT; + profile->Mappings[SDL_CONTROLLER_AXIS_LEFTY | AXIS_SCANCODE_BIT] = BTN_STICKDOWN; + profile->Mappings[-(SDL_CONTROLLER_AXIS_LEFTY | AXIS_SCANCODE_BIT)] = BTN_STICKUP; + profile->Mappings[SDL_CONTROLLER_AXIS_TRIGGERRIGHT | AXIS_SCANCODE_BIT] = BTN_R; + profile->Mappings[SDL_CONTROLLER_AXIS_TRIGGERLEFT | AXIS_SCANCODE_BIT] = BTN_Z; + profile->Mappings[SDL_CONTROLLER_BUTTON_LEFTSHOULDER] = BTN_L; + profile->Mappings[SDL_CONTROLLER_BUTTON_DPAD_RIGHT] = BTN_DRIGHT; + profile->Mappings[SDL_CONTROLLER_BUTTON_DPAD_LEFT] = BTN_DLEFT; + profile->Mappings[SDL_CONTROLLER_BUTTON_DPAD_DOWN] = BTN_DDOWN; + profile->Mappings[SDL_CONTROLLER_BUTTON_DPAD_UP] = BTN_DUP; + profile->Mappings[SDL_CONTROLLER_BUTTON_START] = BTN_START; + profile->Mappings[SDL_CONTROLLER_BUTTON_B] = BTN_B; + profile->Mappings[SDL_CONTROLLER_BUTTON_A] = BTN_A; + + for (int32_t i = SDL_CONTROLLER_AXIS_LEFTX; i < SDL_CONTROLLER_AXIS_MAX; i++) { + profile->AxisSensitivities[i] = 1.0f; + profile->AxisDeadzones[i] = 16.0f; + profile->AxisMinimumPress[i] = 7680.0f; + } + + profile->GyroData[DRIFT_X] = 0.0f; + profile->GyroData[DRIFT_Y] = 0.0f; + profile->GyroData[GYRO_SENSITIVITY] = 1.0f; } } diff --git a/libultraship/libultraship/SDLController.h b/libultraship/libultraship/SDLController.h index b5005e323..e9c696dac 100644 --- a/libultraship/libultraship/SDLController.h +++ b/libultraship/libultraship/SDLController.h @@ -5,18 +5,28 @@ namespace Ship { class SDLController : public Controller { public: - SDLController(int slot) : Controller(), Cont(nullptr), physicalSlot(slot) { } - void ReadFromSource(int32_t slot) override; - const char* GetControllerName() override; - const char* GetButtonName(int slot, int n64Button) override; - void WriteToSource(int32_t slot, ControllerCallback* controller) override; + inline static const char* AxisNames[] = { + "Left Stick X", + "Left Stick Y", + "Right Stick X", + "Right Stick Y", + "Left Trigger", + "Right Trigger", + "Start Button" + }; + + SDLController(int32_t physicalSlot) : Controller(), Cont(nullptr), physicalSlot(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; bool Connected() const override { return Cont != nullptr; } bool CanGyro() const override { return supportsGyro; } bool CanRumble() const override { #if SDL_COMPILEDVERSION >= SDL_VERSIONNUM(2,0,18) return SDL_GameControllerHasRumble(Cont); #endif - return true; + return false; } bool Open(); @@ -24,14 +34,14 @@ namespace Ship { int32_t ReadRawPress() override; protected: - void CreateDefaultBinding(int32_t slot) override; + void CreateDefaultBinding(int32_t virtualSlot) override; private: std::string ControllerName = "Unknown"; SDL_GameController* Cont; - int physicalSlot; + int32_t physicalSlot; bool supportsGyro; - void NormalizeStickAxis(int16_t wAxisValueX, int16_t wAxisValueY, int16_t wAxisThreshold, bool isRightStick, float sensitivity); + void NormalizeStickAxis(SDL_GameControllerAxis axisX, SDL_GameControllerAxis axisY, int16_t axisThreshold, int32_t virtualSlot); bool Close(); }; } diff --git a/libultraship/libultraship/UltraController.h b/libultraship/libultraship/UltraController.h index 41ea7f082..cac606126 100644 --- a/libultraship/libultraship/UltraController.h +++ b/libultraship/libultraship/UltraController.h @@ -124,8 +124,8 @@ typedef struct { /* 0x04 */ uint8_t err_no; /* 0x05 */ float gyro_x; /* 0x09 */ float gyro_y; - /* 0x1C */ float cam_x; - /* 0x20 */ float cam_y; + /* 0x1C */ int8_t right_stick_x; + /* 0x20 */ int8_t right_stick_y; } OSContPad; // size = 0x24 typedef struct { diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp index f4f047428..b302fbfec 100644 --- a/libultraship/libultraship/Window.cpp +++ b/libultraship/libultraship/Window.cpp @@ -61,8 +61,8 @@ extern "C" { pad->button = 0; pad->stick_x = 0; pad->stick_y = 0; - pad->cam_x = 0; - pad->cam_y = 0; + pad->right_stick_x = 0; + pad->right_stick_y = 0; pad->err_no = 0; pad->gyro_x = 0; pad->gyro_y = 0; diff --git a/soh/src/code/z_camera.c b/soh/src/code/z_camera.c index 10a89acdb..dcd70abbe 100644 --- a/soh/src/code/z_camera.c +++ b/soh/src/code/z_camera.c @@ -1410,8 +1410,8 @@ s32 Camera_Noop(Camera* camera) { } s32 SetCameraManual(Camera* camera) { - f32 newCamX = -D_8015BD7C->state.input[0].cur.cam_x; - f32 newCamY = D_8015BD7C->state.input[0].cur.cam_y; + f32 newCamX = -D_8015BD7C->state.input[0].cur.cam_x * 10.0f; + f32 newCamY = D_8015BD7C->state.input[0].cur.cam_y * 10.0f; if ((fabsf(newCamX) >= 15.0f || fabsf(newCamY) >= 15.0f) && camera->globalCtx->manualCamera == false) { camera->globalCtx->manualCamera = true; @@ -1479,8 +1479,8 @@ s32 Camera_Free(Camera* camera) { camera->animState = 1; - f32 newCamX = -D_8015BD7C->state.input[0].cur.cam_x; - f32 newCamY = D_8015BD7C->state.input[0].cur.cam_y; + f32 newCamX = -D_8015BD7C->state.input[0].cur.cam_x * 10.0f; + f32 newCamY = D_8015BD7C->state.input[0].cur.cam_y * 10.0f; camera->globalCtx->camX += newCamX; camera->globalCtx->camY += newCamY; diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index eaa2bb24a..412767866 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -128,8 +128,8 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) { } else if ((AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT)) || (AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CRIGHT))) { link_kaleido_rot.y = link_kaleido_rot.y + RotationSpeed; - } else if(AllowStickRotation && input->cur.cam_x != 0){ - link_kaleido_rot.y = link_kaleido_rot.y + (input->cur.cam_x*(((f32)RotationSpeed)/600.0f)); + } else if(AllowStickRotation && input->cur.cam_x*10.0f != 0){ + link_kaleido_rot.y = link_kaleido_rot.y + (input->cur.cam_x*10.0f*(((f32)RotationSpeed)/600.0f)); } if ((AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DUP)) || // reset rotation @@ -138,13 +138,13 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) { } else if ((AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CUP)) || (AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CDOWN))) { link_kaleido_rot.y = 32300; - } else if (AllowStickRotation && input->cur.cam_y < -1200) { + } else if (AllowStickRotation && input->cur.cam_y * 10.0f < -1200) { link_kaleido_rot.y = 32300; } - if (AllowStickRotation && input->cur.cam_y>0) { // Zoom in - scale = scale + input->cur.cam_y*.00005; - pos.y = pos.y - input->cur.cam_y*.25; + if (AllowStickRotation && input->cur.cam_y * 10.0f > 0) { // Zoom in + scale = scale + input->cur.cam_y*10.0f*.00005f; + pos.y = pos.y - input->cur.cam_y*10.0f*0.25f; }