Mac OS controller support (#1515)
This commit is contained in:
@@ -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 */,
|
||||
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user