diff options
27 files changed, 2004 insertions, 366 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index b69ac30e9c..1eb3d169a5 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -656,7 +656,8 @@ void LLFloater::setTitle( const LLString& title )  	{  		return;  	} -	mDragHandle->setTitle( title ); +	if (mDragHandle) +		mDragHandle->setTitle( title );  }  const LLString& LLFloater::getTitle() const @@ -934,7 +935,8 @@ void LLFloater::setIsChrome(BOOL is_chrome)  	}  	// no titles displayed on "chrome" floaters -	mDragHandle->setTitleVisible(!is_chrome); +	if (mDragHandle) +		mDragHandle->setTitleVisible(!is_chrome);  	LLPanel::setIsChrome(is_chrome);  } @@ -945,7 +947,8 @@ void LLFloater::setForeground(BOOL front)  	if (front != mForeground)  	{  		mForeground = front; -		mDragHandle->setForeground( front ); +		if (mDragHandle) +			mDragHandle->setForeground( front );  		if (!front)  		{ @@ -1580,8 +1583,8 @@ void LLFloater::updateButtons()  			mButtons[i]->setVisible(FALSE);  		}  	} - -	mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (LLFLOATER_CLOSE_BOX_SIZE + 1))); +	if (mDragHandle) +		mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (LLFLOATER_CLOSE_BOX_SIZE + 1)));  }  void LLFloater::buildButtons() diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 37f089e8be..c640a83328 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -143,6 +143,11 @@ BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated)  	return FALSE;  } +BOOL LLWindowCallbacks::handleActivateApp(LLWindow *window, BOOL activating) +{ +	return FALSE; +} +  void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask)  {  } @@ -190,6 +195,15 @@ void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *da  {  } +BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window) +{ +	return FALSE; +} + +BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window) +{ +	return FALSE; +}  S32 OSMessageBox(const char* text, const char* caption, U32 type)  { @@ -247,15 +261,6 @@ LLWindow::LLWindow(BOOL fullscreen, U32 flags)  	  mFlags(flags),  	  mHighSurrogate(0)  { -	for (U32 i = 0; i < 8; i++) -	{ -		mJoyAxis[i] = 0; -	} - -	for (U32 i = 0; i < 16; i++) -	{ -		mJoyButtonState[i] = 0; -	}  }  // virtual @@ -273,24 +278,6 @@ void LLWindow::decBusyCount()  	}  } -F32 LLWindow::getJoystickAxis(U32 axis) -{ -	if (axis < 8) -	{ -		return mJoyAxis[axis]; -	} -	return 0.f; -} - -U8 LLWindow::getJoystickButton(U32 button) -{ -	if (button < 16) -	{ -		return mJoyButtonState[button]; -	} -	return 0; -} -  void LLWindow::setCallbacks(LLWindowCallbacks *callbacks)  {  	mCallbacks = callbacks; diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 6b9414a301..81adf8b13a 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -107,6 +107,7 @@ public:  	virtual BOOL handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask);  	virtual BOOL handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask);  	virtual BOOL handleActivate(LLWindow *window, BOOL activated); +	virtual BOOL handleActivateApp(LLWindow *window, BOOL activating);  	virtual void handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask);  	virtual void handleScrollWheel(LLWindow *window,  S32 clicks);  	virtual void handleResize(LLWindow *window,  S32 width,  S32 height); @@ -118,6 +119,8 @@ public:  	virtual void handleWindowBlock(LLWindow *window);							// window is taking over CPU for a while  	virtual void handleWindowUnblock(LLWindow *window);							// window coming back after taking over CPU for a while  	virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data); +	virtual BOOL handleTimerEvent(LLWindow *window); +	virtual BOOL handleDeviceChange(LLWindow *window);  };  // Refer to llwindow_test in test/common/llwindow for usage example @@ -214,9 +217,6 @@ public:  	virtual F32 getPixelAspectRatio() = 0;  	virtual void setNativeAspectRatio(F32 aspect) = 0; -	F32 getJoystickAxis(U32 axis); -	U8 getJoystickButton(U32 button); -  	void setCallbacks(LLWindowCallbacks *callbacks);  	virtual void beforeDialog() {};	// prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode) @@ -260,8 +260,6 @@ protected:  	ESwapMethod mSwapMethod;  	BOOL		mHideCursorPermanent;  	U32			mFlags; -	F32			mJoyAxis[8];  -	U8			mJoyButtonState[16];  	U16			mHighSurrogate;   	// Handle a UTF-16 encoding unit received from keyboard. diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f05397b058..61daacb567 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -46,7 +46,7 @@  #define DIRECTINPUT_VERSION 0x0800  #include <dinput.h> - +#include <Dbt.h.>  #include "llkeyboardwin32.h"  #include "llerror.h" @@ -359,14 +359,6 @@ LLWinImm::~LLWinImm()  } -LPDIRECTINPUT8       g_pDI              = NULL;          -LPDIRECTINPUTDEVICE8 g_pJoystick        = NULL;      -BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, -									VOID* pContext ); -BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, -								  VOID* pContext ); - -  LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,  							 S32 height, U32 flags,   							 BOOL fullscreen, BOOL clearBg, @@ -666,38 +658,6 @@ LLWindowWin32::LLWindowWin32(char *title, char *name, S32 x, S32 y, S32 width,  	// Initialize (boot strap) the Language text input management,  	// based on the system's (or user's) default settings.  	allowLanguageTextInput(NULL, FALSE); -} - -void LLWindowWin32::initInputDevices() -{ -	// Direct Input -	HRESULT hr; - -	if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION,  -		IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) ) -	{ -		llwarns << "Direct8InputCreate failed!" << llendl; -	} -	else -	{ -		while(1) -		{ -			// Look for a simple joystick we can use for this sample program. -			if (FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,  -				EnumJoysticksCallback, -				NULL, DIEDFL_ATTACHEDONLY ) ) ) -				break; -			if (!g_pJoystick) -				break; -			if( FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick ) ) ) -				break; -			if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback,  -				(VOID*)mWindowHandle, DIDFT_ALL ) ) ) -				break; -			g_pJoystick->Acquire(); -			break; -		} -	}  	SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer  } @@ -1438,8 +1398,6 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO  	SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);  	show(); -	initInputDevices(); -  	// ok to post quit messages now  	mPostQuit = TRUE;  	return TRUE; @@ -1730,7 +1688,22 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  			S32		update_height;  		case WM_TIMER: -			window_imp->updateJoystick( ); +			window_imp->mCallbacks->handleTimerEvent(window_imp); +			break; + +		case WM_DEVICECHANGE: +			if (gDebugWindowProc) +			{ +				llinfos << "  WM_DEVICECHANGE: wParam=" << w_param  +						<< "; lParam=" << l_param << llendl; +			} +			if (w_param == DBT_DEVNODES_CHANGED || w_param == DBT_DEVICEARRIVAL) +			{ +				if (window_imp->mCallbacks->handleDeviceChange(window_imp)) +				{ +					return 0; +				} +			}  			break;  		case WM_PAINT: @@ -1795,6 +1768,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  						window_imp->resetDisplayResolution();  					}  				} + +				window_imp->mCallbacks->handleActivateApp(window_imp, activating); +  				break;  			} @@ -2831,81 +2807,6 @@ void LLWindowWin32::swapBuffers()  } -BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, -									VOID* pContext ) -{ -	HRESULT hr; - -	// Obtain an interface to the enumerated joystick. -	hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL ); - -	// If it failed, then we can't use this joystick. (Maybe the user unplugged -	// it while we were in the middle of enumerating it.) -	if( FAILED(hr) )  -		return DIENUM_CONTINUE; - -	// Stop enumeration. Note: we're just taking the first joystick we get. You -	// could store all the enumerated joysticks and let the user pick. -	return DIENUM_STOP; -} - -BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, -								  VOID* pContext ) -{ -	if( pdidoi->dwType & DIDFT_AXIS ) -	{ -		DIPROPRANGE diprg;  -		diprg.diph.dwSize       = sizeof(DIPROPRANGE);  -		diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);  -		diprg.diph.dwHow        = DIPH_BYID;  -		diprg.diph.dwObj        = pdidoi->dwType; // Specify the enumerated axis -		diprg.lMin              = -1000;  -		diprg.lMax              = +1000;  - -		// Set the range for the axis -		if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )  -			return DIENUM_STOP; - -	} -	return DIENUM_CONTINUE; -} - -void LLWindowWin32::updateJoystick( ) -{ -	HRESULT hr; -	DIJOYSTATE js;           // DInput joystick state - -	if (!g_pJoystick) -		return; -	hr = g_pJoystick->Poll(); -	if ( hr == DIERR_INPUTLOST ) -	{ -		hr = g_pJoystick->Acquire(); -		return; -	} -	else if ( FAILED(hr) ) -		return; - -	// Get the input's device state -	if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js ) ) ) -		return; // The device should have been acquired during the Poll() - -	mJoyAxis[0] = js.lX/1000.f; -	mJoyAxis[1] = js.lY/1000.f; -	mJoyAxis[2] = js.lZ/1000.f; -	mJoyAxis[3] = js.lRx/1000.f; -	mJoyAxis[4] = js.lRy/1000.f; -	mJoyAxis[5] = js.lRz/1000.f; -	mJoyAxis[6] = js.rglSlider[0]/1000.f; -	mJoyAxis[7] = js.rglSlider[1]/1000.f; - -	for (U32 i = 0; i < 16; i++) -	{ -		mJoyButtonState[i] = js.rgbButtons[i]; -	} -} - -  //  // LLSplashScreenImp  // diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 1a26783623..2754b27234 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2791,7 +2791,7 @@          <key>Value</key>              <integer>0</integer>          </map> -    <key>FlycamAutoLeveling</key> +    <key>AutoLeveling</key>          <map>          <key>Comment</key>              <string>Keep Flycam level.</string> @@ -2802,7 +2802,40 @@          <key>Value</key>              <integer>1</integer>          </map> -    <key>FlycamAxis0</key> +    <key>Cursor3D</key> +        <map> +        <key>Comment</key> +            <string>Tread Joystick values as absolute positions (not deltas).</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +        </map> +    <key>ZoomDirect</key> +        <map> +        <key>Comment</key> +            <string>Map Joystick zoom axis directly to camera zoom.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +        </map> +    <key>JoystickInitialized</key> +        <map> +        <key>Comment</key> +            <string>Whether or not a joystick has been detected and initiailized.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>String</string> +        <key>Value</key> +            <string></string> +        </map> +    <key>JoystickAxis0</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 0 ([0, 5]).</string> @@ -2813,7 +2846,7 @@          <key>Value</key>              <integer>0</integer>          </map> -    <key>FlycamAxis1</key> +    <key>JoystickAxis1</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 1 ([0, 5]).</string> @@ -2822,9 +2855,9 @@          <key>Type</key>              <string>S32</string>          <key>Value</key> -            <integer>1</integer> +            <integer>2</integer>          </map> -    <key>FlycamAxis2</key> +    <key>JoystickAxis2</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 2 ([0, 5]).</string> @@ -2833,9 +2866,9 @@          <key>Type</key>              <string>S32</string>          <key>Value</key> -            <integer>2</integer> +            <integer>1</integer>          </map> -    <key>FlycamAxis3</key> +    <key>JoystickAxis3</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 3 ([0, 5]).</string> @@ -2844,9 +2877,9 @@          <key>Type</key>              <string>S32</string>          <key>Value</key> -            <integer>3</integer> +            <integer>5</integer>          </map> -    <key>FlycamAxis4</key> +    <key>JoystickAxis4</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 4 ([0, 5]).</string> @@ -2857,7 +2890,7 @@          <key>Value</key>              <integer>4</integer>          </map> -    <key>FlycamAxis5</key> +    <key>JoystickAxis5</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 5 ([0, 5]).</string> @@ -2866,9 +2899,9 @@          <key>Type</key>              <string>S32</string>          <key>Value</key> -            <integer>5</integer> +            <integer>3</integer>          </map> -    <key>FlycamAxis6</key> +    <key>JoystickAxis6</key>          <map>          <key>Comment</key>              <string>Flycam hardware axis mapping for internal axis 6 ([0, 5]).</string> @@ -2888,7 +2921,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisDeadZone1</key>          <map> @@ -2899,7 +2932,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisDeadZone2</key>          <map> @@ -2910,7 +2943,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisDeadZone3</key>          <map> @@ -2921,7 +2954,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisDeadZone4</key>          <map> @@ -2932,7 +2965,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisDeadZone5</key>          <map> @@ -2943,7 +2976,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisDeadZone6</key>          <map> @@ -2954,7 +2987,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>FlycamAxisScale0</key>          <map> @@ -6016,7 +6049,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>SelectionHighlightThickness</key>          <map> @@ -6049,7 +6082,7 @@          <key>Type</key>              <string>F32</string>          <key>Value</key> -            <real>0.1000000014901161193847656</real> +            <real>0.1</real>          </map>      <key>SelectionHighlightVAnim</key>          <map> @@ -6606,7 +6639,7 @@              <array>                  <real>1</real>                  <real>0</real> -                <real>0.1000000014901161193847656</real> +                <real>0.1</real>              </array>          </map>  	<key>SkyUseClassicClouds</key> @@ -9748,5 +9781,294 @@  		<key>Value</key>  			<real>1</real>  		</map> + +    <key>AvatarAxisDeadZone0</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 0 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>AvatarAxisDeadZone1</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 1 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>AvatarAxisDeadZone2</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 2 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>AvatarAxisDeadZone3</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 3 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>AvatarAxisDeadZone4</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 4 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>AvatarAxisDeadZone5</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 5 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>AvatarAxisScale0</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 0 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarAxisScale1</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 1 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarAxisScale2</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 2 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarAxisScale3</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 3 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarAxisScale4</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 4 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarAxisScale5</key> +        <map> +        <key>Comment</key> +            <string>Avatar axis 5 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>AvatarFeathering</key> +        <map> +        <key>Comment</key> +            <string>Avatar feathering (less is softer)</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>16</real> +        </map> + +    <key>BuildAxisDeadZone0</key> +        <map> +        <key>Comment</key> +            <string>Build axis 0 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>BuildAxisDeadZone1</key> +        <map> +        <key>Comment</key> +            <string>Build axis 1 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>BuildAxisDeadZone2</key> +        <map> +        <key>Comment</key> +            <string>Build axis 2 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>BuildAxisDeadZone3</key> +        <map> +        <key>Comment</key> +            <string>Build axis 3 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>BuildAxisDeadZone4</key> +        <map> +        <key>Comment</key> +            <string>Build axis 4 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>BuildAxisDeadZone5</key> +        <map> +        <key>Comment</key> +            <string>Build axis 5 dead zone.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>0.1</real> +        </map> +    <key>BuildAxisScale0</key> +        <map> +        <key>Comment</key> +            <string>Build axis 0 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>BuildAxisScale1</key> +        <map> +        <key>Comment</key> +            <string>Build axis 1 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>BuildAxisScale2</key> +        <map> +        <key>Comment</key> +            <string>Build axis 2 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>BuildAxisScale3</key> +        <map> +        <key>Comment</key> +            <string>Build axis 3 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>BuildAxisScale4</key> +        <map> +        <key>Comment</key> +            <string>Build axis 4 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>BuildAxisScale5</key> +        <map> +        <key>Comment</key> +            <string>Build axis 5 scaler.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>1</real> +        </map> +    <key>BuildFeathering</key> +        <map> +        <key>Comment</key> +            <string>Build feathering (less is softer)</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>F32</string> +        <key>Value</key> +            <real>16</real> +        </map> +      </map>  </llsd> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 2f5589a966..dcea6b2957 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -581,7 +581,7 @@ void LLAgent::unlockView()  //-----------------------------------------------------------------------------  // moveAt()  //----------------------------------------------------------------------------- -void LLAgent::moveAt(S32 direction) +void LLAgent::moveAt(S32 direction, bool reset)  {  	// age chat timer so it fades more quickly when you are intentionally moving  	ageChat(); @@ -597,7 +597,10 @@ void LLAgent::moveAt(S32 direction)  		setControlFlags(AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT);  	} -	resetView(); +	if (reset) +	{ +		resetView(); +	}  }  //----------------------------------------------------------------------------- @@ -691,7 +694,7 @@ void LLAgent::moveUp(S32 direction)  //-----------------------------------------------------------------------------  // moveYaw()  //----------------------------------------------------------------------------- -void LLAgent::moveYaw(F32 mag) +void LLAgent::moveYaw(F32 mag, bool reset_view)  {  	mYawKey = mag; @@ -704,7 +707,10 @@ void LLAgent::moveYaw(F32 mag)  		setControlFlags(AGENT_CONTROL_YAW_NEG);  	} -	resetView(); +    if (reset_view) +	{ +        resetView(); +	}  }  //----------------------------------------------------------------------------- @@ -1216,7 +1222,16 @@ LLVector3 LLAgent::getReferenceUpVector()  void LLAgent::pitch(F32 angle)  {  	// don't let user pitch if pointed almost all the way down or up -	 +	mFrameAgent.pitch(clampPitchToLimits(angle)); +} + + +// Radians, positive is forward into ground +//----------------------------------------------------------------------------- +// clampPitchToLimits() +//----------------------------------------------------------------------------- +F32 LLAgent::clampPitchToLimits(F32 angle) +{  	// A dot B = mag(A) * mag(B) * cos(angle between A and B)  	// so... cos(angle between A and B) = A dot B / mag(A) / mag(B)  	//                                  = A dot B for unit vectors @@ -1246,8 +1261,8 @@ void LLAgent::pitch(F32 angle)  	{  		angle = look_up_limit - angle_from_skyward;  	} - -	mFrameAgent.pitch(angle); +    +    return angle;  } @@ -2576,15 +2591,18 @@ void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y)  		LLVector3 headLookAxis;  		LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance()); -		F32 x_from_center = ((F32) mouse_x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f; -		F32 y_from_center = ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f; -  		if (cameraMouselook())  		{  			lookAtType = LOOKAT_TARGET_MOUSELOOK;  		}  		else if (cameraThirdPerson())  		{ +			// range from -.5 to .5 +			F32 x_from_center =  +				((F32) mouse_x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f; +			F32 y_from_center =  +				((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f; +  			frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD);  			frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD);  			lookAtType = LOOKAT_TARGET_FREELOOK; diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 1a7d239288..b50fb745ca 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -356,6 +356,7 @@ public:  	void			roll(F32 angle);  	void			yaw(F32 angle);  	LLVector3		getReferenceUpVector(); +    F32             clampPitchToLimits(F32 angle);  	void			setThirdPersonHeadOffset(LLVector3 offset) { mThirdPersonHeadOffset = offset; }  	// Flight management @@ -404,12 +405,12 @@ public:  	// Movement from user input.  All set the appropriate animation flags.  	// All turn off autopilot and make sure the camera is behind the avatar.  	// direction is either positive, zero, or negative -	void			moveAt(S32 direction); +	void			moveAt(S32 direction, bool reset_view = true);  	void			moveAtNudge(S32 direction);  	void			moveLeft(S32 direction);  	void			moveLeftNudge(S32 direction);  	void			moveUp(S32 direction); -	void			moveYaw(F32 mag); +	void			moveYaw(F32 mag, bool reset_view = true);  	void			movePitch(S32 direction);  	void			setOrbitLeftKey(F32 mag)				{ mOrbitLeftKey = mag; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fc092e5cba..3d10eda7fd 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -51,6 +51,7 @@  #include "llstartup.h"  #include "llfocusmgr.h"  #include "llviewerjoystick.h" +#include "llfloaterjoystick.h"  #include "llares.h"   #include "llcurl.h"  #include "llfloatersnapshot.h" @@ -709,7 +710,7 @@ bool LLAppViewer::init()  	// Copy settings to globals. *TODO: Remove or move to appropriage class initializers -    	settings_to_globals(); +	settings_to_globals();  	// Setup settings listeners  	settings_setup_listeners();  	// Modify settings based on system configuration and compile options @@ -858,6 +859,16 @@ bool LLAppViewer::init()  	gSimLastTime = gRenderStartTime.getElapsedTimeF32();  	gSimFrames = (F32)gFrameCount; +	LLViewerJoystick::getInstance()->init(); +	if (LLViewerJoystick::getInstance()->isLikeSpaceNavigator()) +	{ +		if (gSavedSettings.getString("JoystickInitialized") != "SpaceNavigator") +		{ +			LLFloaterJoystick::setSNDefaults(); +			gSavedSettings.setString("JoystickInitialized", "SpaceNavigator"); +		} +	} +	  	return true;  } @@ -880,7 +891,9 @@ bool LLAppViewer::mainLoop()  	LLMemType mt1(LLMemType::MTYPE_MAIN);  	LLTimer frameTimer,idleTimer;  	LLTimer debugTime; -	 +	LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); +	joystick->setNeedsReset(true); + 	  	// Handle messages  	while (!LLApp::isExiting())  	{ @@ -921,8 +934,8 @@ bool LLAppViewer::mainLoop()  					&& !gViewerWindow->getShowProgress()  					&& !gFocusMgr.focusLocked())  				{ +					joystick->scanJoystick();  					gKeyboard->scanKeyboard(); -					LLViewerJoystick::scanJoystick();  				}  				// Update state based on messages, user input, object idle. @@ -3217,13 +3230,18 @@ void LLAppViewer::idle()  	}  	stop_glerror(); -	if (!LLViewerJoystick::sOverrideCamera) +	if (LLViewerJoystick::sOverrideCamera)  	{ -		gAgent.updateCamera(); +		LLViewerJoystick::getInstance()->moveFlycam();  	}  	else  	{ -		LLViewerJoystick::updateCamera(); +		if (LLToolMgr::getInstance()->inBuildMode()) +		{ +			LLViewerJoystick::getInstance()->moveObjects(); +		} + +		gAgent.updateCamera();  	}  	// objects and camera should be in sync, do LOD calculations now diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp new file mode 100644 index 0000000000..44abdd3cde --- /dev/null +++ b/indra/newview/llfloaterjoystick.cpp @@ -0,0 +1,333 @@ +/**  + * @file llfloaterjoystick.cpp + * @brief Joystick preferences panel + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + *  + * Copyright (c) 2007-2008, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// file include +#include "llfloaterjoystick.h" + +// linden library includes +#include "llerror.h" +#include "llrect.h" +#include "llstring.h" + +// project includes +#include "lluictrlfactory.h" +#include "llviewercontrol.h" +#include "llappviewer.h" +#include "llviewerjoystick.h" + +LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) +	: LLFloater("floater_joystick") +{ +	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_joystick.xml"); +	center(); +} + +void LLFloaterJoystick::draw() +{ +	LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); +	for (U32 i = 0; i < 6; i++) +	{ +		F32 value = joystick->getJoystickAxis(i); +		mAxisStats[i]->addValue(value * gFrameIntervalSeconds); +		 +		if (mAxisStatsBar[i]->mMinBar > value) +		{ +			mAxisStatsBar[i]->mMinBar = value; +		} +		if (mAxisStatsBar[i]->mMaxBar < value) +		{ +			mAxisStatsBar[i]->mMaxBar = value; +		} +	} + +	LLFloater::draw(); +} + +BOOL LLFloaterJoystick::postBuild() +{		 +	F32 range = gSavedSettings.getBOOL("Cursor3D") ? 1024.f : 2.f; +	LLUIString axis = getUIString("Axis"); +	LLUIString joystick = getUIString("JoystickMonitor"); + +	// use this child to get relative positioning info; we'll place the +	// joystick monitor on its right, vertically aligned to it. +	LLView* child = getChild<LLView>("FlycamAxisScale1"); +	LLRect rect; + +	if (child) +	{ +		LLRect r = child->getRect(); +		LLRect f = getRect(); +		rect = LLRect(350, r.mTop, r.mRight + 200, 0); +	} + +	mAxisStatsView = new LLStatView("axis values", joystick, "", rect); +	mAxisStatsView->setDisplayChildren(TRUE); + +	for (U32 i = 0; i < 6; i++) +	{ +		axis.setArg("[NUM]", llformat("%d", i)); +		mAxisStats[i] = new LLStat(4); +		mAxisStatsBar[i] = mAxisStatsView->addStat(axis, mAxisStats[i]); +		mAxisStatsBar[i]->mMinBar = -range; +		mAxisStatsBar[i]->mMaxBar = range; +		mAxisStatsBar[i]->mLabelSpacing = range * 0.5f; +		mAxisStatsBar[i]->mTickSpacing = range * 0.25f;			 +	} + +	addChild(mAxisStatsView); +	 +	childSetAction("SpaceNavigatorDefaults", onClickRestoreSNDefaults, this); +	refresh(); +	return TRUE; +} + +LLFloaterJoystick::~LLFloaterJoystick() +{ +	// Children all cleaned up by default view destructor. +} + + +void LLFloaterJoystick::apply() +{ +} + +void LLFloaterJoystick::refresh() +{ +	LLFloater::refresh(); + +	mJoystickAxis[0] = gSavedSettings.getS32("JoystickAxis0"); +	mJoystickAxis[1] = gSavedSettings.getS32("JoystickAxis1"); +	mJoystickAxis[2] = gSavedSettings.getS32("JoystickAxis2"); +	mJoystickAxis[3] = gSavedSettings.getS32("JoystickAxis3"); +	mJoystickAxis[4] = gSavedSettings.getS32("JoystickAxis4"); +	mJoystickAxis[5] = gSavedSettings.getS32("JoystickAxis5"); +	mJoystickAxis[6] = gSavedSettings.getS32("JoystickAxis6"); +	 +	m3DCursor = gSavedSettings.getBOOL("Cursor3D"); +	mAutoLeveling = gSavedSettings.getBOOL("AutoLeveling"); +	mZoomDirect  = gSavedSettings.getBOOL("ZoomDirect"); + +	mAvatarAxisScale[0] = gSavedSettings.getF32("AvatarAxisScale0"); +	mAvatarAxisScale[1] = gSavedSettings.getF32("AvatarAxisScale1"); +	mAvatarAxisScale[2] = gSavedSettings.getF32("AvatarAxisScale2"); +	mAvatarAxisScale[3] = gSavedSettings.getF32("AvatarAxisScale3"); +	mAvatarAxisScale[4] = gSavedSettings.getF32("AvatarAxisScale4"); +	mAvatarAxisScale[5] = gSavedSettings.getF32("AvatarAxisScale5"); + +	mBuildAxisScale[0] = gSavedSettings.getF32("BuildAxisScale0"); +	mBuildAxisScale[1] = gSavedSettings.getF32("BuildAxisScale1"); +	mBuildAxisScale[2] = gSavedSettings.getF32("BuildAxisScale2"); +	mBuildAxisScale[3] = gSavedSettings.getF32("BuildAxisScale3"); +	mBuildAxisScale[4] = gSavedSettings.getF32("BuildAxisScale4"); +	mBuildAxisScale[5] = gSavedSettings.getF32("BuildAxisScale5"); + +	mFlycamAxisScale[0] = gSavedSettings.getF32("FlycamAxisScale0"); +	mFlycamAxisScale[1] = gSavedSettings.getF32("FlycamAxisScale1"); +	mFlycamAxisScale[2] = gSavedSettings.getF32("FlycamAxisScale2"); +	mFlycamAxisScale[3] = gSavedSettings.getF32("FlycamAxisScale3"); +	mFlycamAxisScale[4] = gSavedSettings.getF32("FlycamAxisScale4"); +	mFlycamAxisScale[5] = gSavedSettings.getF32("FlycamAxisScale5"); +	mFlycamAxisScale[6] = gSavedSettings.getF32("FlycamAxisScale6"); + +	mAvatarAxisDeadZone[0] = gSavedSettings.getF32("AvatarAxisDeadZone0"); +	mAvatarAxisDeadZone[1] = gSavedSettings.getF32("AvatarAxisDeadZone1"); +	mAvatarAxisDeadZone[2] = gSavedSettings.getF32("AvatarAxisDeadZone2"); +	mAvatarAxisDeadZone[3] = gSavedSettings.getF32("AvatarAxisDeadZone3"); +	mAvatarAxisDeadZone[4] = gSavedSettings.getF32("AvatarAxisDeadZone4"); +	mAvatarAxisDeadZone[5] = gSavedSettings.getF32("AvatarAxisDeadZone5"); + +	mBuildAxisDeadZone[0] = gSavedSettings.getF32("BuildAxisDeadZone0"); +	mBuildAxisDeadZone[1] = gSavedSettings.getF32("BuildAxisDeadZone1"); +	mBuildAxisDeadZone[2] = gSavedSettings.getF32("BuildAxisDeadZone2"); +	mBuildAxisDeadZone[3] = gSavedSettings.getF32("BuildAxisDeadZone3"); +	mBuildAxisDeadZone[4] = gSavedSettings.getF32("BuildAxisDeadZone4"); +	mBuildAxisDeadZone[5] = gSavedSettings.getF32("BuildAxisDeadZone5"); + +	mFlycamAxisDeadZone[0] = gSavedSettings.getF32("FlycamAxisDeadZone0"); +	mFlycamAxisDeadZone[1] = gSavedSettings.getF32("FlycamAxisDeadZone1"); +	mFlycamAxisDeadZone[2] = gSavedSettings.getF32("FlycamAxisDeadZone2"); +	mFlycamAxisDeadZone[3] = gSavedSettings.getF32("FlycamAxisDeadZone3"); +	mFlycamAxisDeadZone[4] = gSavedSettings.getF32("FlycamAxisDeadZone4"); +	mFlycamAxisDeadZone[5] = gSavedSettings.getF32("FlycamAxisDeadZone5"); +	mFlycamAxisDeadZone[6] = gSavedSettings.getF32("FlycamAxisDeadZone6"); + +	mAvatarFeathering = gSavedSettings.getF32("AvatarFeathering"); +	mBuildFeathering = gSavedSettings.getF32("BuildFeathering"); +	mFlycamFeathering = gSavedSettings.getF32("FlycamFeathering"); +} + +void LLFloaterJoystick::cancel() +{ +	llinfos << "reading from gSavedSettings->Cursor3D="  +		<< gSavedSettings.getBOOL("Cursor3D") << "; m3DCursor="  +		<< m3DCursor << llendl; + +	gSavedSettings.setS32("JoystickAxis0", mJoystickAxis[0]); +	gSavedSettings.setS32("JoystickAxis1", mJoystickAxis[1]); +	gSavedSettings.setS32("JoystickAxis2", mJoystickAxis[2]); +	gSavedSettings.setS32("JoystickAxis3", mJoystickAxis[3]); +	gSavedSettings.setS32("JoystickAxis4", mJoystickAxis[4]); +	gSavedSettings.setS32("JoystickAxis5", mJoystickAxis[5]); +	gSavedSettings.setS32("JoystickAxis6", mJoystickAxis[6]); + +	gSavedSettings.setBOOL("Cursor3D", m3DCursor); +	gSavedSettings.setBOOL("AutoLeveling", mAutoLeveling); +	gSavedSettings.setBOOL("ZoomDirect", mZoomDirect ); + +	gSavedSettings.setF32("AvatarAxisScale0", mAvatarAxisScale[0]); +	gSavedSettings.setF32("AvatarAxisScale1", mAvatarAxisScale[1]); +	gSavedSettings.setF32("AvatarAxisScale2", mAvatarAxisScale[2]); +	gSavedSettings.setF32("AvatarAxisScale3", mAvatarAxisScale[3]); +	gSavedSettings.setF32("AvatarAxisScale4", mAvatarAxisScale[4]); +	gSavedSettings.setF32("AvatarAxisScale5", mAvatarAxisScale[5]); + +	gSavedSettings.setF32("BuildAxisScale0", mBuildAxisScale[0]); +	gSavedSettings.setF32("BuildAxisScale1", mBuildAxisScale[1]); +	gSavedSettings.setF32("BuildAxisScale2", mBuildAxisScale[2]); +	gSavedSettings.setF32("BuildAxisScale3", mBuildAxisScale[3]); +	gSavedSettings.setF32("BuildAxisScale4", mBuildAxisScale[4]); +	gSavedSettings.setF32("BuildAxisScale5", mBuildAxisScale[5]); + +	gSavedSettings.setF32("FlycamAxisScale0", mFlycamAxisScale[0]); +	gSavedSettings.setF32("FlycamAxisScale1", mFlycamAxisScale[1]); +	gSavedSettings.setF32("FlycamAxisScale2", mFlycamAxisScale[2]); +	gSavedSettings.setF32("FlycamAxisScale3", mFlycamAxisScale[3]); +	gSavedSettings.setF32("FlycamAxisScale4", mFlycamAxisScale[4]); +	gSavedSettings.setF32("FlycamAxisScale5", mFlycamAxisScale[5]); +	gSavedSettings.setF32("FlycamAxisScale6", mFlycamAxisScale[6]); + +	gSavedSettings.setF32("AvatarAxisDeadZone0", mAvatarAxisDeadZone[0]); +	gSavedSettings.setF32("AvatarAxisDeadZone1", mAvatarAxisDeadZone[1]); +	gSavedSettings.setF32("AvatarAxisDeadZone2", mAvatarAxisDeadZone[2]); +	gSavedSettings.setF32("AvatarAxisDeadZone3", mAvatarAxisDeadZone[3]); +	gSavedSettings.setF32("AvatarAxisDeadZone4", mAvatarAxisDeadZone[4]); +	gSavedSettings.setF32("AvatarAxisDeadZone5", mAvatarAxisDeadZone[5]); + +	gSavedSettings.setF32("BuildAxisDeadZone0", mBuildAxisDeadZone[0]); +	gSavedSettings.setF32("BuildAxisDeadZone1", mBuildAxisDeadZone[1]); +	gSavedSettings.setF32("BuildAxisDeadZone2", mBuildAxisDeadZone[2]); +	gSavedSettings.setF32("BuildAxisDeadZone3", mBuildAxisDeadZone[3]); +	gSavedSettings.setF32("BuildAxisDeadZone4", mBuildAxisDeadZone[4]); +	gSavedSettings.setF32("BuildAxisDeadZone5", mBuildAxisDeadZone[5]); + +	gSavedSettings.setF32("FlycamAxisDeadZone0", mFlycamAxisDeadZone[0]); +	gSavedSettings.setF32("FlycamAxisDeadZone1", mFlycamAxisDeadZone[1]); +	gSavedSettings.setF32("FlycamAxisDeadZone2", mFlycamAxisDeadZone[2]); +	gSavedSettings.setF32("FlycamAxisDeadZone3", mFlycamAxisDeadZone[3]); +	gSavedSettings.setF32("FlycamAxisDeadZone4", mFlycamAxisDeadZone[4]); +	gSavedSettings.setF32("FlycamAxisDeadZone5", mFlycamAxisDeadZone[5]); +	gSavedSettings.setF32("FlycamAxisDeadZone6", mFlycamAxisDeadZone[6]); + +	gSavedSettings.setF32("AvatarFeathering", mAvatarFeathering); +	gSavedSettings.setF32("BuildFeathering", mBuildFeathering); +	gSavedSettings.setF32("FlycamFeathering", mFlycamFeathering); +} + +void LLFloaterJoystick::onClickRestoreSNDefaults(void *joy_panel) +{ +	setSNDefaults(); +} + +void LLFloaterJoystick::setSNDefaults() +{ +#if LL_DARWIN  +#define kPlatformScale	20.f +#else +#define kPlatformScale	1.f +#endif +	 +	//gViewerWindow->alertXml("CacheWillClear"); +	llinfos << "restoring SpaceNavigator defaults..." << llendl; +	 +	gSavedSettings.setS32("JoystickAxis1", 0); // x (slide) +	gSavedSettings.setS32("JoystickAxis2", 2); // y (up) +	gSavedSettings.setS32("JoystickAxis0", 1); // z (at) +	gSavedSettings.setS32("JoystickAxis4", 3); // roll  +	gSavedSettings.setS32("JoystickAxis5", 5); // yaw +	gSavedSettings.setS32("JoystickAxis3", 4); // pitch +	gSavedSettings.setS32("JoystickAxis6", -1); +	 +#if LL_DARWIN +	// The SpaceNavigator doesn't act as a 3D cursor on OS X.  +	gSavedSettings.setBOOL("Cursor3D", false); +#else +	gSavedSettings.setBOOL("Cursor3D", true); +#endif +	gSavedSettings.setBOOL("AutoLeveling", true); +	gSavedSettings.setBOOL("ZoomDirect", false); +	 +	gSavedSettings.setF32("AvatarAxisScale0", 1.f); +	gSavedSettings.setF32("AvatarAxisScale1", 1.f); +	gSavedSettings.setF32("AvatarAxisScale2", 1.f); +	gSavedSettings.setF32("AvatarAxisScale4", .1f * kPlatformScale); +	gSavedSettings.setF32("AvatarAxisScale5", .1f * kPlatformScale); +	gSavedSettings.setF32("AvatarAxisScale3", 0.f * kPlatformScale); +	gSavedSettings.setF32("BuildAxisScale1", .3f * kPlatformScale); +	gSavedSettings.setF32("BuildAxisScale2", .3f * kPlatformScale); +	gSavedSettings.setF32("BuildAxisScale0", .3f * kPlatformScale); +	gSavedSettings.setF32("BuildAxisScale4", .3f * kPlatformScale); +	gSavedSettings.setF32("BuildAxisScale5", .3f * kPlatformScale); +	gSavedSettings.setF32("BuildAxisScale3", .3f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale1", 2.f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale2", 2.f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale0", 2.1f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale4", .1f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale5", .15f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale3", 0.f * kPlatformScale); +	gSavedSettings.setF32("FlycamAxisScale6", 0.f * kPlatformScale); +	 +	gSavedSettings.setF32("AvatarAxisDeadZone0", .1f); +	gSavedSettings.setF32("AvatarAxisDeadZone1", .1f); +	gSavedSettings.setF32("AvatarAxisDeadZone2", .1f); +	gSavedSettings.setF32("AvatarAxisDeadZone3", 1.f); +	gSavedSettings.setF32("AvatarAxisDeadZone4", .02f); +	gSavedSettings.setF32("AvatarAxisDeadZone5", .01f); +	gSavedSettings.setF32("BuildAxisDeadZone0", .01f); +	gSavedSettings.setF32("BuildAxisDeadZone1", .01f); +	gSavedSettings.setF32("BuildAxisDeadZone2", .01f); +	gSavedSettings.setF32("BuildAxisDeadZone3", .01f); +	gSavedSettings.setF32("BuildAxisDeadZone4", .01f); +	gSavedSettings.setF32("BuildAxisDeadZone5", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone0", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone1", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone2", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone3", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone4", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone5", .01f); +	gSavedSettings.setF32("FlycamAxisDeadZone6", 1.f); +	 +	gSavedSettings.setF32("AvatarFeathering", 6.f); +	gSavedSettings.setF32("BuildFeathering", 12.f); +	gSavedSettings.setF32("FlycamFeathering", 5.f); +} diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h new file mode 100644 index 0000000000..6dc40704f0 --- /dev/null +++ b/indra/newview/llfloaterjoystick.h @@ -0,0 +1,78 @@ +/**  + * @file llfloaterjoystick.h + * @brief Joystick preferences panel + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + *  + * Copyright (c) 2007-2008, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERJOYSTICK_H +#define LL_LLFLOATERJOYSTICK_H + +#include "llfloater.h" +#include "llstatview.h" + +class LLFloaterJoystick : public LLFloater, public LLFloaterSingleton<LLFloaterJoystick > +{ +public: +	LLFloaterJoystick(const LLSD& data); +	virtual ~LLFloaterJoystick(); + +	virtual BOOL postBuild(); +	virtual void refresh(); +	virtual void apply();	// Apply the changed values. +	virtual void cancel();	// Cancel the changed values. +	virtual void draw(); +	static  void setSNDefaults(); + +private: +	static void onClickRestoreSNDefaults(void*); + +private: +	// Device prefs +	S32 mJoystickAxis[7]; +	bool m3DCursor; +	bool mAutoLeveling; +	bool mZoomDirect; + +	// Modes prefs +	F32 mAvatarAxisScale[6]; +	F32 mBuildAxisScale[6]; +	F32 mFlycamAxisScale[7]; +	F32 mAvatarAxisDeadZone[6]; +	F32 mBuildAxisDeadZone[6]; +	F32 mFlycamAxisDeadZone[7]; +	F32 mAvatarFeathering; +	F32 mBuildFeathering; +	F32 mFlycamFeathering; + +	// stats view  +	LLStatView*		mAxisStatsView; +	LLStat*			mAxisStats[6]; +	LLStatBar*		mAxisStatsBar[6]; +}; + +#endif diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 7777544a4c..0e58363de5 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -75,7 +75,7 @@  #include "llviewerparcelmgr.h"  #include "llviewerwindow.h"  #include "llviewercontrol.h" - +#include "llviewerjoystick.h"  #include "lluictrlfactory.h"  // Globals @@ -770,6 +770,8 @@ void LLFloaterTools::onClose(bool app_quitting)  	setVisible(FALSE);  	mTab->setVisible(FALSE); +	LLViewerJoystick::getInstance()->moveAvatar(true); +      // Different from handle_reset_view in that it doesn't actually   	//   move the camera if EditCameraMovement is not set.  	gAgent.resetView(gSavedSettings.getBOOL("EditCameraMovement")); diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index af682508c9..887db4cf95 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -255,7 +255,7 @@ BOOL LLManip::getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector  	return result;  } -BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) +BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) const  {  	if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)  	{ diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h index 2dd0eab8b0..a2ad464f3c 100644 --- a/indra/newview/llmanip.h +++ b/indra/newview/llmanip.h @@ -146,7 +146,7 @@ protected:  	void				renderTickValue(const LLVector3& pos, F32 value, const char* suffix, const LLColor4 &color);  	void				renderTickText(const LLVector3& pos, const char* suffix, const LLColor4 &color);  	void				updateGridSettings(); -	BOOL				getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal); +	BOOL				getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) const;  	BOOL				getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal);  	BOOL				nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param );  	LLColor4			setupSnapGuideRenderPass(S32 pass); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index c2dfd779a3..cd59c8e300 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6241,4 +6241,199 @@ LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent)  	return getFirstSelectedObject(&func, get_parent);  } +//----------------------------------------------------------------------------- +// Position + Rotation update methods called from LLViewerJoystick +//----------------------------------------------------------------------------- +bool LLSelectMgr::selectionMove(const LLVector3& displ, +                                  F32 roll, F32 pitch, F32 yaw, U32 update_type) +{ +	if (update_type == UPD_NONE) +	{ +		return false; +	} +	 +	LLVector3 displ_global; +	bool update_success = true; +	bool update_position = update_type & UPD_POSITION; +	bool update_rotation = update_type & UPD_ROTATION; +	const bool noedit_linked_parts = !gSavedSettings.getBOOL("EditLinkedParts"); +	 +	if (update_position) +	{ +		// calculate the distance of the object closest to the camera origin +		F32 min_dist = 1e+30f; +		LLVector3 obj_pos; +		for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); +			 it != getSelection()->root_end(); ++it) +		{ +			obj_pos = (*it)->getObject()->getPositionEdit(); +			 +			F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin()); +			if (obj_dist < min_dist) +			{ +				min_dist = obj_dist; +			} +		} +		 +		// factor the distance inside the displacement vector. This will get us +		// equally visible movements for both close and far away selections. +		min_dist = sqrt(min_dist) / 2; +		displ_global.setVec(displ.mV[0]*min_dist,  +							displ.mV[1]*min_dist,  +							displ.mV[2]*min_dist); + +		// equates to: Displ_global = Displ * M_cam_axes_in_global_frame +		displ_global = LLViewerCamera::getInstance()->rotateToAbsolute(displ_global); +	} + +	LLQuaternion new_rot; +	if (update_rotation) +	{ +		// let's calculate the rotation around each camera axes  +		LLQuaternion qx(roll, LLViewerCamera::getInstance()->getAtAxis()); +		LLQuaternion qy(pitch, LLViewerCamera::getInstance()->getLeftAxis()); +		LLQuaternion qz(yaw, LLViewerCamera::getInstance()->getUpAxis()); +		new_rot.setQuat(qx * qy * qz); +	} +	 +	LLViewerObject *obj; +	S32 obj_count = getSelection()->getObjectCount(); +	for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); +		 it != getSelection()->root_end(); ++it ) +	{ +		obj = (*it)->getObject(); +		bool enable_pos = false, enable_rot = false; +		bool perm_move = obj->permMove(); +		bool perm_mod = obj->permModify(); +		 +		LLVector3d sel_center(getSelectionCenterGlobal()); +		 +		if (update_rotation) +		{ +			enable_rot = perm_move  +				&& ((perm_mod && !obj->isAttachment()) || noedit_linked_parts); + +			if (enable_rot) +			{ +				int children_count = obj->getChildren().size(); +				if (obj_count > 1 && children_count > 0) +				{ +					// for linked sets, rotate around the group center +					const LLVector3 t(obj->getPositionGlobal() - sel_center); + +					// Ra = T x R x T^-1 +					LLMatrix4 mt;	mt.setTranslation(t); +					const LLMatrix4 mnew_rot(new_rot); +					LLMatrix4 mt_1;	mt_1.setTranslation(-t); +					mt *= mnew_rot; +					mt *= mt_1; +					 +					// Rfin = Rcur * Ra +					obj->setRotation(obj->getRotationEdit() * mt.quaternion()); +					displ_global += mt.getTranslation(); +				} +				else +				{ +					obj->setRotation(obj->getRotationEdit() * new_rot); +				} +			} +			else +			{ +				update_success = false; +			} +		} + +		if (update_position) +		{ +			// establish if object can be moved or not +			enable_pos = perm_move && !obj->isAttachment()  +			&& (perm_mod || noedit_linked_parts); +			 +			if (enable_pos) +			{ +				obj->setPosition(obj->getPositionEdit() + displ_global); +			} +			else +			{ +				update_success = false; +			} +		} +		 +		if (enable_pos && enable_rot && obj->mDrawable.notNull()) +		{ +			gPipeline.markMoved(obj->mDrawable, TRUE); +		} +	} +	 +	if (update_position && update_success && obj_count > 1) +	{ +		updateSelectionCenter(); +	} +	 +	return update_success; +} + +void LLSelectMgr::sendSelectionMove() +{ +	LLSelectNode *node = mSelectedObjects->getFirstRootNode(); +	if (node == NULL) +	{ +		return; +	} +	 +	//saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); +	 +	U32 update_type = UPD_POSITION | UPD_ROTATION; +	LLViewerRegion *last_region, *curr_region = node->getObject()->getRegion(); +	S32 objects_in_this_packet = 0; + +	// apply to linked objects if unable to select their individual parts  +	if (!gSavedSettings.getBOOL("EditLinkedParts") && !getTEMode()) +	{ +		// tell simulator to apply to whole linked sets +		update_type |= UPD_LINKED_SETS; +	} + +	// prepare first bulk message +	gMessageSystem->newMessage("MultipleObjectUpdate"); +	packAgentAndSessionID(&update_type); + +	LLViewerObject *obj = NULL; +	for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); +		 it != getSelection()->root_end(); ++it) +	{ +		obj = (*it)->getObject(); + +		// note: following code adapted from sendListToRegions() (@3924) +		last_region = curr_region; +		curr_region = obj->getRegion(); +		// if not simulator or message too big +		if (curr_region != last_region +			|| gMessageSystem->isSendFull(NULL) +			|| objects_in_this_packet >= MAX_OBJECTS_PER_PACKET) +		{ +			// send sim the current message and start new one +			gMessageSystem->sendReliable(last_region->getHost()); +			objects_in_this_packet = 0; +			gMessageSystem->newMessage("MultipleObjectUpdate"); +			packAgentAndSessionID(&update_type); +		} + +		// add another instance of the body of data +		packMultipleUpdate(*it, &update_type); +		++objects_in_this_packet; +	} + +	// flush remaining messages +	if (gMessageSystem->getCurrentSendTotal() > 0) +	{ +		gMessageSystem->sendReliable(curr_region->getHost()); +	} +	else +	{ +		gMessageSystem->clearMessage(); +	} + +	//saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); +} diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 598a962b3c..4a8f99db1f 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -321,7 +321,7 @@ public:  	bool applyToRootNodes(LLSelectedNodeFunctor* func, bool firstonly = false);  	bool applyToNodes(LLSelectedNodeFunctor* func, bool firstonly = false); -	ESelectType getSelectType() { return mSelectType; } +	ESelectType getSelectType() const { return mSelectType; }  private:  	const LLObjectSelection &operator=(const LLObjectSelection &); @@ -516,6 +516,10 @@ public:  	void selectionResetRotation();				// sets rotation quat to identity  	void selectionRotateAroundZ(F32 degrees); +	bool selectionMove(const LLVector3& displ, F32 rx, F32 ry, F32 rz, +					   U32 update_type); +	void sendSelectionMove(); +  	void sendGodlikeRequest(const LLString& request, const LLString& parameter); diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 7865d8efe3..8d1faa850f 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -300,7 +300,7 @@ BOOL LLToolCompTranslate::handleDoubleClick(S32 x, S32 y, MASK mask)  void LLToolCompTranslate::render()  { -	mCur->render(); +	mCur->render(); // removing this will not draw the RGB arrows and guidelines  	if( mCur != mManip )  	{ diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index b20d4f9d28..a4c7856411 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -49,6 +49,8 @@  #include "lltoolselectland.h"  #include "lltoolobjpicker.h"  #include "lltoolpipette.h" +#include "llagent.h" +#include "llviewercontrol.h"  // Used when app not active to avoid processing hover. @@ -227,6 +229,19 @@ BOOL LLToolMgr::inEdit()  	return mBaseTool != LLToolPie::getInstance() && mBaseTool != gToolNull;  } +bool LLToolMgr::inBuildMode() +{ +	// when entering mouselook inEdit() immediately returns true before  +	// cameraMouselook() actually starts returning true.  Also, appearance edit +	// sets build mode to true, so let's exclude that. +	bool b=(inEdit()  +			&& gSavedSettings.getBOOL("BuildBtnState") +			&& !gAgent.cameraMouselook() +			&& mCurrentToolset != gFaceEditToolset); +	 +	return b; +} +  void LLToolMgr::setTransientTool(LLTool* tool)  {  	if (!tool) diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index 73b8a38c57..e4a4b80dcf 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -58,6 +58,9 @@ public:  	LLTool*			getBaseTool(); // returns active tool when overrides are deactivated  	BOOL			inEdit(); +	 +	/* Determines if we are in Build mode or not. */ +	bool			inBuildMode();  	void			setTransientTool(LLTool* tool);  	void			clearTransientTool(); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 8657f59ccb..a1a2c34222 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -47,6 +47,8 @@  #include "llviewerwindow.h"  #include "llvovolume.h"  #include "llworld.h" +#include "lltoolmgr.h" +#include "llviewerjoystick.h"  GLfloat gGLZFar;  GLfloat gGLZNear; @@ -97,6 +99,13 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er,  											const LLVector3 &up_direction,  											const LLVector3 &point_of_interest)  { +	// do not update if we are in build mode AND avatar didn't move +	if (LLToolMgr::getInstance()->inBuildMode()  +		&& !LLViewerJoystick::getInstance()->getCameraNeedsUpdate()) +	{ +		return; +	} +  	LLVector3 last_position;  	LLVector3 last_axis;  	last_position = getOrigin(); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 2e76fe33a3..d40073b3e7 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -253,7 +253,7 @@ static void handleAudioVolumeChanged(const LLSD& newvalue)  static bool handleJoystickChanged(const LLSD& newvalue)  { -	LLViewerJoystick::updateCamera(TRUE); +	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(TRUE);  	return true;  } @@ -493,13 +493,51 @@ void settings_setup_listeners()  	gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _1));  	gSavedSettings.getControl("RenderLightingDetail")->getSignal()->connect(boost::bind(&handleRenderLightingDetailChanged, _1));  	gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _1)); -	gSavedSettings.getControl("FlycamAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); -	gSavedSettings.getControl("FlycamAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); -	gSavedSettings.getControl("FlycamAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); -	gSavedSettings.getControl("FlycamAxis3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); -	gSavedSettings.getControl("FlycamAxis4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); -	gSavedSettings.getControl("FlycamAxis5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); -	gSavedSettings.getControl("FlycamAxis6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("JoystickAxis6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisScale6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("FlycamAxisDeadZone6")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("AvatarAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisScale0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisScale1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisScale2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisScale3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisScale4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisScale5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisDeadZone0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisDeadZone1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisDeadZone2")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisDeadZone3")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisDeadZone4")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); +	gSavedSettings.getControl("BuildAxisDeadZone5")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1));      gSavedSettings.getControl("DebugViews")->getSignal()->connect(boost::bind(&handleDebugViewsChanged, _1));      gSavedSettings.getControl("UserLogFile")->getSignal()->connect(boost::bind(&handleLogFileChanged, _1));  	gSavedSettings.getControl("RenderHideGroupTitle")->getSignal()->connect(boost::bind(handleHideGroupTitleChanged, _1)); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index a8e898999a..cd4eddb5e1 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -1,6 +1,6 @@  /**    * @file llviewerjoystick.cpp - * @brief Joystick functionality. + * @brief Joystick / NDOF device functionality.   *   * $LicenseInfo:firstyear=2002&license=viewergpl$   *  @@ -30,39 +30,661 @@   */  #include "llviewerprecompiledheaders.h" + +#include "llviewerjoystick.h" +  #include "llviewercontrol.h"  #include "llviewerwindow.h"  #include "llviewercamera.h" -#include "llviewerjoystick.h"  #include "llappviewer.h"  #include "llkeyboard.h" +#include "lltoolmgr.h" +#include "llselectmgr.h" +#include "llviewermenu.h" +#include "llagent.h" +#include "llfocusmgr.h" + + +// ---------------------------------------------------------------------------- +// Constants + +#define  X_I	1 +#define  Y_I	2 +#define  Z_I	0 +#define RX_I	4 +#define RY_I	5 +#define RZ_I	3 + +// flycam translations in build mode should be reduced +const F32 BUILDMODE_FLYCAM_T_SCALE = 3.f; + +bool LLViewerJoystick::sOverrideCamera = false; +F32  LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0}; +F32  LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; + +// These constants specify the maximum absolute value coming in from the device. +// HACK ALERT! the value of MAX_JOYSTICK_INPUT_VALUE is not arbitrary as it  +// should be.  It has to be equal to 3000 because the SpaceNavigator on Windows  +// refuses to respond to the DirectInput SetProperty call; it always returns  +// values in the [-3000, 3000] range. +#define MAX_SPACENAVIGATOR_INPUT  3000.0f +#define MAX_JOYSTICK_INPUT_VALUE  MAX_SPACENAVIGATOR_INPUT + +// ----------------------------------------------------------------------------- +#if LIB_NDOF +NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev) +{ +	LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); +	if (joystick->mDriverState == JDS_UNINITIALIZED) +	{ +        llinfos << "HotPlugAddCallback: will use device:" << llendl; +		ndof_dump(dev); +		joystick->mNdofDev = dev; +        joystick->mDriverState = JDS_INITIALIZED; +        return NDOF_KEEP_HOTPLUGGED; +	} +    return NDOF_DISCARD_HOTPLUGGED; +} +#endif + +// ----------------------------------------------------------------------------- +#if LIB_NDOF +void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev) +{ +	LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); +	if (joystick->mNdofDev == dev) +	{ +        llinfos << "HotPlugRemovalCallback: joystick->mNdofDev="  +				<< joystick->mNdofDev << "; removed device:" << llendl; +		ndof_dump(dev); +		joystick->mDriverState = JDS_UNINITIALIZED; +	} +} +#endif + +// ----------------------------------------------------------------------------- +LLViewerJoystick::LLViewerJoystick() +:	mDriverState(JDS_UNINITIALIZED), +	mNdofDev(NULL), +	mResetFlag(false), +	mCameraUpdated(true) +{ +	for (int i = 0; i < 6; i++) +	{ +		mAxes[i] = sDelta[i] = sLastDelta[i] = 0.0f; +	} +	 +	memset(mBtn, 0, sizeof(mBtn)); + +	// factor in bandwidth? bandwidth = gViewerStats->mKBitStat +	mPerfScale = 4000.f / gSysCPU.getMhz(); +} + +// ----------------------------------------------------------------------------- +LLViewerJoystick::~LLViewerJoystick() +{ +	if (mDriverState == JDS_INITIALIZED) +	{ +		terminate(); +	} +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::init() +{ +#if LIB_NDOF +	static bool libinit = false; +	mDriverState = JDS_INITIALIZING; + +	if (libinit == false) +	{ +		if (ndof_libinit(HotPlugAddCallback,  +						 HotPlugRemovalCallback,  +						 NULL)) +		{ +			mDriverState = JDS_UNINITIALIZED; +		} +		else +		{ +			// NB: ndof_libinit succeeds when there's no device +			libinit = true; + +			// allocate memory once for an eventual device +			mNdofDev = ndof_create(); +		} +	} + +	if (libinit) +	{ +		if (mNdofDev) +		{ +			// Different joysticks will return different ranges of raw values. +			// Since we want to handle every device in the same uniform way,  +			// we initialize the mNdofDev struct and we set the range  +			// of values we would like to receive.  +			//  +			// HACK: On Windows, libndofdev passes our range to DI with a  +			// SetProperty call. This works but with one notable exception, the +			// SpaceNavigator, who doesn't seem to care about the SetProperty +			// call. In theory, we should handle this case inside libndofdev.  +			// However, the range we're setting here is arbitrary anyway,  +			// so let's just use the SpaceNavigator range for our purposes.  +			mNdofDev->axes_min = (long)-MAX_JOYSTICK_INPUT_VALUE; +			mNdofDev->axes_max = (long)+MAX_JOYSTICK_INPUT_VALUE; + +			// libndofdev could be used to return deltas.  Here we choose to +			// just have the absolute values instead. +			mNdofDev->absolute = 1; + +			// init & use the first suitable NDOF device found on the USB chain +			if (ndof_init_first(mNdofDev, NULL)) +			{ +				mDriverState = JDS_UNINITIALIZED; +				llwarns << "ndof_init_first FAILED" << llendl; +			} +			else +			{ +				mDriverState = JDS_INITIALIZED; +			} +		} +		else +		{ +			mDriverState = JDS_UNINITIALIZED; +		} +	} + +	llinfos << "ndof: mDriverState=" << mDriverState << "; mNdofDev="  +			<< mNdofDev << "; libinit=" << libinit << llendl; +#endif +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::terminate() +{ +#if LIB_NDOF + +	ndof_libcleanup(); +	llinfos << "Terminated connection with NDOF device." << llendl; + +#endif +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::updateStatus() +{ +#if LIB_NDOF + +	ndof_update(mNdofDev); + +	for (int i=0; i<6; i++) +	{ +		mAxes[i] = (F32) mNdofDev->axes[i] / mNdofDev->axes_max; +	} + +	for (int i=0; i<16; i++) +	{ +		mBtn[i] = mNdofDev->buttons[i]; +	} +	 +#endif +} + +// ----------------------------------------------------------------------------- +F32 LLViewerJoystick::getJoystickAxis(U32 axis) const +{ +	if (axis < 6) +	{ +		return mAxes[axis]; +	} +	return 0.f; +} + +// ----------------------------------------------------------------------------- +U32 LLViewerJoystick::getJoystickButton(U32 button) const +{ +	if (button < 16) +	{ +		return mBtn[button]; +	} +	return 0; +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::agentJump() +{ +    gAgent.moveUp(1); +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::agentSlide(F32 inc) +{ +	if (inc < 0) +	{ +		gAgent.moveLeft(1); +	} +	else if (inc > 0) +	{ +		gAgent.moveLeft(-1); +	} +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::agentPush(F32 inc) +{ +	if (inc < 0)                            // forward +	{ +		gAgent.moveAt(1, false); +	} +	else if (inc > 0)                       // backward +	{ +		gAgent.moveAt(-1, false); +	} +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::agentFly(F32 inc) +{ +	if (inc < 0) +	{ +		if (gAgent.getFlying()) +		{ +			gAgent.moveUp(1); +		} +		else +		{ +			gAgent.setFlying(true); +		} +	} +	else if (inc > 0) +	{ +		// crouch +		gAgent.moveUp(-1); +	} +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::agentRotate(F32 pitch_inc, F32 yaw_inc) +{ +	LLQuaternion new_rot; +	pitch_inc = gAgent.clampPitchToLimits(-pitch_inc); +	const LLQuaternion qx(pitch_inc, gAgent.getLeftAxis()); +	const LLQuaternion qy(-yaw_inc, gAgent.getReferenceUpVector()); +	new_rot.setQuat(qx * qy); +	gAgent.rotate(new_rot); +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::resetDeltas(S32 axis[], bool flycam_and_build_mode) +{ +	for (U32 i = 0; i < 6; i++) +	{ +		sLastDelta[i] = -mAxes[axis[i]]; +		sDelta[i] = 0.f; +	} + +	if (flycam_and_build_mode) +	{ +		sLastDelta[X_I] /= BUILDMODE_FLYCAM_T_SCALE; +		sLastDelta[Y_I] /= BUILDMODE_FLYCAM_T_SCALE; +		sLastDelta[Z_I] /= BUILDMODE_FLYCAM_T_SCALE; +	} + +	sLastDelta[6] = sDelta[6] = 0.f; +	mResetFlag = false; +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::moveObjects(bool reset) +{ +	static bool toggle_send_to_sim = false; + +	if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED) +	{ +		return; +	} + +	S32 axis[] =  +	{ +		gSavedSettings.getS32("JoystickAxis0"), +		gSavedSettings.getS32("JoystickAxis1"), +		gSavedSettings.getS32("JoystickAxis2"), +		gSavedSettings.getS32("JoystickAxis3"), +		gSavedSettings.getS32("JoystickAxis4"), +		gSavedSettings.getS32("JoystickAxis5"), +	}; + +	if (reset || mResetFlag) +	{ +		resetDeltas(axis); +		return; +	} + +	F32 axis_scale[] = +	{ +		gSavedSettings.getF32("BuildAxisScale0"), +		gSavedSettings.getF32("BuildAxisScale1"), +		gSavedSettings.getF32("BuildAxisScale2"), +		gSavedSettings.getF32("BuildAxisScale3"), +		gSavedSettings.getF32("BuildAxisScale4"), +		gSavedSettings.getF32("BuildAxisScale5"), +	}; + +	F32 dead_zone[] = +	{ +		gSavedSettings.getF32("BuildAxisDeadZone0"), +		gSavedSettings.getF32("BuildAxisDeadZone1"), +		gSavedSettings.getF32("BuildAxisDeadZone2"), +		gSavedSettings.getF32("BuildAxisDeadZone3"), +		gSavedSettings.getF32("BuildAxisDeadZone4"), +		gSavedSettings.getF32("BuildAxisDeadZone5"), +	}; + +	F32 cur_delta[6]; +	F32 time = gFrameIntervalSeconds; + +	// avoid making ridicously big movements if there's a big drop in fps  +	if (time > .2f) +	{ +		time = .2f; +	} + +	// max feather is 32 +	F32 feather = gSavedSettings.getF32("BuildFeathering");  +	bool is_zero = true, absolute = gSavedSettings.getBOOL("Cursor3D"); +	 +	for (U32 i = 0; i < 6; i++) +	{ +		cur_delta[i] = -mAxes[axis[i]]; +		F32 tmp = cur_delta[i]; +		if (absolute) +		{ +			cur_delta[i] = cur_delta[i] - sLastDelta[i]; +		} +		sLastDelta[i] = tmp; +		is_zero = is_zero && (cur_delta[i] == 0.f); +			 +		if (cur_delta[i] > 0) +		{ +			cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f); +		} +		else +		{ +			cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f); +		} +		cur_delta[i] *= axis_scale[i]; +		 +		if (!absolute) +		{ +			cur_delta[i] *= time; +		} -static LLQuaternion sFlycamRotation; -static LLVector3 sFlycamPosition; -static F32		sFlycamZoom; +		sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather; +	} -BOOL  LLViewerJoystick::sOverrideCamera = FALSE; +	U32 upd_type = UPD_NONE; +	LLVector3 v; +     +	if (!is_zero) +	{ +		if (sDelta[0] || sDelta[1] || sDelta[2]) +		{ +			upd_type |= UPD_POSITION; +			v.setVec(sDelta[0], sDelta[1], sDelta[2]); +		} +		 +		if (sDelta[3] || sDelta[4] || sDelta[5]) +		{ +			upd_type |= UPD_ROTATION; +		} +				 +		// the selection update could fail, so we won't send  +		if (LLSelectMgr::getInstance()->selectionMove(v, sDelta[3],sDelta[4],sDelta[5], upd_type)) +		{ +			toggle_send_to_sim = true; +		} +	} +	else if (toggle_send_to_sim) +	{ +		LLSelectMgr::getInstance()->sendSelectionMove(); +		toggle_send_to_sim = false; +	} +} -void LLViewerJoystick::updateCamera(BOOL reset) +// ----------------------------------------------------------------------------- +void LLViewerJoystick::moveAvatar(bool reset)  { -	static F32 last_delta[] = {0,0,0,0,0,0,0}; -	static F32 delta[] = { 0,0,0,0,0,0,0 }; +	if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED) +	{ +		return; +	} + +	S32 axis[] =  +	{ +		// [1 0 2 4  3  5] +		// [Z X Y RZ RX RY] +		gSavedSettings.getS32("JoystickAxis0"), +		gSavedSettings.getS32("JoystickAxis1"), +		gSavedSettings.getS32("JoystickAxis2"), +		gSavedSettings.getS32("JoystickAxis3"), +		gSavedSettings.getS32("JoystickAxis4"), +		gSavedSettings.getS32("JoystickAxis5") +	}; + +	if (reset || mResetFlag) +	{ +		resetDeltas(axis); +		if (reset) +		{ +			// Note: moving the agent triggers agent camera mode; +			//  don't do this every time we set mResetFlag (e.g. because we gained focus) +			gAgent.moveAt(0, true); +		} +		return; +	} + +	if (mBtn[1] == 1) +    { +		agentJump(); +		return; +    } + +	F32 axis_scale[] = +	{ +		gSavedSettings.getF32("AvatarAxisScale0"), +		gSavedSettings.getF32("AvatarAxisScale1"), +		gSavedSettings.getF32("AvatarAxisScale2"), +		gSavedSettings.getF32("AvatarAxisScale3"), +		gSavedSettings.getF32("AvatarAxisScale4"), +		gSavedSettings.getF32("AvatarAxisScale5") +	}; -	LLWindow* window = gViewerWindow->getWindow(); +	F32 dead_zone[] = +	{ +		gSavedSettings.getF32("AvatarAxisDeadZone0"), +		gSavedSettings.getF32("AvatarAxisDeadZone1"), +		gSavedSettings.getF32("AvatarAxisDeadZone2"), +		gSavedSettings.getF32("AvatarAxisDeadZone3"), +		gSavedSettings.getF32("AvatarAxisDeadZone4"), +		gSavedSettings.getF32("AvatarAxisDeadZone5") +	}; +	// time interval in seconds between this frame and the previous  	F32 time = gFrameIntervalSeconds; +	// avoid making ridicously big movements if there's a big drop in fps  +	if (time > .2f) +	{ +		time = .2f; +	} + +	// note: max feather is 32.0 +	F32 feather = gSavedSettings.getF32("AvatarFeathering");  +	 +	F32 cur_delta[6]; +	F32 val, dom_mov = 0.f; +	U32 dom_axis = Z_I; +#if LIB_NDOF +    bool absolute = (gSavedSettings.getBOOL("Cursor3D") && mNdofDev->absolute); +#else +    bool absolute = false; +#endif +	// remove dead zones and determine biggest movement on the joystick  +	for (U32 i = 0; i < 6; i++) +	{ +		cur_delta[i] = -mAxes[axis[i]]; +		if (absolute) +		{ +			F32 tmp = cur_delta[i]; +			cur_delta[i] = cur_delta[i] - sLastDelta[i]; +			sLastDelta[i] = tmp; +		} + +		if (cur_delta[i] > 0) +		{ +			cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f); +		} +		else +		{ +			cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f); +		} + +		// we don't care about Roll (RZ) and Z is calculated after the loop +        if (i != Z_I && i != RZ_I) +		{ +			// find out the axis with the biggest joystick motion +			val = fabs(cur_delta[i]); +			if (val > dom_mov) +			{ +				dom_axis = i; +				dom_mov = val; +			} +		} +	} + +	// forward|backward movements overrule the real dominant movement if  +	// they're bigger than its 20%. This is what you want cos moving forward +	// is what you do most. We also added a special (even more lenient) case  +	// for RX|RY to allow walking while pitching n' turning +	if (fabs(cur_delta[Z_I]) > .2f * dom_mov +		|| ((dom_axis == RX_I || dom_axis == RY_I)  +			&& fabs(cur_delta[Z_I]) > .05f * dom_mov)) +    { +		dom_axis = Z_I; +	} + +	sDelta[X_I] = -cur_delta[X_I] * axis_scale[X_I]; +	sDelta[Y_I] = -cur_delta[Y_I] * axis_scale[Y_I]; +	sDelta[Z_I] = -cur_delta[Z_I] * axis_scale[Z_I]; +	cur_delta[RX_I] *= -axis_scale[RX_I] * mPerfScale; +	cur_delta[RY_I] *= -axis_scale[RY_I] * mPerfScale; +		 +	if (!absolute) +	{ +		cur_delta[RX_I] *= time; +		cur_delta[RY_I] *= time; +	} +	sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather; +	sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather; +	 +    switch (dom_axis) +    { +        case X_I:                                         // move sideways +			agentSlide(sDelta[X_I]); +            break; +         +        case Z_I:                                         // forward/back +		{ +            agentPush(sDelta[Z_I]); +             +            if (fabs(sDelta[Y_I])  > .1f) +			{ +				agentFly(sDelta[Y_I]); +			} +		 +			// too many rotations during walking can be confusing, so apply +			// the deadzones one more time (quick & dirty), at 50%|30% power +			F32 eff_rx = .3f * dead_zone[RX_I]; +			F32 eff_ry = .3f * dead_zone[RY_I]; +		 +			if (sDelta[RX_I] > 0) +			{ +				eff_rx = llmax(sDelta[RX_I] - eff_rx, 0.f); +			} +			else +			{ +				eff_rx = llmin(sDelta[RX_I] + eff_rx, 0.f); +			} + +			if (sDelta[RY_I] > 0) +			{ +				eff_ry = llmax(sDelta[RY_I] - eff_ry, 0.f); +			} +			else +			{ +				eff_ry = llmin(sDelta[RY_I] + eff_ry, 0.f); +			} +			 +			 +			if (fabs(eff_rx) > 0.f || fabs(eff_ry) > 0.f) +			{ +				if (gAgent.getFlying()) +				{ +					agentRotate(eff_rx, eff_ry); +				} +				else +				{ +					agentRotate(eff_rx, 2.f * eff_ry); +				} +			} +            break; +		}    +        case Y_I:                                          // up/crouch +            agentFly(sDelta[Y_I]); +            break; +             +        case RX_I:                                         // pitch +        case RY_I:                                         // turn +			agentRotate(sDelta[RX_I], sDelta[RY_I]); +            break; +        // case RZ_I: roll is unused in avatar mode +    }// switch +} + +// ----------------------------------------------------------------------------- +void LLViewerJoystick::moveFlycam(bool reset) +{ +	static LLQuaternion 		sFlycamRotation; +	static LLVector3    		sFlycamPosition; +	static F32          		sFlycamZoom; +	 +	if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED) +	{ +		return; +	} +  	S32 axis[] =   	{ -		gSavedSettings.getS32("FlycamAxis0"), -		gSavedSettings.getS32("FlycamAxis1"), -		gSavedSettings.getS32("FlycamAxis2"), -		gSavedSettings.getS32("FlycamAxis3"), -		gSavedSettings.getS32("FlycamAxis4"), -		gSavedSettings.getS32("FlycamAxis5"), -		gSavedSettings.getS32("FlycamAxis6") +		gSavedSettings.getS32("JoystickAxis0"), +		gSavedSettings.getS32("JoystickAxis1"), +		gSavedSettings.getS32("JoystickAxis2"), +		gSavedSettings.getS32("JoystickAxis3"), +		gSavedSettings.getS32("JoystickAxis4"), +		gSavedSettings.getS32("JoystickAxis5"), +		gSavedSettings.getS32("JoystickAxis6")  	}; +	bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); +	if (reset || mResetFlag) +	{ +		sFlycamPosition = LLViewerCamera::getInstance()->getOrigin(); +		sFlycamRotation = LLViewerCamera::getInstance()->getQuaternion(); +		sFlycamZoom = LLViewerCamera::getInstance()->getView(); +		 +		resetDeltas(axis, in_build_mode); + +		return; +	} +  	F32 axis_scale[] =  	{  		gSavedSettings.getF32("FlycamAxisScale0"), @@ -85,33 +707,37 @@ void LLViewerJoystick::updateCamera(BOOL reset)  		gSavedSettings.getF32("FlycamAxisDeadZone6")  	}; -	if (reset) -	{ -		sFlycamPosition = LLViewerCamera::getInstance()->getOrigin(); -		sFlycamRotation = LLViewerCamera::getInstance()->getQuaternion(); -		sFlycamZoom = LLViewerCamera::getInstance()->getView(); +	F32 time = gFrameIntervalSeconds; -		for (U32 i = 0; i < 7; i++) -		{ -			last_delta[i] = -window->getJoystickAxis(axis[i]); -			delta[i] = 0.f; -		} -		return; +	// avoid making ridicously big movements if there's a big drop in fps  +	if (time > .2f) +	{ +		time = .2f;  	}  	F32 cur_delta[7];  	F32 feather = gSavedSettings.getF32("FlycamFeathering"); -	BOOL absolute = gSavedSettings.getBOOL("FlycamAbsolute"); +	bool absolute = gSavedSettings.getBOOL("Cursor3D");  	for (U32 i = 0; i < 7; i++)  	{ -		cur_delta[i] = -window->getJoystickAxis(axis[i]);	 +		cur_delta[i] = -getJoystickAxis(axis[i]); + +		// we need smaller camera movements in build mode +		if (in_build_mode) +		{ +			if (i == X_I || i == Y_I || i == Z_I) +			{ +				cur_delta[i] /= BUILDMODE_FLYCAM_T_SCALE; +			} +		} +  		F32 tmp = cur_delta[i];  		if (absolute)  		{ -			cur_delta[i] = cur_delta[i] - last_delta[i]; +			cur_delta[i] = cur_delta[i] - sLastDelta[i];  		} -		last_delta[i] = tmp; +		sLastDelta[i] = tmp;  		if (cur_delta[i] > 0)  		{ @@ -128,18 +754,15 @@ void LLViewerJoystick::updateCamera(BOOL reset)  			cur_delta[i] *= time;  		} -		delta[i] = delta[i] + (cur_delta[i]-delta[i])*time*feather; +		sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather;  	} -	sFlycamPosition += LLVector3(delta) * sFlycamRotation; +	sFlycamPosition += LLVector3(sDelta) * sFlycamRotation; -	LLMatrix3 rot_mat(delta[3], -					  delta[4], -					  delta[5]); -	 +	LLMatrix3 rot_mat(sDelta[3], sDelta[4], sDelta[5]);  	sFlycamRotation = LLQuaternion(rot_mat)*sFlycamRotation; -	if (gSavedSettings.getBOOL("FlycamAutoLeveling")) +	if (gSavedSettings.getBOOL("AutoLeveling"))  	{  		LLMatrix3 level(sFlycamRotation); @@ -153,17 +776,17 @@ void LLViewerJoystick::updateCamera(BOOL reset)  		level.setRows(x,y,z);  		level.orthogonalize(); -		LLQuaternion quat = LLQuaternion(level); +		LLQuaternion quat(level);  		sFlycamRotation = nlerp(llmin(feather*time,1.f), sFlycamRotation, quat);  	} -	if (gSavedSettings.getBOOL("FlycamZoomDirect")) +	if (gSavedSettings.getBOOL("ZoomDirect"))  	{ -		sFlycamZoom = last_delta[6]*axis_scale[6]+dead_zone[6]; +		sFlycamZoom = sLastDelta[6]*axis_scale[6]+dead_zone[6];  	}  	else  	{ -		sFlycamZoom += delta[6]; +		sFlycamZoom += sDelta[6];  	}  	LLMatrix3 mat(sFlycamRotation); @@ -175,101 +798,52 @@ void LLViewerJoystick::updateCamera(BOOL reset)  	LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);  } - +// -----------------------------------------------------------------------------  void LLViewerJoystick::scanJoystick()  { -	if (!sOverrideCamera) +	if (mDriverState != JDS_INITIALIZED)  	{ -		static U32 joystick_state = 0; -		static U32 button_state = 0; +		return; +	} -		F32 xval = gViewerWindow->getWindow()->getJoystickAxis(0); -		F32 yval = gViewerWindow->getWindow()->getJoystickAxis(1); +#if LL_WINDOWS +	// On windows, the flycam is updated syncronously with a timer, so there is +	// no need to update the status of the joystick here. +	if (!sOverrideCamera) +#endif +	updateStatus(); -		if (xval <= -0.5f) -		{ -			if (!(joystick_state & 0x1)) -			{ -				gKeyboard->handleTranslatedKeyDown(KEY_PAD_LEFT, 0); -				joystick_state |= 0x1; -			} -		} -		else  -		{ -			if (joystick_state & 0x1) -			{ -				gKeyboard->handleTranslatedKeyUp(KEY_PAD_LEFT, 0); -				joystick_state &= ~0x1; -			} -		} -		if (xval >= 0.5f) -		{ -			if (!(joystick_state & 0x2)) -			{ -				gKeyboard->handleTranslatedKeyDown(KEY_PAD_RIGHT, 0); -				joystick_state |= 0x2; -			} -		} -		else  -		{ -			if (joystick_state & 0x2) -			{ -				gKeyboard->handleTranslatedKeyUp(KEY_PAD_RIGHT, 0); -				joystick_state &= ~0x2; -			} -		} -		if (yval <= -0.5f) -		{ -			if (!(joystick_state & 0x4)) -			{ -				gKeyboard->handleTranslatedKeyDown(KEY_PAD_UP, 0); -				joystick_state |= 0x4; -			} -		} -		else  -		{ -			if (joystick_state & 0x4) -			{ -				gKeyboard->handleTranslatedKeyUp(KEY_PAD_UP, 0); -				joystick_state &= ~0x4; -			} -		} -		if (yval >=  0.5f) -		{ -			if (!(joystick_state & 0x8)) -			{ -				gKeyboard->handleTranslatedKeyDown(KEY_PAD_DOWN, 0); -				joystick_state |= 0x8; -			} -		} -		else  -		{ -			if (joystick_state & 0x8) -			{ -				gKeyboard->handleTranslatedKeyUp(KEY_PAD_DOWN, 0); -				joystick_state &= ~0x8; -			} -		} +	static long toggle_flycam = 0; -		for( int i = 0; i < 15; i++ ) +	if (mBtn[0] == 1) +    { +		if (mBtn[0] != toggle_flycam)  		{ -			if ( gViewerWindow->getWindow()->getJoystickButton(i) & 0x80 ) -			{ -				if (!(button_state & (1<<i))) -				{ -					gKeyboard->handleTranslatedKeyDown(KEY_BUTTON1+i, 0); -					button_state |= (1<<i); -				} -			} -			else -			{ -				if (button_state & (1<<i)) -				{ -					gKeyboard->handleTranslatedKeyUp(KEY_BUTTON1+i, 0); -					button_state &= ~(1<<i); -				} -			} +			handle_toggle_flycam(); +			toggle_flycam = 1;  		}  	} +	else +	{ +		toggle_flycam = 0; +	} +	 +	if (!sOverrideCamera && !LLToolMgr::getInstance()->inBuildMode()) +	{ +		moveAvatar(); +	}  } +// ----------------------------------------------------------------------------- +bool LLViewerJoystick::isLikeSpaceNavigator() const +{ +#if LIB_NDOF	 +	return (isJoystickInitialized()  +			&& (strncmp(mNdofDev->product, "SpaceNavigator", 14) == 0 +				|| strncmp(mNdofDev->product, "SpaceExplorer", 13) == 0 +				|| strncmp(mNdofDev->product, "SpaceTraveler", 13) == 0 +				|| strncmp(mNdofDev->product, "SpacePilot", 10) == 0)); +#else +	return false; +#endif +} diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index f2fc24b813..47acf17f17 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -1,6 +1,6 @@  /**    * @file llviewerjoystick.h - * @brief Viewer joystick functionality. + * @brief Viewer joystick / NDOF device functionality.   *   * $LicenseInfo:firstyear=2001&license=viewergpl$   *  @@ -32,12 +32,69 @@  #ifndef LL_LLVIEWERJOYSTICK_H  #define LL_LLVIEWERJOYSTICK_H -class LLViewerJoystick +#include "stdtypes.h" + +#define LIB_NDOF (LL_WINDOWS || LL_DARWIN) + +#if LIB_NDOF +#include "ndofdev_external.h" +#else +#define NDOF_Device	void +#define NDOF_HotPlugResult S32 +#endif + +typedef enum e_joystick_driver_state +{ +	JDS_UNINITIALIZED, +	JDS_INITIALIZED, +	JDS_INITIALIZING +} EJoystickDriverState; + +class LLViewerJoystick : public LLSingleton<LLViewerJoystick>  {  public: -	static BOOL sOverrideCamera; -	static void scanJoystick(); -	static void updateCamera(BOOL reset = FALSE); +	static bool sOverrideCamera; +	 +	void init(); +	void updateStatus(); +	void scanJoystick(); +	void moveObjects(bool reset = false); +	void moveAvatar(bool reset = false); +	void moveFlycam(bool reset = false); +	F32 getJoystickAxis(U32 axis) const; +	U32 getJoystickButton(U32 button) const; +	bool isJoystickInitialized() const {return (mDriverState==JDS_INITIALIZED);} +	bool isLikeSpaceNavigator() const; +	void setNeedsReset(bool reset = true) { mResetFlag = reset; } +	void setCameraNeedsUpdate(bool b)     { mCameraUpdated = b; } +	bool getCameraNeedsUpdate() const     { return mCameraUpdated; } +	 +	LLViewerJoystick(); +	virtual ~LLViewerJoystick(); +	 +protected: +	void terminate(); +	void agentSlide(F32 inc); +	void agentPush(F32 inc); +	void agentFly(F32 inc); +	void agentRotate(F32 pitch_inc, F32 turn_inc); +    void agentJump(); +	void resetDeltas(S32 axis[], bool flycam_and_build = false); +#if LIB_NDOF +	static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev); +	static void HotPlugRemovalCallback(NDOF_Device *dev); +#endif +	 +private: +	F32						mAxes[6]; +	long					mBtn[16]; +	EJoystickDriverState	mDriverState; +	NDOF_Device				*mNdofDev; +	bool					mResetFlag; +	F32						mPerfScale; +	bool					mCameraUpdated; +	static F32				sLastDelta[7]; +	static F32				sDelta[7];  };  #endif diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4234d4862c..ec52118098 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -67,7 +67,6 @@  #include "llagentpilot.h"  #include "llbox.h"  #include "llcallingcard.h" -#include "llcameraview.h"  #include "llclipboard.h"  #include "llcompilequeue.h"  #include "llconsole.h" @@ -466,8 +465,6 @@ void handle_dump_image_list(void*);  void handle_crash(void*);  void handle_dump_followcam(void*); -void handle_toggle_flycam(void*); -BOOL check_flycam(void*);  void handle_viewer_enable_message_log(void*);  void handle_viewer_disable_message_log(void*);  void handle_send_postcard(void*); @@ -1082,9 +1079,6 @@ void init_client_menu(LLMenuGL* menu)  									   &menu_check_control,  									   (void*)"DisableCameraConstraints")); -	menu->append(new LLMenuItemCheckGL("Joystick Flycam",  -		&handle_toggle_flycam,NULL,&check_flycam,NULL)); -		  	menu->append(new LLMenuItemCheckGL("Mouse Smoothing",  										&menu_toggle_control,  										NULL, @@ -1825,9 +1819,17 @@ bool toggle_build_mode()  	{  		// just reset the view, will pull us out of edit mode  		handle_reset_view(); + +		// avoid spurious avatar movements pulling out of edit mode +		LLViewerJoystick::getInstance()->moveAvatar(true);  	}  	else  	{ +		if (LLViewerJoystick::sOverrideCamera) +		{ +			handle_toggle_flycam(); +		} +			  		if (gAgent.getFocusOnAvatar() && gSavedSettings.getBOOL("EditCameraMovement") )  		{  			// zoom in if we're looking at the avatar @@ -1855,6 +1857,46 @@ class LLViewBuildMode : public view_listener_t  }; +class LLViewJoystickFlycam : public view_listener_t +{ +	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) +	{ +		handle_toggle_flycam(); +		return true; +	} +}; + +class LLViewCheckJoystickFlycam : public view_listener_t +{ +	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) +	{ +		bool new_val = LLViewerJoystick::sOverrideCamera; +		gMenuHolder->findControl(userdata["control"].asString())->setValue(new_val); +		return true; +	} +}; + +void handle_toggle_flycam() +{ +	LLViewerJoystick::sOverrideCamera = !LLViewerJoystick::sOverrideCamera; +	if (LLViewerJoystick::sOverrideCamera) +	{ +		LLViewerJoystick::getInstance()->moveFlycam(true); +	} +	else if (!LLToolMgr::getInstance()->inBuildMode()) +	{ +		LLViewerJoystick::getInstance()->moveAvatar(true); +	} +	else  +	{ +		// we are in build mode, exiting from the flycam mode: since we are  +		// going to keep the flycam POV for the main camera until the avatar +		// moves, we need to track this situation. +		LLViewerJoystick::getInstance()->setCameraNeedsUpdate(false); +		LLViewerJoystick::getInstance()->setNeedsReset(true); +	} +} +  class LLObjectBuild : public view_listener_t  {  	bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) @@ -1916,6 +1958,9 @@ class LLObjectEdit : public view_listener_t  		LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);  		gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); +		LLViewerJoystick::getInstance()->moveObjects(true); +		LLViewerJoystick::getInstance()->setNeedsReset(true); +  		// Could be first use  		LLFirstUse::useBuild();  		return true; @@ -3339,7 +3384,13 @@ void reset_view_final( BOOL proceed, void* )  	if (LLViewerJoystick::sOverrideCamera)  	{ -		handle_toggle_flycam(NULL); +		handle_toggle_flycam(); +	} + +	// reset avatar mode from eventual residual motion +	if (LLToolMgr::getInstance()->inBuildMode()) +	{ +		LLViewerJoystick::getInstance()->moveAvatar(true);  	}  	gAgent.resetView(!gFloaterTools->getVisible()); @@ -5252,21 +5303,6 @@ void handle_dump_followcam(void*)  	LLFollowCamMgr::dump();  } -BOOL check_flycam(void*) -{ -	return LLViewerJoystick::sOverrideCamera; -} - -void handle_toggle_flycam(void*) -{ -	LLViewerJoystick::sOverrideCamera = !LLViewerJoystick::sOverrideCamera; -	if (LLViewerJoystick::sOverrideCamera) -	{ -		LLViewerJoystick::updateCamera(TRUE); -		LLFloaterJoystick::show(NULL); -	} -} -  void handle_viewer_enable_message_log(void*)  {  	gMessageSystem->startLogging(); @@ -7715,6 +7751,7 @@ void initialize_menus()  	// View menu  	addMenu(new LLViewMouselook(), "View.Mouselook");  	addMenu(new LLViewBuildMode(), "View.BuildMode"); +	addMenu(new LLViewJoystickFlycam(), "View.JoystickFlycam");  	addMenu(new LLViewResetView(), "View.ResetView");  	addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter");  	addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); @@ -7733,6 +7770,7 @@ void initialize_menus()  	addMenu(new LLViewEnableLastChatter(), "View.EnableLastChatter");  	addMenu(new LLViewCheckBuildMode(), "View.CheckBuildMode"); +	addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam");  	addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips");  	addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent");  	addMenu(new LLViewCheckBeaconEnabled(), "View.CheckBeaconEnabled"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 21b2554ceb..98b08c4985 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -102,6 +102,7 @@ void handle_sit_down(void*);  bool toggle_build_mode();  void handle_object_build(void*);  void handle_save_snapshot(void *); +void handle_toggle_flycam();  bool handle_sit_or_stand();  bool handle_give_money_dialog(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 697aea8582..696a2ad3c6 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -32,6 +32,7 @@  #include "llviewerprecompiledheaders.h"  #include "llpanellogin.h" +#include "llviewerkeyboard.h"  #include "llviewerwindow.h"  // system library includes @@ -180,6 +181,7 @@  #include "llurlsimstring.h"  #include "llviewerdisplay.h"  #include "llspatialpartition.h" +#include "llviewerjoystick.h"  #if LL_WINDOWS  #include "llwindebug.h" @@ -514,6 +516,13 @@ public:  			addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));  			ypos += y_inc;  		} +		 +		if (LLViewerJoystick::sOverrideCamera) +		{ +			addText(xpos + 200, ypos, llformat("Flycam")); +			ypos += y_inc; +		} +		  		if (gSavedSettings.getBOOL("DebugShowRenderInfo"))  		{  			if (gPipeline.getUseVertexShaders() == 0) @@ -1302,6 +1311,7 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)  void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)  { +	LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);  	return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);  } @@ -1364,6 +1374,12 @@ BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)  	return TRUE;  } +BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating) +{ +	LLViewerJoystick::getInstance()->setNeedsReset(true); +	return FALSE; +} +  void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)  { @@ -1450,6 +1466,26 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)  	}  } +BOOL LLViewerWindow::handleTimerEvent(LLWindow *window) +{ +	if (LLViewerJoystick::sOverrideCamera) +	{ +		LLViewerJoystick::getInstance()->updateStatus(); +		return TRUE; +	} +	return FALSE; +} + +BOOL LLViewerWindow::handleDeviceChange(LLWindow *window) +{ +	// give a chance to use a joystick after startup (hot-plugging) +	if (!LLViewerJoystick::getInstance()->isJoystickInitialized() ) +	{ +		LLViewerJoystick::getInstance()->init(); +		return TRUE; +	} +	return FALSE; +}  //  // Classes diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ef3b5146e2..cad3bb031f 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -97,6 +97,7 @@ public:  	/*virtual*/ void handleFocus(LLWindow *window);  	/*virtual*/ void handleFocusLost(LLWindow *window);  	/*virtual*/ BOOL handleActivate(LLWindow *window, BOOL activated); +	/*virtual*/ BOOL handleActivateApp(LLWindow *window, BOOL activating);  	/*virtual*/ void handleMenuSelect(LLWindow *window,  S32 menu_item);  	/*virtual*/ BOOL handlePaint(LLWindow *window,  S32 x,  S32 y,  S32 width,  S32 height);  	/*virtual*/ void handleScrollWheel(LLWindow *window,  S32 clicks); @@ -104,6 +105,9 @@ public:  	/*virtual*/ void handleWindowBlock(LLWindow *window);  	/*virtual*/ void handleWindowUnblock(LLWindow *window);  	/*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data); +	/*virtual*/ BOOL handleTimerEvent(LLWindow *window); +	/*virtual*/ BOOL handleDeviceChange(LLWindow *window); +  	// diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index e73d278043..edb7002584 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -342,6 +342,9 @@ class DarwinManifest(ViewerManifest):                          #  <bundle>/Contents/MacOS/                          self.contents_of_tar('mozilla-universal-darwin.tgz', 'MacOS') +                        # copy additional libs in <bundle>/Contents/MacOS/ +                        self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib") +                          # replace the default theme with our custom theme (so scrollbars work).                          if self.prefix(src="mozilla-theme", dst="MacOS/chrome"):                                  self.path("classic.jar")  | 
