JoyShockLibrary
JoyShockLibrary copied to clipboard
[Feature suggestion] Sample with motion
Hello, it would be great to have a simple, reference sample showcasing how to correctly work with the library. It would be nice if the sample also included mouse moving and rotation (on 3.0 can't get stable yaw, pitch, roll axes - one axis smoothly transitions to another, probably I'm doing something wrong, on 2.2.0 I got it right).
Such a sample could greatly help beginner developers easily understand and incorporate these features into their projects.
Additionally, the sample could serve as a kind of test for the library, checking its basic functions.
Thank you for your library and work.
Hi @r57zone! I'd love to add a reference sample. I can't really work on it at the moment without getting permission from my employer, but for now, hopefully this code snippet is helpful.
This code is from this sample that I created while developing v3.0 (using Dear ImGui), but didn't have time to polish it enough to include:
This sample is just what need, thanks 👍
I simplified the example a bit, maybe it will be useful to someone.
#include "JoyShockLibrary.h"
#include <windows.h>
// Settings
int _gyroSpace = 2;
float _sensitivity = 0.5f;
float _tightening = 2.f;
int _defaultCalibrationMode = 1;
// Callback for applying settings to new connections
void ConnectCallback(int deviceId)
{
JslSetGyroSpace(deviceId, _gyroSpace);
if (_defaultCalibrationMode > 0)
{
JslSetAutomaticCalibration(deviceId, true);
}
}
void MoveMouse(float x, float y)
{
static float accumulatedX = 0.f;
static float accumulatedY = 0.f;
accumulatedX += x;
accumulatedY += y;
int applicableX = (int)accumulatedX;
int applicableY = (int)accumulatedY;
accumulatedX -= applicableX;
accumulatedY -= applicableY;
INPUT input = { 0 };
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.time = 0;
input.mi.dx = applicableX;
input.mi.dy = applicableY;
input.mi.dwFlags = MOUSEEVENTF_MOVE;
SendInput(1, &input, sizeof(input));
}
void CalculateYawPitchRoll(float quatW, float quatX, float quatY, float quatZ, float& yaw, float& pitch, float& roll)
{
yaw = atan2f(2.0f * (quatW * quatZ + quatX * quatY), 1.0f - 2.0f * (quatY * quatY + quatZ * quatZ));
pitch = asinf(2.0f * (quatW * quatY - quatZ * quatX));
roll = atan2f(2.0f * (quatW * quatX + quatY * quatZ), 1.0f - 2.0f * (quatX * quatX + quatY * quatY));
}
void HandleDeviceConnections()
{
int deviceHandles[16];
int numConnectedDevices = JslGetConnectedDeviceHandles(deviceHandles, 16);
if (numConnectedDevices > 0)
{
for (int deviceIndex = 0; deviceIndex < numConnectedDevices; ++deviceIndex)
{
const int deviceHandle = deviceHandles[deviceIndex];
float velocityX, velocityY, velocityZ;
JslGetAndFlushAccumulatedGyro(deviceHandle, velocityX, velocityY, velocityZ);
float frameTime = 1.f / 60.f;
const float inputSize = sqrtf(velocityX * velocityX + velocityY * velocityY + velocityZ * velocityZ);
float tightenedSensitivity = _sensitivity * 50.f;
if (inputSize < _tightening && _tightening > 0)
{
tightenedSensitivity *= inputSize / _tightening;
}
MoveMouse(-velocityY * tightenedSensitivity * frameTime, -velocityX * tightenedSensitivity * frameTime);
MOTION_STATE motionState = JslGetMotionState(deviceHandle);
float yaw, pitch, roll;
CalculateYawPitchRoll(motionState.quatW, motionState.quatX, motionState.quatY, motionState.quatZ, yaw, pitch, roll);
//std::cout << "Device " << deviceIndex << " connected." << std::endl;
//std::cout << "Gravity = (" << motionState.gravX << ", " << motionState.gravY << ", " << motionState.gravZ << ")" << std::endl;
//std::cout << "Acceleration = (" << motionState.accelX << ", " << motionState.accelY << ", " << motionState.accelZ << ")" << std::endl;
//std::cout << "Yaw = " << yaw << ", Pitch = " << pitch << ", Roll = " << roll << std::endl; //
std::cout << "Devices connected: " << deviceIndex << std::endl;
}
}
else
{
std::cout << "Not devices." << std::endl;
}
}
int main()
{
SetConsoleTitle("JoyShock Library Sample");
JslSetConnectCallback(ConnectCallback);
JslConnectDevices();
while (true)
{
HandleDeviceConnections();
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
break;
Sleep(1);
}
return 0;
}```