// ----------------------------------------------------------------------------- bool LLViewerJoystick::toggleFlycam() { if (!gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled")) { return false; } if (!mOverrideCamera) { gAgent.changeCameraToDefault(); } mOverrideCamera = !mOverrideCamera; if (mOverrideCamera) { moveFlycam(true); } else if (!LLToolMgr::getInstance()->inBuildMode()) { 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. setCameraNeedsUpdate(false); setNeedsReset(true); } return true; }
// ----------------------------------------------------------------------------- bool LLViewerJoystick::toggleFlycam() { if (!gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled")) { mOverrideCamera = false; LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_FLYCAM); return false; } if (!mOverrideCamera) { gAgentCamera.changeCameraToDefault(); } if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME) { gAgent.clearAFK(); } mOverrideCamera = !mOverrideCamera; if (mOverrideCamera) { moveFlycam(true); LLPanelStandStopFlying::setStandStopFlyingMode(LLPanelStandStopFlying::SSFM_FLYCAM); } else { // 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. setCameraNeedsUpdate(false); setNeedsReset(true); LLPanelStandStopFlying::clearStandStopFlyingMode(LLPanelStandStopFlying::SSFM_FLYCAM); } return true; }
// ----------------------------------------------------------------------------- bool LLViewerJoystick::toggleFlycam() { if (gRlvHandler.hasBehaviour(RLV_BHVR_CAMDISTMAX) || gRlvHandler.hasBehaviour(RLV_BHVR_CAMUNLOCK) // [RLVa:LF] - @camdistmax and @camunlock mean no going away! || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickFlycamEnabled")) { mOverrideCamera = false; return false; } if (!mOverrideCamera) { gAgentCamera.changeCameraToDefault(); } if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME) { gAgent.clearAFK(); } mOverrideCamera = !mOverrideCamera; if (mOverrideCamera) { moveFlycam(true); } else if (!LLToolMgr::getInstance()->inBuildMode()) { moveAvatar(true); } else { // 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. setCameraNeedsUpdate(false); setNeedsReset(true); } return true; }
// ----------------------------------------------------------------------------- void LLViewerJoystick::moveAvatar(bool reset) { if (!gFocusMgr.getAppHasFocus() || mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled") || !gSavedSettings.getBOOL("JoystickAvatarEnabled")) { 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; } bool is_zero = true; if (mBtn[1] == 1) { agentJump(); is_zero = false; } F32 axis_scale[] = { gSavedSettings.getF32("AvatarAxisScale0"), gSavedSettings.getF32("AvatarAxisScale1"), gSavedSettings.getF32("AvatarAxisScale2"), gSavedSettings.getF32("AvatarAxisScale3"), gSavedSettings.getF32("AvatarAxisScale4"), gSavedSettings.getF32("AvatarAxisScale5") }; 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; } } is_zero = is_zero && (cur_delta[i] == 0.f); } if (!is_zero) { // Clear AFK state if moved beyond the deadzone if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME) { gAgent.clearAFK(); } setCameraNeedsUpdate(true); } // 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 and 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; handleRun(F32(sqrt(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I]))); // Allow forward/backward movement some priority if (dom_axis == Z_I) { agentPush(sDelta[Z_I]); // forward/back if (fabs(sDelta[X_I]) > .1f) { agentSlide(sDelta[X_I]); // move sideways } if (fabs(sDelta[Y_I]) > .1f) { agentFly(sDelta[Y_I]); // up/down & crouch } // 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); } } } else { agentSlide(sDelta[X_I]); // move sideways agentFly(sDelta[Y_I]); // up/down & crouch agentPush(sDelta[Z_I]); // forward/back agentRotate(sDelta[RX_I], sDelta[RY_I]); // pitch & turn } }