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; }