SL-5894 #3 WIP enumerate devices to flaoter, let floater set device

temp
meow-7.2.2
Andrey Kleshchev 2020-07-10 20:48:43 +03:00
parent 0fbe4cf62a
commit 54383cac8f
8 changed files with 225 additions and 66 deletions

View File

@ -1380,18 +1380,34 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
LLScrollListItem* item = *iter;
if (item->getEnabled() && (item->getValue().asString() == value.asString()))
if (item->getEnabled())
{
if (selected)
{
selectItem(item);
}
else
{
deselectItem(item);
}
found = TRUE;
break;
if (value.isBinary())
{
if (item->getValue().isBinary())
{
LLSD::Binary data1 = value.asBinary();
LLSD::Binary data2 = item->getValue().asBinary();
found = std::equal(data1.begin(), data1.end(), data2.begin()) ? TRUE : FALSE;
}
}
else
{
found = item->getValue().asString() == value.asString() ? TRUE : FALSE;
}
if (found)
{
if (selected)
{
selectItem(item);
}
else
{
deselectItem(item);
}
break;
}
}
}

View File

@ -171,7 +171,7 @@ public:
// windows only DirectInput8 for joysticks
virtual void* getDirectInput8() { return NULL; };
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback) { return false; };
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; };
protected:
LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
virtual ~LLWindow();

View File

@ -4181,7 +4181,7 @@ void* LLWindowWin32::getDirectInput8()
return &gDirectInput8;
}
bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback)
bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata)
{
if (gDirectInput8 != NULL)
{
@ -4189,7 +4189,7 @@ bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_c
HRESULT status = gDirectInput8->EnumDevices(
(DWORD) device_type_filter, // DWORD dwDevType,
(LPDIENUMDEVICESCALLBACK)di8_devices_callback, // LPDIENUMDEVICESCALLBACK lpCallback, // BOOL DIEnumDevicesCallback( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) // BOOL CALLBACK DinputDevice::DevicesCallback
(LPVOID*)gDirectInput8, // LPVOID pvRef
(LPVOID*)userdata, // LPVOID pvRef
DIEDFL_ATTACHEDONLY // DWORD dwFlags
);

View File

@ -118,7 +118,7 @@ public:
static void setDPIAwareness();
/*virtual*/ void* getDirectInput8();
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback);
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,

View File

@ -40,9 +40,21 @@
#include "llviewercontrol.h"
#include "llappviewer.h"
#include "llviewerjoystick.h"
#include "llviewerwindow.h"
#include "llwindow.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#if LL_WINDOWS && !LL_MESA_HEADLESS
// Require DirectInput version 8
#define DIRECTINPUT_VERSION 0x0800
//#include <InitGuid.h>
//#pragma comment(lib, "dinput8")
//#pragma comment(lib, "dxguid.lib")
#include <dinput.h>
#endif
static LLTrace::SampleStatHandle<> sJoystickAxis0("Joystick axis 0"),
sJoystickAxis1("Joystick axis 1"),
sJoystickAxis2("Joystick axis 2"),
@ -59,6 +71,29 @@ static LLTrace::SampleStatHandle<>* sJoystickAxes[6] =
&sJoystickAxis5
};
#if LL_WINDOWS && !LL_MESA_HEADLESS
BOOL CALLBACK di8_list_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVOID pvRef)
{
// Note: If a single device can function as more than one DirectInput
// device type, it is enumerated as each device type that it supports.
// Capable of detecting devices like Oculus Rift
if (device_instance_ptr && pvRef)
{
std::string product_name = utf16str_to_utf8str(llutf16string(device_instance_ptr->tszProductName));
S32 size = sizeof(GUID);
LLSD::Binary data; //just an std::vector
data.resize(size);
memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size);
LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef;
floater->addDevice(product_name, LLSD(data));
}
return DIENUM_CONTINUE;
}
#endif
LLFloaterJoystick::LLFloaterJoystick(const LLSD& data)
: LLFloater(data),
mHasDeviceList(false)
@ -216,25 +251,62 @@ void LLFloaterJoystick::refresh()
initFromSettings();
}
void LLFloaterJoystick::addDevice(std::string &name, LLSD& value)
{
mJoysticksCombo->add(name, value, ADD_BOTTOM, 1);
}
void LLFloaterJoystick::refreshListOfDevices()
{
mJoysticksCombo->removeall();
mJoysticksCombo->add(getString("JoystickDisabled"), LLSD(LLSD::Integer(0)), ADD_BOTTOM, 1);
std::string no_device = getString("JoystickDisabled");
addDevice(no_device, LLSD(LLSD::Integer(0)));
mHasDeviceList = false;
std::string desc = LLViewerJoystick::getInstance()->getDescription();
if (!desc.empty())
// di8_devices_callback callback is immediate and happens in scope of getInputDevices()
#if LL_WINDOWS && !LL_MESA_HEADLESS
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
U32 device_type = DI8DEVCLASS_GAMECTRL;
void* callback = &di8_list_devices_callback;
#elif
// MAC doesn't support device search yet
// On MAC there is an ndof_idsearch and it is possible to specify product
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
U32 device_type = 0;
void* callback = NULL;
#endif
if (gViewerWindow->getWindow()->getInputDevices(device_type, callback, this))
{
mJoysticksCombo->add(desc, LLSD(LLSD::Integer(1)), ADD_BOTTOM, 1);
mHasDeviceList = true;
}
//todo: load list of devices
LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID();
if (LLViewerJoystick::getInstance()->isJoystickInitialized() &&
(!mHasDeviceList || !guid.isBinary()))
{
#if LL_WINDOWS && !LL_MESA_HEADLESS
LL_WARNS() << "NDOF connected to device without using SL provided handle" << LL_ENDL;
#endif
std::string desc = LLViewerJoystick::getInstance()->getDescription();
if (!desc.empty())
{
addDevice(desc, LLSD(LLSD::Integer(1)));
mHasDeviceList = true;
}
}
if (gSavedSettings.getBOOL("JoystickEnabled") && mHasDeviceList)
{
// todo: select device according to data from LLViewerJoystick
mJoysticksCombo->selectByValue(LLSD::Integer(1));
if (guid.isBinary())
{
mJoysticksCombo->selectByValue(guid);
}
else
{
mJoysticksCombo->selectByValue(LLSD::Integer(1));
}
}
else
{
@ -324,6 +396,7 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel)
}
else
{
LLViewerJoystick::getInstance()->initDevice(value);
// else joystick is enabled, because combobox holds id of device
joystick_enabled = true;
// todo: make LLViewerJoystick select a device based on value

View File

@ -46,6 +46,8 @@ public:
virtual void draw();
static void setSNDefaults();
void addDevice(std::string &name, LLSD& value);
protected:
void refreshListOfDevices();

View File

@ -164,56 +164,66 @@ BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVO
// Note: If a single device can function as more than one DirectInput
// device type, it is enumerated as each device type that it supports.
// Capable of detecting devices like Oculus Rift
if (device_instance_ptr && pvRef)
if (device_instance_ptr)
{
std::string product_name = utf16str_to_utf8str(llutf16string(device_instance_ptr->tszProductName));
LL_DEBUGS("Joystick") << "DirectInput8 Devices: " << product_name << LL_ENDL;
LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID();
U16 product_id = (device_instance_ptr->guidProduct.Data1 >> 16) & 0xFFFF;
U16 vendor_id = (device_instance_ptr->guidProduct.Data1 >> 0) & 0xFFFF;
if (!LLViewerJoystick::getInstance()->isJoystickInitialized())
bool init_device = false;
if (guid.isBinary())
{
bool found_space_mouse = is_space_mouse(product_id, vendor_id);
std::vector<U8> bin_bucket = guid.asBinary();
init_device = memcmp(&bin_bucket[0], &device_instance_ptr->guidInstance, sizeof(GUID)) == 0;
}
else
{
// It might be better to init space navigator here, but if system doesn't has one,
// ndof will pick a random device, it is simpler to pick device now
init_device = true;
}
if (found_space_mouse)
if (init_device)
{
LL_DEBUGS("Joystick") << "Found and attempting to use device: " << product_name << LL_ENDL;
LPDIRECTINPUT8 di8_interface = *((LPDIRECTINPUT8 *)gViewerWindow->getWindow()->getDirectInput8());
LPDIRECTINPUTDEVICE8 device = NULL;
HRESULT status = di8_interface->CreateDevice(
device_instance_ptr->guidInstance, // REFGUID rguid,
&device, // LPDIRECTINPUTDEVICE * lplpDirectInputDevice,
NULL // LPUNKNOWN pUnkOuter
);
if (status == DI_OK)
{
LL_DEBUGS("Joystick") << "Found device that matches criteria: " << product_name << LL_ENDL;
LPDIRECTINPUT8 di8_interface = (LPDIRECTINPUT8)pvRef;
LPDIRECTINPUTDEVICE8 device = NULL;
HRESULT status = di8_interface->CreateDevice(
device_instance_ptr->guidInstance, // REFGUID rguid,
&device, // LPDIRECTINPUTDEVICE * lplpDirectInputDevice,
NULL // LPUNKNOWN pUnkOuter
);
if (status == DI_OK)
{
// prerequisite for aquire()
LL_DEBUGS("Joystick") << "Device created" << LL_ENDL;
status = device->SetDataFormat(&c_dfDIJoystick); // c_dfDIJoystick2
}
if (status == DI_OK)
{
// set properties
LL_DEBUGS("Joystick") << "Format set" << LL_ENDL;
status = device->EnumObjects(EnumNDOFObjectsCallback, &device, DIDFT_ALL);
}
// todo: record device name, ndof won't fill it from passed device
// strncpy(mNdofDev->product, inst->tszProductName, sizeof(mNdofDev->product));
// strncpy(mNdofDev->product, product_name.c_str(), sizeof(mNdofDev->product));
if (status == DI_OK)
{
LL_DEBUGS("Joystick") << "Properties updated" << LL_ENDL;
LLViewerJoystick::getInstance()->initDevice(&device);
return DIENUM_STOP;
}
// prerequisite for aquire()
LL_DEBUGS("Joystick") << "Device created" << LL_ENDL;
status = device->SetDataFormat(&c_dfDIJoystick); // c_dfDIJoystick2
}
if (status == DI_OK)
{
// set properties
LL_DEBUGS("Joystick") << "Format set" << LL_ENDL;
status = device->EnumObjects(EnumNDOFObjectsCallback, &device, DIDFT_ALL);
}
if (status == DI_OK)
{
LL_DEBUGS("Joystick") << "Properties updated" << LL_ENDL;
S32 size = sizeof(GUID);
LLSD::Binary data; //just an std::vector
data.resize(size);
memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size);
LLViewerJoystick::getInstance()->initDevice(&device, product_name, LLSD(data));
return DIENUM_STOP;
}
}
else
{
LL_DEBUGS("Joystick") << "Found device: " << product_name << LL_ENDL;
}
}
return DIENUM_CONTINUE;
@ -310,6 +320,8 @@ LLViewerJoystick::LLViewerJoystick()
// factor in bandwidth? bandwidth = gViewerStats->mKBitStat
mPerfScale = 4000.f / gSysCPU.getMHz(); // hmm. why?
mLastDeviceUUID = LLSD::Integer(1);
}
// -----------------------------------------------------------------------------
@ -327,6 +339,7 @@ void LLViewerJoystick::init(bool autoenable)
#if LIB_NDOF
static bool libinit = false;
mDriverState = JDS_INITIALIZING;
//todo: load mLastDeviceUUID from settings
if (libinit == false)
{
@ -363,10 +376,11 @@ void LLViewerJoystick::init(bool autoenable)
U32 device_type = 0;
void* callback = NULL;
#endif
if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback))
if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL))
{
LL_INFOS() << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL;
// Failed to gather devices from windows, init first suitable one
mLastDeviceUUID = LLSD::Integer(1);
void *preffered_device = NULL;
initDevice(preffered_device);
}
@ -375,6 +389,7 @@ void LLViewerJoystick::init(bool autoenable)
if (mDriverState == JDS_INITIALIZING)
{
LL_INFOS() << "Found no suitable devices. Trying ndof's default init" << LL_ENDL;
mLastDeviceUUID = LLSD::Integer(1);
void *preffered_device = NULL;
initDevice(preffered_device);
}
@ -421,6 +436,47 @@ void LLViewerJoystick::init(bool autoenable)
#endif
}
void LLViewerJoystick::initDevice(LLSD &guid)
{
#if LIB_NDOF
mLastDeviceUUID = guid;
// todo: should we Unacquire old one?
#if LL_WINDOWS && !LL_MESA_HEADLESS
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
U32 device_type = DI8DEVCLASS_GAMECTRL;
void* callback = &di8_devices_callback;
#elif
// MAC doesn't support device search yet
// On MAC there is an ndof_idsearch and it is possible to specify product
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
U32 device_type = 0;
void* callback = NULL;
#endif
if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL))
{
LL_INFOS() << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL;
// Failed to gather devices from windows, init first suitable one
void *preffered_device = NULL;
mLastDeviceUUID = LLSD::Integer(1);
initDevice(preffered_device);
}
#endif
}
void LLViewerJoystick::initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid)
{
#if LIB_NDOF
mLastDeviceUUID = guid;
strncpy(mNdofDev->product, name.c_str(), sizeof(mNdofDev->product));
mNdofDev->manufacturer[0] = '\0';
initDevice(preffered_device);
#endif
}
void LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE8* */)
{
#if LIB_NDOF
@ -452,6 +508,8 @@ void LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE
{
mDriverState = JDS_INITIALIZED;
}
//todo: save mLastDeviceUUID to settings
#endif
}
@ -1251,6 +1309,12 @@ void LLViewerJoystick::scanJoystick()
}
}
// -----------------------------------------------------------------------------
LLSD LLViewerJoystick::getDeviceUUID()
{
return mLastDeviceUUID;
}
// -----------------------------------------------------------------------------
std::string LLViewerJoystick::getDescription()
{

View File

@ -50,7 +50,9 @@ class LLViewerJoystick : public LLSingleton<LLViewerJoystick>
public:
void init(bool autoenable);
void initDevice(LLSD &guid);
void initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/);
void initDevice(void * preffered_device /*LPDIRECTINPUTDEVICE8*/, std::string &name, LLSD &guid);
void terminate();
void updateStatus();
@ -69,8 +71,9 @@ public:
void setOverrideCamera(bool val);
bool toggleFlycam();
void setSNDefaults();
LLSD getDeviceUUID();
std::string getDescription();
protected:
void updateEnabled(bool autoenable);
void handleRun(F32 inc);
@ -96,6 +99,7 @@ private:
bool mCameraUpdated;
bool mOverrideCamera;
U32 mJoystickRun;
LLSD mLastDeviceUUID; // _UUID as U8 binary map, integer 1 for no device/ndof's device
static F32 sLastDelta[7];
static F32 sDelta[7];