diff options
| -rw-r--r-- | indra/llui/llscrolllistctrl.cpp | 40 | ||||
| -rw-r--r-- | indra/llwindow/llwindow.h | 2 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.cpp | 4 | ||||
| -rw-r--r-- | indra/llwindow/llwindowwin32.h | 2 | ||||
| -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 | 
8 files changed, 225 insertions, 66 deletions
| 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 <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]; | 
