USB: Improve Force Feedback test so it doesn't block UI

This commit is contained in:
Silent 2021-03-20 15:11:54 +01:00 committed by jackun
parent 0af847bd29
commit 68d8840075
3 changed files with 76 additions and 23 deletions

View File

@ -53,6 +53,10 @@ namespace usb_pad
int32_t FFMULTI[2][1];
int32_t INVERTFORCES[2]{};
// FFB test
bool ffbTestRunning = false;
unsigned int ffbTestStage = 0;
bool dialogOpen = false;
HWND hKey;
@ -685,6 +689,14 @@ namespace usb_pad
EndPaint(hWnd, &Ps);
}
void EndFFBTest()
{
if (std::exchange(ffbTestRunning, false))
{
KillTimer(hWnd, 23);
}
}
INT_PTR CALLBACK StaticProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
(*pFnPrevFunc)(hDlg, uMsg, wParam, lParam);
@ -890,6 +902,16 @@ namespace usb_pad
ControlTest(s->port);
break;
}
case 23:
{
s = (DXDlgSettings*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
if (!UpdateTestForce(s->port, ffbTestStage++))
{
EndTestForce(s->port);
EndFFBTest();
}
break;
}
}
break;
}
@ -933,6 +955,7 @@ namespace usb_pad
//SendMessage(hWnd, WM_CLOSE, 0, 0);
//return TRUE;
dialogOpen = false;
EndFFBTest();
FreeDirectInput();
EndDialog(hWnd, TRUE);
return TRUE;
@ -943,6 +966,7 @@ namespace usb_pad
//Seems to create some dead locks
//SendMessage(hWnd, WM_CLOSE, 0, 0);
dialogOpen = false;
EndFFBTest();
FreeDirectInput();
EndDialog(hWnd, FALSE);
return TRUE;
@ -950,9 +974,20 @@ namespace usb_pad
break;
case IDC_BUTTON1:
{
//MessageBeep(MB_ICONEXCLAMATION);
ApplySettings(s->port);
TestForce(s->port);
if (!ffbTestRunning)
{
ApplySettings(s->port);
if (StartTestForce(s->port))
{
if (UpdateTestForce(s->port, 0))
{
// Start a timer to "tick" the FFB test every 500ms
ffbTestStage = 1;
SetTimer(hWnd, 23, 500, nullptr);
ffbTestRunning = true;
}
}
}
}
break;
@ -1179,6 +1214,7 @@ namespace usb_pad
case WM_CLOSE:
{
dialogOpen = false;
EndFFBTest();
FreeDirectInput();
EndDialog(hWnd, 0);
}

View File

@ -429,13 +429,13 @@ namespace usb_pad
}
}
void UpdateFFBSettings(int port, LPDIRECTINPUTDEVICE8 device)
bool UpdateFFBSettings(int port, LPDIRECTINPUTDEVICE8 device)
{
DIPROPDWORD prop { sizeof(prop), sizeof(prop.diph) };
prop.diph.dwObj = 0;
prop.diph.dwHow = DIPH_DEVICE;
prop.dwData = std::clamp(GAINZ[port][0], 0, DI_FFNOMINALMAX);
device->SetProperty(DIPROP_FFGAIN, &prop.diph);
return SUCCEEDED(device->SetProperty(DIPROP_FFGAIN, &prop.diph));
}
BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance,
@ -1019,7 +1019,7 @@ namespace usb_pad
return g_pEffectConstant[port]->SetParameters(&eff, DIEP_TYPESPECIFICPARAMS | DIEP_START);
}
void TestForce(int port)
bool StartTestForce(int port)
{
InputMapped im;
LPDIRECTINPUTDEVICE8 dev = nullptr;
@ -1027,23 +1027,36 @@ namespace usb_pad
dev = g_pJoysticks[im.index]->GetDevice();
// Gain value may have changed, so update it for the constant force effect
UpdateFFBSettings(port, dev);
return UpdateFFBSettings(port, dev);
}
if (FAILED(SetConstantForce(port, DI_FFNOMINALMAX / 3)))
return;
Sleep(500);
SetConstantForce(port, -DI_FFNOMINALMAX / 3);
Sleep(1000);
SetConstantForce(port, DI_FFNOMINALMAX / 3);
Sleep(500);
SetConstantForce(port, 0);
if (dev)
{ //FIXME actually center, maybe
AutoCenter(dev, true);
Sleep(1500);
AutoCenter(dev, false);
bool UpdateTestForce(int port, unsigned int stage)
{
// FFB test ticks every 500ms and goes as follows:
// Turn right, wait 500ms, turn left, wait 1000ms, turn right, wait 500ms, end
if (stage == 0)
{
return SUCCEEDED(SetConstantForce(port, DI_FFNOMINALMAX / 3));
}
if (stage == 1)
{
return SUCCEEDED(SetConstantForce(port, -DI_FFNOMINALMAX / 3));
}
if (stage == 2)
{
// Do nothing, as we wait 1000ms
return true;
}
if (stage == 3)
{
return SUCCEEDED(SetConstantForce(port, DI_FFNOMINALMAX / 3));
}
return false;
}
bool EndTestForce(int port)
{
return SUCCEEDED(SetConstantForce(port, 0));
}
} // namespace dx

View File

@ -204,13 +204,17 @@ namespace usb_pad
float ReadAxis(const InputMapped& im);
float ReadAxis(int port, int axisid);
float FilterControl(float input, LONG linear, LONG offset, LONG dead);
void TestForce(int port);
bool StartTestForce(int port);
bool UpdateTestForce(int port, unsigned int stage);
bool EndTestForce(int port);
LONG GetAxisValueFromOffset(int axis, const DIJOYSTATE2& j);
bool GetControl(int port, int id);
float GetAxisControl(int port, ControlID id);
void CreateFFB(int port, LPDIRECTINPUTDEVICE8 device, DWORD axis);
bool FindFFDevice(int port);
void UpdateFFBSettings(int port, LPDIRECTINPUTDEVICE8 device);
bool UpdateFFBSettings(int port, LPDIRECTINPUTDEVICE8 device);
void AddInputMap(int port, int cid, const InputMapped& im);
void RemoveInputMap(int port, int cid);