llagent.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:183k
- /**
- * @file llagent.cpp
- * @brief LLAgent class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2010, 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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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"
- #include "llagent.h"
- #include "pipeline.h"
- #include "llagentlistener.h"
- #include "llagentwearables.h"
- #include "llagentui.h"
- #include "llanimationstates.h"
- #include "llbottomtray.h"
- #include "llcallingcard.h"
- #include "llchannelmanager.h"
- #include "llconsole.h"
- //#include "llfirstuse.h"
- #include "llfloatercamera.h"
- #include "llfloatercustomize.h"
- #include "llfloaterreg.h"
- #include "llfloatertools.h"
- #include "llgroupactions.h"
- #include "llgroupmgr.h"
- #include "llhomelocationresponder.h"
- #include "llhudmanager.h"
- #include "lljoystickbutton.h"
- #include "llmorphview.h"
- #include "llmoveview.h"
- #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state
- #include "llnearbychatbar.h"
- #include "llnotificationsutil.h"
- #include "llparcel.h"
- #include "llsdutil.h"
- #include "llsidetray.h"
- #include "llsky.h"
- #include "llsmoothstep.h"
- #include "llstatusbar.h"
- #include "llteleportflags.h"
- #include "lltool.h"
- #include "lltoolmgr.h"
- #include "lltrans.h"
- #include "llviewercontrol.h"
- #include "llviewerdisplay.h"
- #include "llviewerjoystick.h"
- #include "llviewermediafocus.h"
- #include "llviewerobjectlist.h"
- #include "llviewerparcelmgr.h"
- #include "llviewerstats.h"
- #include "llvoavatarself.h"
- #include "llwindow.h"
- #include "llworld.h"
- #include "llworldmap.h"
- using namespace LLVOAvatarDefines;
- extern LLMenuBarGL* gMenuBarView;
- const BOOL ANIMATE = TRUE;
- const U8 AGENT_STATE_TYPING = 0x04;
- const U8 AGENT_STATE_EDITING = 0x10;
- //drone wandering constants
- const F32 MAX_WANDER_TIME = 20.f; // seconds
- const F32 MAX_HEADING_HALF_ERROR = 0.2f; // radians
- const F32 WANDER_MAX_SLEW_RATE = 2.f * DEG_TO_RAD; // radians / frame
- const F32 WANDER_TARGET_MIN_DISTANCE = 10.f; // meters
- // Autopilot constants
- const F32 AUTOPILOT_HEADING_HALF_ERROR = 10.f * DEG_TO_RAD; // radians
- const F32 AUTOPILOT_MAX_SLEW_RATE = 1.f * DEG_TO_RAD; // radians / frame
- const F32 AUTOPILOT_STOP_DISTANCE = 2.f; // meters
- const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f; // meters
- const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters
- const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f; // seconds
- // face editing constants
- const LLVector3d FACE_EDIT_CAMERA_OFFSET(0.4f, -0.05f, 0.07f);
- const LLVector3d FACE_EDIT_TARGET_OFFSET(0.f, 0.f, 0.05f);
- // Mousewheel camera zoom
- const F32 MIN_ZOOM_FRACTION = 0.25f;
- const F32 INITIAL_ZOOM_FRACTION = 1.f;
- const F32 MAX_ZOOM_FRACTION = 8.f;
- const F32 METERS_PER_WHEEL_CLICK = 1.f;
- const F32 MAX_TIME_DELTA = 1.f;
- const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f; // seconds
- const F32 FOV_ZOOM_HALF_LIFE = 0.07f; // seconds
- const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f;
- const F32 CAMERA_LAG_HALF_LIFE = 0.25f;
- const F32 MIN_CAMERA_LAG = 0.5f;
- const F32 MAX_CAMERA_LAG = 5.f;
- const F32 CAMERA_COLLIDE_EPSILON = 0.1f;
- const F32 MIN_CAMERA_DISTANCE = 0.1f;
- const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.55f;
- const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.7f;
- const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 1.15f;
- const F32 MAX_CAMERA_DISTANCE_FROM_AGENT = 50.f;
- const F32 MAX_CAMERA_SMOOTH_DISTANCE = 50.0f;
- const F32 HEAD_BUFFER_SIZE = 0.3f;
- const F32 CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP = 0.2f;
- const F32 LAND_MIN_ZOOM = 0.15f;
- const F32 AVATAR_MIN_ZOOM = 0.5f;
- const F32 OBJECT_MIN_ZOOM = 0.02f;
- const F32 APPEARANCE_MIN_ZOOM = 0.39f;
- const F32 APPEARANCE_MAX_ZOOM = 8.f;
- // fidget constants
- const F32 MIN_FIDGET_TIME = 8.f; // seconds
- const F32 MAX_FIDGET_TIME = 20.f; // seconds
- const S32 MAX_NUM_CHAT_POSITIONS = 10;
- const F32 GROUND_TO_AIR_CAMERA_TRANSITION_TIME = 0.5f;
- const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f;
- const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f;
- const F32 MAX_FOCUS_OFFSET = 20.f;
- const F32 OBJECT_EXTENTS_PADDING = 0.5f;
- const F32 MIN_RADIUS_ALPHA_SIZZLE = 0.5f;
- const F64 CHAT_AGE_FAST_RATE = 3.0;
- // The agent instance.
- LLAgent gAgent;
- //--------------------------------------------------------------------
- // Statics
- //
- const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f;
- std::map<std::string, std::string> LLAgent::sTeleportErrorMessages;
- std::map<std::string, std::string> LLAgent::sTeleportProgressMessages;
- class LLAgentFriendObserver : public LLFriendObserver
- {
- public:
- LLAgentFriendObserver() {}
- virtual ~LLAgentFriendObserver() {}
- virtual void changed(U32 mask);
- };
- void LLAgentFriendObserver::changed(U32 mask)
- {
- // if there's a change we're interested in.
- if((mask & (LLFriendObserver::POWERS)) != 0)
- {
- gAgent.friendsChanged();
- }
- }
- bool handleSlowMotionAnimation(const LLSD& newvalue)
- {
- if (newvalue.asBoolean())
- {
- gAgent.getAvatarObject()->setAnimTimeFactor(0.2f);
- }
- else
- {
- gAgent.getAvatarObject()->setAnimTimeFactor(1.0f);
- }
- return true;
- }
- // ************************************************************
- // Enabled this definition to compile a 'hacked' viewer that
- // locally believes the end user has godlike powers.
- // #define HACKED_GODLIKE_VIEWER
- // For a toggled version, see viewer.h for the
- // TOGGLE_HACKED_GODLIKE_VIEWER define, instead.
- // ************************************************************
- // Constructors and Destructors
- // JC - Please try to make this order match the order in the header
- // file. Otherwise it's hard to find variables that aren't initialized.
- //-----------------------------------------------------------------------------
- // LLAgent()
- //-----------------------------------------------------------------------------
- LLAgent::LLAgent() :
- mDrawDistance( DEFAULT_FAR_PLANE ),
- mGroupPowers(0),
- mHideGroupTitle(FALSE),
- mGroupID(),
- mLookAt(NULL),
- mPointAt(NULL),
- mHUDTargetZoom(1.f),
- mHUDCurZoom(1.f),
- mInitialized(FALSE),
- mListener(),
- mForceMouselook(FALSE),
- mDoubleTapRunTimer(),
- mDoubleTapRunMode(DOUBLETAP_NONE),
- mbAlwaysRun(false),
- mbRunning(false),
- mAgentAccess(gSavedSettings),
- mTeleportState( TELEPORT_NONE ),
- mRegionp(NULL),
- mAgentOriginGlobal(),
- mPositionGlobal(),
- mDistanceTraveled(0.F),
- mLastPositionGlobal(LLVector3d::zero),
- mAvatarObject(NULL),
- mRenderState(0),
- mTypingTimer(),
- mCameraMode( CAMERA_MODE_THIRD_PERSON ),
- mLastCameraMode( CAMERA_MODE_THIRD_PERSON ),
- mViewsPushed(FALSE),
- mCameraPreset(CAMERA_PRESET_REAR_VIEW),
- mCustomAnim(FALSE),
- mShowAvatar(TRUE),
- mCameraAnimating( FALSE ),
- mAnimationCameraStartGlobal(),
- mAnimationFocusStartGlobal(),
- mAnimationTimer(),
- mAnimationDuration(0.33f),
-
- mCameraFOVZoomFactor(0.f),
- mCameraCurrentFOVZoomFactor(0.f),
- mCameraFocusOffset(),
- mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW),
- mCameraCollidePlane(),
- mCurrentCameraDistance(2.f), // meters, set in init()
- mTargetCameraDistance(2.f),
- mCameraZoomFraction(1.f), // deprecated
- mThirdPersonHeadOffset(0.f, 0.f, 1.f),
- mSitCameraEnabled(FALSE),
- mCameraSmoothingLastPositionGlobal(),
- mCameraSmoothingLastPositionAgent(),
- mCameraSmoothingStop(FALSE),
- mCameraUpVector(LLVector3::z_axis), // default is straight up
- mFocusOnAvatar(TRUE),
- mFocusGlobal(),
- mFocusTargetGlobal(),
- mFocusObject(NULL),
- mFocusObjectDist(0.f),
- mFocusObjectOffset(),
- mFocusDotRadius( 0.1f ), // meters
- mTrackFocusObject(TRUE),
- mUIOffset(0.f),
- mFrameAgent(),
- mIsBusy(FALSE),
- mAtKey(0), // Either 1, 0, or -1... indicates that movement-key is pressed
- mWalkKey(0), // like AtKey, but causes less forward thrust
- mLeftKey(0),
- mUpKey(0),
- mYawKey(0.f),
- mPitchKey(0.f),
- mOrbitLeftKey(0.f),
- mOrbitRightKey(0.f),
- mOrbitUpKey(0.f),
- mOrbitDownKey(0.f),
- mOrbitInKey(0.f),
- mOrbitOutKey(0.f),
- mPanUpKey(0.f),
- mPanDownKey(0.f),
- mPanLeftKey(0.f),
- mPanRightKey(0.f),
- mPanInKey(0.f),
- mPanOutKey(0.f),
- mControlFlags(0x00000000),
- mbFlagsDirty(FALSE),
- mbFlagsNeedReset(FALSE),
- mbJump(FALSE),
- mAutoPilot(FALSE),
- mAutoPilotFlyOnStop(FALSE),
- mAutoPilotTargetGlobal(),
- mAutoPilotStopDistance(1.f),
- mAutoPilotUseRotation(FALSE),
- mAutoPilotTargetFacing(LLVector3::zero),
- mAutoPilotTargetDist(0.f),
- mAutoPilotNoProgressFrameCount(0),
- mAutoPilotRotationThreshold(0.f),
- mAutoPilotFinishedCallback(NULL),
- mAutoPilotCallbackData(NULL),
-
- mEffectColor(LLColor4(0.f, 1.f, 1.f, 1.f)),
- mHaveHomePosition(FALSE),
- mHomeRegionHandle( 0 ),
- mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f),
- mNextFidgetTime(0.f),
- mCurrentFidget(0),
- mFirstLogin(FALSE),
- mGenderChosen(FALSE),
- mAppearanceSerialNum(0)
- {
- for (U32 i = 0; i < TOTAL_CONTROLS; i++)
- {
- mControlsTakenCount[i] = 0;
- mControlsTakenPassedOnCount[i] = 0;
- }
- mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
- mListener.reset(new LLAgentListener(*this));
- }
- // Requires gSavedSettings to be initialized.
- //-----------------------------------------------------------------------------
- // init()
- //-----------------------------------------------------------------------------
- void LLAgent::init()
- {
- gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE);
- gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2));
-
- mDrawDistance = gSavedSettings.getF32("RenderFarClip");
- // *Note: this is where LLViewerCamera::getInstance() used to be constructed.
- LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW);
- // Leave at 0.1 meters until we have real near clip management
- LLViewerCamera::getInstance()->setNear(0.1f);
- LLViewerCamera::getInstance()->setFar(mDrawDistance); // if you want to change camera settings, do so in camera.h
- LLViewerCamera::getInstance()->setAspect( gViewerWindow->getWorldViewAspectRatio() ); // default, overridden in LLViewerWindow::reshape
- LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape
- setFlying( gSavedSettings.getBOOL("FlyingAtExit") );
- mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild"));
-
- mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPreset");
- mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getVector3("CameraOffsetRearView");
- mCameraOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getVector3("CameraOffsetFrontView");
- mCameraOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getVector3("CameraOffsetGroupView");
- mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getVector3d("FocusOffsetRearView");
- mFocusOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getVector3d("FocusOffsetFrontView");
- mFocusOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getVector3d("FocusOffsetGroupView");
- mCameraCollidePlane.clearVec();
- mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale");
- mTargetCameraDistance = mCurrentCameraDistance;
- mCameraZoomFraction = 1.f;
- mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject");
- mEffectColor = LLUIColorTable::instance().getColor("EffectColor");
- gSavedSettings.getControl("PreferredMaturity")->getValidateSignal()->connect(boost::bind(&LLAgent::validateMaturity, this, _2));
- gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLAgent::handleMaturity, this, _2));
-
- mInitialized = TRUE;
- }
- //-----------------------------------------------------------------------------
- // cleanup()
- //-----------------------------------------------------------------------------
- void LLAgent::cleanup()
- {
- setSitCamera(LLUUID::null);
- mAvatarObject = NULL;
- if(mLookAt)
- {
- mLookAt->markDead() ;
- mLookAt = NULL;
- }
- if(mPointAt)
- {
- mPointAt->markDead() ;
- mPointAt = NULL;
- }
- mRegionp = NULL;
- setFocusObject(NULL);
- }
- //-----------------------------------------------------------------------------
- // LLAgent()
- //-----------------------------------------------------------------------------
- LLAgent::~LLAgent()
- {
- cleanup();
- // *Note: this is where LLViewerCamera::getInstance() used to be deleted.
- }
- // Change camera back to third person, stop the autopilot,
- // deselect stuff, etc.
- //-----------------------------------------------------------------------------
- // resetView()
- //-----------------------------------------------------------------------------
- void LLAgent::resetView(BOOL reset_camera, BOOL change_camera)
- {
- if (mAutoPilot)
- {
- stopAutoPilot(TRUE);
- }
- if (!gNoRender)
- {
- LLSelectMgr::getInstance()->unhighlightAll();
- // By popular request, keep land selection while walking around. JC
- // LLViewerParcelMgr::getInstance()->deselectLand();
- // force deselect when walking and attachment is selected
- // this is so people don't wig out when their avatar moves without animating
- if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
- {
- LLSelectMgr::getInstance()->deselectAll();
- }
- // Hide all popup menus
- gMenuHolder->hideMenus();
- }
- if (change_camera && !gSavedSettings.getBOOL("FreezeTime"))
- {
- changeCameraToDefault();
-
- if (LLViewerJoystick::getInstance()->getOverrideCamera())
- {
- handle_toggle_flycam();
- }
- // reset avatar mode from eventual residual motion
- if (LLToolMgr::getInstance()->inBuildMode())
- {
- LLViewerJoystick::getInstance()->moveAvatar(true);
- }
- //Camera Tool is needed for Free Camera Control Mode
- if (!LLFloaterCamera::inFreeCameraMode())
- {
- LLFloaterReg::hideInstance("build");
- // Switch back to basic toolset
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- }
-
- gViewerWindow->showCursor();
- }
- if (reset_camera && !gSavedSettings.getBOOL("FreezeTime"))
- {
- if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson())
- {
- // leaving mouse-steer mode
- LLVector3 agent_at_axis = getAtAxis();
- agent_at_axis -= projected_vec(agent_at_axis, getReferenceUpVector());
- agent_at_axis.normalize();
- gAgent.resetAxes(lerp(getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f)));
- }
- setFocusOnAvatar(TRUE, ANIMATE);
- mCameraFOVZoomFactor = 0.f;
- }
- mHUDTargetZoom = 1.f;
- }
- // Handle any actions that need to be performed when the main app gains focus
- // (such as through alt-tab).
- //-----------------------------------------------------------------------------
- // onAppFocusGained()
- //-----------------------------------------------------------------------------
- void LLAgent::onAppFocusGained()
- {
- if (CAMERA_MODE_MOUSELOOK == mCameraMode)
- {
- changeCameraToDefault();
- LLToolMgr::getInstance()->clearSavedTool();
- }
- }
- void LLAgent::ageChat()
- {
- if (mAvatarObject.notNull())
- {
- // get amount of time since I last chatted
- F64 elapsed_time = (F64)mAvatarObject->mChatTimer.getElapsedTimeF32();
- // add in frame time * 3 (so it ages 4x)
- mAvatarObject->mChatTimer.setAge(elapsed_time + (F64)gFrameDTClamped * (CHAT_AGE_FAST_RATE - 1.0));
- }
- }
- // Allow camera to be moved somewhere other than behind avatar.
- //-----------------------------------------------------------------------------
- // unlockView()
- //-----------------------------------------------------------------------------
- void LLAgent::unlockView()
- {
- if (getFocusOnAvatar())
- {
- if (mAvatarObject.notNull())
- {
- setFocusGlobal( LLVector3d::zero, mAvatarObject->mID );
- }
- setFocusOnAvatar(FALSE, FALSE); // no animation
- }
- }
- //-----------------------------------------------------------------------------
- // moveAt()
- //-----------------------------------------------------------------------------
- void LLAgent::moveAt(S32 direction, bool reset)
- {
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- setKey(direction, mAtKey);
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT);
- }
- if (reset)
- {
- resetView();
- }
- }
- //-----------------------------------------------------------------------------
- // moveAtNudge()
- //-----------------------------------------------------------------------------
- void LLAgent::moveAtNudge(S32 direction)
- {
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- setKey(direction, mWalkKey);
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_AT_POS);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_AT_NEG);
- }
- resetView();
- }
- //-----------------------------------------------------------------------------
- // moveLeft()
- //-----------------------------------------------------------------------------
- void LLAgent::moveLeft(S32 direction)
- {
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- setKey(direction, mLeftKey);
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT);
- }
- resetView();
- }
- //-----------------------------------------------------------------------------
- // moveLeftNudge()
- //-----------------------------------------------------------------------------
- void LLAgent::moveLeftNudge(S32 direction)
- {
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- setKey(direction, mLeftKey);
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_LEFT_POS);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_NUDGE_LEFT_NEG);
- }
- resetView();
- }
- //-----------------------------------------------------------------------------
- // moveUp()
- //-----------------------------------------------------------------------------
- void LLAgent::moveUp(S32 direction)
- {
- // age chat timer so it fades more quickly when you are intentionally moving
- ageChat();
- setKey(direction, mUpKey);
- if (direction > 0)
- {
- setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP);
- }
- else if (direction < 0)
- {
- setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP);
- }
- resetView();
- }
- //-----------------------------------------------------------------------------
- // moveYaw()
- //-----------------------------------------------------------------------------
- void LLAgent::moveYaw(F32 mag, bool reset_view)
- {
- mYawKey = mag;
- if (mag > 0)
- {
- setControlFlags(AGENT_CONTROL_YAW_POS);
- }
- else if (mag < 0)
- {
- setControlFlags(AGENT_CONTROL_YAW_NEG);
- }
- if (reset_view)
- {
- resetView();
- }
- }
- //-----------------------------------------------------------------------------
- // movePitch()
- //-----------------------------------------------------------------------------
- void LLAgent::movePitch(F32 mag)
- {
- mPitchKey = mag;
- if (mag > 0)
- {
- setControlFlags(AGENT_CONTROL_PITCH_POS);
- }
- else if (mag < 0)
- {
- setControlFlags(AGENT_CONTROL_PITCH_NEG);
- }
- }
- // Does this parcel allow you to fly?
- BOOL LLAgent::canFly()
- {
- if (isGodlike()) return TRUE;
- LLViewerRegion* regionp = getRegion();
- if (regionp && regionp->getBlockFly()) return FALSE;
-
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (!parcel) return FALSE;
- // Allow owners to fly on their own land.
- if (LLViewerParcelMgr::isParcelOwnedByAgent(parcel, GP_LAND_ALLOW_FLY))
- {
- return TRUE;
- }
- return parcel->getAllowFly();
- }
- BOOL LLAgent::getFlying() const
- {
- return mControlFlags & AGENT_CONTROL_FLY;
- }
- //-----------------------------------------------------------------------------
- // setFlying()
- //-----------------------------------------------------------------------------
- void LLAgent::setFlying(BOOL fly)
- {
- if (mAvatarObject.notNull())
- {
- // *HACK: Don't allow to start the flying mode if we got ANIM_AGENT_STANDUP signal
- // because in this case we won't get a signal to start avatar flying animation and
- // it will be walking with flying mode "ON" indication. However we allow to switch
- // the flying mode off if we get ANIM_AGENT_STANDUP signal. See process_avatar_animation().
- // See EXT-2781.
- if(fly && mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end())
- {
- return;
- }
- // don't allow taking off while sitting
- if (fly && mAvatarObject->isSitting())
- {
- return;
- }
- }
- if (fly)
- {
- BOOL was_flying = getFlying();
- if (!canFly() && !was_flying)
- {
- // parcel doesn't let you start fly
- // gods can always fly
- // and it's OK if you're already flying
- make_ui_sound("UISndBadKeystroke");
- return;
- }
- if( !was_flying )
- {
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT);
- }
- setControlFlags(AGENT_CONTROL_FLY);
- }
- else
- {
- clearControlFlags(AGENT_CONTROL_FLY);
- }
- // Update Movement Controls according to Fly mode
- LLFloaterMove::setFlyingMode(fly);
- mbFlagsDirty = TRUE;
- }
- // UI based mechanism of setting fly state
- //-----------------------------------------------------------------------------
- // toggleFlying()
- //-----------------------------------------------------------------------------
- // static
- void LLAgent::toggleFlying()
- {
- BOOL fly = !gAgent.getFlying();
- gAgent.setFlying( fly );
- gAgent.resetView();
- }
- // static
- bool LLAgent::enableFlying()
- {
- BOOL sitting = FALSE;
- if (gAgent.getAvatarObject())
- {
- sitting = gAgent.getAvatarObject()->isSitting();
- }
- return !sitting;
- }
- void LLAgent::standUp()
- {
- setControlFlags(AGENT_CONTROL_STAND_UP);
- }
- //-----------------------------------------------------------------------------
- // setRegion()
- //-----------------------------------------------------------------------------
- void LLAgent::setRegion(LLViewerRegion *regionp)
- {
- llassert(regionp);
- if (mRegionp != regionp)
- {
- // std::string host_name;
- // host_name = regionp->getHost().getHostName();
- std::string ip = regionp->getHost().getString();
- llinfos << "Moving agent into region: " << regionp->getName()
- << " located at " << ip << llendl;
- if (mRegionp)
- {
- // We've changed regions, we're now going to change our agent coordinate frame.
- mAgentOriginGlobal = regionp->getOriginGlobal();
- LLVector3d agent_offset_global = mRegionp->getOriginGlobal();
- LLVector3 delta;
- delta.setVec(regionp->getOriginGlobal() - mRegionp->getOriginGlobal());
- setPositionAgent(getPositionAgent() - delta);
- LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin();
- LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta);
- // Update all of the regions.
- LLWorld::getInstance()->updateAgentOffset(agent_offset_global);
- // Hack to keep sky in the agent's region, otherwise it may get deleted - DJS 08/02/02
- // *TODO: possibly refactor into gSky->setAgentRegion(regionp)? -Brad
- if (gSky.mVOSkyp)
- {
- gSky.mVOSkyp->setRegion(regionp);
- }
- if (gSky.mVOGroundp)
- {
- gSky.mVOGroundp->setRegion(regionp);
- }
- }
- else
- {
- // First time initialization.
- // We've changed regions, we're now going to change our agent coordinate frame.
- mAgentOriginGlobal = regionp->getOriginGlobal();
- LLVector3 delta;
- delta.setVec(regionp->getOriginGlobal());
- setPositionAgent(getPositionAgent() - delta);
- LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin();
- LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta);
- // Update all of the regions.
- LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal);
- }
- }
- mRegionp = regionp;
- // Must shift hole-covering water object locations because local
- // coordinate frame changed.
- LLWorld::getInstance()->updateWaterObjects();
- // keep a list of regions we've been too
- // this is just an interesting stat, logged at the dataserver
- // we could trake this at the dataserver side, but that's harder
- U64 handle = regionp->getHandle();
- mRegionsVisited.insert(handle);
- LLSelectMgr::getInstance()->updateSelectionCenter();
- LLFloaterMove::sUpdateFlyingStatus();
- }
- //-----------------------------------------------------------------------------
- // getRegion()
- //-----------------------------------------------------------------------------
- LLViewerRegion *LLAgent::getRegion() const
- {
- return mRegionp;
- }
- LLHost LLAgent::getRegionHost() const
- {
- if (mRegionp)
- {
- return mRegionp->getHost();
- }
- else
- {
- return LLHost::invalid;
- }
- }
- //-----------------------------------------------------------------------------
- // inPrelude()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::inPrelude()
- {
- return mRegionp && mRegionp->isPrelude();
- }
- //-----------------------------------------------------------------------------
- // canManageEstate()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::canManageEstate() const
- {
- return mRegionp && mRegionp->canManageEstate();
- }
- //-----------------------------------------------------------------------------
- // sendMessage()
- //-----------------------------------------------------------------------------
- void LLAgent::sendMessage()
- {
- if (gDisconnected)
- {
- llwarns << "Trying to send message when disconnected!" << llendl;
- return;
- }
- if (!mRegionp)
- {
- llerrs << "No region for agent yet!" << llendl;
- return;
- }
- gMessageSystem->sendMessage(mRegionp->getHost());
- }
- //-----------------------------------------------------------------------------
- // sendReliableMessage()
- //-----------------------------------------------------------------------------
- void LLAgent::sendReliableMessage()
- {
- if (gDisconnected)
- {
- lldebugs << "Trying to send message when disconnected!" << llendl;
- return;
- }
- if (!mRegionp)
- {
- lldebugs << "LLAgent::sendReliableMessage No region for agent yet, not sending message!" << llendl;
- return;
- }
- gMessageSystem->sendReliable(mRegionp->getHost());
- }
- //-----------------------------------------------------------------------------
- // getVelocity()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::getVelocity() const
- {
- if (mAvatarObject.notNull())
- {
- return mAvatarObject->getVelocity();
- }
- else
- {
- return LLVector3::zero;
- }
- }
- //-----------------------------------------------------------------------------
- // setPositionAgent()
- //-----------------------------------------------------------------------------
- void LLAgent::setPositionAgent(const LLVector3 &pos_agent)
- {
- if (!pos_agent.isFinite())
- {
- llerrs << "setPositionAgent is not a number" << llendl;
- }
- if (mAvatarObject.notNull() && mAvatarObject->getParent())
- {
- LLVector3 pos_agent_sitting;
- LLVector3d pos_agent_d;
- LLViewerObject *parent = (LLViewerObject*)mAvatarObject->getParent();
- pos_agent_sitting = mAvatarObject->getPosition() * parent->getRotation() + parent->getPositionAgent();
- pos_agent_d.setVec(pos_agent_sitting);
- mFrameAgent.setOrigin(pos_agent_sitting);
- mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
- }
- else
- {
- mFrameAgent.setOrigin(pos_agent);
- LLVector3d pos_agent_d;
- pos_agent_d.setVec(pos_agent);
- mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
- }
- }
- //-----------------------------------------------------------------------------
- // slamLookAt()
- //-----------------------------------------------------------------------------
- void LLAgent::slamLookAt(const LLVector3 &look_at)
- {
- LLVector3 look_at_norm = look_at;
- look_at_norm.mV[VZ] = 0.f;
- look_at_norm.normalize();
- resetAxes(look_at_norm);
- }
- //-----------------------------------------------------------------------------
- // getPositionGlobal()
- //-----------------------------------------------------------------------------
- const LLVector3d &LLAgent::getPositionGlobal() const
- {
- if (mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull())
- {
- mPositionGlobal = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());
- }
- else
- {
- mPositionGlobal = getPosGlobalFromAgent(mFrameAgent.getOrigin());
- }
- return mPositionGlobal;
- }
- //-----------------------------------------------------------------------------
- // getPositionAgent()
- //-----------------------------------------------------------------------------
- const LLVector3 &LLAgent::getPositionAgent()
- {
- if(mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull())
- {
- mFrameAgent.setOrigin(mAvatarObject->getRenderPosition());
- }
- return mFrameAgent.getOrigin();
- }
- //-----------------------------------------------------------------------------
- // getRegionsVisited()
- //-----------------------------------------------------------------------------
- S32 LLAgent::getRegionsVisited() const
- {
- return mRegionsVisited.size();
- }
- //-----------------------------------------------------------------------------
- // getDistanceTraveled()
- //-----------------------------------------------------------------------------
- F64 LLAgent::getDistanceTraveled() const
- {
- return mDistanceTraveled;
- }
- //-----------------------------------------------------------------------------
- // getPosAgentFromGlobal()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const
- {
- LLVector3 pos_agent;
- pos_agent.setVec(pos_global - mAgentOriginGlobal);
- return pos_agent;
- }
- //-----------------------------------------------------------------------------
- // getPosGlobalFromAgent()
- //-----------------------------------------------------------------------------
- LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const
- {
- LLVector3d pos_agent_d;
- pos_agent_d.setVec(pos_agent);
- return pos_agent_d + mAgentOriginGlobal;
- }
- //-----------------------------------------------------------------------------
- // resetAxes()
- //-----------------------------------------------------------------------------
- void LLAgent::resetAxes()
- {
- mFrameAgent.resetAxes();
- }
- // Copied from LLCamera::setOriginAndLookAt
- // Look_at must be unit vector
- //-----------------------------------------------------------------------------
- // resetAxes()
- //-----------------------------------------------------------------------------
- void LLAgent::resetAxes(const LLVector3 &look_at)
- {
- LLVector3 skyward = getReferenceUpVector();
- // if look_at has zero length, fail
- // if look_at and skyward are parallel, fail
- //
- // Test both of these conditions with a cross product.
- LLVector3 cross(look_at % skyward);
- if (cross.isNull())
- {
- llinfos << "LLAgent::resetAxes cross-product is zero" << llendl;
- return;
- }
- // Make sure look_at and skyward are not parallel
- // and neither are zero length
- LLVector3 left(skyward % look_at);
- LLVector3 up(look_at % left);
- mFrameAgent.setAxes(look_at, left, up);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(F32 angle, const LLVector3 &axis)
- {
- mFrameAgent.rotate(angle, axis);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z)
- {
- mFrameAgent.rotate(angle, x, y, z);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(const LLMatrix3 &matrix)
- {
- mFrameAgent.rotate(matrix);
- }
- //-----------------------------------------------------------------------------
- // rotate()
- //-----------------------------------------------------------------------------
- void LLAgent::rotate(const LLQuaternion &quaternion)
- {
- mFrameAgent.rotate(quaternion);
- }
- //-----------------------------------------------------------------------------
- // getReferenceUpVector()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::getReferenceUpVector()
- {
- // this vector is in the coordinate frame of the avatar's parent object, or the world if none
- LLVector3 up_vector = LLVector3::z_axis;
- if (mAvatarObject.notNull() &&
- mAvatarObject->getParent() &&
- mAvatarObject->mDrawable.notNull())
- {
- U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode;
- // and in third person...
- if (camera_mode == CAMERA_MODE_THIRD_PERSON)
- {
- // make the up vector point to the absolute +z axis
- up_vector = up_vector * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
- }
- else if (camera_mode == CAMERA_MODE_MOUSELOOK)
- {
- // make the up vector point to the avatar's +z axis
- up_vector = up_vector * mAvatarObject->mDrawable->getRotation();
- }
- }
- return up_vector;
- }
- // Radians, positive is forward into ground
- //-----------------------------------------------------------------------------
- // pitch()
- //-----------------------------------------------------------------------------
- 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
- LLVector3 skyward = getReferenceUpVector();
- F32 look_down_limit;
- F32 look_up_limit = 10.f * DEG_TO_RAD;
- F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward );
- if (mAvatarObject.notNull() && mAvatarObject->isSitting())
- {
- look_down_limit = 130.f * DEG_TO_RAD;
- }
- else
- {
- look_down_limit = 170.f * DEG_TO_RAD;
- }
- // clamp pitch to limits
- if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
- {
- angle = look_down_limit - angle_from_skyward;
- }
- else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit))
- {
- angle = look_up_limit - angle_from_skyward;
- }
-
- return angle;
- }
- //-----------------------------------------------------------------------------
- // roll()
- //-----------------------------------------------------------------------------
- void LLAgent::roll(F32 angle)
- {
- mFrameAgent.roll(angle);
- }
- //-----------------------------------------------------------------------------
- // yaw()
- //-----------------------------------------------------------------------------
- void LLAgent::yaw(F32 angle)
- {
- if (!rotateGrabbed())
- {
- mFrameAgent.rotate(angle, getReferenceUpVector());
- }
- }
- // Returns a quat that represents the rotation of the agent in the absolute frame
- //-----------------------------------------------------------------------------
- // getQuat()
- //-----------------------------------------------------------------------------
- LLQuaternion LLAgent::getQuat() const
- {
- return mFrameAgent.getQuaternion();
- }
- //-----------------------------------------------------------------------------
- // calcFocusOffset()
- //-----------------------------------------------------------------------------
- LLVector3 LLAgent::calcFocusOffset(LLViewerObject *object, LLVector3 original_focus_point, S32 x, S32 y)
- {
- LLMatrix4 obj_matrix = object->getRenderMatrix();
- LLQuaternion obj_rot = object->getRenderRotation();
- LLVector3 obj_pos = object->getRenderPosition();
- BOOL is_avatar = object->isAvatar();
- // if is avatar - don't do any funk heuristics to position the focal point
- // see DEV-30589
- if (is_avatar)
- {
- return original_focus_point - obj_pos;
- }
-
- LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
- LLVector3 object_extents = object->getScale();
- // make sure they object extents are non-zero
- object_extents.clamp(0.001f, F32_MAX);
- // obj_to_cam_ray is unit vector pointing from object center to camera, in the coordinate frame of the object
- LLVector3 obj_to_cam_ray = obj_pos - LLViewerCamera::getInstance()->getOrigin();
- obj_to_cam_ray.rotVec(inv_obj_rot);
- obj_to_cam_ray.normalize();
- // obj_to_cam_ray_proportions are the (positive) ratios of
- // the obj_to_cam_ray x,y,z components with the x,y,z object dimensions.
- LLVector3 obj_to_cam_ray_proportions;
- obj_to_cam_ray_proportions.mV[VX] = llabs(obj_to_cam_ray.mV[VX] / object_extents.mV[VX]);
- obj_to_cam_ray_proportions.mV[VY] = llabs(obj_to_cam_ray.mV[VY] / object_extents.mV[VY]);
- obj_to_cam_ray_proportions.mV[VZ] = llabs(obj_to_cam_ray.mV[VZ] / object_extents.mV[VZ]);
- // find the largest ratio stored in obj_to_cam_ray_proportions
- // this corresponds to the object's local axial plane (XY, YZ, XZ) that is *most* facing the camera
- LLVector3 longest_object_axis;
- // is x-axis longest?
- if (obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VY]
- && obj_to_cam_ray_proportions.mV[VX] > obj_to_cam_ray_proportions.mV[VZ])
- {
- // then grab it
- longest_object_axis.setVec(obj_matrix.getFwdRow4());
- }
- // is y-axis longest?
- else if (obj_to_cam_ray_proportions.mV[VY] > obj_to_cam_ray_proportions.mV[VZ])
- {
- // then grab it
- longest_object_axis.setVec(obj_matrix.getLeftRow4());
- }
- // otherwise, use z axis
- else
- {
- longest_object_axis.setVec(obj_matrix.getUpRow4());
- }
- // Use this axis as the normal to project mouse click on to plane with that normal, at the object center.
- // This generates a point behind the mouse cursor that is approximately in the middle of the object in
- // terms of depth.
- // We do this to allow the camera rotation tool to "tumble" the object by rotating the camera.
- // If the focus point were the object surface under the mouse, camera rotation would introduce an undesirable
- // eccentricity to the object orientation
- LLVector3 focus_plane_normal(longest_object_axis);
- focus_plane_normal.normalize();
- LLVector3d focus_pt_global;
- gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), focus_plane_normal);
- LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global);
- // find vector from camera to focus point in object space
- LLVector3 camera_to_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin();
- camera_to_focus_vec.rotVec(inv_obj_rot);
- // find vector from object origin to focus point in object coordinates
- LLVector3 focus_offset_from_object_center = focus_pt - obj_pos;
- // convert to object-local space
- focus_offset_from_object_center.rotVec(inv_obj_rot);
- // We need to project the focus point back into the bounding box of the focused object.
- // Do this by calculating the XYZ scale factors needed to get focus offset back in bounds along the camera_focus axis
- LLVector3 clip_fraction;
- // for each axis...
- for (U32 axis = VX; axis <= VZ; axis++)
- {
- //...calculate distance that focus offset sits outside of bounding box along that axis...
- //NOTE: dist_out_of_bounds keeps the sign of focus_offset_from_object_center
- F32 dist_out_of_bounds;
- if (focus_offset_from_object_center.mV[axis] > 0.f)
- {
- dist_out_of_bounds = llmax(0.f, focus_offset_from_object_center.mV[axis] - (object_extents.mV[axis] * 0.5f));
- }
- else
- {
- dist_out_of_bounds = llmin(0.f, focus_offset_from_object_center.mV[axis] + (object_extents.mV[axis] * 0.5f));
- }
- //...then calculate the scale factor needed to push camera_to_focus_vec back in bounds along current axis
- if (llabs(camera_to_focus_vec.mV[axis]) < 0.0001f)
- {
- // don't divide by very small number
- clip_fraction.mV[axis] = 0.f;
- }
- else
- {
- clip_fraction.mV[axis] = dist_out_of_bounds / camera_to_focus_vec.mV[axis];
- }
- }
- LLVector3 abs_clip_fraction = clip_fraction;
- abs_clip_fraction.abs();
- // find axis of focus offset that is *most* outside the bounding box and use that to
- // rescale focus offset to inside object extents
- if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY]
- && abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ])
- {
- focus_offset_from_object_center -= clip_fraction.mV[VX] * camera_to_focus_vec;
- }
- else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ])
- {
- focus_offset_from_object_center -= clip_fraction.mV[VY] * camera_to_focus_vec;
- }
- else
- {
- focus_offset_from_object_center -= clip_fraction.mV[VZ] * camera_to_focus_vec;
- }
- // convert back to world space
- focus_offset_from_object_center.rotVec(obj_rot);
-
- // now, based on distance of camera from object relative to object size
- // push the focus point towards the near surface of the object when (relatively) close to the objcet
- // or keep the focus point in the object middle when (relatively) far
- // NOTE: leave focus point in middle of avatars, since the behavior you want when alt-zooming on avatars
- // is almost always "tumble about middle" and not "spin around surface point"
- if (!is_avatar)
- {
- LLVector3 obj_rel = original_focus_point - object->getRenderPosition();
-
- //now that we have the object relative position, we should bias toward the center of the object
- //based on the distance of the camera to the focus point vs. the distance of the camera to the focus
- F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis());
- F32 viewDist = dist_vec(obj_pos + obj_rel, LLViewerCamera::getInstance()->getOrigin());
- LLBBox obj_bbox = object->getBoundingBoxAgent();
- F32 bias = 0.f;
- // virtual_camera_pos is the camera position we are simulating by backing the camera off
- // and adjusting the FOV
- LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor));
- // if the camera is inside the object (large, hollow objects, for example)
- // leave focus point all the way to destination depth, away from object center
- if(!obj_bbox.containsPointAgent(virtual_camera_pos))
- {
- // perform magic number biasing of focus point towards surface vs. planar center
- bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f);
- obj_rel = lerp(focus_offset_from_object_center, obj_rel, bias);
- }
-
- focus_offset_from_object_center = obj_rel;
- }
- return focus_offset_from_object_center;
- }
- //-----------------------------------------------------------------------------
- // calcCameraMinDistance()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::calcCameraMinDistance(F32 &obj_min_distance)
- {
- BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars)
- if (!mFocusObject || mFocusObject->isDead())
- {
- obj_min_distance = 0.f;
- return TRUE;
- }
- if (mFocusObject->mDrawable.isNull())
- {
- #ifdef LL_RELEASE_FOR_DOWNLOAD
- llwarns << "Focus object with no drawable!" << llendl;
- #else
- mFocusObject->dump();
- llerrs << "Focus object with no drawable!" << llendl;
- #endif
- obj_min_distance = 0.f;
- return TRUE;
- }
-
- LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation();
- LLVector3 target_offset_origin = mFocusObjectOffset;
- LLVector3 camera_offset_target(getCameraPositionAgent() - getPosAgentFromGlobal(mFocusTargetGlobal));
- // convert offsets into object local space
- camera_offset_target.rotVec(inv_object_rot);
- target_offset_origin.rotVec(inv_object_rot);
- // push around object extents based on target offset
- LLVector3 object_extents = mFocusObject->getScale();
- if (mFocusObject->isAvatar())
- {
- // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom)
- object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR;
- object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR;
- object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR;
- soft_limit = TRUE;
- }
- LLVector3 abs_target_offset = target_offset_origin;
- abs_target_offset.abs();
- LLVector3 target_offset_dir = target_offset_origin;
- F32 object_radius = mFocusObject->getVObjRadius();
- BOOL target_outside_object_extents = FALSE;
- for (U32 i = VX; i <= VZ; i++)
- {
- if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING)
- {
- target_outside_object_extents = TRUE;
- }
- if (camera_offset_target.mV[i] > 0.f)
- {
- object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f;
- }
- else
- {
- object_extents.mV[i] += target_offset_origin.mV[i] * 2.f;
- }
- }
- // don't shrink the object extents so far that the object inverts
- object_extents.clamp(0.001f, F32_MAX);
- // move into first octant
- LLVector3 camera_offset_target_abs_norm = camera_offset_target;
- camera_offset_target_abs_norm.abs();
- // make sure offset is non-zero
- camera_offset_target_abs_norm.clamp(0.001f, F32_MAX);
- camera_offset_target_abs_norm.normalize();
- // find camera position relative to normalized object extents
- LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm;
- camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX];
- camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY];
- camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ];
- if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] &&
- camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ])
- {
- if (camera_offset_target_abs_norm.mV[VX] < 0.001f)
- {
- obj_min_distance = object_extents.mV[VX] * 0.5f;
- }
- else
- {
- obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX];
- }
- }
- else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ])
- {
- if (camera_offset_target_abs_norm.mV[VY] < 0.001f)
- {
- obj_min_distance = object_extents.mV[VY] * 0.5f;
- }
- else
- {
- obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY];
- }
- }
- else
- {
- if (camera_offset_target_abs_norm.mV[VZ] < 0.001f)
- {
- obj_min_distance = object_extents.mV[VZ] * 0.5f;
- }
- else
- {
- obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ];
- }
- }
- LLVector3 object_split_axis;
- LLVector3 target_offset_scaled = target_offset_origin;
- target_offset_scaled.abs();
- target_offset_scaled.normalize();
- target_offset_scaled.mV[VX] /= object_extents.mV[VX];
- target_offset_scaled.mV[VY] /= object_extents.mV[VY];
- target_offset_scaled.mV[VZ] /= object_extents.mV[VZ];
- if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] &&
- target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ])
- {
- object_split_axis = LLVector3::x_axis;
- }
- else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ])
- {
- object_split_axis = LLVector3::y_axis;
- }
- else
- {
- object_split_axis = LLVector3::z_axis;
- }
- LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent());
- // length projected orthogonal to target offset
- F32 camera_offset_dist = (camera_offset_object - target_offset_dir * (camera_offset_object * target_offset_dir)).magVec();
- // calculate whether the target point would be "visible" if it were outside the bounding box
- // on the opposite of the splitting plane defined by object_split_axis;
- BOOL exterior_target_visible = FALSE;
- if (camera_offset_dist > object_radius)
- {
- // target is visible from camera, so turn off fov zoom
- exterior_target_visible = TRUE;
- }
- F32 camera_offset_clip = camera_offset_object * object_split_axis;
- F32 target_offset_clip = target_offset_dir * object_split_axis;
- // target has moved outside of object extents
- // check to see if camera and target are on same side
- if (target_outside_object_extents)
- {
- if (camera_offset_clip > 0.f && target_offset_clip > 0.f)
- {
- return FALSE;
- }
- else if (camera_offset_clip < 0.f && target_offset_clip < 0.f)
- {
- return FALSE;
- }
- }
- // clamp obj distance to diagonal of 10 by 10 cube
- obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3);
- obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f);
-
- return TRUE;
- }
- F32 LLAgent::getCameraZoomFraction()
- {
- // 0.f -> camera zoomed all the way out
- // 1.f -> camera zoomed all the way in
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
- {
- // already [0,1]
- return mHUDTargetZoom;
- }
- else if (mFocusOnAvatar && cameraThirdPerson())
- {
- return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f);
- }
- else if (cameraCustomizeAvatar())
- {
- F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
- return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f );
- }
- else
- {
- F32 min_zoom;
- const F32 DIST_FUDGE = 16.f; // meters
- F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE,
- LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE,
- MAX_CAMERA_DISTANCE_FROM_AGENT);
- F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
- if (mFocusObject.notNull())
- {
- if (mFocusObject->isAvatar())
- {
- min_zoom = AVATAR_MIN_ZOOM;
- }
- else
- {
- min_zoom = OBJECT_MIN_ZOOM;
- }
- }
- else
- {
- min_zoom = LAND_MIN_ZOOM;
- }
- return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f);
- }
- }
- void LLAgent::setCameraZoomFraction(F32 fraction)
- {
- // 0.f -> camera zoomed all the way out
- // 1.f -> camera zoomed all the way in
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
- {
- mHUDTargetZoom = fraction;
- }
- else if (mFocusOnAvatar && cameraThirdPerson())
- {
- mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION);
- }
- else if (cameraCustomizeAvatar())
- {
- LLVector3d camera_offset_dir = mCameraFocusOffsetTarget;
- camera_offset_dir.normalize();
- mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM);
- }
- else
- {
- F32 min_zoom = LAND_MIN_ZOOM;
- const F32 DIST_FUDGE = 16.f; // meters
- F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE,
- LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE,
- MAX_CAMERA_DISTANCE_FROM_AGENT);
- if (mFocusObject.notNull())
- {
- if (mFocusObject.notNull())
- {
- if (mFocusObject->isAvatar())
- {
- min_zoom = AVATAR_MIN_ZOOM;
- }
- else
- {
- min_zoom = OBJECT_MIN_ZOOM;
- }
- }
- }
- LLVector3d camera_offset_dir = mCameraFocusOffsetTarget;
- camera_offset_dir.normalize();
- mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom);
- }
- startCameraAnimation();
- }
- //-----------------------------------------------------------------------------
- // cameraOrbitAround()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraOrbitAround(const F32 radians)
- {
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
- {
- // do nothing for hud selection
- }
- else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW))
- {
- mFrameAgent.rotate(radians, getReferenceUpVector());
- }
- else
- {
- mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f);
-
- cameraZoomIn(1.f);
- }
- }
- //-----------------------------------------------------------------------------
- // cameraOrbitOver()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraOrbitOver(const F32 angle)
- {
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
- {
- // do nothing for hud selection
- }
- else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
- {
- pitch(angle);
- }
- else
- {
- LLVector3 camera_offset_unit(mCameraFocusOffsetTarget);
- camera_offset_unit.normalize();
- F32 angle_from_up = acos( camera_offset_unit * getReferenceUpVector() );
- LLVector3d left_axis;
- left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
- F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD);
- mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis);
- cameraZoomIn(1.f);
- }
- }
- //-----------------------------------------------------------------------------
- // cameraZoomIn()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraZoomIn(const F32 fraction)
- {
- if (gDisconnected)
- {
- return;
- }
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
- {
- // just update hud zoom level
- mHUDTargetZoom /= fraction;
- return;
- }
- LLVector3d camera_offset(mCameraFocusOffsetTarget);
- LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
- F32 min_zoom = LAND_MIN_ZOOM;
- F32 current_distance = (F32)camera_offset_unit.normalize();
- F32 new_distance = current_distance * fraction;
- // Don't move through focus point
- if (mFocusObject)
- {
- LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]);
- if (mFocusObject->isAvatar())
- {
- calcCameraMinDistance(min_zoom);
- }
- else
- {
- min_zoom = OBJECT_MIN_ZOOM;
- }
- }
- new_distance = llmax(new_distance, min_zoom);
- // Don't zoom too far back
- const F32 DIST_FUDGE = 16.f; // meters
- F32 max_distance = llmin(mDrawDistance - DIST_FUDGE,
- LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
- if (new_distance > max_distance)
- {
- new_distance = max_distance;
- /*
- // Unless camera is unlocked
- if (!LLViewerCamera::sDisableCameraConstraints)
- {
- return;
- }
- */
- }
- if( cameraCustomizeAvatar() )
- {
- new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
- }
- mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
- }
- //-----------------------------------------------------------------------------
- // cameraOrbitIn()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraOrbitIn(const F32 meters)
- {
- if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
- {
- F32 camera_offset_dist = llmax(0.001f, getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"));
-
- mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist;
- if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f)
- {
- // No need to animate, camera is already there.
- changeCameraToMouselook(FALSE);
- }
- mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION);
- }
- else
- {
- LLVector3d camera_offset(mCameraFocusOffsetTarget);
- LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
- F32 current_distance = (F32)camera_offset_unit.normalize();
- F32 new_distance = current_distance - meters;
- F32 min_zoom = LAND_MIN_ZOOM;
-
- // Don't move through focus point
- if (mFocusObject.notNull())
- {
- if (mFocusObject->isAvatar())
- {
- min_zoom = AVATAR_MIN_ZOOM;
- }
- else
- {
- min_zoom = OBJECT_MIN_ZOOM;
- }
- }
- new_distance = llmax(new_distance, min_zoom);
- // Don't zoom too far back
- const F32 DIST_FUDGE = 16.f; // meters
- F32 max_distance = llmin(mDrawDistance - DIST_FUDGE,
- LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
- if (new_distance > max_distance)
- {
- // Unless camera is unlocked
- if (!gSavedSettings.getBOOL("DisableCameraConstraints"))
- {
- return;
- }
- }
- if( CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode() )
- {
- new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
- }
- // Compute new camera offset
- mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
- cameraZoomIn(1.f);
- }
- }
- //-----------------------------------------------------------------------------
- // cameraPanIn()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraPanIn(F32 meters)
- {
- LLVector3d at_axis;
- at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis());
- mFocusTargetGlobal += meters * at_axis;
- mFocusGlobal = mFocusTargetGlobal;
- // don't enforce zoom constraints as this is the only way for users to get past them easily
- updateFocusOffset();
- // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx
- mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
- }
- //-----------------------------------------------------------------------------
- // cameraPanLeft()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraPanLeft(F32 meters)
- {
- LLVector3d left_axis;
- left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
- mFocusTargetGlobal += meters * left_axis;
- mFocusGlobal = mFocusTargetGlobal;
- // disable smoothing for camera pan, which causes some residents unhappiness
- mCameraSmoothingStop = TRUE;
-
- cameraZoomIn(1.f);
- updateFocusOffset();
- // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind - Nyx
- mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
- }
- //-----------------------------------------------------------------------------
- // cameraPanUp()
- //-----------------------------------------------------------------------------
- void LLAgent::cameraPanUp(F32 meters)
- {
- LLVector3d up_axis;
- up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis());
- mFocusTargetGlobal += meters * up_axis;
- mFocusGlobal = mFocusTargetGlobal;
- // disable smoothing for camera pan, which causes some residents unhappiness
- mCameraSmoothingStop = TRUE;
- cameraZoomIn(1.f);
- updateFocusOffset();
- // NOTE: panning movements expect the camera to move exactly with the focus target, not animated behind -Nyx
- mCameraSmoothingLastPositionGlobal = calcCameraPositionTargetGlobal();
- }
- //-----------------------------------------------------------------------------
- // setKey()
- //-----------------------------------------------------------------------------
- void LLAgent::setKey(const S32 direction, S32 &key)
- {
- if (direction > 0)
- {
- key = 1;
- }
- else if (direction < 0)
- {
- key = -1;
- }
- else
- {
- key = 0;
- }
- }
- //-----------------------------------------------------------------------------
- // getControlFlags()
- //-----------------------------------------------------------------------------
- U32 LLAgent::getControlFlags()
- {
- /*
- // HACK -- avoids maintenance of control flags when camera mode is turned on or off,
- // only worries about it when the flags are measured
- if (mCameraMode == CAMERA_MODE_MOUSELOOK)
- {
- if ( !(mControlFlags & AGENT_CONTROL_MOUSELOOK) )
- {
- mControlFlags |= AGENT_CONTROL_MOUSELOOK;
- }
- }
- */
- return mControlFlags;
- }
- //-----------------------------------------------------------------------------
- // setControlFlags()
- //-----------------------------------------------------------------------------
- void LLAgent::setControlFlags(U32 mask)
- {
- mControlFlags |= mask;
- mbFlagsDirty = TRUE;
- }
- //-----------------------------------------------------------------------------
- // clearControlFlags()
- //-----------------------------------------------------------------------------
- void LLAgent::clearControlFlags(U32 mask)
- {
- U32 old_flags = mControlFlags;
- mControlFlags &= ~mask;
- if (old_flags != mControlFlags)
- {
- mbFlagsDirty = TRUE;
- }
- }
- //-----------------------------------------------------------------------------
- // controlFlagsDirty()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::controlFlagsDirty() const
- {
- return mbFlagsDirty;
- }
- //-----------------------------------------------------------------------------
- // enableControlFlagReset()
- //-----------------------------------------------------------------------------
- void LLAgent::enableControlFlagReset()
- {
- mbFlagsNeedReset = TRUE;
- }
- //-----------------------------------------------------------------------------
- // resetControlFlags()
- //-----------------------------------------------------------------------------
- void LLAgent::resetControlFlags()
- {
- if (mbFlagsNeedReset)
- {
- mbFlagsNeedReset = FALSE;
- mbFlagsDirty = FALSE;
- // reset all of the ephemeral flags
- // some flags are managed elsewhere
- mControlFlags &= AGENT_CONTROL_AWAY | AGENT_CONTROL_FLY | AGENT_CONTROL_MOUSELOOK;
- }
- }
- //-----------------------------------------------------------------------------
- // setAFK()
- //-----------------------------------------------------------------------------
- void LLAgent::setAFK()
- {
- // Drones can't go AFK
- if (gNoRender)
- {
- return;
- }
- if (!gAgent.getRegion())
- {
- // Don't set AFK if we're not talking to a region yet.
- return;
- }
- if (!(mControlFlags & AGENT_CONTROL_AWAY))
- {
- sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START);
- setControlFlags(AGENT_CONTROL_AWAY | AGENT_CONTROL_STOP);
- gAwayTimer.start();
- if (gAFKMenu)
- {
- gAFKMenu->setLabel(LLTrans::getString("AvatarSetNotAway"));
- }
- }
- }
- //-----------------------------------------------------------------------------
- // clearAFK()
- //-----------------------------------------------------------------------------
- void LLAgent::clearAFK()
- {
- gAwayTriggerTimer.reset();
- // Gods can sometimes get into away state (via gestures)
- // without setting the appropriate control flag. JC
- LLVOAvatar* av = mAvatarObject;
- if (mControlFlags & AGENT_CONTROL_AWAY
- || (av
- && (av->mSignaledAnimations.find(ANIM_AGENT_AWAY) != av->mSignaledAnimations.end())))
- {
- sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP);
- clearControlFlags(AGENT_CONTROL_AWAY);
- if (gAFKMenu)
- {
- gAFKMenu->setLabel(LLTrans::getString("AvatarSetAway"));
- }
- }
- }
- //-----------------------------------------------------------------------------
- // getAFK()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::getAFK() const
- {
- return (mControlFlags & AGENT_CONTROL_AWAY) != 0;
- }
- //-----------------------------------------------------------------------------
- // setBusy()
- //-----------------------------------------------------------------------------
- void LLAgent::setBusy()
- {
- sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START);
- mIsBusy = TRUE;
- if (gBusyMenu)
- {
- gBusyMenu->setLabel(LLTrans::getString("AvatarSetNotBusy"));
- }
- LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(true);
- }
- //-----------------------------------------------------------------------------
- // clearBusy()
- //-----------------------------------------------------------------------------
- void LLAgent::clearBusy()
- {
- mIsBusy = FALSE;
- sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP);
- if (gBusyMenu)
- {
- gBusyMenu->setLabel(LLTrans::getString("AvatarSetBusy"));
- }
- LLNotificationsUI::LLChannelManager::getInstance()->muteAllChannels(false);
- }
- //-----------------------------------------------------------------------------
- // getBusy()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::getBusy() const
- {
- return mIsBusy;
- }
- //-----------------------------------------------------------------------------
- // startAutoPilotGlobal()
- //-----------------------------------------------------------------------------
- void LLAgent::startAutoPilotGlobal(const LLVector3d &target_global, const std::string& behavior_name, const LLQuaternion *target_rotation, void (*finish_callback)(BOOL, void *), void *callback_data, F32 stop_distance, F32 rot_threshold)
- {
- if (!gAgent.getAvatarObject())
- {
- return;
- }
-
- mAutoPilotFinishedCallback = finish_callback;
- mAutoPilotCallbackData = callback_data;
- mAutoPilotRotationThreshold = rot_threshold;
- mAutoPilotBehaviorName = behavior_name;
- LLVector3d delta_pos( target_global );
- delta_pos -= getPositionGlobal();
- F64 distance = delta_pos.magVec();
- LLVector3d trace_target = target_global;
- trace_target.mdV[VZ] -= 10.f;
- LLVector3d intersection;
- LLVector3 normal;
- LLViewerObject *hit_obj;
- F32 heightDelta = LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, trace_target, intersection, normal, &hit_obj);
- if (stop_distance > 0.f)
- {
- mAutoPilotStopDistance = stop_distance;
- }
- else
- {
- // Guess at a reasonable stop distance.
- mAutoPilotStopDistance = fsqrtf( distance );
- if (mAutoPilotStopDistance < 0.5f)
- {
- mAutoPilotStopDistance = 0.5f;
- }
- }
- mAutoPilotFlyOnStop = getFlying();
- if (distance > 30.0)
- {
- setFlying(TRUE);
- }
- if ( distance > 1.f && heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f))
- {
- setFlying(TRUE);
- mAutoPilotFlyOnStop = TRUE;
- }
- mAutoPilot = TRUE;
- mAutoPilotTargetGlobal = target_global;
- // trace ray down to find height of destination from ground
- LLVector3d traceEndPt = target_global;
- traceEndPt.mdV[VZ] -= 20.f;
- LLVector3d targetOnGround;
- LLVector3 groundNorm;
- LLViewerObject *obj;
- LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj);
- F64 target_height = llmax((F64)gAgent.getAvatarObject()->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]);
- // clamp z value of target to minimum height above ground
- mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height;
- mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal);
- if (target_rotation)
- {
- mAutoPilotUseRotation = TRUE;
- mAutoPilotTargetFacing = LLVector3::x_axis * *target_rotation;
- mAutoPilotTargetFacing.mV[VZ] = 0.f;
- mAutoPilotTargetFacing.normalize();
- }
- else
- {
- mAutoPilotUseRotation = FALSE;
- }
- mAutoPilotNoProgressFrameCount = 0;
- }
- //-----------------------------------------------------------------------------
- // startFollowPilot()
- //-----------------------------------------------------------------------------
- void LLAgent::startFollowPilot(const LLUUID &leader_id)
- {
- if (!mAutoPilot) return;
- mLeaderID = leader_id;
- if ( mLeaderID.isNull() ) return;
- LLViewerObject* object = gObjectList.findObject(mLeaderID);
- if (!object)
- {
- mLeaderID = LLUUID::null;
- return;
- }
- startAutoPilotGlobal(object->getPositionGlobal());
- }
- //-----------------------------------------------------------------------------
- // stopAutoPilot()
- //-----------------------------------------------------------------------------
- void LLAgent::stopAutoPilot(BOOL user_cancel)
- {
- if (mAutoPilot)
- {
- mAutoPilot = FALSE;
- if (mAutoPilotUseRotation && !user_cancel)
- {
- resetAxes(mAutoPilotTargetFacing);
- }
- //NB: auto pilot can terminate for a reason other than reaching the destination
- if (mAutoPilotFinishedCallback)
- {
- mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
- }
- mLeaderID = LLUUID::null;
- // If the user cancelled, don't change the fly state
- if (!user_cancel)
- {
- setFlying(mAutoPilotFlyOnStop);
- }
- setControlFlags(AGENT_CONTROL_STOP);
- if (user_cancel && !mAutoPilotBehaviorName.empty())
- {
- if (mAutoPilotBehaviorName == "Sit")
- LLNotificationsUtil::add("CancelledSit");
- else if (mAutoPilotBehaviorName == "Attach")
- LLNotificationsUtil::add("CancelledAttach");
- else
- LLNotificationsUtil::add("Cancelled");
- }
- }
- }
- // Returns necessary agent pitch and yaw changes, radians.
- //-----------------------------------------------------------------------------
- // autoPilot()
- //-----------------------------------------------------------------------------
- void LLAgent::autoPilot(F32 *delta_yaw)
- {
- if (mAutoPilot)
- {
- if (!mLeaderID.isNull())
- {
- LLViewerObject* object = gObjectList.findObject(mLeaderID);
- if (!object)
- {
- stopAutoPilot();
- return;
- }
- mAutoPilotTargetGlobal = object->getPositionGlobal();
- }
-
- if (mAvatarObject.isNull())
- {
- return;
- }
- if (mAvatarObject->mInAir)
- {
- setFlying(TRUE);
- }
-
- LLVector3 at;
- at.setVec(mFrameAgent.getAtAxis());
- LLVector3 target_agent = getPosAgentFromGlobal(mAutoPilotTargetGlobal);
- LLVector3 direction = target_agent - getPositionAgent();
- F32 target_dist = direction.magVec();
- if (target_dist >= mAutoPilotTargetDist)
- {
- mAutoPilotNoProgressFrameCount++;
- if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped)
- {
- stopAutoPilot();
- return;
- }
- }
- mAutoPilotTargetDist = target_dist;
- // Make this a two-dimensional solution
- at.mV[VZ] = 0.f;
- direction.mV[VZ] = 0.f;
- at.normalize();
- F32 xy_distance = direction.normalize();
- F32 yaw = 0.f;
- if (mAutoPilotTargetDist > mAutoPilotStopDistance)
- {
- yaw = angle_between(mFrameAgent.getAtAxis(), direction);
- }
- else if (mAutoPilotUseRotation)
- {
- // we're close now just aim at target facing
- yaw = angle_between(at, mAutoPilotTargetFacing);
- direction = mAutoPilotTargetFacing;
- }
- yaw = 4.f * yaw / gFPSClamped;
- // figure out which direction to turn
- LLVector3 scratch(at % direction);
- if (scratch.mV[VZ] > 0.f)
- {
- setControlFlags(AGENT_CONTROL_YAW_POS);
- }
- else
- {
- yaw = -yaw;
- setControlFlags(AGENT_CONTROL_YAW_NEG);
- }
- *delta_yaw = yaw;
- // Compute when to start slowing down and when to stop
- F32 stop_distance = mAutoPilotStopDistance;
- F32 slow_distance;
- if (getFlying())
- {
- slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f);
- stop_distance = llmax(2.f, mAutoPilotStopDistance);
- }
- else
- {
- slow_distance = llmax(3.f, mAutoPilotStopDistance + 2.f);
- }
- // If we're flying, handle autopilot points above or below you.
- if (getFlying() && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE)
- {
- if (mAvatarObject.notNull())
- {
- F64 current_height = mAvatarObject->getPositionGlobal().mdV[VZ];
- F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - current_height);
- F32 slope = delta_z / xy_distance;
- if (slope > 0.45f && delta_z > 6.f)
- {
- setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_POS);
- }
- else if (slope > 0.002f && delta_z > 0.5f)
- {
- setControlFlags(AGENT_CONTROL_UP_POS);
- }
- else if (slope < -0.45f && delta_z < -6.f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
- {
- setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_NEG);
- }
- else if (slope < -0.002f && delta_z < -0.5f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
- {
- setControlFlags(AGENT_CONTROL_UP_NEG);
- }
- }
- }
- // calculate delta rotation to target heading
- F32 delta_target_heading = angle_between(mFrameAgent.getAtAxis(), mAutoPilotTargetFacing);
- if (xy_distance > slow_distance && yaw < (F_PI / 10.f))
- {
- // walking/flying fast
- setControlFlags(AGENT_CONTROL_FAST_AT | AGENT_CONTROL_AT_POS);
- }
- else if (mAutoPilotTargetDist > mAutoPilotStopDistance)
- {
- // walking/flying slow
- if (at * direction > 0.9f)
- {
- setControlFlags(AGENT_CONTROL_AT_POS);
- }
- else if (at * direction < -0.9f)
- {
- setControlFlags(AGENT_CONTROL_AT_NEG);
- }
- }
- // check to see if we need to keep rotating to target orientation
- if (mAutoPilotTargetDist < mAutoPilotStopDistance)
- {
- setControlFlags(AGENT_CONTROL_STOP);
- if(!mAutoPilotUseRotation || (delta_target_heading < mAutoPilotRotationThreshold))
- {
- stopAutoPilot();
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- // propagate()
- //-----------------------------------------------------------------------------
- void LLAgent::propagate(const F32 dt)
- {
- // Update UI based on agent motion
- LLFloaterMove *floater_move = LLFloaterReg::findTypedInstance<LLFloaterMove>("moveview");
- if (floater_move)
- {
- floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 );
- floater_move->mBackwardButton ->setToggleState( mAtKey < 0 || mWalkKey < 0 );
- floater_move->mTurnLeftButton ->setToggleState( mYawKey > 0.f );
- floater_move->mTurnRightButton ->setToggleState( mYawKey < 0.f );
- floater_move->mMoveUpButton ->setToggleState( mUpKey > 0 );
- floater_move->mMoveDownButton ->setToggleState( mUpKey < 0 );
- }
- // handle rotation based on keyboard levels
- const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second
- yaw(YAW_RATE * mYawKey * dt);
- const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second
- pitch(PITCH_RATE * mPitchKey * dt);
-
- // handle auto-land behavior
- if (mAvatarObject.notNull())
- {
- BOOL in_air = mAvatarObject->mInAir;
- LLVector3 land_vel = getVelocity();
- land_vel.mV[VZ] = 0.f;
- if (!in_air
- && mUpKey < 0
- && land_vel.magVecSquared() < MAX_VELOCITY_AUTO_LAND_SQUARED
- && gSavedSettings.getBOOL("AutomaticFly"))
- {
- // land automatically
- setFlying(FALSE);
- }
- }
- // clear keys
- mAtKey = 0;
- mWalkKey = 0;
- mLeftKey = 0;
- mUpKey = 0;
- mYawKey = 0.f;
- mPitchKey = 0.f;
- }
- //-----------------------------------------------------------------------------
- // updateAgentPosition()
- //-----------------------------------------------------------------------------
- void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)
- {
- propagate(dt);
- // static S32 cameraUpdateCount = 0;
- rotate(yaw_radians, 0, 0, 1);
-
- //
- // Check for water and land collision, set underwater flag
- //
- updateLookAt(mouse_x, mouse_y);
- }
- //-----------------------------------------------------------------------------
- // updateLookAt()
- //-----------------------------------------------------------------------------
- void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y)
- {
- static LLVector3 last_at_axis;
- if (mAvatarObject.isNull())
- {
- return;
- }
- LLQuaternion av_inv_rot = ~mAvatarObject->mRoot.getWorldRotation();
- LLVector3 root_at = LLVector3::x_axis * mAvatarObject->mRoot.getWorldRotation();
- if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) &&
- (root_at * last_at_axis > 0.95f ))
- {
- LLVector3 vel = mAvatarObject->getVelocity();
- if (vel.magVecSquared() > 4.f)
- {
- setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, vel * av_inv_rot);
- }
- else
- {
- // *FIX: rotate mframeagent by sit object's rotation?
- LLQuaternion look_rotation = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation
- LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot;
- setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset);
- }
- last_at_axis = root_at;
- return;
- }
- last_at_axis = root_at;
-
- if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode())
- {
- setLookAt(LOOKAT_TARGET_NONE, mAvatarObject, LLVector3(-2.f, 0.f, 0.f));
- }
- else
- {
- // Move head based on cursor position
- ELookAtType lookAtType = LOOKAT_TARGET_NONE;
- LLVector3 headLookAxis;
- LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance());
- if (cameraMouselook())
- {
- lookAtType = LOOKAT_TARGET_MOUSELOOK;
- }
- else if (cameraThirdPerson())
- {
- // range from -.5 to .5
- F32 x_from_center =
- ((F32) mouse_x / (F32) gViewerWindow->getWindowWidthScaled() ) - 0.5f;
- F32 y_from_center =
- ((F32) mouse_y / (F32) gViewerWindow->getWindowHeightScaled() ) - 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;
- }
- headLookAxis = frameCamera.getAtAxis();
- // RN: we use world-space offset for mouselook and freelook
- //headLookAxis = headLookAxis * av_inv_rot;
- setLookAt(lookAtType, mAvatarObject, headLookAxis);
- }
- }
- // friends and operators
- std::ostream& operator<<(std::ostream &s, const LLAgent &agent)
- {
- // This is unfinished, but might never be used.
- // We'll just leave it for now; we can always delete it.
- s << " { "
- << " Frame = " << agent.mFrameAgent << "n"
- << " }";
- return s;
- }
- // ------------------- Beginning of legacy LLCamera hack ----------------------
- // This section is included for legacy LLCamera support until
- // it is no longer needed. Some legacy code must exist in
- // non-legacy functions, and is labeled with "// legacy" comments.
- //-----------------------------------------------------------------------------
- // setAvatarObject()
- //-----------------------------------------------------------------------------
- void LLAgent::setAvatarObject(LLVOAvatarSelf *avatar)
- {
- mAvatarObject = avatar;
- if (!avatar)
- {
- llinfos << "Setting LLAgent::mAvatarObject to NULL" << llendl;
- return;
- }
- if (!mLookAt)
- {
- mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT);
- }
- if (!mPointAt)
- {
- mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT);
- }
-
- if (!mLookAt.isNull())
- {
- mLookAt->setSourceObject(avatar);
- }
- if (!mPointAt.isNull())
- {
- mPointAt->setSourceObject(avatar);
- }
- }
- // TRUE if your own avatar needs to be rendered. Usually only
- // in third person and build.
- //-----------------------------------------------------------------------------
- // needsRenderAvatar()
- //-----------------------------------------------------------------------------
- BOOL LLAgent::needsRenderAvatar()
- {
- if (cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson)
- {
- return FALSE;
- }
- return mShowAvatar && mGenderChosen;
- }
- // TRUE if we need to render your own avatar's head.
- BOOL LLAgent::needsRenderHead()
- {
- return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !cameraMouselook());
- }
- //-----------------------------------------------------------------------------
- // startTyping()
- //-----------------------------------------------------------------------------
- void LLAgent::startTyping()
- {
- mTypingTimer.reset();
- if (getRenderState() & AGENT_STATE_TYPING)
- {
- // already typing, don't trigger a different animation
- return;
- }
- setRenderState(AGENT_STATE_TYPING);
- if (mChatTimer.getElapsedTimeF32() < 2.f)
- {
- LLViewerObject* chatter = gObjectList.findObject(mLastChatterID);
- if (chatter && chatter->isAvatar())
- {
- gAgent.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero);
- }
- }
- if (gSavedSettings.getBOOL("PlayTypingAnim"))
- {
- sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);
- }
- LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
- }
- //-----------------------------------------------------------------------------
- // stopTyping()
- //-----------------------------------------------------------------------------
- void LLAgent::stopTyping()
- {
- if (mRenderState & AGENT_STATE_TYPING)
- {
- clearRenderState(AGENT_STATE_TYPING);
- sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP);
- LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
- }
- }
- //-----------------------------------------------------------------------------
- // setRenderState()
- //-----------------------------------------------------------------------------
- void LLAgent::setRenderState(U8 newstate)
- {
- mRenderState |= newstate;
- }
- //-----------------------------------------------------------------------------
- // clearRenderState()
- //-----------------------------------------------------------------------------
- void LLAgent::clearRenderState(U8 clearstate)
- {
- mRenderState &= ~clearstate;
- }
- //-----------------------------------------------------------------------------
- // getRenderState()
- //-----------------------------------------------------------------------------
- U8 LLAgent::getRenderState()
- {
- if (gNoRender || gKeyboard == NULL)
- {
- return 0;
- }
- // *FIX: don't do stuff in a getter! This is infinite loop city!
- if ((mTypingTimer.getElapsedTimeF32() > TYPING_TIMEOUT_SECS)
- && (mRenderState & AGENT_STATE_TYPING))
- {
- stopTyping();
- }
-
- if ((!LLSelectMgr::getInstance()->getSelection()->isEmpty() && LLSelectMgr::getInstance()->shouldShowSelection())
- || LLToolMgr::getInstance()->getCurrentTool()->isEditing() )
- {
- setRenderState(AGENT_STATE_EDITING);
- }
- else
- {
- clearRenderState(AGENT_STATE_EDITING);
- }
- return mRenderState;
- }
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // endAnimationUpdateUI()
- //-----------------------------------------------------------------------------
- void LLAgent::endAnimationUpdateUI()
- {
- if (mCameraMode == mLastCameraMode)
- {
- // We're already done endAnimationUpdateUI for this transition.
- return;
- }
- // clean up UI from mode we're leaving
- if ( mLastCameraMode == CAMERA_MODE_MOUSELOOK )
- {
- // show mouse cursor
- gViewerWindow->showCursor();
- // show menus
- gMenuBarView->setVisible(TRUE);
- LLNavigationBar::getInstance()->setVisible(TRUE);
- gStatusBar->setVisibleForMouselook(true);
- LLBottomTray::getInstance()->onMouselookModeOut();
- LLSideTray::getInstance()->getButtonsPanel()->setVisible(TRUE);
- LLSideTray::getInstance()->updateSidetrayVisibility();
- LLPanelStandStopFlying::getInstance()->setVisible(TRUE);
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- LLFloaterCamera::onLeavingMouseLook();
- // Only pop if we have pushed...
- if (TRUE == mViewsPushed)
- {
- #if 0 // Use this once all floaters are registered
- LLFloaterReg::restoreVisibleInstances();
- #else // Use this for now
- LLFloaterView::skip_list_t skip_list;
- if (LLFloaterReg::findInstance("mini_map"))
- {
- skip_list.insert(LLFloaterReg::findInstance("mini_map"));
- }
-
- gFloaterView->popVisibleAll(skip_list);
- #endif
- mViewsPushed = FALSE;
- }
-
- gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
- if( gMorphView )
- {
- gMorphView->setVisible( FALSE );
- }
- // Disable mouselook-specific animations
- if (mAvatarObject.notNull())
- {
- if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )
- {
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_RIFLE_R) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_START);
- }
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_START);
- }
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_START);
- }
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BOW_L) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_START);
- }
- }
- }
- }
- else
- if( mLastCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR )
- {
- // make sure we ask to save changes
- LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
- if( gMorphView )
- {
- gMorphView->setVisible( FALSE );
- }
- if (mAvatarObject.notNull())
- {
- if(mCustomAnim)
- {
- sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_CUSTOMIZE_DONE, ANIM_REQUEST_START);
- mCustomAnim = FALSE ;
- }
-
- }
- setLookAt(LOOKAT_TARGET_CLEAR);
- }
- //---------------------------------------------------------------------
- // Set up UI for mode we're entering
- //---------------------------------------------------------------------
- if (mCameraMode == CAMERA_MODE_MOUSELOOK)
- {
- // hide menus
- gMenuBarView->setVisible(FALSE);
- LLNavigationBar::getInstance()->setVisible(FALSE);
- gStatusBar->setVisibleForMouselook(false);
- LLBottomTray::getInstance()->onMouselookModeIn();
- LLSideTray::getInstance()->getButtonsPanel()->setVisible(FALSE);
- LLSideTray::getInstance()->updateSidetrayVisibility();
- LLPanelStandStopFlying::getInstance()->setVisible(FALSE);
- // clear out camera lag effect
- mCameraLag.clearVec();
- // JC - Added for always chat in third person option
- gFocusMgr.setKeyboardFocus(NULL);
- LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset);
- mViewsPushed = TRUE;
- // hide all floaters except the mini map
- #if 0 // Use this once all floaters are registered
- std::set<std::string> exceptions;
- exceptions.insert("mini_map");
- LLFloaterReg::hideVisibleInstances(exceptions);
- #else // Use this for now
- LLFloaterView::skip_list_t skip_list;
- skip_list.insert(LLFloaterReg::findInstance("mini_map"));
- gFloaterView->pushVisibleAll(FALSE, skip_list);
- #endif
- if( gMorphView )
- {
- gMorphView->setVisible(FALSE);
- }
- gConsole->setVisible( TRUE );
- if (mAvatarObject.notNull())
- {
- // Trigger mouselook-specific animations
- if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_HOLD_ANIMS, NUM_AGENT_GUN_HOLD_ANIMS) )
- {
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_RIFLE_R) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_START);
- }
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_START);
- }
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_START);
- }
- if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BOW_L) != mAvatarObject->mSignaledAnimations.end())
- {
- sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_STOP);
- sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_START);
- }
- }
- if (mAvatarObject->getParent())
- {
- LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis();
- LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot();
- if (root_object->flagCameraDecoupled())
- {
- resetAxes(at_axis);
- }
- else
- {
- resetAxes(at_axis * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation());
- }
- }
- }
- }
- else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR)
- {
- LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
- if( gMorphView )
- {
- gMorphView->setVisible( TRUE );
- }
- // freeze avatar
- if (mAvatarObject.notNull())
- {
- mPauseRequest = mAvatarObject->requestPause();
- }
- }
- if (getAvatarObject())
- {
- getAvatarObject()->updateAttachmentVisibility(mCameraMode);
- }
- gFloaterTools->dirty();
- // Don't let this be called more than once if the camera
- // mode hasn't changed. --JC
- mLastCameraMode = mCameraMode;
- }
- //-----------------------------------------------------------------------------
- // updateCamera()
- //-----------------------------------------------------------------------------
- void LLAgent::updateCamera()
- {
- //Ventrella - changed camera_skyward to the new global "mCameraUpVector"
- mCameraUpVector = LLVector3::z_axis;
- //LLVector3 camera_skyward(0.f, 0.f, 1.f);
- //end Ventrella
- U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode;
- validateFocusObject();
- if (mAvatarObject.notNull() &&
- mAvatarObject->isSitting() &&
- camera_mode == CAMERA_MODE_MOUSELOOK)
- {
- //Ventrella
- //changed camera_skyward to the new global "mCameraUpVector"
- mCameraUpVector = mCameraUpVector * mAvatarObject->getRenderRotation();
- //end Ventrella
- }
- if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams())
- {
- changeCameraToFollow();
- }
- //Ventrella
- //NOTE - this needs to be integrated into a general upVector system here within llAgent.
- if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar )
- {
- mCameraUpVector = mFollowCam.getUpVector();
- }
- //end Ventrella
- if (mSitCameraEnabled)
- {
- if (mSitCameraReferenceObject->isDead())
- {
- setSitCamera(LLUUID::null);
- }
- }
- // Update UI with our camera inputs
- LLFloaterCamera* camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("camera");
- if (camera_floater)
- {
- camera_floater->mRotate->setToggleState(
- mOrbitRightKey > 0.f, // left
- mOrbitUpKey > 0.f, // top
- mOrbitLeftKey > 0.f, // right
- mOrbitDownKey > 0.f); // bottom
- camera_floater->mTrack->setToggleState(
- mPanLeftKey > 0.f, // left
- mPanUpKey > 0.f, // top
- mPanRightKey > 0.f, // right
- mPanDownKey > 0.f); // bottom
- }
- // Handle camera movement based on keyboard.
- const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second
- const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second
- const F32 PAN_RATE = 5.f; // meters per second
- if( mOrbitUpKey || mOrbitDownKey )
- {
- F32 input_rate = mOrbitUpKey - mOrbitDownKey;
- cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped );
- }
- if( mOrbitLeftKey || mOrbitRightKey)
- {
- F32 input_rate = mOrbitLeftKey - mOrbitRightKey;
- cameraOrbitAround( input_rate * ORBIT_AROUND_RATE / gFPSClamped );
- }
- if( mOrbitInKey || mOrbitOutKey )
- {
- F32 input_rate = mOrbitInKey - mOrbitOutKey;
-
- LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal();
- F32 distance_to_focus = (F32)to_focus.magVec();
- // Move at distance (in meters) meters per second
- cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped );
- }
- if( mPanInKey || mPanOutKey )
- {
- F32 input_rate = mPanInKey - mPanOutKey;
- cameraPanIn( input_rate * PAN_RATE / gFPSClamped );
- }
- if( mPanRightKey || mPanLeftKey )
- {
- F32 input_rate = mPanRightKey - mPanLeftKey;
- cameraPanLeft( input_rate * -PAN_RATE / gFPSClamped );
- }
- if( mPanUpKey || mPanDownKey )
- {
- F32 input_rate = mPanUpKey - mPanDownKey;
- cameraPanUp( input_rate * PAN_RATE / gFPSClamped );
- }
- // Clear camera keyboard keys.
- mOrbitLeftKey = 0.f;
- mOrbitRightKey = 0.f;
- mOrbitUpKey = 0.f;
- mOrbitDownKey = 0.f;
- mOrbitInKey = 0.f;
- mOrbitOutKey = 0.f;
- mPanRightKey = 0.f;
- mPanLeftKey = 0.f;
- mPanUpKey = 0.f;
- mPanDownKey = 0.f;
- mPanInKey = 0.f;
- mPanOutKey = 0.f;
- // lerp camera focus offset
- mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE));
- //Ventrella
- if ( mCameraMode == CAMERA_MODE_FOLLOW )
- {
- if ( mAvatarObject.notNull() )
- {
- //--------------------------------------------------------------------------------
- // this is where the avatar's position and rotation are given to followCam, and
- // where it is updated. All three of its attributes are updated: (1) position,
- // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent.
- //--------------------------------------------------------------------------------
- // *TODO: use combined rotation of frameagent and sit object
- LLQuaternion avatarRotationForFollowCam = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion();
- LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams();
- if (current_cam)
- {
- mFollowCam.copyParams(*current_cam);
- mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam );
- mFollowCam.update();
- LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
- }
- else
- {
- changeCameraToThirdPerson(TRUE);
- }
- }
- }
- // end Ventrella
- BOOL hit_limit;
- LLVector3d camera_pos_global;
- LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit);
- mCameraVirtualPositionAgent = getPosAgentFromGlobal(camera_target_global);
- LLVector3d focus_target_global = calcFocusPositionTargetGlobal();
- // perform field of view correction
- mCameraFOVZoomFactor = calcCameraFOVZoomFactor();
- camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor);
- mShowAvatar = TRUE; // can see avatar by default
- // Adjust position for animation
- if (mCameraAnimating)
- {
- F32 time = mAnimationTimer.getElapsedTimeF32();
- // yet another instance of critically damped motion, hooray!
- // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE);
- // linear interpolation
- F32 fraction_of_animation = time / mAnimationDuration;
- BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK;
- BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK;
- F32 fraction_animation_to_skip;
- if (mAnimationCameraStartGlobal == camera_target_global)
- {
- fraction_animation_to_skip = 0.f;
- }
- else
- {
- LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global;
- fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec();
- }
- F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f;
- F32 animation_finish_fraction = (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f;
-
- if (fraction_of_animation < animation_finish_fraction)
- {
- if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction )
- {
- mShowAvatar = FALSE;
- }
- // ...adjust position for animation
- F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation);
- camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation);
- mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation);
- }
- else
- {
- // ...animation complete
- mCameraAnimating = FALSE;
- camera_pos_global = camera_target_global;
- mFocusGlobal = focus_target_global;
- endAnimationUpdateUI();
- mShowAvatar = TRUE;
- }
- if (getAvatarObject() && mCameraMode != CAMERA_MODE_MOUSELOOK)
- {
- getAvatarObject()->updateAttachmentVisibility(mCameraMode);
- }
- }
- else
- {
- camera_pos_global = camera_target_global;
- mFocusGlobal = focus_target_global;
- mShowAvatar = TRUE;
- }
- // smoothing
- if (TRUE)
- {
- LLVector3d agent_pos = getPositionGlobal();
- LLVector3d camera_pos_agent = camera_pos_global - agent_pos;
- // Sitting on what you're manipulating can cause camera jitter with smoothing.
- // This turns off smoothing while editing. -MG
- mCameraSmoothingStop |= (BOOL)LLToolMgr::getInstance()->inBuildMode();
-
- if (cameraThirdPerson() && !mCameraSmoothingStop)