diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2020-07-10 20:48:43 +0300 |
---|---|---|
committer | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2020-07-15 13:55:32 +0300 |
commit | 54383cac8fa8a40d96590a300d4fce618f7413f3 (patch) | |
tree | 25e5d5b28bcc914a779292f33a2070593f5c247f /indra/newview | |
parent | 0fbe4cf62a236ea24f383818bf81b933f87380d8 (diff) |
SL-5894 #3 WIP enumerate devices to flaoter, let floater set device
temp
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llfloaterjoystick.cpp | 87 | ||||
-rw-r--r-- | indra/newview/llfloaterjoystick.h | 2 | ||||
-rw-r--r-- | indra/newview/llviewerjoystick.cpp | 148 | ||||
-rw-r--r-- | indra/newview/llviewerjoystick.h | 6 |
4 files changed, 193 insertions, 50 deletions
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 <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 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<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 (!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 } @@ -1252,6 +1310,12 @@ void LLViewerJoystick::scanJoystick() } // ----------------------------------------------------------------------------- +LLSD LLViewerJoystick::getDeviceUUID() +{ + return mLastDeviceUUID; +} + +// ----------------------------------------------------------------------------- std::string LLViewerJoystick::getDescription() { std::string res; 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<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]; |