diff --git a/Editor/Editor.xcodeproj/project.pbxproj b/Editor/Editor.xcodeproj/project.pbxproj index 0d2a844b3..118ad03c3 100644 --- a/Editor/Editor.xcodeproj/project.pbxproj +++ b/Editor/Editor.xcodeproj/project.pbxproj @@ -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 */, diff --git a/README.md b/README.md index 66c09b2ff..cd42695ec 100644 --- a/README.md +++ b/README.md @@ -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.
- [Website](https://wickedengine.net/)
-- [Forum](https://wickedengine.net/forum/)
- [Features](features.txt)
- [Editor Manual](Content/Documentation/WickedEditor-Manual.pdf)
- [C++ Documentation](Content/Documentation/WickedEngine-Documentation.md)
@@ -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. diff --git a/Samples/Template_MacOS/Template_MacOS.xcodeproj/project.pbxproj b/Samples/Template_MacOS/Template_MacOS.xcodeproj/project.pbxproj index 77c2fed02..50d0dd9cd 100644 --- a/Samples/Template_MacOS/Template_MacOS.xcodeproj/project.pbxproj +++ b/Samples/Template_MacOS/Template_MacOS.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 = ""; }; 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 */, diff --git a/WickedEngine/WickedEngine.xcodeproj/project.pbxproj b/WickedEngine/WickedEngine.xcodeproj/project.pbxproj index 85f4b5647..87bc72628 100644 --- a/WickedEngine/WickedEngine.xcodeproj/project.pbxproj +++ b/WickedEngine/WickedEngine.xcodeproj/project.pbxproj @@ -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 = ""; }; 1E7929892EFE75BA00B9E35C /* wiAppleHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = wiAppleHelper.mm; sourceTree = ""; }; 1E79298B2EFE76C500B9E35C /* wiAppleHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wiAppleHelper.h; sourceTree = ""; }; + 1EBD1BFF2F2514D700C29B34 /* wiInput_Apple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wiInput_Apple.h; sourceTree = ""; }; + 1EBD1C002F2514E700C29B34 /* wiInput_Apple.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = wiInput_Apple.mm; sourceTree = ""; }; + 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 = ""; }; 1ED576B92F0115B40032621C /* bcn_common_kernel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bcn_common_kernel.h; sourceTree = ""; }; 1ED576BA2F0115B40032621C /* common_def.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common_def.h; sourceTree = ""; }; @@ -1624,6 +1628,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 1EBD1C022F25166100C29B34 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1EBD1C032F25166100C29B34 /* GameController.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 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 = ""; }; @@ -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 */, diff --git a/WickedEngine/offlineshadercompiler.xcodeproj/project.pbxproj b/WickedEngine/offlineshadercompiler.xcodeproj/project.pbxproj index c2c6ab432..54715c6cb 100644 --- a/WickedEngine/offlineshadercompiler.xcodeproj/project.pbxproj +++ b/WickedEngine/offlineshadercompiler.xcodeproj/project.pbxproj @@ -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 = ""; }; 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 */, diff --git a/WickedEngine/wiInput.cpp b/WickedEngine/wiInput.cpp index d2704af2c..333491548 100644 --- a/WickedEngine/wiInput.cpp +++ b/WickedEngine/wiInput.cpp @@ -26,6 +26,7 @@ #endif // PLATFORM_PS5 #ifdef __APPLE__ +#include "wiInput_Apple.h" #include #include 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) { diff --git a/WickedEngine/wiInput_Apple.h b/WickedEngine/wiInput_Apple.h new file mode 100644 index 000000000..5f095e47e --- /dev/null +++ b/WickedEngine/wiInput_Apple.h @@ -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); +} + diff --git a/WickedEngine/wiInput_Apple.mm b/WickedEngine/wiInput_Apple.mm new file mode 100644 index 000000000..ef3ca46a5 --- /dev/null +++ b/WickedEngine/wiInput_Apple.mm @@ -0,0 +1,151 @@ +#include "wiInput_Apple.h" + +#import +#import + +#include + +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 +} + +} diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 86adad5f3..742061907 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -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);