From df986a402a2706fe12a7dae0caec181da8c0e5f0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 7 Jul 2020 19:45:06 +0300 Subject: SL-5894 Changed joystick init to select device with apropriate manufacturer and type --- indra/llwindow/llwindow.h | 4 ++++ indra/llwindow/llwindowwin32.cpp | 41 ++++++++++++++++++++++++++++++++++++++++ indra/llwindow/llwindowwin32.h | 3 +++ 3 files changed, 48 insertions(+) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index a05ba8cbba..90107a7c29 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -168,6 +168,10 @@ public: // Get system UI size based on DPI (for 96 DPI UI size should be 1.0) virtual F32 getSystemUISize() { return 1.0; } + + // windows only DirectInput8 for joysticks + virtual void* getDirectInput8() { return NULL; }; + virtual bool getInputDevices(U32 device_type_filter, void * devices_callback) { return false; }; protected: LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); virtual ~LLWindow(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 0b3936f8a5..2bc9c8d63c 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -59,6 +59,9 @@ #include #include +#include +#pragma comment(lib, "dinput8") +#pragma comment(lib, "dxguid.lib") const S32 MAX_MESSAGE_PER_UPDATE = 20; const S32 BITS_PER_PIXEL = 32; @@ -76,6 +79,7 @@ const F32 ICON_FLASH_TIME = 0.5f; extern BOOL gDebugWindowProc; LPWSTR gIconResource = IDI_APPLICATION; +LPDIRECTINPUT8 gDirectInput8; LLW32MsgCallback gAsyncMsgCallback = NULL; @@ -482,6 +486,21 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, mhInstance = GetModuleHandle(NULL); mWndProc = NULL; + // Init Direct Input - needed for joystick / Spacemouse + + LPDIRECTINPUT8 di8_interface; + HRESULT status = DirectInput8Create( + mhInstance, // HINSTANCE hinst, + DIRECTINPUT_VERSION, // DWORD dwVersion, + IID_IDirectInput8, // REFIID riidltf, + (LPVOID*)&di8_interface, // LPVOID * ppvOut, + NULL // LPUNKNOWN punkOuter + ); + if (status == DI_OK) + { + gDirectInput8 = di8_interface; + } + mSwapMethod = SWAP_METHOD_UNDEFINED; // No WPARAM yet. @@ -4157,6 +4176,28 @@ void LLWindowWin32::setDPIAwareness() } } +void* LLWindowWin32::getDirectInput8() +{ + return &gDirectInput8; +} + +bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback) +{ + if (gDirectInput8 != NULL) + { + // Enumerate devices + 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 + DIEDFL_ATTACHEDONLY // DWORD dwFlags + ); + + return status == DI_OK; + } + return false; +} + F32 LLWindowWin32::getSystemUISize() { F32 scale_value = 1.f; diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 9cd16eb993..dc02528bf2 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -116,6 +116,9 @@ public: static std::vector getDynamicFallbackFontList(); static void setDPIAwareness(); + + /*virtual*/ void* getDirectInput8(); + /*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback); protected: LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, -- cgit v1.3 From 54383cac8fa8a40d96590a300d4fce618f7413f3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Jul 2020 20:48:43 +0300 Subject: SL-5894 #3 WIP enumerate devices to flaoter, let floater set device temp --- indra/llui/llscrolllistctrl.cpp | 40 +++++++--- indra/llwindow/llwindow.h | 2 +- indra/llwindow/llwindowwin32.cpp | 4 +- indra/llwindow/llwindowwin32.h | 2 +- indra/newview/llfloaterjoystick.cpp | 87 +++++++++++++++++++-- indra/newview/llfloaterjoystick.h | 2 + indra/newview/llviewerjoystick.cpp | 148 ++++++++++++++++++++++++++---------- indra/newview/llviewerjoystick.h | 6 +- 8 files changed, 225 insertions(+), 66 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 763c3aeb81..8570dcf318 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -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 (selected) - { - selectItem(item); - } - else - { - deselectItem(item); - } - found = TRUE; - break; + if (item->getEnabled()) + { + 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; + } } } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 90107a7c29..f1113acd5f 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -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(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 2bc9c8d63c..c67e7f7c6c 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -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 ); diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index dc02528bf2..ee0df570e9 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -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, diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index 4538d34c95..79814de28d 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -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 +//#pragma comment(lib, "dinput8") +//#pragma comment(lib, "dxguid.lib") +#include +#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 diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index b3d879b233..93f5696272 100644 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -46,6 +46,8 @@ public: virtual void draw(); static void setSNDefaults(); + void addDevice(std::string &name, LLSD& value); + protected: void refreshListOfDevices(); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index 9775bf646a..baeaaa0722 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -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; + bool init_device = false; + if (guid.isBinary()) + { + std::vector 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 (!LLViewerJoystick::getInstance()->isJoystickInitialized()) + if (init_device) { - bool found_space_mouse = is_space_mouse(product_id, vendor_id); + 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 (found_space_mouse) + 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() { diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index 9c59f811f1..eba549c5f2 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -50,7 +50,9 @@ class LLViewerJoystick : public LLSingleton 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]; -- cgit v1.3 From 8c66f54cfa9b1d26271338b7629290b35222617f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 14 Jul 2020 00:28:21 +0300 Subject: SL-5894 #4 Organize device storage between sessions --- indra/llwindow/llwindowwin32.cpp | 2 - indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llfloaterjoystick.cpp | 30 +++-- indra/newview/llfloaterjoystick.h | 1 + indra/newview/llviewerjoystick.cpp | 200 ++++++++++++++++++-------------- indra/newview/llviewerjoystick.h | 7 +- 6 files changed, 148 insertions(+), 103 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index c67e7f7c6c..5bb27084d7 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -59,9 +59,7 @@ #include #include -#include #pragma comment(lib, "dinput8") -#pragma comment(lib, "dxguid.lib") const S32 MAX_MESSAGE_PER_UPDATE = 20; const S32 BITS_PER_PIXEL = 32; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dfc3c7b89d..1ab97ccc02 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5242,6 +5242,17 @@ Value + JoystickDeviceUUID + + Comment + Preffered device ID. + Persist + 1 + Type + String + Value + + JoystickMouselookYaw Comment diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index 79814de28d..93a26f31cc 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -49,9 +49,6 @@ // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 -//#include -//#pragma comment(lib, "dinput8") -//#pragma comment(lib, "dxguid.lib") #include #endif @@ -88,7 +85,8 @@ BOOL CALLBACK di8_list_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size); LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef; - floater->addDevice(product_name, LLSD(data)); + LLSD value = data; + floater->addDevice(product_name, value); } return DIENUM_CONTINUE; } @@ -178,6 +176,7 @@ void LLFloaterJoystick::apply() void LLFloaterJoystick::initFromSettings() { mJoystickEnabled = gSavedSettings.getBOOL("JoystickEnabled"); + mJoystickId = gSavedSettings.getLLSD("JoystickDeviceUUID"); mJoystickAxis[0] = gSavedSettings.getS32("JoystickAxis0"); mJoystickAxis[1] = gSavedSettings.getS32("JoystickAxis1"); @@ -260,7 +259,8 @@ void LLFloaterJoystick::refreshListOfDevices() { mJoysticksCombo->removeall(); std::string no_device = getString("JoystickDisabled"); - addDevice(no_device, LLSD(LLSD::Integer(0))); + LLSD value = LLSD::Integer(0); + addDevice(no_device, value); mHasDeviceList = false; @@ -269,7 +269,7 @@ void LLFloaterJoystick::refreshListOfDevices() // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib U32 device_type = DI8DEVCLASS_GAMECTRL; void* callback = &di8_list_devices_callback; -#elif +#else // 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 @@ -281,10 +281,10 @@ void LLFloaterJoystick::refreshListOfDevices() mHasDeviceList = true; } - LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID(); + bool is_device_id_set = LLViewerJoystick::getInstance()->isDeviceUUIDSet(); if (LLViewerJoystick::getInstance()->isJoystickInitialized() && - (!mHasDeviceList || !guid.isBinary())) + (!mHasDeviceList || !is_device_id_set)) { #if LL_WINDOWS && !LL_MESA_HEADLESS LL_WARNS() << "NDOF connected to device without using SL provided handle" << LL_ENDL; @@ -292,15 +292,17 @@ void LLFloaterJoystick::refreshListOfDevices() std::string desc = LLViewerJoystick::getInstance()->getDescription(); if (!desc.empty()) { - addDevice(desc, LLSD(LLSD::Integer(1))); + LLSD value = LLSD::Integer(0); + addDevice(desc, value); mHasDeviceList = true; } } if (gSavedSettings.getBOOL("JoystickEnabled") && mHasDeviceList) { - if (guid.isBinary()) + if (is_device_id_set) { + LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID(); mJoysticksCombo->selectByValue(guid); } else @@ -317,6 +319,7 @@ void LLFloaterJoystick::refreshListOfDevices() void LLFloaterJoystick::cancel() { gSavedSettings.setBOOL("JoystickEnabled", mJoystickEnabled); + gSavedSettings.setLLSD("JoystickDeviceUUID", mJoystickId); gSavedSettings.setS32("JoystickAxis0", mJoystickAxis[0]); gSavedSettings.setS32("JoystickAxis1", mJoystickAxis[1]); @@ -391,15 +394,14 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel) bool joystick_enabled = true; if (value.isInteger()) { - joystick_enabled = value.asInteger(); // ndof already has a device selected, we are just setting it enabled or disabled + joystick_enabled = value.asInteger(); } 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 } gSavedSettings.setBOOL("JoystickEnabled", joystick_enabled); BOOL flycam_enabled = self->mCheckFlycamEnabled->get(); @@ -414,6 +416,10 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel) } } + std::string device_id = LLViewerJoystick::getInstance()->getDeviceUUIDString(); + gSavedSettings.setString("JoystickDeviceUUID", device_id); + LL_DEBUGS("Joystick") << "Selected " << device_id << " as joystick." << LL_ENDL; + self->refreshListOfDevices(); } diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index 93f5696272..1d46efd3f6 100644 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -69,6 +69,7 @@ private: private: // Device prefs bool mJoystickEnabled; + LLSD mJoystickId; S32 mJoystickAxis[7]; bool m3DCursor; bool mAutoLeveling; diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index baeaaa0722..a75e0b5569 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -46,9 +46,6 @@ // Require DirectInput version 8 #define DIRECTINPUT_VERSION 0x0800 -//#include -//#pragma comment(lib, "dinput8") -//#pragma comment(lib, "dxguid.lib") #include #endif @@ -76,13 +73,11 @@ F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; #if LL_WINDOWS && !LL_MESA_HEADLESS -// took this from ndofdev_win.cpp -BOOL CALLBACK EnumNDOFObjectsCallback(const DIDEVICEOBJECTINSTANCE* inst, - VOID* user_data) +// this should reflect ndof and set axises, see ndofdev_win.cpp from ndof package +BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* inst, VOID* user_data) { if (inst->dwType & DIDFT_AXIS) { - HRESULT hr = DI_OK; LPDIRECTINPUTDEVICE8 device = *((LPDIRECTINPUTDEVICE8 *)user_data); DIPROPRANGE diprg; diprg.diph.dwSize = sizeof(DIPROPRANGE); @@ -93,70 +88,15 @@ BOOL CALLBACK EnumNDOFObjectsCallback(const DIDEVICEOBJECTINSTANCE* inst, // Set the range for the axis diprg.lMin = (long)-MAX_JOYSTICK_INPUT_VALUE; diprg.lMax = (long)+MAX_JOYSTICK_INPUT_VALUE; - hr = device->SetProperty(DIPROP_RANGE, &diprg.diph); - assert(hr == DI_OK); - + HRESULT hr = device->SetProperty(DIPROP_RANGE, &diprg.diph); if (FAILED(hr)) - return DIENUM_STOP; - } - - return DIENUM_CONTINUE; -} - -// vvvv Product ID -// 0xC62B046D -// ^^^^ Vendor ID -// 0x046D Logitech's Vendor ID -// 0x256F 3Dconnexion's Vendor ID -// -// See: -// https://github.com/janoc/libndofdev/blob/master/ndofdev.c -// http://spacemice.org/index.php?title=Dev -// https://www.3dconnexion.com/nc/service/faq/faq/how-can-i-check-if-my-usb-3d-mouse-is-recognized-by-windows.html -bool is_space_mouse(const U16 product_id, const U16 vendor_id) -{ - if (vendor_id == 0x046d) // Logitech's Vendor ID - { - if (false - || (product_id == 0xc603) // SpaceMouse Plus USB, SpaceMouse Plus XT USB - || (product_id == 0xc605) // CadMan: USB - || (product_id == 0xc606) // SpaceMouse Classic USB - || (product_id == 0xc621) // SpaceBall 5000 USB - || (product_id == 0xc623) // SpaceTraveler: USB - || (product_id == 0xc625) // SpacePilot: USB - || (product_id == 0xc626) // SpaceNavigator: USB - || (product_id == 0xc627) // SpaceExplorer: USB - || (product_id == 0xc628) // SpaceNavigator for Notebooks: USB - || (product_id == 0xc629) // SpacePilot Pro: USB - || (product_id == 0xc62b) // SpaceMouse Pro: USB - ) { - return true; + return DIENUM_STOP; } } - else - if (vendor_id == 0x256F) // 3Dconnexion's Vendor ID - { - if (false - || (product_id == 0xc62E) // SpaceMouse Wireless (cabled) - || (product_id == 0xc62F) // SpaceMouse Wireless Receiver - || (product_id == 0xc631) // Spacemouse Wireless (cabled) - || (product_id == 0xc632) // SpacemousePro Wireless Receiver - || (product_id == 0xc633) // SpaceMouse Enterprise - || (product_id == 0xc635) // Spacemouse Compact - || (product_id == 0xc650) // CadMouse - || (product_id == 0xc651) // CadMouse Wireless - || (product_id == 0xc652) // Universal Receiver - || (product_id == 0xc654) // CadMouse Pro Wireless - || (product_id == 0xc657) // CadMouse Pro Wireless Left - ) - { - return true; - } - } - return false; + return DIENUM_CONTINUE; } BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVOID pvRef) @@ -179,7 +119,7 @@ BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVO 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 + // ndof will pick a random device, it is simpler to pick first device now to have an id init_device = true; } @@ -206,7 +146,7 @@ BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVO { // set properties LL_DEBUGS("Joystick") << "Format set" << LL_ENDL; - status = device->EnumObjects(EnumNDOFObjectsCallback, &device, DIDFT_ALL); + status = device->EnumObjects(EnumObjectsCallback, &device, DIDFT_ALL); } if (status == DI_OK) @@ -228,6 +168,27 @@ BOOL CALLBACK di8_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVO } return DIENUM_CONTINUE; } + +// Windows guids +// This is GUID2 so teoretically it can be memcpy copied into LLUUID +void guid_from_string(GUID &guid, const std::string &input) +{ + CLSIDFromString(utf8str_to_utf16str(input).c_str(), &guid); +} + +std::string string_from_guid(const GUID &guid) +{ + OLECHAR* guidString; //wchat + StringFromCLSID(guid, &guidString); + + // use guidString... + + std::string res = utf16str_to_utf8str(llutf16string(guidString)); + // ensure memory is freed + ::CoTaskMemFree(guidString); + + return res; +} #endif // ----------------------------------------------------------------------------- @@ -239,7 +200,8 @@ void LLViewerJoystick::updateEnabled(bool autoenable) } else { - if (isLikeSpaceNavigator() && autoenable) + // autoenable if user specifically chose this device + if (autoenable && (isLikeSpaceNavigator() || isDeviceUUIDSet())) { gSavedSettings.setBOOL("JoystickEnabled", TRUE ); } @@ -275,7 +237,7 @@ NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev) LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); if (joystick->mDriverState == JDS_UNINITIALIZED) { - LL_INFOS() << "HotPlugAddCallback: will use device:" << LL_ENDL; + LL_INFOS("Joystick") << "HotPlugAddCallback: will use device:" << LL_ENDL; ndof_dump(dev); joystick->mNdofDev = dev; joystick->mDriverState = JDS_INITIALIZED; @@ -293,7 +255,7 @@ void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev) LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); if (joystick->mNdofDev == dev) { - LL_INFOS() << "HotPlugRemovalCallback: joystick->mNdofDev=" + LL_INFOS("Joystick") << "HotPlugRemovalCallback: joystick->mNdofDev=" << joystick->mNdofDev << "; removed device:" << LL_ENDL; ndof_dump(dev); joystick->mDriverState = JDS_UNINITIALIZED; @@ -339,7 +301,8 @@ void LLViewerJoystick::init(bool autoenable) #if LIB_NDOF static bool libinit = false; mDriverState = JDS_INITIALIZING; - //todo: load mLastDeviceUUID from settings + + loadDeviceIdFromSettings(); if (libinit == false) { @@ -369,7 +332,7 @@ void LLViewerJoystick::init(bool autoenable) // space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib U32 device_type = DI8DEVCLASS_GAMECTRL; void* callback = &di8_devices_callback; -#elif +#else // 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 @@ -378,20 +341,17 @@ void LLViewerJoystick::init(bool autoenable) #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; + LL_INFOS("Joystick") << "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); + mLastDeviceUUID = LLSD(); void *preffered_device = NULL; initDevice(preffered_device); } - // make sure a device was found: 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); + LL_INFOS("Joystick") << "Found no matching joystick devices." << LL_ENDL; + mDriverState = JDS_UNINITIALIZED; } } else @@ -431,7 +391,7 @@ void LLViewerJoystick::init(bool autoenable) // No device connected, don't change any settings } - LL_INFOS() << "ndof: mDriverState=" << mDriverState << "; mNdofDev=" + LL_INFOS("Joystick") << "ndof: mDriverState=" << mDriverState << "; mNdofDev=" << mNdofDev << "; libinit=" << libinit << LL_ENDL; #endif } @@ -440,13 +400,12 @@ 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 +#else // 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 @@ -454,14 +413,21 @@ void LLViewerJoystick::initDevice(LLSD &guid) void* callback = NULL; #endif + mDriverState = JDS_INITIALIZING; if (!gViewerWindow->getWindow()->getInputDevices(device_type, callback, NULL)) { - LL_INFOS() << "Failed to gather devices from window. Falling back to ndof's init" << LL_ENDL; + LL_INFOS("Joystick") << "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); + mLastDeviceUUID = LLSD(); initDevice(preffered_device); } + + if (mDriverState == JDS_INITIALIZING) + { + LL_INFOS("Joystick") << "Found no matching joystick devices." << LL_ENDL; + mDriverState = JDS_UNINITIALIZED; + } #endif } @@ -508,8 +474,6 @@ void LLViewerJoystick::initDevice(void * preffered_device /* LPDIRECTINPUTDEVICE { mDriverState = JDS_INITIALIZED; } - - //todo: save mLastDeviceUUID to settings #endif } @@ -519,7 +483,7 @@ void LLViewerJoystick::terminate() #if LIB_NDOF ndof_libcleanup(); - LL_INFOS() << "Terminated connection with NDOF device." << LL_ENDL; + LL_INFOS("Joystick") << "Terminated connection with NDOF device." << LL_ENDL; mDriverState = JDS_UNINITIALIZED; #endif } @@ -1310,11 +1274,73 @@ void LLViewerJoystick::scanJoystick() } // ----------------------------------------------------------------------------- +bool LLViewerJoystick::isDeviceUUIDSet() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // for ease of comparison and to dial less with platform specific variables, we store id as LLSD binary + return mLastDeviceUUID.isBinary(); +#else + return false; +#endif +} + LLSD LLViewerJoystick::getDeviceUUID() { return mLastDeviceUUID; } +std::string LLViewerJoystick::getDeviceUUIDString() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // Might be simpler to just convert _GUID into string everywhere, store and compare as string + if (mLastDeviceUUID.isBinary()) + { + S32 size = sizeof(GUID); + LLSD::Binary data = mLastDeviceUUID.asBinary(); + GUID guid; + memcpy(&guid, &data[0], size); + return string_from_guid(guid); + } + else + { + return std::string(); + } +#else + return std::string(); + // return mLastDeviceUUID; +#endif +} + +void LLViewerJoystick::loadDeviceIdFromSettings() +{ +#if LL_WINDOWS && !LL_MESA_HEADLESS + // We can't save binary data to gSavedSettings, somebody editing the file will corrupt it, + // so _GUID data gets converted to string (we probably can convert it to LLUUID with memcpy) + // and here we need to convert it back to binary from string + std::string device_string = gSavedSettings.getString("JoystickDeviceUUID"); + if (device_string.empty()) + { + mLastDeviceUUID = LLSD(); + } + else + { + LL_DEBUGS("Joystick") << "Looking for device by id: " << device_string << LL_ENDL; + GUID guid; + guid_from_string(guid, device_string); + S32 size = sizeof(GUID); + LLSD::Binary data; //just an std::vector + data.resize(size); + memcpy(&data[0], &guid /*POD _GUID*/, size); + // We store this data in LLSD since LLSD is versatile and will be able to handle both GUID2 + // and any data MAC will need for device selection + mLastDeviceUUID = LLSD(data); + } +#else + mLastDeviceUUID = LLSD(); + //mLastDeviceUUID = gSavedSettings.getLLSD("JoystickDeviceUUID"); +#endif +} + // ----------------------------------------------------------------------------- std::string LLViewerJoystick::getDescription() { diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index eba549c5f2..782c523d4f 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -71,7 +71,9 @@ public: void setOverrideCamera(bool val); bool toggleFlycam(); void setSNDefaults(); - LLSD getDeviceUUID(); + bool isDeviceUUIDSet(); + LLSD getDeviceUUID(); //unconverted, OS dependent value wrapped into LLSD, for comparison/search + std::string getDeviceUUIDString(); // converted readable value for settings std::string getDescription(); protected: @@ -84,6 +86,7 @@ protected: void agentYaw(F32 yaw_inc); void agentJump(); void resetDeltas(S32 axis[]); + void loadDeviceIdFromSettings(); #if LIB_NDOF static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev); static void HotPlugRemovalCallback(NDOF_Device *dev); @@ -99,7 +102,7 @@ private: bool mCameraUpdated; bool mOverrideCamera; U32 mJoystickRun; - LLSD mLastDeviceUUID; // _UUID as U8 binary map, integer 1 for no device/ndof's device + LLSD mLastDeviceUUID; // _GUID as U8 binary map, integer 1 for no device/ndof's device static F32 sLastDelta[7]; static F32 sDelta[7]; -- cgit v1.3 From 201384690c72807128c6acde344b5191d88818ab Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 15 Jul 2020 16:02:51 +0300 Subject: SL-5894 Fix llurlentry test building --- indra/llwindow/llwindowwin32.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 5bb27084d7..164133b5eb 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -59,6 +59,8 @@ #include #include +#include // needed for llurlentry test to build on some systems +#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems #pragma comment(lib, "dinput8") const S32 MAX_MESSAGE_PER_UPDATE = 20; -- cgit v1.3