summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml366
-rw-r--r--indra/newview/llagent.cpp38
-rw-r--r--indra/newview/llagent.h5
-rw-r--r--indra/newview/llappviewer.cpp30
-rw-r--r--indra/newview/llfloaterjoystick.cpp333
-rw-r--r--indra/newview/llfloaterjoystick.h78
-rw-r--r--indra/newview/llfloatertools.cpp4
-rw-r--r--indra/newview/llmanip.cpp2
-rw-r--r--indra/newview/llmanip.h2
-rw-r--r--indra/newview/llselectmgr.cpp195
-rw-r--r--indra/newview/llselectmgr.h6
-rw-r--r--indra/newview/lltoolcomp.cpp2
-rw-r--r--indra/newview/lltoolmgr.cpp15
-rw-r--r--indra/newview/lltoolmgr.h3
-rw-r--r--indra/newview/llviewercamera.cpp9
-rw-r--r--indra/newview/llviewercontrol.cpp54
-rw-r--r--indra/newview/llviewerjoystick.cpp834
-rw-r--r--indra/newview/llviewerjoystick.h67
-rw-r--r--indra/newview/llviewermenu.cpp82
-rw-r--r--indra/newview/llviewermenu.h1
-rw-r--r--indra/newview/llviewerwindow.cpp36
-rw-r--r--indra/newview/llviewerwindow.h4
-rwxr-xr-xindra/newview/viewer_manifest.py3
23 files changed, 1959 insertions, 210 deletions
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 &center,
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")