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();
}
}