aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerjoystick.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2009-04-30 13:04:20 -0500
committerJacek Antonelli2009-04-30 13:07:16 -0500
commitca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e (patch)
tree8348301d0ac44a524f1819b777686bf086907d76 /linden/indra/newview/llviewerjoystick.cpp
parentSecond Life viewer sources 1.22.11 (diff)
downloadmeta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.zip
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.gz
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.bz2
meta-impy-ca8149ca6d157eb4b5fc8ba0e5ba3a6e56f72e7e.tar.xz
Second Life viewer sources 1.23.0-RC
Diffstat (limited to 'linden/indra/newview/llviewerjoystick.cpp')
-rw-r--r--linden/indra/newview/llviewerjoystick.cpp285
1 files changed, 180 insertions, 105 deletions
diff --git a/linden/indra/newview/llviewerjoystick.cpp b/linden/indra/newview/llviewerjoystick.cpp
index 721e02d..652e50e 100644
--- a/linden/indra/newview/llviewerjoystick.cpp
+++ b/linden/indra/newview/llviewerjoystick.cpp
@@ -17,7 +17,8 @@
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception 20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 22 *
22 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -58,12 +59,15 @@
58// flycam translations in build mode should be reduced 59// flycam translations in build mode should be reduced
59const F32 BUILDMODE_FLYCAM_T_SCALE = 3.f; 60const F32 BUILDMODE_FLYCAM_T_SCALE = 3.f;
60 61
62// minimum time after setting away state before coming back
63const F32 MIN_AFK_TIME = 2.f;
64
61F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0}; 65F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0};
62F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; 66F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0};
63 67
64// These constants specify the maximum absolute value coming in from the device. 68// These constants specify the maximum absolute value coming in from the device.
65// HACK ALERT! the value of MAX_JOYSTICK_INPUT_VALUE is not arbitrary as it 69// HACK ALERT! the value of MAX_JOYSTICK_INPUT_VALUE is not arbitrary as it
66// should be. It has to be equal to 3000 because the SpaceNavigator on Windows 70// should be. It has to be equal to 3000 because the SpaceNavigator on Windows
67// refuses to respond to the DirectInput SetProperty call; it always returns 71// refuses to respond to the DirectInput SetProperty call; it always returns
68// values in the [-3000, 3000] range. 72// values in the [-3000, 3000] range.
69#define MAX_SPACENAVIGATOR_INPUT 3000.0f 73#define MAX_SPACENAVIGATOR_INPUT 3000.0f
@@ -147,7 +151,8 @@ LLViewerJoystick::LLViewerJoystick()
147 mNdofDev(NULL), 151 mNdofDev(NULL),
148 mResetFlag(false), 152 mResetFlag(false),
149 mCameraUpdated(true), 153 mCameraUpdated(true),
150 mOverrideCamera(false) 154 mOverrideCamera(false),
155 mJoystickRun(0)
151{ 156{
152 for (int i = 0; i < 6; i++) 157 for (int i = 0; i < 6; i++)
153 { 158 {
@@ -322,6 +327,40 @@ U32 LLViewerJoystick::getJoystickButton(U32 button) const
322} 327}
323 328
324// ----------------------------------------------------------------------------- 329// -----------------------------------------------------------------------------
330void LLViewerJoystick::handleRun(F32 inc)
331{
332 // Decide whether to walk or run by applying a threshold, with slight
333 // hysteresis to avoid oscillating between the two with input spikes.
334 // Analog speed control would be better, but not likely any time soon.
335 if (inc > gSavedSettings.getF32("JoystickRunThreshold"))
336 {
337 if (1 == mJoystickRun)
338 {
339 ++mJoystickRun;
340 gAgent.setRunning();
341 gAgent.sendWalkRun(gAgent.getRunning());
342 }
343 else if (0 == mJoystickRun)
344 {
345 // hysteresis - respond NEXT frame
346 ++mJoystickRun;
347 }
348 }
349 else
350 {
351 if (mJoystickRun > 0)
352 {
353 --mJoystickRun;
354 if (0 == mJoystickRun)
355 {
356 gAgent.clearRunning();
357 gAgent.sendWalkRun(gAgent.getRunning());
358 }
359 }
360 }
361}
362
363// -----------------------------------------------------------------------------
325void LLViewerJoystick::agentJump() 364void LLViewerJoystick::agentJump()
326{ 365{
327 gAgent.moveUp(1); 366 gAgent.moveUp(1);
@@ -330,11 +369,11 @@ void LLViewerJoystick::agentJump()
330// ----------------------------------------------------------------------------- 369// -----------------------------------------------------------------------------
331void LLViewerJoystick::agentSlide(F32 inc) 370void LLViewerJoystick::agentSlide(F32 inc)
332{ 371{
333 if (inc < 0) 372 if (inc < 0.f)
334 { 373 {
335 gAgent.moveLeft(1); 374 gAgent.moveLeft(1);
336 } 375 }
337 else if (inc > 0) 376 else if (inc > 0.f)
338 { 377 {
339 gAgent.moveLeft(-1); 378 gAgent.moveLeft(-1);
340 } 379 }
@@ -343,11 +382,11 @@ void LLViewerJoystick::agentSlide(F32 inc)
343// ----------------------------------------------------------------------------- 382// -----------------------------------------------------------------------------
344void LLViewerJoystick::agentPush(F32 inc) 383void LLViewerJoystick::agentPush(F32 inc)
345{ 384{
346 if (inc < 0) // forward 385 if (inc < 0.f) // forward
347 { 386 {
348 gAgent.moveAt(1, false); 387 gAgent.moveAt(1, false);
349 } 388 }
350 else if (inc > 0) // backward 389 else if (inc > 0.f) // backward
351 { 390 {
352 gAgent.moveAt(-1, false); 391 gAgent.moveAt(-1, false);
353 } 392 }
@@ -356,18 +395,18 @@ void LLViewerJoystick::agentPush(F32 inc)
356// ----------------------------------------------------------------------------- 395// -----------------------------------------------------------------------------
357void LLViewerJoystick::agentFly(F32 inc) 396void LLViewerJoystick::agentFly(F32 inc)
358{ 397{
359 if (inc < 0) 398 if (inc < 0.f)
360 { 399 {
361 if (gAgent.getFlying()) 400 if (! (gAgent.getFlying() ||
362 { 401 !gAgent.canFly() ||
363 gAgent.moveUp(1); 402 gAgent.upGrabbed() ||
364 } 403 !gSavedSettings.getBOOL("AutomaticFly")) )
365 else
366 { 404 {
367 gAgent.setFlying(true); 405 gAgent.setFlying(true);
368 } 406 }
407 gAgent.moveUp(1);
369 } 408 }
370 else if (inc > 0) 409 else if (inc > 0.f)
371 { 410 {
372 // crouch 411 // crouch
373 gAgent.moveUp(-1); 412 gAgent.moveUp(-1);
@@ -492,6 +531,12 @@ void LLViewerJoystick::moveObjects(bool reset)
492 531
493 if (!is_zero) 532 if (!is_zero)
494 { 533 {
534 // Clear AFK state if moved beyond the deadzone
535 if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
536 {
537 gAgent.clearAFK();
538 }
539
495 if (sDelta[0] || sDelta[1] || sDelta[2]) 540 if (sDelta[0] || sDelta[1] || sDelta[2])
496 { 541 {
497 upd_type |= UPD_POSITION; 542 upd_type |= UPD_POSITION;
@@ -549,11 +594,13 @@ void LLViewerJoystick::moveAvatar(bool reset)
549 return; 594 return;
550 } 595 }
551 596
597 bool is_zero = true;
598
552 if (mBtn[1] == 1) 599 if (mBtn[1] == 1)
553 { 600 {
554 agentJump(); 601 agentJump();
555 return; 602 is_zero = false;
556 } 603 }
557 604
558 F32 axis_scale[] = 605 F32 axis_scale[] =
559 { 606 {
@@ -626,16 +673,29 @@ void LLViewerJoystick::moveAvatar(bool reset)
626 dom_mov = val; 673 dom_mov = val;
627 } 674 }
628 } 675 }
676
677 is_zero = is_zero && (cur_delta[i] == 0.f);
678 }
679
680 if (!is_zero)
681 {
682 // Clear AFK state if moved beyond the deadzone
683 if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
684 {
685 gAgent.clearAFK();
686 }
687
688 setCameraNeedsUpdate(true);
629 } 689 }
630 690
631 // forward|backward movements overrule the real dominant movement if 691 // forward|backward movements overrule the real dominant movement if
632 // they're bigger than its 20%. This is what you want cos moving forward 692 // they're bigger than its 20%. This is what you want 'cos moving forward
633 // is what you do most. We also added a special (even more lenient) case 693 // is what you do most. We also added a special (even more lenient) case
634 // for RX|RY to allow walking while pitching n' turning 694 // for RX|RY to allow walking while pitching and turning
635 if (fabs(cur_delta[Z_I]) > .2f * dom_mov 695 if (fabs(cur_delta[Z_I]) > .2f * dom_mov
636 || ((dom_axis == RX_I || dom_axis == RY_I) 696 || ((dom_axis == RX_I || dom_axis == RY_I)
637 && fabs(cur_delta[Z_I]) > .05f * dom_mov)) 697 && fabs(cur_delta[Z_I]) > .05f * dom_mov))
638 { 698 {
639 dom_axis = Z_I; 699 dom_axis = Z_I;
640 } 700 }
641 701
@@ -653,68 +713,66 @@ void LLViewerJoystick::moveAvatar(bool reset)
653 sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather; 713 sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather;
654 sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather; 714 sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather;
655 715
656 switch (dom_axis) 716 handleRun(fsqrtf(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I]));
657 { 717
658 case X_I: // move sideways 718 // Allow forward/backward movement some priority
659 agentSlide(sDelta[X_I]); 719 if (dom_axis == Z_I)
660 break; 720 {
661 721 agentPush(sDelta[Z_I]); // forward/back
662 case Z_I: // forward/back
663 {
664 agentPush(sDelta[Z_I]);
665
666 if (fabs(sDelta[Y_I]) > .1f)
667 {
668 agentFly(sDelta[Y_I]);
669 }
670 722
671 // too many rotations during walking can be confusing, so apply 723 if (fabs(sDelta[X_I]) > .1f)
672 // the deadzones one more time (quick & dirty), at 50%|30% power 724 {
673 F32 eff_rx = .3f * dead_zone[RX_I]; 725 agentSlide(sDelta[X_I]); // move sideways
674 F32 eff_ry = .3f * dead_zone[RY_I]; 726 }
675 727
676 if (sDelta[RX_I] > 0) 728 if (fabs(sDelta[Y_I]) > .1f)
677 { 729 {
678 eff_rx = llmax(sDelta[RX_I] - eff_rx, 0.f); 730 agentFly(sDelta[Y_I]); // up/down & crouch
679 } 731 }
680 else 732
681 { 733 // too many rotations during walking can be confusing, so apply
682 eff_rx = llmin(sDelta[RX_I] + eff_rx, 0.f); 734 // the deadzones one more time (quick & dirty), at 50%|30% power
683 } 735 F32 eff_rx = .3f * dead_zone[RX_I];
736 F32 eff_ry = .3f * dead_zone[RY_I];
737
738 if (sDelta[RX_I] > 0)
739 {
740 eff_rx = llmax(sDelta[RX_I] - eff_rx, 0.f);
741 }
742 else
743 {
744 eff_rx = llmin(sDelta[RX_I] + eff_rx, 0.f);
745 }
684 746
685 if (sDelta[RY_I] > 0) 747 if (sDelta[RY_I] > 0)
748 {
749 eff_ry = llmax(sDelta[RY_I] - eff_ry, 0.f);
750 }
751 else
752 {
753 eff_ry = llmin(sDelta[RY_I] + eff_ry, 0.f);
754 }
755
756
757 if (fabs(eff_rx) > 0.f || fabs(eff_ry) > 0.f)
758 {
759 if (gAgent.getFlying())
686 { 760 {
687 eff_ry = llmax(sDelta[RY_I] - eff_ry, 0.f); 761 agentRotate(eff_rx, eff_ry);
688 } 762 }
689 else 763 else
690 { 764 {
691 eff_ry = llmin(sDelta[RY_I] + eff_ry, 0.f); 765 agentRotate(eff_rx, 2.f * eff_ry);
692 }
693
694
695 if (fabs(eff_rx) > 0.f || fabs(eff_ry) > 0.f)
696 {
697 if (gAgent.getFlying())
698 {
699 agentRotate(eff_rx, eff_ry);
700 }
701 else
702 {
703 agentRotate(eff_rx, 2.f * eff_ry);
704 }
705 } 766 }
706 break; 767 }
707 } 768 }
708 case Y_I: // up/crouch 769 else
709 agentFly(sDelta[Y_I]); 770 {
710 break; 771 agentSlide(sDelta[X_I]); // move sideways
711 772 agentFly(sDelta[Y_I]); // up/down & crouch
712 case RX_I: // pitch 773 agentPush(sDelta[Z_I]); // forward/back
713 case RY_I: // turn 774 agentRotate(sDelta[RX_I], sDelta[RY_I]); // pitch & turn
714 agentRotate(sDelta[RX_I], sDelta[RY_I]); 775 }
715 break;
716 // case RZ_I: roll is unused in avatar mode
717 }// switch
718} 776}
719 777
720// ----------------------------------------------------------------------------- 778// -----------------------------------------------------------------------------
@@ -777,7 +835,7 @@ void LLViewerJoystick::moveFlycam(bool reset)
777 835
778 F32 time = gFrameIntervalSeconds; 836 F32 time = gFrameIntervalSeconds;
779 837
780 // avoid making ridicously big movements if there's a big drop in fps 838 // avoid making ridiculously big movements if there's a big drop in fps
781 if (time > .2f) 839 if (time > .2f)
782 { 840 {
783 time = .2f; 841 time = .2f;
@@ -786,6 +844,7 @@ void LLViewerJoystick::moveFlycam(bool reset)
786 F32 cur_delta[7]; 844 F32 cur_delta[7];
787 F32 feather = gSavedSettings.getF32("FlycamFeathering"); 845 F32 feather = gSavedSettings.getF32("FlycamFeathering");
788 bool absolute = gSavedSettings.getBOOL("Cursor3D"); 846 bool absolute = gSavedSettings.getBOOL("Cursor3D");
847 bool is_zero = true;
789 848
790 for (U32 i = 0; i < 7; i++) 849 for (U32 i = 0; i < 7; i++)
791 { 850 {
@@ -827,6 +886,15 @@ void LLViewerJoystick::moveFlycam(bool reset)
827 } 886 }
828 887
829 sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather; 888 sDelta[i] = sDelta[i] + (cur_delta[i]-sDelta[i])*time*feather;
889
890 is_zero = is_zero && (cur_delta[i] == 0.f);
891
892 }
893
894 // Clear AFK state if moved beyond the deadzone
895 if (!is_zero && gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
896 {
897 gAgent.clearAFK();
830 } 898 }
831 899
832 sFlycamPosition += LLVector3(sDelta) * sFlycamRotation; 900 sFlycamPosition += LLVector3(sDelta) * sFlycamRotation;
@@ -875,13 +943,20 @@ bool LLViewerJoystick::toggleFlycam()
875{ 943{
876 if (!gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled")) 944 if (!gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled"))
877 { 945 {
946 mOverrideCamera = false;
878 return false; 947 return false;
879 } 948 }
949
880 if (!mOverrideCamera) 950 if (!mOverrideCamera)
881 { 951 {
882 gAgent.changeCameraToDefault(); 952 gAgent.changeCameraToDefault();
883 } 953 }
884 954
955 if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
956 {
957 gAgent.clearAFK();
958 }
959
885 mOverrideCamera = !mOverrideCamera; 960 mOverrideCamera = !mOverrideCamera;
886 if (mOverrideCamera) 961 if (mOverrideCamera)
887 { 962 {
@@ -931,7 +1006,7 @@ void LLViewerJoystick::scanJoystick()
931 toggle_flycam = 0; 1006 toggle_flycam = 0;
932 } 1007 }
933 1008
934 if (!mOverrideCamera && !LLToolMgr::getInstance()->inBuildMode()) 1009 if (!mOverrideCamera && !(LLToolMgr::getInstance()->inBuildMode() && gSavedSettings.getBOOL("JoystickBuildEnabled")))
935 { 1010 {
936 moveAvatar(); 1011 moveAvatar();
937 } 1012 }
@@ -966,10 +1041,15 @@ bool LLViewerJoystick::isLikeSpaceNavigator() const
966// ----------------------------------------------------------------------------- 1041// -----------------------------------------------------------------------------
967void LLViewerJoystick::setSNDefaults() 1042void LLViewerJoystick::setSNDefaults()
968{ 1043{
969#if LL_DARWIN 1044#if LL_DARWIN || LL_LINUX
970#define kPlatformScale 20.f 1045 const float platformScale = 20.f;
1046 const float platformScaleAvXZ = 1.f;
1047 // The SpaceNavigator doesn't act as a 3D cursor on OS X / Linux.
1048 const bool is_3d_cursor = false;
971#else 1049#else
972#define kPlatformScale 1.f 1050 const float platformScale = 1.f;
1051 const float platformScaleAvXZ = 2.f;
1052 const bool is_3d_cursor = true;
973#endif 1053#endif
974 1054
975 //gViewerWindow->alertXml("CacheWillClear"); 1055 //gViewerWindow->alertXml("CacheWillClear");
@@ -983,34 +1063,29 @@ void LLViewerJoystick::setSNDefaults()
983 gSavedSettings.setS32("JoystickAxis5", 5); // yaw 1063 gSavedSettings.setS32("JoystickAxis5", 5); // yaw
984 gSavedSettings.setS32("JoystickAxis6", -1); 1064 gSavedSettings.setS32("JoystickAxis6", -1);
985 1065
986#if LL_DARWIN 1066 gSavedSettings.setBOOL("Cursor3D", is_3d_cursor);
987 // The SpaceNavigator doesn't act as a 3D cursor on OS X.
988 gSavedSettings.setBOOL("Cursor3D", false);
989#else
990 gSavedSettings.setBOOL("Cursor3D", true);
991#endif
992 gSavedSettings.setBOOL("AutoLeveling", true); 1067 gSavedSettings.setBOOL("AutoLeveling", true);
993 gSavedSettings.setBOOL("ZoomDirect", false); 1068 gSavedSettings.setBOOL("ZoomDirect", false);
994 1069
995 gSavedSettings.setF32("AvatarAxisScale0", 1.f); 1070 gSavedSettings.setF32("AvatarAxisScale0", 1.f * platformScaleAvXZ);
996 gSavedSettings.setF32("AvatarAxisScale1", 1.f); 1071 gSavedSettings.setF32("AvatarAxisScale1", 1.f * platformScaleAvXZ);
997 gSavedSettings.setF32("AvatarAxisScale2", 1.f); 1072 gSavedSettings.setF32("AvatarAxisScale2", 1.f);
998 gSavedSettings.setF32("AvatarAxisScale4", .1f * kPlatformScale); 1073 gSavedSettings.setF32("AvatarAxisScale4", .1f * platformScale);
999 gSavedSettings.setF32("AvatarAxisScale5", .1f * kPlatformScale); 1074 gSavedSettings.setF32("AvatarAxisScale5", .1f * platformScale);
1000 gSavedSettings.setF32("AvatarAxisScale3", 0.f * kPlatformScale); 1075 gSavedSettings.setF32("AvatarAxisScale3", 0.f * platformScale);
1001 gSavedSettings.setF32("BuildAxisScale1", .3f * kPlatformScale); 1076 gSavedSettings.setF32("BuildAxisScale1", .3f * platformScale);
1002 gSavedSettings.setF32("BuildAxisScale2", .3f * kPlatformScale); 1077 gSavedSettings.setF32("BuildAxisScale2", .3f * platformScale);
1003 gSavedSettings.setF32("BuildAxisScale0", .3f * kPlatformScale); 1078 gSavedSettings.setF32("BuildAxisScale0", .3f * platformScale);
1004 gSavedSettings.setF32("BuildAxisScale4", .3f * kPlatformScale); 1079 gSavedSettings.setF32("BuildAxisScale4", .3f * platformScale);
1005 gSavedSettings.setF32("BuildAxisScale5", .3f * kPlatformScale); 1080 gSavedSettings.setF32("BuildAxisScale5", .3f * platformScale);
1006 gSavedSettings.setF32("BuildAxisScale3", .3f * kPlatformScale); 1081 gSavedSettings.setF32("BuildAxisScale3", .3f * platformScale);
1007 gSavedSettings.setF32("FlycamAxisScale1", 2.f * kPlatformScale); 1082 gSavedSettings.setF32("FlycamAxisScale1", 2.f * platformScale);
1008 gSavedSettings.setF32("FlycamAxisScale2", 2.f * kPlatformScale); 1083 gSavedSettings.setF32("FlycamAxisScale2", 2.f * platformScale);
1009 gSavedSettings.setF32("FlycamAxisScale0", 2.1f * kPlatformScale); 1084 gSavedSettings.setF32("FlycamAxisScale0", 2.1f * platformScale);
1010 gSavedSettings.setF32("FlycamAxisScale4", .1f * kPlatformScale); 1085 gSavedSettings.setF32("FlycamAxisScale4", .1f * platformScale);
1011 gSavedSettings.setF32("FlycamAxisScale5", .15f * kPlatformScale); 1086 gSavedSettings.setF32("FlycamAxisScale5", .15f * platformScale);
1012 gSavedSettings.setF32("FlycamAxisScale3", 0.f * kPlatformScale); 1087 gSavedSettings.setF32("FlycamAxisScale3", 0.f * platformScale);
1013 gSavedSettings.setF32("FlycamAxisScale6", 0.f * kPlatformScale); 1088 gSavedSettings.setF32("FlycamAxisScale6", 0.f * platformScale);
1014 1089
1015 gSavedSettings.setF32("AvatarAxisDeadZone0", .1f); 1090 gSavedSettings.setF32("AvatarAxisDeadZone0", .1f);
1016 gSavedSettings.setF32("AvatarAxisDeadZone1", .1f); 1091 gSavedSettings.setF32("AvatarAxisDeadZone1", .1f);