Mac OS controller support (#1515)

This commit is contained in:
Turánszki János
2026-01-25 12:24:08 +01:00
committed by GitHub
parent 7c8934ba72
commit c8d712513b
9 changed files with 248 additions and 3 deletions
+4
View File
@@ -65,6 +65,7 @@
1E73E7142F0510C10090D1DA /* main_MacOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1E73E7132F0510B40090D1DA /* main_MacOS.mm */; };
1E73E7392F0513710090D1DA /* libWickedEngine.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E73E7382F0513620090D1DA /* libWickedEngine.a */; };
1E73E7552F053DBE0090D1DA /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E73E7532F053DBE0090D1DA /* Metal.framework */; };
1EBD1C072F251B7E00C29B34 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBD1C052F251B7E00C29B34 /* GameController.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -225,6 +226,7 @@
1E73E74D2F053DAB0090D1DA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
1E73E7512F053DB80090D1DA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
1E73E7532F053DBE0090D1DA /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
1EBD1C052F251B7E00C29B34 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -232,6 +234,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1EBD1C072F251B7E00C29B34 /* GameController.framework in Frameworks */,
1E640FDB2F0AE648003D9FC7 /* AppKit.framework in Frameworks */,
1E73E7392F0513710090D1DA /* libWickedEngine.a in Frameworks */,
1E73E7552F053DBE0090D1DA /* Metal.framework in Frameworks */,
@@ -406,6 +409,7 @@
1E73E7162F0511130090D1DA /* Frameworks */ = {
isa = PBXGroup;
children = (
1EBD1C052F251B7E00C29B34 /* GameController.framework */,
1E73E7532F053DBE0090D1DA /* Metal.framework */,
1E73E7512F053DB80090D1DA /* Foundation.framework */,
1E73E74D2F053DAB0090D1DA /* AppKit.framework */,
+1 -2
View File
@@ -15,7 +15,6 @@
Wicked Engine is an open-source 3D engine with modern graphics. Use this as a C++ framework for your graphics projects, a standalone 3D editor, LUA scripting or just for learning.<br/>
- [Website](https://wickedengine.net/)<br/>
- [Forum](https://wickedengine.net/forum/)<br/>
- [Features](features.txt)<br/>
- [Editor Manual](Content/Documentation/WickedEditor-Manual.pdf)<br/>
- [C++ Documentation](Content/Documentation/WickedEngine-Documentation.md)<br/>
@@ -83,7 +82,7 @@ To build the engine for Mac OS, use the provided .xcodeproj files with the Xcod
- Editor/Editor.xcodeproj to build the Wicked Editor
- Samples/Template_MacOS/Template_MacOS.xcodeproj to build a minimal template application for MacOS
If you want to develop an application that uses Wicked Engine, you will have to link to libWickedEngine.a and `#include "WickedEngine.h"` into the source code. You also need to add references to the following Apple SDKs: `Metal`, `AppKit`. I also recommend to set up a custom working directory in the Product->Scheme->Edit Scheme->Options->custom working directory = `$(PROJECT_DIR)`, this will better match the development experience in Visual Studio. For examples, look at the Template_MacOS and Editor projects.
If you want to develop an application that uses Wicked Engine, you will have to link to libWickedEngine.a and `#include "WickedEngine.h"` into the source code. You also need to add references to the following Apple SDKs: `Metal`, `AppKit`, `GameController`. I also recommend to set up a custom working directory in the Product->Scheme->Edit Scheme->Options->custom working directory = `$(PROJECT_DIR)`, this will better match the development experience in Visual Studio. For examples, look at the Template_MacOS and Editor projects.
#### Xbox Series X|S
Xbox Series specific extension files required for building are currently private.
@@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
1E79298D2EFE77ED00B9E35C /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1E79298C2EFE77ED00B9E35C /* main.mm */; };
1E79298F2EFE783B00B9E35C /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E79298E2EFE783B00B9E35C /* AppKit.framework */; };
1EBD1C112F2525E900C29B34 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBD1C0F2F2525E900C29B34 /* GameController.framework */; };
1EDA80B52EE2C9BD00210D41 /* libWickedEngine.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EDA80B42EE2C9BD00210D41 /* libWickedEngine.a */; };
1EDA82202EE3802C00210D41 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EDA821F2EE3802C00210D41 /* Metal.framework */; };
/* End PBXBuildFile section */
@@ -26,6 +27,7 @@
/* Begin PBXFileReference section */
1E79298C2EFE77ED00B9E35C /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
1E79298E2EFE783B00B9E35C /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
1EBD1C0F2F2525E900C29B34 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
1EDA807B2EE2C1DB00210D41 /* Template_MacOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Template_MacOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
1EDA809E2EE2C5AD00210D41 /* WickedEngine.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = WickedEngine.xcodeproj; path = ../../WickedEngine/WickedEngine.xcodeproj; sourceTree = "<group>"; };
1EDA821F2EE3802C00210D41 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
@@ -38,6 +40,7 @@
files = (
1E79298F2EFE783B00B9E35C /* AppKit.framework in Frameworks */,
1EDA82202EE3802C00210D41 /* Metal.framework in Frameworks */,
1EBD1C112F2525E900C29B34 /* GameController.framework in Frameworks */,
1EDA80B52EE2C9BD00210D41 /* libWickedEngine.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -65,6 +68,7 @@
1EDA809D2EE2C5AD00210D41 /* Frameworks */ = {
isa = PBXGroup;
children = (
1EBD1C0F2F2525E900C29B34 /* GameController.framework */,
1E79298E2EFE783B00B9E35C /* AppKit.framework */,
1EDA821F2EE3802C00210D41 /* Metal.framework */,
1EDA809E2EE2C5AD00210D41 /* WickedEngine.xcodeproj */,
@@ -11,6 +11,7 @@
1E640FEA2F0B0565003D9FC7 /* libdxcompiler.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 1EDA8A692EE5D68100210D41 /* libdxcompiler.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
1E640FEC2F0B0567003D9FC7 /* libmetalirconverter.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 1E640FE12F0AEC0B003D9FC7 /* libmetalirconverter.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
1E79298A2EFE75E400B9E35C /* wiAppleHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1E7929892EFE75BA00B9E35C /* wiAppleHelper.mm */; };
1EBD1C012F2514EC00C29B34 /* wiInput_Apple.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1EBD1C002F2514E700C29B34 /* wiInput_Apple.mm */; };
1EDA7A562EE1DF2100210D41 /* wiArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EDA7A552EE1DF2100210D41 /* wiArchive.cpp */; };
1EDA7B042EE1DFE300210D41 /* wiNetwork_Linux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EDA7AA82EE1DFE300210D41 /* wiNetwork_Linux.cpp */; };
1EDA7B062EE1DFE300210D41 /* wiScene_Components.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1EDA7AD92EE1DFE300210D41 /* wiScene_Components.cpp */; };
@@ -299,6 +300,9 @@
1E640FE12F0AEC0B003D9FC7 /* libmetalirconverter.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libmetalirconverter.dylib; sourceTree = "<group>"; };
1E7929892EFE75BA00B9E35C /* wiAppleHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = wiAppleHelper.mm; sourceTree = "<group>"; };
1E79298B2EFE76C500B9E35C /* wiAppleHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wiAppleHelper.h; sourceTree = "<group>"; };
1EBD1BFF2F2514D700C29B34 /* wiInput_Apple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wiInput_Apple.h; sourceTree = "<group>"; };
1EBD1C002F2514E700C29B34 /* wiInput_Apple.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = wiInput_Apple.mm; sourceTree = "<group>"; };
1EBD1C032F25166100C29B34 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
1ED576B82F0115B40032621C /* bcn_common_api.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bcn_common_api.h; sourceTree = "<group>"; };
1ED576B92F0115B40032621C /* bcn_common_kernel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bcn_common_kernel.h; sourceTree = "<group>"; };
1ED576BA2F0115B40032621C /* common_def.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common_def.h; sourceTree = "<group>"; };
@@ -1624,6 +1628,14 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1EBD1C022F25166100C29B34 /* Frameworks */ = {
isa = PBXGroup;
children = (
1EBD1C032F25166100C29B34 /* GameController.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
1ED576BB2F0115B40032621C /* compressonator */ = {
isa = PBXGroup;
children = (
@@ -2085,6 +2097,8 @@
1EDA71632EE0978C00210D41 = {
isa = PBXGroup;
children = (
1EBD1C002F2514E700C29B34 /* wiInput_Apple.mm */,
1EBD1BFF2F2514D700C29B34 /* wiInput_Apple.h */,
1E640FE12F0AEC0B003D9FC7 /* libmetalirconverter.dylib */,
1ED5785F2F0115B40032621C /* shaders */,
1E79298B2EFE76C500B9E35C /* wiAppleHelper.h */,
@@ -2271,6 +2285,7 @@
1EDA7B032EE1DFE300210D41 /* wiVoxelGrid_BindLua.cpp */,
1EDA7A552EE1DF2100210D41 /* wiArchive.cpp */,
1EDA7BB12EE1E60500210D41 /* libWickedEngine.a */,
1EBD1C022F25166100C29B34 /* Frameworks */,
);
sourceTree = "<group>";
};
@@ -3400,6 +3415,7 @@
1EDA7DB62EE1EC9500210D41 /* SkeletonMapper.cpp in Sources */,
1EDA7DB72EE1EC9500210D41 /* SkeletonPose.cpp in Sources */,
1EDA7DB82EE1EC9500210D41 /* CylinderShape.cpp in Sources */,
1EBD1C012F2514EC00C29B34 /* wiInput_Apple.mm in Sources */,
1EDA7DB92EE1EC9500210D41 /* PhysicsSystem.cpp in Sources */,
1EDA7DBA2EE1EC9500210D41 /* TriangleSplitter.cpp in Sources */,
1EDA7DBB2EE1EC9500210D41 /* DebugRendererPlayback.cpp in Sources */,
@@ -11,6 +11,7 @@
1E640FC92F0AE1C3003D9FC7 /* libWickedEngine.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E640FC22F0AE07B003D9FC7 /* libWickedEngine.a */; };
1E640FD02F0AE275003D9FC7 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E640FCF2F0AE275003D9FC7 /* Metal.framework */; };
1E640FD42F0AE282003D9FC7 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E640FD32F0AE282003D9FC7 /* AppKit.framework */; };
1EBD1C0D2F2525BD00C29B34 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1EBD1C0B2F2525BD00C29B34 /* GameController.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -41,6 +42,7 @@
1E640FBD2F0AE07B003D9FC7 /* WickedEngine.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = WickedEngine.xcodeproj; sourceTree = "<group>"; };
1E640FCF2F0AE275003D9FC7 /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; };
1E640FD32F0AE282003D9FC7 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
1EBD1C0B2F2525BD00C29B34 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -50,6 +52,7 @@
files = (
1E640FD02F0AE275003D9FC7 /* Metal.framework in Frameworks */,
1E640FD42F0AE282003D9FC7 /* AppKit.framework in Frameworks */,
1EBD1C0D2F2525BD00C29B34 /* GameController.framework in Frameworks */,
1E640FC92F0AE1C3003D9FC7 /* libWickedEngine.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -77,6 +80,7 @@
1E640FBC2F0AE07B003D9FC7 /* Frameworks */ = {
isa = PBXGroup;
children = (
1EBD1C0B2F2525BD00C29B34 /* GameController.framework */,
1E640FD32F0AE282003D9FC7 /* AppKit.framework */,
1E640FCF2F0AE275003D9FC7 /* Metal.framework */,
1E640FBD2F0AE07B003D9FC7 /* WickedEngine.xcodeproj */,
+47
View File
@@ -26,6 +26,7 @@
#endif // PLATFORM_PS5
#ifdef __APPLE__
#include "wiInput_Apple.h"
#include <ApplicationServices/ApplicationServices.h>
#include <Carbon/Carbon.h>
namespace wi::input::apple
@@ -141,6 +142,7 @@ namespace wi::input
RAWINPUT,
SDLINPUT,
PS5,
APPLE,
};
DeviceType deviceType;
int deviceIndex;
@@ -161,6 +163,7 @@ namespace wi::input
#endif // PLATFORM_PS5
#ifdef __APPLE__
wi::input::apple::Initialize();
wi::apple::CursorInit(cursor_table_original);
#endif // __APPLE__
@@ -336,6 +339,39 @@ namespace wi::input
}
}
#ifdef __APPLE__
// Check if low-level Apple controller is not registered for playerindex slot and register:
for (int i = 0; i < wi::input::apple::GetMaxControllerCount(); ++i)
{
if (wi::input::apple::GetControllerState(nullptr, i))
{
int slot = -1;
for (int j = 0; j < (int)controllers.size(); ++j)
{
if (slot < 0 && controllers[j].deviceType == Controller::DISCONNECTED)
{
// take the first disconnected slot
slot = j;
}
if (controllers[j].deviceType == Controller::APPLE && controllers[j].deviceIndex == i)
{
// it is already registered to this slot
slot = j;
break;
}
}
if (slot == -1)
{
// no disconnected slot was found, and it was not registered
slot = (int)controllers.size();
controllers.emplace_back();
}
controllers[slot].deviceType = Controller::APPLE;
controllers[slot].deviceIndex = i;
}
}
#endif // __APPLE__
#ifdef PLATFORM_PS5
// Check if low-level PS5 controller is not registered for playerindex slot and register:
for (int i = 0; i < wi::input::ps5::GetMaxControllerCount(); ++i)
@@ -389,6 +425,11 @@ namespace wi::input
connected = wi::input::ps5::GetControllerState(&controller.state, controller.deviceIndex);
#endif // PLATFORM_PS5
break;
case Controller::APPLE:
#ifdef __APPLE__
connected = wi::input::apple::GetControllerState(&controller.state, controller.deviceIndex);
#endif // __APPLE__
break;
case Controller::DISCONNECTED:
connected = false;
break;
@@ -1132,6 +1173,12 @@ namespace wi::input
{
wi::input::sdlinput::SetControllerFeedback(data, controller.deviceIndex);
}
#ifdef __APPLE__
else if (controller.deviceType == Controller::APPLE)
{
wi::input::apple::SetControllerFeedback(data, controller.deviceIndex);
}
#endif // __APPLE__
#ifdef PLATFORM_PS5
else if (controller.deviceType == Controller::PS5)
{
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "CommonInclude.h"
#include "wiInput.h"
namespace wi::input::apple
{
// Initialize once
void Initialize();
// Returns how many gamepads can Xinput handle
int GetMaxControllerCount();
// Returns whether the controller identified by index parameter is available or not.
// Id state parameter is not nullptr, and the controller is available, the state will be written into it
bool GetControllerState(wi::input::ControllerState* state, int index);
// Sends feedback data for the controller identified by index parameter to output
void SetControllerFeedback(const wi::input::ControllerFeedback& data, int index);
}
+151
View File
@@ -0,0 +1,151 @@
#include "wiInput_Apple.h"
#import <Cocoa/Cocoa.h>
#import <GameController/GameController.h>
#include <mutex>
namespace wi::input::apple
{
static std::mutex locker;
static GCController* controllers[8] = {};
void Initialize()
{
@autoreleasepool {
// Register new controller event:
[[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidConnectNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
GCController *controller = note.object;
std::scoped_lock lck(locker);
for (int i = 0; i < arraysize(controllers); ++i)
{
if (controllers[i] == nullptr)
{
controllers[i] = controller;
break;
}
}
}];
// Remove controller event:
[[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
GCController *controller = note.object;
std::scoped_lock lck(locker);
for (int i = 0; i < arraysize(controllers); ++i)
{
if (controllers[i] == controller)
{
controllers[i] = nullptr;
break;
}
}
}];
// Register already connected controllers:
for (GCController *controller in [GCController controllers])
{
std::scoped_lock lck(locker);
for (int i = 0; i < arraysize(controllers); ++i)
{
if (controllers[i] == nullptr)
{
controllers[i] = controller;
break;
}
}
}
}
}
int GetMaxControllerCount()
{
return arraysize(controllers);
}
constexpr float deadzone(float x)
{
if (x > -0.24f && x < 0.24f)
return 0.f;
return clamp(x, -1.0f, 1.0f);
}
constexpr uint64_t buttonToBit(int button)
{
return 1ull << (button - GAMEPAD_RANGE_START - 1);
}
bool GetControllerState(wi::input::ControllerState* state, int index)
{
std::scoped_lock lck(locker);
if (index < 0 || index >= arraysize(controllers))
return false;
GCController* controller = controllers[index];
if (controller == nullptr)
return false;
GCExtendedGamepad* pad = controller.extendedGamepad;
if (pad == nullptr)
return false;
if (state)
{
*state = wi::input::ControllerState();
if (pad.dpad.up.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_UP);
if (pad.dpad.left.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_LEFT);
if (pad.dpad.down.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_DOWN);
if (pad.dpad.right.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_RIGHT);
// It looks like this exactly matches the xbox layout:
if (pad.buttonX.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_X);
if (pad.buttonA.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_A);
if (pad.buttonB.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_B);
if (pad.buttonY.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_Y);
if (pad.leftShoulder.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_L1);
if (pad.rightShoulder.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_R1);
if (pad.leftThumbstickButton.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_L3);
if (pad.rightThumbstickButton.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_R3);
if (pad.buttonMenu.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_START);
if (pad.buttonOptions.pressed) state->buttons |= buttonToBit(GAMEPAD_BUTTON_XBOX_BACK);
state->thumbstick_L = XMFLOAT2(deadzone(pad.leftThumbstick.xAxis.value), deadzone(pad.leftThumbstick.yAxis.value));
state->thumbstick_R = XMFLOAT2(deadzone(pad.rightThumbstick.xAxis.value), -deadzone(pad.rightThumbstick.yAxis.value));
state->trigger_L = pad.leftTrigger.value;
state->trigger_R = pad.rightTrigger.value;
}
return true;
}
void SetControllerFeedback(const wi::input::ControllerFeedback& data, int index)
{
std::scoped_lock lck(locker);
if (index < 0 || index >= arraysize(controllers))
return;
GCController* controller = controllers[index];
if (controller == nullptr)
return;
if (controller.light)
{
XMFLOAT3 color = data.led_color.toFloat3();
controller.light.color = [[GCColor alloc] initWithRed:color.x green:color.y blue:color.z];
}
// TODO: vibration
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 72;
// minor bug fixes, alterations, refactors, updates
const int revision = 17;
const int revision = 18;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);