00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llviewerjoystick.h"
00035
00036 #include "llviewercontrol.h"
00037 #include "llviewerwindow.h"
00038 #include "llviewercamera.h"
00039 #include "llappviewer.h"
00040 #include "llkeyboard.h"
00041 #include "lltoolmgr.h"
00042 #include "llselectmgr.h"
00043 #include "llviewermenu.h"
00044 #include "llagent.h"
00045 #include "llfocusmgr.h"
00046
00047
00048
00049
00050
00051 #define X_I 1
00052 #define Y_I 2
00053 #define Z_I 0
00054 #define RX_I 4
00055 #define RY_I 5
00056 #define RZ_I 3
00057
00058
00059 const F32 BUILDMODE_FLYCAM_T_SCALE = 3.f;
00060
00061 F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0};
00062 F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0};
00063
00064
00065
00066
00067
00068
00069 #define MAX_SPACENAVIGATOR_INPUT 3000.0f
00070 #define MAX_JOYSTICK_INPUT_VALUE MAX_SPACENAVIGATOR_INPUT
00071
00072
00073 void LLViewerJoystick::updateEnabled(bool autoenable)
00074 {
00075 if (mDriverState == JDS_UNINITIALIZED)
00076 {
00077 gSavedSettings.setBOOL("JoystickEnabled", FALSE );
00078 }
00079 else
00080 {
00081 if (isLikeSpaceNavigator() && autoenable)
00082 {
00083 gSavedSettings.setBOOL("JoystickEnabled", TRUE );
00084 }
00085 }
00086 if (!gSavedSettings.getBOOL("JoystickEnabled"))
00087 {
00088 mOverrideCamera = FALSE;
00089 }
00090 }
00091
00092 void LLViewerJoystick::setOverrideCamera(bool val)
00093 {
00094 if (!gSavedSettings.getBOOL("JoystickEnabled"))
00095 {
00096 mOverrideCamera = FALSE;
00097 }
00098 else
00099 {
00100 mOverrideCamera = val;
00101 }
00102 }
00103
00104
00105 #if LIB_NDOF
00106 NDOF_HotPlugResult LLViewerJoystick::HotPlugAddCallback(NDOF_Device *dev)
00107 {
00108 NDOF_HotPlugResult res = NDOF_DISCARD_HOTPLUGGED;
00109 LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
00110 if (joystick->mDriverState == JDS_UNINITIALIZED)
00111 {
00112 llinfos << "HotPlugAddCallback: will use device:" << llendl;
00113 ndof_dump(dev);
00114 joystick->mNdofDev = dev;
00115 joystick->mDriverState = JDS_INITIALIZED;
00116 res = NDOF_KEEP_HOTPLUGGED;
00117 }
00118 joystick->updateEnabled(true);
00119 return res;
00120 }
00121 #endif
00122
00123
00124 #if LIB_NDOF
00125 void LLViewerJoystick::HotPlugRemovalCallback(NDOF_Device *dev)
00126 {
00127 LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
00128 if (joystick->mNdofDev == dev)
00129 {
00130 llinfos << "HotPlugRemovalCallback: joystick->mNdofDev="
00131 << joystick->mNdofDev << "; removed device:" << llendl;
00132 ndof_dump(dev);
00133 joystick->mDriverState = JDS_UNINITIALIZED;
00134 }
00135 joystick->updateEnabled(true);
00136 }
00137 #endif
00138
00139
00140 LLViewerJoystick::LLViewerJoystick()
00141 : mDriverState(JDS_UNINITIALIZED),
00142 mNdofDev(NULL),
00143 mResetFlag(false),
00144 mCameraUpdated(true),
00145 mOverrideCamera(false)
00146 {
00147 for (int i = 0; i < 6; i++)
00148 {
00149 mAxes[i] = sDelta[i] = sLastDelta[i] = 0.0f;
00150 }
00151
00152 memset(mBtn, 0, sizeof(mBtn));
00153
00154
00155 mPerfScale = 4000.f / gSysCPU.getMhz();
00156 }
00157
00158
00159 LLViewerJoystick::~LLViewerJoystick()
00160 {
00161 if (mDriverState == JDS_INITIALIZED)
00162 {
00163 terminate();
00164 }
00165 }
00166
00167
00168 void LLViewerJoystick::init(bool autoenable)
00169 {
00170 #if LIB_NDOF
00171 static bool libinit = false;
00172 mDriverState = JDS_INITIALIZING;
00173
00174 if (libinit == false)
00175 {
00176
00177 if (ndof_libinit(HotPlugAddCallback,
00178 HotPlugRemovalCallback,
00179 NULL))
00180 {
00181 mDriverState = JDS_UNINITIALIZED;
00182 }
00183 else
00184 {
00185
00186 libinit = true;
00187
00188
00189 mNdofDev = ndof_create();
00190 }
00191 }
00192
00193 if (libinit)
00194 {
00195 if (mNdofDev)
00196 {
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 mNdofDev->axes_min = (long)-MAX_JOYSTICK_INPUT_VALUE;
00209 mNdofDev->axes_max = (long)+MAX_JOYSTICK_INPUT_VALUE;
00210
00211
00212
00213 mNdofDev->absolute = 1;
00214
00215
00216 if (ndof_init_first(mNdofDev, NULL))
00217 {
00218 mDriverState = JDS_UNINITIALIZED;
00219 llwarns << "ndof_init_first FAILED" << llendl;
00220 }
00221 else
00222 {
00223 mDriverState = JDS_INITIALIZED;
00224 }
00225 }
00226 else
00227 {
00228 mDriverState = JDS_UNINITIALIZED;
00229 }
00230 }
00231
00232
00233 if (!autoenable)
00234 {
00235 autoenable = gSavedSettings.getString("JoystickInitialized").empty() ? true : false;
00236 }
00237 updateEnabled(autoenable);
00238
00239 if (mDriverState == JDS_INITIALIZED)
00240 {
00241
00242 if (isLikeSpaceNavigator())
00243 {
00244
00245 if (gSavedSettings.getString("JoystickInitialized") != "SpaceNavigator")
00246 {
00247
00248 setSNDefaults();
00249 gSavedSettings.setString("JoystickInitialized", "SpaceNavigator");
00250 }
00251 }
00252 else
00253 {
00254
00255 gSavedSettings.setString("JoystickInitialized", "UnknownDevice");
00256 }
00257 }
00258 else
00259 {
00260
00261 }
00262
00263 llinfos << "ndof: mDriverState=" << mDriverState << "; mNdofDev="
00264 << mNdofDev << "; libinit=" << libinit << llendl;
00265 #endif
00266 }
00267
00268
00269 void LLViewerJoystick::terminate()
00270 {
00271 #if LIB_NDOF
00272
00273 ndof_libcleanup();
00274 llinfos << "Terminated connection with NDOF device." << llendl;
00275
00276 #endif
00277 }
00278
00279
00280 void LLViewerJoystick::updateStatus()
00281 {
00282 #if LIB_NDOF
00283
00284 ndof_update(mNdofDev);
00285
00286 for (int i=0; i<6; i++)
00287 {
00288 mAxes[i] = (F32) mNdofDev->axes[i] / mNdofDev->axes_max;
00289 }
00290
00291 for (int i=0; i<16; i++)
00292 {
00293 mBtn[i] = mNdofDev->buttons[i];
00294 }
00295
00296 #endif
00297 }
00298
00299
00300 F32 LLViewerJoystick::getJoystickAxis(U32 axis) const
00301 {
00302 if (axis < 6)
00303 {
00304 return mAxes[axis];
00305 }
00306 return 0.f;
00307 }
00308
00309
00310 U32 LLViewerJoystick::getJoystickButton(U32 button) const
00311 {
00312 if (button < 16)
00313 {
00314 return mBtn[button];
00315 }
00316 return 0;
00317 }
00318
00319
00320 void LLViewerJoystick::agentJump()
00321 {
00322 gAgent.moveUp(1);
00323 }
00324
00325
00326 void LLViewerJoystick::agentSlide(F32 inc)
00327 {
00328 if (inc < 0)
00329 {
00330 gAgent.moveLeft(1);
00331 }
00332 else if (inc > 0)
00333 {
00334 gAgent.moveLeft(-1);
00335 }
00336 }
00337
00338
00339 void LLViewerJoystick::agentPush(F32 inc)
00340 {
00341 if (inc < 0)
00342 {
00343 gAgent.moveAt(1, false);
00344 }
00345 else if (inc > 0)
00346 {
00347 gAgent.moveAt(-1, false);
00348 }
00349 }
00350
00351
00352 void LLViewerJoystick::agentFly(F32 inc)
00353 {
00354 if (inc < 0)
00355 {
00356 if (gAgent.getFlying())
00357 {
00358 gAgent.moveUp(1);
00359 }
00360 else
00361 {
00362 gAgent.setFlying(true);
00363 }
00364 }
00365 else if (inc > 0)
00366 {
00367
00368 gAgent.moveUp(-1);
00369 }
00370 }
00371
00372
00373 void LLViewerJoystick::agentRotate(F32 pitch_inc, F32 yaw_inc)
00374 {
00375 LLQuaternion new_rot;
00376 pitch_inc = gAgent.clampPitchToLimits(-pitch_inc);
00377 const LLQuaternion qx(pitch_inc, gAgent.getLeftAxis());
00378 const LLQuaternion qy(-yaw_inc, gAgent.getReferenceUpVector());
00379 new_rot.setQuat(qx * qy);
00380 gAgent.rotate(new_rot);
00381 }
00382
00383
00384 void LLViewerJoystick::resetDeltas(S32 axis[], bool flycam_and_build_mode)
00385 {
00386 for (U32 i = 0; i < 6; i++)
00387 {
00388 sLastDelta[i] = -mAxes[axis[i]];
00389 sDelta[i] = 0.f;
00390 }
00391
00392 if (flycam_and_build_mode)
00393 {
00394 sLastDelta[X_I] /= BUILDMODE_FLYCAM_T_SCALE;
00395 sLastDelta[Y_I] /= BUILDMODE_FLYCAM_T_SCALE;
00396 sLastDelta[Z_I] /= BUILDMODE_FLYCAM_T_SCALE;
00397 }
00398
00399 sLastDelta[6] = sDelta[6] = 0.f;
00400 mResetFlag = false;
00401 }
00402
00403
00404 void LLViewerJoystick::moveObjects(bool reset)
00405 {
00406 static bool toggle_send_to_sim = false;
00407
00408 if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED
00409 || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickBuildEnabled"))
00410 {
00411 return;
00412 }
00413
00414 S32 axis[] =
00415 {
00416 gSavedSettings.getS32("JoystickAxis0"),
00417 gSavedSettings.getS32("JoystickAxis1"),
00418 gSavedSettings.getS32("JoystickAxis2"),
00419 gSavedSettings.getS32("JoystickAxis3"),
00420 gSavedSettings.getS32("JoystickAxis4"),
00421 gSavedSettings.getS32("JoystickAxis5"),
00422 };
00423
00424 if (reset || mResetFlag)
00425 {
00426 resetDeltas(axis);
00427 return;
00428 }
00429
00430 F32 axis_scale[] =
00431 {
00432 gSavedSettings.getF32("BuildAxisScale0"),
00433 gSavedSettings.getF32("BuildAxisScale1"),
00434 gSavedSettings.getF32("BuildAxisScale2"),
00435 gSavedSettings.getF32("BuildAxisScale3"),
00436 gSavedSettings.getF32("BuildAxisScale4"),
00437 gSavedSettings.getF32("BuildAxisScale5"),
00438 };
00439
00440 F32 dead_zone[] =
00441 {
00442 gSavedSettings.getF32("BuildAxisDeadZone0"),
00443 gSavedSettings.getF32("BuildAxisDeadZone1"),
00444 gSavedSettings.getF32("BuildAxisDeadZone2"),
00445 gSavedSettings.getF32("BuildAxisDeadZone3"),
00446 gSavedSettings.getF32("BuildAxisDeadZone4"),
00447 gSavedSettings.getF32("BuildAxisDeadZone5"),
00448 };
00449
00450 F32 cur_delta[6];
00451 F32 time = gFrameIntervalSeconds;
00452
00453
00454 if (time > .2f)
00455 {
00456 time = .2f;
00457 }
00458
00459
00460 F32 feather = gSavedSettings.getF32("BuildFeathering");
00461 bool is_zero = true, absolute = gSavedSettings.getBOOL("Cursor3D");
00462
00463 for (U32 i = 0; i < 6; i++)
00464 {
00465 cur_delta[i] = -mAxes[axis[i]];
00466 F32 tmp = cur_delta[i];
00467 if (absolute)
00468 {
00469 cur_delta[i] = cur_delta[i] - sLastDelta[i];
00470 }
00471 sLastDelta[i] = tmp;
00472 is_zero = is_zero && (cur_delta[i] == 0.f);
00473
00474 if (cur_delta[i] > 0)
00475 {
00476 cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f);
00477 }
00478 else
00479 {
00480 cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f);
00481 }
00482 cur_delta[i] *= axis_scale[i];
00483
00484 if (!absolute)
00485 {
00486 cur_delta[i] *= time;
00487 }
00488
00489 sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather;
00490 }
00491
00492 U32 upd_type = UPD_NONE;
00493 LLVector3 v;
00494
00495 if (!is_zero)
00496 {
00497 if (sDelta[0] || sDelta[1] || sDelta[2])
00498 {
00499 upd_type |= UPD_POSITION;
00500 v.setVec(sDelta[0], sDelta[1], sDelta[2]);
00501 }
00502
00503 if (sDelta[3] || sDelta[4] || sDelta[5])
00504 {
00505 upd_type |= UPD_ROTATION;
00506 }
00507
00508
00509 if (LLSelectMgr::getInstance()->selectionMove(v, sDelta[3],sDelta[4],sDelta[5], upd_type))
00510 {
00511 toggle_send_to_sim = true;
00512 }
00513 }
00514 else if (toggle_send_to_sim)
00515 {
00516 LLSelectMgr::getInstance()->sendSelectionMove();
00517 toggle_send_to_sim = false;
00518 }
00519 }
00520
00521
00522 void LLViewerJoystick::moveAvatar(bool reset)
00523 {
00524 if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED
00525 || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickAvatarEnabled"))
00526 {
00527 return;
00528 }
00529
00530 S32 axis[] =
00531 {
00532
00533
00534 gSavedSettings.getS32("JoystickAxis0"),
00535 gSavedSettings.getS32("JoystickAxis1"),
00536 gSavedSettings.getS32("JoystickAxis2"),
00537 gSavedSettings.getS32("JoystickAxis3"),
00538 gSavedSettings.getS32("JoystickAxis4"),
00539 gSavedSettings.getS32("JoystickAxis5")
00540 };
00541
00542 if (reset || mResetFlag)
00543 {
00544 resetDeltas(axis);
00545 if (reset)
00546 {
00547
00548
00549 gAgent.moveAt(0, true);
00550 }
00551 return;
00552 }
00553
00554 if (mBtn[1] == 1)
00555 {
00556 agentJump();
00557 return;
00558 }
00559
00560 F32 axis_scale[] =
00561 {
00562 gSavedSettings.getF32("AvatarAxisScale0"),
00563 gSavedSettings.getF32("AvatarAxisScale1"),
00564 gSavedSettings.getF32("AvatarAxisScale2"),
00565 gSavedSettings.getF32("AvatarAxisScale3"),
00566 gSavedSettings.getF32("AvatarAxisScale4"),
00567 gSavedSettings.getF32("AvatarAxisScale5")
00568 };
00569
00570 F32 dead_zone[] =
00571 {
00572 gSavedSettings.getF32("AvatarAxisDeadZone0"),
00573 gSavedSettings.getF32("AvatarAxisDeadZone1"),
00574 gSavedSettings.getF32("AvatarAxisDeadZone2"),
00575 gSavedSettings.getF32("AvatarAxisDeadZone3"),
00576 gSavedSettings.getF32("AvatarAxisDeadZone4"),
00577 gSavedSettings.getF32("AvatarAxisDeadZone5")
00578 };
00579
00580
00581 F32 time = gFrameIntervalSeconds;
00582
00583
00584 if (time > .2f)
00585 {
00586 time = .2f;
00587 }
00588
00589
00590 F32 feather = gSavedSettings.getF32("AvatarFeathering");
00591
00592 F32 cur_delta[6];
00593 F32 val, dom_mov = 0.f;
00594 U32 dom_axis = Z_I;
00595 #if LIB_NDOF
00596 bool absolute = (gSavedSettings.getBOOL("Cursor3D") && mNdofDev->absolute);
00597 #else
00598 bool absolute = false;
00599 #endif
00600
00601 for (U32 i = 0; i < 6; i++)
00602 {
00603 cur_delta[i] = -mAxes[axis[i]];
00604 if (absolute)
00605 {
00606 F32 tmp = cur_delta[i];
00607 cur_delta[i] = cur_delta[i] - sLastDelta[i];
00608 sLastDelta[i] = tmp;
00609 }
00610
00611 if (cur_delta[i] > 0)
00612 {
00613 cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f);
00614 }
00615 else
00616 {
00617 cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f);
00618 }
00619
00620
00621 if (i != Z_I && i != RZ_I)
00622 {
00623
00624 val = fabs(cur_delta[i]);
00625 if (val > dom_mov)
00626 {
00627 dom_axis = i;
00628 dom_mov = val;
00629 }
00630 }
00631 }
00632
00633
00634
00635
00636
00637 if (fabs(cur_delta[Z_I]) > .2f * dom_mov
00638 || ((dom_axis == RX_I || dom_axis == RY_I)
00639 && fabs(cur_delta[Z_I]) > .05f * dom_mov))
00640 {
00641 dom_axis = Z_I;
00642 }
00643
00644 sDelta[X_I] = -cur_delta[X_I] * axis_scale[X_I];
00645 sDelta[Y_I] = -cur_delta[Y_I] * axis_scale[Y_I];
00646 sDelta[Z_I] = -cur_delta[Z_I] * axis_scale[Z_I];
00647 cur_delta[RX_I] *= -axis_scale[RX_I] * mPerfScale;
00648 cur_delta[RY_I] *= -axis_scale[RY_I] * mPerfScale;
00649
00650 if (!absolute)
00651 {
00652 cur_delta[RX_I] *= time;
00653 cur_delta[RY_I] *= time;
00654 }
00655 sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather;
00656 sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather;
00657
00658 switch (dom_axis)
00659 {
00660 case X_I:
00661 agentSlide(sDelta[X_I]);
00662 break;
00663
00664 case Z_I:
00665 {
00666 agentPush(sDelta[Z_I]);
00667
00668 if (fabs(sDelta[Y_I]) > .1f)
00669 {
00670 agentFly(sDelta[Y_I]);
00671 }
00672
00673
00674
00675 F32 eff_rx = .3f * dead_zone[RX_I];
00676 F32 eff_ry = .3f * dead_zone[RY_I];
00677
00678 if (sDelta[RX_I] > 0)
00679 {
00680 eff_rx = llmax(sDelta[RX_I] - eff_rx, 0.f);
00681 }
00682 else
00683 {
00684 eff_rx = llmin(sDelta[RX_I] + eff_rx, 0.f);
00685 }
00686
00687 if (sDelta[RY_I] > 0)
00688 {
00689 eff_ry = llmax(sDelta[RY_I] - eff_ry, 0.f);
00690 }
00691 else
00692 {
00693 eff_ry = llmin(sDelta[RY_I] + eff_ry, 0.f);
00694 }
00695
00696
00697 if (fabs(eff_rx) > 0.f || fabs(eff_ry) > 0.f)
00698 {
00699 if (gAgent.getFlying())
00700 {
00701 agentRotate(eff_rx, eff_ry);
00702 }
00703 else
00704 {
00705 agentRotate(eff_rx, 2.f * eff_ry);
00706 }
00707 }
00708 break;
00709 }
00710 case Y_I:
00711 agentFly(sDelta[Y_I]);
00712 break;
00713
00714 case RX_I:
00715 case RY_I:
00716 agentRotate(sDelta[RX_I], sDelta[RY_I]);
00717 break;
00718
00719 }
00720 }
00721
00722
00723 void LLViewerJoystick::moveFlycam(bool reset)
00724 {
00725 static LLQuaternion sFlycamRotation;
00726 static LLVector3 sFlycamPosition;
00727 static F32 sFlycamZoom;
00728
00729 if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED
00730 || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled"))
00731 {
00732 return;
00733 }
00734
00735 S32 axis[] =
00736 {
00737 gSavedSettings.getS32("JoystickAxis0"),
00738 gSavedSettings.getS32("JoystickAxis1"),
00739 gSavedSettings.getS32("JoystickAxis2"),
00740 gSavedSettings.getS32("JoystickAxis3"),
00741 gSavedSettings.getS32("JoystickAxis4"),
00742 gSavedSettings.getS32("JoystickAxis5"),
00743 gSavedSettings.getS32("JoystickAxis6")
00744 };
00745
00746 bool in_build_mode = LLToolMgr::getInstance()->inBuildMode();
00747 if (reset || mResetFlag)
00748 {
00749 sFlycamPosition = LLViewerCamera::getInstance()->getOrigin();
00750 sFlycamRotation = LLViewerCamera::getInstance()->getQuaternion();
00751 sFlycamZoom = LLViewerCamera::getInstance()->getView();
00752
00753 resetDeltas(axis, in_build_mode);
00754
00755 return;
00756 }
00757
00758 F32 axis_scale[] =
00759 {
00760 gSavedSettings.getF32("FlycamAxisScale0"),
00761 gSavedSettings.getF32("FlycamAxisScale1"),
00762 gSavedSettings.getF32("FlycamAxisScale2"),
00763 gSavedSettings.getF32("FlycamAxisScale3"),
00764 gSavedSettings.getF32("FlycamAxisScale4"),
00765 gSavedSettings.getF32("FlycamAxisScale5"),
00766 gSavedSettings.getF32("FlycamAxisScale6")
00767 };
00768
00769 F32 dead_zone[] =
00770 {
00771 gSavedSettings.getF32("FlycamAxisDeadZone0"),
00772 gSavedSettings.getF32("FlycamAxisDeadZone1"),
00773 gSavedSettings.getF32("FlycamAxisDeadZone2"),
00774 gSavedSettings.getF32("FlycamAxisDeadZone3"),
00775 gSavedSettings.getF32("FlycamAxisDeadZone4"),
00776 gSavedSettings.getF32("FlycamAxisDeadZone5"),
00777 gSavedSettings.getF32("FlycamAxisDeadZone6")
00778 };
00779
00780 F32 time = gFrameIntervalSeconds;
00781
00782
00783 if (time > .2f)
00784 {
00785 time = .2f;
00786 }
00787
00788 F32 cur_delta[7];
00789 F32 feather = gSavedSettings.getF32("FlycamFeathering");
00790 bool absolute = gSavedSettings.getBOOL("Cursor3D");
00791
00792 for (U32 i = 0; i < 7; i++)
00793 {
00794 cur_delta[i] = -getJoystickAxis(axis[i]);
00795
00796
00797 if (in_build_mode)
00798 {
00799 if (i == X_I || i == Y_I || i == Z_I)
00800 {
00801 cur_delta[i] /= BUILDMODE_FLYCAM_T_SCALE;
00802 }
00803 }
00804
00805 F32 tmp = cur_delta[i];
00806 if (absolute)
00807 {
00808 cur_delta[i] = cur_delta[i] - sLastDelta[i];
00809 }
00810 sLastDelta[i] = tmp;
00811
00812 if (cur_delta[i] > 0)
00813 {
00814 cur_delta[i] = llmax(cur_delta[i]-dead_zone[i], 0.f);
00815 }
00816 else
00817 {
00818 cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f);
00819 }
00820 cur_delta[i] *= axis_scale[i];
00821
00822 if (!absolute)
00823 {
00824 cur_delta[i] *= time;
00825 }
00826
00827 sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather;
00828 }
00829
00830 sFlycamPosition += LLVector3(sDelta) * sFlycamRotation;
00831
00832 LLMatrix3 rot_mat(sDelta[3], sDelta[4], sDelta[5]);
00833 sFlycamRotation = LLQuaternion(rot_mat)*sFlycamRotation;
00834
00835 if (gSavedSettings.getBOOL("AutoLeveling"))
00836 {
00837 LLMatrix3 level(sFlycamRotation);
00838
00839 LLVector3 x = LLVector3(level.mMatrix[0]);
00840 LLVector3 y = LLVector3(level.mMatrix[1]);
00841 LLVector3 z = LLVector3(level.mMatrix[2]);
00842
00843 y.mV[2] = 0.f;
00844 y.normVec();
00845
00846 level.setRows(x,y,z);
00847 level.orthogonalize();
00848
00849 LLQuaternion quat(level);
00850 sFlycamRotation = nlerp(llmin(feather*time,1.f), sFlycamRotation, quat);
00851 }
00852
00853 if (gSavedSettings.getBOOL("ZoomDirect"))
00854 {
00855 sFlycamZoom = sLastDelta[6]*axis_scale[6]+dead_zone[6];
00856 }
00857 else
00858 {
00859 sFlycamZoom += sDelta[6];
00860 }
00861
00862 LLMatrix3 mat(sFlycamRotation);
00863
00864 LLViewerCamera::getInstance()->setView(sFlycamZoom);
00865 LLViewerCamera::getInstance()->setOrigin(sFlycamPosition);
00866 LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]);
00867 LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
00868 LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
00869 }
00870
00871
00872 bool LLViewerJoystick::toggleFlycam()
00873 {
00874 if (!gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled"))
00875 {
00876 return false;
00877 }
00878 mOverrideCamera = !mOverrideCamera;
00879 if (mOverrideCamera)
00880 {
00881 moveFlycam(true);
00882 }
00883 else if (!LLToolMgr::getInstance()->inBuildMode())
00884 {
00885 moveAvatar(true);
00886 }
00887 else
00888 {
00889
00890
00891
00892 setCameraNeedsUpdate(false);
00893 setNeedsReset(true);
00894 }
00895 return true;
00896 }
00897
00898 void LLViewerJoystick::scanJoystick()
00899 {
00900 if (mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled"))
00901 {
00902 return;
00903 }
00904
00905 #if LL_WINDOWS
00906
00907
00908 if (!mOverrideCamera)
00909 #endif
00910 updateStatus();
00911
00912 static long toggle_flycam = 0;
00913
00914 if (mBtn[0] == 1)
00915 {
00916 if (mBtn[0] != toggle_flycam)
00917 {
00918 toggle_flycam = toggleFlycam() ? 1 : 0;
00919 }
00920 }
00921 else
00922 {
00923 toggle_flycam = 0;
00924 }
00925
00926 if (!mOverrideCamera && !LLToolMgr::getInstance()->inBuildMode())
00927 {
00928 moveAvatar();
00929 }
00930 }
00931
00932
00933 std::string LLViewerJoystick::getDescription()
00934 {
00935 std::string res;
00936 #if LIB_NDOF
00937 if (mDriverState == JDS_INITIALIZED && mNdofDev)
00938 {
00939 res = ll_safe_string(mNdofDev->product);
00940 }
00941 #endif
00942 return res;
00943 }
00944
00945 bool LLViewerJoystick::isLikeSpaceNavigator() const
00946 {
00947 #if LIB_NDOF
00948 return (isJoystickInitialized()
00949 && (strncmp(mNdofDev->product, "SpaceNavigator", 14) == 0
00950 || strncmp(mNdofDev->product, "SpaceExplorer", 13) == 0
00951 || strncmp(mNdofDev->product, "SpaceTraveler", 13) == 0
00952 || strncmp(mNdofDev->product, "SpacePilot", 10) == 0));
00953 #else
00954 return false;
00955 #endif
00956 }
00957
00958
00959 void LLViewerJoystick::setSNDefaults()
00960 {
00961 #if LL_DARWIN
00962 #define kPlatformScale 20.f
00963 #else
00964 #define kPlatformScale 1.f
00965 #endif
00966
00967
00968 llinfos << "restoring SpaceNavigator defaults..." << llendl;
00969
00970 gSavedSettings.setS32("JoystickAxis0", 1);
00971 gSavedSettings.setS32("JoystickAxis1", 0);
00972 gSavedSettings.setS32("JoystickAxis2", 2);
00973 gSavedSettings.setS32("JoystickAxis3", 4);
00974 gSavedSettings.setS32("JoystickAxis4", 3);
00975 gSavedSettings.setS32("JoystickAxis5", 5);
00976 gSavedSettings.setS32("JoystickAxis6", -1);
00977
00978 #if LL_DARWIN
00979
00980 gSavedSettings.setBOOL("Cursor3D", false);
00981 #else
00982 gSavedSettings.setBOOL("Cursor3D", true);
00983 #endif
00984 gSavedSettings.setBOOL("AutoLeveling", true);
00985 gSavedSettings.setBOOL("ZoomDirect", false);
00986
00987 gSavedSettings.setF32("AvatarAxisScale0", 1.f);
00988 gSavedSettings.setF32("AvatarAxisScale1", 1.f);
00989 gSavedSettings.setF32("AvatarAxisScale2", 1.f);
00990 gSavedSettings.setF32("AvatarAxisScale4", .1f * kPlatformScale);
00991 gSavedSettings.setF32("AvatarAxisScale5", .1f * kPlatformScale);
00992 gSavedSettings.setF32("AvatarAxisScale3", 0.f * kPlatformScale);
00993 gSavedSettings.setF32("BuildAxisScale1", .3f * kPlatformScale);
00994 gSavedSettings.setF32("BuildAxisScale2", .3f * kPlatformScale);
00995 gSavedSettings.setF32("BuildAxisScale0", .3f * kPlatformScale);
00996 gSavedSettings.setF32("BuildAxisScale4", .3f * kPlatformScale);
00997 gSavedSettings.setF32("BuildAxisScale5", .3f * kPlatformScale);
00998 gSavedSettings.setF32("BuildAxisScale3", .3f * kPlatformScale);
00999 gSavedSettings.setF32("FlycamAxisScale1", 2.f * kPlatformScale);
01000 gSavedSettings.setF32("FlycamAxisScale2", 2.f * kPlatformScale);
01001 gSavedSettings.setF32("FlycamAxisScale0", 2.1f * kPlatformScale);
01002 gSavedSettings.setF32("FlycamAxisScale4", .1f * kPlatformScale);
01003 gSavedSettings.setF32("FlycamAxisScale5", .15f * kPlatformScale);
01004 gSavedSettings.setF32("FlycamAxisScale3", 0.f * kPlatformScale);
01005 gSavedSettings.setF32("FlycamAxisScale6", 0.f * kPlatformScale);
01006
01007 gSavedSettings.setF32("AvatarAxisDeadZone0", .1f);
01008 gSavedSettings.setF32("AvatarAxisDeadZone1", .1f);
01009 gSavedSettings.setF32("AvatarAxisDeadZone2", .1f);
01010 gSavedSettings.setF32("AvatarAxisDeadZone3", 1.f);
01011 gSavedSettings.setF32("AvatarAxisDeadZone4", .02f);
01012 gSavedSettings.setF32("AvatarAxisDeadZone5", .01f);
01013 gSavedSettings.setF32("BuildAxisDeadZone0", .01f);
01014 gSavedSettings.setF32("BuildAxisDeadZone1", .01f);
01015 gSavedSettings.setF32("BuildAxisDeadZone2", .01f);
01016 gSavedSettings.setF32("BuildAxisDeadZone3", .01f);
01017 gSavedSettings.setF32("BuildAxisDeadZone4", .01f);
01018 gSavedSettings.setF32("BuildAxisDeadZone5", .01f);
01019 gSavedSettings.setF32("FlycamAxisDeadZone0", .01f);
01020 gSavedSettings.setF32("FlycamAxisDeadZone1", .01f);
01021 gSavedSettings.setF32("FlycamAxisDeadZone2", .01f);
01022 gSavedSettings.setF32("FlycamAxisDeadZone3", .01f);
01023 gSavedSettings.setF32("FlycamAxisDeadZone4", .01f);
01024 gSavedSettings.setF32("FlycamAxisDeadZone5", .01f);
01025 gSavedSettings.setF32("FlycamAxisDeadZone6", 1.f);
01026
01027 gSavedSettings.setF32("AvatarFeathering", 6.f);
01028 gSavedSettings.setF32("BuildFeathering", 12.f);
01029 gSavedSettings.setF32("FlycamFeathering", 5.f);
01030 }