From 1434051f4ef7f0ead78dffba22e8b0ecf6cd0d13 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 7 Jun 2011 22:39:23 -0500 Subject: [PATCH] LLAgentCamera transition (2/2) --- indra/newview/CMakeLists.txt | 2 + indra/newview/llagent.cpp | 3522 ++++--------------------------- indra/newview/llagent.h | 1431 ++++++------- indra/newview/llagentcamera.cpp | 3071 +++++++++++++++++++++++++++ indra/newview/llagentcamera.h | 378 ++++ indra/newview/llworldmap.cpp | 9 +- 6 files changed, 4553 insertions(+), 3860 deletions(-) create mode 100644 indra/newview/llagentcamera.cpp create mode 100644 indra/newview/llagentcamera.h diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 597f42634..06fc0c543 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -101,6 +101,7 @@ set(viewer_SOURCE_FILES qtoolalign.cpp llagent.cpp llagentaccess.cpp + llagentcamera.cpp llagentdata.cpp llagentlanguage.cpp llagentpilot.cpp @@ -575,6 +576,7 @@ set(viewer_HEADER_FILES qtoolalign.h llagent.h llagentaccess.h + llagentcamera.h llagentdata.h llagentlanguage.h llagentpilot.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 8e3c01011..221c2b1ef 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -32,113 +32,74 @@ #include "llviewerprecompiledheaders.h" -#include "stdtypes.h" -#include "stdenums.h" - -#include "cofmgr.h" #include "llagent.h" -#include "llcamera.h" -#include "llcoordframe.h" -#include "indra_constants.h" -#include "llmath.h" -#include "llcriticaldamp.h" -#include "llfocusmgr.h" -#include "llglheaders.h" -#include "llparcel.h" -#include "llpermissions.h" -#include "llregionhandle.h" -#include "m3math.h" -#include "m4math.h" -#include "message.h" -#include "llquaternion.h" -#include "v3math.h" -#include "v4math.h" -#include "llsmoothstep.h" -#include "llsdutil.h" -//#include "vmath.h" -#include "imageids.h" -#include "llbox.h" -#include "llbutton.h" +#include "pipeline.h" + +#include "llagentaccess.h" +#include "llagentcamera.h" +#include "llanimationstates.h" #include "llcallingcard.h" -#include "llchatbar.h" #include "llconsole.h" -#include "lldrawable.h" -#include "llface.h" #include "llfirstuse.h" -#include "llfloater.h" -#include "floaterao.h" -#include "llfloateractivespeakers.h" -#include "llfloateravatarinfo.h" -#include "llfloaterbuildoptions.h" #include "llfloatercamera.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" +#include "llfloatertools.h" + +#include "llgroupmgr.h" +#include "llhomelocationresponder.h" +#include "llhudmanager.h" +#include "lljoystickbutton.h" +#include "llmorphview.h" +#include "llmoveview.h" +#include "llchatbar.h" +#include "llnotify.h" +#include "llparcel.h" +#include "llrendersphere.h" +#include "llsdutil.h" +#include "llsky.h" +#include "llsmoothstep.h" +#include "llstartup.h" +#include "llstatusbar.h" +#include "lltool.h" +#include "lltoolpie.h" +#include "lltoolmgr.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewerdisplay.h" +#include "llviewerjoystick.h" +#include "llviewermediafocus.h" +#include "llviewermenu.h" +#include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" +#include "llviewerstats.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llworld.h" +#include "llworldmap.h" + +//Misc non-standard includes +#include "llviewerregion.h" +#include "llurldispatcher.h" +#include "llimview.h" //For gIMMgr +//Floaters +#include "llfloatermute.h" +#include "llfloatermap.h" +#include "llfloateractivespeakers.h" #include "llfloaterdirectory.h" #include "llfloatergroupinfo.h" #include "llfloatergroups.h" -#include "llfloaterland.h" -#include "llfloatermap.h" -#include "llfloatermute.h" -#include "llfloatersnapshot.h" -#include "llfloatertools.h" +#include "llfloateravatarinfo.h" #include "llfloaterworldmap.h" -#include "llgroupmgr.h" -#include "llhomelocationresponder.h" -#include "llhudeffectlookat.h" -#include "llhudmanager.h" -#include "llinventorymodel.h" +#include "llfloaterland.h" +#include "llfloatersnapshot.h" +#include "llfloaterchat.h" + +//Wearables #include "llinventoryview.h" -#include "lljoystickbutton.h" -#include "llmenugl.h" -#include "llmorphview.h" -#include "llmoveview.h" -#include "llnotify.h" -#include "llprimitive.h" //For new client id method -HgB -#include "llquantize.h" -#include "llsdutil.h" -#include "llselectmgr.h" -#include "llsky.h" -#include "llrendersphere.h" -#include "llstatusbar.h" -#include "llstartup.h" -#include "llimview.h" -#include "lltexturestats.h" -#include "lltool.h" -#include "lltoolcomp.h" -#include "lltoolfocus.h" -#include "lltoolgrab.h" -#include "lltoolmgr.h" -#include "lltoolpie.h" -#include "lltoolview.h" -#include "lltrans.h" -#include "llui.h" // for make_ui_sound -#include "llurldispatcher.h" -#include "llviewercamera.h" -#include "llviewerinventory.h" -#include "llviewermediafocus.h" -#include "llviewermenu.h" -#include "llviewernetwork.h" -#include "llviewerobjectlist.h" -#include "llviewerparcelmgr.h" -#include "llviewerparceloverlay.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llviewerwindow.h" -#include "llviewerdisplay.h" -#include "llvoavatar.h" -#include "llvoground.h" -#include "llvosky.h" -#include "llwearable.h" +#include "cofmgr.h" #include "llwearablelist.h" -#include "llworld.h" -#include "llworldmap.h" -#include "pipeline.h" -#include "roles_constants.h" -#include "llviewercontrol.h" -#include "llappviewer.h" -#include "llviewerjoystick.h" -#include "llfollowcam.h" +#include "llfloatercustomize.h" + #include "hippogridmanager.h" @@ -150,8 +111,6 @@ using namespace LLVOAvatarDefines; -extern LLMenuBarGL* gMenuBarView; - //drone wandering constants const F32 MAX_WANDER_TIME = 20.f; // seconds const F32 MAX_HEADING_HALF_ERROR = 0.2f; // radians @@ -170,56 +129,15 @@ const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f; // seconds 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.0f; -const F32 MIN_CAMERA_DISTANCE = 0.0f; -const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.0f; -const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.0f; -const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 0.0f; - -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; @@ -236,20 +154,6 @@ LLVector3 gReSitOffset; // Statics // -// -// For MapBlockReply funk 'cause I dunno what I'm doing -BOOL LLAgent::lure_show = FALSE; -std::string LLAgent::lure_name; -LLVector3d LLAgent::lure_posglobal; -U16 LLAgent::lure_global_x; -U16 LLAgent::lure_global_y; -int LLAgent::lure_x; -int LLAgent::lure_y; -int LLAgent::lure_z; -std::string LLAgent::lure_maturity; - -// - BOOL LLAgent::exlPhantom = 0; BOOL LLAgent::mForceTPose = 0; LLVector3 LLAgent::exlStartMeasurePoint = LLVector3::zero; @@ -300,34 +204,20 @@ void LLAgentFriendObserver::changed(U32 mask) // LLAgent() //----------------------------------------------------------------------------- LLAgent::LLAgent() : - mDrawDistance( DEFAULT_FAR_PLANE ), - mGroupPowers(0), mHideGroupTitle(FALSE), mGroupID(), - mMapOriginX(0.F), - mMapOriginY(0.F), - mMapWidth(0), - mMapHeight(0), - - mLookAt(NULL), - mPointAt(NULL), - - mHUDTargetZoom(1.f), - mHUDCurZoom(1.f), mInitialized(FALSE), - mNumPendingQueries(0), - mActiveCacheQueries(NULL), - mForceMouselook(FALSE), mDoubleTapRunTimer(), mDoubleTapRunMode(DOUBLETAP_NONE), mbAlwaysRun(false), mbRunning(false), + mbTeleportKeepsLookAt(false), - mAgentAccess(gSavedSettings), + mAgentAccess(new LLAgentAccess(gSavedSettings)), mTeleportState( TELEPORT_NONE ), mRegionp(NULL), @@ -342,78 +232,18 @@ LLAgent::LLAgent() : mRenderState(0), mTypingTimer(), - mCameraMode( CAMERA_MODE_THIRD_PERSON ), - mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), mViewsPushed(FALSE), mCustomAnim(FALSE), mShowAvatar(TRUE), - mCameraAnimating( FALSE ), - mAnimationCameraStartGlobal(), - mAnimationFocusStartGlobal(), - mAnimationTimer(), - mAnimationDuration(0.33f), - - mCameraFOVZoomFactor(0.f), - mCameraCurrentFOVZoomFactor(0.f), - mCameraFocusOffset(), - mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW), - - mCameraOffsetDefault(), - 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), - - 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(), @@ -436,12 +266,10 @@ LLAgent::LLAgent() : mCurrentFidget(0), mFirstLogin(FALSE), mGenderChosen(FALSE), - - mAgentWearablesUpdateSerialNum(0), mWearablesLoaded(FALSE), - mTextureCacheQueryID(0), mAppearanceSerialNum(0), - mbTeleportKeepsLookAt(false) + + mPendingLure(NULL) { U32 i; for (i = 0; i < TOTAL_CONTROLS; i++) @@ -449,14 +277,6 @@ LLAgent::LLAgent() : mControlsTakenCount[i] = 0; mControlsTakenPassedOnCount[i] = 0; } - - mActiveCacheQueries = new S32[BAKED_NUM_INDICES]; - for (i = 0; i < (U32)BAKED_NUM_INDICES; i++) - { - mActiveCacheQueries[i] = 0; - } - - mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); } // Requires gSavedSettings to be initialized. @@ -465,26 +285,10 @@ LLAgent::LLAgent() : //----------------------------------------------------------------------------- void LLAgent::init() { - 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->getDisplayAspectRatio() ); // default, overridden in LLViewerWindow::reshape - LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape setFlying( gSavedSettings.getBOOL("FlyingAtExit") ); - mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); - mCameraOffsetDefault = gSavedSettings.getVector3("CameraOffsetDefault"); - mCameraCollidePlane.clearVec(); - mCurrentCameraDistance = mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale"); - mTargetCameraDistance = mCurrentCameraDistance; - mCameraZoomFraction = 1.f; - mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); + // LLDebugVarMessageBox::show("Camera Lag", &CAMERA_FOCUS_HALF_LIFE, 0.5f, 0.01f); @@ -498,20 +302,11 @@ void LLAgent::init() //----------------------------------------------------------------------------- void LLAgent::cleanup() { - setSitCamera(LLUUID::null); mAvatarObject = NULL; - if(mLookAt) - { - mLookAt->markDead() ; - mLookAt = NULL; - } - if(mPointAt) - { - mPointAt->markDead() ; - mPointAt = NULL; - } mRegionp = NULL; - setFocusObject(NULL); + if(mPendingLure) + delete mPendingLure; + mPendingLure = NULL; } //----------------------------------------------------------------------------- @@ -521,87 +316,10 @@ LLAgent::~LLAgent() { cleanup(); - delete [] mActiveCacheQueries; - mActiveCacheQueries = NULL; - - // *Note: this is where LLViewerCamera::getInstance() used to be deleted. + delete mAgentAccess; + mAgentAccess = NULL; } -// 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(); - } - - if (gMenuHolder != NULL) - { - // Hide all popup menus - gMenuHolder->hideMenus(); - } - } - - static const LLCachedControl freeze_time("FreezeTime",false); - if (change_camera && !freeze_time) - { - changeCameraToDefault(); - - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - handle_toggle_flycam(); - } - - // reset avatar mode from eventual residual motion - if (LLToolMgr::getInstance()->inBuildMode()) - { - LLViewerJoystick::getInstance()->moveAvatar(true); - } - - gFloaterTools->close(); - - gViewerWindow->showCursor(); - - // Switch back to basic toolset - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - if (reset_camera && !freeze_time) - { - 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). @@ -610,9 +328,9 @@ void LLAgent::resetView(BOOL reset_camera, BOOL change_camera) //----------------------------------------------------------------------------- void LLAgent::onAppFocusGained() { - if (CAMERA_MODE_MOUSELOOK == mCameraMode) + if (CAMERA_MODE_MOUSELOOK == gAgentCamera.getCameraMode()) { - changeCameraToDefault(); + gAgentCamera.changeCameraToDefault(); LLToolMgr::getInstance()->clearSavedTool(); } } @@ -629,22 +347,6 @@ void LLAgent::ageChat() } } -// Allow camera to be moved somewhere other than behind avatar. -//----------------------------------------------------------------------------- -// unlockView() -//----------------------------------------------------------------------------- -void LLAgent::unlockView() -{ - if (getFocusOnAvatar()) - { - if (isAgentAvatarValid()) - { - setFocusGlobal( LLVector3d::zero, mAvatarObject->mID ); - } - setFocusOnAvatar(FALSE, FALSE); // no animation - } -} - //----------------------------------------------------------------------------- // moveAt() @@ -654,7 +356,7 @@ void LLAgent::moveAt(S32 direction, bool reset) // age chat timer so it fades more quickly when you are intentionally moving ageChat(); - setKey(direction, mAtKey); + gAgentCamera.setAtKey(LLAgentCamera::directionToKey(direction)); if (direction > 0) { @@ -667,7 +369,7 @@ void LLAgent::moveAt(S32 direction, bool reset) if (reset) { - resetView(); + gAgentCamera.resetView(); } } @@ -679,7 +381,7 @@ void LLAgent::moveAtNudge(S32 direction) // age chat timer so it fades more quickly when you are intentionally moving ageChat(); - setKey(direction, mWalkKey); + gAgentCamera.setWalkKey(LLAgentCamera::directionToKey(direction)); if (direction > 0) { @@ -690,7 +392,7 @@ void LLAgent::moveAtNudge(S32 direction) setControlFlags(AGENT_CONTROL_NUDGE_AT_NEG); } - resetView(); + gAgentCamera.resetView(); } //----------------------------------------------------------------------------- @@ -701,7 +403,7 @@ void LLAgent::moveLeft(S32 direction) // age chat timer so it fades more quickly when you are intentionally moving ageChat(); - setKey(direction, mLeftKey); + gAgentCamera.setLeftKey(LLAgentCamera::directionToKey(direction)); if (direction > 0) { @@ -712,7 +414,7 @@ void LLAgent::moveLeft(S32 direction) setControlFlags(AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT); } - resetView(); + gAgentCamera.resetView(); } //----------------------------------------------------------------------------- @@ -723,7 +425,7 @@ void LLAgent::moveLeftNudge(S32 direction) // age chat timer so it fades more quickly when you are intentionally moving ageChat(); - setKey(direction, mLeftKey); + gAgentCamera.setLeftKey(LLAgentCamera::directionToKey(direction)); if (direction > 0) { @@ -734,7 +436,7 @@ void LLAgent::moveLeftNudge(S32 direction) setControlFlags(AGENT_CONTROL_NUDGE_LEFT_NEG); } - resetView(); + gAgentCamera.resetView(); } //----------------------------------------------------------------------------- @@ -745,7 +447,7 @@ void LLAgent::moveUp(S32 direction) // age chat timer so it fades more quickly when you are intentionally moving ageChat(); - setKey(direction, mUpKey); + gAgentCamera.setUpKey(LLAgentCamera::directionToKey(direction)); if (direction > 0) { @@ -756,7 +458,7 @@ void LLAgent::moveUp(S32 direction) setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP); } - resetView(); + gAgentCamera.resetView(); } //----------------------------------------------------------------------------- @@ -764,7 +466,7 @@ void LLAgent::moveUp(S32 direction) //----------------------------------------------------------------------------- void LLAgent::moveYaw(F32 mag, bool reset_view) { - mYawKey = mag; + gAgentCamera.setYawKey(mag); if (mag > 0) { @@ -777,22 +479,22 @@ void LLAgent::moveYaw(F32 mag, bool reset_view) if (reset_view) { - resetView(); + gAgentCamera.resetView(); } } //----------------------------------------------------------------------------- // movePitch() //----------------------------------------------------------------------------- -void LLAgent::movePitch(S32 direction) +void LLAgent::movePitch(F32 mag) { - setKey(direction, mPitchKey); + gAgentCamera.setPitchKey(mag); - if (direction > 0) + if (mag > 0) { setControlFlags(AGENT_CONTROL_PITCH_POS ); } - else if (direction < 0) + else if (mag < 0) { setControlFlags(AGENT_CONTROL_PITCH_NEG); } @@ -828,6 +530,11 @@ BOOL LLAgent::canFly() return parcel->getAllowFly(); } +BOOL LLAgent::getFlying() const +{ + return mControlFlags & AGENT_CONTROL_FLY; +} + // Better Set Phantom options ~Charbl void LLAgent::setPhantom(BOOL phantom) { @@ -910,10 +617,26 @@ void LLAgent::setFlying(BOOL fly) //----------------------------------------------------------------------------- void LLAgent::toggleFlying() { - BOOL fly = !(mControlFlags & AGENT_CONTROL_FLY); + BOOL fly = !gAgent.getFlying(); - setFlying( fly ); - resetView(); + gAgent.setFlying( fly ); + gAgentCamera.resetView(); +} + +// static +bool LLAgent::enableFlying() +{ + BOOL sitting = FALSE; + if (isAgentAvatarValid()) + { + sitting = gAgent.getAvatarObject()->isSitting(); + } + return !sitting; +} + +void LLAgent::standUp() +{ + setControlFlags(AGENT_CONTROL_STAND_UP); } void LLAgent::togglePhantom() @@ -1150,16 +873,6 @@ void LLAgent::setPositionAgent(const LLVector3 &pos_agent) } } -//----------------------------------------------------------------------------- -// 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() @@ -1229,6 +942,11 @@ LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const return pos_agent_d + mAgentOriginGlobal; } +void LLAgent::sitDown() +{ + setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); +} + //----------------------------------------------------------------------------- // resetAxes() @@ -1315,7 +1033,7 @@ LLVector3 LLAgent::getReferenceUpVector() mAvatarObject->getParent() && mAvatarObject->mDrawable.notNull()) { - U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; + U32 camera_mode = gAgentCamera.getCameraAnimating() ? gAgentCamera.getLastCameraMode() : gAgentCamera.getCameraMode(); // and in third person... if (camera_mode == CAMERA_MODE_THIRD_PERSON) { @@ -1414,730 +1132,6 @@ 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) -{ - /* Emerald: - We don't care about minimum distances in Emerald. No we don't. - ~Zwag - */ - BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) - - if (!mFocusObject || mFocusObject->isDead() || gSavedSettings.getBOOL("DisableCameraConstraints")) - { - 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 (gSavedSettings.getBOOL("AscentDisableMinZoomDist")) - { - return mCameraZoomFraction; - } - 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 = 65535.f*4.f;//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(); - BOOL disable_min = gSavedSettings.getBOOL("AscentDisableMinZoomDist"); - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - mHUDTargetZoom = fraction; - } - else if (mFocusOnAvatar && cameraThirdPerson() && !disable_min) - { - 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 (!disable_min) - { - if (mFocusObject.notNull()) - { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } - } - } - else - { - min_zoom = 0.f; - } - LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; - camera_offset_dir.normalize(); - //mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); - mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 65535.*4., 1.f, 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 = 0.f;//LAND_MIN_ZOOM; - F32 current_distance = (F32)camera_offset_unit.normalize(); - F32 new_distance = current_distance * fraction; - - if (!gSavedSettings.getBOOL("AscentDisableMinZoomDist")) - { - 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*/ INT_MAX - DIST_FUDGE//, - /*LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE )*/; - - if (new_distance > max_distance) - { - // screw cam constraints - //new_distance = max_distance; - // - - /* - // Unless camera is unlocked - if (!LLViewerCamera::sDisableCameraConstraints) - { - return; - } - */ - } - - 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, mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); - - mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist; - - static const LLCachedControl freeze_time("FreezeTime",false); - if (!freeze_time && 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() //----------------------------------------------------------------------------- @@ -2317,7 +1311,13 @@ BOOL LLAgent::getBusy() const //----------------------------------------------------------------------------- // 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) +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 (!isAgentAvatarValid()) { @@ -2447,7 +1447,7 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) //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); + mAutoPilotFinishedCallback(!user_cancel && dist_vec_squared(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < (mAutoPilotStopDistance * mAutoPilotStopDistance), mAutoPilotCallbackData); } mLeaderID = LLUUID::null; @@ -2630,22 +1630,22 @@ void LLAgent::propagate(const F32 dt) LLFloaterMove *floater_move = LLFloaterMove::getInstance(); if (floater_move) { - floater_move->mForwardButton ->setToggleState( mAtKey > 0 || mWalkKey > 0 ); - floater_move->mBackwardButton ->setToggleState( mAtKey < 0 || mWalkKey < 0 ); - floater_move->mSlideLeftButton ->setToggleState( mLeftKey > 0 ); - floater_move->mSlideRightButton->setToggleState( mLeftKey < 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 ); + floater_move->mForwardButton ->setToggleState( gAgentCamera.getAtKey() > 0 || gAgentCamera.getWalkKey() > 0 ); + floater_move->mBackwardButton ->setToggleState( gAgentCamera.getAtKey() < 0 || gAgentCamera.getWalkKey() < 0 ); + floater_move->mTurnLeftButton ->setToggleState( gAgentCamera.getYawKey() > 0.f ); + floater_move->mTurnRightButton ->setToggleState( gAgentCamera.getYawKey() < 0.f ); + floater_move->mSlideLeftButton ->setToggleState( gAgentCamera.getLeftKey() > 0.f ); + floater_move->mSlideRightButton ->setToggleState( gAgentCamera.getLeftKey() < 0.f ); + floater_move->mMoveUpButton ->setToggleState( gAgentCamera.getUpKey() > 0 ); + floater_move->mMoveDownButton ->setToggleState( gAgentCamera.getUpKey() < 0 ); } // handle rotation based on keyboard levels const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second - yaw( YAW_RATE * mYawKey * dt ); + yaw(YAW_RATE * gAgentCamera.getYawKey() * dt); const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second - pitch(PITCH_RATE * (F32) mPitchKey * dt); + pitch(PITCH_RATE * gAgentCamera.getPitchKey() * dt); // handle auto-land behavior if (mAvatarObject.notNull()) @@ -2655,7 +1655,7 @@ void LLAgent::propagate(const F32 dt) land_vel.mV[VZ] = 0.f; if (!in_air - && mUpKey < 0 + && gAgentCamera.getUpKey() < 0 && land_vel.magVecSquared() < MAX_VELOCITY_AUTO_LAND_SQUARED && gSavedSettings.getBOOL("AutomaticFly")) { @@ -2664,13 +1664,7 @@ void LLAgent::propagate(const F32 dt) } } - // clear keys - mAtKey = 0; - mWalkKey = 0; - mLeftKey = 0; - mUpKey = 0; - mYawKey = 0.f; - mPitchKey = 0; + gAgentCamera.clearGeneralKeys(); } //----------------------------------------------------------------------------- @@ -2688,76 +1682,9 @@ void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 // Check for water and land collision, set underwater flag // - updateLookAt(mouse_x, mouse_y); + gAgentCamera.updateLookAt(mouse_x, mouse_y); } -//----------------------------------------------------------------------------- -// updateLookAt() -//----------------------------------------------------------------------------- -void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y) -{ - static LLVector3 last_at_axis; - - if (!isAgentAvatarValid()) 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->getWindowWidth() ) - 0.5f; - F32 y_from_center = - ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 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 @@ -2789,25 +1716,7 @@ void LLAgent::setAvatarObject(LLVOAvatar *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); - } - + gAgentCamera.setAvatarObject(avatar); sendAgentWearablesRequest(); } @@ -2818,7 +1727,7 @@ void LLAgent::setAvatarObject(LLVOAvatar *avatar) //----------------------------------------------------------------------------- BOOL LLAgent::needsRenderAvatar() { - if (cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson) + if (gAgentCamera.cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson) { return FALSE; } @@ -2829,7 +1738,7 @@ BOOL LLAgent::needsRenderAvatar() // TRUE if we need to render your own avatar's head. BOOL LLAgent::needsRenderHead() { - return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !cameraMouselook()); + return (LLVOAvatar::sVisibleInFirstPerson && LLPipeline::sReflectionRender) || (mShowAvatar && !gAgentCamera.cameraMouselook()); } //----------------------------------------------------------------------------- @@ -2853,7 +1762,7 @@ void LLAgent::startTyping() LLVOAvatar* chatter = gObjectList.findAvatar(mLastChatterID); if (chatter) { - gAgent.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero); + gAgentCamera.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero); } } @@ -2939,14 +1848,14 @@ static const LLFloaterView::skip_list_t& get_skip_list() //----------------------------------------------------------------------------- void LLAgent::endAnimationUpdateUI() { - if (mCameraMode == mLastCameraMode) + if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode()) { // We're already done endAnimationUpdateUI for this transition. return; } // clean up UI from mode we're leaving - if ( mLastCameraMode == CAMERA_MODE_MOUSELOOK ) + if (gAgentCamera.getLastCameraMode() == CAMERA_MODE_MOUSELOOK ) { // show mouse cursor gViewerWindow->showCursor(); @@ -2963,7 +1872,7 @@ void LLAgent::endAnimationUpdateUI() gFloaterView->popVisibleAll(get_skip_list()); } - gAgent.setLookAt(LOOKAT_TARGET_CLEAR); + gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); if( gMorphView ) { gMorphView->setVisible( FALSE ); @@ -2997,8 +1906,7 @@ void LLAgent::endAnimationUpdateUI() } } } - else - if( mLastCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR ) + else if (gAgentCamera.getLastCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { // make sure we ask to save changes @@ -3027,20 +1935,20 @@ void LLAgent::endAnimationUpdateUI() } } - setLookAt(LOOKAT_TARGET_CLEAR); + gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); } //--------------------------------------------------------------------- // Set up UI for mode we're entering //--------------------------------------------------------------------- - if (mCameraMode == CAMERA_MODE_MOUSELOOK) + if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) { // hide menus gMenuBarView->setVisible(FALSE); gStatusBar->setVisibleForMouselook(false); // clear out camera lag effect - mCameraLag.clearVec(); + gAgentCamera.clearCameraLag(); // JC - Added for always chat in third person option gFocusMgr.setKeyboardFocus(NULL); @@ -3100,7 +2008,7 @@ void LLAgent::endAnimationUpdateUI() } } - else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) + else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); @@ -3129,1561 +2037,17 @@ void LLAgent::endAnimationUpdateUI() if (isAgentAvatarValid()) { - mAvatarObject->updateAttachmentVisibility(mCameraMode); + gAgent.getAvatarObject()->updateAttachmentVisibility(gAgentCamera.getCameraMode()); } gFloaterTools->dirty(); // Don't let this be called more than once if the camera // mode hasn't changed. --JC - mLastCameraMode = mCameraMode; - + gAgentCamera.updateLastCamera(); } -//----------------------------------------------------------------------------- -// 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 (isAgentAvatarValid() && - 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::getInstance()->mRotate->setToggleState( - mOrbitRightKey > 0.f, // left - mOrbitUpKey > 0.f, // top - mOrbitLeftKey > 0.f, // right - mOrbitDownKey > 0.f); // bottom - - LLFloaterCamera::getInstance()->mZoom->setToggleState( - mOrbitInKey > 0.f, // top - mOrbitOutKey > 0.f); // bottom - - LLFloaterCamera::getInstance()->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 (isAgentAvatarValid()) - { - //-------------------------------------------------------------------------------- - // 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) - { - const F32 SMOOTHING_HALF_LIFE = 0.02f; - - F32 smoothing = LLCriticalDamp::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); - - if (!mFocusObject) // we differentiate on avatar mode - { - // for avatar-relative focus, we smooth in avatar space - - // the avatar moves too jerkily w/r/t global space to smooth there. - - LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; - if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please - { - camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); - camera_pos_global = camera_pos_agent + agent_pos; - } - } - else - { - LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; - if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please - { - camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); - } - } - } - - mCameraSmoothingLastPositionGlobal = camera_pos_global; - mCameraSmoothingLastPositionAgent = camera_pos_agent; - mCameraSmoothingStop = FALSE; - } - - - mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE)); - -// llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl; - - F32 ui_offset = 0.f; - if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) - { - ui_offset = calcCustomizeAvatarUIOffset( camera_pos_global ); - } - - - LLVector3 focus_agent = getPosAgentFromGlobal(mFocusGlobal); - - mCameraPositionAgent = getPosAgentFromGlobal(camera_pos_global); - - // Move the camera - - //Ventrella - LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); - //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); - //end Ventrella - - //RN: translate UI offset after camera is oriented properly - LLViewerCamera::getInstance()->translate(LLViewerCamera::getInstance()->getLeftAxis() * ui_offset); - - // Change FOV - LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); - - // follow camera when in customize mode - if (cameraCustomizeAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); - } - - // update the travel distance stat - // this isn't directly related to the camera - // but this seemed like the best place to do this - LLVector3d global_pos = getPositionGlobal(); - if (! mLastPositionGlobal.isExactlyZero()) - { - LLVector3d delta = global_pos - mLastPositionGlobal; - mDistanceTraveled += delta.magVec(); - } - mLastPositionGlobal = global_pos; - - if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->isSitting() && cameraMouselook()) - { - LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + - LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() + - LLVector3(0.1f, 0.f, 0.f) * mAvatarObject->mPelvisp->getWorldRotation(); - LLVector3 diff = mCameraPositionAgent - head_pos; - diff = diff * ~mAvatarObject->mRoot.getWorldRotation(); - - LLJoint* torso_joint = mAvatarObject->mTorsop; - LLJoint* chest_joint = mAvatarObject->mChestp; - LLVector3 torso_scale = torso_joint->getScale(); - LLVector3 chest_scale = chest_joint->getScale(); - - // shorten avatar skeleton to avoid foot interpenetration - if (!mAvatarObject->mInAir) - { - LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); - F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); - F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); - torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - - LLJoint* neck_joint = mAvatarObject->mNeckp; - LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); - scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); - chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); - diff.mV[VZ] = 0.f; - } - - mAvatarObject->mPelvisp->setPosition(mAvatarObject->mPelvisp->getPosition() + diff); - - mAvatarObject->mRoot.updateWorldMatrixChildren(); - - for (LLVOAvatar::attachment_map_t::iterator iter = mAvatarObject->mAttachmentPoints.begin(); - iter != mAvatarObject->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { - LLViewerObject *attached_object = (*attachment_iter); - if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) - { - // clear any existing "early" movements of attachment - attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); - gPipeline.updateMoveNormalAsync(attached_object->mDrawable); - attached_object->updateText(); - } - } - } - - torso_joint->setScale(torso_scale); - chest_joint->setScale(chest_scale); - } -} - -void LLAgent::updateLastCamera() -{ - mLastCameraMode = mCameraMode; -} - -void LLAgent::updateFocusOffset() -{ - validateFocusObject(); - if (mFocusObject.notNull()) - { - LLVector3d obj_pos = getPosGlobalFromAgent(mFocusObject->getRenderPosition()); - mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); - } -} - -void LLAgent::validateFocusObject() -{ - if (mFocusObject.notNull() && - (mFocusObject->isDead())) - { - mFocusObjectOffset.clearVec(); - clearFocusObject(); - mCameraFOVZoomFactor = 0.f; - } -} - -//----------------------------------------------------------------------------- -// calcCustomizeAvatarUIOffset() -//----------------------------------------------------------------------------- -F32 LLAgent::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ) -{ - F32 ui_offset = 0.f; - - if( gFloaterCustomize ) - { - const LLRect& rect = gFloaterCustomize->getRect(); - - // Move the camera so that the avatar isn't covered up by this floater. - F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidth())))); - F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); // radians - F32 offset = tan(apparent_angle); - - if( rect.mLeft < (gViewerWindow->getWindowWidth() - rect.mRight) ) - { - // Move the avatar to the right (camera to the left) - ui_offset = offset; - } - else - { - // Move the avatar to the left (camera to the right) - ui_offset = -offset; - } - } - F32 range = (F32)dist_vec(camera_pos_global, gAgent.getFocusGlobal()); - mUIOffset = lerp(mUIOffset, ui_offset, LLCriticalDamp::getInterpolant(0.05f)); - return mUIOffset * range; -} - -//----------------------------------------------------------------------------- -// calcFocusPositionTargetGlobal() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::calcFocusPositionTargetGlobal() -{ - if (mFocusObject.notNull() && mFocusObject->isDead()) - { - clearFocusObject(); - } - - // Ventrella - if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) - { - mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); - return mFocusTargetGlobal; - }// End Ventrella - else if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - LLVector3d at_axis(1.0, 0.0, 0.0); - LLQuaternion agent_rot = mFrameAgent.getQuaternion(); - if (mAvatarObject.notNull() && mAvatarObject->getParent()) - { - LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot(); - if (!root_object->flagCameraDecoupled()) - { - agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation(); - } - } - at_axis = at_axis * agent_rot; - mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; - return mFocusTargetGlobal; - } - else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) - { - return mFocusTargetGlobal; - } - else if (!mFocusOnAvatar) - { - if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) - { - LLDrawable* drawablep = mFocusObject->mDrawable; - - if (mTrackFocusObject && - drawablep && - drawablep->isActive()) - { - if (!mFocusObject->isAvatar()) - { - if (mFocusObject->isSelected()) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) - { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - gPipeline.updateMoveDampedAsync(drawablep); - } - } - } - } - // if not tracking object, update offset based on new object position - else - { - updateFocusOffset(); - } - LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; - mFocusTargetGlobal.setVec(getPosGlobalFromAgent(focus_agent)); - } - return mFocusTargetGlobal; - } - else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->isSitting() && mSitCameraReferenceObject.notNull()) - { - // sit camera - LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); - LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - - LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); - return getPosGlobalFromAgent(target_pos); - } - else - { - return getPositionGlobal() + calcThirdPersonFocusOffset(); - } -} - -LLVector3d LLAgent::calcThirdPersonFocusOffset() -{ - // ...offset from avatar - LLVector3d focus_offset; - focus_offset.setVec(gSavedSettings.getVector3("FocusOffsetDefault")); - - LLQuaternion agent_rot = mFrameAgent.getQuaternion(); - if (isAgentAvatarValid() && mAvatarObject->getParent()) - { - agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation(); - } - - focus_offset = focus_offset * agent_rot; - return focus_offset; -} - -void LLAgent::setupSitCamera() -{ - // agent frame entering this function is in world coordinates - if (isAgentAvatarValid() && mAvatarObject->getParent()) - { - LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - // slam agent coordinate frame to proper parent local version - LLVector3 at_axis = mFrameAgent.getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~parent_rot); - } -} - -//----------------------------------------------------------------------------- -// getCameraPositionAgent() -//----------------------------------------------------------------------------- -const LLVector3 &LLAgent::getCameraPositionAgent() const -{ - return LLViewerCamera::getInstance()->getOrigin(); -} - -//----------------------------------------------------------------------------- -// getCameraPositionGlobal() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::getCameraPositionGlobal() const -{ - return getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); -} - -//----------------------------------------------------------------------------- -// calcCameraFOVZoomFactor() -//----------------------------------------------------------------------------- -F32 LLAgent::calcCameraFOVZoomFactor() -{ - LLVector3 camera_offset_dir; - camera_offset_dir.setVec(mCameraFocusOffset); - - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - return 0.f; - } - else if (mFocusObject.notNull() && !mFocusObject->isAvatar()) - { - // don't FOV zoom on mostly transparent objects - LLVector3 focus_offset = mFocusObjectOffset; - F32 obj_min_dist = 0.f; - if (!gSavedSettings.getBOOL("AscentDisableMinZoomDist")) - calcCameraMinDistance(obj_min_dist); - F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); - - mFocusObjectDist = obj_min_dist - current_distance; - - F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); - return new_fov_zoom; - } - else // focusing on land or avatar - { - // keep old field of view until user changes focus explicitly - return mCameraFOVZoomFactor; - //return 0.f; - } -} - -//----------------------------------------------------------------------------- -// calcCameraPositionTargetGlobal() -//----------------------------------------------------------------------------- -LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) -{ - // Compute base camera position and look-at points. - //F32 camera_land_height; - LLVector3d frame_center_global = !isAgentAvatarValid() ? getPositionGlobal() - : getPosGlobalFromAgent(mAvatarObject->mRoot.getWorldPosition()); - - LLVector3 upAxis = getUpAxis(); - BOOL isConstrained = FALSE; - LLVector3d head_offset; - head_offset.setVec(mThirdPersonHeadOffset); - - LLVector3d camera_position_global; - - // Ventrella - if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) - { - camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); - }// End Ventrella - else if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - if (!isAgentAvatarValid() || mAvatarObject->mDrawable.isNull()) - { - llwarns << "Null avatar drawable!" << llendl; - return LLVector3d::zero; - } - head_offset.clearVec(); - if (mAvatarObject->isSitting() && mAvatarObject->getParent()) - { - mAvatarObject->updateHeadOffset(); - head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX]; - head_offset.mdV[VY] = mAvatarObject->mHeadOffset.mV[VY]; - head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ] + 0.1f; - const LLMatrix4& mat = ((LLViewerObject*) mAvatarObject->getParent())->getRenderMatrix(); - camera_position_global = getPosGlobalFromAgent - ((mAvatarObject->getPosition()+ - LLVector3(head_offset)*mAvatarObject->getRotation()) * mat); - } - else - { - head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ]; - if (mAvatarObject->isSitting()) - { - head_offset.mdV[VZ] += 0.1; - } - camera_position_global = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());//frame_center_global; - head_offset = head_offset * mAvatarObject->getRenderRotation(); - camera_position_global = camera_position_global + head_offset; - } - } - else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) - { - LLVector3 local_camera_offset; - F32 camera_distance = 0.f; - - if (mSitCameraEnabled - && isAgentAvatarValid() - && mAvatarObject->isSitting() - && mSitCameraReferenceObject.notNull()) - { - // sit camera - LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); - LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); - - LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); - - camera_position_global = getPosGlobalFromAgent(target_pos); - } - else - { - local_camera_offset = mCameraZoomFraction * mCameraOffsetDefault * gSavedSettings.getF32("CameraOffsetScale"); - - // are we sitting down? - if (isAgentAvatarValid() && mAvatarObject->getParent()) - { - LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - // slam agent coordinate frame to proper parent local version - LLVector3 at_axis = mFrameAgent.getAtAxis() * parent_rot; - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~parent_rot); - - local_camera_offset = local_camera_offset * mFrameAgent.getQuaternion() * parent_rot; - } - else - { - local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset ); - } - - if (!mCameraCollidePlane.isExactlyZero() && (!isAgentAvatarValid() || !mAvatarObject->isSitting())) - { - LLVector3 plane_normal; - plane_normal.setVec(mCameraCollidePlane.mV); - - F32 offset_dot_norm = local_camera_offset * plane_normal; - if (llabs(offset_dot_norm) < 0.001f) - { - offset_dot_norm = 0.001f; - } - - camera_distance = local_camera_offset.normalize(); - - F32 pos_dot_norm = getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; - - // if agent is outside the colliding half-plane - if (pos_dot_norm > mCameraCollidePlane.mV[VW]) - { - // check to see if camera is on the opposite side (inside) the half-plane - if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) - { - // diminish offset by factor to push it back outside the half-plane - camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; - } - } - else - { - if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) - { - camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; - } - } - } - else - { - camera_distance = local_camera_offset.normalize(); - } - - mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); - - if (mTargetCameraDistance != mCurrentCameraDistance) - { - F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE); - - mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); - } - - // Make the camera distance current - local_camera_offset *= mCurrentCameraDistance; - - // set the global camera position - LLVector3d camera_offset; - - LLVector3 av_pos = !isAgentAvatarValid() ? LLVector3::zero : mAvatarObject->getRenderPosition(); - camera_offset.setVec( local_camera_offset ); - camera_position_global = frame_center_global + head_offset + camera_offset; - - if (isAgentAvatarValid()) - { - LLVector3d camera_lag_d; - F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE); - LLVector3 target_lag; - LLVector3 vel = getVelocity(); - - // lag by appropriate amount for flying - F32 time_in_air = mAvatarObject->mTimeInAir.getElapsedTimeF32(); - if(!mCameraAnimating && mAvatarObject->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) - { - LLVector3 frame_at_axis = mFrameAgent.getAtAxis(); - frame_at_axis -= projected_vec(frame_at_axis, getReferenceUpVector()); - frame_at_axis.normalize(); - - //transition smoothly in air mode, to avoid camera pop - F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; - u = llclamp(u, 0.f, 1.f); - - lag_interp *= u; - - if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == mAvatarObject->getID()) - { - // disable camera lag when using mouse-directed steering - target_lag.clearVec(); - } - else - { - target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; - } - - mCameraLag = lerp(mCameraLag, target_lag, lag_interp); - - F32 lag_dist = mCameraLag.magVec(); - if (lag_dist > MAX_CAMERA_LAG) - { - mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; - } - - // clamp camera lag so that avatar is always in front - F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; - if (dot < -(MIN_CAMERA_LAG * u)) - { - mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; - } - } - else - { - mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f)); - } - - camera_lag_d.setVec(mCameraLag); - camera_position_global = camera_position_global - camera_lag_d; - } - } - } - else - { - LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); - // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value - camera_position_global = focusPosGlobal + mCameraFocusOffset; - } - - if (hit_limit) - { - *hit_limit = isConstrained; - } - - return camera_position_global; -} - - -//----------------------------------------------------------------------------- -// handleScrollWheel() -//----------------------------------------------------------------------------- -void LLAgent::handleScrollWheel(S32 clicks) -{ - if ( mCameraMode == CAMERA_MODE_FOLLOW && gAgent.getFocusOnAvatar()) - { - if ( ! mFollowCam.getPositionLocked() ) // not if the followCam position is locked in place - { - mFollowCam.zoom( clicks ); - if ( mFollowCam.isZoomedToMinimumDistance() ) - { - changeCameraToMouselook(FALSE); - } - } - } - else - { - LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); - const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); - - // Block if camera is animating - if (mCameraAnimating) - { - return; - } - - if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom_factor = (F32)pow(0.8, -clicks); - cameraZoomIn(zoom_factor); - } - else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - F32 current_zoom_fraction = mTargetCameraDistance / (mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); - current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); - - cameraOrbitIn(current_zoom_fraction * mCameraOffsetDefault.magVec() * gSavedSettings.getF32("CameraOffsetScale")); - } - else - { - F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); - cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); - } - } -} - - -//----------------------------------------------------------------------------- -// getCameraMinOffGround() -//----------------------------------------------------------------------------- -F32 LLAgent::getCameraMinOffGround() -{ - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - return 0.f; - } - else - { - if (gSavedSettings.getBOOL("DisableCameraConstraints")) - { - return -1000.f; - } - else - { - return 0.5f; - } - } -} - - -//----------------------------------------------------------------------------- -// resetCamera() -//----------------------------------------------------------------------------- -void LLAgent::resetCamera() -{ - // Remove any pitch from the avatar - LLVector3 at = mFrameAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - // have to explicitly clear field of view zoom now - mCameraFOVZoomFactor = 0.f; - - updateCamera(); -} - -//----------------------------------------------------------------------------- -// changeCameraToMouselook() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToMouselook(BOOL animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - // visibility changes at end of animation - gViewerWindow->getWindow()->resetBusyCount(); - - // Menus should not remain open on switching to mouselook... - LLMenuGL::sMenuContainer->hideMenus(); - - // unpause avatar animation - mPauseRequest = NULL; - - LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", TRUE); - gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - if (mAvatarObject.notNull()) - { - mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE ); - mAvatarObject->stopMotion( ANIM_AGENT_BREATHE_ROT ); - } - - //gViewerWindow->stopGrab(); - LLSelectMgr::getInstance()->deselectAll(); - gViewerWindow->hideCursor(); - gViewerWindow->moveCursorToCenter(); - - if( mCameraMode != CAMERA_MODE_MOUSELOOK ) - { - gFocusMgr.setKeyboardFocus( NULL ); - if (gSavedSettings.getBOOL("AONoStandsInMouselook")) LLFloaterAO::stopMotion(LLFloaterAO::getCurrentStandId(), FALSE,TRUE); - - updateLastCamera(); - mCameraMode = CAMERA_MODE_MOUSELOOK; - U32 old_flags = mControlFlags; - setControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - } -} - - -//----------------------------------------------------------------------------- -// changeCameraToDefault() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToDefault() -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - if (LLFollowCamMgr::getActiveFollowCamParams()) - { - changeCameraToFollow(); - } - else - { - changeCameraToThirdPerson(); - } -} - - -// Ventrella -//----------------------------------------------------------------------------- -// changeCameraToFollow() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToFollow(BOOL animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - if( mCameraMode != CAMERA_MODE_FOLLOW ) - { - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - animate = FALSE; - } - startCameraAnimation(); - - updateLastCamera(); - mCameraMode = CAMERA_MODE_FOLLOW; - - // bang-in the current focus, position, and up vector of the follow cam - mFollowCam.reset( mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis ); - - if (gBasicToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - if (isAgentAvatarValid()) - { - mAvatarObject->mPelvisp->setPosition(LLVector3::zero); - mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE ); - mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT ); - } - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - // unpause avatar animation - mPauseRequest = NULL; - - U32 old_flags = mControlFlags; - clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - } -} - -//----------------------------------------------------------------------------- -// changeCameraToThirdPerson() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToThirdPerson(BOOL animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - -// [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) +SG - if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) - && (mAvatarObject.notNull()) - && (mAvatarObject->isSitting()) - && gSavedSettings.getBOOL("SianaUnsitOnCamReset")) - { - setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up - } -// [/RLVa:KB] - - gViewerWindow->getWindow()->resetBusyCount(); - - mCameraZoomFraction = INITIAL_ZOOM_FRACTION; - - if (isAgentAvatarValid()) - { - if (!mAvatarObject->isSitting()) - { - mAvatarObject->mPelvisp->setPosition(LLVector3::zero); - } - mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE ); - mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT ); - } - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - LLVector3 at_axis; - - // unpause avatar animation - mPauseRequest = NULL; - - if( mCameraMode != CAMERA_MODE_THIRD_PERSON ) - { - if (gBasicToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - } - - mCameraLag.clearVec(); - if (mCameraMode == CAMERA_MODE_MOUSELOOK) - { - mCurrentCameraDistance = MIN_CAMERA_DISTANCE; - mTargetCameraDistance = MIN_CAMERA_DISTANCE; - animate = FALSE; - } - updateLastCamera(); - mCameraMode = CAMERA_MODE_THIRD_PERSON; - U32 old_flags = mControlFlags; - clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - } - - // Remove any pitch from the avatar - if (isAgentAvatarValid() && mAvatarObject->getParent()) - { - LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~obj_rot); - } - else - { - at_axis = mFrameAgent.getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis); - } - - - if (animate) - { - startCameraAnimation(); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } -} - -//----------------------------------------------------------------------------- -// changeCameraToCustomizeAvatar() -//----------------------------------------------------------------------------- -void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_animate) -{ - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - return; - } - - // - //setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up - // - gViewerWindow->getWindow()->resetBusyCount(); - - if (gFaceEditToolset) - { - LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); - } - - gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); - gSavedSettings.setBOOL("MouselookBtnState", FALSE); - gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); - gSavedSettings.setBOOL("BuildBtnState", FALSE); - - if (camera_animate) - { - // - if(gSavedSettings.getBOOL("AppearanceCameraMovement")) - // - startCameraAnimation(); - } - - // Remove any pitch from the avatar - //LLVector3 at = mFrameAgent.getAtAxis(); - //at.mV[VZ] = 0.f; - //at.normalize(); - //gAgent.resetAxes(at); - - if( mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR ) - { - mLastCameraMode = mCameraMode; - mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; - U32 old_flags = mControlFlags; - clearControlFlags(AGENT_CONTROL_MOUSELOOK); - if (old_flags != mControlFlags) - { - mbFlagsDirty = TRUE; - } - - gFocusMgr.setKeyboardFocus( NULL ); - gFocusMgr.setMouseCapture( NULL ); - - LLVOAvatar::onCustomizeStart(); - } - - if (isAgentAvatarValid()) - { - if(avatar_animate) - { - // Remove any pitch from the avatar - LLVector3 at = mFrameAgent.getAtAxis(); - at.mV[VZ] = 0.f; - at.normalize(); - gAgent.resetAxes(at); - - sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); - mCustomAnim = TRUE ; - mAvatarObject->startMotion(ANIM_AGENT_CUSTOMIZE); - LLMotion* turn_motion = mAvatarObject->findMotion(ANIM_AGENT_CUSTOMIZE); - - if (turn_motion) - { - mAnimationDuration = turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP; - - } - else - { - mAnimationDuration = gSavedSettings.getF32("ZoomTime"); - } - } - - - - gAgent.setFocusGlobal(LLVector3d::zero); - } - else - { - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - - // - if(!gSavedSettings.getBOOL("AppearanceCameraMovement")) - { - //hmm - mCameraAnimating = FALSE; - endAnimationUpdateUI(); - } - -} - - -// -// Focus point management -// - -//----------------------------------------------------------------------------- -// startCameraAnimation() -//----------------------------------------------------------------------------- -void LLAgent::startCameraAnimation() -{ - mAnimationCameraStartGlobal = getCameraPositionGlobal(); - mAnimationFocusStartGlobal = mFocusGlobal; - mAnimationTimer.reset(); - mCameraAnimating = TRUE; - mAnimationDuration = gSavedSettings.getF32("ZoomTime"); -} - -//----------------------------------------------------------------------------- -// stopCameraAnimation() -//----------------------------------------------------------------------------- -void LLAgent::stopCameraAnimation() -{ - mCameraAnimating = FALSE; -} - -void LLAgent::clearFocusObject() -{ - if (mFocusObject.notNull()) - { - startCameraAnimation(); - - setFocusObject(NULL); - mFocusObjectOffset.clearVec(); - } -} - -void LLAgent::setFocusObject(LLViewerObject* object) -{ - mFocusObject = object; -} - -// Focus on a point, but try to keep camera position stable. -//----------------------------------------------------------------------------- -// setFocusGlobal() -//----------------------------------------------------------------------------- -void LLAgent::setFocusGlobal(const LLPickInfo& pick) -{ - LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); - - if (objectp) - { - // focus on object plus designated offset - // which may or may not be same as pick.mPosGlobal - setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); - } - else - { - // focus directly on point where user clicked - setFocusGlobal(pick.mPosGlobal, pick.mObjectID); - } -} - - -void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id) -{ - setFocusObject(gObjectList.findObject(object_id)); - LLVector3d old_focus = mFocusTargetGlobal; - LLViewerObject *focus_obj = mFocusObject; - - // if focus has changed - if (old_focus != focus) - { - if (focus.isExactlyZero()) - { - if (isAgentAvatarValid()) - { - mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition()); - } - else - { - mFocusTargetGlobal = getPositionGlobal(); - } - mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; - mCameraFocusOffset = mCameraFocusOffsetTarget; - setLookAt(LOOKAT_TARGET_CLEAR); - } - else - { - mFocusTargetGlobal = focus; - if (!focus_obj) - { - mCameraFOVZoomFactor = 0.f; - } - - mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; - - startCameraAnimation(); - - if (focus_obj) - { - if (focus_obj->isAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); - } - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal)); - } - } - } - else // focus == mFocusTargetGlobal - { - if (focus.isExactlyZero()) - { - if (isAgentAvatarValid()) - { - mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition()); - } - else - { - mFocusTargetGlobal = getPositionGlobal(); - } - } - mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; - mCameraFocusOffset = mCameraFocusOffsetTarget; - } - - if (mFocusObject.notNull()) - { - // for attachments, make offset relative to avatar, not the attachment - if (mFocusObject->isAttachment()) - { - while (mFocusObject.notNull() // DEV-29123 - can crash with a messed-up attachment - && !mFocusObject->isAvatar()) - { - mFocusObject = (LLViewerObject*) mFocusObject->getParent(); - } - setFocusObject((LLViewerObject*)mFocusObject); - } - updateFocusOffset(); - } -} - -// Used for avatar customization -//----------------------------------------------------------------------------- -// setCameraPosAndFocusGlobal() -//----------------------------------------------------------------------------- -void LLAgent::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id) -{ - LLVector3d old_focus = mFocusTargetGlobal; - - F64 focus_delta_squared = (old_focus - focus).magVecSquared(); - const F64 ANIM_EPSILON_SQUARED = 0.0001; - if( focus_delta_squared > ANIM_EPSILON_SQUARED ) - { - startCameraAnimation(); - - if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) - { - // Compensate for the fact that the camera has already been offset to make room for LLFloaterCustomize. - mAnimationCameraStartGlobal -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * calcCustomizeAvatarUIOffset( mAnimationCameraStartGlobal )); - } - } - - //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); - setFocusObject(gObjectList.findObject(object_id)); - mFocusTargetGlobal = focus; - mCameraFocusOffsetTarget = camera_pos - focus; - mCameraFocusOffset = mCameraFocusOffsetTarget; - - if (mFocusObject) - { - if (mFocusObject->isAvatar()) - { - setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); - } - } - else - { - setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal)); - } - - if( mCameraAnimating ) - { - const F64 ANIM_METERS_PER_SECOND = 10.0; - const F64 MIN_ANIM_SECONDS = 0.5; - F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); - setAnimationDuration( (F32)anim_duration ); - } - - updateFocusOffset(); -} - -//----------------------------------------------------------------------------- -// setSitCamera() -//----------------------------------------------------------------------------- -void LLAgent::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus) -{ - BOOL camera_enabled = !object_id.isNull(); - - if (camera_enabled) - { - LLViewerObject *reference_object = gObjectList.findObject(object_id); - if (reference_object) - { - //convert to root object relative? - mSitCameraPos = camera_pos; - mSitCameraFocus = camera_focus; - mSitCameraReferenceObject = reference_object; - mSitCameraEnabled = TRUE; - } - } - else - { - mSitCameraPos.clearVec(); - mSitCameraFocus.clearVec(); - mSitCameraReferenceObject = NULL; - mSitCameraEnabled = FALSE; - } -} - -//----------------------------------------------------------------------------- -// setFocusOnAvatar() -//----------------------------------------------------------------------------- -void LLAgent::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) -{ - if (focus_on_avatar != mFocusOnAvatar) - { - if (animate) - { - startCameraAnimation(); - } - else - { - stopCameraAnimation(); - } - } - - //RN: when focused on the avatar, we're not "looking" at it - // looking implies intent while focusing on avatar means - // you're just walking around with a camera on you...eesh. - if (!mFocusOnAvatar && focus_on_avatar) - { - setFocusGlobal(LLVector3d::zero); - mCameraFOVZoomFactor = 0.f; - if (mCameraMode == CAMERA_MODE_THIRD_PERSON) - { - LLVector3 at_axis; - if (isAgentAvatarValid() && mAvatarObject->getParent()) - { - LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation(); - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis * ~obj_rot); - } - else - { - at_axis = LLViewerCamera::getInstance()->getAtAxis(); - at_axis.mV[VZ] = 0.f; - at_axis.normalize(); - resetAxes(at_axis); - } - } - } - // unlocking camera from avatar - else if (mFocusOnAvatar && !focus_on_avatar) - { - // keep camera focus point consistent, even though it is now unlocked - setFocusGlobal(getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); - } - - mFocusOnAvatar = focus_on_avatar; -} - //----------------------------------------------------------------------------- // heardChat() //----------------------------------------------------------------------------- @@ -4699,303 +2063,106 @@ void LLAgent::heardChat(const LLUUID& id) if (ll_rand(2) == 0) { LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); - setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero); + gAgentCamera.setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero); } mLastChatterID = id; mChatTimer.reset(); } -//----------------------------------------------------------------------------- -// lookAtLastChat() -//----------------------------------------------------------------------------- -void LLAgent::lookAtLastChat() -{ - // Block if camera is animating or not in normal third person camera mode - if (mCameraAnimating || !cameraThirdPerson()) - { - return; - } - - LLViewerObject *chatter = gObjectList.findObject(mLastChatterID); - if (chatter) - { - LLVector3 delta_pos; - if (chatter->isAvatar()) - { - LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; - if (isAgentAvatarValid() && chatter_av->mHeadp) - { - delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition(); - } - else - { - delta_pos = chatter->getPositionAgent() - getPositionAgent(); - } - delta_pos.normalize(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normalize(); - LLVector3 up = left % delta_pos; - up.normalize(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - if (chatter_av->mHeadp) - { - setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), mLastChatterID); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - } - else - { - setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - } - setFocusOnAvatar(FALSE, TRUE); - } - else - { - delta_pos = chatter->getRenderPosition() - getPositionAgent(); - delta_pos.normalize(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normalize(); - LLVector3 up = left % delta_pos; - up.normalize(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - setFocusOnAvatar(FALSE, TRUE); - } - } -} - -void LLAgent::lookAtObject(LLUUID object_id, ECameraPosition camera_pos) -{ - // Block if camera is animating or not in normal third person camera mode - if (mCameraAnimating || !cameraThirdPerson()) - { - return; - } - - LLViewerObject *chatter = gObjectList.findObject(object_id); - if (chatter) - { - LLVector3 delta_pos; - if (chatter->isAvatar()) - { - LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; - if (!mAvatarObject.isNull() && chatter_av->mHeadp) - { - delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition(); - } - else - { - delta_pos = chatter->getPositionAgent() - getPositionAgent(); - } - delta_pos.normVec(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normVec(); - LLVector3 up = left % delta_pos; - up.normVec(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - F32 radius = chatter_av->getVObjRadius(); - LLVector3d view_dist(radius, radius, 0.0f); - - if (chatter_av->mHeadp) - { - setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), object_id); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - - switch(camera_pos) - { - case CAMERA_POSITION_SELF: - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); - break; - case CAMERA_POSITION_OBJECT: - mCameraFocusOffsetTarget = view_dist; - break; - } - } - else - { - setFocusGlobal(chatter->getPositionGlobal(), object_id); - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - - switch(camera_pos) - { - case CAMERA_POSITION_SELF: - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - break; - case CAMERA_POSITION_OBJECT: - mCameraFocusOffsetTarget = view_dist; - break; - } - } - setFocusOnAvatar(FALSE, TRUE); - } - else - { - delta_pos = chatter->getRenderPosition() - getPositionAgent(); - delta_pos.normVec(); - - setControlFlags(AGENT_CONTROL_STOP); - - changeCameraToThirdPerson(); - - LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition(); - LLVector3 left = delta_pos % LLVector3::z_axis; - left.normVec(); - LLVector3 up = left % delta_pos; - up.normVec(); - new_camera_pos -= delta_pos * 0.4f; - new_camera_pos += left * 0.3f; - new_camera_pos += up * 0.2f; - - setFocusGlobal(chatter->getPositionGlobal(), object_id); - - switch(camera_pos) - { - case CAMERA_POSITION_SELF: - mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); - break; - case CAMERA_POSITION_OBJECT: - F32 radius = chatter->getVObjRadius(); - LLVector3d view_dist(radius, radius, 0.0f); - mCameraFocusOffsetTarget = view_dist; - break; - } - - setFocusOnAvatar(FALSE, TRUE); - } - } -} - const F32 SIT_POINT_EXTENTS = 0.2f; +LLSD ll_sdmap_from_vector3(const LLVector3& vec) +{ + LLSD ret; + ret["X"] = vec.mV[VX]; + ret["Y"] = vec.mV[VY]; + ret["Z"] = vec.mV[VZ]; + return ret; +} + +LLVector3 ll_vector3_from_sdmap(const LLSD& sd) +{ + LLVector3 ret; + ret.mV[VX] = F32(sd["X"].asReal()); + ret.mV[VY] = F32(sd["Y"].asReal()); + ret.mV[VZ] = F32(sd["Z"].asReal()); + return ret; +} + void LLAgent::setStartPosition( U32 location_id ) { - LLViewerObject *object; - - if ( !(gAgentID == LLUUID::null) ) - { - // we've got an ID for an agent viewerobject - object = gObjectList.findObject(gAgentID); - if (object) + if (gAgentID == LLUUID::null) { - // we've got the viewer object - // Sometimes the agent can be velocity interpolated off of - // this simulator. Clamp it to the region the agent is - // in, a little bit in on each side. - const F32 INSET = 0.5f; //meters - const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters(); + return; + } + if (gObjectList.findAvatar(gAgentID) == NULL) + { + llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl; + return; + } + // we've got the viewer object + // Sometimes the agent can be velocity interpolated off of + // this simulator. Clamp it to the region the agent is + // in, a little bit in on each side. + const F32 INSET = 0.5f; //meters + const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters(); - LLVector3 agent_pos = getPositionAgent(); - LLVector3 agent_look_at = mFrameAgent.getAtAxis(); + LLVector3 agent_pos = getPositionAgent(); - if (isAgentAvatarValid()) - { - // the z height is at the agent's feet + if (isAgentAvatarValid()) + { + // the z height is at the agent's feet agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ]; - } + } - agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET ); - agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET ); + agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET ); + agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET ); - // Don't let them go below ground, or too high. - agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ], - mRegionp->getLandHeightRegion( agent_pos ), - LLWorld::getInstance()->getRegionMaxHeight() ); - // Send the CapReq + // Don't let them go below ground, or too high. + agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ], + mRegionp->getLandHeightRegion( agent_pos ), + LLWorld::getInstance()->getRegionMaxHeight() ); + std::string url = gAgent.getRegion()->getCapability("HomeLocation"); + if( !url.empty() ) + { + // Send the CapReq + LLSD request; + LLSD body; + LLSD homeLocation; - LLSD body; + homeLocation["LocationId"] = LLSD::Integer(location_id); + homeLocation["LocationPos"] = ll_sdmap_from_vector3(agent_pos); + homeLocation["LocationLookAt"] = ll_sdmap_from_vector3(mFrameAgent.getAtAxis()); - std::string url = gAgent.getRegion()->getCapability("HomeLocation"); - std::ostringstream strBuffer; - if( url.empty() ) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetStartLocationRequest); - msg->nextBlockFast( _PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, getID()); - msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); - msg->nextBlockFast( _PREHASH_StartLocationData); - // corrected by sim - msg->addStringFast(_PREHASH_SimName, ""); - msg->addU32Fast(_PREHASH_LocationID, location_id); - msg->addVector3Fast(_PREHASH_LocationPos, agent_pos); - msg->addVector3Fast(_PREHASH_LocationLookAt,mFrameAgent.getAtAxis()); + body["HomeLocation"] = homeLocation; + + LLHTTPClient::post( url, body, new LLHomeLocationResponder() ); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetStartLocationRequest); + msg->nextBlockFast( _PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, getID()); + msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + msg->nextBlockFast( _PREHASH_StartLocationData); + // corrected by sim + msg->addStringFast(_PREHASH_SimName, ""); + msg->addU32Fast(_PREHASH_LocationID, location_id); + msg->addVector3Fast(_PREHASH_LocationPos, agent_pos); + msg->addVector3Fast(_PREHASH_LocationLookAt,mFrameAgent.getAtAxis()); - // Reliable only helps when setting home location. Last - // location is sent on quit, and we don't have time to ack - // the packets. - msg->sendReliable(mRegionp->getHost()); - + // Reliable only helps when setting home location. Last + // location is sent on quit, and we don't have time to ack + // the packets. + msg->sendReliable(mRegionp->getHost()); + } const U32 HOME_INDEX = 1; if( HOME_INDEX == location_id ) - { - setHomePosRegion( mRegionp->getHandle(), getPositionAgent() ); - } - } - else - { - strBuffer << location_id; - body["HomeLocation"]["LocationId"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_pos.mV[VX]; - body["HomeLocation"]["LocationPos"]["X"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_pos.mV[VY]; - body["HomeLocation"]["LocationPos"]["Y"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_pos.mV[VZ]; - body["HomeLocation"]["LocationPos"]["Z"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_look_at.mV[VX]; - body["HomeLocation"]["LocationLookAt"]["X"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_look_at.mV[VY]; - body["HomeLocation"]["LocationLookAt"]["Y"] = strBuffer.str(); - - strBuffer.str(""); - strBuffer << agent_look_at.mV[VZ]; - body["HomeLocation"]["LocationLookAt"]["Z"] = strBuffer.str(); - - LLHTTPClient::post( url, body, new LLHomeLocationResponder() ); - } - } - else - { - llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl; - } - } + { + setHomePosRegion( mRegionp->getHandle(), getPositionAgent() ); + } } void LLAgent::requestStopMotion( LLMotion* motion ) @@ -5045,29 +2212,29 @@ void LLAgent::onAnimStop(const LLUUID& id) } } -BOOL LLAgent::isGodlike() const +bool LLAgent::isGodlike() const { - return mAgentAccess.isGodlike(); + return mAgentAccess->isGodlike(); } U8 LLAgent::getGodLevel() const { - return mAgentAccess.getGodLevel(); + return mAgentAccess->getGodLevel(); } bool LLAgent::wantsPGOnly() const { - return mAgentAccess.wantsPGOnly(); + return mAgentAccess->wantsPGOnly(); } bool LLAgent::canAccessMature() const { - return mAgentAccess.canAccessMature(); + return mAgentAccess->canAccessMature(); } bool LLAgent::canAccessAdult() const { - return mAgentAccess.canAccessAdult(); + return mAgentAccess->canAccessAdult(); } bool LLAgent::canAccessMaturityInRegion( U64 region_handle ) const @@ -5102,37 +2269,37 @@ bool LLAgent::canAccessMaturityAtGlobal( LLVector3d pos_global ) const bool LLAgent::prefersPG() const { - return mAgentAccess.prefersPG(); + return mAgentAccess->prefersPG(); } bool LLAgent::prefersMature() const { - return mAgentAccess.prefersMature(); + return mAgentAccess->prefersMature(); } bool LLAgent::prefersAdult() const { - return mAgentAccess.prefersAdult(); + return mAgentAccess->prefersAdult(); } bool LLAgent::isTeen() const { - return mAgentAccess.isTeen(); + return mAgentAccess->isTeen(); } bool LLAgent::isMature() const { - return mAgentAccess.isMature(); + return mAgentAccess->isMature(); } bool LLAgent::isAdult() const { - return mAgentAccess.isAdult(); + return mAgentAccess->isAdult(); } void LLAgent::setTeen(bool teen) { - mAgentAccess.setTeen(teen); + mAgentAccess->setTeen(teen); } //static @@ -5177,32 +2344,32 @@ bool LLAgent::sendMaturityPreferenceToServer(int preferredMaturity) BOOL LLAgent::getAdminOverride() const { - return mAgentAccess.getAdminOverride(); + return mAgentAccess->getAdminOverride(); } void LLAgent::setMaturity(char text) { - mAgentAccess.setMaturity(text); + mAgentAccess->setMaturity(text); } void LLAgent::setAdminOverride(BOOL b) { - mAgentAccess.setAdminOverride(b); + mAgentAccess->setAdminOverride(b); } void LLAgent::setGodLevel(U8 god_level) { - mAgentAccess.setGodLevel(god_level); + mAgentAccess->setGodLevel(god_level); } void LLAgent::setAOTransition() { - mAgentAccess.setTransition(); + mAgentAccess->setTransition(); } const LLAgentAccess& LLAgent::getAgentAccess() { - return mAgentAccess; + return *mAgentAccess; } @@ -5430,7 +2597,7 @@ LLQuaternion LLAgent::getHeadRotation() return LLQuaternion::DEFAULT; } - if (!gAgent.cameraMouselook()) + if (!gAgentCamera.cameraMouselook()) { return mAvatarObject->getRotation(); } @@ -5623,6 +2790,41 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global) mAgentOriginGlobal = origin_global; } +BOOL LLAgent::leftButtonGrabbed() const +{ + const BOOL camera_mouse_look = gAgentCamera.cameraMouselook(); + return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) + || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0) + || (!camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) + || (camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0); +} + +BOOL LLAgent::rotateGrabbed() const +{ + return (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0) + || (mControlsTakenCount[CONTROL_YAW_NEG_INDEX] > 0); +} + +BOOL LLAgent::forwardGrabbed() const +{ + return (mControlsTakenCount[CONTROL_AT_POS_INDEX] > 0); +} + +BOOL LLAgent::backwardGrabbed() const +{ + return (mControlsTakenCount[CONTROL_AT_NEG_INDEX] > 0); +} + +BOOL LLAgent::upGrabbed() const +{ + return (mControlsTakenCount[CONTROL_UP_POS_INDEX] > 0); +} + +BOOL LLAgent::downGrabbed() const +{ + return (mControlsTakenCount[CONTROL_UP_NEG_INDEX] > 0); +} + void update_group_floaters(const LLUUID& group_id) { LLFloaterGroupInfo::refreshGroup(group_id); @@ -6068,7 +3270,7 @@ void LLAgent::processControlRelease(LLMessageSystem *msg, void **) //static void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data) { - gAgent.mNumPendingQueries--; + gAgentQueryManager.mNumPendingQueries--; if (!isAgentAvatarValid()) { @@ -6076,7 +3278,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * return; } - if (gAgent.cameraCustomizeAvatar()) + if (gAgentCamera.cameraCustomizeAvatar()) { // ignore baked textures when in customize mode return; @@ -6099,12 +3301,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * if (texture_id.notNull() && (S32)texture_index < BAKED_NUM_INDICES - && gAgent.mActiveCacheQueries[ texture_index ] == query_id) + && gAgentQueryManager.mActiveCacheQueries[ texture_index ] == query_id) { //llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl; gAgent.getAvatarObject()->setCachedBakedTexture(getTextureIndex((EBakedTextureIndex)texture_index), texture_id); //avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id ); - gAgent.mActiveCacheQueries[ texture_index ] = 0; + gAgentQueryManager.mActiveCacheQueries[ texture_index ] = 0; num_results++; } } @@ -6113,7 +3315,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * gAgent.getAvatarObject()->updateMeshTextures(); - if (gAgent.mNumPendingQueries == 0) + if (gAgentQueryManager.mNumPendingQueries == 0) { // RN: not sure why composites are disabled at this point gAgent.getAvatarObject()->setCompositeUpdatesEnabled(TRUE); @@ -6229,9 +3431,9 @@ bool LLAgent::teleportCore(bool is_local) // Close all pie menus, deselect land, etc. // Don't change the camera until we know teleport succeeded. JC // - if(gAgent.getFocusOnAvatar()) + if(gAgentCamera.getFocusOnAvatar()) // - resetView(FALSE); + gAgentCamera.resetView(FALSE); // local logic LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TELEPORT_COUNT); @@ -6458,7 +3660,7 @@ void LLAgent::teleportViaLocationLookAt(const LLVector3d& pos_global) // [/RLVa:KB] mbTeleportKeepsLookAt = true; - setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); // detach camera form avatar, so it keeps direction U64 region_handle = to_region_handle(pos_global); LLVector3 pos_local = (LLVector3)(pos_global - from_region_handle(region_handle)); teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt()); @@ -7081,7 +4283,7 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void LLVOAvatar* avatar = gAgent.getAvatarObject(); if( avatar && (agent_id == avatar->getID()) ) { - gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgent.mAgentWearablesUpdateSerialNum ); + gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum ); S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData); if( num_wearables < 4 ) @@ -7205,7 +4407,7 @@ void LLAgent::onInitialWearableAssetArrived( LLWearable* wearable, void* userdat // Check to see if there are any baked textures that we hadn't uploaded before we logged off last time. // If there are any, schedule them to be uploaded as soon as the layer textures they depend on arrive. - if( !gAgent.cameraCustomizeAvatar() ) + if( !gAgentCamera.cameraCustomizeAvatar() ) { avatar->requestLayerSetUploads(); } @@ -7586,7 +4788,7 @@ void LLAgent::sendAgentSetAppearance() { if (!isAgentAvatarValid()) return; - if (mNumPendingQueries > 0 && !gAgent.cameraCustomizeAvatar()) + if (gAgentQueryManager.mNumPendingQueries > 0 && !gAgentCamera.cameraCustomizeAvatar()) { return; } @@ -8151,7 +5353,7 @@ void LLAgent::queryWearableCache() gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); - gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID); + gMessageSystem->addS32Fast(_PREHASH_SerialNum, gAgentQueryManager.mWearablesCacheQueryID); S32 num_queries = 0; for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) @@ -8180,13 +5382,13 @@ void LLAgent::queryWearableCache() gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index); } - mActiveCacheQueries[ baked_index ] = mTextureCacheQueryID; + gAgentQueryManager.mActiveCacheQueries[ baked_index ] = gAgentQueryManager.mWearablesCacheQueryID; } llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; gMessageSystem->sendReliable(getRegion()->getHost()); - mNumPendingQueries++; - mTextureCacheQueryID++; + gAgentQueryManager.mNumPendingQueries++; + gAgentQueryManager.mWearablesCacheQueryID++; } // User has picked "remove from avatar" from a menu. @@ -8329,6 +5531,37 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename) }//end for (all message sets in xml file) } +// Draw a representation of current autopilot target +void LLAgent::renderAutoPilotTarget() +{ + if (mAutoPilot) + { + F32 height_meters; + LLVector3d target_global; + + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + + // not textured + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // lovely green + glColor4f(0.f, 1.f, 1.f, 1.f); + + target_global = mAutoPilotTargetGlobal; + + gGL.translatef((F32)(target_global.mdV[VX]), (F32)(target_global.mdV[VY]), (F32)(target_global.mdV[VZ])); + + height_meters = 1.f; + + glScalef(height_meters, height_meters, height_meters); + + gSphere.render(1500.f); + + gGL.popMatrix(); + } +} + // Combines userRemoveAllAttachments() and userAttachMultipleAttachments() logic to // get attachments into desired state with minimal number of adds/removes. //void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj_item_array) @@ -8535,65 +5768,72 @@ void LLAgent::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_ void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity) { const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0)); - LLSimInfo* siminfo; - siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal); - std::string sim_name; - LLWorldMap::getInstance()->simNameFromPosGlobal( posglobal, sim_name ); + LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal); + if(mPendingLure) + delete mPendingLure; + mPendingLure = new SHLureRequest(fromname,posglobal,x,y,z); + + if(siminfo) //We already have an entry? Go right on to displaying it. + { + onFoundLureDestination(siminfo); + } + else + { + U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS); + U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS); + LLWorldMap::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response + } +} + +void LLAgent::onFoundLureDestination(LLSimInfo *siminfo) +{ + if(!mPendingLure) + return; + + if(!siminfo) + siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(mPendingLure->mPosGlobal); if(siminfo) { - llinfos << fromname << "'s teleport lure is to " << sim_name << " (" << maturity << ")" << llendl; + const std::string sim_name = siminfo->mName; + const std::string maturity = LLViewerRegion::accessToString(siminfo->mAccess); + + llinfos << mPendingLure->mAvatarName << "'s teleport lure is to " << sim_name << " (" << maturity << ")" << llendl; LLStringUtil::format_map_t args; - args["[NAME]"] = fromname; - args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name.c_str(), S32(x), S32(y), S32(z)); - std::string msg = LLTrans::getString("TeleportLureMaturity", args); - if (maturity != "") + args["[NAME]"] = mPendingLure->mAvatarName; + args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name, (S32)mPendingLure->mPosLocal[0], (S32)mPendingLure->mPosLocal[1], (S32)mPendingLure->mPosLocal[2] ); + std::string msg = LLTrans::getString("TeleportOfferMaturity", args); + if (!maturity.empty()) { msg.append(llformat(" (%s)", maturity.c_str())); } LLChat chat(msg); LLFloaterChat::addChat(chat); } - else - { - LLAgent::lure_show = TRUE; - LLAgent::lure_name = fromname; - LLAgent::lure_posglobal = posglobal; - LLAgent::lure_global_x = U16(global_x / 256); - LLAgent::lure_global_y = U16(global_y / 256); - LLAgent::lure_x = x; - LLAgent::lure_y = y; - LLAgent::lure_z = z; - LLAgent::lure_maturity = maturity; - LLWorldMap::getInstance()->sendMapBlockRequest(lure_global_x, lure_global_y, lure_global_x, lure_global_y, true); - } -} - -void LLAgent::onFoundLureDestination() -{ - LLAgent::lure_show = FALSE; - LLSimInfo* siminfo; - siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(LLAgent::lure_posglobal); - std::string sim_name; - LLWorldMap::getInstance()->simNameFromPosGlobal(LLAgent::lure_posglobal, sim_name ); - if(siminfo) - { - llinfos << LLAgent::lure_name << "'s teleport lure is to " << sim_name << " (" << LLAgent::lure_maturity << ")" << llendl; - LLStringUtil::format_map_t args; - args["[NAME]"] = LLAgent::lure_name; - args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name, S32(LLAgent::lure_x), S32(LLAgent::lure_y), S32(LLAgent::lure_z)); - std::string msg = LLTrans::getString("TeleportOfferMaturity", args); - if (LLAgent::lure_maturity != "") - { - msg.append(llformat(" (%s)", LLAgent::lure_maturity.c_str())); - } - LLChat chat(msg); - LLFloaterChat::addChat(chat); - } else llwarns << "Grand scheme failed" << llendl; + delete mPendingLure; + mPendingLure = NULL; } +/********************************************************************************/ + +LLAgentQueryManager gAgentQueryManager; + +LLAgentQueryManager::LLAgentQueryManager() : + mWearablesCacheQueryID(0), + mNumPendingQueries(0), + mUpdateSerialNum(0) +{ + for (U32 i = 0; i < BAKED_NUM_INDICES; i++) + { + mActiveCacheQueries[i] = 0; + } +} + +LLAgentQueryManager::~LLAgentQueryManager() +{ +} // EOF diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index f697e4778..8b6e9821c 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -36,66 +36,24 @@ #include #include "indra_constants.h" -#include "llmath.h" -#include "llcontrol.h" -#include "llcoordframe.h" -#include "llevent.h" -#include "llagentaccess.h" + +#include "llevent.h" // LLObservable base class #include "llagentconstants.h" -#include "llanimationstates.h" -#include "lldbstrings.h" -#include "llhudeffectlookat.h" -#include "llhudeffectpointat.h" -#include "llinventorymodel.h" -#include "llmemory.h" -#include "llstring.h" -#include "lluuid.h" -#include "m3math.h" -#include "m4math.h" -#include "llquaternion.h" -#include "lltimer.h" -#include "v3dmath.h" -#include "v3math.h" -#include "v4color.h" -#include "v4math.h" -//#include "vmath.h" -#include "stdenums.h" -#include "llwearable.h" +#include "llagentdata.h" // gAgentID, gAgentSessionID #include "llcharacter.h" -#include "llinventory.h" +#include "llcoordframe.h" // for mFrameAgent +#include "llvoavatardefines.h" #include "llviewerinventory.h" -#include "llviewerobject.h" -#include "llagentdata.h" +#include "llinventorymodel.h" // Ventrella #include "llfollowcam.h" // end Ventrella +const BOOL ANIMATE = TRUE; const U8 AGENT_STATE_TYPING = 0x04; // Typing indication const U8 AGENT_STATE_EDITING = 0x10; // Set when agent has objects selected -const BOOL ANIMATE = TRUE; - -typedef enum e_camera_modes -{ - CAMERA_MODE_THIRD_PERSON, - CAMERA_MODE_MOUSELOOK, - CAMERA_MODE_CUSTOMIZE_AVATAR, - CAMERA_MODE_FOLLOW -} ECameraMode; - -typedef enum e_camera_position -{ - CAMERA_POSITION_SELF, /** Camera positioned at our position */ - CAMERA_POSITION_OBJECT /** Camera positioned at observed object's position */ -} ECameraPosition; - -typedef enum e_anim_request -{ - ANIM_REQUEST_START, - ANIM_REQUEST_STOP -} EAnimRequest; - class LLChat; class LLVOAvatar; class LLViewerRegion; @@ -106,6 +64,18 @@ class LLPermissions; class LLHost; class LLFriendObserver; class LLPickInfo; +class LLViewerObject; +class LLAgentDropGroupViewerNode; +class LLAgentAccess; +class LLSimInfo; + +typedef std::vector llvo_vec_t; + +enum EAnimRequest +{ + ANIM_REQUEST_START, + ANIM_REQUEST_STOP +}; struct LLGroupData { @@ -118,11 +88,6 @@ struct LLGroupData std::string mName; }; -inline bool operator==(const LLGroupData &a, const LLGroupData &b) -{ - return (a.mID == b.mID); -} - BOOL isAgentAvatarValid(); // forward declarations @@ -134,261 +99,396 @@ class LLAgent : public LLObservable LOG_CLASS(LLAgent); public: - // When the agent hasn't typed anything for this duration, it leaves the - // typing state (for both chat and IM). - static const F32 TYPING_TIMEOUT_SECS; + friend class LLAgentDropGroupViewerNode; +/******************************************************************************** + ** ** + ** INITIALIZATION + **/ + + //-------------------------------------------------------------------- + // Constructors / Destructors + //-------------------------------------------------------------------- +public: LLAgent(); ~LLAgent(); void init(); void cleanup(); - // - // MANIPULATORS - // - // TODO: Put all non-const functions here. +//Avatar object decoupled from agent in v2. Access changed to global gAgentAvatarp pointer. Stuff below will vanish. + void setAvatarObject(LLVOAvatar *avatar); //Legacy + LLVOAvatar *getAvatarObject() const { return mAvatarObject; } +private: + LLPointer mAvatarObject; - // Called whenever the agent moves. Puts camera back in default position, - // deselects items, etc. - void resetView(BOOL reset_camera = TRUE, BOOL change_camera = FALSE); + //-------------------------------------------------------------------- + // Login + //-------------------------------------------------------------------- +public: + void onAppFocusGained(); + void setFirstLogin(BOOL b) { mFirstLogin = b; } + // Return TRUE if the database reported this login as the first for this particular user. + BOOL isFirstLogin() const { return mFirstLogin; } + BOOL isInitialized() const { return mInitialized; } +public: + std::string mMOTD; // Message of the day +private: + BOOL mInitialized; + BOOL mFirstLogin; - // Called on camera movement, to allow the camera to be unlocked from the - // default position behind the avatar. - void unlockView(); - - void onAppFocusGained(); - - void sendMessage(); // Send message to this agent's region. - void sendReliableMessage(); - void resetClientTag(); - LLVector3d calcCameraPositionTargetGlobal(BOOL *hit_limit = NULL); // Calculate the camera position target - LLVector3d calcFocusPositionTargetGlobal(); - LLVector3d calcThirdPersonFocusOffset(); - // target for this mode - LLVector3d getCameraPositionGlobal() const; - const LLVector3 &getCameraPositionAgent() const; - F32 calcCameraFOVZoomFactor(); - F32 getCameraMinOffGround(); // minimum height off ground for this mode, meters - void endAnimationUpdateUI(); - void setKey(const S32 direction, S32 &key); // sets key to +1 for +direction, -1 for -direction - void handleScrollWheel(S32 clicks); // mousewheel driven zoom + //-------------------------------------------------------------------- + // Session + //-------------------------------------------------------------------- +public: + const LLUUID& getID() const { return gAgentID; } + const LLUUID& getSessionID() const { return gAgentSessionID; } + // Note: NEVER send this value in the clear or over any weakly + // encrypted channel (such as simple XOR masking). If you are unsure + // ask Aaron or MarkL. + const LLUUID& getSecureSessionID() const { return mSecureSessionID; } +public: + LLUUID mSecureSessionID; // Secure token for this login session - void setAvatarObject(LLVOAvatar *avatar); +/** Initialization + ** ** + *******************************************************************************/ - // rendering state bitmask helpers - void startTyping(); - void stopTyping(); - void setRenderState(U8 newstate); - void clearRenderState(U8 clearstate); - U8 getRenderState(); +/******************************************************************************** + ** ** + ** IDENTITY + **/ - // Set the home data + //-------------------------------------------------------------------- + // Name + //-------------------------------------------------------------------- +public: + void getName(std::string& name); //Legacy + void buildFullname(std::string &name) const; //Legacy + //*TODO remove, is not used as of August 20, 2009 + void buildFullnameAndTitle(std::string &name) const; + + //-------------------------------------------------------------------- + // Gender + //-------------------------------------------------------------------- +public: + // On the very first login, gender isn't chosen until the user clicks + // in a dialog. We don't render the avatar until they choose. + BOOL isGenderChosen() const { return mGenderChosen; } + void setGenderChosen(BOOL b) { mGenderChosen = b; } + private: + BOOL mGenderChosen; + + //-------------------------------------------------------------------- + // Client Tagging + //-------------------------------------------------------------------- +public: + void resetClientTag(); + +/** Identity + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** POSITION + **/ + + //-------------------------------------------------------------------- + // Position + //-------------------------------------------------------------------- +public: + LLVector3 getPosAgentFromGlobal(const LLVector3d &pos_global) const; + LLVector3d getPosGlobalFromAgent(const LLVector3 &pos_agent) const; + const LLVector3d &getPositionGlobal() const; + const LLVector3 &getPositionAgent(); + // Call once per frame to update position, angles (radians). + void updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y); // call once per frame to update position, angles radians + void setPositionAgent(const LLVector3 ¢er); +protected: + void propagate(const F32 dt); // ! BUG ! Should roll into updateAgentPosition +private: + mutable LLVector3d mPositionGlobal; + + //-------------------------------------------------------------------- + // Velocity + //-------------------------------------------------------------------- +public: + LLVector3 getVelocity() const; + F32 getVelocityZ() const { return getVelocity().mV[VZ]; } // ! HACK ! + + //-------------------------------------------------------------------- + // Coordinate System + //-------------------------------------------------------------------- +public: + const LLCoordFrame& getFrameAgent() const { return mFrameAgent; } + void initOriginGlobal(const LLVector3d &origin_global); // Only to be used in ONE place! - djs 08/07/02 + void resetAxes(); + void resetAxes(const LLVector3 &look_at); // Makes reasonable left and up + // The following three get*Axis functions return direction avatar is looking, not camera. + const LLVector3& getAtAxis() const { return mFrameAgent.getAtAxis(); } + const LLVector3& getUpAxis() const { return mFrameAgent.getUpAxis(); } + const LLVector3& getLeftAxis() const { return mFrameAgent.getLeftAxis(); } + LLQuaternion getQuat() const; // Returns the quat that represents the rotation of the agent in the absolute frame +private: + LLVector3d mAgentOriginGlobal; // Origin of agent coords from global coords + LLCoordFrame mFrameAgent; // Agent position and view, agent-region coordinates + + + //-------------------------------------------------------------------- + // Home + //-------------------------------------------------------------------- +public: + void setStartPosition(U32 location_id); // Marks current location as start, sends information to servers + void setHomePosRegion( const U64& region_handle, const LLVector3& pos_region ); + BOOL getHomePosGlobal(LLVector3d* pos_global); +private: + BOOL mHaveHomePosition; + U64 mHomeRegionHandle; + LLVector3 mHomePosRegion; + + //-------------------------------------------------------------------- + // Region + //-------------------------------------------------------------------- +public: void setRegion(LLViewerRegion *regionp); LLViewerRegion *getRegion() const; const LLHost& getRegionHost() const; - std::string getSLURL() const; + BOOL inPrelude(); + std::string getSLURL() const; //Return uri for current region + void buildLocationString(std::string& str); //Build a description string for current location - void updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y); // call once per frame to update position, angles radians - void updateLookAt(const S32 mouse_x, const S32 mouse_y); + // + struct SHLureRequest + { + SHLureRequest(const std::string& avatar_name, const LLVector3d& pos_global, const int x, const int y, const int z) : + mAvatarName(avatar_name), mPosGlobal(pos_global) + { mPosLocal[0] = x; mPosLocal[1] = y; mPosLocal[2] = z;} + const std::string mAvatarName; + const LLVector3d mPosGlobal; + int mPosLocal[3]; + }; + SHLureRequest *mPendingLure; + void showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity); + void onFoundLureDestination(LLSimInfo *siminfo = NULL); + static LLVector3 exlStartMeasurePoint; + static LLVector3 exlEndMeasurePoint; + // + +private: + LLViewerRegion *mRegionp; - void updateCamera(); // call once per frame to update camera location/orientation - void resetCamera(); // slam camera into its default position - void setupSitCamera(); - void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; } - - void changeCameraToDefault(); - void changeCameraToMouselook(BOOL animate = TRUE); - void changeCameraToThirdPerson(BOOL animate = TRUE); - void changeCameraToCustomizeAvatar(BOOL avatar_animate = TRUE, BOOL camera_animate = TRUE); // trigger transition animation - // Ventrella - void changeCameraToFollow(BOOL animate = TRUE); - //end Ventrella - - void setFocusGlobal(const LLPickInfo& pick); - void setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null); - void setFocusOnAvatar(BOOL focus, BOOL animate); - void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id); - void setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos = LLVector3::zero, const LLVector3 &camera_focus = LLVector3::zero); - void clearFocusObject(); - void setFocusObject(LLViewerObject* object); - void setObjectTracking(BOOL track) { mTrackFocusObject = track; } -// void setLookingAtAvatar(BOOL looking); + //-------------------------------------------------------------------- + // History + //-------------------------------------------------------------------- +public: + S32 getRegionsVisited() const; + F64 getDistanceTraveled() const; + void setDistanceTraveled(F64 dist) { mDistanceTraveled = dist; } + + const LLVector3d &getLastPositionGlobal() const { return mLastPositionGlobal; } + void setLastPositionGlobal(const LLVector3d &pos) { mLastPositionGlobal = pos; } +private: + std::set mRegionsVisited; // Stat - what distinct regions has the avatar been to? + F64 mDistanceTraveled; // Stat - how far has the avatar moved? + LLVector3d mLastPositionGlobal; // Used to calculate travel distance + +/** Position + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** ACTIONS + **/ + + //-------------------------------------------------------------------- + // Fidget + //-------------------------------------------------------------------- + // Trigger random fidget animations +public: + void fidget(); + static void stopFidget(); +private: + LLFrameTimer mFidgetTimer; + LLFrameTimer mFocusObjectFadeTimer; + LLFrameTimer mMoveTimer; + F32 mNextFidgetTime; + S32 mCurrentFidget; + //-------------------------------------------------------------------- + // Fly + //-------------------------------------------------------------------- +public: + BOOL getFlying() const; + void setFlying(BOOL fly); + static void toggleFlying(); + static bool enableFlying(); + BOOL canFly(); // Does this parcel allow you to fly? + + //-------------------------------------------------------------------- + // Chat + //-------------------------------------------------------------------- +public: void heardChat(const LLUUID& id); - void lookAtLastChat(); - void lookAtObject(LLUUID avatar_id, ECameraPosition camera_pos); - F32 getTypingTime() { return mTypingTimer.getElapsedTimeF32(); } + F32 getTypingTime() { return mTypingTimer.getElapsedTimeF32(); } + LLUUID getLastChatter() const { return mLastChatterID; } + F32 getNearChatRadius() { return mNearChatRadius; } +protected: + void ageChat(); // Helper function to prematurely age chat when agent is moving +private: + LLFrameTimer mChatTimer; + LLUUID mLastChatterID; + F32 mNearChatRadius; + + //-------------------------------------------------------------------- + // Typing + //-------------------------------------------------------------------- +public: + void startTyping(); + void stopTyping(); +public: + // When the agent hasn't typed anything for this duration, it leaves the + // typing state (for both chat and IM). + static const F32 TYPING_TIMEOUT_SECS; +private: + LLFrameTimer mTypingTimer; + //-------------------------------------------------------------------- + // AFK + //-------------------------------------------------------------------- +public: void setAFK(); void clearAFK(); BOOL getAFK() const; + + //-------------------------------------------------------------------- + // Run + //-------------------------------------------------------------------- +public: + enum EDoubleTapRunMode + { + DOUBLETAP_NONE, + DOUBLETAP_FORWARD, + DOUBLETAP_BACKWARD, + DOUBLETAP_SLIDELEFT, + DOUBLETAP_SLIDERIGHT + }; - void setAlwaysRun() { mbAlwaysRun = true; } - void clearAlwaysRun() { mbAlwaysRun = false; } + void setAlwaysRun() { mbAlwaysRun = true; } + void clearAlwaysRun() { mbAlwaysRun = false; } + void setRunning() { mbRunning = true; } + void clearRunning() { mbRunning = false; } + void sendWalkRun(bool running); + bool getAlwaysRun() const { return mbAlwaysRun; } + bool getRunning() const { return mbRunning; } +public: + LLFrameTimer mDoubleTapRunTimer; + EDoubleTapRunMode mDoubleTapRunMode; +private: + bool mbAlwaysRun; // Should the avatar run by default rather than walk? + bool mbRunning; // Is the avatar trying to run right now? + bool mbTeleportKeepsLookAt; // Try to keep look-at after teleport is complete - void setRunning() { mbRunning = true; } - void clearRunning() { mbRunning = false; } + //-------------------------------------------------------------------- + // Sit and stand + //-------------------------------------------------------------------- +public: + void standUp(); + /// @brief ground-sit at agent's current position + void sitDown(); + //-------------------------------------------------------------------- + // Busy + //-------------------------------------------------------------------- +public: void setBusy(); void clearBusy(); BOOL getBusy() const; - - void setAdminOverride(BOOL b); - void setGodLevel(U8 god_level); - void setFirstLogin(BOOL b) { mFirstLogin = b; } - void setGenderChosen(BOOL b) { mGenderChosen = b; } - - // update internal datastructures and update the server with the - // new contribution level. Returns true if the group id was found - // and contribution could be set. - BOOL setGroupContribution(const LLUUID& group_id, S32 contribution); - BOOL setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile); - void setHideGroupTitle(BOOL hide) { mHideGroupTitle = hide; } - - // - // ACCESSORS - // - // TODO: Put all read functions here, make them const - - const LLUUID& getID() const { return gAgentID; } - const LLUUID& getSessionID() const { return gAgentSessionID; } +private: + BOOL mIsBusy; - const LLUUID& getSecureSessionID() const { return mSecureSessionID; } - // Note: NEVER send this value in the clear or over any weakly - // encrypted channel (such as simple XOR masking). If you are unsure - // ask Aaron or MarkL. - - BOOL isGodlike() const; - U8 getGodLevel() const; - // note: this is a prime candidate for pulling out into a Maturity class - // rather than just expose the preference setting, we're going to actually - // expose what the client code cares about -- what the user should see - // based on a combination of the is* and prefers* flags, combined with God bit. - bool wantsPGOnly() const; - bool canAccessMature() const; - bool canAccessAdult() const; - bool canAccessMaturityInRegion( U64 region_handle ) const; - bool canAccessMaturityAtGlobal( LLVector3d pos_global ) const; - bool prefersPG() const; - bool prefersMature() const; - bool prefersAdult() const; - bool isTeen() const; - bool isMature() const; - bool isAdult() const; - void setTeen(bool teen); - void setMaturity(char text); - static int convertTextToMaturity(char text); - bool sendMaturityPreferenceToServer(int preferredMaturity); + //-------------------------------------------------------------------- + // Grab + //-------------------------------------------------------------------- +public: + BOOL leftButtonGrabbed() const; + BOOL rotateGrabbed() const; + BOOL forwardGrabbed() const; + BOOL backwardGrabbed() const; + BOOL upGrabbed() const; + BOOL downGrabbed() const; + + //-------------------------------------------------------------------- + // Controls + //-------------------------------------------------------------------- +public: + U32 getControlFlags(); + void setControlFlags(U32 mask); // performs bitwise mControlFlags |= mask + void clearControlFlags(U32 mask); // performs bitwise mControlFlags &= ~mask + BOOL controlFlagsDirty() const; + void enableControlFlagReset(); + void resetControlFlags(); + BOOL anyControlGrabbed() const; // True iff a script has taken over a control + BOOL isControlGrabbed(S32 control_index) const; + // Send message to simulator to force grabbed controls to be + // released, in case of a poorly written script. + void forceReleaseControls(); + void setFlagsDirty() { mbFlagsDirty = TRUE; } + +private: + S32 mControlsTakenCount[TOTAL_CONTROLS]; + S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS]; + U32 mControlFlags; // Replacement for the mFooKey's + BOOL mbFlagsDirty; + BOOL mbFlagsNeedReset; // ! HACK ! For preventing incorrect flags sent when crossing region boundaries + + //-------------------------------------------------------------------- + // Animations + //-------------------------------------------------------------------- +public: + void stopCurrentAnimations(); + void requestStopMotion(LLMotion* motion); + void onAnimStop(const LLUUID& id); + void sendAnimationRequests(LLDynamicArray &anim_ids, EAnimRequest request); + void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); + void endAnimationUpdateUI(); + void unpauseAnimation() { mPauseRequest = NULL; } + BOOL getCustomAnim() const { return mCustomAnim; } + void setCustomAnim(BOOL anim) { mCustomAnim = anim; } + BOOL mCustomAnim; // Current animation is ANIM_AGENT_CUSTOMIZE ? + LLPointer mPauseRequest; + BOOL mViewsPushed; // Keep track of whether or not we have pushed views - const LLAgentAccess& getAgentAccess(); - - // This function can go away after the AO transition (see llstartup.cpp) - void setAOTransition(); - - BOOL isGroupTitleHidden() const { return mHideGroupTitle; } - BOOL isGroupMember() const { return !mGroupID.isNull(); } // This is only used for building titles! - const LLUUID &getGroupID() const { return mGroupID; } - ECameraMode getCameraMode() const { return mCameraMode; } - BOOL getFocusOnAvatar() const { return mFocusOnAvatar; } - LLPointer& getFocusObject() { return mFocusObject; } - F32 getFocusObjectDist() const { return mFocusObjectDist; } - BOOL inPrelude(); - BOOL canManageEstate() const; - BOOL getAdminOverride() const; +/** Animation + ** ** + *******************************************************************************/ - LLUUID getLastChatter() const { return mLastChatterID; } - bool getAlwaysRun() const { return mbAlwaysRun; } - bool getRunning() const { return mbRunning; } +/******************************************************************************** + ** ** + ** MOVEMENT + **/ - const LLUUID& getInventoryRootID() const { return mInventoryRootID; } + //-------------------------------------------------------------------- + // Movement from user input + //-------------------------------------------------------------------- + // All set the appropriate animation flags. + // All turn off autopilot and make sure the camera is behind the avatar. + // Direction is either positive, zero, or negative +public: + void moveAt(S32 direction, bool reset_view = true); + void moveAtNudge(S32 direction); + void moveLeft(S32 direction); + void moveLeftNudge(S32 direction); + void moveUp(S32 direction); + void moveYaw(F32 mag, bool reset_view = true); + void movePitch(F32 mag); - void buildFullname(std::string &name) const; - void buildFullnameAndTitle(std::string &name) const; - - // Check against all groups in the entire agent group list. - BOOL isInGroup(const LLUUID& group_id) const; - BOOL hasPowerInGroup(const LLUUID& group_id, U64 power) const; - // Check for power in just the active group. - BOOL hasPowerInActiveGroup(const U64 power) const; - U64 getPowerInGroup(const LLUUID& group_id) const; - - // Get group information by group_id. if not in group, data is - // left unchanged and method returns FALSE. otherwise, values are - // copied and returns TRUE. - BOOL getGroupData(const LLUUID& group_id, LLGroupData& data) const; - // Get just the agent's contribution to the given group. - S32 getGroupContribution(const LLUUID& group_id) const; - - // return TRUE if the database reported this login as the first - // for this particular user. - BOOL isFirstLogin() const { return mFirstLogin; } - - // On the very first login, gender isn't chosen until the user clicks - // in a dialog. We don't render the avatar until they choose. - BOOL isGenderChosen() const { return mGenderChosen; } - - // utility to build a location string - void buildLocationString(std::string& str); - - LLQuaternion getHeadRotation(); - LLVOAvatar *getAvatarObject() const { return mAvatarObject; } - - BOOL needsRenderAvatar(); // TRUE when camera mode is such that your own avatar should draw - // Not const because timers can't be accessed in const-fashion. - BOOL needsRenderHead(); - BOOL cameraThirdPerson() const { return (mCameraMode == CAMERA_MODE_THIRD_PERSON && mLastCameraMode == CAMERA_MODE_THIRD_PERSON); } - BOOL cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK); } - BOOL cameraCustomizeAvatar() const { return (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR /*&& !mCameraAnimating*/); } - BOOL cameraFollow() const { return (mCameraMode == CAMERA_MODE_FOLLOW && mLastCameraMode == CAMERA_MODE_FOLLOW); } - - LLVector3 getPosAgentFromGlobal(const LLVector3d &pos_global) const; - LLVector3d getPosGlobalFromAgent(const LLVector3 &pos_agent) const; - - // Get the data members - const LLVector3& getAtAxis() const { return mFrameAgent.getAtAxis(); } // direction avatar is looking, not camera - const LLVector3& getUpAxis() const { return mFrameAgent.getUpAxis(); } // direction avatar is looking, not camera - const LLVector3& getLeftAxis() const { return mFrameAgent.getLeftAxis(); } // direction avatar is looking, not camera - - LLCoordFrame getFrameAgent() const { return mFrameAgent; } - LLVector3 getVelocity() const; - F32 getVelocityZ() const { return getVelocity().mV[VZ]; } // a hack - - const LLVector3d &getPositionGlobal() const; - const LLVector3 &getPositionAgent(); - S32 getRegionsVisited() const; - F64 getDistanceTraveled() const; - - const LLVector3d &getFocusGlobal() const { return mFocusGlobal; } - const LLVector3d &getFocusTargetGlobal() const { return mFocusTargetGlobal; } - - BOOL getJump() const { return mbJump; } - BOOL getAutoPilot() const { return mAutoPilot; } - LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; } - - LLQuaternion getQuat() const; // returns the quat that represents the rotation - // of the agent in the absolute frame -// BOOL getLookingAtAvatar() const; - - void getName(std::string& name); - - const LLColor4 &getEffectColor(); - void setEffectColor(const LLColor4 &color); - - // - // UTILITIES - // - - // Set the physics data - void slamLookAt(const LLVector3 &look_at); - - void setPositionAgent(const LLVector3 ¢er); - - void resetAxes(); - void resetAxes(const LLVector3 &look_at); // makes reasonable left and up - - // Move the avatar's frame + //-------------------------------------------------------------------- + // Move the avatar's frame + //-------------------------------------------------------------------- +public: void rotate(F32 angle, const LLVector3 &axis); void rotate(F32 angle, F32 x, F32 y, F32 z); void rotate(const LLMatrix3 &matrix); @@ -399,213 +499,47 @@ public: LLVector3 getReferenceUpVector(); F32 clampPitchToLimits(F32 angle); - void setThirdPersonHeadOffset(LLVector3 offset) { mThirdPersonHeadOffset = offset; } - // Flight management - BOOL getFlying() const { return mControlFlags & AGENT_CONTROL_FLY; } - void setFlying(BOOL fly); - void toggleFlying(); - - static BOOL getPhantom(); - static void setPhantom(BOOL phantom); - static void togglePhantom(); - - static BOOL isTPosed() { return mForceTPose; } - static void setTPosed(BOOL TPose) { mForceTPose = TPose; } - static void toggleTPosed(); - - // Does this parcel allow you to fly? - BOOL canFly(); - - // Animation functions - void stopCurrentAnimations(); - void requestStopMotion( LLMotion* motion ); - void onAnimStop(const LLUUID& id); - - void sendAnimationRequests(LLDynamicArray &anim_ids, EAnimRequest request); - void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); - - LLVector3 calcFocusOffset(LLViewerObject *object, LLVector3 pos_agent, S32 x, S32 y); - BOOL calcCameraMinDistance(F32 &obj_min_distance); - - void startCameraAnimation(); - void stopCameraAnimation(); - - void cameraZoomIn(const F32 factor); // zoom in by fraction of current distance - void cameraOrbitAround(const F32 radians); // rotate camera CCW radians about build focus point - void cameraOrbitOver(const F32 radians); // rotate camera forward radians over build focus point - void cameraOrbitIn(const F32 meters); // move camera in toward build focus point - - F32 getCameraZoomFraction(); // get camera zoom as fraction of minimum and maximum zoom - void setCameraZoomFraction(F32 fraction); // set camera zoom as fraction of minimum and maximum zoom - - void cameraPanIn(const F32 meters); - void cameraPanLeft(const F32 meters); - void cameraPanUp(const F32 meters); - - void updateLastCamera(); - void updateFocusOffset(); - void validateFocusObject(); - - void setUsingFollowCam( bool using_follow_cam); - - F32 calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ); - - // marks current location as start, sends information to servers - void setStartPosition(U32 location_id); - - // Movement from user input. All set the appropriate animation flags. - // All turn off autopilot and make sure the camera is behind the avatar. - // direction is either positive, zero, or negative - void moveAt(S32 direction, bool reset_view = true); - void moveAtNudge(S32 direction); - void moveLeft(S32 direction); - void moveLeftNudge(S32 direction); - void moveUp(S32 direction); - void moveYaw(F32 mag, bool reset_view = true); - void movePitch(S32 direction); - - void setOrbitLeftKey(F32 mag) { mOrbitLeftKey = mag; } - void setOrbitRightKey(F32 mag) { mOrbitRightKey = mag; } - void setOrbitUpKey(F32 mag) { mOrbitUpKey = mag; } - void setOrbitDownKey(F32 mag) { mOrbitDownKey = mag; } - void setOrbitInKey(F32 mag) { mOrbitInKey = mag; } - void setOrbitOutKey(F32 mag) { mOrbitOutKey = mag; } - - void setPanLeftKey(F32 mag) { mPanLeftKey = mag; } - void setPanRightKey(F32 mag) { mPanRightKey = mag; } - void setPanUpKey(F32 mag) { mPanUpKey = mag; } - void setPanDownKey(F32 mag) { mPanDownKey = mag; } - void setPanInKey(F32 mag) { mPanInKey = mag; } - void setPanOutKey(F32 mag) { mPanOutKey = mag; } - - U32 getControlFlags(); - void setControlFlags(U32 mask); // performs bitwise mControlFlags |= mask - void clearControlFlags(U32 mask); // performs bitwise mControlFlags &= ~mask - BOOL controlFlagsDirty() const; - void enableControlFlagReset(); - void resetControlFlags(); - - void propagate(const F32 dt); // BUG: should roll into updateAgentPosition - - void startAutoPilotGlobal(const LLVector3d &pos_global, const std::string& behavior_name = std::string(), const LLQuaternion *target_rotation = NULL, - void (*finish_callback)(BOOL, void *) = NULL, void *callback_data = NULL, F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f); - + //-------------------------------------------------------------------- + // Autopilot + //-------------------------------------------------------------------- +public: + BOOL getAutoPilot() const { return mAutoPilot; } + LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; } + void startAutoPilotGlobal(const LLVector3d &pos_global, + const std::string& behavior_name = std::string(), + const LLQuaternion *target_rotation = NULL, + void (*finish_callback)(BOOL, void *) = NULL, void *callback_data = NULL, + F32 stop_distance = 0.f, F32 rotation_threshold = 0.03f); void startFollowPilot(const LLUUID &leader_id); void stopAutoPilot(BOOL user_cancel = FALSE); void setAutoPilotGlobal(const LLVector3d &pos_global); void autoPilot(F32 *delta_yaw); // autopilot walking action, angles in radians void renderAutoPilotTarget(); - - // - // teportation methods - // - - // go to a named location home - void teleportRequest( - const U64& region_handle, - const LLVector3& pos_local, - bool look_at_from_camera = false); - - // teleport to a landmark - void teleportViaLandmark(const LLUUID& landmark_id); - - // go home - void teleportHome() { teleportViaLandmark(LLUUID::null); } - - // to an invited location - void teleportViaLure(const LLUUID& lure_id, BOOL godlike); - - // to a global location - this will probably need to be - // deprecated. - void teleportViaLocation(const LLVector3d& pos_global); - - // to a global location, preserving camera rotation - void teleportViaLocationLookAt(const LLVector3d& pos_global); +private: + BOOL mAutoPilot; + BOOL mAutoPilotFlyOnStop; + LLVector3d mAutoPilotTargetGlobal; + F32 mAutoPilotStopDistance; + BOOL mAutoPilotUseRotation; + LLVector3 mAutoPilotTargetFacing; + F32 mAutoPilotTargetDist; + S32 mAutoPilotNoProgressFrameCount; + F32 mAutoPilotRotationThreshold; + std::string mAutoPilotBehaviorName; + void (*mAutoPilotFinishedCallback)(BOOL, void *); + void* mAutoPilotCallbackData; + LLUUID mLeaderID; - // cancel the teleport, may or may not be allowed by server - void teleportCancel(); +/** Movement + ** ** + *******************************************************************************/ - void setTargetVelocity(const LLVector3 &vel); - const LLVector3 &getTargetVelocity() const; - - const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; } - - // Setting the ability for this avatar to proxy for another avatar. - //static void processAddModifyAbility(LLMessageSystem* msg, void**); - //static void processGrantedProxies(LLMessageSystem* msg, void**); - //static void processRemoveModifyAbility(LLMessageSystem* msg, void**); - //BOOL isProxyFor(const LLUUID& agent_id);// *FIX should be const - - static void processAgentDataUpdate(LLMessageSystem *msg, void **); - static void processAgentGroupDataUpdate(LLMessageSystem *msg, void **); - static void processAgentDropGroup(LLMessageSystem *msg, void **); - static void processScriptControlChange(LLMessageSystem *msg, void **); - static void processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data); - //static void processControlTake(LLMessageSystem *msg, void **); - //static void processControlRelease(LLMessageSystem *msg, void **); - - // This method checks to see if this agent can modify an object - // based on the permissions and the agent's proxy status. - BOOL isGrantedProxy(const LLPermissions& perm); - - BOOL allowOperation(PermissionBit op, - const LLPermissions& perm, - U64 group_proxy_power = 0, - U8 god_minimum = GOD_MAINTENANCE); - - friend std::ostream& operator<<(std::ostream &s, const LLAgent &sphere); - - void initOriginGlobal(const LLVector3d &origin_global); // Only to be used in ONE place! - djs 08/07/02 - - BOOL leftButtonGrabbed() const { return ( (!cameraMouselook() && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) - ||(cameraMouselook() && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0) - ||(!cameraMouselook() && mControlsTakenPassedOnCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) - ||(cameraMouselook() && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)); } - BOOL rotateGrabbed() const { return ( (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0) - ||(mControlsTakenCount[CONTROL_YAW_NEG_INDEX] > 0)); } - BOOL forwardGrabbed() const { return ( (mControlsTakenCount[CONTROL_AT_POS_INDEX] > 0)); } - BOOL backwardGrabbed() const { return ( (mControlsTakenCount[CONTROL_AT_NEG_INDEX] > 0)); } - BOOL upGrabbed() const { return ( (mControlsTakenCount[CONTROL_UP_POS_INDEX] > 0)); } - BOOL downGrabbed() const { return ( (mControlsTakenCount[CONTROL_UP_NEG_INDEX] > 0)); } - - // True iff a script has taken over a control. - BOOL anyControlGrabbed() const; - - BOOL isControlGrabbed(S32 control_index) const; - - // Send message to simulator to force grabbed controls to be - // released, in case of a poorly written script. - void forceReleaseControls(); - - BOOL sitCameraEnabled() { return mSitCameraEnabled; } - - F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); } - - // look at behavior - BOOL setLookAt(ELookAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero); - ELookAtType getLookAtType(); - - // point at behavior - BOOL setPointAt(EPointAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero); - EPointAtType getPointAtType(); - - void setHomePosRegion( const U64& region_handle, const LLVector3& pos_region ); - BOOL getHomePosGlobal( LLVector3d* pos_global ); - void setCameraAnimating( BOOL b ) { mCameraAnimating = b; } - BOOL getCameraAnimating( ) { return mCameraAnimating; } - void setAnimationDuration( F32 seconds ) { mAnimationDuration = seconds; } - - F32 getNearChatRadius() { return mNearChatRadius; } - - enum EDoubleTapRunMode - { - DOUBLETAP_NONE, - DOUBLETAP_FORWARD, - DOUBLETAP_BACKWARD, - DOUBLETAP_SLIDELEFT, - DOUBLETAP_SLIDERIGHT - }; +/******************************************************************************** + ** ** + ** TELEPORT + **/ +public: enum ETeleportState { TELEPORT_NONE = 0, // No teleport in progress @@ -614,34 +548,298 @@ public: TELEPORT_MOVING = 3, // Viewer has received destination location from source simulator TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches" - TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen + TELEPORT_LOCAL = 6 // Teleporting in-sim without showing the progress screen }; - ETeleportState getTeleportState() const { return mTeleportState; } - void setTeleportState( ETeleportState state ); - const std::string& getTeleportMessage() const { return mTeleportMessage; } - void setTeleportMessage(const std::string& message) - { - mTeleportMessage = message; - } +public: + static void parseTeleportMessages(const std::string& xml_filename); + const std::string& getTeleportSourceSLURL() const { return mTeleportSourceSLURL; } +public: + // ! TODO ! Define ERROR and PROGRESS enums here instead of exposing the mappings. + static std::map sTeleportErrorMessages; + static std::map sTeleportProgressMessages; +public: + std::string mTeleportSourceSLURL; // SLURL where last TP began. + //-------------------------------------------------------------------- + // Teleport Actions + //-------------------------------------------------------------------- +public: + void teleportRequest(const U64& region_handle, + const LLVector3& pos_local, // Go to a named location home + bool look_at_from_camera = false); + void teleportViaLandmark(const LLUUID& landmark_id); // Teleport to a landmark + void teleportHome() { teleportViaLandmark(LLUUID::null); } // Go home + void teleportViaLure(const LLUUID& lure_id, BOOL godlike); // To an invited location + void teleportViaLocation(const LLVector3d& pos_global); // To a global location - this will probably need to be deprecated + void teleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation + void teleportCancel(); // May or may not be allowed by server + bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; } // Whether look-at reset after teleport +protected: + bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed - // trigger random fidget animations - void fidget(); + //-------------------------------------------------------------------- + // Teleport State + //-------------------------------------------------------------------- +public: + ETeleportState getTeleportState() const { return mTeleportState; } + void setTeleportState(ETeleportState state); +private: + ETeleportState mTeleportState; + //-------------------------------------------------------------------- + // Teleport Message + //-------------------------------------------------------------------- +public: + const std::string& getTeleportMessage() const { return mTeleportMessage; } + void setTeleportMessage(const std::string& message) { mTeleportMessage = message; } +private: + std::string mTeleportMessage; + +/** Teleport + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** ACCESS + **/ + +public: + // Checks if agent can modify an object based on the permissions and the agent's proxy status. + BOOL isGrantedProxy(const LLPermissions& perm); + BOOL allowOperation(PermissionBit op, + const LLPermissions& perm, + U64 group_proxy_power = 0, + U8 god_minimum = GOD_MAINTENANCE); + const LLAgentAccess& getAgentAccess(); + BOOL canManageEstate() const; + BOOL getAdminOverride() const; + // ! BACKWARDS COMPATIBILITY ! This function can go away after the AO transition (see llstartup.cpp). + void setAOTransition(); +private: + LLAgentAccess *mAgentAccess; + + //-------------------------------------------------------------------- + // God + //-------------------------------------------------------------------- +public: + bool isGodlike() const; + U8 getGodLevel() const; + void setAdminOverride(BOOL b); + void setGodLevel(U8 god_level); void requestEnterGodMode(); void requestLeaveGodMode(); + //-------------------------------------------------------------------- + // Maturity + //-------------------------------------------------------------------- +public: + // Note: this is a prime candidate for pulling out into a Maturity class. + // Rather than just expose the preference setting, we're going to actually + // expose what the client code cares about -- what the user should see + // based on a combination of the is* and prefers* flags, combined with god bit. + bool wantsPGOnly() const; + bool canAccessMature() const; + bool canAccessAdult() const; + bool canAccessMaturityInRegion( U64 region_handle ) const; + bool canAccessMaturityAtGlobal( LLVector3d pos_global ) const; + bool prefersPG() const; + bool prefersMature() const; + bool prefersAdult() const; + bool isTeen() const; + bool isMature() const; + bool isAdult() const; + void setTeen(bool teen); + void setMaturity(char text); + static int convertTextToMaturity(char text); + bool sendMaturityPreferenceToServer(int preferredMaturity); // ! "U8" instead of "int"? + + + +/** Access + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** RENDERING + **/ + +public: + LLQuaternion getHeadRotation(); + BOOL needsRenderAvatar(); // TRUE when camera mode is such that your own avatar should draw + BOOL needsRenderHead(); + void setShowAvatar(BOOL show) { mShowAvatar = show; } + BOOL getShowAvatar() const { return mShowAvatar; } + +private: + BOOL mShowAvatar; // Should we render the avatar? + U32 mAppearanceSerialNum; + + //-------------------------------------------------------------------- + // Rendering state bitmap helpers + //-------------------------------------------------------------------- +public: + void setRenderState(U8 newstate); + void clearRenderState(U8 clearstate); + U8 getRenderState(); +private: + U8 mRenderState; // Current behavior state of agent + + //-------------------------------------------------------------------- + // HUD + //-------------------------------------------------------------------- +public: + const LLColor4 &getEffectColor(); + void setEffectColor(const LLColor4 &color); +private: + LLColor4 mEffectColor; + +/** Rendering + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** GROUPS + **/ + +public: + const LLUUID &getGroupID() const { return mGroupID; } + // Get group information by group_id, or FALSE if not in group. + BOOL getGroupData(const LLUUID& group_id, LLGroupData& data) const; + // Get just the agent's contribution to the given group. + S32 getGroupContribution(const LLUUID& group_id) const; + // Update internal datastructures and update the server. + BOOL setGroupContribution(const LLUUID& group_id, S32 contribution); + BOOL setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile); + const std::string &getGroupName() const { return mGroupName; } +private: + std::string mGroupName; + LLUUID mGroupID; + + //-------------------------------------------------------------------- + // Group Membership + //-------------------------------------------------------------------- +public: + // Checks against all groups in the entire agent group list. + BOOL isInGroup(const LLUUID& group_id) const; +protected: + // Only used for building titles. + BOOL isGroupMember() const { return !mGroupID.isNull(); } +public: + LLDynamicArray mGroups; + + //-------------------------------------------------------------------- + // Group Title + //-------------------------------------------------------------------- +public: + void setHideGroupTitle(BOOL hide) { mHideGroupTitle = hide; } + BOOL isGroupTitleHidden() const { return mHideGroupTitle; } + const std::string& getGroupTitle() const { return mGroupTitle; } +private: + std::string mGroupTitle; // Honorific, like "Sir" + BOOL mHideGroupTitle; + + //-------------------------------------------------------------------- + // Group Powers + //-------------------------------------------------------------------- +public: + BOOL hasPowerInGroup(const LLUUID& group_id, U64 power) const; + BOOL hasPowerInActiveGroup(const U64 power) const; + U64 getPowerInGroup(const LLUUID& group_id) const; + U64 mGroupPowers; + + //-------------------------------------------------------------------- + // Friends + //-------------------------------------------------------------------- +public: + void observeFriends(); + void friendsChanged(); +private: + LLFriendObserver* mFriendObserver; + std::set mProxyForAgents; + +/** Groups + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** MESSAGING + **/ + + //-------------------------------------------------------------------- + // Send + //-------------------------------------------------------------------- +public: + void sendMessage(); // Send message to this agent's region. + void sendReliableMessage(); void sendAgentSetAppearance(); - void sendAgentDataUpdateRequest(); + + //-------------------------------------------------------------------- + // Receive + //-------------------------------------------------------------------- +public: + static void processAgentDataUpdate(LLMessageSystem *msg, void **); + static void processAgentGroupDataUpdate(LLMessageSystem *msg, void **); + static void processAgentDropGroup(LLMessageSystem *msg, void **); + static void processScriptControlChange(LLMessageSystem *msg, void **); + static void processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data); + +/** Messaging + ** ** + *******************************************************************************/ - // Ventrella - LLFollowCam mFollowCam; - // end Ventrella +/******************************************************************************** + ** ** + ** DEBUGGING + **/ + +public: + static void clearVisualParams(void *); + friend std::ostream& operator<<(std::ostream &s, const LLAgent &sphere); +/** Debugging + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** Phantom mode! + **/ + + public: + static BOOL getPhantom(); + static void setPhantom(BOOL phantom); + static void togglePhantom(); +private: + static BOOL exlPhantom; +/** PHANTOM + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** Deperciated stuff. Move when ready. + **/ +public: + const LLUUID& getInventoryRootID() const { return mInventoryRootID; } + void setInventoryRootID(const LLUUID &id) { mInventoryRootID = id; } + //What's this t-posed stuff from? + static BOOL isTPosed() { return mForceTPose; } + static void setTPosed(BOOL TPose) { mForceTPose = TPose; } + static void toggleTPosed(); + +private: + LLUUID mInventoryRootID; + static BOOL mForceTPose; + //-------------------------------------------------------------------- // Wearables //-------------------------------------------------------------------- +public: void setWearable( LLInventoryItem* new_item, LLWearable* wearable ); static bool onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable ); void setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable ); @@ -707,13 +905,7 @@ public: BOOL areWearablesLoaded() { return mWearablesLoaded; } - void sendWalkRun(bool running); - - void observeFriends(); - void friendsChanged(); - // statics - static void stopFidget(); static void processAgentInitialWearablesUpdate(LLMessageSystem* mesgsys, void** user_data); static void userRemoveWearable( void* userdata ); // userdata is EWearableType static void userRemoveAllClothes( void* userdata ); // userdata is NULL @@ -729,20 +921,7 @@ public: static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); - //debug methods - static void clearVisualParams(void *); - - // whether look-at reset after teleport - bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; } - protected: - // stuff to do for any sort of teleport. Returns true if the - // teleport can proceed. - bool teleportCore(bool is_local = false); - - - // helper function to prematurely age chat when agent is moving - void ageChat(); // internal wearable functions void sendAgentWearablesRequest(); @@ -752,210 +931,8 @@ protected: void addWearableToAgentInventory(LLPointer cb, LLWearable* wearable, const LLUUID& category_id = LLUUID::null, BOOL notify = TRUE); -public: - // TODO: Make these private! - LLUUID mSecureSessionID; // secure token for this login session - - F32 mDrawDistance; - - U64 mGroupPowers; - BOOL mHideGroupTitle; - std::string mGroupTitle; // honorific, like "Sir" - std::string mGroupName; - LLUUID mGroupID; - //LLUUID mGroupInsigniaID; - LLUUID mInventoryRootID; - LLUUID mMapID; - F64 mMapOriginX; // Global x coord of mMapID's bottom left corner. - F64 mMapOriginY; // Global y coord of mMapID's bottom left corner. - S32 mMapWidth; // Width of map in meters - S32 mMapHeight; // Height of map in meters - std::string mMOTD; // message of the day - - LLPointer mLookAt; - LLPointer mPointAt; - - LLDynamicArray mGroups; - - F32 mHUDTargetZoom; // target zoom level for HUD objects (used when editing) - F32 mHUDCurZoom; // current animated zoom level for HUD objects - - BOOL mInitialized; - - // - static BOOL lure_show; - static std::string lure_name; - static LLVector3d lure_posglobal; - static U16 lure_global_x; - static U16 lure_global_y; - static int lure_x; - static int lure_y; - static int lure_z; - static std::string lure_maturity; - - static LLVector3 exlStartMeasurePoint; - static LLVector3 exlEndMeasurePoint; - // - - S32 mNumPendingQueries; - S32* mActiveCacheQueries; - - BOOL mForceMouselook; - - static void parseTeleportMessages(const std::string& xml_filename); - //we should really define ERROR and PROGRESS enums here - //but I don't really feel like doing that, so I am just going - //to expose the mappings....yup - static std::map sTeleportErrorMessages; - static std::map sTeleportProgressMessages; - - LLFrameTimer mDoubleTapRunTimer; - EDoubleTapRunMode mDoubleTapRunMode; - - // - static void showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity); - static void onFoundLureDestination(); - // private: - static BOOL exlPhantom; - static BOOL mForceTPose; - bool mbTeleportKeepsLookAt; // try to keep look-at after teleport is complete - bool mbAlwaysRun; // should the avatar run by default rather than walk - bool mbRunning; // is the avatar trying to run right now - - LLAgentAccess mAgentAccess; - - ETeleportState mTeleportState; - std::string mTeleportMessage; - - S32 mControlsTakenCount[TOTAL_CONTROLS]; - S32 mControlsTakenPassedOnCount[TOTAL_CONTROLS]; - - LLViewerRegion *mRegionp; - LLVector3d mAgentOriginGlobal; // Origin of agent coords from global coords - mutable LLVector3d mPositionGlobal; - - std::string mTeleportSourceSLURL; // SLURL where last TP began. - - std::set mRegionsVisited; // stat - what distinct regions has the avatar been to? - F64 mDistanceTraveled; // stat - how far has the avatar moved? - LLVector3d mLastPositionGlobal; // Used to calculate travel distance - - LLPointer mAvatarObject; // NULL until avatar object sent down from simulator - - U8 mRenderState; // Current behavior state of agent - LLFrameTimer mTypingTimer; - - ECameraMode mCameraMode; // target mode after transition animation is done - ECameraMode mLastCameraMode; - BOOL mViewsPushed; // keep track of whether or not we have pushed views. - - BOOL mCustomAnim ; //current animation is ANIM_AGENT_CUSTOMIZE ? - BOOL mShowAvatar; // should we render the avatar? - BOOL mCameraAnimating; // camera is transitioning from one mode to another - LLVector3d mAnimationCameraStartGlobal; // camera start position, global coords - LLVector3d mAnimationFocusStartGlobal; // camera focus point, global coords - LLFrameTimer mAnimationTimer; // seconds that transition animation has been active - F32 mAnimationDuration; // seconds - F32 mCameraFOVZoomFactor; // amount of fov zoom applied to camera when zeroing in on an object - F32 mCameraCurrentFOVZoomFactor; // interpolated fov zoom - F32 mCameraFOVDefault; // default field of view that is basis for FOV zoom effect - LLVector3d mCameraFocusOffset; // offset from focus point in build mode - LLVector3d mCameraFocusOffsetTarget; // target towards which we are lerping the camera's focus offset - LLVector3 mCameraOffsetDefault; // default third-person camera offset - LLVector4 mCameraCollidePlane; // colliding plane for camera - F32 mCurrentCameraDistance; // current camera offset from avatar - F32 mTargetCameraDistance; // target camera offset from avatar - F32 mCameraZoomFraction; // mousewheel driven fraction of zoom - LLVector3 mCameraLag; // third person camera lag - LLVector3 mThirdPersonHeadOffset; // head offset for third person camera position - LLVector3 mCameraPositionAgent; // camera position in agent coordinates - LLVector3 mCameraVirtualPositionAgent; // camera virtual position (target) before performing FOV zoom - BOOL mSitCameraEnabled; // use provided camera information when sitting? - LLVector3 mSitCameraPos; // root relative camera pos when sitting - LLVector3 mSitCameraFocus; // root relative camera target when sitting - LLVector3d mCameraSmoothingLastPositionGlobal; - LLVector3d mCameraSmoothingLastPositionAgent; - BOOL mCameraSmoothingStop; - - LLVector3 mCameraUpVector; // camera's up direction in world coordinates (determines the 'roll' of the view) - - LLPointer mSitCameraReferenceObject; // object to which camera is related when sitting - - BOOL mFocusOnAvatar; - LLVector3d mFocusGlobal; - LLVector3d mFocusTargetGlobal; - LLPointer mFocusObject; - F32 mFocusObjectDist; - LLVector3 mFocusObjectOffset; - F32 mFocusDotRadius; // meters - BOOL mTrackFocusObject; - F32 mUIOffset; - - LLCoordFrame mFrameAgent; // Agent position and view, agent-region coordinates - - BOOL mIsBusy; - - S32 mAtKey; // Either 1, 0, or -1... indicates that movement-key is pressed - S32 mWalkKey; // like AtKey, but causes less forward thrust - S32 mLeftKey; - S32 mUpKey; - F32 mYawKey; - S32 mPitchKey; - - F32 mOrbitLeftKey; - F32 mOrbitRightKey; - F32 mOrbitUpKey; - F32 mOrbitDownKey; - F32 mOrbitInKey; - F32 mOrbitOutKey; - - F32 mPanUpKey; - F32 mPanDownKey; - F32 mPanLeftKey; - F32 mPanRightKey; - F32 mPanInKey; - F32 mPanOutKey; - - U32 mControlFlags; // replacement for the mFooKey's - BOOL mbFlagsDirty; - BOOL mbFlagsNeedReset; // HACK for preventing incorrect flags sent when crossing region boundaries - - BOOL mbJump; - - BOOL mAutoPilot; - BOOL mAutoPilotFlyOnStop; - LLVector3d mAutoPilotTargetGlobal; - F32 mAutoPilotStopDistance; - BOOL mAutoPilotUseRotation; - LLVector3 mAutoPilotTargetFacing; - F32 mAutoPilotTargetDist; - S32 mAutoPilotNoProgressFrameCount; - F32 mAutoPilotRotationThreshold; - std::string mAutoPilotBehaviorName; - void (*mAutoPilotFinishedCallback)(BOOL, void *); - void* mAutoPilotCallbackData; - LLUUID mLeaderID; - - std::set mProxyForAgents; - - LLColor4 mEffectColor; - - BOOL mHaveHomePosition; - U64 mHomeRegionHandle; - LLVector3 mHomePosRegion; - LLFrameTimer mChatTimer; - LLUUID mLastChatterID; - F32 mNearChatRadius; - - LLFrameTimer mFidgetTimer; - LLFrameTimer mFocusObjectFadeTimer; - F32 mNextFidgetTime; - S32 mCurrentFidget; - BOOL mFirstLogin; - BOOL mGenderChosen; - //-------------------------------------------------------------------- // Wearables //-------------------------------------------------------------------- @@ -967,11 +944,8 @@ private: LLWearable* mWearable; }; LLWearableEntry mWearableEntry[ WT_COUNT ]; - U32 mAgentWearablesUpdateSerialNum; BOOL mWearablesLoaded; - S32 mTextureCacheQueryID; - U32 mAppearanceSerialNum; - LLAnimPauseRequest mPauseRequest; + class createStandardWearablesAllDoneCallback : public LLRefCount { @@ -1018,11 +992,40 @@ private: U32 mTodo; LLPointer mCB; }; - - LLFriendObserver* mFriendObserver; + +/** DEPERCIATED + ** ** + *******************************************************************************/ + }; extern LLAgent gAgent; + +inline bool operator==(const LLGroupData &a, const LLGroupData &b) +{ + return (a.mID == b.mID); +} + +class LLAgentQueryManager +{ + friend class LLAgent; + friend class LLAgentWearables; + +public: + LLAgentQueryManager(); + virtual ~LLAgentQueryManager(); + + BOOL hasNoPendingQueries() const { return getNumPendingQueries() == 0; } + S32 getNumPendingQueries() const { return mNumPendingQueries; } +private: + S32 mNumPendingQueries; + S32 mWearablesCacheQueryID; //mTextureCacheQueryID; + U32 mUpdateSerialNum; //mAgentWearablesUpdateSerialNum + S32 mActiveCacheQueries[LLVOAvatarDefines::BAKED_NUM_INDICES]; +}; + +extern LLAgentQueryManager gAgentQueryManager; + extern std::string gAuthString; // diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp new file mode 100644 index 000000000..a53c23897 --- /dev/null +++ b/indra/newview/llagentcamera.cpp @@ -0,0 +1,3071 @@ +/** + * @file llagentcamera.cpp + * @brief LLAgent class implementation + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llagentcamera.h" + +#include "pipeline.h" + +#include "llagent.h" +#include "llanimationstates.h" +#include "llfloatercamera.h" +#include "llfloatergroups.h" +#include "llhudmanager.h" +#include "lljoystickbutton.h" +#include "llselectmgr.h" +#include "llsmoothstep.h" +#include "lltoolmgr.h" +#include "llviewercamera.h" +#include "llviewercontrol.h" +#include "llviewerjoystick.h" +#include "llviewermenu.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" +#include "llvoavatar.h" +#include "llwindow.h" +#include "llworld.h" +#include "llfloatertools.h" //For gFloaterTools +#include "floaterao.h" //For LLFloaterAO +#include "llfloatercustomize.h" //For gFloaterCustomize + +using namespace LLVOAvatarDefines; + +extern LLMenuBarGL* gMenuBarView; + +// 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 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.f;//0.1f; +const F32 MIN_CAMERA_DISTANCE = 0.f;//0.1f; + +const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.f;//0.55f; +const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.f;//0.7f; +const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 0.f;//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.1f; + +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; + +const F32 CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST = 3.5f; + +const F32 GROUND_TO_AIR_CAMERA_TRANSITION_TIME = 0.5f; +const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f; + +const F32 OBJECT_EXTENTS_PADDING = 0.5f; + +// The agent instance. +LLAgentCamera gAgentCamera; + +//----------------------------------------------------------------------------- +// LLAgentCamera() +//----------------------------------------------------------------------------- +LLAgentCamera::LLAgentCamera() : + mInitialized(false), + + mDrawDistance( DEFAULT_FAR_PLANE ), + + mLookAt(NULL), + mPointAt(NULL), + + mHUDTargetZoom(1.f), + mHUDCurZoom(1.f), + + mForceMouselook(FALSE), + + mCameraMode( CAMERA_MODE_THIRD_PERSON ), + mLastCameraMode( CAMERA_MODE_THIRD_PERSON ), + + //mCameraPreset(CAMERA_PRESET_REAR_VIEW), + + mCameraAnimating( FALSE ), + mAnimationCameraStartGlobal(), + mAnimationFocusStartGlobal(), + mAnimationTimer(), + mAnimationDuration(0.33f), + + mCameraFOVZoomFactor(0.f), + mCameraCurrentFOVZoomFactor(0.f), + mCameraFocusOffset(), + mCameraFOVDefault(DEFAULT_FIELD_OF_VIEW), + + mCameraOffsetDefault(), + 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), + + 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) +{ + mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT ); + + clearGeneralKeys(); + clearOrbitKeys(); + clearPanKeys(); +} + +// Requires gSavedSettings to be initialized. +//----------------------------------------------------------------------------- +// init() +//----------------------------------------------------------------------------- +void LLAgentCamera::init() +{ + // *Note: this is where LLViewerCamera::getInstance() used to be constructed. + + mDrawDistance = gSavedSettings.getF32("RenderFarClip"); + + 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->getDisplayAspectRatio() ); // default, overridden in LLViewerWindow::reshape + LLViewerCamera::getInstance()->setViewHeightInPixels(768); // default, overridden in LLViewerWindow::reshape + + mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild")); + + mCameraOffsetDefault = gSavedSettings.getVector3("CameraOffsetDefault");//Legacy + /*mCameraPreset = (ECameraPreset) gSavedSettings.getU32("CameraPreset"); + + mCameraOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("CameraOffsetRearView"); + mCameraOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("CameraOffsetFrontView"); + mCameraOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("CameraOffsetGroupView"); + + mFocusOffsetInitial[CAMERA_PRESET_REAR_VIEW] = gSavedSettings.getControl("FocusOffsetRearView"); + mFocusOffsetInitial[CAMERA_PRESET_FRONT_VIEW] = gSavedSettings.getControl("FocusOffsetFrontView"); + mFocusOffsetInitial[CAMERA_PRESET_GROUP_VIEW] = gSavedSettings.getControl("FocusOffsetGroupView");*/ + + mCameraCollidePlane.clearVec(); + mCurrentCameraDistance = getCameraOffsetInitial().magVec() * gSavedSettings.getF32("CameraOffsetScale"); + mTargetCameraDistance = mCurrentCameraDistance; + mCameraZoomFraction = 1.f; + mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject"); + + mInitialized = true; +} + +//----------------------------------------------------------------------------- +// cleanup() +//----------------------------------------------------------------------------- +void LLAgentCamera::cleanup() +{ + setSitCamera(LLUUID::null); + + if(mLookAt) + { + mLookAt->markDead() ; + mLookAt = NULL; + } + if(mPointAt) + { + mPointAt->markDead() ; + mPointAt = NULL; + } + setFocusObject(NULL); +} + +void LLAgentCamera::setAvatarObject(LLVOAvatar* avatar) +{ + 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); + } +} + +//----------------------------------------------------------------------------- +// LLAgent() +//----------------------------------------------------------------------------- +LLAgentCamera::~LLAgentCamera() +{ + 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 LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) +{ + if (gAgent.getAutoPilot()) + { + gAgent.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(); + } + + if (gMenuHolder != NULL) + { + // Hide all popup menus + gMenuHolder->hideMenus(); + } + } + + static const LLCachedControl freeze_time("FreezeTime",false); + if (change_camera && !freeze_time) + { + 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); + }*/ + gFloaterTools->close(); + + gViewerWindow->showCursor(); + + // Switch back to basic toolset + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + if (reset_camera && !freeze_time) + { + if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson()) + { + // leaving mouse-steer mode + LLVector3 agent_at_axis = gAgent.getAtAxis(); + agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); + agent_at_axis.normalize(); + gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f))); + } + + setFocusOnAvatar(TRUE, ANIMATE); + + mCameraFOVZoomFactor = 0.f; + } + + mHUDTargetZoom = 1.f; +} + +// Allow camera to be moved somewhere other than behind avatar. +//----------------------------------------------------------------------------- +// unlockView() +//----------------------------------------------------------------------------- +void LLAgentCamera::unlockView() +{ + if (getFocusOnAvatar()) + { + if (isAgentAvatarValid()) + { + setFocusGlobal(LLVector3d::zero, gAgent.getAvatarObject()->mID); + } + setFocusOnAvatar(FALSE, FALSE); // no animation + } +} + +//----------------------------------------------------------------------------- +// slamLookAt() +//----------------------------------------------------------------------------- +void LLAgentCamera::slamLookAt(const LLVector3 &look_at) +{ + LLVector3 look_at_norm = look_at; + look_at_norm.mV[VZ] = 0.f; + look_at_norm.normalize(); + gAgent.resetAxes(look_at_norm); +} + +//----------------------------------------------------------------------------- +// calcFocusOffset() +//----------------------------------------------------------------------------- +LLVector3 LLAgentCamera::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 LLAgentCamera::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() || + //mFocusObject->isMesh() || + gSavedSettings.getBOOL("DisableCameraConstraints")) + { + 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() - gAgent.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 LLAgentCamera::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 (gSavedSettings.getBOOL("AscentDisableMinZoomDist")) + { + return mCameraZoomFraction; + } + 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 = 65535.f*4.f;//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 LLAgentCamera::setCameraZoomFraction(F32 fraction) +{ + // 0.f -> camera zoomed all the way out + // 1.f -> camera zoomed all the way in + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + BOOL disable_min = gSavedSettings.getBOOL("AscentDisableMinZoomDist"); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + mHUDTargetZoom = fraction; + } + else if (mFocusOnAvatar && cameraThirdPerson() && !disable_min) + { + 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 (!disable_min) + { + if (mFocusObject.notNull()) + { + if (mFocusObject->isAvatar()) + { + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; + } + } + } + else + { + min_zoom = 0.f; + } + LLVector3d camera_offset_dir = mCameraFocusOffsetTarget; + camera_offset_dir.normalize(); + //mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); + mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 65535.*4., 1.f, min_zoom); + } + startCameraAnimation(); +} + + +//----------------------------------------------------------------------------- +// cameraOrbitAround() +//----------------------------------------------------------------------------- +void LLAgentCamera::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)) + { + gAgent.yaw(radians); + } + else + { + mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f); + + cameraZoomIn(1.f); + } +} + + +//----------------------------------------------------------------------------- +// cameraOrbitOver() +//----------------------------------------------------------------------------- +void LLAgentCamera::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) + { + gAgent.pitch(angle); + } + else + { + LLVector3 camera_offset_unit(mCameraFocusOffsetTarget); + camera_offset_unit.normalize(); + + F32 angle_from_up = acos( camera_offset_unit * gAgent.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 LLAgentCamera::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 = 0.f;//LAND_MIN_ZOOM; + F32 current_distance = (F32)camera_offset_unit.normalize(); + F32 new_distance = current_distance * fraction; + + if (!gSavedSettings.getBOOL("AscentDisableMinZoomDist")) + { + 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*/ INT_MAX - DIST_FUDGE//, + /*LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE )*/; + + if (new_distance > max_distance) + { + // screw cam constraints + //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 LLAgentCamera::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; + + static const LLCachedControl freeze_time("FreezeTime",false); + if (!freeze_time && 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 LLAgentCamera::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 LLAgentCamera::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 LLAgentCamera::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(); +} + +//----------------------------------------------------------------------------- +// updateLookAt() +//----------------------------------------------------------------------------- +void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) +{ + LLVOAvatar *pAvatar = gAgent.getAvatarObject(); // bleh + + static LLVector3 last_at_axis; + + if (!isAgentAvatarValid()) return; + + LLQuaternion av_inv_rot = ~pAvatar->mRoot.getWorldRotation(); + LLVector3 root_at = LLVector3::x_axis * pAvatar->mRoot.getWorldRotation(); + + if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) && + (root_at * last_at_axis > 0.95f)) + { + LLVector3 vel = pAvatar->getVelocity(); + if (vel.magVecSquared() > 4.f) + { + setLookAt(LOOKAT_TARGET_IDLE, pAvatar, vel * av_inv_rot); + } + else + { + // *FIX: rotate mframeagent by sit object's rotation? + LLQuaternion look_rotation = pAvatar->isSitting() ? pAvatar->getRenderRotation() : gAgent.getFrameAgent().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, pAvatar, look_offset); + } + last_at_axis = root_at; + return; + } + + last_at_axis = root_at; + + if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode()) + { + setLookAt(LOOKAT_TARGET_NONE, pAvatar, 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->getWindowWidth() ) - 0.5f; + F32 y_from_center = + ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 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, pAvatar, headLookAxis); + } +} + +//----------------------------------------------------------------------------- +// updateCamera() +//----------------------------------------------------------------------------- +void LLAgentCamera::updateCamera() +{ + //static LLFastTimer::DeclareTimer ftm("Camera"); + //LLFastTimer t(ftm); + + LLVOAvatar *pAvatar = gAgent.getAvatarObject(); + + // - changed camera_skyward to the new global "mCameraUpVector" + mCameraUpVector = LLVector3::z_axis; + //LLVector3 camera_skyward(0.f, 0.f, 1.f); + + U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode; + + validateFocusObject(); + + if (isAgentAvatarValid() && + pAvatar->isSitting() && + camera_mode == CAMERA_MODE_MOUSELOOK) + { + //changed camera_skyward to the new global "mCameraUpVector" + mCameraUpVector = mCameraUpVector * pAvatar->getRenderRotation(); + } + + if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams()) + { + changeCameraToFollow(); + } + + //NOTE - this needs to be integrated into a general upVector system here within llAgent. + if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar ) + { + mCameraUpVector = mFollowCam.getUpVector(); + } + + if (mSitCameraEnabled) + { + if (mSitCameraReferenceObject->isDead()) + { + setSitCamera(LLUUID::null); + } + } + + // Update UI with our camera inputs + LLFloaterCamera* camera_floater = LLFloaterCamera::getInstance();//LLFloaterReg::findTypedInstance("camera"); + if (camera_floater) + { + camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left + gAgentCamera.getOrbitUpKey() > 0.f, // top + gAgentCamera.getOrbitLeftKey() > 0.f, // right + gAgentCamera.getOrbitDownKey() > 0.f); // bottom + + camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left + gAgentCamera.getPanUpKey() > 0.f, // top + gAgentCamera.getPanRightKey() > 0.f, // right + gAgentCamera.getPanDownKey() > 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 (gAgentCamera.getOrbitUpKey() || gAgentCamera.getOrbitDownKey()) + { + F32 input_rate = gAgentCamera.getOrbitUpKey() - gAgentCamera.getOrbitDownKey(); + cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped ); + } + + if (gAgentCamera.getOrbitLeftKey() || gAgentCamera.getOrbitRightKey()) + { + F32 input_rate = gAgentCamera.getOrbitLeftKey() - gAgentCamera.getOrbitRightKey(); + cameraOrbitAround(input_rate * ORBIT_AROUND_RATE / gFPSClamped); + } + + if (gAgentCamera.getOrbitInKey() || gAgentCamera.getOrbitOutKey()) + { + F32 input_rate = gAgentCamera.getOrbitInKey() - gAgentCamera.getOrbitOutKey(); + + 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 (gAgentCamera.getPanInKey() || gAgentCamera.getPanOutKey()) + { + F32 input_rate = gAgentCamera.getPanInKey() - gAgentCamera.getPanOutKey(); + cameraPanIn(input_rate * PAN_RATE / gFPSClamped); + } + + if (gAgentCamera.getPanRightKey() || gAgentCamera.getPanLeftKey()) + { + F32 input_rate = gAgentCamera.getPanRightKey() - gAgentCamera.getPanLeftKey(); + cameraPanLeft(input_rate * -PAN_RATE / gFPSClamped ); + } + + if (gAgentCamera.getPanUpKey() || gAgentCamera.getPanDownKey()) + { + F32 input_rate = gAgentCamera.getPanUpKey() - gAgentCamera.getPanDownKey(); + cameraPanUp(input_rate * PAN_RATE / gFPSClamped ); + } + + // Clear camera keyboard keys. + gAgentCamera.clearOrbitKeys(); + gAgentCamera.clearPanKeys(); + + // lerp camera focus offset + mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); + + if ( mCameraMode == CAMERA_MODE_FOLLOW ) + { + if (isAgentAvatarValid()) + { + //-------------------------------------------------------------------------------- + // 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 = pAvatar->isSitting() ? pAvatar->getRenderRotation() : gAgent.getFrameAgent().getQuaternion(); + + LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams(); + if (current_cam) + { + mFollowCam.copyParams(*current_cam); + mFollowCam.setSubjectPositionAndRotation( pAvatar->getRenderPosition(), avatarRotationForFollowCam ); + mFollowCam.update(); + LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); + } + else + { + changeCameraToThirdPerson(TRUE); + } + } + } + + BOOL hit_limit; + LLVector3d camera_pos_global; + LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit); + mCameraVirtualPositionAgent = gAgent.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); + + gAgent.setShowAvatar(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 ) + { + gAgent.setShowAvatar(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; + + gAgent.endAnimationUpdateUI(); + gAgent.setShowAvatar(TRUE); + } + + if (isAgentAvatarValid() && (mCameraMode != CAMERA_MODE_MOUSELOOK)) + { + pAvatar->updateAttachmentVisibility(mCameraMode); + } + } + else + { + camera_pos_global = camera_target_global; + mFocusGlobal = focus_target_global; + gAgent.setShowAvatar(TRUE); + } + + // smoothing + if (TRUE) + { + LLVector3d agent_pos = gAgent.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 + bool in_build_mode = LLToolMgr::getInstance()->inBuildMode(); + mCameraSmoothingStop = mCameraSmoothingStop || in_build_mode; + + if (cameraThirdPerson() && !mCameraSmoothingStop) + { + const F32 SMOOTHING_HALF_LIFE = 0.02f; + + F32 smoothing = LLCriticalDamp::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); + + if (!mFocusObject) // we differentiate on avatar mode + { + // for avatar-relative focus, we smooth in avatar space - + // the avatar moves too jerkily w/r/t global space to smooth there. + + LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent; + if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please + { + camera_pos_agent = lerp(mCameraSmoothingLastPositionAgent, camera_pos_agent, smoothing); + camera_pos_global = camera_pos_agent + agent_pos; + } + } + else + { + LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal; + if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please + { + camera_pos_global = lerp(mCameraSmoothingLastPositionGlobal, camera_pos_global, smoothing); + } + } + } + + mCameraSmoothingLastPositionGlobal = camera_pos_global; + mCameraSmoothingLastPositionAgent = camera_pos_agent; + mCameraSmoothingStop = false; + } + + + mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE)); + +// llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl; + + F32 ui_offset = 0.f; + if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) + { + ui_offset = calcCustomizeAvatarUIOffset( camera_pos_global ); + } + + LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal); + + mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global); + + // Move the camera + + LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent); + //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent); + + //RN: translate UI offset after camera is oriented properly + LLViewerCamera::getInstance()->translate(LLViewerCamera::getInstance()->getLeftAxis() * ui_offset); + + // Change FOV + LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); + + // follow camera when in customize mode + if (cameraCustomizeAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); + } + + // update the travel distance stat + // this isn't directly related to the camera + // but this seemed like the best place to do this + LLVector3d global_pos = gAgent.getPositionGlobal(); + if (!gAgent.getLastPositionGlobal().isExactlyZero()) + { + LLVector3d delta = global_pos - gAgent.getLastPositionGlobal(); + gAgent.setDistanceTraveled(gAgent.getDistanceTraveled() + delta.magVec()); + } + gAgent.setLastPositionGlobal(global_pos); + + if (LLVOAvatar::sVisibleInFirstPerson && isAgentAvatarValid() && !pAvatar->isSitting() && cameraMouselook()) + { + LLVector3 head_pos = pAvatar->mHeadp->getWorldPosition() + + LLVector3(0.08f, 0.f, 0.05f) * pAvatar->mHeadp->getWorldRotation() + + LLVector3(0.1f, 0.f, 0.f) * pAvatar->mPelvisp->getWorldRotation(); + LLVector3 diff = mCameraPositionAgent - head_pos; + diff = diff * ~pAvatar->mRoot.getWorldRotation(); + + LLJoint* torso_joint = pAvatar->mTorsop; + LLJoint* chest_joint = pAvatar->mChestp; + LLVector3 torso_scale = torso_joint->getScale(); + LLVector3 chest_scale = chest_joint->getScale(); + + // shorten avatar skeleton to avoid foot interpenetration + if (!pAvatar->mInAir) + { + LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation(); + F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f); + F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f); + torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + + LLJoint* neck_joint = pAvatar->mNeckp; + LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation(); + scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f); + chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor)); + diff.mV[VZ] = 0.f; + } + + pAvatar->mPelvisp->setPosition(pAvatar->mPelvisp->getPosition() + diff); + + pAvatar->mRoot.updateWorldMatrixChildren(); + + for (LLVOAvatar::attachment_map_t::iterator iter = pAvatar->mAttachmentPoints.begin(); + iter != pAvatar->mAttachmentPoints.end(); ) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *attached_object = (*attachment_iter); + if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) + { + // clear any existing "early" movements of attachment + attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE); + gPipeline.updateMoveNormalAsync(attached_object->mDrawable); + attached_object->updateText(); + } + } + } + + torso_joint->setScale(torso_scale); + chest_joint->setScale(chest_scale); + } +} + +void LLAgentCamera::updateLastCamera() +{ + mLastCameraMode = mCameraMode; +} + +void LLAgentCamera::updateFocusOffset() +{ + validateFocusObject(); + if (mFocusObject.notNull()) + { + LLVector3d obj_pos = gAgent.getPosGlobalFromAgent(mFocusObject->getRenderPosition()); + mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos); + } +} + +void LLAgentCamera::validateFocusObject() +{ + if (mFocusObject.notNull() && + mFocusObject->isDead()) + { + mFocusObjectOffset.clearVec(); + clearFocusObject(); + mCameraFOVZoomFactor = 0.f; + } +} + +//----------------------------------------------------------------------------- +// calcCustomizeAvatarUIOffset() +//----------------------------------------------------------------------------- +F32 LLAgentCamera::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ) +{ + F32 ui_offset = 0.f; + + if( gFloaterCustomize ) + { + const LLRect& rect = gFloaterCustomize->getRect(); + + // Move the camera so that the avatar isn't covered up by this floater. + F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidth())))); + F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); // radians + F32 offset = tan(apparent_angle); + + if( rect.mLeft < (gViewerWindow->getWindowWidth() - rect.mRight) ) + { + // Move the avatar to the right (camera to the left) + ui_offset = offset; + } + else + { + // Move the avatar to the left (camera to the right) + ui_offset = -offset; + } + } + F32 range = (F32)dist_vec(camera_pos_global, gAgentCamera.getFocusGlobal()); + mUIOffset = lerp(mUIOffset, ui_offset, LLCriticalDamp::getInterpolant(0.05f)); + return mUIOffset * range; +} + +//----------------------------------------------------------------------------- +// calcFocusPositionTargetGlobal() +//----------------------------------------------------------------------------- +LLVector3d LLAgentCamera::calcFocusPositionTargetGlobal() +{ + if (mFocusObject.notNull() && mFocusObject->isDead()) + { + clearFocusObject(); + } + + if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus()); + return mFocusTargetGlobal; + } + else if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + LLVector3d at_axis(1.0, 0.0, 0.0); + LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); + if (isAgentAvatarValid() && gAgent.getAvatarObject()->getParent()) + { + LLViewerObject* root_object = (LLViewerObject*)gAgent.getAvatarObject()->getRoot(); + if (!root_object->flagCameraDecoupled()) + { + agent_rot *= ((LLViewerObject*)(gAgent.getAvatarObject()->getParent()))->getRenderRotation(); + } + } + at_axis = at_axis * agent_rot; + mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis; + return mFocusTargetGlobal; + } + else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) + { + return mFocusTargetGlobal; + } + else if (!mFocusOnAvatar) + { + if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull()) + { + LLDrawable* drawablep = mFocusObject->mDrawable; + + if (mTrackFocusObject && + drawablep && + drawablep->isActive()) + { + if (!mFocusObject->isAvatar()) + { + if (mFocusObject->isSelected()) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + gPipeline.updateMoveDampedAsync(drawablep); + } + } + } + } + // if not tracking object, update offset based on new object position + else + { + updateFocusOffset(); + } + LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; + mFocusTargetGlobal.setVec(gAgent.getPosGlobalFromAgent(focus_agent)); + } + return mFocusTargetGlobal; + } + else if (mSitCameraEnabled && isAgentAvatarValid() && gAgent.getAvatarObject()->isSitting() && mSitCameraReferenceObject.notNull()) + { + // sit camera + LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); + LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + + LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot); + return gAgent.getPosGlobalFromAgent(target_pos); + } + else + { + return gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(); + } +} + +LLVector3d LLAgentCamera::calcThirdPersonFocusOffset() +{ + // ...offset from avatar + LLVector3d focus_offset; + focus_offset.setVec(gSavedSettings.getVector3("FocusOffsetDefault")); + LLQuaternion agent_rot = gAgent.getFrameAgent().getQuaternion(); + if (isAgentAvatarValid() && gAgent.getAvatarObject()->getParent()) + { + agent_rot *= ((LLViewerObject*)(gAgent.getAvatarObject()->getParent()))->getRenderRotation(); + } + + //focus_offset = convert_from_llsd(mFocusOffsetInitial[mCameraPreset]->get(), TYPE_VEC3D, ""); + return focus_offset * agent_rot; +} + +void LLAgentCamera::setupSitCamera() +{ + // agent frame entering this function is in world coordinates + if (isAgentAvatarValid() && gAgent.getAvatarObject()->getParent()) + { + LLQuaternion parent_rot = ((LLViewerObject*)gAgent.getAvatarObject()->getParent())->getRenderRotation(); + // slam agent coordinate frame to proper parent local version + LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis * ~parent_rot); + } +} + +//----------------------------------------------------------------------------- +// getCameraPositionAgent() +//----------------------------------------------------------------------------- +const LLVector3 &LLAgentCamera::getCameraPositionAgent() const +{ + return LLViewerCamera::getInstance()->getOrigin(); +} + +//----------------------------------------------------------------------------- +// getCameraPositionGlobal() +//----------------------------------------------------------------------------- +LLVector3d LLAgentCamera::getCameraPositionGlobal() const +{ + return gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()); +} + +//----------------------------------------------------------------------------- +// calcCameraFOVZoomFactor() +//----------------------------------------------------------------------------- +F32 LLAgentCamera::calcCameraFOVZoomFactor() +{ + LLVector3 camera_offset_dir; + camera_offset_dir.setVec(mCameraFocusOffset); + + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + return 0.f; + } + else if (mFocusObject.notNull() && !mFocusObject->isAvatar() && !mFocusOnAvatar) + { + // don't FOV zoom on mostly transparent objects + LLVector3 focus_offset = mFocusObjectOffset; + F32 obj_min_dist = 0.f; + if (!gSavedSettings.getBOOL("AscentDisableMinZoomDist")) + calcCameraMinDistance(obj_min_dist); + F32 current_distance = llmax(0.001f, camera_offset_dir.magVec()); + + mFocusObjectDist = obj_min_dist - current_distance; + + F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f); + return new_fov_zoom; + } + else // focusing on land or avatar + { + // keep old field of view until user changes focus explicitly + return mCameraFOVZoomFactor; + //return 0.f; + } +} + +//----------------------------------------------------------------------------- +// calcCameraPositionTargetGlobal() +//----------------------------------------------------------------------------- +LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) +{ + // Compute base camera position and look-at points. + F32 camera_land_height; + LLVector3d frame_center_global = !isAgentAvatarValid() ? + gAgent.getPositionGlobal() : + gAgent.getPosGlobalFromAgent(gAgent.getAvatarObject()->mRoot.getWorldPosition()); + + LLVOAvatar *pAvatar = gAgent.getAvatarObject(); + BOOL isConstrained = FALSE; + LLVector3d head_offset; + head_offset.setVec(mThirdPersonHeadOffset); + + LLVector3d camera_position_global; + + if (mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar) + { + camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition()); + } + else if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + if (!isAgentAvatarValid() || pAvatar->mDrawable.isNull()) + { + llwarns << "Null avatar drawable!" << llendl; + return LLVector3d::zero; + } + head_offset.clearVec(); + if (pAvatar->isSitting() && pAvatar->getParent()) + { + pAvatar->updateHeadOffset(); + head_offset.mdV[VX] = pAvatar->mHeadOffset.mV[VX]; + head_offset.mdV[VY] = pAvatar->mHeadOffset.mV[VY]; + head_offset.mdV[VZ] = pAvatar->mHeadOffset.mV[VZ] + 0.1f; + const LLMatrix4& mat = ((LLViewerObject*) pAvatar->getParent())->getRenderMatrix(); + camera_position_global = gAgent.getPosGlobalFromAgent + ((gAgent.getAvatarObject()->getPosition()+ + LLVector3(head_offset)*pAvatar->getRotation()) * mat); + } + else + { + head_offset.mdV[VZ] = pAvatar->mHeadOffset.mV[VZ]; + if (pAvatar->isSitting()) + { + head_offset.mdV[VZ] += 0.1; + } + camera_position_global = gAgent.getPosGlobalFromAgent(pAvatar->getRenderPosition());//frame_center_global; + head_offset = head_offset * pAvatar->getRenderRotation(); + camera_position_global = camera_position_global + head_offset; + } + } + else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar) + { + LLVector3 local_camera_offset; + F32 camera_distance = 0.f; + + if (mSitCameraEnabled + && isAgentAvatarValid() + && pAvatar->isSitting() + && mSitCameraReferenceObject.notNull()) + { + // sit camera + LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); + LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation(); + + LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot); + + camera_position_global = gAgent.getPosGlobalFromAgent(target_pos); + } + else + { + local_camera_offset = mCameraZoomFraction * getCameraOffsetInitial() * gSavedSettings.getF32("CameraOffsetScale"); + + // are we sitting down? + if (isAgentAvatarValid() && pAvatar->getParent()) + { + LLQuaternion parent_rot = ((LLViewerObject*)gAgent.getAvatarObject()->getParent())->getRenderRotation(); + // slam agent coordinate frame to proper parent local version + LLVector3 at_axis = gAgent.getFrameAgent().getAtAxis() * parent_rot; + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis * ~parent_rot); + + local_camera_offset = local_camera_offset * gAgent.getFrameAgent().getQuaternion() * parent_rot; + } + else + { + local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); + } + + if (!mCameraCollidePlane.isExactlyZero() && (!isAgentAvatarValid() || !pAvatar->isSitting())) + { + LLVector3 plane_normal; + plane_normal.setVec(mCameraCollidePlane.mV); + + F32 offset_dot_norm = local_camera_offset * plane_normal; + if (llabs(offset_dot_norm) < 0.001f) + { + offset_dot_norm = 0.001f; + } + + camera_distance = local_camera_offset.normalize(); + + F32 pos_dot_norm = gAgent.getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal; + + // if agent is outside the colliding half-plane + if (pos_dot_norm > mCameraCollidePlane.mV[VW]) + { + // check to see if camera is on the opposite side (inside) the half-plane + if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW]) + { + // diminish offset by factor to push it back outside the half-plane + camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm; + } + } + else + { + if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW]) + { + camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm; + } + } + } + else + { + camera_distance = local_camera_offset.normalize(); + } + + mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE); + + if (mTargetCameraDistance != mCurrentCameraDistance) + { + F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE); + + mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); + } + + // Make the camera distance current + local_camera_offset *= mCurrentCameraDistance; + + // set the global camera position + LLVector3d camera_offset; + + LLVector3 av_pos = !isAgentAvatarValid() ? LLVector3::zero : pAvatar->getRenderPosition(); + camera_offset.setVec( local_camera_offset ); + camera_position_global = frame_center_global + head_offset + camera_offset; + + if (isAgentAvatarValid()) + { + LLVector3d camera_lag_d; + F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE); + LLVector3 target_lag; + LLVector3 vel = gAgent.getVelocity(); + + // lag by appropriate amount for flying + F32 time_in_air = pAvatar->mTimeInAir.getElapsedTimeF32(); + if(!mCameraAnimating && pAvatar->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) + { + LLVector3 frame_at_axis = gAgent.getFrameAgent().getAtAxis(); + frame_at_axis -= projected_vec(frame_at_axis, gAgent.getReferenceUpVector()); + frame_at_axis.normalize(); + + //transition smoothly in air mode, to avoid camera pop + F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME; + u = llclamp(u, 0.f, 1.f); + + lag_interp *= u; + + if (gViewerWindow->getLeftMouseDown() && gViewerWindow->getLastPick().mObjectID == pAvatar->getID()) + { + // disable camera lag when using mouse-directed steering + target_lag.clearVec(); + } + else + { + target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f; + } + + mCameraLag = lerp(mCameraLag, target_lag, lag_interp); + + F32 lag_dist = mCameraLag.magVec(); + if (lag_dist > MAX_CAMERA_LAG) + { + mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist; + } + + // clamp camera lag so that avatar is always in front + F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis; + if (dot < -(MIN_CAMERA_LAG * u)) + { + mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis; + } + } + else + { + mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f)); + } + + camera_lag_d.setVec(mCameraLag); + camera_position_global = camera_position_global - camera_lag_d; + } + } + } + else + { + LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal(); + // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value + camera_position_global = focusPosGlobal + mCameraFocusOffset; + } + + if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike()) + { + LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); + bool constrain = true; + if(regionp && regionp->canManageEstate()) + { + constrain = false; + } + if(constrain) + { + F32 max_dist = (CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode) ? APPEARANCE_MAX_ZOOM : mDrawDistance; + + LLVector3d camera_offset = camera_position_global - gAgent.getPositionGlobal(); + F32 camera_distance = (F32)camera_offset.magVec(); + + if(camera_distance > max_dist) + { + camera_position_global = gAgent.getPositionGlobal() + (max_dist/camera_distance)*camera_offset; + isConstrained = TRUE; + } + } + +// JC - Could constrain camera based on parcel stuff here. +// LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); +// +// if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global))) +// { +// camera_position_global = last_position_global; +// +// isConstrained = TRUE; +// } + } + + // Don't let camera go underground + F32 camera_min_off_ground = getCameraMinOffGround(); + + camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global); + + if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground) + { + camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground; + isConstrained = TRUE; + } + + + if (hit_limit) + { + *hit_limit = isConstrained; + } + + return camera_position_global; +} + + +LLVector3 LLAgentCamera::getCameraOffsetInitial() +{ + //return convert_from_llsd(mCameraOffsetInitial[mCameraPreset]->get(), TYPE_VEC3, ""); + return mCameraOffsetDefault; +} + + +//----------------------------------------------------------------------------- +// handleScrollWheel() +//----------------------------------------------------------------------------- +void LLAgentCamera::handleScrollWheel(S32 clicks) +{ + if (mCameraMode == CAMERA_MODE_FOLLOW && getFocusOnAvatar()) + { + if (!mFollowCam.getPositionLocked()) // not if the followCam position is locked in place + { + mFollowCam.zoom(clicks); + if (mFollowCam.isZoomedToMinimumDistance()) + { + changeCameraToMouselook(FALSE); + } + } + } + else + { + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); + + // Block if camera is animating + if (mCameraAnimating) + { + return; + } + + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom_factor = (F32)pow(0.8, -clicks); + cameraZoomIn(zoom_factor); + } + else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON)) + { + F32 camera_offset_initial_mag = getCameraOffsetInitial().magVec(); + + F32 current_zoom_fraction = mTargetCameraDistance / (camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); + current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks); + + cameraOrbitIn(current_zoom_fraction * camera_offset_initial_mag * gSavedSettings.getF32("CameraOffsetScale")); + } + else + { + F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec(); + cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks))); + } + } +} + + +//----------------------------------------------------------------------------- +// getCameraMinOffGround() +//----------------------------------------------------------------------------- +F32 LLAgentCamera::getCameraMinOffGround() +{ + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + return 0.f; + } + else + { + if (gSavedSettings.getBOOL("DisableCameraConstraints")) + { + return -1000.f; + } + else + { + return 0.5f; + } + } +} + + +//----------------------------------------------------------------------------- +// resetCamera() +//----------------------------------------------------------------------------- +void LLAgentCamera::resetCamera() +{ + // Remove any pitch from the avatar + LLVector3 at = gAgent.getFrameAgent().getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); + // have to explicitly clear field of view zoom now + mCameraFOVZoomFactor = 0.f; + + updateCamera(); +} + +//----------------------------------------------------------------------------- +// changeCameraToMouselook() +//----------------------------------------------------------------------------- +void LLAgentCamera::changeCameraToMouselook(BOOL animate) +{ + if (!gSavedSettings.getBOOL("EnableMouselook") || LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + // visibility changes at end of animation + gViewerWindow->getWindow()->resetBusyCount(); + + // Menus should not remain open on switching to mouselook... + LLMenuGL::sMenuContainer->hideMenus(); + //LLUI::clearPopups(); + + // unpause avatar animation + gAgent.unpauseAnimation(); + + LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", TRUE); + gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + if (isAgentAvatarValid()) + { + gAgent.getAvatarObject()->stopMotion(ANIM_AGENT_BODY_NOISE); + gAgent.getAvatarObject()->stopMotion(ANIM_AGENT_BREATHE_ROT); + } + + //gViewerWindow->stopGrab(); + LLSelectMgr::getInstance()->deselectAll(); + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); + + if (mCameraMode != CAMERA_MODE_MOUSELOOK) + { + gFocusMgr.setKeyboardFocus( NULL ); + if (gSavedSettings.getBOOL("AONoStandsInMouselook")) LLFloaterAO::stopMotion(LLFloaterAO::getCurrentStandId(), FALSE,TRUE); + + updateLastCamera(); + mCameraMode = CAMERA_MODE_MOUSELOOK; + const U32 old_flags = gAgent.getControlFlags(); + gAgent.setControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != gAgent.getControlFlags()) + { + gAgent.setFlagsDirty(); + } + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } + } +} + + +//----------------------------------------------------------------------------- +// changeCameraToDefault() +//----------------------------------------------------------------------------- +void LLAgentCamera::changeCameraToDefault() +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + if (LLFollowCamMgr::getActiveFollowCamParams()) + { + changeCameraToFollow(); + } + else + { + changeCameraToThirdPerson(); + } +} + + +//----------------------------------------------------------------------------- +// changeCameraToFollow() +//----------------------------------------------------------------------------- +void LLAgentCamera::changeCameraToFollow(BOOL animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + if(mCameraMode != CAMERA_MODE_FOLLOW) + { + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + animate = FALSE; + } + startCameraAnimation(); + + updateLastCamera(); + mCameraMode = CAMERA_MODE_FOLLOW; + + // bang-in the current focus, position, and up vector of the follow cam + mFollowCam.reset(mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis); + + if (gBasicToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + if (isAgentAvatarValid()) + { + gAgent.getAvatarObject()->mPelvisp->setPosition(LLVector3::zero); + gAgent.getAvatarObject()->startMotion( ANIM_AGENT_BODY_NOISE ); + gAgent.getAvatarObject()->startMotion( ANIM_AGENT_BREATHE_ROT ); + } + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", FALSE); + gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + // unpause avatar animation + gAgent.unpauseAnimation(); + + gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } + } +} + +//----------------------------------------------------------------------------- +// changeCameraToThirdPerson() +//----------------------------------------------------------------------------- +void LLAgentCamera::changeCameraToThirdPerson(BOOL animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + gViewerWindow->getWindow()->resetBusyCount(); + + mCameraZoomFraction = INITIAL_ZOOM_FRACTION; + + if (isAgentAvatarValid()) + { + if (!gAgent.getAvatarObject()->isSitting()) + { + gAgent.getAvatarObject()->mPelvisp->setPosition(LLVector3::zero); + } + gAgent.getAvatarObject()->startMotion(ANIM_AGENT_BODY_NOISE); + gAgent.getAvatarObject()->startMotion(ANIM_AGENT_BREATHE_ROT); + } + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", FALSE); + gSavedSettings.setBOOL("ThirdPersonBtnState", TRUE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + + LLVector3 at_axis; + + // unpause avatar animation + gAgent.unpauseAnimation(); + + if (mCameraMode != CAMERA_MODE_THIRD_PERSON) + { + if (gBasicToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + } + + mCameraLag.clearVec(); + if (mCameraMode == CAMERA_MODE_MOUSELOOK) + { + mCurrentCameraDistance = MIN_CAMERA_DISTANCE; + mTargetCameraDistance = MIN_CAMERA_DISTANCE; + animate = FALSE; + } + updateLastCamera(); + mCameraMode = CAMERA_MODE_THIRD_PERSON; + U32 old_flags = gAgent.getControlFlags(); + gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != gAgent.getControlFlags()) + { + gAgent.setFlagsDirty(); + } + } + + // Remove any pitch from the avatar + if (isAgentAvatarValid() && gAgent.getAvatarObject()->getParent()) + { + LLQuaternion obj_rot = ((LLViewerObject*)gAgent.getAvatarObject()->getParent())->getRenderRotation(); + at_axis = LLViewerCamera::getInstance()->getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis * ~obj_rot); + } + else + { + at_axis = gAgent.getFrameAgent().getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis); + } + + + if (animate) + { + startCameraAnimation(); + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } +} + +//----------------------------------------------------------------------------- +// changeCameraToCustomizeAvatar() +//----------------------------------------------------------------------------- +void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_animate) +{ + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + return; + } + + // + //gAgent.standUp(); // force stand up + // + gViewerWindow->getWindow()->resetBusyCount(); + + if (gFaceEditToolset) + { + LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset); + } + + gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); + gSavedSettings.setBOOL("MouselookBtnState", FALSE); + gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE); + gSavedSettings.setBOOL("BuildBtnState", FALSE); + + if (camera_animate) + { + // + if(gSavedSettings.getBOOL("AppearanceCameraMovement")) + // + startCameraAnimation(); + } + + if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) + { + updateLastCamera(); + mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR; + U32 old_flags = gAgent.getControlFlags(); + gAgent.clearControlFlags(AGENT_CONTROL_MOUSELOOK); + if (old_flags != gAgent.getControlFlags()) + { + gAgent.setFlagsDirty(); + } + + gFocusMgr.setKeyboardFocus( NULL ); + gFocusMgr.setMouseCapture( NULL ); + + LLVOAvatar::onCustomizeStart(); + + if (isAgentAvatarValid()) + { + if(avatar_animate) + { + // Remove any pitch or rotation from the avatar + LLVector3 at = gAgent.getAtAxis(); + at.mV[VZ] = 0.f; + at.normalize(); + gAgent.resetAxes(at); + + gAgent.sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START); + gAgent.setCustomAnim(TRUE); + gAgent.getAvatarObject()->startMotion(ANIM_AGENT_CUSTOMIZE); + LLMotion* turn_motion = gAgent.getAvatarObject()->findMotion(ANIM_AGENT_CUSTOMIZE); + + if (turn_motion) + { + // delay camera animation long enough to play through turn animation + setAnimationDuration(turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP); + } + else + { + setAnimationDuration(gSavedSettings.getF32("ZoomTime")); + } + //gAgentAvatarp->invalidateAll(); + //gAgentAvatarp->updateMeshTextures(); + } + + gAgentCamera.setFocusGlobal(LLVector3d::zero); + } + } + else + { + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } + + // + if(!gSavedSettings.getBOOL("AppearanceCameraMovement")) + { + //hmm + mCameraAnimating = FALSE; + gAgent.endAnimationUpdateUI(); + } + /*LLVector3 agent_at = gAgent.getAtAxis(); + agent_at.mV[VZ] = 0.f; + agent_at.normalize(); + + // default focus point for customize avatar + LLVector3 focus_target = isAgentAvatarValid() + ? gAgentAvatarp->mHeadp->getWorldPosition() + : gAgent.getPositionAgent(); + + LLVector3d camera_offset(agent_at * -1.0); + // push camera up and out from avatar + camera_offset.mdV[VZ] = 0.1f; + camera_offset *= CUSTOMIZE_AVATAR_CAMERA_DEFAULT_DIST; + LLVector3d focus_target_global = gAgent.getPosGlobalFromAgent(focus_target); + setAnimationDuration(gSavedSettings.getF32("ZoomTime")); + setCameraPosAndFocusGlobal(focus_target_global + camera_offset, focus_target_global, gAgent.getID());*/ +} + + +/*void LLAgentCamera::switchCameraPreset(ECameraPreset preset) +{ + //zoom is supposed to be reset for the front and group views + mCameraZoomFraction = 1.f; + + //focusing on avatar in that case means following him on movements + mFocusOnAvatar = TRUE; + + mCameraPreset = preset; + + gSavedSettings.setU32("CameraPreset", mCameraPreset); +}*/ + + +// +// Focus point management +// + +void LLAgentCamera::setAnimationDuration(F32 duration) +{ + if (mCameraAnimating) + { + // do not cut any existing camera animation short + F32 animation_left = llmax(0.f, mAnimationDuration - mAnimationTimer.getElapsedTimeF32()); + mAnimationDuration = llmax(duration, animation_left); + } + else + { + mAnimationDuration = duration; + } +} + +//----------------------------------------------------------------------------- +// startCameraAnimation() +//----------------------------------------------------------------------------- +void LLAgentCamera::startCameraAnimation() +{ + mAnimationCameraStartGlobal = getCameraPositionGlobal(); + mAnimationFocusStartGlobal = mFocusGlobal; + setAnimationDuration(gSavedSettings.getF32("ZoomTime")); + mAnimationTimer.reset(); + mCameraAnimating = TRUE; +} + +//----------------------------------------------------------------------------- +// stopCameraAnimation() +//----------------------------------------------------------------------------- +void LLAgentCamera::stopCameraAnimation() +{ + mCameraAnimating = FALSE; +} + +void LLAgentCamera::clearFocusObject() +{ + if (mFocusObject.notNull()) + { + startCameraAnimation(); + + setFocusObject(NULL); + mFocusObjectOffset.clearVec(); + } +} + +void LLAgentCamera::setFocusObject(LLViewerObject* object) +{ + mFocusObject = object; +} + +// Focus on a point, but try to keep camera position stable. +//----------------------------------------------------------------------------- +// setFocusGlobal() +//----------------------------------------------------------------------------- +void LLAgentCamera::setFocusGlobal(const LLPickInfo& pick) +{ + LLViewerObject* objectp = gObjectList.findObject(pick.mObjectID); + + if (objectp) + { + // focus on object plus designated offset + // which may or may not be same as pick.mPosGlobal + setFocusGlobal(objectp->getPositionGlobal() + LLVector3d(pick.mObjectOffset), pick.mObjectID); + } + else + { + // focus directly on point where user clicked + setFocusGlobal(pick.mPosGlobal, pick.mObjectID); + } +} + + +void LLAgentCamera::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id) +{ + setFocusObject(gObjectList.findObject(object_id)); + LLVector3d old_focus = mFocusTargetGlobal; + LLViewerObject *focus_obj = mFocusObject; + + // if focus has changed + if (old_focus != focus) + { + if (focus.isExactlyZero()) + { + if (isAgentAvatarValid()) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgent.getAvatarObject()->mHeadp->getWorldPosition()); + } + else + { + mFocusTargetGlobal = gAgent.getPositionGlobal(); + } + mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal; + mCameraFocusOffset = mCameraFocusOffsetTarget; + setLookAt(LOOKAT_TARGET_CLEAR); + } + else + { + mFocusTargetGlobal = focus; + if (!focus_obj) + { + mCameraFOVZoomFactor = 0.f; + } + + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal; + + startCameraAnimation(); + + if (focus_obj) + { + if (focus_obj->isAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, focus_obj); + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (gAgent.getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation()); + } + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); + } + } + } + else // focus == mFocusTargetGlobal + { + if (focus.isExactlyZero()) + { + if (isAgentAvatarValid()) + { + mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(gAgent.getAvatarObject()->mHeadp->getWorldPosition()); + } + else + { + mFocusTargetGlobal = gAgent.getPositionGlobal(); + } + } + mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);; + mCameraFocusOffset = mCameraFocusOffsetTarget; + } + + if (mFocusObject.notNull()) + { + // for attachments, make offset relative to avatar, not the attachment + if (mFocusObject->isAttachment()) + { + while (mFocusObject.notNull() && !mFocusObject->isAvatar()) + { + mFocusObject = (LLViewerObject*) mFocusObject->getParent(); + } + setFocusObject((LLViewerObject*)mFocusObject); + } + updateFocusOffset(); + } +} + +// Used for avatar customization +//----------------------------------------------------------------------------- +// setCameraPosAndFocusGlobal() +//----------------------------------------------------------------------------- +void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id) +{ + LLVector3d old_focus = mFocusTargetGlobal.isExactlyZero() ? focus : mFocusTargetGlobal; + + F64 focus_delta_squared = (old_focus - focus).magVecSquared(); + const F64 ANIM_EPSILON_SQUARED = 0.0001; + if (focus_delta_squared > ANIM_EPSILON_SQUARED) + { + startCameraAnimation(); + + if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) + { + // Compensate for the fact that the camera has already been offset to make room for LLFloaterCustomize. + mAnimationCameraStartGlobal -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * calcCustomizeAvatarUIOffset( mAnimationCameraStartGlobal )); + } + } + + //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) ); + setFocusObject(gObjectList.findObject(object_id)); + mFocusTargetGlobal = focus; + mCameraFocusOffsetTarget = camera_pos - focus; + mCameraFocusOffset = mCameraFocusOffsetTarget; + + if (mFocusObject) + { + if (mFocusObject->isAvatar()) + { + setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject); + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (gAgent.getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation()); + } + } + else + { + setLookAt(LOOKAT_TARGET_FOCUS, NULL, gAgent.getPosAgentFromGlobal(mFocusTargetGlobal)); + } + + if (mCameraAnimating) + { + const F64 ANIM_METERS_PER_SECOND = 10.0; + const F64 MIN_ANIM_SECONDS = 0.5; + const F64 MAX_ANIM_SECONDS = 10.0; + F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); + anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS ); + setAnimationDuration( (F32)anim_duration ); + } + + updateFocusOffset(); +} + +//----------------------------------------------------------------------------- +// setSitCamera() +//----------------------------------------------------------------------------- +void LLAgentCamera::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus) +{ + BOOL camera_enabled = !object_id.isNull(); + + if (camera_enabled) + { + LLViewerObject *reference_object = gObjectList.findObject(object_id); + if (reference_object) + { + //convert to root object relative? + mSitCameraPos = camera_pos; + mSitCameraFocus = camera_focus; + mSitCameraReferenceObject = reference_object; + mSitCameraEnabled = TRUE; + } + } + else + { + mSitCameraPos.clearVec(); + mSitCameraFocus.clearVec(); + mSitCameraReferenceObject = NULL; + mSitCameraEnabled = FALSE; + } +} + +//----------------------------------------------------------------------------- +// setFocusOnAvatar() +//----------------------------------------------------------------------------- +void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate) +{ + if (focus_on_avatar != mFocusOnAvatar) + { + if (animate) + { + startCameraAnimation(); + } + else + { + stopCameraAnimation(); + } + } + + //RN: when focused on the avatar, we're not "looking" at it + // looking implies intent while focusing on avatar means + // you're just walking around with a camera on you...eesh. + if (!mFocusOnAvatar && focus_on_avatar) + { + setFocusGlobal(LLVector3d::zero); + mCameraFOVZoomFactor = 0.f; + if (mCameraMode == CAMERA_MODE_THIRD_PERSON) + { + LLVector3 at_axis; + if (isAgentAvatarValid() && gAgent.getAvatarObject()->getParent()) + { + LLQuaternion obj_rot = ((LLViewerObject*)gAgent.getAvatarObject()->getParent())->getRenderRotation(); + at_axis = LLViewerCamera::getInstance()->getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis * ~obj_rot); + } + else + { + at_axis = LLViewerCamera::getInstance()->getAtAxis(); + at_axis.mV[VZ] = 0.f; + at_axis.normalize(); + gAgent.resetAxes(at_axis); + } + } + } + // unlocking camera from avatar + else if (mFocusOnAvatar && !focus_on_avatar) + { + // keep camera focus point consistent, even though it is now unlocked + setFocusGlobal(gAgent.getPositionGlobal() + calcThirdPersonFocusOffset(), gAgent.getID()); + } + + mFocusOnAvatar = focus_on_avatar; +} + + +BOOL LLAgentCamera::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position) +{ + if(gSavedSettings.getBOOL("PrivateLookAt")) + { + if(!mLookAt || mLookAt->isDead()) + return FALSE; + position.clearVec(); + return mLookAt->setLookAt(LOOKAT_TARGET_NONE, gAgent.getAvatarObject(), position); + } + if(object && object->isAttachment()) + { + LLViewerObject* parent = object; + while(parent) + { + if (parent == gAgent.getAvatarObject()) + { + // looking at an attachment on ourselves, which we don't want to do + object = gAgent.getAvatarObject(); + position.clearVec(); + } + parent = (LLViewerObject*)parent->getParent(); + } + } + if(!mLookAt || mLookAt->isDead()) + { + mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT); + mLookAt->setSourceObject(gAgent.getAvatarObject()); + } + + return mLookAt->setLookAt(target_type, object, position); +} + +void LLAgentCamera::lookAtObject(LLUUID object_id, ECameraPosition camera_pos) +{ + // Block if camera is animating or not in normal third person camera mode + if (mCameraAnimating || !cameraThirdPerson()) + { + return; + } + + LLViewerObject *chatter = gObjectList.findObject(object_id); + if (chatter) + { + LLVector3 delta_pos; + if (chatter->isAvatar()) + { + LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; + if (!gAgent.getAvatarObject() && chatter_av->mHeadp) + { + delta_pos = chatter_av->mHeadp->getWorldPosition() - gAgent.getAvatarObject()->mHeadp->getWorldPosition(); + } + else + { + delta_pos = chatter->getPositionAgent() - gAgent.getPositionAgent(); + } + delta_pos.normVec(); + + gAgent.setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = gAgent.getAvatarObject()->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normVec(); + LLVector3 up = left % delta_pos; + up.normVec(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + F32 radius = chatter_av->getVObjRadius(); + LLVector3d view_dist(radius, radius, 0.0f); + + if (chatter_av->mHeadp) + { + setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), object_id); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + + switch(camera_pos) + { + case CAMERA_POSITION_SELF: + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + break; + case CAMERA_POSITION_OBJECT: + mCameraFocusOffsetTarget = view_dist; + break; + } + } + else + { + setFocusGlobal(chatter->getPositionGlobal(), object_id); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + + switch(camera_pos) + { + case CAMERA_POSITION_SELF: + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + break; + case CAMERA_POSITION_OBJECT: + mCameraFocusOffsetTarget = view_dist; + break; + } + } + setFocusOnAvatar(FALSE, TRUE); + } + else + { + delta_pos = chatter->getRenderPosition() - gAgent.getPositionAgent(); + delta_pos.normVec(); + + gAgent.setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = gAgent.getAvatarObject()->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normVec(); + LLVector3 up = left % delta_pos; + up.normVec(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + setFocusGlobal(chatter->getPositionGlobal(), object_id); + + switch(camera_pos) + { + case CAMERA_POSITION_SELF: + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + break; + case CAMERA_POSITION_OBJECT: + F32 radius = chatter->getVObjRadius(); + LLVector3d view_dist(radius, radius, 0.0f); + mCameraFocusOffsetTarget = view_dist; + break; + } + + setFocusOnAvatar(FALSE, TRUE); + } + } +} + +//----------------------------------------------------------------------------- +// lookAtLastChat() +//----------------------------------------------------------------------------- +void LLAgentCamera::lookAtLastChat() +{ + // Block if camera is animating or not in normal third person camera mode + if (mCameraAnimating || !cameraThirdPerson()) + { + return; + } + + LLViewerObject *chatter = gObjectList.findObject(gAgent.getLastChatter()); + if (!chatter) + { + return; + } + + LLVector3 delta_pos; + if (chatter->isAvatar()) + { + LLVOAvatar *chatter_av = (LLVOAvatar*)chatter; + if (isAgentAvatarValid() && chatter_av->mHeadp) + { + delta_pos = chatter_av->mHeadp->getWorldPosition() - gAgent.getAvatarObject()->mHeadp->getWorldPosition(); + } + else + { + delta_pos = chatter->getPositionAgent() - gAgent.getPositionAgent(); + } + delta_pos.normalize(); + + gAgent.setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = gAgent.getAvatarObject()->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normalize(); + LLVector3 up = left % delta_pos; + up.normalize(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + //setFocusOnAvatar(FALSE, FALSE); + + if (chatter_av->mHeadp) + { + setFocusGlobal(gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), gAgent.getLastChatter()); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()); + } + else + { + setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + } + setFocusOnAvatar(FALSE, TRUE); + } + else + { + delta_pos = chatter->getRenderPosition() - gAgent.getPositionAgent(); + delta_pos.normalize(); + + gAgent.setControlFlags(AGENT_CONTROL_STOP); + + changeCameraToThirdPerson(); + + LLVector3 new_camera_pos = gAgent.getAvatarObject()->mHeadp->getWorldPosition(); + LLVector3 left = delta_pos % LLVector3::z_axis; + left.normalize(); + LLVector3 up = left % delta_pos; + up.normalize(); + new_camera_pos -= delta_pos * 0.4f; + new_camera_pos += left * 0.3f; + new_camera_pos += up * 0.2f; + + //setFocusOnAvatar(FALSE, FALSE); + + + setFocusGlobal(chatter->getPositionGlobal(), gAgent.getLastChatter()); + mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal(); + setFocusOnAvatar(FALSE, TRUE); + } +} + +BOOL LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position) +{ + // disallow pointing at attachments and avatars + if (object && (object->isAttachment() || object->isAvatar()) || gSavedSettings.getBOOL("DisablePointAtAndBeam")) + { + return FALSE; + } + if (!mPointAt || mPointAt->isDead()) + { + mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT); + mPointAt->setSourceObject(gAgent.getAvatarObject()); + } + return mPointAt->setPointAt(target_type, object, position); +} + +ELookAtType LLAgentCamera::getLookAtType() +{ + if (mLookAt) + { + return mLookAt->getLookAtType(); + } + return LOOKAT_TARGET_NONE; +} + +EPointAtType LLAgentCamera::getPointAtType() +{ + if (mPointAt) + { + return mPointAt->getPointAtType(); + } + return POINTAT_TARGET_NONE; +} + +void LLAgentCamera::clearGeneralKeys() +{ + mAtKey = 0; + mWalkKey = 0; + mLeftKey = 0; + mUpKey = 0; + mYawKey = 0.f; + mPitchKey = 0.f; +} + +void LLAgentCamera::clearOrbitKeys() +{ + mOrbitLeftKey = 0.f; + mOrbitRightKey = 0.f; + mOrbitUpKey = 0.f; + mOrbitDownKey = 0.f; + mOrbitInKey = 0.f; + mOrbitOutKey = 0.f; +} + +void LLAgentCamera::clearPanKeys() +{ + mPanRightKey = 0.f; + mPanLeftKey = 0.f; + mPanUpKey = 0.f; + mPanDownKey = 0.f; + mPanInKey = 0.f; + mPanOutKey = 0.f; +} + +// static +S32 LLAgentCamera::directionToKey(S32 direction) +{ + if (direction > 0) return 1; + if (direction < 0) return -1; + return 0; +} + + +// EOF diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h new file mode 100644 index 000000000..c09ba546c --- /dev/null +++ b/indra/newview/llagentcamera.h @@ -0,0 +1,378 @@ +/** + * @file llagent.h + * @brief LLAgent class header file + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAGENTCAMERA_H +#define LL_LLAGENTCAMERA_H + +#include "llfollowcam.h" // Ventrella +#include "llhudeffectlookat.h" // EPointAtType +#include "llhudeffectpointat.h" // ELookAtType + +class LLPickInfo; +class LLVOAvatar; +class LLControlVariable; + + +//-------------------------------------------------------------------- +// Types +//-------------------------------------------------------------------- +enum ECameraMode +{ + CAMERA_MODE_THIRD_PERSON, + CAMERA_MODE_MOUSELOOK, + CAMERA_MODE_CUSTOMIZE_AVATAR, + CAMERA_MODE_FOLLOW +}; +typedef enum e_camera_position +{ + CAMERA_POSITION_SELF, /** Camera positioned at our position */ + CAMERA_POSITION_OBJECT /** Camera positioned at observed object's position */ +} ECameraPosition; + +//------------------------------------------------------------------------ +// LLAgentCamera +//------------------------------------------------------------------------ +class LLAgentCamera +{ + LOG_CLASS(LLAgentCamera); + +public: + //-------------------------------------------------------------------- + // Constructors / Destructors + //-------------------------------------------------------------------- +public: + LLAgentCamera(); + virtual ~LLAgentCamera(); + void init(); + void cleanup(); + void setAvatarObject(LLVOAvatar* avatar); + bool isInitialized() { return mInitialized; } +private: + bool mInitialized; + + + //-------------------------------------------------------------------- + // Mode + //-------------------------------------------------------------------- +public: + void changeCameraToDefault(); + void changeCameraToMouselook(BOOL animate = TRUE); + void changeCameraToThirdPerson(BOOL animate = TRUE); + void changeCameraToCustomizeAvatar(BOOL avatar_animate = TRUE, BOOL camera_animate = TRUE); // trigger transition animation + F32 calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global ); + // Ventrella + void changeCameraToFollow(BOOL animate = TRUE); + //end Ventrella + BOOL cameraThirdPerson() const { return (mCameraMode == CAMERA_MODE_THIRD_PERSON && mLastCameraMode == CAMERA_MODE_THIRD_PERSON); } + BOOL cameraMouselook() const { return (mCameraMode == CAMERA_MODE_MOUSELOOK && mLastCameraMode == CAMERA_MODE_MOUSELOOK); } + BOOL cameraCustomizeAvatar() const { return (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR /*&& !mCameraAnimating*/); } + BOOL cameraFollow() const { return (mCameraMode == CAMERA_MODE_FOLLOW && mLastCameraMode == CAMERA_MODE_FOLLOW); } + ECameraMode getCameraMode() const { return mCameraMode; } + ECameraMode getLastCameraMode() const { return mLastCameraMode; } + void updateCamera(); // Call once per frame to update camera location/orientation + void resetCamera(); // Slam camera into its default position + void updateLastCamera(); // Set last camera to current camera + +private: + ECameraMode mCameraMode; // Target mode after transition animation is done + ECameraMode mLastCameraMode; + F32 mUIOffset; + /** Determines default camera offset depending on the current camera preset */ + LLVector3 getCameraOffsetInitial(); + +public: + LLVector3d getCameraPositionGlobal() const; + const LLVector3 &getCameraPositionAgent() const; + LLVector3d calcCameraPositionTargetGlobal(BOOL *hit_limit = NULL); // Calculate the camera position target + F32 getCameraMinOffGround(); // Minimum height off ground for this mode, meters + void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; } + BOOL calcCameraMinDistance(F32 &obj_min_distance); + F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); } + void clearCameraLag() { mCameraLag.clearVec(); } +private: + F32 mCurrentCameraDistance; // Current camera offset from avatar + F32 mTargetCameraDistance; // Target camera offset from avatar + F32 mCameraFOVZoomFactor; // Amount of fov zoom applied to camera when zeroing in on an object + F32 mCameraCurrentFOVZoomFactor; // Interpolated fov zoom + F32 mCameraFOVDefault; // Default field of view that is basis for FOV zoom effect + LLVector4 mCameraCollidePlane; // Colliding plane for camera + F32 mCameraZoomFraction; // Mousewheel driven fraction of zoom + LLVector3 mCameraPositionAgent; // Camera position in agent coordinates + LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom + LLVector3d mCameraSmoothingLastPositionGlobal; + LLVector3d mCameraSmoothingLastPositionAgent; + bool mCameraSmoothingStop; + LLVector3 mCameraLag; // Third person camera lag + LLVector3 mCameraUpVector; // Camera's up direction in world coordinates (determines the 'roll' of the view) + + //-------------------------------------------------------------------- + // Follow + //-------------------------------------------------------------------- +public: + void setUsingFollowCam(bool using_follow_cam); +private: + LLFollowCam mFollowCam; // Ventrella + + + //-------------------------------------------------------------------- + // Sit + //-------------------------------------------------------------------- +public: + void setupSitCamera(); + BOOL sitCameraEnabled() { return mSitCameraEnabled; } + void setSitCamera(const LLUUID &object_id, + const LLVector3 &camera_pos = LLVector3::zero, const LLVector3 &camera_focus = LLVector3::zero); +private: + LLPointer mSitCameraReferenceObject; // Object to which camera is related when sitting + BOOL mSitCameraEnabled; // Use provided camera information when sitting? + LLVector3 mSitCameraPos; // Root relative camera pos when sitting + LLVector3 mSitCameraFocus; // Root relative camera target when sitting + + + //-------------------------------------------------------------------- + // Animation + //-------------------------------------------------------------------- +public: + void setCameraAnimating(BOOL b) { mCameraAnimating = b; } + BOOL getCameraAnimating() { return mCameraAnimating; } + void setAnimationDuration(F32 seconds); + void startCameraAnimation(); + void stopCameraAnimation(); +private: + LLFrameTimer mAnimationTimer; // Seconds that transition animation has been active + F32 mAnimationDuration; // In seconds + BOOL mCameraAnimating; // Camera is transitioning from one mode to another + LLVector3d mAnimationCameraStartGlobal; // Camera start position, global coords + LLVector3d mAnimationFocusStartGlobal; // Camera focus point, global coords + + //-------------------------------------------------------------------- + // Focus + //-------------------------------------------------------------------- +public: + LLVector3d calcFocusPositionTargetGlobal(); + LLVector3 calcFocusOffset(LLViewerObject *object, LLVector3 pos_agent, S32 x, S32 y); + BOOL getFocusOnAvatar() const { return mFocusOnAvatar; } + LLPointer& getFocusObject() { return mFocusObject; } + F32 getFocusObjectDist() const { return mFocusObjectDist; } + void updateFocusOffset(); + void validateFocusObject(); + void setFocusGlobal(const LLPickInfo& pick); + void setFocusGlobal(const LLVector3d &focus, const LLUUID &object_id = LLUUID::null); + void setFocusOnAvatar(BOOL focus, BOOL animate); + void setCameraPosAndFocusGlobal(const LLVector3d& pos, const LLVector3d& focus, const LLUUID &object_id); + void clearFocusObject(); + void setFocusObject(LLViewerObject* object); + void setObjectTracking(BOOL track) { mTrackFocusObject = track; } + const LLVector3d &getFocusGlobal() const { return mFocusGlobal; } + const LLVector3d &getFocusTargetGlobal() const { return mFocusTargetGlobal; } +private: + LLVector3d mCameraFocusOffset; // Offset from focus point in build mode + LLVector3d mCameraFocusOffsetTarget; // Target towards which we are lerping the camera's focus offset + LLVector3 mCameraOffsetDefault; + BOOL mFocusOnAvatar; + LLVector3d mFocusGlobal; + LLVector3d mFocusTargetGlobal; + LLPointer mFocusObject; + F32 mFocusObjectDist; + LLVector3 mFocusObjectOffset; + F32 mFocusDotRadius; // Meters + BOOL mTrackFocusObject; + + //-------------------------------------------------------------------- + // Lookat / Pointat + //-------------------------------------------------------------------- +public: + void updateLookAt(const S32 mouse_x, const S32 mouse_y); + BOOL setLookAt(ELookAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero); + void lookAtObject(LLUUID object_id, ECameraPosition camera_pos); + ELookAtType getLookAtType(); + void lookAtLastChat(); + void slamLookAt(const LLVector3 &look_at); // Set the physics data + BOOL setPointAt(EPointAtType target_type, LLViewerObject *object = NULL, LLVector3 position = LLVector3::zero); + EPointAtType getPointAtType(); +public: + LLPointer mLookAt; + LLPointer mPointAt; + + //-------------------------------------------------------------------- + // Third person + //-------------------------------------------------------------------- +public: + LLVector3d calcThirdPersonFocusOffset(); + void setThirdPersonHeadOffset(LLVector3 offset) { mThirdPersonHeadOffset = offset; } +private: + LLVector3 mThirdPersonHeadOffset; // Head offset for third person camera position + + //-------------------------------------------------------------------- + // Orbit + //-------------------------------------------------------------------- +public: + void cameraOrbitAround(const F32 radians); // Rotate camera CCW radians about build focus point + void cameraOrbitOver(const F32 radians); // Rotate camera forward radians over build focus point + void cameraOrbitIn(const F32 meters); // Move camera in toward build focus point + + //-------------------------------------------------------------------- + // Zoom + //-------------------------------------------------------------------- +public: + void handleScrollWheel(S32 clicks); // Mousewheel driven zoom + void cameraZoomIn(const F32 factor); // Zoom in by fraction of current distance + F32 getCameraZoomFraction(); // Get camera zoom as fraction of minimum and maximum zoom + void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom + F32 calcCameraFOVZoomFactor(); + + //-------------------------------------------------------------------- + // Pan + //-------------------------------------------------------------------- +public: + void cameraPanIn(const F32 meters); + void cameraPanLeft(const F32 meters); + void cameraPanUp(const F32 meters); + + //-------------------------------------------------------------------- + // View + //-------------------------------------------------------------------- +public: + // Called whenever the agent moves. Puts camera back in default position, deselects items, etc. + void resetView(BOOL reset_camera = TRUE, BOOL change_camera = FALSE); + // Called on camera movement. Unlocks camera from the default position behind the avatar. + void unlockView(); +public: + F32 mDrawDistance; + + //-------------------------------------------------------------------- + // Mouselook + //-------------------------------------------------------------------- +public: + BOOL getForceMouselook() const { return mForceMouselook; } + void setForceMouselook(BOOL mouselook) { mForceMouselook = mouselook; } +private: + BOOL mForceMouselook; + + //-------------------------------------------------------------------- + // HUD + //-------------------------------------------------------------------- +public: + F32 mHUDTargetZoom; // Target zoom level for HUD objects (used when editing) + F32 mHUDCurZoom; // Current animated zoom level for HUD objects + + +/******************************************************************************** + ** ** + ** KEYS + **/ + +public: + S32 getAtKey() const { return mAtKey; } + S32 getWalkKey() const { return mWalkKey; } + S32 getLeftKey() const { return mLeftKey; } + S32 getUpKey() const { return mUpKey; } + F32 getYawKey() const { return mYawKey; } + F32 getPitchKey() const { return mPitchKey; } + + void setAtKey(S32 mag) { mAtKey = mag; } + void setWalkKey(S32 mag) { mWalkKey = mag; } + void setLeftKey(S32 mag) { mLeftKey = mag; } + void setUpKey(S32 mag) { mUpKey = mag; } + void setYawKey(F32 mag) { mYawKey = mag; } + void setPitchKey(F32 mag) { mPitchKey = mag; } + + void clearGeneralKeys(); + static S32 directionToKey(S32 direction); // Changes direction to -1/0/1 + +private: + S32 mAtKey; // Either 1, 0, or -1. Indicates that movement key is pressed + S32 mWalkKey; // Like AtKey, but causes less forward thrust + S32 mLeftKey; + S32 mUpKey; + F32 mYawKey; + F32 mPitchKey; + + + //-------------------------------------------------------------------- + // Orbit + //-------------------------------------------------------------------- +public: + F32 getOrbitLeftKey() const { return mOrbitLeftKey; } + F32 getOrbitRightKey() const { return mOrbitRightKey; } + F32 getOrbitUpKey() const { return mOrbitUpKey; } + F32 getOrbitDownKey() const { return mOrbitDownKey; } + F32 getOrbitInKey() const { return mOrbitInKey; } + F32 getOrbitOutKey() const { return mOrbitOutKey; } + + void setOrbitLeftKey(F32 mag) { mOrbitLeftKey = mag; } + void setOrbitRightKey(F32 mag) { mOrbitRightKey = mag; } + void setOrbitUpKey(F32 mag) { mOrbitUpKey = mag; } + void setOrbitDownKey(F32 mag) { mOrbitDownKey = mag; } + void setOrbitInKey(F32 mag) { mOrbitInKey = mag; } + void setOrbitOutKey(F32 mag) { mOrbitOutKey = mag; } + + void clearOrbitKeys(); +private: + F32 mOrbitLeftKey; + F32 mOrbitRightKey; + F32 mOrbitUpKey; + F32 mOrbitDownKey; + F32 mOrbitInKey; + F32 mOrbitOutKey; + + //-------------------------------------------------------------------- + // Pan + //-------------------------------------------------------------------- +public: + F32 getPanLeftKey() const { return mPanLeftKey; } + F32 getPanRightKey() const { return mPanRightKey; } + F32 getPanUpKey() const { return mPanUpKey; } + F32 getPanDownKey() const { return mPanDownKey; } + F32 getPanInKey() const { return mPanInKey; } + F32 getPanOutKey() const { return mPanOutKey; } + + void setPanLeftKey(F32 mag) { mPanLeftKey = mag; } + void setPanRightKey(F32 mag) { mPanRightKey = mag; } + void setPanUpKey(F32 mag) { mPanUpKey = mag; } + void setPanDownKey(F32 mag) { mPanDownKey = mag; } + void setPanInKey(F32 mag) { mPanInKey = mag; } + void setPanOutKey(F32 mag) { mPanOutKey = mag; } + + void clearPanKeys(); +private: + F32 mPanUpKey; + F32 mPanDownKey; + F32 mPanLeftKey; + F32 mPanRightKey; + F32 mPanInKey; + F32 mPanOutKey; + +/** Keys + ** ** + *******************************************************************************/ + +}; + +extern LLAgentCamera gAgentCamera; + +#endif + diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index b56260403..cec853e8b 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -744,12 +744,11 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) callback(handle, LLWorldMap::getInstance()->mSLURL, image_id, LLWorldMap::getInstance()->mSLURLTeleport); } } - if(LLAgent::lure_show) + if( gAgent.mPendingLure && + (U16)(gAgent.mPendingLure->mPosGlobal.mdV[0] / REGION_WIDTH_UNITS) == x_regions && + (U16)(gAgent.mPendingLure->mPosGlobal.mdV[1] / REGION_WIDTH_UNITS) == y_regions ) { - if((x_regions == LLAgent::lure_global_x) && (y_regions == LLAgent::lure_global_y)) - { - gAgent.onFoundLureDestination(); - } + gAgent.onFoundLureDestination(); } }