summaryrefslogtreecommitdiff
path: root/indra/newview/llviewerjoystick.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewerjoystick.cpp')
-rw-r--r--indra/newview/llviewerjoystick.cpp834
1 files changed, 704 insertions, 130 deletions
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
+}