dinput: Only convert DIEFFECT directions to spherical when needed.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4289bae3b4
commit
bd6d258e33
|
@ -2017,6 +2017,127 @@ static BOOL get_parameters_object_ofs( struct hid_joystick *impl, struct hid_val
|
||||||
return DIENUM_STOP;
|
return DIENUM_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void convert_directions_to_spherical( const DIEFFECT *in, DIEFFECT *out )
|
||||||
|
{
|
||||||
|
DWORD i, direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL;
|
||||||
|
|
||||||
|
switch (in->dwFlags & direction_flags)
|
||||||
|
{
|
||||||
|
case DIEFF_CARTESIAN:
|
||||||
|
for (i = 1; i < in->cAxes; ++i)
|
||||||
|
out->rglDirection[i - 1] = atan2( in->rglDirection[i], in->rglDirection[0] );
|
||||||
|
out->rglDirection[in->cAxes - 1] = 0;
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
case DIEFF_POLAR:
|
||||||
|
out->rglDirection[0] = (in->rglDirection[0] % 36000) - 9000;
|
||||||
|
if (out->rglDirection[0] < 0) out->rglDirection[0] += 36000;
|
||||||
|
for (i = 1; i < in->cAxes; ++i) out->rglDirection[i] = 0;
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
case DIEFF_SPHERICAL:
|
||||||
|
for (i = 0; i < in->cAxes; ++i)
|
||||||
|
{
|
||||||
|
out->rglDirection[i] = in->rglDirection[i] % 36000;
|
||||||
|
if (out->rglDirection[i] < 0) out->rglDirection[i] += 36000;
|
||||||
|
}
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convert_directions_from_spherical( const DIEFFECT *in, DIEFFECT *out )
|
||||||
|
{
|
||||||
|
DWORD i, j, direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL;
|
||||||
|
LONG tmp;
|
||||||
|
|
||||||
|
switch (out->dwFlags & direction_flags)
|
||||||
|
{
|
||||||
|
case DIEFF_CARTESIAN:
|
||||||
|
out->rglDirection[0] = 10000;
|
||||||
|
for (i = 1; i <= in->cAxes; ++i)
|
||||||
|
{
|
||||||
|
tmp = cos( in->rglDirection[i - 1] * M_PI / 18000 ) * 10000;
|
||||||
|
for (j = 0; j < i; ++j)
|
||||||
|
out->rglDirection[j] = round( out->rglDirection[j] * tmp / 10000.0 );
|
||||||
|
out->rglDirection[i] = sin( in->rglDirection[i - 1] * M_PI / 18000 ) * 10000;
|
||||||
|
}
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
case DIEFF_POLAR:
|
||||||
|
out->rglDirection[0] = (in->rglDirection[0] + 9000) % 36000;
|
||||||
|
if (out->rglDirection[0] < 0) out->rglDirection[0] += 36000;
|
||||||
|
out->rglDirection[1] = 0;
|
||||||
|
out->cAxes = 2;
|
||||||
|
break;
|
||||||
|
case DIEFF_SPHERICAL:
|
||||||
|
for (i = 0; i < in->cAxes; ++i)
|
||||||
|
{
|
||||||
|
out->rglDirection[i] = in->rglDirection[i] % 36000;
|
||||||
|
if (out->rglDirection[i] < 0) out->rglDirection[i] += 36000;
|
||||||
|
}
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void convert_directions( const DIEFFECT *in, DIEFFECT *out )
|
||||||
|
{
|
||||||
|
DWORD direction_flags = DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL;
|
||||||
|
LONG directions[6] = {0};
|
||||||
|
DIEFFECT spherical = {.rglDirection = directions};
|
||||||
|
|
||||||
|
switch (in->dwFlags & direction_flags)
|
||||||
|
{
|
||||||
|
case DIEFF_CARTESIAN:
|
||||||
|
switch (out->dwFlags & direction_flags)
|
||||||
|
{
|
||||||
|
case DIEFF_CARTESIAN:
|
||||||
|
memcpy( out->rglDirection, in->rglDirection, in->cAxes * sizeof(LONG) );
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
case DIEFF_POLAR:
|
||||||
|
convert_directions_to_spherical( in, &spherical );
|
||||||
|
convert_directions_from_spherical( &spherical, out );
|
||||||
|
break;
|
||||||
|
case DIEFF_SPHERICAL:
|
||||||
|
convert_directions_to_spherical( in, out );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIEFF_POLAR:
|
||||||
|
switch (out->dwFlags & direction_flags)
|
||||||
|
{
|
||||||
|
case DIEFF_POLAR:
|
||||||
|
memcpy( out->rglDirection, in->rglDirection, in->cAxes * sizeof(LONG) );
|
||||||
|
out->cAxes = in->cAxes;
|
||||||
|
break;
|
||||||
|
case DIEFF_CARTESIAN:
|
||||||
|
convert_directions_to_spherical( in, &spherical );
|
||||||
|
convert_directions_from_spherical( &spherical, out );
|
||||||
|
break;
|
||||||
|
case DIEFF_SPHERICAL:
|
||||||
|
convert_directions_to_spherical( in, out );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIEFF_SPHERICAL:
|
||||||
|
switch (out->dwFlags & direction_flags)
|
||||||
|
{
|
||||||
|
case DIEFF_POLAR:
|
||||||
|
case DIEFF_CARTESIAN:
|
||||||
|
convert_directions_from_spherical( in, out );
|
||||||
|
break;
|
||||||
|
case DIEFF_SPHERICAL:
|
||||||
|
convert_directions_to_spherical( in, out );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags )
|
static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *iface, DIEFFECT *params, DWORD flags )
|
||||||
{
|
{
|
||||||
DIPROPHEADER filter =
|
DIPROPHEADER filter =
|
||||||
|
@ -2026,8 +2147,7 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa
|
||||||
.dwHow = DIPH_BYUSAGE,
|
.dwHow = DIPH_BYUSAGE,
|
||||||
};
|
};
|
||||||
struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
|
struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
|
||||||
ULONG i, j, count, capacity, object_flags, direction_flags;
|
ULONG i, count, capacity, object_flags, direction_flags;
|
||||||
LONG tmp, directions[6] = {0};
|
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
TRACE( "iface %p, params %p, flags %#x.\n", iface, params, flags );
|
TRACE( "iface %p, params %p, flags %#x.\n", iface, params, flags );
|
||||||
|
@ -2067,27 +2187,9 @@ static HRESULT WINAPI hid_joystick_effect_GetParameters( IDirectInputEffect *ifa
|
||||||
if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM;
|
if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM;
|
||||||
if (capacity < params->cAxes) return DIERR_MOREDATA;
|
if (capacity < params->cAxes) return DIERR_MOREDATA;
|
||||||
|
|
||||||
if (direction_flags & DIEFF_SPHERICAL)
|
|
||||||
memcpy( directions, impl->params.rglDirection, count * sizeof(LONG) );
|
|
||||||
else if (direction_flags & DIEFF_POLAR)
|
|
||||||
{
|
|
||||||
directions[0] = (impl->params.rglDirection[0] + 9000) % 36000;
|
|
||||||
if (directions[0] < 0) directions[0] += 36000;
|
|
||||||
}
|
|
||||||
else if (direction_flags & DIEFF_CARTESIAN)
|
|
||||||
{
|
|
||||||
directions[0] = 10000;
|
|
||||||
for (i = 1; i <= count; ++i)
|
|
||||||
{
|
|
||||||
tmp = cos( impl->params.rglDirection[i - 1] * M_PI / 18000 ) * 10000;
|
|
||||||
for (j = 0; j < i; ++j) directions[j] = round( directions[j] * tmp / 10000.0 );
|
|
||||||
directions[i] = sin( impl->params.rglDirection[i - 1] * M_PI / 18000 ) * 10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count) params->rglDirection = NULL;
|
if (!count) params->rglDirection = NULL;
|
||||||
else if (!params->rglDirection) return DIERR_INVALIDPARAM;
|
else if (!params->rglDirection) return DIERR_INVALIDPARAM;
|
||||||
else memcpy( params->rglDirection, directions, count * sizeof(LONG) );
|
else convert_directions( &impl->params, params );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DIEP_TYPESPECIFICPARAMS)
|
if (flags & DIEP_TYPESPECIFICPARAMS)
|
||||||
|
@ -2182,7 +2284,6 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa
|
||||||
};
|
};
|
||||||
struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
|
struct hid_joystick_effect *impl = impl_from_IDirectInputEffect( iface );
|
||||||
ULONG i, count, old_value, object_flags, direction_flags;
|
ULONG i, count, old_value, object_flags, direction_flags;
|
||||||
LONG directions[6] = {0};
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
|
@ -2226,31 +2327,11 @@ static HRESULT WINAPI hid_joystick_effect_SetParameters( IDirectInputEffect *ifa
|
||||||
if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM;
|
if ((direction_flags & DIEFF_POLAR) && count != 2) return DIERR_INVALIDPARAM;
|
||||||
if ((direction_flags & DIEFF_CARTESIAN) && params->cAxes != count) return DIERR_INVALIDPARAM;
|
if ((direction_flags & DIEFF_CARTESIAN) && params->cAxes != count) return DIERR_INVALIDPARAM;
|
||||||
|
|
||||||
if (!count) memset( directions, 0, sizeof(directions) );
|
impl->params.dwFlags &= ~(DIEFF_CARTESIAN | DIEFF_POLAR | DIEFF_SPHERICAL);
|
||||||
else if (direction_flags & DIEFF_POLAR)
|
impl->params.dwFlags |= direction_flags;
|
||||||
{
|
if (memcmp( impl->params.rglDirection, params->rglDirection, count * sizeof(LONG) ))
|
||||||
directions[0] = (params->rglDirection[0] % 36000) - 9000;
|
|
||||||
if (directions[0] < 0) directions[0] += 36000;
|
|
||||||
for (i = 1; i < count; ++i) directions[i] = 0;
|
|
||||||
}
|
|
||||||
else if (direction_flags & DIEFF_CARTESIAN)
|
|
||||||
{
|
|
||||||
for (i = 1; i < count; ++i)
|
|
||||||
directions[i - 1] = atan2( params->rglDirection[i], params->rglDirection[0] );
|
|
||||||
directions[count - 1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < count; ++i)
|
|
||||||
{
|
|
||||||
directions[i] = params->rglDirection[i] % 36000;
|
|
||||||
if (directions[i] < 0) directions[i] += 36000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp( impl->params.rglDirection, directions, count * sizeof(LONG) ))
|
|
||||||
impl->modified = TRUE;
|
impl->modified = TRUE;
|
||||||
memcpy( impl->params.rglDirection, directions, count * sizeof(LONG) );
|
memcpy( impl->params.rglDirection, params->rglDirection, count * sizeof(LONG) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DIEP_TYPESPECIFICPARAMS)
|
if (flags & DIEP_TYPESPECIFICPARAMS)
|
||||||
|
@ -2514,7 +2595,9 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface )
|
||||||
ULONG report_len = impl->joystick->caps.OutputReportByteLength;
|
ULONG report_len = impl->joystick->caps.OutputReportByteLength;
|
||||||
HANDLE device = impl->joystick->device;
|
HANDLE device = impl->joystick->device;
|
||||||
struct hid_value_caps *caps;
|
struct hid_value_caps *caps;
|
||||||
|
LONG directions[4] = {0};
|
||||||
DWORD i, tmp, count;
|
DWORD i, tmp, count;
|
||||||
|
DIEFFECT spherical;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
USAGE usage;
|
USAGE usage;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -2659,10 +2742,13 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface )
|
||||||
impl->joystick->preparsed, impl->effect_update_buf, report_len );
|
impl->joystick->preparsed, impl->effect_update_buf, report_len );
|
||||||
if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsages returned %#x\n", status );
|
if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsages returned %#x\n", status );
|
||||||
|
|
||||||
|
spherical.rglDirection = directions;
|
||||||
|
convert_directions_to_spherical( &impl->params, &spherical );
|
||||||
|
|
||||||
if (!effect_update->direction_count) WARN( "no PID effect direction caps found\n" );
|
if (!effect_update->direction_count) WARN( "no PID effect direction caps found\n" );
|
||||||
else for (i = 0; i < impl->params.cAxes - 1; ++i)
|
else for (i = 0; i < spherical.cAxes - 1; ++i)
|
||||||
{
|
{
|
||||||
tmp = impl->directions[i] + (i == 0 ? 9000 : 0);
|
tmp = directions[i] + (i == 0 ? 9000 : 0);
|
||||||
caps = effect_update->direction_caps[effect_update->direction_count - i - 1];
|
caps = effect_update->direction_caps[effect_update->direction_count - i - 1];
|
||||||
set_parameter_value( impl, impl->effect_update_buf, caps, tmp % 36000 );
|
set_parameter_value( impl, impl->effect_update_buf, caps, tmp % 36000 );
|
||||||
}
|
}
|
||||||
|
|
|
@ -6114,26 +6114,19 @@ static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWO
|
||||||
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
|
hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
|
||||||
ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
|
ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
|
||||||
ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes );
|
ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes );
|
||||||
todo_wine
|
|
||||||
ok( desc.rglDirection[0] == 1000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 1000 );
|
ok( desc.rglDirection[0] == 1000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 1000 );
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n",
|
ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n",
|
||||||
desc.rglDirection[1], 0xcdcdcdcd );
|
desc.rglDirection[1], 0xcdcdcdcd );
|
||||||
else
|
else
|
||||||
{
|
|
||||||
todo_wine
|
|
||||||
ok( desc.rglDirection[1] == 2000, "got rglDirection[1] %d expected %d\n",
|
ok( desc.rglDirection[1] == 2000, "got rglDirection[1] %d expected %d\n",
|
||||||
desc.rglDirection[1], 2000 );
|
desc.rglDirection[1], 2000 );
|
||||||
}
|
|
||||||
if (i <= 2)
|
if (i <= 2)
|
||||||
ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n",
|
ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n",
|
||||||
desc.rglDirection[2], 0xcdcdcdcd );
|
desc.rglDirection[2], 0xcdcdcdcd );
|
||||||
else
|
else
|
||||||
{
|
|
||||||
todo_wine
|
|
||||||
ok( desc.rglDirection[2] == 3000, "got rglDirection[2] %d expected %d\n",
|
ok( desc.rglDirection[2] == 3000, "got rglDirection[2] %d expected %d\n",
|
||||||
desc.rglDirection[2], 3000 );
|
desc.rglDirection[2], 3000 );
|
||||||
}
|
|
||||||
|
|
||||||
desc.dwFlags = DIEFF_POLAR;
|
desc.dwFlags = DIEFF_POLAR;
|
||||||
desc.cAxes = 1;
|
desc.cAxes = 1;
|
||||||
|
|
Loading…
Reference in New Issue