Created
July 13, 2012 19:21
-
-
Save lfzawacki/3106806 to your computer and use it in GitHub Desktop.
force feedback
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From bd9e9c08082419828098ee7b327448725d1455ca Mon Sep 17 00:00:00 2001 | |
From: Lucas Zawacki <lfzawacki@gmail.com> | |
Date: Wed, 11 Jul 2012 14:24:04 -0300 | |
Subject: joy.cpl: Correct joystick testing thread behavior (try 2) | |
The problem with the original behavior is that it starts a new thread each time the test tab is switched to, but | |
only stopped them on PSN_RESET. Now when the window receives PSN_KILLACTIVE (cancel button, X button or tab switch) or | |
PSN_RESET (ok button), the thread will rightfully die. | |
--- | |
dlls/joy.cpl/main.c | 4 +++- | |
1 file changed, 3 insertions(+), 1 deletion(-) | |
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c | |
index eb8f982..e9b3a72 100644 | |
--- a/dlls/joy.cpl/main.c | |
+++ b/dlls/joy.cpl/main.c | |
@@ -424,9 +424,11 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM | |
} | |
break; | |
- case PSN_RESET: | |
+ case PSN_RESET: /* intentional fall-through */ | |
+ case PSN_KILLACTIVE: | |
/* Stop input thread */ | |
data->stop = TRUE; | |
+ MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, 0); | |
CloseHandle(thread); | |
break; | |
} | |
-- | |
1.7.9.5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 11ce24ec3c54f1a84349b785ae6f69f679748415 Mon Sep 17 00:00:00 2001 | |
From: Lucas Zawacki <lfzawacki@gmail.com> | |
Date: Mon, 2 Jul 2012 20:11:13 -0300 | |
Subject: [PATCH 2/3] joy.cpl: Tab for force feedback tests (try 3) | |
* Minor corrections to the effect selection logic | |
* Using simple solution to stop threads | |
--- | |
dlls/joy.cpl/joy.h | 18 ++++ | |
dlls/joy.cpl/joy.rc | 4 + | |
dlls/joy.cpl/main.c | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++- | |
3 files changed, 282 insertions(+), 2 deletions(-) | |
diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h | |
index 07c13fa..13efe1b 100644 | |
--- a/dlls/joy.cpl/joy.h | |
+++ b/dlls/joy.cpl/joy.h | |
@@ -29,11 +29,22 @@ | |
extern HMODULE hcpl; | |
+struct Effect { | |
+ IDirectInputEffect *effect; | |
+ DIEFFECT params; | |
+ DIEFFECTINFOW info; | |
+}; | |
+ | |
struct Joystick { | |
IDirectInputDevice8W *device; | |
DIDEVICEINSTANCEW instance; | |
int num_buttons; | |
int num_axes; | |
+ BOOL forcefeedback; | |
+ int num_effects; | |
+ int cur_effect; | |
+ int chosen_effect; | |
+ struct Effect *effects; | |
}; | |
#define TEST_MAX_BUTTONS 32 | |
@@ -43,6 +54,7 @@ struct JoystickData { | |
IDirectInput8W *di; | |
struct Joystick *joysticks; | |
int num_joysticks; | |
+ int num_ff; | |
int cur_joystick; | |
int chosen_joystick; | |
HWND buttons[TEST_MAX_BUTTONS]; | |
@@ -76,6 +88,9 @@ struct JoystickData { | |
#define IDC_JOYSTICKBUTTON 3000 | |
#define IDC_JOYSTICKAXES 4000 | |
+#define IDC_FFSELECTCOMBO 2009 | |
+#define IDC_FFEFFECTLIST 2010 | |
+ | |
/* constants */ | |
#define TEST_POLL_TIME 100 | |
@@ -95,4 +110,7 @@ struct JoystickData { | |
#define TEST_AXIS_MIN -40 | |
#define TEST_AXIS_MAX 40 | |
+#define FF_PLAY_TIME 2*DI_SECONDS | |
+#define FF_PERIOD_TIME FF_PLAY_TIME/4 | |
+ | |
#endif | |
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc | |
index 22d9253..0eb4378 100644 | |
--- a/dlls/joy.cpl/joy.rc | |
+++ b/dlls/joy.cpl/joy.rc | |
@@ -59,6 +59,10 @@ STYLE WS_CAPTION | WS_CHILD | WS_DISABLED | |
CAPTION "Test Force Feedback" | |
FONT 8, "Ms Shell Dlg" | |
{ | |
+ COMBOBOX IDC_FFSELECTCOMBO, 5, 5, 100, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | |
+ LTEXT "Available Effects", IDC_STATIC, 10, 30, 100, 10 | |
+ LISTBOX IDC_FFEFFECTLIST, 10, 40, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY | |
+ LTEXT "Press any button in the controller to activate the chosen effect.", IDC_STATIC, 10, 110, 210, 25 | |
} | |
#define WINE_FILENAME_STR "joy.cpl" | |
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c | |
index e9b3a72..40a0f6f9 100644 | |
--- a/dlls/joy.cpl/main.c | |
+++ b/dlls/joy.cpl/main.c | |
@@ -88,6 +88,9 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont | |
joystick->num_buttons = caps.dwButtons; | |
joystick->num_axes = caps.dwAxes; | |
+ joystick->forcefeedback = caps.dwFlags & DIDC_FORCEFEEDBACK; | |
+ | |
+ if (joystick->forcefeedback) data->num_ff++; | |
return DIENUM_CONTINUE; | |
} | |
@@ -111,10 +114,19 @@ static void initialize_joysticks(struct JoystickData *data) | |
*/ | |
static void destroy_joysticks(struct JoystickData *data) | |
{ | |
- int i; | |
+ int i, j; | |
for (i = 0; i < data->num_joysticks; i++) | |
{ | |
+ | |
+ if (data->joysticks[i].forcefeedback) | |
+ { | |
+ for (j = 0; j < data->joysticks[i].num_effects; j++) | |
+ IDirectInputEffect_Release(data->joysticks[i].effects[j].effect); | |
+ | |
+ HeapFree(GetProcessHeap(), 0, data->joysticks[i].effects); | |
+ } | |
+ | |
IDirectInputDevice8_Unacquire(data->joysticks[i].device); | |
IDirectInputDevice8_Release(data->joysticks[i].device); | |
} | |
@@ -437,6 +449,252 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM | |
return FALSE; | |
} | |
+/********************************************************************* | |
+ * Joystick force feedback testing functions | |
+ * | |
+ */ | |
+ | |
+static void initialize_effects_list(HWND hwnd, struct Joystick* joy) | |
+{ | |
+ int i; | |
+ | |
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_RESETCONTENT, 0, 0); | |
+ | |
+ for (i=0; i < joy->num_effects; i++) | |
+ { | |
+ /* Effect names start with GUID_, so we'll skip this part */ | |
+ WCHAR *name = joy->effects[i].info.tszName + 5; | |
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_ADDSTRING, 0, (LPARAM) name); | |
+ } | |
+} | |
+ | |
+static void ff_handle_joychange(HWND hwnd, struct JoystickData *data) | |
+{ | |
+ int sel; | |
+ | |
+ if (data->num_ff == 0) return; | |
+ | |
+ sel = SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_GETCURSEL, 0, 0); | |
+ data->chosen_joystick = SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_GETITEMDATA, sel, 0); | |
+ initialize_effects_list(hwnd, &data->joysticks[data->chosen_joystick]); | |
+} | |
+ | |
+static void ff_handle_effectchange(HWND hwnd, struct Joystick *joy) | |
+{ | |
+ int sel = SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_GETCURSEL, 0, 0); | |
+ | |
+ if (sel < 0) return; | |
+ | |
+ joy->chosen_effect = sel; | |
+} | |
+ | |
+static DWORD WINAPI ff_input_thread(void *param) | |
+{ | |
+ struct JoystickData *data = param; | |
+ DIJOYSTATE state; | |
+ | |
+ ZeroMemory(&state, sizeof(state)); | |
+ | |
+ while (!data->stop) | |
+ { | |
+ int i; | |
+ struct Joystick *joy = &data->joysticks[data->chosen_joystick]; | |
+ int chosen_effect = joy->chosen_effect; | |
+ | |
+ /* Skip this if we have no effects */ | |
+ if (joy->num_effects == 0 || chosen_effect < 0) continue; | |
+ | |
+ poll_input(joy, &state); | |
+ | |
+ for (i=0; i < joy->num_buttons; i++) | |
+ if (state.rgbButtons[i]) | |
+ { | |
+ IDirectInputEffect_Start(joy->effects[chosen_effect].effect, 1, 0); | |
+ break; | |
+ } | |
+ | |
+ Sleep(TEST_POLL_TIME); | |
+ } | |
+ | |
+ return 0; | |
+} | |
+ | |
+/*********************************************************************** | |
+ * ff_effects_callback [internal] | |
+ * Enumerates, creates, sets the some parameters and stores all ff effects | |
+ * supported by the joystick. Works like enum_callback, counting the effects | |
+ * first and then storing them. | |
+ */ | |
+static BOOL CALLBACK ff_effects_callback(const DIEFFECTINFOW *pdei, void *pvRef) | |
+{ | |
+ HRESULT hr; | |
+ DIEFFECT dieffect; | |
+ DWORD axes[2] = {DIJOFS_X, DIJOFS_Y}; | |
+ int direction[2] = {0, 0}; | |
+ struct Joystick *joystick = pvRef; | |
+ | |
+ if (joystick->effects == NULL) | |
+ { | |
+ joystick->num_effects += 1; | |
+ return DIENUM_CONTINUE; | |
+ } | |
+ | |
+ hr = IDirectInputDevice8_Acquire(joystick->device); | |
+ | |
+ if (FAILED(hr)) return DIENUM_CONTINUE; | |
+ | |
+ ZeroMemory(&dieffect, sizeof(dieffect)); | |
+ | |
+ dieffect.dwSize = sizeof(dieffect); | |
+ dieffect.dwFlags = DIEFF_CARTESIAN; | |
+ dieffect.dwDuration = FF_PLAY_TIME; | |
+ | |
+ dieffect.cAxes = 2; | |
+ dieffect.rgdwAxes = axes; | |
+ dieffect.rglDirection = direction; | |
+ | |
+ if (IsEqualGUID(&pdei->guid, &GUID_RampForce)) | |
+ { | |
+ DIRAMPFORCE rforce; | |
+ | |
+ rforce.lStart = 0; | |
+ rforce.lEnd = DI_FFNOMINALMAX; | |
+ | |
+ dieffect.cbTypeSpecificParams = sizeof(rforce); | |
+ dieffect.lpvTypeSpecificParams = &rforce; | |
+ dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS; | |
+ } | |
+ else if (IsEqualGUID(&pdei->guid, &GUID_ConstantForce)) | |
+ { | |
+ DICONSTANTFORCE cforce; | |
+ | |
+ cforce.lMagnitude = DI_FFNOMINALMAX; | |
+ | |
+ dieffect.cbTypeSpecificParams = sizeof(cforce); | |
+ dieffect.lpvTypeSpecificParams = &cforce; | |
+ dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS; | |
+ } | |
+ else if (IsEqualGUID(&pdei->guid, &GUID_Sine) || | |
+ IsEqualGUID(&pdei->guid, &GUID_Square) || | |
+ IsEqualGUID(&pdei->guid, &GUID_Triangle) || | |
+ IsEqualGUID(&pdei->guid, &GUID_SawtoothUp) || | |
+ IsEqualGUID(&pdei->guid, &GUID_SawtoothDown)) | |
+ { | |
+ DIPERIODIC pforce; | |
+ | |
+ pforce.dwMagnitude = DI_FFNOMINALMAX; | |
+ pforce.lOffset = 0; | |
+ pforce.dwPhase = 0; | |
+ pforce.dwPeriod = FF_PERIOD_TIME; | |
+ | |
+ dieffect.cbTypeSpecificParams = sizeof(pforce); | |
+ dieffect.lpvTypeSpecificParams = &pforce; | |
+ dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS; | |
+ } | |
+ | |
+ hr = IDirectInputDevice2_CreateEffect( | |
+ joystick->device, &pdei->guid, &dieffect, &joystick->effects[joystick->cur_effect].effect, NULL); | |
+ | |
+ joystick->effects[joystick->cur_effect].params = dieffect; | |
+ joystick->effects[joystick->cur_effect].info = *pdei; | |
+ joystick->cur_effect += 1; | |
+ | |
+ return DIENUM_CONTINUE; | |
+} | |
+ | |
+/********************************************************************* | |
+ * ff_dlgproc [internal] | |
+ * | |
+ */ | |
+static INT_PTR CALLBACK ff_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) | |
+{ | |
+ static HANDLE thread; | |
+ static struct JoystickData *data; | |
+ TRACE("(%p, 0x%08x/%d, 0x%lx)\n", hwnd, msg, msg, lparam); | |
+ | |
+ switch (msg) | |
+ { | |
+ case WM_INITDIALOG: | |
+ { | |
+ int i, cur = 0; | |
+ | |
+ data = (struct JoystickData*) ((PROPSHEETPAGEW*)lparam)->lParam; | |
+ | |
+ /* Add joysticks with FF support to the combobox and get the effects */ | |
+ for (i = 0; i < data->num_joysticks; i++) | |
+ { | |
+ struct Joystick *joy = &data->joysticks[i]; | |
+ | |
+ if (joy->forcefeedback) | |
+ { | |
+ SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName); | |
+ SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_SETITEMDATA, cur, i); | |
+ | |
+ cur++; | |
+ | |
+ /* Count device effects and then store them */ | |
+ joy->num_effects = 0; | |
+ joy->effects = NULL; | |
+ IDirectInputDevice8_EnumEffects(joy->device, ff_effects_callback, (void *) joy, 0); | |
+ joy->effects = HeapAlloc(GetProcessHeap(), 0, sizeof(struct Effect) * joy->num_effects); | |
+ | |
+ joy->cur_effect = 0; | |
+ IDirectInputDevice8_EnumEffects(joy->device, ff_effects_callback, (void*) joy, 0); | |
+ } | |
+ } | |
+ | |
+ return TRUE; | |
+ } | |
+ | |
+ case WM_COMMAND: | |
+ switch(wparam) | |
+ { | |
+ case MAKEWPARAM(IDC_FFSELECTCOMBO, CBN_SELCHANGE): | |
+ ff_handle_joychange(hwnd, data); | |
+ | |
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_SETCURSEL, 0, 0); | |
+ ff_handle_effectchange(hwnd, &data->joysticks[data->chosen_joystick]); | |
+ break; | |
+ | |
+ case MAKEWPARAM(IDC_FFEFFECTLIST, LBN_SELCHANGE): | |
+ ff_handle_effectchange(hwnd, &data->joysticks[data->chosen_joystick]); | |
+ break; | |
+ } | |
+ return TRUE; | |
+ | |
+ case WM_NOTIFY: | |
+ switch(((LPNMHDR)lparam)->code) | |
+ { | |
+ case PSN_SETACTIVE: | |
+ if (data->num_ff > 0) | |
+ { | |
+ DWORD tid; | |
+ | |
+ data->stop = FALSE; | |
+ /* Set the first joystick as default */ | |
+ SendDlgItemMessageW(hwnd, IDC_FFSELECTCOMBO, CB_SETCURSEL, 0, 0); | |
+ ff_handle_joychange(hwnd, data); | |
+ | |
+ SendDlgItemMessageW(hwnd, IDC_FFEFFECTLIST, LB_SETCURSEL, 0, 0); | |
+ ff_handle_effectchange(hwnd, &data->joysticks[data->chosen_joystick]); | |
+ | |
+ thread = CreateThread(NULL, 0, ff_input_thread, (void*) data, 0, &tid); | |
+ } | |
+ break; | |
+ | |
+ case PSN_RESET: /* intentional fall-through */ | |
+ case PSN_KILLACTIVE: | |
+ /* Stop ff thread */ | |
+ data->stop = TRUE; | |
+ MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, 0); | |
+ CloseHandle(thread); | |
+ break; | |
+ } | |
+ return TRUE; | |
+ } | |
+ return FALSE; | |
+} | |
+ | |
/****************************************************************************** | |
* propsheet_callback [internal] | |
*/ | |
@@ -491,7 +749,7 @@ static void display_cpl_sheets(HWND parent, struct JoystickData *data) | |
psp[id].dwSize = sizeof (PROPSHEETPAGEW); | |
psp[id].hInstance = hcpl; | |
psp[id].u.pszTemplate = MAKEINTRESOURCEW(IDD_FORCEFEEDBACK); | |
- psp[id].pfnDlgProc = NULL; | |
+ psp[id].pfnDlgProc = ff_dlgproc; | |
psp[id].lParam = (INT_PTR) data; | |
id++; | |
-- | |
1.7.9.5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 84088df48a88dbe95a1a1e0195cd542025accc60 Mon Sep 17 00:00:00 2001 | |
From: Lucas Zawacki <lfzawacki@gmail.com> | |
Date: Mon, 2 Jul 2012 21:19:29 -0300 | |
Subject: [PATCH 3/3] joy.cpl: Added force feedback direction control (try 2) | |
--- | |
dlls/joy.cpl/joy.h | 7 +++++++ | |
dlls/joy.cpl/joy.rc | 5 ++++- | |
dlls/joy.cpl/main.c | 51 +++++++++++++++++++++++++++++++++++---------------- | |
3 files changed, 46 insertions(+), 17 deletions(-) | |
diff --git a/dlls/joy.cpl/joy.h b/dlls/joy.cpl/joy.h | |
index 13efe1b..e40a71b 100644 | |
--- a/dlls/joy.cpl/joy.h | |
+++ b/dlls/joy.cpl/joy.h | |
@@ -59,6 +59,7 @@ struct JoystickData { | |
int chosen_joystick; | |
HWND buttons[TEST_MAX_BUTTONS]; | |
HWND axes[TEST_MAX_AXES]; | |
+ HWND ff_axis; | |
BOOL stop; | |
}; | |
@@ -90,6 +91,7 @@ struct JoystickData { | |
#define IDC_FFSELECTCOMBO 2009 | |
#define IDC_FFEFFECTLIST 2010 | |
+#define IDC_FFAXIS 2011 | |
/* constants */ | |
#define TEST_POLL_TIME 100 | |
@@ -110,6 +112,11 @@ struct JoystickData { | |
#define TEST_AXIS_MIN -40 | |
#define TEST_AXIS_MAX 40 | |
+#define FF_AXIS_X 373 | |
+#define FF_AXIS_Y 98 | |
+#define FF_AXIS_SIZE_X 5 | |
+#define FF_AXIS_SIZE_Y 5 | |
+ | |
#define FF_PLAY_TIME 2*DI_SECONDS | |
#define FF_PERIOD_TIME FF_PLAY_TIME/4 | |
diff --git a/dlls/joy.cpl/joy.rc b/dlls/joy.cpl/joy.rc | |
index 0eb4378..1bfcfee 100644 | |
--- a/dlls/joy.cpl/joy.rc | |
+++ b/dlls/joy.cpl/joy.rc | |
@@ -62,7 +62,10 @@ FONT 8, "Ms Shell Dlg" | |
COMBOBOX IDC_FFSELECTCOMBO, 5, 5, 100, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS | |
LTEXT "Available Effects", IDC_STATIC, 10, 30, 100, 10 | |
LISTBOX IDC_FFEFFECTLIST, 10, 40, 180, 70, WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY | |
- LTEXT "Press any button in the controller to activate the chosen effect.", IDC_STATIC, 10, 110, 210, 25 | |
+ LTEXT "Press any button in the controller to activate the chosen effect." \ | |
+ "The effect direction can be changed with the controller axis.", \ | |
+ IDC_STATIC, 10, 110, 210, 25 | |
+ GROUPBOX "Direction", IDC_STATIC, 220, 30, 60, 60 | |
} | |
#define WINE_FILENAME_STR "joy.cpl" | |
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c | |
index 40a0f6f9..8e29612 100644 | |
--- a/dlls/joy.cpl/main.c | |
+++ b/dlls/joy.cpl/main.c | |
@@ -67,6 +67,7 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont | |
{ | |
struct JoystickData *data = context; | |
struct Joystick *joystick; | |
+ DIPROPRANGE proprange; | |
DIDEVCAPS caps; | |
if (data->joysticks == NULL) | |
@@ -92,6 +93,16 @@ static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *cont | |
if (joystick->forcefeedback) data->num_ff++; | |
+ /* Set axis range to ease the GUI visualization */ | |
+ proprange.diph.dwSize = sizeof(DIPROPRANGE); | |
+ proprange.diph.dwHeaderSize = sizeof(DIPROPHEADER); | |
+ proprange.diph.dwHow = DIPH_DEVICE; | |
+ proprange.diph.dwObj = 0; | |
+ proprange.lMin = TEST_AXIS_MIN; | |
+ proprange.lMax = TEST_AXIS_MAX; | |
+ | |
+ IDirectInputDevice_SetProperty(joystick->device, DIPROP_RANGE, &proprange.diph); | |
+ | |
return DIENUM_CONTINUE; | |
} | |
@@ -340,8 +351,6 @@ static void draw_joystick_buttons(HWND hwnd, struct JoystickData* data) | |
static void draw_joystick_axes(HWND hwnd, struct JoystickData* data) | |
{ | |
int i; | |
- struct Joystick *joy; | |
- DIPROPRANGE propRange; | |
HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE); | |
static const WCHAR button_class[] = {'B','u','t','t','o','n','\0'}; | |
static const WCHAR axes_names[TEST_MAX_AXES][7] = { {'X',',','Y','\0'}, {'R','x',',','R','y','\0'}, | |
@@ -349,20 +358,6 @@ static void draw_joystick_axes(HWND hwnd, struct JoystickData* data) | |
static const DWORD axes_idc[TEST_MAX_AXES] = { IDC_TESTGROUPXY, IDC_TESTGROUPRXRY, | |
IDC_TESTGROUPZRZ, IDC_TESTGROUPPOV }; | |
- /* Set axis range to ease the GUI visualization */ | |
- for (i = 0; i < data->num_joysticks; i++) | |
- { | |
- joy = &data->joysticks[i]; | |
- propRange.diph.dwSize = sizeof(DIPROPRANGE); | |
- propRange.diph.dwHeaderSize = sizeof(DIPROPHEADER); | |
- propRange.diph.dwHow = DIPH_DEVICE; | |
- propRange.diph.dwObj = 0; | |
- propRange.lMin = TEST_AXIS_MIN; | |
- propRange.lMax = TEST_AXIS_MAX; | |
- | |
- IDirectInputDevice_SetProperty(joy->device, DIPROP_RANGE, &propRange.diph); | |
- } | |
- | |
for (i = 0; i < TEST_MAX_AXES; i++) | |
{ | |
/* Set axis box name */ | |
@@ -453,6 +448,17 @@ static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM | |
* Joystick force feedback testing functions | |
* | |
*/ | |
+static void draw_ff_axis(HWND hwnd, struct JoystickData *data) | |
+{ | |
+ HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE); | |
+ static WCHAR button_class[] = {'B','u','t','t','o','n','\0'}; | |
+ | |
+ /* Draw direction axis */ | |
+ data->ff_axis = CreateWindowW( button_class, NULL, WS_CHILD | WS_VISIBLE, | |
+ FF_AXIS_X, FF_AXIS_Y, | |
+ FF_AXIS_SIZE_X, FF_AXIS_SIZE_Y, | |
+ hwnd, (HMENU) IDC_FFAXIS, NULL, hinst); | |
+} | |
static void initialize_effects_list(HWND hwnd, struct Joystick* joy) | |
{ | |
@@ -500,15 +506,26 @@ static DWORD WINAPI ff_input_thread(void *param) | |
int i; | |
struct Joystick *joy = &data->joysticks[data->chosen_joystick]; | |
int chosen_effect = joy->chosen_effect; | |
+ DIEFFECT *dieffect; | |
+ DWORD flags = DIEP_AXES | DIEP_DIRECTION | DIEP_NORESTART; | |
/* Skip this if we have no effects */ | |
if (joy->num_effects == 0 || chosen_effect < 0) continue; | |
poll_input(joy, &state); | |
+ /* Set ff parameters and draw the axis */ | |
+ dieffect = &joy->effects[chosen_effect].params; | |
+ dieffect->rgdwAxes[0] = state.lX; | |
+ dieffect->rgdwAxes[1] = state.lY; | |
+ | |
+ SetWindowPos(data->ff_axis, 0, FF_AXIS_X + state.lX, FF_AXIS_Y + state.lY, | |
+ 0, 0, SWP_NOZORDER | SWP_NOSIZE); | |
+ | |
for (i=0; i < joy->num_buttons; i++) | |
if (state.rgbButtons[i]) | |
{ | |
+ IDirectInputEffect_SetParameters(joy->effects[chosen_effect].effect, dieffect, flags); | |
IDirectInputEffect_Start(joy->effects[chosen_effect].effect, 1, 0); | |
break; | |
} | |
@@ -643,6 +660,8 @@ static INT_PTR CALLBACK ff_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp | |
} | |
} | |
+ draw_ff_axis(hwnd, data); | |
+ | |
return TRUE; | |
} | |
-- | |
1.7.9.5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment