Skip to content

Commit ccaf34d

Browse files
committed
v1.0Final - Comprehensive DirectInput Force Feedback & Input System Overhaul
Implements a complete runtime and editor-based input management system with DirectInput Force Feedback support and IL2CPP compatibility. Core Changes: - Added Logitech SDK logics - Added runtime configuration UIs (F2: Input Mapping, F3: FFB Settings) - Implemented IL2CPP callback support with proper __stdcall convention - Added input mapping cache with duplicate protection - Integrated real-time device detection and configuration Technical Improvements: - Enhanced error handling and device connection management - Implemented proper FFB effect cleanup and memory management - Added DBTEvents enum support (0x0007, 0x8000, 0x8004) - Streamlined save/load system with PlayerPrefs persistence - Fixed IL2CPP NotSupportedException in Windows builds The update provides a complete runtime alternative to editor-only configuration, enabling both FFB and input mapping adjustments during gameplay while ensuring proper IL2CPP support for production builds. Core Changes: - Added Logitech SDK logics - Added runtime configuration UIs (F2: Input Mapping, F3: FFB Settings) - Implemented IL2CPP callback support with proper __stdcall convention - Added input mapping cache with duplicate protection - Integrated real-time device detection and configuration Technical Improvements: - Enhanced error handling and device connection management - Implemented proper FFB effect cleanup and memory management - Added DBTEvents enum support (0x0007, 0x8000, 0x8004) - Streamlined save/load system with PlayerPrefs persistence - Fixed IL2CPP NotSupportedException in Windows builds The update provides a complete runtime alternative to editor-only configuration, enabling both FFB and input mapping adjustments during gameplay while ensuring proper IL2CPP support for production builds.
1 parent 920018e commit ccaf34d

25 files changed

+50
-1888
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ sysinfo.txt
7777
# Builds
7878
*.apk
7979
*.aab
80-
*.unitypackage
80+
#.unitypackage
8181

8282
# Crashlytics generated file
8383
crashlytics-build.properties
22.9 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.

DirectInputForceFeedback~/DirectInputForceFeedback/DirectInputForceFeedback.cpp

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ std::map < DeviceGUID, std::vector<DIDEVICEOBJECTINSTANCE> > _DeviceF
1313
std::map < DeviceGUID, std::map<Effects::Type, DIEFFECT> > _DeviceFFBEffectConfig; // Effect Configuration
1414
std::map < DeviceGUID, std::map<Effects::Type, LPDIRECTINPUTEFFECT> > _DeviceFFBEffectControl; // Handle to Start/Stop Effect
1515

16-
DeviceChangeCallback _DeviceChangeCallback; // External function to invoke on device change
16+
DeviceChangeCallback g_deviceCallback = nullptr;
1717

1818
std::vector<std::wstring> DEBUGDATA; // Used for Debugging during development
1919

@@ -595,7 +595,7 @@ HRESULT StopAllFFBEffects(LPCSTR guidInstance) {
595595
}
596596

597597
void SetDeviceChangeCallback(DeviceChangeCallback CB) {
598-
_DeviceChangeCallback = CB;
598+
g_deviceCallback = CB;
599599
}
600600

601601
// Generate SAFEARRAY of DEBUG data
@@ -702,34 +702,18 @@ BOOL CALLBACK _EnumFFBAxisCallback(const DIDEVICEOBJECTINSTANCE* ObjectInst, LPV
702702
}
703703

704704
LRESULT _WindowsHookCallback(int code, WPARAM wParam, LPARAM lParam) {
705-
if (code < 0) return CallNextHookEx(NULL, code, wParam, lParam); // invalid code skip
705+
if (code < 0) return CallNextHookEx(NULL, code, wParam, lParam);
706706

707-
// check if device was added/removed
708707
PCWPSTRUCT pMsg = PCWPSTRUCT(lParam);
709708
if (pMsg->message == WM_DEVICECHANGE) {
710-
if (_DeviceChangeCallback) { _DeviceChangeCallback((int)pMsg->wParam); } // If callback assigned, invoke it
711-
//switch (pMsg->wParam) {
712-
// case DBT_DEVNODES_CHANGED:
713-
// DEBUGDATA.push_back(L"Changed!");
714-
// // TODO: Invoke Callback
715-
// //if (_DeviceChangeCallback) { _DeviceChangeCallback(1); }
716-
// break;
717-
// case DBT_DEVICEARRIVAL:
718-
// DEBUGDATA.push_back(L"Arrival!");
719-
// // TODO: Invoke Callback
720-
// break;
721-
// case DBT_DEVICEREMOVECOMPLETE:
722-
// DEBUGDATA.push_back(L"Remove!");
723-
// // TODO: Invoke Callback
724-
// break;
725-
// default:
726-
// DEBUGDATA.push_back(L"Other!");
727-
// break;
728-
//}
709+
if (g_deviceCallback) {
710+
g_deviceCallback(static_cast<DBTEvents>(pMsg->wParam));
711+
}
729712
}
730-
return CallNextHookEx(NULL, code, wParam, lParam); // Continue to next hook
713+
return CallNextHookEx(NULL, code, wParam, lParam);
731714
}
732715

716+
733717
//////////////////////////////////////////////////////////////
734718
// Helper Functions
735719
//////////////////////////////////////////////////////////////

DirectInputForceFeedback~/DirectInputForceFeedback/DirectInputForceFeedback.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,19 @@ extern "C" { // Everything to be made available by the DLL
9595
DIRECTINPUTFORCEFEEDBACK_API HRESULT DestroyFFBEffect(LPCSTR guidInstance, Effects::Type effectType);
9696
DIRECTINPUTFORCEFEEDBACK_API HRESULT UpdateFFBEffect(LPCSTR guidInstance, Effects::Type effectType, DICONDITION* conditions);
9797
DIRECTINPUTFORCEFEEDBACK_API HRESULT StopAllFFBEffects(LPCSTR guidInstance);
98-
99-
typedef void(__stdcall* DeviceChangeCallback)(int);
100-
DIRECTINPUTFORCEFEEDBACK_API void SetDeviceChangeCallback(DeviceChangeCallback CB);
101-
102-
10398
DIRECTINPUTFORCEFEEDBACK_API HRESULT DEBUG1(LPCSTR guidInstance, /*[out]*/ SAFEARRAY** DebugData);
99+
extern "C" { // Everything to be made available by the DLL
100+
enum DBTEvents {
101+
DBTDEVNODESCHANGED = 0x0007,
102+
DBTDEVICEARRIVAL = 0x8000,
103+
DBTDEVICEREMOVECOMPLETE = 0x8004
104+
};
105+
typedef void(__stdcall* DeviceChangeCallback)(DBTEvents state);
106+
107+
extern DeviceChangeCallback g_deviceCallback;
108+
109+
DIRECTINPUTFORCEFEEDBACK_API void SetDeviceChangeCallback(DeviceChangeCallback CB);
110+
}
104111
}
105112

106113

Plugin/DLL.meta

Lines changed: 0 additions & 8 deletions
This file was deleted.
0 Bytes
Binary file not shown.

Plugin/DirectInputManager.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class Native
4747
}
4848
public class DIManager
4949
{
50+
// Define all callback delegates at class level with proper attributes
51+
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
52+
private delegate void DeviceChangeCallback(DBTEvents DBTEvent);
53+
54+
// Static delegate instances to prevent garbage collection
55+
private static DeviceChangeCallback s_deviceChangeCallback;
56+
5057
//////////////////////////////////////////////////////////////
5158
// Cross Platform "Macros" - Allows lib to work in Visual Studio & Unity
5259
//////////////////////////////////////////////////////////////
@@ -92,9 +99,18 @@ public class DIManager
9299
public static bool Initialize()
93100
{
94101
if (_isInitialized) { return _isInitialized; }
95-
if (Native.StartDirectInput() != 0) { return _isInitialized = false; }
96-
Native.SetDeviceChangeCallback(OnDeviceChange);
97-
return _isInitialized = true;
102+
try
103+
{
104+
if (Native.StartDirectInput() != 0) { return _isInitialized = false; }
105+
s_deviceChangeCallback = OnDeviceChange;
106+
Native.SetDeviceChangeCallback(OnDeviceChange);
107+
return _isInitialized = true;
108+
}
109+
catch (Exception ex)
110+
{
111+
DebugLog($"Failed to initialize DirectInput: {ex.Message}");
112+
return _isInitialized = false;
113+
}
98114
}
99115

100116
/// <summary>
@@ -438,6 +454,9 @@ public static bool GetADI(string guidInstance, out ActiveDeviceInfo ADI)
438454
/// Called from the DLL when a windows WM_DEVICECHANGE event is captured
439455
/// This function invokes the necessary events
440456
/// </summary>
457+
#if UNITY_STANDALONE_WIN
458+
[AOT.MonoPInvokeCallback(typeof(DeviceChangeCallback))]
459+
#endif
441460
private static void OnDeviceChange(DBTEvents DBTEvent)
442461
{
443462
//DebugLog($"DeviceChange {DBTEvent.ToString()}");

Plugin/DirectInputManager.cs.meta

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)