llagent.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "stdtypes.h"
00035 #include "stdenums.h"
00036 
00037 #include "llagent.h" 
00038 
00039 #include "llcoordframe.h"
00040 #include "indra_constants.h"
00041 #include "llmath.h"
00042 #include "llcriticaldamp.h"
00043 #include "llfocusmgr.h"
00044 #include "llglheaders.h"
00045 #include "llparcel.h"
00046 #include "llpermissions.h"
00047 #include "llregionhandle.h"
00048 #include "m3math.h"
00049 #include "m4math.h"
00050 #include "message.h"
00051 #include "llquaternion.h"
00052 #include "v3math.h"
00053 #include "v4math.h"
00054 #include "llsmoothstep.h"
00055 #include "llsdutil.h"
00056 //#include "vmath.h"
00057 
00058 #include "imageids.h"
00059 #include "llbox.h"
00060 #include "llbutton.h"
00061 #include "llcallingcard.h"
00062 #include "llchatbar.h"
00063 #include "llconsole.h"
00064 #include "lldrawable.h"
00065 #include "llface.h"
00066 #include "llfirstuse.h"
00067 #include "llfloater.h"
00068 #include "llfloateractivespeakers.h"
00069 #include "llfloateravatarinfo.h"
00070 #include "llfloaterbuildoptions.h"
00071 #include "llfloatercamera.h"
00072 #include "llfloaterchat.h"
00073 #include "llfloatercustomize.h"
00074 #include "llfloaterdirectory.h"
00075 #include "llfloatergroupinfo.h"
00076 #include "llfloatergroups.h"
00077 #include "llfloatermap.h"
00078 #include "llfloatermute.h"
00079 #include "llfloatersnapshot.h"
00080 #include "llfloatertools.h"
00081 #include "llfloaterworldmap.h"
00082 #include "llgroupmgr.h"
00083 #include "llhudeffectlookat.h"
00084 #include "llhudmanager.h"
00085 #include "llinventorymodel.h"
00086 #include "llinventoryview.h"
00087 #include "lljoystickbutton.h"
00088 #include "llmenugl.h"
00089 #include "llmorphview.h"
00090 #include "llmoveview.h"
00091 #include "llnotify.h"
00092 #include "llquantize.h"
00093 #include "llselectmgr.h"
00094 #include "llsky.h"
00095 #include "llrendersphere.h"
00096 #include "llstatusbar.h"
00097 #include "llimview.h"
00098 #include "lltool.h"
00099 #include "lltoolfocus.h"
00100 #include "lltoolgrab.h"
00101 #include "lltoolmgr.h"
00102 #include "lltoolpie.h"
00103 #include "lltoolview.h"
00104 #include "llui.h"                       // for make_ui_sound
00105 #include "llurldispatcher.h"
00106 #include "llviewercamera.h"
00107 #include "llviewerinventory.h"
00108 #include "llviewermenu.h"
00109 #include "llviewernetwork.h"
00110 #include "llviewerobjectlist.h"
00111 #include "llviewerparcelmgr.h"
00112 #include "llviewerparceloverlay.h"
00113 #include "llviewerregion.h"
00114 #include "llviewerstats.h"
00115 #include "llviewerwindow.h"
00116 #include "llviewerdisplay.h"
00117 #include "llvoavatar.h"
00118 #include "llvoground.h"
00119 #include "llvosky.h"
00120 #include "llwearable.h"
00121 #include "llwearablelist.h"
00122 #include "llworld.h"
00123 #include "llworldmap.h"
00124 #include "pipeline.h"
00125 #include "roles_constants.h"
00126 #include "llviewercontrol.h"
00127 #include "llappviewer.h"
00128 #include "llvoiceclient.h"
00129 
00130 // Ventrella
00131 #include "llfollowcam.h"
00132 // end Ventrella
00133 
00134 extern LLMenuBarGL* gMenuBarView;
00135 extern U8 gLastPickAlpha;
00136 
00137 //drone wandering constants
00138 const F32 MAX_WANDER_TIME = 20.f;                                               // seconds
00139 const F32 MAX_HEADING_HALF_ERROR = 0.2f;                                // radians
00140 const F32 WANDER_MAX_SLEW_RATE = 2.f * DEG_TO_RAD;              // radians / frame
00141 const F32 WANDER_TARGET_MIN_DISTANCE = 10.f;                    // meters
00142 
00143 // Autopilot constants
00144 const F32 AUTOPILOT_HEADING_HALF_ERROR = 10.f * DEG_TO_RAD;     // radians
00145 const F32 AUTOPILOT_MAX_SLEW_RATE = 1.f * DEG_TO_RAD;           // radians / frame
00146 const F32 AUTOPILOT_STOP_DISTANCE = 2.f;                                        // meters
00147 const F32 AUTOPILOT_HEIGHT_ADJUST_DISTANCE = 8.f;                       // meters
00148 const F32 AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND = 1.f; // meters
00149 const F32 AUTOPILOT_MAX_TIME_NO_PROGRESS = 1.5f;                // seconds
00150 
00151 // face editing constants
00152 const LLVector3d FACE_EDIT_CAMERA_OFFSET(0.4f, -0.05f, 0.07f);
00153 const LLVector3d FACE_EDIT_TARGET_OFFSET(0.f, 0.f, 0.05f);
00154 
00155 // Mousewheel camera zoom
00156 const F32 MIN_ZOOM_FRACTION = 0.25f;
00157 const F32 INITIAL_ZOOM_FRACTION = 1.f;
00158 const F32 MAX_ZOOM_FRACTION = 8.f;
00159 const F32 METERS_PER_WHEEL_CLICK = 1.f;
00160 
00161 const F32 MAX_TIME_DELTA = 1.f;
00162 
00163 const F32 CAMERA_ZOOM_HALF_LIFE = 0.07f;        // seconds
00164 const F32 FOV_ZOOM_HALF_LIFE = 0.07f;   // seconds
00165 
00166 const F32 CAMERA_FOCUS_HALF_LIFE = 0.f;//0.02f;
00167 const F32 CAMERA_LAG_HALF_LIFE = 0.25f;
00168 const F32 MIN_CAMERA_LAG = 0.5f;
00169 const F32 MAX_CAMERA_LAG = 5.f;
00170 
00171 const F32 CAMERA_COLLIDE_EPSILON = 0.1f;
00172 const F32 MIN_CAMERA_DISTANCE = 0.1f;
00173 const F32 AVATAR_ZOOM_MIN_X_FACTOR = 0.55f;
00174 const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.7f;
00175 const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 1.15f;
00176 
00177 const F32 MAX_CAMERA_DISTANCE_FROM_AGENT = 50.f;
00178 
00179 const F32 MAX_CAMERA_SMOOTH_DISTANCE = 20.0f;
00180 
00181 const F32 HEAD_BUFFER_SIZE = 0.3f;
00182 const F32 CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP = 0.2f;
00183 
00184 const F32 LAND_MIN_ZOOM = 0.15f;
00185 const F32 AVATAR_MIN_ZOOM = 0.5f;
00186 const F32 OBJECT_MIN_ZOOM = 0.02f;
00187 
00188 const F32 APPEARANCE_MIN_ZOOM = 0.39f;
00189 const F32 APPEARANCE_MAX_ZOOM = 8.f;
00190 
00191 // fidget constants
00192 const F32 MIN_FIDGET_TIME = 8.f; // seconds
00193 const F32 MAX_FIDGET_TIME = 20.f; // seconds
00194 
00195 const S32 MAX_NUM_CHAT_POSITIONS = 10;
00196 const F32 GROUND_TO_AIR_CAMERA_TRANSITION_TIME = 0.5f;
00197 const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f;
00198 
00199 const F32 MAX_VELOCITY_AUTO_LAND_SQUARED = 4.f * 4.f;
00200 
00201 const F32 MAX_FOCUS_OFFSET = 20.f;
00202 
00203 const F32 OBJECT_EXTENTS_PADDING = 0.5f;
00204 
00205 const F32 MIN_RADIUS_ALPHA_SIZZLE = 0.5f;
00206 
00207 const F64 CHAT_AGE_FAST_RATE = 3.0;
00208 
00209 const S32 MAX_WEARABLES_PER_LAYERSET = 7;
00210 
00211 const EWearableType WEARABLE_BAKE_TEXTURE_MAP[BAKED_TEXTURE_COUNT][MAX_WEARABLES_PER_LAYERSET] = 
00212 {
00213         { WT_SHAPE,     WT_SKIN,        WT_HAIR,        WT_INVALID,     WT_INVALID,     WT_INVALID,             WT_INVALID    },        // TEX_HEAD_BAKED
00214         { WT_SHAPE, WT_SKIN,    WT_SHIRT,       WT_JACKET,      WT_GLOVES,      WT_UNDERSHIRT,  WT_INVALID        },    // TEX_UPPER_BAKED
00215         { WT_SHAPE, WT_SKIN,    WT_PANTS,       WT_SHOES,       WT_SOCKS,       WT_JACKET,              WT_UNDERPANTS },        // TEX_LOWER_BAKED
00216         { WT_EYES,      WT_INVALID,     WT_INVALID,     WT_INVALID,     WT_INVALID,     WT_INVALID,             WT_INVALID    },        // TEX_EYES_BAKED
00217         { WT_SKIRT,     WT_INVALID,     WT_INVALID,     WT_INVALID,     WT_INVALID,     WT_INVALID,             WT_INVALID    }         // TEX_SKIRT_BAKED
00218 };
00219 
00220 const LLUUID BAKED_TEXTURE_HASH[BAKED_TEXTURE_COUNT] = 
00221 {
00222         LLUUID("18ded8d6-bcfc-e415-8539-944c0f5ea7a6"),
00223         LLUUID("338c29e3-3024-4dbb-998d-7c04cf4fa88f"),
00224         LLUUID("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f"),
00225         LLUUID("b2cf28af-b840-1071-3c6a-78085d8128b5"),
00226         LLUUID("ea800387-ea1a-14e0-56cb-24f2022f969a")
00227 };
00228 
00229 // The agent instance.
00230 LLAgent gAgent;
00231 
00232 //
00233 // Statics
00234 //
00235 BOOL LLAgent::sDebugDisplayTarget = FALSE;
00236 
00237 const F32 LLAgent::TYPING_TIMEOUT_SECS = 5.f;
00238 
00239 std::map<LLString, LLString> LLAgent::sTeleportErrorMessages;
00240 std::map<LLString, LLString> LLAgent::sTeleportProgressMessages;
00241 
00242 class LLAgentFriendObserver : public LLFriendObserver
00243 {
00244 public:
00245         LLAgentFriendObserver() {}
00246         virtual ~LLAgentFriendObserver() {}
00247         virtual void changed(U32 mask);
00248 };
00249 
00250 void LLAgentFriendObserver::changed(U32 mask)
00251 {
00252         // if there's a change we're interested in.
00253         if((mask & (LLFriendObserver::POWERS)) != 0)
00254         {
00255                 gAgent.friendsChanged();
00256         }
00257 }
00258 
00259 // ************************************************************
00260 // Enabled this definition to compile a 'hacked' viewer that
00261 // locally believes the end user has godlike powers.
00262 // #define HACKED_GODLIKE_VIEWER
00263 // For a toggled version, see viewer.h for the
00264 // TOGGLE_HACKED_GODLIKE_VIEWER define, instead.
00265 // ************************************************************
00266 
00267 // Constructors and Destructors
00268 
00269 // JC - Please try to make this order match the order in the header
00270 // file.  Otherwise it's hard to find variables that aren't initialized.
00271 //-----------------------------------------------------------------------------
00272 // LLAgent()
00273 //-----------------------------------------------------------------------------
00274 LLAgent::LLAgent()
00275 :       mDrawDistance( DEFAULT_FAR_PLANE ),
00276 
00277         mDoubleTapRunTimer(),
00278         mDoubleTapRunMode(DOUBLETAP_NONE),
00279 
00280         mbAlwaysRun(false),
00281         mbRunning(false),
00282 
00283         mAccess(SIM_ACCESS_PG),
00284         mGroupPowers(0),
00285         mGroupID(),
00286         //mGroupInsigniaID(),
00287         mMapOriginX(0),
00288         mMapOriginY(0),
00289         mMapWidth(0),
00290         mMapHeight(0),
00291         mLookAt(NULL),
00292         mPointAt(NULL),
00293         mInitialized(FALSE),
00294         mNumPendingQueries(0),
00295         mForceMouselook(FALSE),
00296         mTeleportState( TELEPORT_NONE ),
00297         mRegionp(NULL),
00298 
00299         mAgentOriginGlobal(),
00300         mPositionGlobal(),
00301 
00302         mDistanceTraveled(0),
00303         mLastPositionGlobal(LLVector3d::zero),
00304 
00305         mAvatarObject(NULL),
00306 
00307         mRenderState(0),
00308         mTypingTimer(),
00309 
00310         mCameraMode( CAMERA_MODE_THIRD_PERSON ),
00311         mLastCameraMode( CAMERA_MODE_THIRD_PERSON ),
00312         mViewsPushed(FALSE),
00313 
00314         mShowAvatar(TRUE),
00315         
00316         mCameraAnimating( FALSE ),
00317         mAnimationCameraStartGlobal(),
00318         mAnimationFocusStartGlobal(),
00319         mAnimationTimer(),
00320         mAnimationDuration(0.33f),
00321         mCameraFOVZoomFactor(0.f),
00322         mCameraCurrentFOVZoomFactor(0.f),
00323         mCameraFocusOffset(),
00324         mCameraOffsetDefault(),
00325 //      mCameraOffsetNorm(),
00326         mCameraCollidePlane(),
00327         mCurrentCameraDistance(2.f),            // meters, set in init()
00328         mTargetCameraDistance(2.f),
00329         mCameraZoomFraction(1.f),                       // deprecated
00330         mThirdPersonHeadOffset(0.f, 0.f, 1.f),
00331         mSitCameraEnabled(FALSE),
00332         mFocusOnAvatar(TRUE),
00333         mFocusGlobal(),
00334         mFocusTargetGlobal(),
00335         mFocusObject(NULL),
00336         mFocusObjectOffset(),
00337         mFocusDotRadius( 0.1f ),                        // meters
00338         mTrackFocusObject(TRUE),
00339         mCameraSmoothingLastPositionGlobal(),
00340         mCameraSmoothingLastPositionAgent(),
00341 
00342         mFrameAgent(),
00343 
00344         mCrouching(FALSE),
00345         mIsBusy(FALSE),
00346 
00347         // movement keys below
00348 
00349         mControlFlags(0x00000000),
00350         mbFlagsDirty(FALSE),
00351         mbFlagsNeedReset(FALSE),
00352 
00353         mbJump(FALSE),
00354 
00355         mAutoPilot(FALSE),
00356         mAutoPilotFlyOnStop(FALSE),
00357         mAutoPilotTargetGlobal(),
00358         mAutoPilotStopDistance(1.f),
00359         mAutoPilotUseRotation(FALSE),
00360         mAutoPilotTargetFacing(LLVector3::zero),
00361         mAutoPilotTargetDist(0.f),
00362         mAutoPilotFinishedCallback(NULL),
00363         mAutoPilotCallbackData(NULL),
00364         
00365 
00366         mEffectColor(0.f, 1.f, 1.f, 1.f),
00367         mHaveHomePosition(FALSE),
00368         mHomeRegionHandle( 0 ),
00369         mNearChatRadius(CHAT_NORMAL_RADIUS / 2.f),
00370         mGodLevel( GOD_NOT ),
00371 
00372 
00373         mNextFidgetTime(0.f),
00374         mCurrentFidget(0),
00375         mFirstLogin(FALSE),
00376         mGenderChosen(FALSE),
00377         mAgentWearablesUpdateSerialNum(0),
00378         mWearablesLoaded(FALSE),
00379         mTextureCacheQueryID(0),
00380         mAppearanceSerialNum(0)
00381 {
00382 
00383         U32 i;
00384         for (i = 0; i < TOTAL_CONTROLS; i++)
00385         {
00386                 mControlsTakenCount[i] = 0;
00387                 mControlsTakenPassedOnCount[i] = 0;
00388         }
00389 
00390         // Initialize movement keys
00391         mAtKey                          = 0;    // Either 1, 0, or -1... indicates that movement-key is pressed
00392         mWalkKey                        = 0;    // like AtKey, but causes less forward thrust
00393         mLeftKey                        = 0;
00394         mUpKey                          = 0;
00395         mYawKey                         = 0.f;
00396         mPitchKey                       = 0;
00397 
00398         mOrbitLeftKey           = 0.f;
00399         mOrbitRightKey          = 0.f;
00400         mOrbitUpKey                     = 0.f;
00401         mOrbitDownKey           = 0.f;
00402         mOrbitInKey                     = 0.f;
00403         mOrbitOutKey            = 0.f;
00404 
00405         mPanUpKey                       = 0.f;
00406         mPanDownKey                     = 0.f;
00407         mPanLeftKey                     = 0.f;
00408         mPanRightKey            = 0.f;
00409         mPanInKey                       = 0.f;
00410         mPanOutKey                      = 0.f;
00411 
00412         mActiveCacheQueries = new S32[BAKED_TEXTURE_COUNT];
00413         for (i = 0; i < (U32)BAKED_TEXTURE_COUNT; i++)
00414         {
00415                 mActiveCacheQueries[i] = 0;
00416         }
00417 
00418         //Ventrella
00419         mCameraUpVector = LLVector3::z_axis;// default is straight up 
00420         mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
00421         //end ventrella
00422 
00423         mCustomAnim = FALSE ;
00424 }
00425 
00426 // Requires gSavedSettings to be initialized.
00427 //-----------------------------------------------------------------------------
00428 // init()
00429 //-----------------------------------------------------------------------------
00430 void LLAgent::init()
00431 {
00432         mDrawDistance = gSavedSettings.getF32("RenderFarClip");
00433 
00434         // *Note: this is where LLViewerCamera::getInstance() used to be constructed.
00435 
00436         LLViewerCamera::getInstance()->setView(DEFAULT_FIELD_OF_VIEW);
00437         // Leave at 0.1 meters until we have real near clip management
00438         LLViewerCamera::getInstance()->setNear(0.1f);
00439         LLViewerCamera::getInstance()->setFar(mDrawDistance);                   // if you want to change camera settings, do so in camera.h
00440         LLViewerCamera::getInstance()->setAspect( gViewerWindow->getDisplayAspectRatio() );             // default, overridden in LLViewerWindow::reshape
00441         LLViewerCamera::getInstance()->setViewHeightInPixels(768);                      // default, overridden in LLViewerWindow::reshape
00442 
00443         setFlying( gSavedSettings.getBOOL("FlyingAtExit") );
00444 
00445         mCameraFocusOffsetTarget = LLVector4(gSavedSettings.getVector3("CameraOffsetBuild"));
00446         mCameraOffsetDefault = gSavedSettings.getVector3("CameraOffsetDefault");
00447 //      mCameraOffsetNorm = mCameraOffsetDefault;
00448 //      mCameraOffsetNorm.normVec();
00449         mCameraCollidePlane.clearVec();
00450         mCurrentCameraDistance = mCameraOffsetDefault.magVec();
00451         mTargetCameraDistance = mCurrentCameraDistance;
00452         mCameraZoomFraction = 1.f;
00453         mTrackFocusObject = gSavedSettings.getBOOL("TrackFocusObject");
00454 
00455 //      LLDebugVarMessageBox::show("Camera Lag", &CAMERA_FOCUS_HALF_LIFE, 0.5f, 0.01f);
00456 
00457         mEffectColor = gSavedSettings.getColor4("EffectColor");
00458         
00459         mInitialized = TRUE;
00460 }
00461 
00462 //-----------------------------------------------------------------------------
00463 // cleanup()
00464 //-----------------------------------------------------------------------------
00465 void LLAgent::cleanup()
00466 {
00467         setSitCamera(LLUUID::null);
00468         mAvatarObject = NULL;
00469         mLookAt = NULL;
00470         mPointAt = NULL;
00471         mRegionp = NULL;
00472         setFocusObject(NULL);
00473 }
00474 
00475 //-----------------------------------------------------------------------------
00476 // LLAgent()
00477 //-----------------------------------------------------------------------------
00478 LLAgent::~LLAgent()
00479 {
00480         cleanup();
00481 
00482         delete [] mActiveCacheQueries;
00483         mActiveCacheQueries = NULL;
00484 
00485         // *Note: this is where LLViewerCamera::getInstance() used to be deleted.
00486 }
00487 
00488 // Change camera back to third person, stop the autopilot,
00489 // deselect stuff, etc.
00490 //-----------------------------------------------------------------------------
00491 // resetView()
00492 //-----------------------------------------------------------------------------
00493 void LLAgent::resetView(BOOL reset_camera)
00494 {
00495         if (mAutoPilot)
00496         {
00497                 stopAutoPilot(TRUE);
00498         }
00499 
00500         if (!gNoRender)
00501         {
00502                 LLSelectMgr::getInstance()->unhighlightAll();
00503 
00504                 // By popular request, keep land selection while walking around. JC
00505                 // LLViewerParcelMgr::getInstance()->deselectLand();
00506 
00507                 // force deselect when walking and attachment is selected
00508                 // this is so people don't wig out when their avatar moves without animating
00509                 if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
00510                 {
00511                         LLSelectMgr::getInstance()->deselectAll();
00512                 }
00513 
00514                 // Hide all popup menus
00515                 gMenuHolder->hideMenus();
00516         }
00517 
00518         if (reset_camera && !gSavedSettings.getBOOL("FreezeTime"))
00519         {
00520                 if (!gViewerWindow->getLeftMouseDown() && cameraThirdPerson())
00521                 {
00522                         // leaving mouse-steer mode
00523                         LLVector3 agent_at_axis = getAtAxis();
00524                         agent_at_axis -= projected_vec(agent_at_axis, getReferenceUpVector());
00525                         agent_at_axis.normVec();
00526                         gAgent.resetAxes(lerp(getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f)));
00527                 }
00528 
00529                 setFocusOnAvatar(TRUE, ANIMATE);
00530         }
00531 
00532         if (mAvatarObject.notNull())
00533         {
00534                 mAvatarObject->mHUDTargetZoom = 1.f;
00535         }
00536 }
00537 
00538 // Handle any actions that need to be performed when the main app gains focus
00539 // (such as through alt-tab).
00540 //-----------------------------------------------------------------------------
00541 // onAppFocusGained()
00542 //-----------------------------------------------------------------------------
00543 void LLAgent::onAppFocusGained()
00544 {
00545         if (CAMERA_MODE_MOUSELOOK == mCameraMode)
00546         {
00547                 changeCameraToDefault();
00548                 LLToolMgr::getInstance()->clearSavedTool();
00549         }
00550 }
00551 
00552 
00553 void LLAgent::ageChat()
00554 {
00555         if (mAvatarObject)
00556         {
00557                 // get amount of time since I last chatted
00558                 F64 elapsed_time = (F64)mAvatarObject->mChatTimer.getElapsedTimeF32();
00559                 // add in frame time * 3 (so it ages 4x)
00560                 mAvatarObject->mChatTimer.setAge(elapsed_time + (F64)gFrameDTClamped * (CHAT_AGE_FAST_RATE - 1.0));
00561         }
00562 }
00563 
00564 // Allow camera to be moved somewhere other than behind avatar.
00565 //-----------------------------------------------------------------------------
00566 // unlockView()
00567 //-----------------------------------------------------------------------------
00568 void LLAgent::unlockView()
00569 {
00570         if (getFocusOnAvatar())
00571         {
00572                 if (mAvatarObject)
00573                 {
00574                         setFocusGlobal( LLVector3d::zero, mAvatarObject->mID );
00575                 }
00576                 setFocusOnAvatar(FALSE, FALSE); // no animation
00577         }
00578 }
00579 
00580 
00581 //-----------------------------------------------------------------------------
00582 // moveAt()
00583 //-----------------------------------------------------------------------------
00584 void LLAgent::moveAt(S32 direction, bool reset)
00585 {
00586         // age chat timer so it fades more quickly when you are intentionally moving
00587         ageChat();
00588 
00589         setKey(direction, mAtKey);
00590 
00591         if (direction > 0)
00592         {
00593                 setControlFlags(AGENT_CONTROL_AT_POS | AGENT_CONTROL_FAST_AT);
00594         }
00595         else if (direction < 0)
00596         {
00597                 setControlFlags(AGENT_CONTROL_AT_NEG | AGENT_CONTROL_FAST_AT);
00598         }
00599 
00600         if (reset)
00601         {
00602                 resetView();
00603         }
00604 }
00605 
00606 //-----------------------------------------------------------------------------
00607 // moveAtNudge()
00608 //-----------------------------------------------------------------------------
00609 void LLAgent::moveAtNudge(S32 direction)
00610 {
00611         // age chat timer so it fades more quickly when you are intentionally moving
00612         ageChat();
00613 
00614         setKey(direction, mWalkKey);
00615 
00616         if (direction > 0)
00617         {
00618                 setControlFlags(AGENT_CONTROL_NUDGE_AT_POS);
00619         }
00620         else if (direction < 0)
00621         {
00622                 setControlFlags(AGENT_CONTROL_NUDGE_AT_NEG);
00623         }
00624 
00625         resetView();
00626 }
00627 
00628 //-----------------------------------------------------------------------------
00629 // moveLeft()
00630 //-----------------------------------------------------------------------------
00631 void LLAgent::moveLeft(S32 direction)
00632 {
00633         // age chat timer so it fades more quickly when you are intentionally moving
00634         ageChat();
00635 
00636         setKey(direction, mLeftKey);
00637 
00638         if (direction > 0)
00639         {
00640                 setControlFlags(AGENT_CONTROL_LEFT_POS | AGENT_CONTROL_FAST_LEFT);
00641         }
00642         else if (direction < 0)
00643         {
00644                 setControlFlags(AGENT_CONTROL_LEFT_NEG | AGENT_CONTROL_FAST_LEFT);
00645         }
00646 
00647         resetView();
00648 }
00649 
00650 //-----------------------------------------------------------------------------
00651 // moveLeftNudge()
00652 //-----------------------------------------------------------------------------
00653 void LLAgent::moveLeftNudge(S32 direction)
00654 {
00655         // age chat timer so it fades more quickly when you are intentionally moving
00656         ageChat();
00657 
00658         setKey(direction, mLeftKey);
00659 
00660         if (direction > 0)
00661         {
00662                 setControlFlags(AGENT_CONTROL_NUDGE_LEFT_POS);
00663         }
00664         else if (direction < 0)
00665         {
00666                 setControlFlags(AGENT_CONTROL_NUDGE_LEFT_NEG);
00667         }
00668 
00669         resetView();
00670 }
00671 
00672 //-----------------------------------------------------------------------------
00673 // moveUp()
00674 //-----------------------------------------------------------------------------
00675 void LLAgent::moveUp(S32 direction)
00676 {
00677         // age chat timer so it fades more quickly when you are intentionally moving
00678         ageChat();
00679 
00680         setKey(direction, mUpKey);
00681 
00682         if (direction > 0)
00683         {
00684                 setControlFlags(AGENT_CONTROL_UP_POS | AGENT_CONTROL_FAST_UP);
00685         }
00686         else if (direction < 0)
00687         {
00688                 setControlFlags(AGENT_CONTROL_UP_NEG | AGENT_CONTROL_FAST_UP);
00689         }
00690 
00691         resetView();
00692 }
00693 
00694 //-----------------------------------------------------------------------------
00695 // moveYaw()
00696 //-----------------------------------------------------------------------------
00697 void LLAgent::moveYaw(F32 mag, bool reset_view)
00698 {
00699         mYawKey = mag;
00700 
00701         if (mag > 0)
00702         {
00703                 setControlFlags(AGENT_CONTROL_YAW_POS);
00704         }
00705         else if (mag < 0)
00706         {
00707                 setControlFlags(AGENT_CONTROL_YAW_NEG);
00708         }
00709 
00710     if (reset_view)
00711         {
00712         resetView();
00713         }
00714 }
00715 
00716 //-----------------------------------------------------------------------------
00717 // movePitch()
00718 //-----------------------------------------------------------------------------
00719 void LLAgent::movePitch(S32 direction)
00720 {
00721         setKey(direction, mPitchKey);
00722 
00723         if (direction > 0)
00724         {
00725                 setControlFlags(AGENT_CONTROL_PITCH_POS );
00726         }
00727         else if (direction < 0)
00728         {
00729                 setControlFlags(AGENT_CONTROL_PITCH_NEG);
00730         }
00731 }
00732 
00733 
00734 // Does this parcel allow you to fly?
00735 BOOL LLAgent::canFly()
00736 {
00737         if (isGodlike()) return TRUE;
00738 
00739         LLViewerRegion* regionp = getRegion();
00740         if (regionp && regionp->getBlockFly()) return FALSE;
00741         
00742         LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
00743         if (!parcel) return FALSE;
00744 
00745         // Allow owners to fly on their own land.
00746         if (LLViewerParcelMgr::isParcelOwnedByAgent(parcel, GP_LAND_ALLOW_FLY))
00747         {
00748                 return TRUE;
00749         }
00750 
00751         return parcel->getAllowFly();
00752 }
00753 
00754 
00755 //-----------------------------------------------------------------------------
00756 // setFlying()
00757 //-----------------------------------------------------------------------------
00758 void LLAgent::setFlying(BOOL fly)
00759 {
00760         if (mAvatarObject.notNull())
00761         {
00762                 if(mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end())
00763                 {
00764                         return;
00765                 }
00766 
00767                 // don't allow taking off while sitting
00768                 if (fly && mAvatarObject->mIsSitting)
00769                 {
00770                         return;
00771                 }
00772         }
00773 
00774         if (fly)
00775         {
00776                 BOOL was_flying = getFlying();
00777                 if (!canFly() && !was_flying)
00778                 {
00779                         // parcel doesn't let you start fly
00780                         // gods can always fly
00781                         // and it's OK if you're already flying
00782                         make_ui_sound("UISndBadKeystroke");
00783                         return;
00784                 }
00785                 if( !was_flying )
00786                 {
00787                         LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT);
00788                 }
00789                 setControlFlags(AGENT_CONTROL_FLY);
00790                 gSavedSettings.setBOOL("FlyBtnState", TRUE);
00791         }
00792         else
00793         {
00794                 clearControlFlags(AGENT_CONTROL_FLY);
00795                 gSavedSettings.setBOOL("FlyBtnState", FALSE);
00796         }
00797         mbFlagsDirty = TRUE;
00798 }
00799 
00800 
00801 // UI based mechanism of setting fly state
00802 //-----------------------------------------------------------------------------
00803 // toggleFlying()
00804 //-----------------------------------------------------------------------------
00805 void LLAgent::toggleFlying()
00806 {
00807         BOOL fly = !(mControlFlags & AGENT_CONTROL_FLY);
00808 
00809         setFlying( fly );
00810         resetView();
00811 }
00812 
00813 
00814 //-----------------------------------------------------------------------------
00815 // setRegion()
00816 //-----------------------------------------------------------------------------
00817 void LLAgent::setRegion(LLViewerRegion *regionp)
00818 {
00819         llassert(regionp);
00820         if (mRegionp != regionp)
00821         {
00822                 // JC - Avoid this, causes out-of-bounds array write deep within
00823                 // Windows.
00824                 // char host_name[MAX_STRING];
00825                 // regionp->getHost().getHostName(host_name, MAX_STRING);
00826 
00827                 char ip[MAX_STRING];            /*Flawfinder: ignore*/
00828                 regionp->getHost().getString(ip, MAX_STRING);
00829                 llinfos << "Moving agent into region: " << regionp->getName()
00830                                 << " located at " << ip << llendl;
00831                 if (mRegionp)
00832                 {
00833                         // We've changed regions, we're now going to change our agent coordinate frame.
00834                         mAgentOriginGlobal = regionp->getOriginGlobal();
00835                         LLVector3d agent_offset_global = mRegionp->getOriginGlobal();
00836 
00837                         LLVector3 delta;
00838                         delta.setVec(regionp->getOriginGlobal() - mRegionp->getOriginGlobal());
00839 
00840                         setPositionAgent(getPositionAgent() - delta);
00841 
00842                         LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin();
00843                         LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta);
00844 
00845                         // Update all of the regions.
00846                         LLWorld::getInstance()->updateAgentOffset(agent_offset_global);
00847 
00848                         // Hack to keep sky in the agent's region, otherwise it may get deleted - DJS 08/02/02
00849                         // *TODO: possibly refactor into gSky->setAgentRegion(regionp)? -Brad
00850                         if (gSky.mVOSkyp)
00851                         {
00852                                 gSky.mVOSkyp->setRegion(regionp);
00853                         }
00854                         if (gSky.mVOGroundp)
00855                         {
00856                                 gSky.mVOGroundp->setRegion(regionp);
00857                         }
00858 
00859                 }
00860                 else
00861                 {
00862                         // First time initialization.
00863                         // We've changed regions, we're now going to change our agent coordinate frame.
00864                         mAgentOriginGlobal = regionp->getOriginGlobal();
00865 
00866                         LLVector3 delta;
00867                         delta.setVec(regionp->getOriginGlobal());
00868 
00869                         setPositionAgent(getPositionAgent() - delta);
00870                         LLVector3 camera_position_agent = LLViewerCamera::getInstance()->getOrigin();
00871                         LLViewerCamera::getInstance()->setOrigin(camera_position_agent - delta);
00872 
00873                         // Update all of the regions.
00874                         LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal);
00875                 }
00876         }
00877         mRegionp = regionp;
00878 
00879         // Must shift hole-covering water object locations because local
00880         // coordinate frame changed.
00881         LLWorld::getInstance()->updateWaterObjects();
00882 
00883         // keep a list of regions we've been too
00884         // this is just an interesting stat, logged at the dataserver
00885         // we could trake this at the dataserver side, but that's harder
00886         U64 handle = regionp->getHandle();
00887         mRegionsVisited.insert(handle);
00888 
00889         LLSelectMgr::getInstance()->updateSelectionCenter();
00890 }
00891 
00892 
00893 //-----------------------------------------------------------------------------
00894 // getRegion()
00895 //-----------------------------------------------------------------------------
00896 LLViewerRegion *LLAgent::getRegion() const
00897 {
00898         return mRegionp;
00899 }
00900 
00901 
00902 const LLHost& LLAgent::getRegionHost() const
00903 {
00904         if (mRegionp)
00905         {
00906                 return mRegionp->getHost();
00907         }
00908         else
00909         {
00910                 return LLHost::invalid;
00911         }
00912 }
00913 
00914 //-----------------------------------------------------------------------------
00915 // getSLURL()
00916 // returns empty() if getRegion() == NULL
00917 //-----------------------------------------------------------------------------
00918 std::string LLAgent::getSLURL() const
00919 {
00920         std::string slurl;
00921         LLViewerRegion *regionp = getRegion();
00922         if (regionp)
00923         {
00924                 LLVector3d agentPos = getPositionGlobal();
00925                 S32 x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) );
00926                 S32 y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
00927                 S32 z = llround( (F32)agentPos.mdV[VZ] );
00928                 slurl = LLURLDispatcher::buildSLURL(regionp->getName(), x, y, z);
00929         }
00930         return slurl;
00931 }
00932 
00933 //-----------------------------------------------------------------------------
00934 // inPrelude()
00935 //-----------------------------------------------------------------------------
00936 BOOL LLAgent::inPrelude()
00937 {
00938         return mRegionp && mRegionp->isPrelude();
00939 }
00940 
00941 
00942 //-----------------------------------------------------------------------------
00943 // canManageEstate()
00944 //-----------------------------------------------------------------------------
00945 
00946 BOOL LLAgent::canManageEstate() const
00947 {
00948         return mRegionp && mRegionp->canManageEstate();
00949 }
00950 
00951 //-----------------------------------------------------------------------------
00952 // sendMessage()
00953 //-----------------------------------------------------------------------------
00954 void LLAgent::sendMessage()
00955 {
00956         if (gDisconnected)
00957         {
00958                 llwarns << "Trying to send message when disconnected!" << llendl;
00959                 return;
00960         }
00961         if (!mRegionp)
00962         {
00963                 llerrs << "No region for agent yet!" << llendl;
00964         }
00965         gMessageSystem->sendMessage(mRegionp->getHost());
00966 }
00967 
00968 
00969 //-----------------------------------------------------------------------------
00970 // sendReliableMessage()
00971 //-----------------------------------------------------------------------------
00972 void LLAgent::sendReliableMessage()
00973 {
00974         if (gDisconnected)
00975         {
00976                 lldebugs << "Trying to send message when disconnected!" << llendl;
00977                 return;
00978         }
00979         if (!mRegionp)
00980         {
00981                 lldebugs << "LLAgent::sendReliableMessage No region for agent yet, not sending message!" << llendl;
00982                 return;
00983         }
00984         gMessageSystem->sendReliable(mRegionp->getHost());
00985 }
00986 
00987 //-----------------------------------------------------------------------------
00988 // getVelocity()
00989 //-----------------------------------------------------------------------------
00990 LLVector3 LLAgent::getVelocity() const
00991 {
00992         if (mAvatarObject)
00993         {
00994                 return mAvatarObject->getVelocity();
00995         }
00996         else
00997         {
00998                 return LLVector3::zero;
00999         }
01000 }
01001 
01002 
01003 //-----------------------------------------------------------------------------
01004 // setPositionAgent()
01005 //-----------------------------------------------------------------------------
01006 void LLAgent::setPositionAgent(const LLVector3 &pos_agent)
01007 {
01008         if (!pos_agent.isFinite())
01009         {
01010                 llerrs << "setPositionAgent is not a number" << llendl;
01011         }
01012 
01013         if (!mAvatarObject.isNull() && mAvatarObject->getParent())
01014         {
01015                 LLVector3 pos_agent_sitting;
01016                 LLVector3d pos_agent_d;
01017                 LLViewerObject *parent = (LLViewerObject*)mAvatarObject->getParent();
01018 
01019                 pos_agent_sitting = mAvatarObject->getPosition() * parent->getRotation() + parent->getPositionAgent();
01020                 pos_agent_d.setVec(pos_agent_sitting);
01021 
01022                 mFrameAgent.setOrigin(pos_agent_sitting);
01023                 mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
01024         }
01025         else
01026         {
01027                 mFrameAgent.setOrigin(pos_agent);
01028 
01029                 LLVector3d pos_agent_d;
01030                 pos_agent_d.setVec(pos_agent);
01031                 mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
01032         }
01033 }
01034 
01035 //-----------------------------------------------------------------------------
01036 // slamLookAt()
01037 //-----------------------------------------------------------------------------
01038 void LLAgent::slamLookAt(const LLVector3 &look_at)
01039 {
01040         LLVector3 look_at_norm = look_at;
01041         look_at_norm.mV[VZ] = 0.f;
01042         look_at_norm.normVec();
01043         resetAxes(look_at_norm);
01044 }
01045 
01046 //-----------------------------------------------------------------------------
01047 // getPositionGlobal()
01048 //-----------------------------------------------------------------------------
01049 const LLVector3d &LLAgent::getPositionGlobal() const
01050 {
01051         if (!mAvatarObject.isNull() && !mAvatarObject->mDrawable.isNull())
01052         {
01053                 mPositionGlobal = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());
01054         }
01055         else
01056         {
01057                 mPositionGlobal = getPosGlobalFromAgent(mFrameAgent.getOrigin());
01058         }
01059 
01060         return mPositionGlobal;
01061 }
01062 
01063 //-----------------------------------------------------------------------------
01064 // getPositionAgent()
01065 //-----------------------------------------------------------------------------
01066 const LLVector3 &LLAgent::getPositionAgent()
01067 {
01068         if(!mAvatarObject.isNull() && !mAvatarObject->mDrawable.isNull())
01069         {
01070                 mFrameAgent.setOrigin(mAvatarObject->getRenderPosition());      
01071         }
01072 
01073         return mFrameAgent.getOrigin();
01074 }
01075 
01076 //-----------------------------------------------------------------------------
01077 // getRegionsVisited()
01078 //-----------------------------------------------------------------------------
01079 S32 LLAgent::getRegionsVisited() const
01080 {
01081         return mRegionsVisited.size();
01082 }
01083 
01084 //-----------------------------------------------------------------------------
01085 // getDistanceTraveled()
01086 //-----------------------------------------------------------------------------
01087 F64 LLAgent::getDistanceTraveled() const
01088 {
01089         return mDistanceTraveled;
01090 }
01091 
01092 
01093 //-----------------------------------------------------------------------------
01094 // getPosAgentFromGlobal()
01095 //-----------------------------------------------------------------------------
01096 LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const
01097 {
01098         LLVector3 pos_agent;
01099         pos_agent.setVec(pos_global - mAgentOriginGlobal);
01100         return pos_agent;
01101 }
01102 
01103 
01104 //-----------------------------------------------------------------------------
01105 // getPosGlobalFromAgent()
01106 //-----------------------------------------------------------------------------
01107 LLVector3d LLAgent::getPosGlobalFromAgent(const LLVector3 &pos_agent) const
01108 {
01109         LLVector3d pos_agent_d;
01110         pos_agent_d.setVec(pos_agent);
01111         return pos_agent_d + mAgentOriginGlobal;
01112 }
01113 
01114 
01115 //-----------------------------------------------------------------------------
01116 // resetAxes()
01117 //-----------------------------------------------------------------------------
01118 void LLAgent::resetAxes()
01119 {
01120         mFrameAgent.resetAxes();
01121 }
01122 
01123 
01124 // Copied from LLCamera::setOriginAndLookAt
01125 // Look_at must be unit vector
01126 //-----------------------------------------------------------------------------
01127 // resetAxes()
01128 //-----------------------------------------------------------------------------
01129 void LLAgent::resetAxes(const LLVector3 &look_at)
01130 {
01131         LLVector3       skyward = getReferenceUpVector();
01132 
01133         // if look_at has zero length, fail
01134         // if look_at and skyward are parallel, fail
01135         //
01136         // Test both of these conditions with a cross product.
01137         LLVector3 cross(look_at % skyward);
01138         if (cross.isNull())
01139         {
01140                 llinfos << "LLAgent::resetAxes cross-product is zero" << llendl;
01141                 return;
01142         }
01143 
01144         // Make sure look_at and skyward are not parallel
01145         // and neither are zero length
01146         LLVector3 left(skyward % look_at);
01147         LLVector3 up(look_at % left);
01148 
01149         mFrameAgent.setAxes(look_at, left, up);
01150 }
01151 
01152 
01153 //-----------------------------------------------------------------------------
01154 // rotate()
01155 //-----------------------------------------------------------------------------
01156 void LLAgent::rotate(F32 angle, const LLVector3 &axis) 
01157 { 
01158         mFrameAgent.rotate(angle, axis); 
01159 }
01160 
01161 
01162 //-----------------------------------------------------------------------------
01163 // rotate()
01164 //-----------------------------------------------------------------------------
01165 void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z) 
01166 { 
01167         mFrameAgent.rotate(angle, x, y, z); 
01168 }
01169 
01170 
01171 //-----------------------------------------------------------------------------
01172 // rotate()
01173 //-----------------------------------------------------------------------------
01174 void LLAgent::rotate(const LLMatrix3 &matrix) 
01175 { 
01176         mFrameAgent.rotate(matrix); 
01177 }
01178 
01179 
01180 //-----------------------------------------------------------------------------
01181 // rotate()
01182 //-----------------------------------------------------------------------------
01183 void LLAgent::rotate(const LLQuaternion &quaternion) 
01184 { 
01185         mFrameAgent.rotate(quaternion); 
01186 }
01187 
01188 
01189 //-----------------------------------------------------------------------------
01190 // getReferenceUpVector()
01191 //-----------------------------------------------------------------------------
01192 LLVector3 LLAgent::getReferenceUpVector()
01193 {
01194         // this vector is in the coordinate frame of the avatar's parent object, or the world if none
01195         LLVector3 up_vector = LLVector3::z_axis;
01196         if (mAvatarObject.notNull() && 
01197                 mAvatarObject->getParent() &&
01198                 mAvatarObject->mDrawable.notNull())
01199         {
01200                 U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode;
01201                 // and in third person...
01202                 if (camera_mode == CAMERA_MODE_THIRD_PERSON)
01203                 {
01204                         // make the up vector point to the absolute +z axis
01205                         up_vector = up_vector * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
01206                 }
01207                 else if (camera_mode == CAMERA_MODE_MOUSELOOK)
01208                 {
01209                         // make the up vector point to the avatar's +z axis
01210                         up_vector = up_vector * mAvatarObject->mDrawable->getRotation();
01211                 }
01212         }
01213 
01214         return up_vector;
01215 }
01216 
01217 
01218 // Radians, positive is forward into ground
01219 //-----------------------------------------------------------------------------
01220 // pitch()
01221 //-----------------------------------------------------------------------------
01222 void LLAgent::pitch(F32 angle)
01223 {
01224         // don't let user pitch if pointed almost all the way down or up
01225         mFrameAgent.pitch(clampPitchToLimits(angle));
01226 }
01227 
01228 
01229 // Radians, positive is forward into ground
01230 //-----------------------------------------------------------------------------
01231 // clampPitchToLimits()
01232 //-----------------------------------------------------------------------------
01233 F32 LLAgent::clampPitchToLimits(F32 angle)
01234 {
01235         // A dot B = mag(A) * mag(B) * cos(angle between A and B)
01236         // so... cos(angle between A and B) = A dot B / mag(A) / mag(B)
01237         //                                  = A dot B for unit vectors
01238 
01239         LLVector3 skyward = getReferenceUpVector();
01240 
01241         F32                     look_down_limit;
01242         F32                     look_up_limit = 10.f * DEG_TO_RAD;
01243 
01244         F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward );
01245 
01246         if (mAvatarObject.notNull() && mAvatarObject->mIsSitting)
01247         {
01248                 look_down_limit = 130.f * DEG_TO_RAD;
01249         }
01250         else
01251         {
01252                 look_down_limit = 170.f * DEG_TO_RAD;
01253         }
01254 
01255         // clamp pitch to limits
01256         if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
01257         {
01258                 angle = look_down_limit - angle_from_skyward;
01259         }
01260         else if ((angle < 0.f) && (angle_from_skyward + angle < look_up_limit))
01261         {
01262                 angle = look_up_limit - angle_from_skyward;
01263         }
01264    
01265     return angle;
01266 }
01267 
01268 
01269 //-----------------------------------------------------------------------------
01270 // roll()
01271 //-----------------------------------------------------------------------------
01272 void LLAgent::roll(F32 angle)
01273 {
01274         mFrameAgent.roll(angle);
01275 }
01276 
01277 
01278 //-----------------------------------------------------------------------------
01279 // yaw()
01280 //-----------------------------------------------------------------------------
01281 void LLAgent::yaw(F32 angle)
01282 {
01283         if (!rotateGrabbed())
01284         {
01285                 mFrameAgent.rotate(angle, getReferenceUpVector());
01286         }
01287 }
01288 
01289 
01290 // Returns a quat that represents the rotation of the agent in the absolute frame
01291 //-----------------------------------------------------------------------------
01292 // getQuat()
01293 //-----------------------------------------------------------------------------
01294 LLQuaternion LLAgent::getQuat() const
01295 {
01296         return mFrameAgent.getQuaternion();
01297 }
01298 
01299 
01300 //-----------------------------------------------------------------------------
01301 // calcFocusOffset()
01302 //-----------------------------------------------------------------------------
01303 LLVector3d LLAgent::calcFocusOffset(LLViewerObject *object, S32 x, S32 y)
01304 {
01305         // calculate offset based on view direction
01306         BOOL is_avatar = object->isAvatar();
01307         LLMatrix4 obj_matrix = is_avatar  ? ((LLVOAvatar*)object)->mPelvisp->getWorldMatrix() : object->getRenderMatrix();
01308         LLQuaternion obj_rot = is_avatar  ? ((LLVOAvatar*)object)->mPelvisp->getWorldRotation() : object->getRenderRotation();
01309         LLVector3 obj_pos = is_avatar ? ((LLVOAvatar*)object)->mPelvisp->getWorldPosition() : object->getRenderPosition();
01310         LLQuaternion inv_obj_rot = ~obj_rot;
01311 
01312         LLVector3 obj_dir_abs = obj_pos - LLViewerCamera::getInstance()->getOrigin();
01313         obj_dir_abs.rotVec(inv_obj_rot);
01314         obj_dir_abs.normVec();
01315         obj_dir_abs.abs();
01316 
01317         LLVector3 object_extents = object->getScale();
01318         // make sure they object extents are non-zero
01319         object_extents.clamp(0.001f, F32_MAX);
01320         LLVector3 object_half_extents = object_extents * 0.5f;
01321 
01322         obj_dir_abs.mV[VX] = obj_dir_abs.mV[VX] / object_extents.mV[VX];
01323         obj_dir_abs.mV[VY] = obj_dir_abs.mV[VY] / object_extents.mV[VY];
01324         obj_dir_abs.mV[VZ] = obj_dir_abs.mV[VZ] / object_extents.mV[VZ];
01325 
01326         LLVector3 normal;
01327         if (obj_dir_abs.mV[VX] > obj_dir_abs.mV[VY] && obj_dir_abs.mV[VX] > obj_dir_abs.mV[VZ])
01328         {
01329                 normal.setVec(obj_matrix.getFwdRow4());
01330         }
01331         else if (obj_dir_abs.mV[VY] > obj_dir_abs.mV[VZ])
01332         {
01333                 normal.setVec(obj_matrix.getLeftRow4());
01334         }
01335         else
01336         {
01337                 normal.setVec(obj_matrix.getUpRow4());
01338         }
01339         normal.normVec();
01340 
01341         LLVector3d focus_pt_global;
01342         // RN: should we check return value for valid pick?
01343         gViewerWindow->mousePointOnPlaneGlobal(focus_pt_global, x, y, gAgent.getPosGlobalFromAgent(obj_pos), normal);
01344         LLVector3 focus_pt = gAgent.getPosAgentFromGlobal(focus_pt_global);
01345         // find vector from camera to focus point in object coordinates
01346         LLVector3 camera_focus_vec = focus_pt - LLViewerCamera::getInstance()->getOrigin();
01347         // convert to object-local space
01348         camera_focus_vec.rotVec(inv_obj_rot);
01349 
01350         // find vector from object origin to focus point in object coordinates
01351         LLVector3 focus_delta = focus_pt - obj_pos;
01352         // convert to object-local space
01353         focus_delta.rotVec(inv_obj_rot);
01354 
01355         // calculate clip percentage needed to get focus offset back in bounds along the camera_focus axis
01356         LLVector3 clip_fraction;
01357 
01358         for (U32 axis = VX; axis <= VZ; axis++)
01359         {
01360                 F32 clip_amt;
01361                 if (focus_delta.mV[axis] > 0.f)
01362                 {
01363                         clip_amt = llmax(0.f, focus_delta.mV[axis] - object_half_extents.mV[axis]);
01364                 }
01365                 else
01366                 {
01367                         clip_amt = llmin(0.f, focus_delta.mV[axis] + object_half_extents.mV[axis]);
01368                 }
01369 
01370                 // don't divide by very small nunber
01371                 if (llabs(camera_focus_vec.mV[axis]) < 0.0001f)
01372                 {
01373                         clip_fraction.mV[axis] = 0.f;
01374                 }
01375                 else
01376                 {
01377                         clip_fraction.mV[axis] = clip_amt / camera_focus_vec.mV[axis];
01378                 }
01379         }
01380 
01381         LLVector3 abs_clip_fraction = clip_fraction;
01382         abs_clip_fraction.abs();
01383 
01384         // find greatest shrinkage factor and
01385         // rescale focus offset to inside object extents
01386         if (abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VY] &&
01387                 abs_clip_fraction.mV[VX] > abs_clip_fraction.mV[VZ])
01388         {
01389                 focus_delta -= clip_fraction.mV[VX] * camera_focus_vec;
01390         }
01391         else if (abs_clip_fraction.mV[VY] > abs_clip_fraction.mV[VZ])
01392         {
01393                 focus_delta -= clip_fraction.mV[VY] * camera_focus_vec;
01394         }
01395         else
01396         {
01397                 focus_delta -= clip_fraction.mV[VZ] * camera_focus_vec;
01398         }
01399 
01400         // convert back to world space
01401         focus_delta.rotVec(obj_rot);
01402         
01403         if (!is_avatar) 
01404         {
01405                 //unproject relative clicked coordinate from window coordinate using GL
01406                 GLint viewport[4];
01407                 GLdouble modelview[16];
01408                 GLdouble projection[16];
01409                 GLfloat winX, winY, winZ;
01410                 GLdouble posX, posY, posZ;
01411 
01412                 // convert our matrices to something that has a multiply that works
01413                 glh::matrix4f newModel((F32*)LLViewerCamera::getInstance()->getModelview().mMatrix);
01414                 glh::matrix4f tmpObjMat((F32*)obj_matrix.mMatrix);
01415                 newModel *= tmpObjMat;
01416 
01417                 for(U32 i = 0; i < 16; ++i)
01418                 {
01419                         modelview[i] = newModel.m[i];
01420                         projection[i] = LLViewerCamera::getInstance()->getProjection().mMatrix[i/4][i%4];
01421                 }
01422                 glGetIntegerv( GL_VIEWPORT, viewport );
01423 
01424                 winX = ((F32)x) * gViewerWindow->getDisplayScale().mV[VX];
01425                 winY = ((F32)y) * gViewerWindow->getDisplayScale().mV[VY];
01426                 glReadPixels( llfloor(winX), llfloor(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
01427 
01428                 gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
01429 
01430                 LLVector3 obj_rel((F32)posX, (F32)posY, (F32)posZ);
01431                 obj_rel = obj_rel * object->getRenderMatrix();
01432                 obj_rel -= object->getRenderPosition();
01433                 
01434                 LLVector3 obj_center = LLVector3(0, 0, 0) * object->getRenderMatrix();
01435 
01436                 //now that we have the object relative position, we should bias toward the center of the object 
01437                 //based on the distance of the camera to the focus point vs. the distance of the camera to the focus
01438 
01439                 F32 relDist = llabs(obj_rel * LLViewerCamera::getInstance()->getAtAxis());
01440                 F32 viewDist = dist_vec(obj_center + obj_rel, LLViewerCamera::getInstance()->getOrigin());
01441 
01442 
01443                 LLBBox obj_bbox = object->getBoundingBoxAgent();
01444                 F32 bias = 0.f;
01445 
01446                 LLVector3 virtual_camera_pos = gAgent.getPosAgentFromGlobal(mFocusTargetGlobal + (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor));
01447 
01448                 if(obj_bbox.containsPointAgent(virtual_camera_pos))
01449                 {
01450                         // if the camera is inside the object (large, hollow objects, for example)
01451                         // force focus point all the way to destination depth, away from object center
01452                         bias = 1.f;
01453                 }
01454                 else
01455                 {
01456                         // perform magic number biasing of focus point towards surface vs. planar center
01457                         bias = clamp_rescale(relDist/viewDist, 0.1f, 0.7f, 0.0f, 1.0f);
01458                 }
01459                 
01460                 obj_rel = lerp(focus_delta, obj_rel, bias);
01461                 
01462                 return LLVector3d(obj_rel);
01463         }
01464 
01465         return LLVector3d(focus_delta.mV[VX], focus_delta.mV[VY], focus_delta.mV[VZ]);
01466 }
01467 
01468 //-----------------------------------------------------------------------------
01469 // calcCameraMinDistance()
01470 //-----------------------------------------------------------------------------
01471 BOOL LLAgent::calcCameraMinDistance(F32 &obj_min_distance)
01472 {
01473         BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars)
01474 
01475         if (!mFocusObject || mFocusObject->isDead())
01476         {
01477                 obj_min_distance = 0.f;
01478                 return TRUE;
01479         }
01480 
01481         if (mFocusObject->mDrawable.isNull())
01482         {
01483 #ifdef LL_RELEASE_FOR_DOWNLOAD
01484                 llwarns << "Focus object with no drawable!" << llendl;
01485 #else
01486                 mFocusObject->dump();
01487                 llerrs << "Focus object with no drawable!" << llendl;
01488 #endif
01489                 obj_min_distance = 0.f;
01490                 return TRUE;
01491         }
01492         
01493         LLQuaternion inv_object_rot = ~mFocusObject->getRenderRotation();
01494         LLVector3 target_offset_origin = mFocusObjectOffset;
01495         LLVector3 camera_offset_target(getCameraPositionAgent() - getPosAgentFromGlobal(mFocusTargetGlobal));
01496 
01497         // convert offsets into object local space
01498         camera_offset_target.rotVec(inv_object_rot);
01499         target_offset_origin.rotVec(inv_object_rot);
01500 
01501         // push around object extents based on target offset
01502         LLVector3 object_extents = mFocusObject->getScale();
01503         if (mFocusObject->isAvatar())
01504         {
01505                 // fudge factors that lets you zoom in on avatars a bit more (which don't do FOV zoom)
01506                 object_extents.mV[VX] *= AVATAR_ZOOM_MIN_X_FACTOR;
01507                 object_extents.mV[VY] *= AVATAR_ZOOM_MIN_Y_FACTOR;
01508                 object_extents.mV[VZ] *= AVATAR_ZOOM_MIN_Z_FACTOR;
01509                 soft_limit = TRUE;
01510         }
01511         LLVector3 abs_target_offset = target_offset_origin;
01512         abs_target_offset.abs();
01513 
01514         LLVector3 target_offset_dir = target_offset_origin;
01515         F32 object_radius = mFocusObject->getVObjRadius();
01516 
01517         BOOL target_outside_object_extents = FALSE;
01518 
01519         for (U32 i = VX; i <= VZ; i++)
01520         {
01521                 if (abs_target_offset.mV[i] * 2.f > object_extents.mV[i] + OBJECT_EXTENTS_PADDING)
01522                 {
01523                         target_outside_object_extents = TRUE;
01524                 }
01525                 if (camera_offset_target.mV[i] > 0.f)
01526                 {
01527                         object_extents.mV[i] -= target_offset_origin.mV[i] * 2.f;
01528                 }
01529                 else
01530                 {
01531                         object_extents.mV[i] += target_offset_origin.mV[i] * 2.f;
01532                 }
01533         }
01534 
01535         // don't shrink the object extents so far that the object inverts
01536         object_extents.clamp(0.001f, F32_MAX);
01537 
01538         // move into first octant
01539         LLVector3 camera_offset_target_abs_norm = camera_offset_target;
01540         camera_offset_target_abs_norm.abs();
01541         // make sure offset is non-zero
01542         camera_offset_target_abs_norm.clamp(0.001f, F32_MAX);
01543         camera_offset_target_abs_norm.normVec();
01544 
01545         // find camera position relative to normalized object extents
01546         LLVector3 camera_offset_target_scaled = camera_offset_target_abs_norm;
01547         camera_offset_target_scaled.mV[VX] /= object_extents.mV[VX];
01548         camera_offset_target_scaled.mV[VY] /= object_extents.mV[VY];
01549         camera_offset_target_scaled.mV[VZ] /= object_extents.mV[VZ];
01550 
01551         if (camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VY] && 
01552                 camera_offset_target_scaled.mV[VX] > camera_offset_target_scaled.mV[VZ])
01553         {
01554                 if (camera_offset_target_abs_norm.mV[VX] < 0.001f)
01555                 {
01556                         obj_min_distance = object_extents.mV[VX] * 0.5f;
01557                 }
01558                 else
01559                 {
01560                         obj_min_distance = object_extents.mV[VX] * 0.5f / camera_offset_target_abs_norm.mV[VX];
01561                 }
01562         }
01563         else if (camera_offset_target_scaled.mV[VY] > camera_offset_target_scaled.mV[VZ])
01564         {
01565                 if (camera_offset_target_abs_norm.mV[VY] < 0.001f)
01566                 {
01567                         obj_min_distance = object_extents.mV[VY] * 0.5f;
01568                 }
01569                 else
01570                 {
01571                         obj_min_distance = object_extents.mV[VY] * 0.5f / camera_offset_target_abs_norm.mV[VY];
01572                 }
01573         }
01574         else
01575         {
01576                 if (camera_offset_target_abs_norm.mV[VZ] < 0.001f)
01577                 {
01578                         obj_min_distance = object_extents.mV[VZ] * 0.5f;
01579                 }
01580                 else
01581                 {
01582                         obj_min_distance = object_extents.mV[VZ] * 0.5f / camera_offset_target_abs_norm.mV[VZ];
01583                 }
01584         }
01585 
01586         LLVector3 object_split_axis;
01587         LLVector3 target_offset_scaled = target_offset_origin;
01588         target_offset_scaled.abs();
01589         target_offset_scaled.normVec();
01590         target_offset_scaled.mV[VX] /= object_extents.mV[VX];
01591         target_offset_scaled.mV[VY] /= object_extents.mV[VY];
01592         target_offset_scaled.mV[VZ] /= object_extents.mV[VZ];
01593 
01594         if (target_offset_scaled.mV[VX] > target_offset_scaled.mV[VY] && 
01595                 target_offset_scaled.mV[VX] > target_offset_scaled.mV[VZ])
01596         {
01597                 object_split_axis = LLVector3::x_axis;
01598         }
01599         else if (target_offset_scaled.mV[VY] > target_offset_scaled.mV[VZ])
01600         {
01601                 object_split_axis = LLVector3::y_axis;
01602         }
01603         else
01604         {
01605                 object_split_axis = LLVector3::z_axis;
01606         }
01607 
01608         LLVector3 camera_offset_object(getCameraPositionAgent() - mFocusObject->getPositionAgent());
01609 
01610         // length projected orthogonal to target offset
01611         F32 camera_offset_dist = (camera_offset_object - target_offset_dir * (camera_offset_object * target_offset_dir)).magVec();
01612 
01613         // calculate whether the target point would be "visible" if it were outside the bounding box
01614         // on the opposite of the splitting plane defined by object_split_axis;
01615         BOOL exterior_target_visible = FALSE;
01616         if (camera_offset_dist > object_radius)
01617         {
01618                 // target is visible from camera, so turn off fov zoom
01619                 exterior_target_visible = TRUE;
01620         }
01621 
01622         F32 camera_offset_clip = camera_offset_object * object_split_axis;
01623         F32 target_offset_clip = target_offset_dir * object_split_axis;
01624 
01625         // target has moved outside of object extents
01626         // check to see if camera and target are on same side 
01627         if (target_outside_object_extents)
01628         {
01629                 if (camera_offset_clip > 0.f && target_offset_clip > 0.f)
01630                 {
01631                         return FALSE;
01632                 }
01633                 else if (camera_offset_clip < 0.f && target_offset_clip < 0.f)
01634                 {
01635                         return FALSE;
01636                 }
01637         }
01638 
01639         // clamp obj distance to diagonal of 10 by 10 cube
01640         obj_min_distance = llmin(obj_min_distance, 10.f * F_SQRT3);
01641 
01642         obj_min_distance += LLViewerCamera::getInstance()->getNear() + (soft_limit ? 0.1f : 0.2f);
01643         
01644         return TRUE;
01645 }
01646 
01647 F32 LLAgent::getCameraZoomFraction()
01648 {
01649         // 0.f -> camera zoomed all the way out
01650         // 1.f -> camera zoomed all the way in
01651         LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
01652         if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
01653         {
01654                 // already [0,1]
01655                 return mAvatarObject->mHUDTargetZoom;
01656         }
01657         else if (mFocusOnAvatar && cameraThirdPerson())
01658         {
01659                 return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f);
01660         }
01661         else if (cameraCustomizeAvatar())
01662         {
01663                 F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
01664                 return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f );
01665         }
01666         else
01667         {
01668                 F32 min_zoom;
01669                 const F32 DIST_FUDGE = 16.f; // meters
01670                 F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, 
01671                                                                 LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE,
01672                                                                 MAX_CAMERA_DISTANCE_FROM_AGENT);
01673 
01674                 F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
01675                 if (mFocusObject.notNull())
01676                 {
01677                         if (mFocusObject->isAvatar())
01678                         {
01679                                 min_zoom = AVATAR_MIN_ZOOM;
01680                         }
01681                         else
01682                         {
01683                                 min_zoom = OBJECT_MIN_ZOOM;
01684                         }
01685                 }
01686                 else
01687                 {
01688                         min_zoom = LAND_MIN_ZOOM;
01689                 }
01690 
01691                 return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f);
01692         }
01693 }
01694 
01695 void LLAgent::setCameraZoomFraction(F32 fraction)
01696 {
01697         // 0.f -> camera zoomed all the way out
01698         // 1.f -> camera zoomed all the way in
01699         LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
01700 
01701         if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
01702         {
01703                 mAvatarObject->mHUDTargetZoom = fraction;
01704         }
01705         else if (mFocusOnAvatar && cameraThirdPerson())
01706         {
01707                 mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION);
01708         }
01709         else if (cameraCustomizeAvatar())
01710         {
01711                 LLVector3d camera_offset_dir = mCameraFocusOffsetTarget;
01712                 camera_offset_dir.normVec();
01713                 mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, APPEARANCE_MAX_ZOOM, APPEARANCE_MIN_ZOOM);
01714         }
01715         else
01716         {
01717                 F32 min_zoom = LAND_MIN_ZOOM;
01718                 const F32 DIST_FUDGE = 16.f; // meters
01719                 F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, 
01720                                                                 LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE,
01721                                                                 MAX_CAMERA_DISTANCE_FROM_AGENT);
01722 
01723                 if (mFocusObject.notNull())
01724                 {
01725                         if (mFocusObject.notNull())
01726                         {
01727                                 if (mFocusObject->isAvatar())
01728                                 {
01729                                         min_zoom = AVATAR_MIN_ZOOM;
01730                                 }
01731                                 else
01732                                 {
01733                                         min_zoom = OBJECT_MIN_ZOOM;
01734                                 }
01735                         }
01736                 }
01737 
01738                 LLVector3d camera_offset_dir = mCameraFocusOffsetTarget;
01739                 camera_offset_dir.normVec();
01740                 mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom);
01741         }
01742         startCameraAnimation();
01743 }
01744 
01745 
01746 //-----------------------------------------------------------------------------
01747 // cameraOrbitAround()
01748 //-----------------------------------------------------------------------------
01749 void LLAgent::cameraOrbitAround(const F32 radians)
01750 {
01751         LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
01752         if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
01753         {
01754                 // do nothing for hud selection
01755         }
01756         else if (mFocusOnAvatar && (mCameraMode == CAMERA_MODE_THIRD_PERSON || mCameraMode == CAMERA_MODE_FOLLOW))
01757         {
01758                 mFrameAgent.rotate(radians, getReferenceUpVector());
01759         }
01760         else
01761         {
01762                 mCameraFocusOffsetTarget.rotVec(radians, 0.f, 0.f, 1.f);
01763                 
01764                 cameraZoomIn(1.f);
01765         }
01766 }
01767 
01768 
01769 //-----------------------------------------------------------------------------
01770 // cameraOrbitOver()
01771 //-----------------------------------------------------------------------------
01772 void LLAgent::cameraOrbitOver(const F32 angle)
01773 {
01774         LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
01775         if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
01776         {
01777                 // do nothing for hud selection
01778         }
01779         else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
01780         {
01781                 pitch(angle);
01782         }
01783         else
01784         {
01785                 LLVector3 camera_offset_unit(mCameraFocusOffsetTarget);
01786                 camera_offset_unit.normVec();
01787 
01788                 F32 angle_from_up = acos( camera_offset_unit * getReferenceUpVector() );
01789 
01790                 LLVector3d left_axis;
01791                 left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
01792                 F32 new_angle = llclamp(angle_from_up - angle, 1.f * DEG_TO_RAD, 179.f * DEG_TO_RAD);
01793                 mCameraFocusOffsetTarget.rotVec(angle_from_up - new_angle, left_axis);
01794 
01795                 cameraZoomIn(1.f);
01796         }
01797 }
01798 
01799 //-----------------------------------------------------------------------------
01800 // cameraZoomIn()
01801 //-----------------------------------------------------------------------------
01802 void LLAgent::cameraZoomIn(const F32 fraction)
01803 {
01804         if (gDisconnected)
01805         {
01806                 return;
01807         }
01808 
01809         LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
01810         if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
01811         {
01812                 // just update hud zoom level
01813                 mAvatarObject->mHUDTargetZoom /= fraction;
01814                 return;
01815         }
01816 
01817 
01818         LLVector3d      camera_offset(mCameraFocusOffsetTarget);
01819         LLVector3d      camera_offset_unit(mCameraFocusOffsetTarget);
01820         F32 min_zoom = LAND_MIN_ZOOM;
01821         F32 current_distance = (F32)camera_offset_unit.normVec();
01822         F32 new_distance = current_distance * fraction;
01823 
01824         // Don't move through focus point
01825         if (mFocusObject)
01826         {
01827                 LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]);
01828 
01829                 if (mFocusObject->isAvatar())
01830                 {
01831                         calcCameraMinDistance(min_zoom);
01832                 }
01833                 else
01834                 {
01835                         min_zoom = OBJECT_MIN_ZOOM;
01836                 }
01837         }
01838 
01839         new_distance = llmax(new_distance, min_zoom); 
01840 
01841         // Don't zoom too far back
01842         const F32 DIST_FUDGE = 16.f; // meters
01843         F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, 
01844                                                          LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
01845 
01846         if (new_distance > max_distance)
01847         {
01848                 new_distance = max_distance;
01849 
01850                 /*
01851                 // Unless camera is unlocked
01852                 if (!LLViewerCamera::sDisableCameraConstraints)
01853                 {
01854                         return;
01855                 }
01856                 */
01857         }
01858 
01859         if( cameraCustomizeAvatar() )
01860         {
01861                 new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
01862         }
01863 
01864         mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
01865 }
01866 
01867 //-----------------------------------------------------------------------------
01868 // cameraOrbitIn()
01869 //-----------------------------------------------------------------------------
01870 void LLAgent::cameraOrbitIn(const F32 meters)
01871 {
01872         if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
01873         {
01874                 F32 camera_offset_dist = llmax(0.001f, mCameraOffsetDefault.magVec());
01875                 
01876                 mCameraZoomFraction = (mTargetCameraDistance - meters) / camera_offset_dist;
01877 
01878                 if (!gSavedSettings.getBOOL("FreezeTime") && mCameraZoomFraction < MIN_ZOOM_FRACTION && meters > 0.f)
01879                 {
01880                         // No need to animate, camera is already there.
01881                         changeCameraToMouselook(FALSE);
01882                 }
01883 
01884                 mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION);
01885         }
01886         else
01887         {
01888                 LLVector3d      camera_offset(mCameraFocusOffsetTarget);
01889                 LLVector3d      camera_offset_unit(mCameraFocusOffsetTarget);
01890                 F32 current_distance = (F32)camera_offset_unit.normVec();
01891                 F32 new_distance = current_distance - meters;
01892                 F32 min_zoom = LAND_MIN_ZOOM;
01893                 
01894                 // Don't move through focus point
01895                 if (mFocusObject.notNull())
01896                 {
01897                         if (mFocusObject->isAvatar())
01898                         {
01899                                 min_zoom = AVATAR_MIN_ZOOM;
01900                         }
01901                         else
01902                         {
01903                                 min_zoom = OBJECT_MIN_ZOOM;
01904                         }
01905                 }
01906 
01907                 new_distance = llmax(new_distance, min_zoom);
01908 
01909                 // Don't zoom too far back
01910                 const F32 DIST_FUDGE = 16.f; // meters
01911                 F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, 
01912                                                                  LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
01913 
01914                 if (new_distance > max_distance)
01915                 {
01916                         // Unless camera is unlocked
01917                         if (!gSavedSettings.getBOOL("DisableCameraConstraints"))
01918                         {
01919                                 return;
01920                         }
01921                 }
01922 
01923                 if( CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode() )
01924                 {
01925                         new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
01926                 }
01927 
01928                 // Compute new camera offset
01929                 mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
01930                 cameraZoomIn(1.f);
01931         }
01932 }
01933 
01934 
01935 //-----------------------------------------------------------------------------
01936 // cameraPanIn()
01937 //-----------------------------------------------------------------------------
01938 void LLAgent::cameraPanIn(F32 meters)
01939 {
01940         LLVector3d at_axis;
01941         at_axis.setVec(LLViewerCamera::getInstance()->getAtAxis());
01942 
01943         mFocusTargetGlobal += meters * at_axis;
01944         mFocusGlobal = mFocusTargetGlobal;
01945         // don't enforce zoom constraints as this is the only way for users to get past them easily
01946         updateFocusOffset();
01947 }
01948 
01949 //-----------------------------------------------------------------------------
01950 // cameraPanLeft()
01951 //-----------------------------------------------------------------------------
01952 void LLAgent::cameraPanLeft(F32 meters)
01953 {
01954         LLVector3d left_axis;
01955         left_axis.setVec(LLViewerCamera::getInstance()->getLeftAxis());
01956 
01957         mFocusTargetGlobal += meters * left_axis;
01958         mFocusGlobal = mFocusTargetGlobal;
01959         cameraZoomIn(1.f);
01960         updateFocusOffset();
01961 }
01962 
01963 //-----------------------------------------------------------------------------
01964 // cameraPanUp()
01965 //-----------------------------------------------------------------------------
01966 void LLAgent::cameraPanUp(F32 meters)
01967 {
01968         LLVector3d up_axis;
01969         up_axis.setVec(LLViewerCamera::getInstance()->getUpAxis());
01970 
01971         mFocusTargetGlobal += meters * up_axis;
01972         mFocusGlobal = mFocusTargetGlobal;
01973         cameraZoomIn(1.f);
01974         updateFocusOffset();
01975 }
01976 
01977 //-----------------------------------------------------------------------------
01978 // setKey()
01979 //-----------------------------------------------------------------------------
01980 void LLAgent::setKey(const S32 direction, S32 &key)
01981 {
01982         if (direction > 0)
01983         {
01984                 key = 1;
01985         }
01986         else if (direction < 0)
01987         {
01988                 key = -1;
01989         }
01990         else
01991         {
01992                 key = 0;
01993         }
01994 }
01995 
01996 
01997 //-----------------------------------------------------------------------------
01998 // getControlFlags()
01999 //-----------------------------------------------------------------------------
02000 U32 LLAgent::getControlFlags()
02001 {
02002 /*
02003         // HACK -- avoids maintenance of control flags when camera mode is turned on or off,
02004         // only worries about it when the flags are measured
02005         if (mCameraMode == CAMERA_MODE_MOUSELOOK) 
02006         {
02007                 if ( !(mControlFlags & AGENT_CONTROL_MOUSELOOK) )
02008                 {
02009                         mControlFlags |= AGENT_CONTROL_MOUSELOOK;
02010                 }
02011         }
02012 */
02013         return mControlFlags;
02014 }
02015 
02016 //-----------------------------------------------------------------------------
02017 // setControlFlags()
02018 //-----------------------------------------------------------------------------
02019 void LLAgent::setControlFlags(U32 mask)
02020 {
02021         mControlFlags |= mask;
02022         mbFlagsDirty = TRUE;
02023 }
02024 
02025 
02026 //-----------------------------------------------------------------------------
02027 // clearControlFlags()
02028 //-----------------------------------------------------------------------------
02029 void LLAgent::clearControlFlags(U32 mask)
02030 {
02031         U32 old_flags = mControlFlags;
02032         mControlFlags &= ~mask;
02033         if (old_flags != mControlFlags)
02034         {
02035                 mbFlagsDirty = TRUE;
02036         }
02037 }
02038 
02039 //-----------------------------------------------------------------------------
02040 // controlFlagsDirty()
02041 //-----------------------------------------------------------------------------
02042 BOOL LLAgent::controlFlagsDirty() const
02043 {
02044         return mbFlagsDirty;
02045 }
02046 
02047 //-----------------------------------------------------------------------------
02048 // enableControlFlagReset()
02049 //-----------------------------------------------------------------------------
02050 void LLAgent::enableControlFlagReset()
02051 {
02052         mbFlagsNeedReset = TRUE;
02053 }
02054 
02055 //-----------------------------------------------------------------------------
02056 // resetControlFlags()
02057 //-----------------------------------------------------------------------------
02058 void LLAgent::resetControlFlags()
02059 {
02060         if (mbFlagsNeedReset)
02061         {
02062                 mbFlagsNeedReset = FALSE;
02063                 mbFlagsDirty = FALSE;
02064                 // reset all of the ephemeral flags
02065                 // some flags are managed elsewhere
02066                 mControlFlags &= AGENT_CONTROL_AWAY | AGENT_CONTROL_FLY | AGENT_CONTROL_MOUSELOOK;
02067         }
02068 }
02069 
02070 //-----------------------------------------------------------------------------
02071 // setAFK()
02072 //-----------------------------------------------------------------------------
02073 void LLAgent::setAFK()
02074 {
02075         // Drones can't go AFK
02076         if (gNoRender)
02077         {
02078                 return;
02079         }
02080 
02081         if (!gAgent.getRegion())
02082         {
02083                 // Don't set AFK if we're not talking to a region yet.
02084                 return;
02085         }
02086 
02087         if (!(mControlFlags & AGENT_CONTROL_AWAY))
02088         {
02089                 sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_START);
02090                 setControlFlags(AGENT_CONTROL_AWAY | AGENT_CONTROL_STOP);
02091                 gAwayTimer.start();
02092                 if (gAFKMenu)
02093                 {
02094                         //*TODO:Translate
02095                         gAFKMenu->setLabel(LLString("Set Not Away"));
02096                 }
02097         }
02098 }
02099 
02100 //-----------------------------------------------------------------------------
02101 // clearAFK()
02102 //-----------------------------------------------------------------------------
02103 void LLAgent::clearAFK()
02104 {
02105         gAwayTriggerTimer.reset();
02106 
02107         // Gods can sometimes get into away state (via gestures)
02108         // without setting the appropriate control flag. JC
02109         LLVOAvatar* av = mAvatarObject;
02110         if (mControlFlags & AGENT_CONTROL_AWAY
02111                 || (av
02112                         && (av->mSignaledAnimations.find(ANIM_AGENT_AWAY) != av->mSignaledAnimations.end())))
02113         {
02114                 sendAnimationRequest(ANIM_AGENT_AWAY, ANIM_REQUEST_STOP);
02115                 clearControlFlags(AGENT_CONTROL_AWAY);
02116                 if (gAFKMenu)
02117                 {
02118                         //*TODO:Translate
02119                         gAFKMenu->setLabel(LLString("Set Away"));
02120                 }
02121         }
02122 }
02123 
02124 //-----------------------------------------------------------------------------
02125 // getAFK()
02126 //-----------------------------------------------------------------------------
02127 BOOL LLAgent::getAFK() const
02128 {
02129         return (mControlFlags & AGENT_CONTROL_AWAY) != 0;
02130 }
02131 
02132 //-----------------------------------------------------------------------------
02133 // setBusy()
02134 //-----------------------------------------------------------------------------
02135 void LLAgent::setBusy()
02136 {
02137         sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START);
02138         mIsBusy = TRUE;
02139         if (gBusyMenu)
02140         {
02141                 //*TODO:Translate
02142                 gBusyMenu->setLabel(LLString("Set Not Busy"));
02143         }
02144         LLFloaterMute::getInstance()->updateButtons();
02145 }
02146 
02147 //-----------------------------------------------------------------------------
02148 // clearBusy()
02149 //-----------------------------------------------------------------------------
02150 void LLAgent::clearBusy()
02151 {
02152         mIsBusy = FALSE;
02153         sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_STOP);
02154         if (gBusyMenu)
02155         {
02156                 //*TODO:Translate
02157                 gBusyMenu->setLabel(LLString("Set Busy"));
02158         }
02159         LLFloaterMute::getInstance()->updateButtons();
02160 }
02161 
02162 //-----------------------------------------------------------------------------
02163 // getBusy()
02164 //-----------------------------------------------------------------------------
02165 BOOL LLAgent::getBusy() const
02166 {
02167         return mIsBusy;
02168 }
02169 
02170 
02171 //-----------------------------------------------------------------------------
02172 // startAutoPilotGlobal()
02173 //-----------------------------------------------------------------------------
02174 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)
02175 {
02176         if (!gAgent.getAvatarObject())
02177         {
02178                 return;
02179         }
02180         
02181         mAutoPilotFinishedCallback = finish_callback;
02182         mAutoPilotCallbackData = callback_data;
02183         mAutoPilotRotationThreshold = rot_threshold;
02184         mAutoPilotBehaviorName = behavior_name;
02185 
02186         LLVector3d delta_pos( target_global );
02187         delta_pos -= getPositionGlobal();
02188         F64 distance = delta_pos.magVec();
02189         LLVector3d trace_target = target_global;
02190 
02191         trace_target.mdV[VZ] -= 10.f;
02192 
02193         LLVector3d intersection;
02194         LLVector3 normal;
02195         LLViewerObject *hit_obj;
02196         F32 heightDelta = LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, trace_target, intersection, normal, &hit_obj);
02197 
02198         if (stop_distance > 0.f)
02199         {
02200                 mAutoPilotStopDistance = stop_distance;
02201         }
02202         else
02203         {
02204                 // Guess at a reasonable stop distance.
02205                 mAutoPilotStopDistance = fsqrtf( distance );
02206                 if (mAutoPilotStopDistance < 0.5f) 
02207                 {
02208                         mAutoPilotStopDistance = 0.5f;
02209                 }
02210         }
02211 
02212         mAutoPilotFlyOnStop = getFlying();
02213 
02214         if (distance > 30.0)
02215         {
02216                 setFlying(TRUE);
02217         }
02218 
02219         if ( distance > 1.f && heightDelta > (sqrtf(mAutoPilotStopDistance) + 1.f))
02220         {
02221                 setFlying(TRUE);
02222                 mAutoPilotFlyOnStop = TRUE;
02223         }
02224 
02225         mAutoPilot = TRUE;
02226         mAutoPilotTargetGlobal = target_global;
02227 
02228         // trace ray down to find height of destination from ground
02229         LLVector3d traceEndPt = target_global;
02230         traceEndPt.mdV[VZ] -= 20.f;
02231 
02232         LLVector3d targetOnGround;
02233         LLVector3 groundNorm;
02234         LLViewerObject *obj;
02235 
02236         LLWorld::getInstance()->resolveStepHeightGlobal(NULL, target_global, traceEndPt, targetOnGround, groundNorm, &obj);
02237         F64 target_height = llmax((F64)gAgent.getAvatarObject()->getPelvisToFoot(), target_global.mdV[VZ] - targetOnGround.mdV[VZ]);
02238 
02239         // clamp z value of target to minimum height above ground
02240         mAutoPilotTargetGlobal.mdV[VZ] = targetOnGround.mdV[VZ] + target_height;
02241         mAutoPilotTargetDist = (F32)dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal);
02242         if (target_rotation)
02243         {
02244                 mAutoPilotUseRotation = TRUE;
02245                 mAutoPilotTargetFacing = LLVector3::x_axis * *target_rotation;
02246                 mAutoPilotTargetFacing.mV[VZ] = 0.f;
02247                 mAutoPilotTargetFacing.normVec();
02248         }
02249         else
02250         {
02251                 mAutoPilotUseRotation = FALSE;
02252         }
02253 
02254         mAutoPilotNoProgressFrameCount = 0;
02255 }
02256 
02257 
02258 //-----------------------------------------------------------------------------
02259 // startFollowPilot()
02260 //-----------------------------------------------------------------------------
02261 void LLAgent::startFollowPilot(const LLUUID &leader_id)
02262 {
02263         if (!mAutoPilot) return;
02264 
02265         mLeaderID = leader_id;
02266         if ( mLeaderID.isNull() ) return;
02267 
02268         LLViewerObject* object = gObjectList.findObject(mLeaderID);
02269         if (!object) 
02270         {
02271                 mLeaderID = LLUUID::null;
02272                 return;
02273         }
02274 
02275         startAutoPilotGlobal(object->getPositionGlobal());
02276 }
02277 
02278 
02279 //-----------------------------------------------------------------------------
02280 // stopAutoPilot()
02281 //-----------------------------------------------------------------------------
02282 void LLAgent::stopAutoPilot(BOOL user_cancel)
02283 {
02284         if (mAutoPilot)
02285         {
02286                 mAutoPilot = FALSE;
02287                 if (mAutoPilotUseRotation && !user_cancel)
02288                 {
02289                         resetAxes(mAutoPilotTargetFacing);
02290                 }
02291                 //NB: auto pilot can terminate for a reason other than reaching the destination
02292                 if (mAutoPilotFinishedCallback)
02293                 {
02294                         mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData);
02295                 }
02296                 mLeaderID = LLUUID::null;
02297 
02298                 // If the user cancelled, don't change the fly state
02299                 if (!user_cancel)
02300                 {
02301                         setFlying(mAutoPilotFlyOnStop);
02302                 }
02303                 setControlFlags(AGENT_CONTROL_STOP);
02304 
02305                 if (user_cancel && !mAutoPilotBehaviorName.empty())
02306                 {
02307                         if (mAutoPilotBehaviorName == "Sit")
02308                                 LLNotifyBox::showXml("CancelledSit");
02309                         else if (mAutoPilotBehaviorName == "Attach")
02310                                 LLNotifyBox::showXml("CancelledAttach");
02311                         else
02312                                 LLNotifyBox::showXml("Cancelled");
02313                 }
02314         }
02315 }
02316 
02317 
02318 // Returns necessary agent pitch and yaw changes, radians.
02319 //-----------------------------------------------------------------------------
02320 // autoPilot()
02321 //-----------------------------------------------------------------------------
02322 void LLAgent::autoPilot(F32 *delta_yaw)
02323 {
02324         if (mAutoPilot)
02325         {
02326                 if (!mLeaderID.isNull())
02327                 {
02328                         LLViewerObject* object = gObjectList.findObject(mLeaderID);
02329                         if (!object) 
02330                         {
02331                                 stopAutoPilot();
02332                                 return;
02333                         }
02334                         mAutoPilotTargetGlobal = object->getPositionGlobal();
02335                 }
02336                 
02337                 if (!mAvatarObject)
02338                 {
02339                         return;
02340                 }
02341 
02342                 if (mAvatarObject->mInAir)
02343                 {
02344                         setFlying(TRUE);
02345                 }
02346         
02347                 LLVector3 at;
02348                 at.setVec(mFrameAgent.getAtAxis());
02349                 LLVector3 target_agent = getPosAgentFromGlobal(mAutoPilotTargetGlobal);
02350                 LLVector3 direction = target_agent - getPositionAgent();
02351 
02352                 F32 target_dist = direction.magVec();
02353 
02354                 if (target_dist >= mAutoPilotTargetDist)
02355                 {
02356                         mAutoPilotNoProgressFrameCount++;
02357                         if (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped)
02358                         {
02359                                 stopAutoPilot();
02360                                 return;
02361                         }
02362                 }
02363 
02364                 mAutoPilotTargetDist = target_dist;
02365 
02366                 // Make this a two-dimensional solution
02367                 at.mV[VZ] = 0.f;
02368                 direction.mV[VZ] = 0.f;
02369 
02370                 at.normVec();
02371                 F32 xy_distance = direction.normVec();
02372 
02373                 F32 yaw = 0.f;
02374                 if (mAutoPilotTargetDist > mAutoPilotStopDistance)
02375                 {
02376                         yaw = angle_between(mFrameAgent.getAtAxis(), direction);
02377                 }
02378                 else if (mAutoPilotUseRotation)
02379                 {
02380                         // we're close now just aim at target facing
02381                         yaw = angle_between(at, mAutoPilotTargetFacing);
02382                         direction = mAutoPilotTargetFacing;
02383                 }
02384 
02385                 yaw = 4.f * yaw / gFPSClamped;
02386 
02387                 // figure out which direction to turn
02388                 LLVector3 scratch(at % direction);
02389 
02390                 if (scratch.mV[VZ] > 0.f)
02391                 {
02392                         setControlFlags(AGENT_CONTROL_YAW_POS);
02393                 }
02394                 else
02395                 {
02396                         yaw = -yaw;
02397                         setControlFlags(AGENT_CONTROL_YAW_NEG);
02398                 }
02399 
02400                 *delta_yaw = yaw;
02401 
02402                 // Compute when to start slowing down and when to stop
02403                 F32 stop_distance = mAutoPilotStopDistance;
02404                 F32 slow_distance;
02405                 if (getFlying())
02406                 {
02407                         slow_distance = llmax(6.f, mAutoPilotStopDistance + 5.f);
02408                         stop_distance = llmax(2.f, mAutoPilotStopDistance);
02409                 }
02410                 else
02411                 {
02412                         slow_distance = llmax(3.f, mAutoPilotStopDistance + 2.f);
02413                 }
02414 
02415                 // If we're flying, handle autopilot points above or below you.
02416                 if (getFlying() && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE)
02417                 {
02418                         if (mAvatarObject)
02419                         {
02420                                 F64 current_height = mAvatarObject->getPositionGlobal().mdV[VZ];
02421                                 F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - current_height);
02422                                 F32 slope = delta_z / xy_distance;
02423                                 if (slope > 0.45f && delta_z > 6.f)
02424                                 {
02425                                         setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_POS);
02426                                 }
02427                                 else if (slope > 0.002f && delta_z > 0.5f)
02428                                 {
02429                                         setControlFlags(AGENT_CONTROL_UP_POS);
02430                                 }
02431                                 else if (slope < -0.45f && delta_z < -6.f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
02432                                 {
02433                                         setControlFlags(AGENT_CONTROL_FAST_UP | AGENT_CONTROL_UP_NEG);
02434                                 }
02435                                 else if (slope < -0.002f && delta_z < -0.5f && current_height > AUTOPILOT_MIN_TARGET_HEIGHT_OFF_GROUND)
02436                                 {
02437                                         setControlFlags(AGENT_CONTROL_UP_NEG);
02438                                 }
02439                         }
02440                 }
02441 
02442                 //  calculate delta rotation to target heading
02443                 F32 delta_target_heading = angle_between(mFrameAgent.getAtAxis(), mAutoPilotTargetFacing);
02444 
02445                 if (xy_distance > slow_distance && yaw < (F_PI / 10.f))
02446                 {
02447                         // walking/flying fast
02448                         setControlFlags(AGENT_CONTROL_FAST_AT | AGENT_CONTROL_AT_POS);
02449                 }
02450                 else if (mAutoPilotTargetDist > mAutoPilotStopDistance)
02451                 {
02452                         // walking/flying slow
02453                         if (at * direction > 0.9f)
02454                         {
02455                                 setControlFlags(AGENT_CONTROL_AT_POS);
02456                         }
02457                         else if (at * direction < -0.9f)
02458                         {
02459                                 setControlFlags(AGENT_CONTROL_AT_NEG);
02460                         }
02461                 }
02462 
02463                 // check to see if we need to keep rotating to target orientation
02464                 if (mAutoPilotTargetDist < mAutoPilotStopDistance)
02465                 {
02466                         setControlFlags(AGENT_CONTROL_STOP);
02467                         if(!mAutoPilotUseRotation || (delta_target_heading < mAutoPilotRotationThreshold))
02468                         {
02469                                 stopAutoPilot();
02470                         }
02471                 }
02472         }
02473 }
02474 
02475 
02476 //-----------------------------------------------------------------------------
02477 // propagate()
02478 //-----------------------------------------------------------------------------
02479 void LLAgent::propagate(const F32 dt)
02480 {
02481         // Update UI based on agent motion
02482         LLFloaterMove *floater_move = LLFloaterMove::getInstance();
02483         if (floater_move)
02484         {
02485                 floater_move->mForwardButton   ->setToggleState( mAtKey > 0 || mWalkKey > 0 );
02486                 floater_move->mBackwardButton  ->setToggleState( mAtKey < 0 || mWalkKey < 0 );
02487                 floater_move->mSlideLeftButton ->setToggleState( mLeftKey > 0 );
02488                 floater_move->mSlideRightButton->setToggleState( mLeftKey < 0 );
02489                 floater_move->mTurnLeftButton  ->setToggleState( mYawKey > 0.f );
02490                 floater_move->mTurnRightButton ->setToggleState( mYawKey < 0.f );
02491                 floater_move->mMoveUpButton    ->setToggleState( mUpKey > 0 );
02492                 floater_move->mMoveDownButton  ->setToggleState( mUpKey < 0 );
02493         }
02494 
02495         // handle rotation based on keyboard levels
02496         const F32 YAW_RATE = 90.f * DEG_TO_RAD;                         // radians per second
02497         yaw( YAW_RATE * mYawKey * dt );
02498 
02499         const F32 PITCH_RATE = 90.f * DEG_TO_RAD;                       // radians per second
02500         pitch(PITCH_RATE * (F32) mPitchKey * dt);
02501         
02502         // handle auto-land behavior
02503         if (mAvatarObject)
02504         {
02505                 BOOL in_air = mAvatarObject->mInAir;
02506                 LLVector3 land_vel = getVelocity();
02507                 land_vel.mV[VZ] = 0.f;
02508 
02509                 if (!in_air 
02510                         && mUpKey < 0 
02511                         && land_vel.magVecSquared() < MAX_VELOCITY_AUTO_LAND_SQUARED
02512                         && gSavedSettings.getBOOL("AutomaticFly"))
02513                 {
02514                         // land automatically
02515                         setFlying(FALSE);
02516                 }
02517         }
02518 
02519         // clear keys
02520         mAtKey = 0;
02521         mWalkKey = 0;
02522         mLeftKey = 0;
02523         mUpKey = 0;
02524         mYawKey = 0.f;
02525         mPitchKey = 0;
02526 }
02527 
02528 //-----------------------------------------------------------------------------
02529 // updateAgentPosition()
02530 //-----------------------------------------------------------------------------
02531 void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)
02532 {
02533         propagate(dt);
02534 
02535         // static S32 cameraUpdateCount = 0;
02536 
02537         rotate(yaw_radians, 0, 0, 1);
02538         
02539         //
02540         // Check for water and land collision, set underwater flag
02541         //
02542 
02543         updateLookAt(mouse_x, mouse_y);
02544 }
02545 
02546 //-----------------------------------------------------------------------------
02547 // updateLookAt()
02548 //-----------------------------------------------------------------------------
02549 void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y)
02550 {
02551         static LLVector3 last_at_axis;
02552 
02553 
02554         if ( mAvatarObject.isNull() )
02555         {
02556                 return;
02557         }
02558 
02559         LLQuaternion av_inv_rot = ~mAvatarObject->mRoot.getWorldRotation();
02560         LLVector3 root_at = LLVector3::x_axis * mAvatarObject->mRoot.getWorldRotation();
02561 
02562         if      ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) &&
02563                 (root_at * last_at_axis > 0.95f ))
02564         {
02565                 LLVector3 vel = mAvatarObject->getVelocity();
02566                 if (vel.magVecSquared() > 4.f)
02567                 {
02568                         setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, vel * av_inv_rot);
02569                 }
02570                 else
02571                 {
02572                         // *FIX: rotate mframeagent by sit object's rotation?
02573                         LLQuaternion look_rotation = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation
02574                         LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot;
02575                         setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset);
02576                 }
02577                 last_at_axis = root_at;
02578                 return;
02579         }
02580 
02581         last_at_axis = root_at;
02582         
02583         if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode())
02584         {
02585                 setLookAt(LOOKAT_TARGET_NONE, mAvatarObject, LLVector3(-2.f, 0.f, 0.f));        
02586         }
02587         else
02588         {
02589                 // Move head based on cursor position
02590                 ELookAtType lookAtType = LOOKAT_TARGET_NONE;
02591                 LLVector3 headLookAxis;
02592                 LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance());
02593 
02594                 if (cameraMouselook())
02595                 {
02596                         lookAtType = LOOKAT_TARGET_MOUSELOOK;
02597                 }
02598                 else if (cameraThirdPerson())
02599                 {
02600                         // range from -.5 to .5
02601                         F32 x_from_center = 
02602                                 ((F32) mouse_x / (F32) gViewerWindow->getWindowWidth() ) - 0.5f;
02603                         F32 y_from_center = 
02604                                 ((F32) mouse_y / (F32) gViewerWindow->getWindowHeight() ) - 0.5f;
02605 
02606                         frameCamera.yaw( - x_from_center * gSavedSettings.getF32("YawFromMousePosition") * DEG_TO_RAD);
02607                         frameCamera.pitch( - y_from_center * gSavedSettings.getF32("PitchFromMousePosition") * DEG_TO_RAD);
02608                         lookAtType = LOOKAT_TARGET_FREELOOK;
02609                 }
02610 
02611                 headLookAxis = frameCamera.getAtAxis();
02612                 // RN: we use world-space offset for mouselook and freelook
02613                 //headLookAxis = headLookAxis * av_inv_rot;
02614                 setLookAt(lookAtType, mAvatarObject, headLookAxis);
02615         }
02616 }
02617 
02618 // friends and operators
02619 
02620 std::ostream& operator<<(std::ostream &s, const LLAgent &agent)
02621 {
02622         // This is unfinished, but might never be used. 
02623         // We'll just leave it for now; we can always delete it.
02624         s << " { "
02625           << "  Frame = " << agent.mFrameAgent << "\n"
02626           << " }";
02627         return s;
02628 }
02629 
02630 
02631 // ------------------- Beginning of legacy LLCamera hack ----------------------
02632 // This section is included for legacy LLCamera support until
02633 // it is no longer needed.  Some legacy code must exist in 
02634 // non-legacy functions, and is labeled with "// legacy" comments.
02635 
02636 //-----------------------------------------------------------------------------
02637 // setAvatarObject()
02638 //-----------------------------------------------------------------------------
02639 void LLAgent::setAvatarObject(LLVOAvatar *avatar)                       
02640 { 
02641         mAvatarObject = avatar;
02642 
02643         if (!avatar)
02644         {
02645                 llinfos << "Setting LLAgent::mAvatarObject to NULL" << llendl;
02646                 return;
02647         }
02648 
02649         if (!mLookAt)
02650         {
02651                 mLookAt = (LLHUDEffectLookAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_LOOKAT);
02652         }
02653         if (!mPointAt)
02654         {
02655                 mPointAt = (LLHUDEffectPointAt *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINTAT);
02656         }
02657         
02658         if (!mLookAt.isNull())
02659         {
02660                 mLookAt->setSourceObject(avatar);
02661         }
02662         if (!mPointAt.isNull())
02663         {
02664                 mPointAt->setSourceObject(avatar);
02665         }
02666 
02667         sendAgentWearablesRequest();
02668 }
02669 
02670 // TRUE if your own avatar needs to be rendered.  Usually only
02671 // in third person and build.
02672 //-----------------------------------------------------------------------------
02673 // needsRenderAvatar()
02674 //-----------------------------------------------------------------------------
02675 BOOL LLAgent::needsRenderAvatar()
02676 {
02677         if (cameraMouselook() && !LLVOAvatar::sVisibleInFirstPerson)
02678         {
02679                 return FALSE;
02680         }
02681 
02682         return mShowAvatar && mGenderChosen;
02683 }
02684 
02685 // TRUE if we need to render your own avatar's head.
02686 BOOL LLAgent::needsRenderHead()
02687 {
02688         return mShowAvatar && !cameraMouselook();
02689 }
02690 
02691 //-----------------------------------------------------------------------------
02692 // startTyping()
02693 //-----------------------------------------------------------------------------
02694 void LLAgent::startTyping()
02695 {
02696         mTypingTimer.reset();
02697 
02698         if (getRenderState() & AGENT_STATE_TYPING)
02699         {
02700                 // already typing, don't trigger a different animation
02701                 return;
02702         }
02703         setRenderState(AGENT_STATE_TYPING);
02704 
02705         if (mChatTimer.getElapsedTimeF32() < 2.f)
02706         {
02707                 LLViewerObject* chatter = gObjectList.findObject(mLastChatterID);
02708                 if (chatter && chatter->isAvatar())
02709                 {
02710                         gAgent.setLookAt(LOOKAT_TARGET_RESPOND, chatter, LLVector3::zero);
02711                 }
02712         }
02713 
02714         if (gSavedSettings.getBOOL("PlayTypingAnim"))
02715         {
02716                 sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);
02717         }
02718         gChatBar->sendChatFromViewer("", CHAT_TYPE_START, FALSE);
02719 }
02720 
02721 //-----------------------------------------------------------------------------
02722 // stopTyping()
02723 //-----------------------------------------------------------------------------
02724 void LLAgent::stopTyping()
02725 {
02726         if (mRenderState & AGENT_STATE_TYPING)
02727         {
02728                 clearRenderState(AGENT_STATE_TYPING);
02729                 sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP);
02730                 gChatBar->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);
02731         }
02732 }
02733 
02734 //-----------------------------------------------------------------------------
02735 // setRenderState()
02736 //-----------------------------------------------------------------------------
02737 void LLAgent::setRenderState(U8 newstate)
02738 {
02739         mRenderState |= newstate;
02740 }
02741 
02742 //-----------------------------------------------------------------------------
02743 // clearRenderState()
02744 //-----------------------------------------------------------------------------
02745 void LLAgent::clearRenderState(U8 clearstate)
02746 {
02747         mRenderState &= ~clearstate;
02748 }
02749 
02750 
02751 //-----------------------------------------------------------------------------
02752 // getRenderState()
02753 //-----------------------------------------------------------------------------
02754 U8 LLAgent::getRenderState()
02755 {
02756         if (gNoRender || gKeyboard == NULL)
02757         {
02758                 return 0;
02759         }
02760 
02761         // *FIX: don't do stuff in a getter!  This is infinite loop city!
02762         if ((mTypingTimer.getElapsedTimeF32() > TYPING_TIMEOUT_SECS) 
02763                 && (mRenderState & AGENT_STATE_TYPING))
02764         {
02765                 stopTyping();
02766         }
02767         
02768         if ((!LLSelectMgr::getInstance()->getSelection()->isEmpty() && LLSelectMgr::getInstance()->shouldShowSelection())
02769                 || LLToolMgr::getInstance()->getCurrentTool()->isEditing() )
02770         {
02771                 setRenderState(AGENT_STATE_EDITING);
02772         }
02773         else
02774         {
02775                 clearRenderState(AGENT_STATE_EDITING);
02776         }
02777 
02778         return mRenderState;
02779 }
02780 
02781 //-----------------------------------------------------------------------------
02782 //-----------------------------------------------------------------------------
02783 
02784 static const LLFloaterView::skip_list_t& get_skip_list()
02785 {
02786         static LLFloaterView::skip_list_t skip_list;
02787         skip_list.insert(gFloaterMap);
02788         return skip_list;
02789 }
02790 
02791 //-----------------------------------------------------------------------------
02792 // endAnimationUpdateUI()
02793 //-----------------------------------------------------------------------------
02794 void LLAgent::endAnimationUpdateUI()
02795 {
02796         if (mCameraMode == mLastCameraMode)
02797         {
02798                 // We're already done endAnimationUpdateUI for this transition.
02799                 return;
02800         }
02801 
02802         // clean up UI from mode we're leaving
02803         if ( mLastCameraMode == CAMERA_MODE_MOUSELOOK )
02804         {
02805                 // show mouse cursor
02806                 gViewerWindow->showCursor();
02807                 // show menus
02808                 gMenuBarView->setVisible(TRUE);
02809                 gStatusBar->setVisibleForMouselook(true);
02810 
02811                 LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
02812 
02813                 // Only pop if we have pushed...
02814                 if (TRUE == mViewsPushed)
02815                 {
02816                         mViewsPushed = FALSE;
02817                         gFloaterView->popVisibleAll(get_skip_list());
02818                 }
02819 
02820                 gAgent.setLookAt(LOOKAT_TARGET_CLEAR);
02821                 if( gMorphView )
02822                 {
02823                         gMorphView->setVisible( FALSE );
02824                 }
02825 
02826                 // Disable mouselook-specific animations
02827                 if (mAvatarObject)
02828                 {
02829                         if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )
02830                         {
02831                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_RIFLE_R) != mAvatarObject->mSignaledAnimations.end())
02832                                 {
02833                                         sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_STOP);
02834                                         sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_START);
02835                                 }
02836                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end())
02837                                 {
02838                                         sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_STOP);
02839                                         sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_START);
02840                                 }
02841                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end())
02842                                 {
02843                                         sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_STOP);
02844                                         sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_START);
02845                                 }
02846                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_AIM_BOW_L) != mAvatarObject->mSignaledAnimations.end())
02847                                 {
02848                                         sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_STOP);
02849                                         sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_START);
02850                                 }
02851                         }
02852                 }
02853         }
02854         else
02855         if(     mLastCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR )
02856         {
02857                 // make sure we ask to save changes
02858 
02859                 LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
02860 
02861                 // HACK: If we're quitting, and we were in customize avatar, don't
02862                 // let the mini-map go visible again. JC
02863         if (!LLAppViewer::instance()->quitRequested())
02864                 {
02865                         gFloaterMap->popVisible();
02866                 }
02867 
02868                 if( gMorphView )
02869                 {
02870                         gMorphView->setVisible( FALSE );
02871                 }
02872 
02873                 if (mAvatarObject)
02874                 {
02875                         if(mCustomAnim)
02876                         {
02877                                 sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_STOP);
02878                                 sendAnimationRequest(ANIM_AGENT_CUSTOMIZE_DONE, ANIM_REQUEST_START);
02879 
02880                                 mCustomAnim = FALSE ;
02881                         }
02882                         
02883                 }
02884                 setLookAt(LOOKAT_TARGET_CLEAR);
02885         }
02886 
02887         //---------------------------------------------------------------------
02888         // Set up UI for mode we're entering
02889         //---------------------------------------------------------------------
02890         if (mCameraMode == CAMERA_MODE_MOUSELOOK)
02891         {
02892                 // hide menus
02893                 gMenuBarView->setVisible(FALSE);
02894                 gStatusBar->setVisibleForMouselook(false);
02895 
02896                 // clear out camera lag effect
02897                 mCameraLag.clearVec();
02898 
02899                 // JC - Added for always chat in third person option
02900                 gFocusMgr.setKeyboardFocus(NULL);
02901 
02902                 LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset);
02903 
02904                 mViewsPushed = TRUE;
02905 
02906                 gFloaterView->pushVisibleAll(FALSE, get_skip_list());
02907 
02908                 if( gMorphView )
02909                 {
02910                         gMorphView->setVisible(FALSE);
02911                 }
02912 
02913                 gIMMgr->setFloaterOpen( FALSE );
02914                 gConsole->setVisible( TRUE );
02915 
02916                 if (mAvatarObject)
02917                 {
02918                         // Trigger mouselook-specific animations
02919                         if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_HOLD_ANIMS, NUM_AGENT_GUN_HOLD_ANIMS) )
02920                         {
02921                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_RIFLE_R) != mAvatarObject->mSignaledAnimations.end())
02922                                 {
02923                                         sendAnimationRequest(ANIM_AGENT_HOLD_RIFLE_R, ANIM_REQUEST_STOP);
02924                                         sendAnimationRequest(ANIM_AGENT_AIM_RIFLE_R, ANIM_REQUEST_START);
02925                                 }
02926                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_HANDGUN_R) != mAvatarObject->mSignaledAnimations.end())
02927                                 {
02928                                         sendAnimationRequest(ANIM_AGENT_HOLD_HANDGUN_R, ANIM_REQUEST_STOP);
02929                                         sendAnimationRequest(ANIM_AGENT_AIM_HANDGUN_R, ANIM_REQUEST_START);
02930                                 }
02931                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BAZOOKA_R) != mAvatarObject->mSignaledAnimations.end())
02932                                 {
02933                                         sendAnimationRequest(ANIM_AGENT_HOLD_BAZOOKA_R, ANIM_REQUEST_STOP);
02934                                         sendAnimationRequest(ANIM_AGENT_AIM_BAZOOKA_R, ANIM_REQUEST_START);
02935                                 }
02936                                 if (mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_HOLD_BOW_L) != mAvatarObject->mSignaledAnimations.end())
02937                                 {
02938                                         sendAnimationRequest(ANIM_AGENT_HOLD_BOW_L, ANIM_REQUEST_STOP);
02939                                         sendAnimationRequest(ANIM_AGENT_AIM_BOW_L, ANIM_REQUEST_START);
02940                                 }
02941                         }
02942                         if (mAvatarObject->getParent())
02943                         {
02944                                 LLVector3 at_axis = LLViewerCamera::getInstance()->getAtAxis();
02945                                 LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot();
02946                                 if (root_object->flagCameraDecoupled())
02947                                 {
02948                                         resetAxes(at_axis);
02949                                 }
02950                                 else
02951                                 {
02952                                         resetAxes(at_axis * ~((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation());
02953                                 }
02954                         }
02955                 }
02956 
02957         }
02958         else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR)
02959         {
02960                 LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
02961 
02962                 gFloaterMap->pushVisible(FALSE);
02963                 /*
02964                 LLView *view;
02965                 for (view = gFloaterView->getFirstChild(); view; view = gFloaterView->getNextChild())
02966                 {
02967                         view->pushVisible(FALSE);
02968                 }
02969                 */
02970 
02971                 if( gMorphView )
02972                 {
02973                         gMorphView->setVisible( TRUE );
02974                 }
02975 
02976                 // freeze avatar
02977                 if (mAvatarObject)
02978                 {
02979                         mPauseRequest = mAvatarObject->requestPause();
02980                 }
02981         }
02982 
02983         if (getAvatarObject())
02984         {
02985                 getAvatarObject()->updateAttachmentVisibility(mCameraMode);
02986         }
02987 
02988         gFloaterTools->dirty();
02989 
02990         // Don't let this be called more than once if the camera
02991         // mode hasn't changed.  --JC
02992         mLastCameraMode = mCameraMode;
02993 
02994 }
02995 
02996 
02997 //-----------------------------------------------------------------------------
02998 // updateCamera()
02999 //-----------------------------------------------------------------------------
03000 void LLAgent::updateCamera()
03001 {
03002         //Ventrella - changed camera_skyward to the new global "mCameraUpVector"
03003         mCameraUpVector = LLVector3::z_axis;
03004         //LLVector3     camera_skyward(0.f, 0.f, 1.f);
03005         //end Ventrella
03006 
03007         U32 camera_mode = mCameraAnimating ? mLastCameraMode : mCameraMode;
03008 
03009         validateFocusObject();
03010 
03011         if (!mAvatarObject.isNull() && 
03012                 mAvatarObject->mIsSitting &&
03013                 camera_mode == CAMERA_MODE_MOUSELOOK)
03014         {
03015                 //Ventrella
03016                 //changed camera_skyward to the new global "mCameraUpVector"
03017                 mCameraUpVector = mCameraUpVector * mAvatarObject->getRenderRotation();
03018                 //end Ventrella
03019         }
03020 
03021         if (cameraThirdPerson() && mFocusOnAvatar && LLFollowCamMgr::getActiveFollowCamParams())
03022         {
03023                 changeCameraToFollow();
03024         }
03025 
03026         //Ventrella
03027         //NOTE - this needs to be integrated into a general upVector system here within llAgent. 
03028         if ( camera_mode == CAMERA_MODE_FOLLOW && mFocusOnAvatar )
03029         {
03030                 mCameraUpVector = mFollowCam.getUpVector();
03031         }
03032         //end Ventrella
03033 
03034         if (mSitCameraEnabled)
03035         {
03036                 if (mSitCameraReferenceObject->isDead())
03037                 {
03038                         setSitCamera(LLUUID::null);
03039                 }
03040         }
03041 
03042         // Update UI with our camera inputs
03043         LLFloaterCamera::getInstance()->mRotate->setToggleState(
03044                 mOrbitRightKey > 0.f,   // left
03045                 mOrbitUpKey > 0.f,              // top
03046                 mOrbitLeftKey > 0.f,    // right
03047                 mOrbitDownKey > 0.f);   // bottom
03048 
03049         LLFloaterCamera::getInstance()->mZoom->setToggleState( 
03050                 mOrbitInKey > 0.f,              // top
03051                 mOrbitOutKey > 0.f);    // bottom
03052 
03053         LLFloaterCamera::getInstance()->mTrack->setToggleState(
03054                 mPanLeftKey > 0.f,              // left
03055                 mPanUpKey > 0.f,                // top
03056                 mPanRightKey > 0.f,             // right
03057                 mPanDownKey > 0.f);             // bottom
03058 
03059         // Handle camera movement based on keyboard.
03060         const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD;                  // radians per second
03061         const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD;                // radians per second
03062         const F32 PAN_RATE = 5.f;                                                               // meters per second
03063 
03064         if( mOrbitUpKey || mOrbitDownKey )
03065         {
03066                 F32 input_rate = mOrbitUpKey - mOrbitDownKey;
03067                 cameraOrbitOver( input_rate * ORBIT_OVER_RATE / gFPSClamped );
03068         }
03069 
03070         if( mOrbitLeftKey || mOrbitRightKey)
03071         {
03072                 F32 input_rate = mOrbitLeftKey - mOrbitRightKey;
03073                 cameraOrbitAround( input_rate * ORBIT_AROUND_RATE / gFPSClamped );
03074         }
03075 
03076         if( mOrbitInKey || mOrbitOutKey )
03077         {
03078                 F32 input_rate = mOrbitInKey - mOrbitOutKey;
03079                 
03080                 LLVector3d to_focus = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin()) - calcFocusPositionTargetGlobal();
03081                 F32 distance_to_focus = (F32)to_focus.magVec();
03082                 // Move at distance (in meters) meters per second
03083                 cameraOrbitIn( input_rate * distance_to_focus / gFPSClamped );
03084         }
03085 
03086         if( mPanInKey || mPanOutKey )
03087         {
03088                 F32 input_rate = mPanInKey - mPanOutKey;
03089                 cameraPanIn( input_rate * PAN_RATE / gFPSClamped );
03090         }
03091 
03092         if( mPanRightKey || mPanLeftKey )
03093         {
03094                 F32 input_rate = mPanRightKey - mPanLeftKey;
03095                 cameraPanLeft( input_rate * -PAN_RATE / gFPSClamped );
03096         }
03097 
03098         if( mPanUpKey || mPanDownKey )
03099         {
03100                 F32 input_rate = mPanUpKey - mPanDownKey;
03101                 cameraPanUp( input_rate * PAN_RATE / gFPSClamped );
03102         }
03103 
03104         // Clear camera keyboard keys.
03105         mOrbitLeftKey           = 0.f;
03106         mOrbitRightKey          = 0.f;
03107         mOrbitUpKey                     = 0.f;
03108         mOrbitDownKey           = 0.f;
03109         mOrbitInKey                     = 0.f;
03110         mOrbitOutKey            = 0.f;
03111 
03112         mPanRightKey            = 0.f;
03113         mPanLeftKey                     = 0.f;
03114         mPanUpKey                       = 0.f;
03115         mPanDownKey                     = 0.f;
03116         mPanInKey                       = 0.f;
03117         mPanOutKey                      = 0.f;
03118 
03119         // lerp camera focus offset
03120         mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE));
03121 
03122         //Ventrella
03123         if ( mCameraMode == CAMERA_MODE_FOLLOW )
03124         {
03125                 if ( !mAvatarObject.isNull() )
03126                 {
03127                         //--------------------------------------------------------------------------------
03128                         // this is where the avatar's position and rotation are given to followCam, and 
03129                         // where it is updated. All three of its attributes are updated: (1) position, 
03130                         // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent.
03131                         //--------------------------------------------------------------------------------
03132                         // *TODO: use combined rotation of frameagent and sit object
03133                         LLQuaternion avatarRotationForFollowCam = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion();
03134 
03135                         LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams();
03136                         if (current_cam)
03137                         {
03138                                 mFollowCam.copyParams(*current_cam);
03139                                 mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam );
03140                                 mFollowCam.update();
03141                         }
03142                         else
03143                         {
03144                                 changeCameraToThirdPerson(TRUE);
03145                         }
03146                 }
03147         }
03148         // end Ventrella
03149 
03150         BOOL hit_limit;
03151         LLVector3d camera_pos_global;
03152         LLVector3d camera_target_global = calcCameraPositionTargetGlobal(&hit_limit);
03153         mCameraVirtualPositionAgent = getPosAgentFromGlobal(camera_target_global);
03154         LLVector3d focus_target_global = calcFocusPositionTargetGlobal();
03155 
03156         // perform field of view correction
03157         mCameraFOVZoomFactor = calcCameraFOVZoomFactor();
03158         camera_target_global = focus_target_global + (camera_target_global - focus_target_global) * (1.f + mCameraFOVZoomFactor);
03159 
03160         mShowAvatar = TRUE; // can see avatar by default
03161 
03162         // Adjust position for animation
03163         if (mCameraAnimating)
03164         {
03165                 F32 time = mAnimationTimer.getElapsedTimeF32();
03166 
03167                 // yet another instance of critically damped motion, hooray!
03168                 // F32 fraction_of_animation = 1.f - pow(2.f, -time / CAMERA_ZOOM_HALF_LIFE);
03169 
03170                 // linear interpolation
03171                 F32 fraction_of_animation = time / mAnimationDuration;
03172 
03173                 BOOL isfirstPerson = mCameraMode == CAMERA_MODE_MOUSELOOK;
03174                 BOOL wasfirstPerson = mLastCameraMode == CAMERA_MODE_MOUSELOOK;
03175                 F32 fraction_animation_to_skip;
03176 
03177                 if (mAnimationCameraStartGlobal == camera_target_global)
03178                 {
03179                         fraction_animation_to_skip = 0.f;
03180                 }
03181                 else
03182                 {
03183                         LLVector3d cam_delta = mAnimationCameraStartGlobal - camera_target_global;
03184                         fraction_animation_to_skip = HEAD_BUFFER_SIZE / (F32)cam_delta.magVec();
03185                 }
03186                 F32 animation_start_fraction = (wasfirstPerson) ? fraction_animation_to_skip : 0.f;
03187                 F32 animation_finish_fraction =  (isfirstPerson) ? (1.f - fraction_animation_to_skip) : 1.f;
03188         
03189                 if (fraction_of_animation < animation_finish_fraction)
03190                 {
03191                         if (fraction_of_animation < animation_start_fraction || fraction_of_animation > animation_finish_fraction )
03192                         {
03193                                 mShowAvatar = FALSE;
03194                         }
03195 
03196                         // ...adjust position for animation
03197                         F32 smooth_fraction_of_animation = llsmoothstep(0.0f, 1.0f, fraction_of_animation);
03198                         camera_pos_global = lerp(mAnimationCameraStartGlobal, camera_target_global, smooth_fraction_of_animation);
03199                         mFocusGlobal = lerp(mAnimationFocusStartGlobal, focus_target_global, smooth_fraction_of_animation);
03200                 }
03201                 else
03202                 {
03203                         // ...animation complete
03204                         mCameraAnimating = FALSE;
03205 
03206                         camera_pos_global = camera_target_global;
03207                         mFocusGlobal = focus_target_global;
03208 
03209                         endAnimationUpdateUI();
03210                         mShowAvatar = TRUE;
03211                 }
03212 
03213                 if (getAvatarObject() && mCameraMode != CAMERA_MODE_MOUSELOOK)
03214                 {
03215                         getAvatarObject()->updateAttachmentVisibility(mCameraMode);
03216                 }
03217         }
03218         else 
03219         {
03220                 camera_pos_global = camera_target_global;
03221                 mFocusGlobal = focus_target_global;
03222                 mShowAvatar = TRUE;
03223         }
03224 
03225         // smoothing
03226         if (TRUE)       
03227         {
03228                 LLVector3d agent_pos = getPositionGlobal();
03229                 LLVector3d camera_pos_agent = camera_pos_global - agent_pos;
03230                 
03231                 if (cameraThirdPerson()) // only smooth in third person mode
03232                 {
03233                         F32 smoothing = llclampf(1.f - pow(2.f, -4.f * gSavedSettings.getF32("CameraPositionSmoothing") / gFPSClamped));
03234                         // we use average FPS instead of LLCriticalDamp b/c exact frame time is jittery
03235 
03236                                         
03237                         if (!mFocusObject)  // we differentiate on avatar mode 
03238                         {
03239                                 // for avatar-relative focus, we smooth in avatar space -
03240                                 // the avatar moves too jerkily w/r/t global space to smooth there.
03241 
03242                                 LLVector3d delta = camera_pos_agent - mCameraSmoothingLastPositionAgent;
03243                                 if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE)  // only smooth over short distances please
03244                                 {
03245                                         camera_pos_agent = lerp(camera_pos_agent, mCameraSmoothingLastPositionAgent, smoothing);
03246                                         camera_pos_global = camera_pos_agent + agent_pos;
03247                                 }
03248                         }
03249                         else
03250                         {
03251                                 LLVector3d delta = camera_pos_global - mCameraSmoothingLastPositionGlobal;
03252                                 if (delta.magVec() < MAX_CAMERA_SMOOTH_DISTANCE) // only smooth over short distances please
03253                                 {
03254                                         camera_pos_global = lerp(camera_pos_global, mCameraSmoothingLastPositionGlobal, smoothing);
03255                                 }
03256                         }
03257                 }
03258                                                                  
03259                 mCameraSmoothingLastPositionGlobal = camera_pos_global;
03260                 mCameraSmoothingLastPositionAgent = camera_pos_agent;
03261         }
03262 
03263         
03264         mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE));
03265 
03266 //      llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl;
03267 
03268         F32 ui_offset = 0.f;
03269         if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) 
03270         {
03271                 ui_offset = calcCustomizeAvatarUIOffset( camera_pos_global );
03272         }
03273 
03274 
03275         LLVector3 focus_agent = getPosAgentFromGlobal(mFocusGlobal);
03276         
03277         mCameraPositionAgent    = getPosAgentFromGlobal(camera_pos_global);
03278 
03279         // Move the camera
03280 
03281         //Ventrella
03282         LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent);
03283         //LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent);
03284         //end Ventrella
03285 
03286         //RN: translate UI offset after camera is oriented properly
03287         LLViewerCamera::getInstance()->translate(LLViewerCamera::getInstance()->getLeftAxis() * ui_offset);
03288         
03289         // Change FOV
03290         LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor));
03291 
03292         // follow camera when in customize mode
03293         if (cameraCustomizeAvatar())    
03294         {
03295                 setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent);
03296         }
03297 
03298         // Send the camera position to the spatialized voice system.
03299         if(gVoiceClient && getRegion())
03300         {
03301                 LLMatrix3 rot;
03302                 rot.setRows(LLViewerCamera::getInstance()->getAtAxis(), LLViewerCamera::getInstance()->getLeftAxis (),  LLViewerCamera::getInstance()->getUpAxis());            
03303 
03304                 // MBW -- XXX -- Setting velocity to 0 for now.  May figure it out later...
03305                 gVoiceClient->setCameraPosition(
03306                                 getRegion()->getPosGlobalFromRegion(LLViewerCamera::getInstance()->getOrigin()),// position
03307                                 LLVector3::zero,                        // velocity
03308                                 rot);                                           // rotation matrix
03309         }
03310 
03311         // update the travel distance stat
03312         // this isn't directly related to the camera
03313         // but this seemed like the best place to do this
03314         LLVector3d global_pos = getPositionGlobal(); 
03315         if (! mLastPositionGlobal.isExactlyZero())
03316         {
03317                 LLVector3d delta = global_pos - mLastPositionGlobal;
03318                 mDistanceTraveled += delta.magVec();
03319         }
03320         mLastPositionGlobal = global_pos;
03321         
03322         if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook())
03323         {
03324                 LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + 
03325                         LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() + 
03326                         LLVector3(0.1f, 0.f, 0.f) * mAvatarObject->mPelvisp->getWorldRotation();
03327                 LLVector3 diff = mCameraPositionAgent - head_pos;
03328                 diff = diff * ~mAvatarObject->mRoot.getWorldRotation();
03329 
03330                 LLJoint* torso_joint = mAvatarObject->mTorsop;
03331                 LLJoint* chest_joint = mAvatarObject->mChestp;
03332                 LLVector3 torso_scale = torso_joint->getScale();
03333                 LLVector3 chest_scale = chest_joint->getScale();
03334 
03335                 // shorten avatar skeleton to avoid foot interpenetration
03336                 if (!mAvatarObject->mInAir)
03337                 {
03338                         LLVector3 chest_offset = LLVector3(0.f, 0.f, chest_joint->getPosition().mV[VZ]) * torso_joint->getWorldRotation();
03339                         F32 z_compensate = llclamp(-diff.mV[VZ], -0.2f, 1.f);
03340                         F32 scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / chest_offset.mV[VZ]), 0.5f, 1.2f);
03341                         torso_joint->setScale(LLVector3(1.f, 1.f, scale_factor));
03342 
03343                         LLJoint* neck_joint = mAvatarObject->mNeckp;
03344                         LLVector3 neck_offset = LLVector3(0.f, 0.f, neck_joint->getPosition().mV[VZ]) * chest_joint->getWorldRotation();
03345                         scale_factor = llclamp(1.f - ((z_compensate * 0.5f) / neck_offset.mV[VZ]), 0.5f, 1.2f);
03346                         chest_joint->setScale(LLVector3(1.f, 1.f, scale_factor));
03347                         diff.mV[VZ] = 0.f;
03348                 }
03349 
03350                 mAvatarObject->mPelvisp->setPosition(mAvatarObject->mPelvisp->getPosition() + diff);
03351 
03352                 mAvatarObject->mRoot.updateWorldMatrixChildren();
03353 
03354                 for (LLVOAvatar::attachment_map_t::iterator iter = mAvatarObject->mAttachmentPoints.begin(); 
03355                          iter != mAvatarObject->mAttachmentPoints.end(); )
03356                 {
03357                         LLVOAvatar::attachment_map_t::iterator curiter = iter++;
03358                         LLViewerJointAttachment* attachment = curiter->second;
03359                         LLViewerObject *attached_object = attachment->getObject();
03360                         if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull())
03361                         {
03362                                 // clear any existing "early" movements of attachment
03363                                 attached_object->mDrawable->clearState(LLDrawable::EARLY_MOVE);
03364                                 gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
03365                                 attached_object->updateText();
03366                         }
03367                 }
03368 
03369                 torso_joint->setScale(torso_scale);
03370                 chest_joint->setScale(chest_scale);
03371         }
03372 }
03373 
03374 void LLAgent::updateFocusOffset()
03375 {
03376         validateFocusObject();
03377         if (mFocusObject.notNull())
03378         {
03379                 LLVector3d obj_pos = getPosGlobalFromAgent(mFocusObject->getRenderPosition());
03380                 mFocusObjectOffset.setVec(mFocusTargetGlobal - obj_pos);
03381         }
03382 }
03383 
03384 void LLAgent::validateFocusObject()
03385 {
03386         if (mFocusObject.notNull() && 
03387                 (mFocusObject->isDead()))
03388         {
03389                 mFocusObjectOffset.clearVec();
03390                 clearFocusObject();
03391                 mCameraFOVZoomFactor = 0.f;
03392         }
03393 }
03394 
03395 //-----------------------------------------------------------------------------
03396 // calcCustomizeAvatarUIOffset()
03397 //-----------------------------------------------------------------------------
03398 F32 LLAgent::calcCustomizeAvatarUIOffset( const LLVector3d& camera_pos_global )
03399 {
03400         F32 ui_offset = 0.f;
03401 
03402         if( gFloaterCustomize )
03403         {
03404                 const LLRect& rect = gFloaterCustomize->getRect();
03405 
03406                 // Move the camera so that the avatar isn't covered up by this floater.
03407                 F32 fraction_of_fov = 0.5f - (0.5f * (1.f - llmin(1.f, ((F32)rect.getWidth() / (F32)gViewerWindow->getWindowWidth()))));
03408                 F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect();  // radians
03409                 F32 offset = tan(apparent_angle);
03410 
03411                 if( rect.mLeft < (gViewerWindow->getWindowWidth() - rect.mRight) )
03412                 {
03413                         // Move the avatar to the right (camera to the left)
03414                         ui_offset = offset;
03415                 }
03416                 else
03417                 {
03418                         // Move the avatar to the left (camera to the right)
03419                         ui_offset = -offset;
03420                 }
03421         }
03422         F32 range = (F32)dist_vec(camera_pos_global, gAgent.getFocusGlobal());
03423         mUIOffset = lerp(mUIOffset, ui_offset, LLCriticalDamp::getInterpolant(0.05f));
03424         return mUIOffset * range;
03425 }
03426 
03427 //-----------------------------------------------------------------------------
03428 // calcFocusPositionTargetGlobal()
03429 //-----------------------------------------------------------------------------
03430 LLVector3d LLAgent::calcFocusPositionTargetGlobal()
03431 {
03432         if (mFocusObject.notNull() && mFocusObject->isDead())
03433         {
03434                 clearFocusObject();
03435         }
03436 
03437         // Ventrella
03438         if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar )
03439         {
03440                 mFocusTargetGlobal = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedFocus());
03441                 return mFocusTargetGlobal;
03442         }// End Ventrella 
03443         else if (mCameraMode == CAMERA_MODE_MOUSELOOK)
03444         {
03445                 LLVector3d at_axis(1.0, 0.0, 0.0);
03446                 LLQuaternion agent_rot = mFrameAgent.getQuaternion();
03447                 if (!mAvatarObject.isNull() && mAvatarObject->getParent())
03448                 {
03449                         LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot();
03450                         if (!root_object->flagCameraDecoupled())
03451                         {
03452                                 agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation();
03453                         }
03454                 }
03455                 at_axis = at_axis * agent_rot;
03456                 mFocusTargetGlobal = calcCameraPositionTargetGlobal() + at_axis;
03457                 return mFocusTargetGlobal;
03458         }
03459         else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR)
03460         {
03461                 return mFocusTargetGlobal;
03462         }
03463         else if (!mFocusOnAvatar)
03464         {
03465                 if (mFocusObject.notNull() && !mFocusObject->isDead() && mFocusObject->mDrawable.notNull())
03466                 {
03467                         LLDrawable* drawablep = mFocusObject->mDrawable;
03468                         
03469                         if (mTrackFocusObject &&
03470                                 drawablep && 
03471                                 drawablep->isActive())
03472                         {
03473                                 if (!mFocusObject->isAvatar())
03474                                 {
03475                                         if (mFocusObject->isSelected())
03476                                         {
03477                                                 gPipeline.updateMoveNormalAsync(drawablep);
03478                                         }
03479                                         else
03480                                         {
03481                                                 if (drawablep->isState(LLDrawable::MOVE_UNDAMPED))
03482                                                 {
03483                                                         gPipeline.updateMoveNormalAsync(drawablep);
03484                                                 }
03485                                                 else
03486                                                 {
03487                                                         gPipeline.updateMoveDampedAsync(drawablep);
03488                                                 }
03489                                         }
03490                                 }
03491                         }
03492                         // if not tracking object, update offset based on new object position
03493                         else
03494                         {
03495                                 updateFocusOffset();
03496                         }
03497                         LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset;
03498                         mFocusTargetGlobal.setVec(getPosGlobalFromAgent(focus_agent));
03499                 }
03500                 return mFocusTargetGlobal;
03501         }
03502         else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->mIsSitting && mSitCameraReferenceObject.notNull())
03503         {
03504                 // sit camera
03505                 LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition();
03506                 LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation();
03507 
03508                 LLVector3 target_pos = object_pos + (mSitCameraFocus * object_rot);
03509                 return getPosGlobalFromAgent(target_pos);
03510         }
03511         else
03512         {
03513                 // ...offset from avatar
03514                 LLVector3d focus_offset;
03515                 focus_offset.setVec(gSavedSettings.getVector3("FocusOffsetDefault"));
03516 
03517                 LLQuaternion agent_rot = mFrameAgent.getQuaternion();
03518                 if (!mAvatarObject.isNull() && mAvatarObject->getParent())
03519                 {
03520                         agent_rot *= ((LLViewerObject*)(mAvatarObject->getParent()))->getRenderRotation();
03521                 }
03522 
03523                 focus_offset = focus_offset * agent_rot;
03524 
03525                 return getPositionGlobal() + focus_offset;
03526         }
03527 }
03528 
03529 void LLAgent::setupSitCamera()
03530 {
03531         // agent frame entering this function is in world coordinates
03532         if (mAvatarObject.notNull() && mAvatarObject->getParent())
03533         {
03534                 LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
03535                 // slam agent coordinate frame to proper parent local version
03536                 LLVector3 at_axis = mFrameAgent.getAtAxis();
03537                 at_axis.mV[VZ] = 0.f;
03538                 at_axis.normVec();
03539                 resetAxes(at_axis * ~parent_rot);
03540         }
03541 }
03542 
03543 //-----------------------------------------------------------------------------
03544 // getCameraPositionAgent()
03545 //-----------------------------------------------------------------------------
03546 const LLVector3 &LLAgent::getCameraPositionAgent() const
03547 {
03548         return LLViewerCamera::getInstance()->getOrigin();
03549 }
03550 
03551 //-----------------------------------------------------------------------------
03552 // getCameraPositionGlobal()
03553 //-----------------------------------------------------------------------------
03554 LLVector3d LLAgent::getCameraPositionGlobal() const
03555 {
03556         return getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin());
03557 }
03558 
03559 //-----------------------------------------------------------------------------
03560 // calcCameraFOVZoomFactor()
03561 //-----------------------------------------------------------------------------
03562 F32     LLAgent::calcCameraFOVZoomFactor()
03563 {
03564         LLVector3 camera_offset_dir;
03565         camera_offset_dir.setVec(mCameraFocusOffset);
03566 
03567         if (mCameraMode == CAMERA_MODE_MOUSELOOK)
03568         {
03569                 return 0.f;
03570         }
03571         else if (mFocusObject.notNull() && !mFocusObject->isAvatar())
03572         {
03573                 // don't FOV zoom on mostly transparent objects
03574                 LLVector3 focus_offset = mFocusObjectOffset;
03575                 F32 obj_min_dist = 0.f;
03576                 calcCameraMinDistance(obj_min_dist);
03577                 F32 current_distance = llmax(0.001f, camera_offset_dir.magVec());
03578 
03579                 mFocusObjectDist = obj_min_dist - current_distance;
03580 
03581                 F32 new_fov_zoom = llclamp(mFocusObjectDist / current_distance, 0.f, 1000.f);
03582                 return new_fov_zoom;
03583         }
03584         else // focusing on land or avatar
03585         {
03586                 // keep old field of view until user changes focus explicitly
03587                 return mCameraFOVZoomFactor;
03588                 //return 0.f;
03589         }
03590 }
03591 
03592 //-----------------------------------------------------------------------------
03593 // calcCameraPositionTargetGlobal()
03594 //-----------------------------------------------------------------------------
03595 LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
03596 {
03597         // Compute base camera position and look-at points.
03598         F32                     camera_land_height;
03599         LLVector3d      frame_center_global = mAvatarObject.isNull() ? getPositionGlobal() 
03600                                                                                                                          : getPosGlobalFromAgent(mAvatarObject->mRoot.getWorldPosition());
03601                 
03602         LLVector3   upAxis = getUpAxis();
03603         BOOL            isConstrained = FALSE;
03604         LLVector3d      head_offset;
03605         head_offset.setVec(mThirdPersonHeadOffset);
03606 
03607         LLVector3d camera_position_global;
03608 
03609         // Ventrella 
03610         if ( mCameraMode == CAMERA_MODE_FOLLOW && mFocusOnAvatar )
03611         {
03612                 camera_position_global = gAgent.getPosGlobalFromAgent(mFollowCam.getSimulatedPosition());
03613         }// End Ventrella
03614         else if (mCameraMode == CAMERA_MODE_MOUSELOOK)
03615         {
03616                 if (mAvatarObject.isNull() || mAvatarObject->mDrawable.isNull())
03617                 {
03618                         llwarns << "Null avatar drawable!" << llendl;
03619                         return LLVector3d::zero;
03620                 }
03621                 head_offset.clearVec();
03622                 if (mAvatarObject->mIsSitting && mAvatarObject->getParent())
03623                 {
03624                         mAvatarObject->updateHeadOffset();
03625                         head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX];
03626                         head_offset.mdV[VY] = mAvatarObject->mHeadOffset.mV[VY];
03627                         head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ] + 0.1f;
03628                         const LLMatrix4& mat = ((LLViewerObject*) mAvatarObject->getParent())->getRenderMatrix();
03629                         camera_position_global = getPosGlobalFromAgent
03630                                                                 ((mAvatarObject->getPosition()+
03631                                                                  LLVector3(head_offset)*mAvatarObject->getRotation()) * mat);
03632                 }
03633                 else
03634                 {
03635                         head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ];
03636                         if (mAvatarObject->mIsSitting)
03637                         {
03638                                 head_offset.mdV[VZ] += 0.1;
03639                         }
03640                         camera_position_global = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());//frame_center_global;
03641                         head_offset = head_offset * mAvatarObject->getRenderRotation();
03642                         camera_position_global = camera_position_global + head_offset;
03643                 }
03644         }
03645         else if (mCameraMode == CAMERA_MODE_THIRD_PERSON && mFocusOnAvatar)
03646         {
03647                 LLVector3 local_camera_offset;
03648                 F32 camera_distance = 0.f;
03649 
03650                 if (mSitCameraEnabled 
03651                         && mAvatarObject.notNull() 
03652                         && mAvatarObject->mIsSitting 
03653                         && mSitCameraReferenceObject.notNull())
03654                 {
03655                         // sit camera
03656                         LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition();
03657                         LLQuaternion object_rot = mSitCameraReferenceObject->getRenderRotation();
03658 
03659                         LLVector3 target_pos = object_pos + (mSitCameraPos * object_rot);
03660 
03661                         camera_position_global = getPosGlobalFromAgent(target_pos);
03662                 }
03663                 else
03664                 {
03665                         local_camera_offset = mCameraZoomFraction * mCameraOffsetDefault;
03666                         
03667                         // are we sitting down?
03668                         if (mAvatarObject.notNull() && mAvatarObject->getParent())
03669                         {
03670                                 LLQuaternion parent_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
03671                                 // slam agent coordinate frame to proper parent local version
03672                                 LLVector3 at_axis = mFrameAgent.getAtAxis() * parent_rot;
03673                                 at_axis.mV[VZ] = 0.f;
03674                                 at_axis.normVec();
03675                                 resetAxes(at_axis * ~parent_rot);
03676 
03677                                 local_camera_offset = local_camera_offset * mFrameAgent.getQuaternion() * parent_rot;
03678                         }
03679                         else
03680                         {
03681                                 local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset );
03682                         }
03683 
03684                         if (!mCameraCollidePlane.isExactlyZero() && (mAvatarObject.isNull() || !mAvatarObject->mIsSitting))
03685                         {
03686                                 LLVector3 plane_normal;
03687                                 plane_normal.setVec(mCameraCollidePlane.mV);
03688 
03689                                 F32 offset_dot_norm = local_camera_offset * plane_normal;
03690                                 if (llabs(offset_dot_norm) < 0.001f)
03691                                 {
03692                                         offset_dot_norm = 0.001f;
03693                                 }
03694                                 
03695                                 camera_distance = local_camera_offset.normVec();
03696 
03697                                 F32 pos_dot_norm = getPosAgentFromGlobal(frame_center_global + head_offset) * plane_normal;
03698                                 
03699                                 // if agent is outside the colliding half-plane
03700                                 if (pos_dot_norm > mCameraCollidePlane.mV[VW])
03701                                 {
03702                                         // check to see if camera is on the opposite side (inside) the half-plane
03703                                         if (offset_dot_norm + pos_dot_norm < mCameraCollidePlane.mV[VW])
03704                                         {
03705                                                 // diminish offset by factor to push it back outside the half-plane
03706                                                 camera_distance *= (pos_dot_norm - mCameraCollidePlane.mV[VW] - CAMERA_COLLIDE_EPSILON) / -offset_dot_norm;
03707                                         }
03708                                 }
03709                                 else
03710                                 {
03711                                         if (offset_dot_norm + pos_dot_norm > mCameraCollidePlane.mV[VW])
03712                                         {
03713                                                 camera_distance *= (mCameraCollidePlane.mV[VW] - pos_dot_norm - CAMERA_COLLIDE_EPSILON) / offset_dot_norm;
03714                                         }
03715                                 }
03716                         }
03717                         else
03718                         {
03719                                 camera_distance = local_camera_offset.normVec();
03720                         }
03721 
03722                         mTargetCameraDistance = llmax(camera_distance, MIN_CAMERA_DISTANCE);
03723 
03724                         if (mTargetCameraDistance != mCurrentCameraDistance)
03725                         {
03726                                 F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE);
03727 
03728                                 mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt);
03729                         }
03730 
03731                         // Make the camera distance current
03732                         local_camera_offset *= mCurrentCameraDistance;
03733 
03734                         // set the global camera position
03735                         LLVector3d camera_offset;
03736                         
03737                         LLVector3 av_pos = mAvatarObject.isNull() ? LLVector3::zero : mAvatarObject->getRenderPosition();
03738                         camera_offset.setVec( local_camera_offset );
03739                         camera_position_global = frame_center_global + head_offset + camera_offset;
03740 
03741                         if (!mAvatarObject.isNull())
03742                         {
03743                                 LLVector3d camera_lag_d;
03744                                 F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE);
03745                                 LLVector3 target_lag;
03746                                 LLVector3 vel = getVelocity();
03747 
03748                                 // lag by appropriate amount for flying
03749                                 F32 time_in_air = mAvatarObject->mTimeInAir.getElapsedTimeF32();
03750                                 if(!mCameraAnimating && mAvatarObject->mInAir && time_in_air > GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME)
03751                                 {
03752                                         LLVector3 frame_at_axis = mFrameAgent.getAtAxis();
03753                                         frame_at_axis -= projected_vec(frame_at_axis, getReferenceUpVector());
03754                                         frame_at_axis.normVec();
03755 
03756                                         //transition smoothly in air mode, to avoid camera pop
03757                                         F32 u = (time_in_air - GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME) / GROUND_TO_AIR_CAMERA_TRANSITION_TIME;
03758                                         u = llclamp(u, 0.f, 1.f);
03759 
03760                                         lag_interp *= u;
03761 
03762                                         if (gViewerWindow->getLeftMouseDown() && gLastHitObjectID == mAvatarObject->getID())
03763                                         {
03764                                                 // disable camera lag when using mouse-directed steering
03765                                                 target_lag.clearVec();
03766                                         }
03767                                         else
03768                                         {
03769                                                 target_lag = vel * gSavedSettings.getF32("DynamicCameraStrength") / 30.f;
03770                                         }
03771 
03772                                         mCameraLag = lerp(mCameraLag, target_lag, lag_interp);
03773 
03774                                         F32 lag_dist = mCameraLag.magVec();
03775                                         if (lag_dist > MAX_CAMERA_LAG)
03776                                         {
03777                                                 mCameraLag = mCameraLag * MAX_CAMERA_LAG / lag_dist;
03778                                         }
03779 
03780                                         // clamp camera lag so that avatar is always in front
03781                                         F32 dot = (mCameraLag - (frame_at_axis * (MIN_CAMERA_LAG * u))) * frame_at_axis;
03782                                         if (dot < -(MIN_CAMERA_LAG * u))
03783                                         {
03784                                                 mCameraLag -= (dot + (MIN_CAMERA_LAG * u)) * frame_at_axis;
03785                                         }
03786                                 }
03787                                 else
03788                                 {
03789                                         mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f));
03790                                 }
03791 
03792                                 camera_lag_d.setVec(mCameraLag);
03793                                 camera_position_global = camera_position_global - camera_lag_d;
03794                         }
03795                 }
03796         }
03797         else
03798         {
03799                 LLVector3d focusPosGlobal = calcFocusPositionTargetGlobal();
03800                 // camera gets pushed out later wrt mCameraFOVZoomFactor...this is "raw" value
03801                 camera_position_global = focusPosGlobal + mCameraFocusOffset;
03802         }
03803 
03804         if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike())
03805         {
03806                 LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(
03807                         camera_position_global);
03808                 bool constrain = true;
03809                 if(regionp && regionp->canManageEstate())
03810                 {
03811                         constrain = false;
03812                 }
03813                 if(constrain)
03814                 {
03815                         F32 max_dist = ( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) ?
03816                                 APPEARANCE_MAX_ZOOM : MAX_CAMERA_DISTANCE_FROM_AGENT;
03817 
03818                         LLVector3d camera_offset = camera_position_global
03819                                 - gAgent.getPositionGlobal();
03820                         F32 camera_distance = (F32)camera_offset.magVec();
03821 
03822                         if(camera_distance > max_dist)
03823                         {
03824                                 camera_position_global = gAgent.getPositionGlobal() + 
03825                                         (max_dist / camera_distance) * camera_offset;
03826                                 isConstrained = TRUE;
03827                         }
03828                 }
03829 
03830 // JC - Could constrain camera based on parcel stuff here.
03831 //                      LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global);
03832 //                      
03833 //                      if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global)))
03834 //                      {
03835 //                              camera_position_global = last_position_global;
03836 //
03837 //                              isConstrained = TRUE;
03838 //                      }
03839         }
03840 
03841         // Don't let camera go underground
03842         F32 camera_min_off_ground = getCameraMinOffGround();
03843 
03844         camera_land_height = LLWorld::getInstance()->resolveLandHeightGlobal(camera_position_global);
03845 
03846         if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground)
03847         {
03848                 camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground;
03849                 isConstrained = TRUE;
03850         }
03851 
03852 
03853         if (hit_limit)
03854         {
03855                 *hit_limit = isConstrained;
03856         }
03857 
03858         return camera_position_global;
03859 }
03860 
03861 
03862 //-----------------------------------------------------------------------------
03863 // handleScrollWheel()
03864 //-----------------------------------------------------------------------------
03865 void LLAgent::handleScrollWheel(S32 clicks)
03866 {
03867         if ( mCameraMode == CAMERA_MODE_FOLLOW && gAgent.getFocusOnAvatar())
03868         {
03869                 if ( ! mFollowCam.getPositionLocked() ) // not if the followCam position is locked in place
03870                 {
03871                         mFollowCam.zoom( clicks ); 
03872                         if ( mFollowCam.isZoomedToMinimumDistance() )
03873                         {
03874                                 changeCameraToMouselook(FALSE);
03875                         }
03876                 }
03877         }
03878         else
03879         {
03880                 LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
03881                 const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2);
03882 
03883                 // Block if camera is animating
03884                 if (mCameraAnimating)
03885                 {
03886                         return;
03887                 }
03888 
03889                 if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD)
03890                 {
03891                         F32 zoom_factor = (F32)pow(0.8, -clicks);
03892                         cameraZoomIn(zoom_factor);
03893                 }
03894                 else if (mFocusOnAvatar && mCameraMode == CAMERA_MODE_THIRD_PERSON)
03895                 {
03896                         F32 current_zoom_fraction = mTargetCameraDistance / mCameraOffsetDefault.magVec();
03897                         current_zoom_fraction *= 1.f - pow(ROOT_ROOT_TWO, clicks);
03898                         
03899                         cameraOrbitIn(current_zoom_fraction * mCameraOffsetDefault.magVec());
03900                 }
03901                 else
03902                 {
03903                         F32 current_zoom_fraction = (F32)mCameraFocusOffsetTarget.magVec();
03904                         cameraOrbitIn(current_zoom_fraction * (1.f - pow(ROOT_ROOT_TWO, clicks)));
03905                 }
03906         }
03907 }
03908 
03909 
03910 //-----------------------------------------------------------------------------
03911 // getCameraMinOffGround()
03912 //-----------------------------------------------------------------------------
03913 F32 LLAgent::getCameraMinOffGround()
03914 {
03915         if (mCameraMode == CAMERA_MODE_MOUSELOOK)
03916         {
03917                 return 0.f;
03918         }
03919         else
03920         {
03921                 if (gSavedSettings.getBOOL("DisableCameraConstraints"))
03922                 {
03923                         return -1000.f;
03924                 }
03925                 else
03926                 {
03927                         return 0.5f;
03928                 }
03929         }
03930 }
03931 
03932 
03933 //-----------------------------------------------------------------------------
03934 // resetCamera()
03935 //-----------------------------------------------------------------------------
03936 void LLAgent::resetCamera()
03937 {
03938         // Remove any pitch from the avatar
03939         LLVector3 at = mFrameAgent.getAtAxis();
03940         at.mV[VZ] = 0.f;
03941         at.normVec();
03942         gAgent.resetAxes(at);
03943         // have to explicitly clear field of view zoom now
03944         mCameraFOVZoomFactor = 0.f;
03945 
03946         updateCamera();
03947 }
03948 
03949 //-----------------------------------------------------------------------------
03950 // changeCameraToMouselook()
03951 //-----------------------------------------------------------------------------
03952 void LLAgent::changeCameraToMouselook(BOOL animate)
03953 {
03954         // visibility changes at end of animation
03955         gViewerWindow->getWindow()->resetBusyCount();
03956 
03957         // unpause avatar animation
03958         mPauseRequest = NULL;
03959 
03960         LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset);
03961 
03962         gSavedSettings.setBOOL("FirstPersonBtnState",   FALSE);
03963         gSavedSettings.setBOOL("MouselookBtnState",             TRUE);
03964         gSavedSettings.setBOOL("ThirdPersonBtnState",   FALSE);
03965         gSavedSettings.setBOOL("BuildBtnState",                 FALSE);
03966 
03967         if (mAvatarObject)
03968         {
03969                 mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE );
03970                 mAvatarObject->stopMotion( ANIM_AGENT_BREATHE_ROT );
03971         }
03972 
03973         //gViewerWindow->stopGrab();
03974         LLSelectMgr::getInstance()->deselectAll();
03975         gViewerWindow->hideCursor();
03976         gViewerWindow->moveCursorToCenter();
03977 
03978         if( mCameraMode != CAMERA_MODE_MOUSELOOK )
03979         {
03980                 gViewerWindow->setKeyboardFocus( NULL );
03981                 
03982                 mLastCameraMode = mCameraMode;
03983                 mCameraMode = CAMERA_MODE_MOUSELOOK;
03984                 U32 old_flags = mControlFlags;
03985                 setControlFlags(AGENT_CONTROL_MOUSELOOK);
03986                 if (old_flags != mControlFlags)
03987                 {
03988                         mbFlagsDirty = TRUE;
03989                 }
03990 
03991                 if (animate)
03992                 {
03993                         startCameraAnimation();
03994                 }
03995                 else
03996                 {
03997                         mCameraAnimating = FALSE;
03998                         endAnimationUpdateUI();
03999                 }
04000         }
04001 }
04002 
04003 
04004 //-----------------------------------------------------------------------------
04005 // changeCameraToDefault()
04006 //-----------------------------------------------------------------------------
04007 void LLAgent::changeCameraToDefault()
04008 {
04009         if (LLFollowCamMgr::getActiveFollowCamParams())
04010         {
04011                 changeCameraToFollow();
04012         }
04013         else
04014         {
04015                 changeCameraToThirdPerson();
04016         }
04017 }
04018 
04019 
04020 // Ventrella
04021 //-----------------------------------------------------------------------------
04022 // changeCameraToFollow()
04023 //-----------------------------------------------------------------------------
04024 void LLAgent::changeCameraToFollow(BOOL animate)
04025 {
04026         if( mCameraMode != CAMERA_MODE_FOLLOW )
04027         {
04028                 if (mCameraMode == CAMERA_MODE_MOUSELOOK)
04029                 {
04030                         animate = FALSE;
04031                 }
04032                 startCameraAnimation();
04033 
04034                 mLastCameraMode = mCameraMode;
04035                 mCameraMode = CAMERA_MODE_FOLLOW;
04036 
04037                 // bang-in the current focus, position, and up vector of the follow cam
04038                 mFollowCam.reset( mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis );
04039                 
04040                 if (gBasicToolset)
04041                 {
04042                         LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
04043                 }
04044 
04045                 if (mAvatarObject)
04046                 {
04047                         mAvatarObject->mPelvisp->setPosition(LLVector3::zero);
04048                         mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE );
04049                         mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT );
04050                 }
04051 
04052                 gSavedSettings.setBOOL("FirstPersonBtnState",   FALSE);
04053                 gSavedSettings.setBOOL("MouselookBtnState",             FALSE);
04054                 gSavedSettings.setBOOL("ThirdPersonBtnState",   TRUE);
04055                 gSavedSettings.setBOOL("BuildBtnState",                 FALSE);
04056 
04057                 // unpause avatar animation
04058                 mPauseRequest = NULL;
04059 
04060                 U32 old_flags = mControlFlags;
04061                 clearControlFlags(AGENT_CONTROL_MOUSELOOK);
04062                 if (old_flags != mControlFlags)
04063                 {
04064                         mbFlagsDirty = TRUE;
04065                 }
04066 
04067                 if (animate)
04068                 {
04069                         startCameraAnimation();
04070                 }
04071                 else
04072                 {
04073                         mCameraAnimating = FALSE;
04074                         endAnimationUpdateUI();
04075                 }
04076         }
04077 }
04078 
04079 //-----------------------------------------------------------------------------
04080 // changeCameraToThirdPerson()
04081 //-----------------------------------------------------------------------------
04082 void LLAgent::changeCameraToThirdPerson(BOOL animate)
04083 {
04084 //printf( "changeCameraToThirdPerson\n" );
04085 
04086         gViewerWindow->getWindow()->resetBusyCount();
04087 
04088         mCameraZoomFraction = INITIAL_ZOOM_FRACTION;
04089 
04090         if (mAvatarObject)
04091         {
04092                 mAvatarObject->mPelvisp->setPosition(LLVector3::zero);
04093                 mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE );
04094                 mAvatarObject->startMotion( ANIM_AGENT_BREATHE_ROT );
04095         }
04096 
04097         gSavedSettings.setBOOL("FirstPersonBtnState",   FALSE);
04098         gSavedSettings.setBOOL("MouselookBtnState",             FALSE);
04099         gSavedSettings.setBOOL("ThirdPersonBtnState",   TRUE);
04100         gSavedSettings.setBOOL("BuildBtnState",                 FALSE);
04101 
04102         LLVector3 at_axis;
04103 
04104         // unpause avatar animation
04105         mPauseRequest = NULL;
04106 
04107         if( mCameraMode != CAMERA_MODE_THIRD_PERSON )
04108         {
04109                 if (gBasicToolset)
04110                 {
04111                         LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
04112                 }
04113 
04114                 mCameraLag.clearVec();
04115                 if (mCameraMode == CAMERA_MODE_MOUSELOOK)
04116                 {
04117                         mCurrentCameraDistance = MIN_CAMERA_DISTANCE;
04118                         mTargetCameraDistance = MIN_CAMERA_DISTANCE;
04119                         animate = FALSE;
04120                 }
04121                 mLastCameraMode = mCameraMode;
04122                 mCameraMode = CAMERA_MODE_THIRD_PERSON;
04123                 U32 old_flags = mControlFlags;
04124                 clearControlFlags(AGENT_CONTROL_MOUSELOOK);
04125                 if (old_flags != mControlFlags)
04126                 {
04127                         mbFlagsDirty = TRUE;
04128                 }
04129 
04130         }
04131 
04132         // Remove any pitch from the avatar
04133         if (!mAvatarObject.isNull() && mAvatarObject->getParent())
04134         {
04135                 LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
04136                 at_axis = LLViewerCamera::getInstance()->getAtAxis();
04137                 at_axis.mV[VZ] = 0.f;
04138                 at_axis.normVec();
04139                 resetAxes(at_axis * ~obj_rot);
04140         }
04141         else
04142         {
04143                 at_axis = mFrameAgent.getAtAxis();
04144                 at_axis.mV[VZ] = 0.f;
04145                 at_axis.normVec();
04146                 resetAxes(at_axis);
04147         }
04148 
04149 
04150         if (animate)
04151         {
04152                 startCameraAnimation();
04153         }
04154         else
04155         {
04156                 mCameraAnimating = FALSE;
04157                 endAnimationUpdateUI();
04158         }
04159 }
04160 
04161 //-----------------------------------------------------------------------------
04162 // changeCameraToCustomizeAvatar()
04163 //-----------------------------------------------------------------------------
04164 void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_animate)
04165 {
04166         setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up
04167         gViewerWindow->getWindow()->resetBusyCount();
04168 
04169         if (gFaceEditToolset)
04170         {
04171                 LLToolMgr::getInstance()->setCurrentToolset(gFaceEditToolset);
04172         }
04173 
04174         gSavedSettings.setBOOL("FirstPersonBtnState", FALSE);
04175         gSavedSettings.setBOOL("MouselookBtnState", FALSE);
04176         gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE);
04177         gSavedSettings.setBOOL("BuildBtnState", FALSE);
04178 
04179         if (camera_animate)
04180         {
04181                 startCameraAnimation();
04182         }
04183 
04184         // Remove any pitch from the avatar
04185         //LLVector3 at = mFrameAgent.getAtAxis();
04186         //at.mV[VZ] = 0.f;
04187         //at.normVec();
04188         //gAgent.resetAxes(at);
04189 
04190         if( mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR )
04191         {
04192                 mLastCameraMode = mCameraMode;
04193                 mCameraMode = CAMERA_MODE_CUSTOMIZE_AVATAR;
04194                 U32 old_flags = mControlFlags;
04195                 clearControlFlags(AGENT_CONTROL_MOUSELOOK);
04196                 if (old_flags != mControlFlags)
04197                 {
04198                         mbFlagsDirty = TRUE;
04199                 }
04200 
04201                 gViewerWindow->setKeyboardFocus( NULL );
04202                 gViewerWindow->setMouseCapture( NULL );
04203 
04204                 LLVOAvatar::onCustomizeStart();
04205         }
04206 
04207         if (!mAvatarObject.isNull())
04208         {
04209                 if(avatar_animate)
04210                 {
04211                                 // Remove any pitch from the avatar
04212                         LLVector3 at = mFrameAgent.getAtAxis();
04213                         at.mV[VZ] = 0.f;
04214                         at.normVec();
04215                         gAgent.resetAxes(at);
04216 
04217                         sendAnimationRequest(ANIM_AGENT_CUSTOMIZE, ANIM_REQUEST_START);
04218                         mCustomAnim = TRUE ;
04219                         mAvatarObject->startMotion(ANIM_AGENT_CUSTOMIZE);
04220                         LLMotion* turn_motion = mAvatarObject->findMotion(ANIM_AGENT_CUSTOMIZE);
04221 
04222                         if (turn_motion)
04223                         {
04224                                 mAnimationDuration = turn_motion->getDuration() + CUSTOMIZE_AVATAR_CAMERA_ANIM_SLOP;
04225 
04226                         }
04227                         else
04228                         {
04229                                 mAnimationDuration = gSavedSettings.getF32("ZoomTime");
04230                         }
04231                 }
04232 
04233 
04234 
04235                 gAgent.setFocusGlobal(LLVector3d::zero);
04236         }
04237         else
04238         {
04239                 mCameraAnimating = FALSE;
04240                 endAnimationUpdateUI();
04241         }
04242 
04243 }
04244 
04245 
04246 //
04247 // Focus point management
04248 //
04249 
04250 //-----------------------------------------------------------------------------
04251 // startCameraAnimation()
04252 //-----------------------------------------------------------------------------
04253 void LLAgent::startCameraAnimation()
04254 {
04255         mAnimationCameraStartGlobal = getCameraPositionGlobal();
04256         mAnimationFocusStartGlobal = mFocusGlobal;
04257         mAnimationTimer.reset();
04258         mCameraAnimating = TRUE;
04259         mAnimationDuration = gSavedSettings.getF32("ZoomTime");
04260 }
04261 
04262 //-----------------------------------------------------------------------------
04263 // stopCameraAnimation()
04264 //-----------------------------------------------------------------------------
04265 void LLAgent::stopCameraAnimation()
04266 {
04267         mCameraAnimating = FALSE;
04268 }
04269 
04270 void LLAgent::clearFocusObject()
04271 {
04272         if (mFocusObject.notNull())
04273         {
04274                 startCameraAnimation();
04275 
04276                 setFocusObject(NULL);
04277                 mFocusObjectOffset.clearVec();
04278         }
04279 }
04280 
04281 void LLAgent::setFocusObject(LLViewerObject* object)
04282 {
04283         mFocusObject = object;
04284 }
04285 
04286 // Focus on a point, but try to keep camera position stable.
04287 //-----------------------------------------------------------------------------
04288 // setFocusGlobal()
04289 //-----------------------------------------------------------------------------
04290 void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id)
04291 {
04292         setFocusObject(gObjectList.findObject(object_id));
04293         LLVector3d old_focus = mFocusTargetGlobal;
04294         LLViewerObject *focus_obj = mFocusObject;
04295 
04296         // if focus has changed
04297         if (old_focus != focus)
04298         {
04299                 if (focus.isExactlyZero())
04300                 {
04301                         if (!mAvatarObject.isNull())
04302                         {
04303                                 mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition());
04304                         }
04305                         else
04306                         {
04307                                 mFocusTargetGlobal = getPositionGlobal();
04308                         }
04309                         mCameraFocusOffsetTarget = getCameraPositionGlobal() - mFocusTargetGlobal;
04310                         mCameraFocusOffset = mCameraFocusOffsetTarget;
04311                         setLookAt(LOOKAT_TARGET_CLEAR);
04312                 }
04313                 else
04314                 {
04315                         mFocusTargetGlobal = focus;
04316                         if (!focus_obj)
04317                         {
04318                                 mCameraFOVZoomFactor = 0.f;
04319                         }
04320 
04321                         mCameraFocusOffsetTarget = gAgent.getPosGlobalFromAgent(mCameraVirtualPositionAgent) - mFocusTargetGlobal;
04322 
04323                         startCameraAnimation();
04324 
04325                         if (focus_obj)
04326                         {
04327                                 if (focus_obj->isAvatar())
04328                                 {
04329                                         setLookAt(LOOKAT_TARGET_FOCUS, focus_obj);
04330                                 }
04331                                 else
04332                                 {
04333                                         setLookAt(LOOKAT_TARGET_FOCUS, focus_obj, (getPosAgentFromGlobal(focus) - focus_obj->getRenderPosition()) * ~focus_obj->getRenderRotation());
04334                                 }
04335                         }
04336                         else
04337                         {
04338                                 setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal));
04339                         }
04340                 }
04341         }
04342         else // focus == mFocusTargetGlobal
04343         {
04344                 if (focus.isExactlyZero())
04345                 {
04346                         if (!mAvatarObject.isNull())
04347                         {
04348                                 mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition());
04349                         }
04350                         else
04351                         {
04352                                 mFocusTargetGlobal = getPositionGlobal();
04353                         }
04354                 }
04355                 mCameraFocusOffsetTarget = (getCameraPositionGlobal() - mFocusTargetGlobal) / (1.f + mCameraFOVZoomFactor);;
04356                 mCameraFocusOffset = mCameraFocusOffsetTarget;
04357         }
04358 
04359         if (mFocusObject.notNull())
04360         {
04361                 // for attachments, make offset relative to avatar, not the attachment
04362                 if (mFocusObject->isAttachment())
04363                 {
04364                         while (!mFocusObject->isAvatar())
04365                         {
04366                                 mFocusObject = (LLViewerObject*) mFocusObject->getParent();
04367                         }
04368                         setFocusObject((LLViewerObject*)mFocusObject);
04369                 }
04370                 updateFocusOffset();
04371         }
04372 }
04373 
04374 // Used for avatar customization
04375 //-----------------------------------------------------------------------------
04376 // setCameraPosAndFocusGlobal()
04377 //-----------------------------------------------------------------------------
04378 void LLAgent::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLVector3d& focus, const LLUUID &object_id)
04379 {
04380         LLVector3d old_focus = mFocusTargetGlobal;
04381 
04382         F64 focus_delta_squared = (old_focus - focus).magVecSquared();
04383         const F64 ANIM_EPSILON_SQUARED = 0.0001;
04384         if( focus_delta_squared > ANIM_EPSILON_SQUARED )
04385         {
04386                 startCameraAnimation();
04387 
04388                 if( CAMERA_MODE_CUSTOMIZE_AVATAR == mCameraMode ) 
04389                 {
04390                         // Compensate for the fact that the camera has already been offset to make room for LLFloaterCustomize.
04391                         mAnimationCameraStartGlobal -= LLVector3d(LLViewerCamera::getInstance()->getLeftAxis() * calcCustomizeAvatarUIOffset( mAnimationCameraStartGlobal ));
04392                 }
04393         }
04394         
04395         //LLViewerCamera::getInstance()->setOrigin( gAgent.getPosAgentFromGlobal( camera_pos ) );
04396         setFocusObject(gObjectList.findObject(object_id));
04397         mFocusTargetGlobal = focus;
04398         mCameraFocusOffsetTarget = camera_pos - focus;
04399         mCameraFocusOffset = mCameraFocusOffsetTarget;
04400 
04401         if (mFocusObject)
04402         {
04403                 if (mFocusObject->isAvatar())
04404                 {
04405                         setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject);
04406                 }
04407                 else
04408                 {
04409                         setLookAt(LOOKAT_TARGET_FOCUS, mFocusObject, (getPosAgentFromGlobal(focus) - mFocusObject->getRenderPosition()) * ~mFocusObject->getRenderRotation());
04410                 }
04411         }
04412         else
04413         {
04414                 setLookAt(LOOKAT_TARGET_FOCUS, NULL, getPosAgentFromGlobal(mFocusTargetGlobal));
04415         }
04416 
04417         if( mCameraAnimating )
04418         {
04419                 const F64 ANIM_METERS_PER_SECOND = 10.0;
04420                 const F64 MIN_ANIM_SECONDS = 0.5;
04421                 F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND );
04422                 setAnimationDuration( (F32)anim_duration );
04423         }
04424 
04425         updateFocusOffset();
04426 }
04427 
04428 //-----------------------------------------------------------------------------
04429 // setSitCamera()
04430 //-----------------------------------------------------------------------------
04431 void LLAgent::setSitCamera(const LLUUID &object_id, const LLVector3 &camera_pos, const LLVector3 &camera_focus)
04432 {
04433         BOOL camera_enabled = !object_id.isNull();
04434 
04435         if (camera_enabled)
04436         {
04437                 LLViewerObject *reference_object = gObjectList.findObject(object_id);
04438                 if (reference_object)
04439                 {
04440                         //convert to root object relative?
04441                         mSitCameraPos = camera_pos;
04442                         mSitCameraFocus = camera_focus;
04443                         mSitCameraReferenceObject = reference_object;
04444                         mSitCameraEnabled = TRUE;
04445                 }
04446         }
04447         else
04448         {
04449                 mSitCameraPos.clearVec();
04450                 mSitCameraFocus.clearVec();
04451                 mSitCameraReferenceObject = NULL;
04452                 mSitCameraEnabled = FALSE;
04453         }
04454 }
04455 
04456 //-----------------------------------------------------------------------------
04457 // setFocusOnAvatar()
04458 //-----------------------------------------------------------------------------
04459 void LLAgent::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate)
04460 {
04461         if (focus_on_avatar != mFocusOnAvatar)
04462         {
04463                 if (animate)
04464                 {
04465                         startCameraAnimation();
04466                 }
04467                 else
04468                 {
04469                         stopCameraAnimation();
04470                 }
04471         }
04472         
04473         //RN: when focused on the avatar, we're not "looking" at it
04474         // looking implies intent while focusing on avatar means
04475         // you're just walking around with a camera on you...eesh.
04476         if (focus_on_avatar && !mFocusOnAvatar)
04477         {
04478                 setFocusGlobal(LLVector3d::zero);
04479                 mCameraFOVZoomFactor = 0.f;
04480                 if (mCameraMode == CAMERA_MODE_THIRD_PERSON)
04481                 {
04482                         LLVector3 at_axis;
04483                         if (!mAvatarObject.isNull() && mAvatarObject->getParent())
04484                         {
04485                                 LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
04486                                 at_axis = LLViewerCamera::getInstance()->getAtAxis();
04487                                 at_axis.mV[VZ] = 0.f;
04488                                 at_axis.normVec();
04489                                 resetAxes(at_axis * ~obj_rot);
04490                         }
04491                         else
04492                         {
04493                                 at_axis = LLViewerCamera::getInstance()->getAtAxis();
04494                                 at_axis.mV[VZ] = 0.f;
04495                                 at_axis.normVec();
04496                                 resetAxes(at_axis);
04497                         }
04498                 }
04499         }
04500         
04501         mFocusOnAvatar = focus_on_avatar;
04502 }
04503 
04504 //-----------------------------------------------------------------------------
04505 // heardChat()
04506 //-----------------------------------------------------------------------------
04507 void LLAgent::heardChat(const LLUUID& id)
04508 {
04509         // log text and voice chat to speaker mgr
04510         // for keeping track of active speakers, etc.
04511         LLLocalSpeakerMgr::getInstance()->speakerChatted(id);
04512 
04513         // don't respond to your own voice
04514         if (id == getID()) return;
04515         
04516         if (ll_rand(2) == 0) 
04517         {
04518                 LLViewerObject *chatter = gObjectList.findObject(mLastChatterID);
04519                 setLookAt(LOOKAT_TARGET_AUTO_LISTEN, chatter, LLVector3::zero);
04520         }                       
04521 
04522         mLastChatterID = id;
04523         mChatTimer.reset();
04524 }
04525 
04526 //-----------------------------------------------------------------------------
04527 // lookAtLastChat()
04528 //-----------------------------------------------------------------------------
04529 void LLAgent::lookAtLastChat()
04530 {
04531         // Block if camera is animating or not in normal third person camera mode
04532         if (mCameraAnimating || !cameraThirdPerson())
04533         {
04534                 return;
04535         }
04536 
04537         LLViewerObject *chatter = gObjectList.findObject(mLastChatterID);
04538         if (chatter)
04539         {
04540                 LLVector3 delta_pos;
04541                 if (chatter->isAvatar())
04542                 {
04543                         LLVOAvatar *chatter_av = (LLVOAvatar*)chatter;
04544                         if (!mAvatarObject.isNull() && chatter_av->mHeadp)
04545                         {
04546                                 delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition();
04547                         }
04548                         else
04549                         {
04550                                 delta_pos = chatter->getPositionAgent() - getPositionAgent();
04551                         }
04552                         delta_pos.normVec();
04553 
04554                         setControlFlags(AGENT_CONTROL_STOP);
04555 
04556                         changeCameraToThirdPerson();
04557 
04558                         LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition();
04559                         LLVector3 left = delta_pos % LLVector3::z_axis;
04560                         left.normVec();
04561                         LLVector3 up = left % delta_pos;
04562                         up.normVec();
04563                         new_camera_pos -= delta_pos * 0.4f;
04564                         new_camera_pos += left * 0.3f;
04565                         new_camera_pos += up * 0.2f;
04566                         if (chatter_av->mHeadp)
04567                         {
04568                                 setFocusGlobal(getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition()), mLastChatterID);
04569                                 mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - gAgent.getPosGlobalFromAgent(chatter_av->mHeadp->getWorldPosition());
04570                         }
04571                         else
04572                         {
04573                                 setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID);
04574                                 mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
04575                         }
04576                         setFocusOnAvatar(FALSE, TRUE);
04577                 }
04578                 else
04579                 {
04580                         delta_pos = chatter->getRenderPosition() - getPositionAgent();
04581                         delta_pos.normVec();
04582 
04583                         setControlFlags(AGENT_CONTROL_STOP);
04584 
04585                         changeCameraToThirdPerson();
04586 
04587                         LLVector3 new_camera_pos = mAvatarObject->mHeadp->getWorldPosition();
04588                         LLVector3 left = delta_pos % LLVector3::z_axis;
04589                         left.normVec();
04590                         LLVector3 up = left % delta_pos;
04591                         up.normVec();
04592                         new_camera_pos -= delta_pos * 0.4f;
04593                         new_camera_pos += left * 0.3f;
04594                         new_camera_pos += up * 0.2f;
04595 
04596                         setFocusGlobal(chatter->getPositionGlobal(), mLastChatterID);
04597                         mCameraFocusOffsetTarget = getPosGlobalFromAgent(new_camera_pos) - chatter->getPositionGlobal();
04598                         setFocusOnAvatar(FALSE, TRUE);
04599                 }
04600         }
04601 }
04602 
04603 const F32 SIT_POINT_EXTENTS = 0.2f;
04604 
04605 // Grabs current position
04606 void LLAgent::setStartPosition(U32 location_id)
04607 {
04608         LLViewerObject          *object;
04609 
04610         if ( !(gAgentID == LLUUID::null) )
04611         {
04612                 // we've got an ID for an agent viewerobject
04613                 object = gObjectList.findObject(gAgentID);
04614                 if (object)
04615                 {
04616                         // we've got the viewer object
04617                         // Sometimes the agent can be velocity interpolated off of
04618                         // this simulator.  Clamp it to the region the agent is
04619                         // in, a little bit in on each side.
04620                         const F32 INSET = 0.5f; //meters
04621                         const F32 REGION_WIDTH = LLWorld::getInstance()->getRegionWidthInMeters();
04622 
04623                         LLVector3 agent_pos = getPositionAgent();
04624 
04625                         if (mAvatarObject)
04626                         {
04627                                 // the z height is at the agent's feet
04628                                 agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ];
04629                         }
04630 
04631                         agent_pos.mV[VX] = llclamp( agent_pos.mV[VX], INSET, REGION_WIDTH - INSET );
04632                         agent_pos.mV[VY] = llclamp( agent_pos.mV[VY], INSET, REGION_WIDTH - INSET );
04633 
04634                         // Don't let them go below ground, or too high.
04635                         agent_pos.mV[VZ] = llclamp( agent_pos.mV[VZ], 
04636                                 mRegionp->getLandHeightRegion( agent_pos ), 
04637                                 LLWorld::getInstance()->getRegionMaxHeight() );
04638 
04639                         LLMessageSystem* msg = gMessageSystem;
04640                         msg->newMessageFast(_PREHASH_SetStartLocationRequest);
04641                         msg->nextBlockFast( _PREHASH_AgentData);
04642                         msg->addUUIDFast(_PREHASH_AgentID, getID());
04643                         msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
04644                         msg->nextBlockFast( _PREHASH_StartLocationData);
04645                         // corrected by sim
04646                         msg->addStringFast(_PREHASH_SimName, "");
04647                         msg->addU32Fast(_PREHASH_LocationID, location_id);
04648                         msg->addVector3Fast(_PREHASH_LocationPos, agent_pos);
04649                         msg->addVector3Fast(_PREHASH_LocationLookAt,mFrameAgent.getAtAxis());
04650 
04651                         // Reliable only helps when setting home location.  Last
04652                         // location is sent on quit, and we don't have time to ack
04653                         // the packets.
04654                         msg->sendReliable(mRegionp->getHost());
04655 
04656                         const U32 HOME_INDEX = 1;
04657                         if( HOME_INDEX == location_id )
04658                         {
04659                                 setHomePosRegion( mRegionp->getHandle(), getPositionAgent() );
04660                         }
04661                 }
04662                 else
04663                 {
04664                         llinfos << "setStartPosition - Can't find agent viewerobject id " << gAgentID << llendl;
04665                 }
04666         }
04667 }
04668 
04669 void LLAgent::requestStopMotion( LLMotion* motion )
04670 {
04671         // Notify all avatars that a motion has stopped.
04672         // This is needed to clear the animation state bits
04673         LLUUID anim_state = motion->getID();
04674         onAnimStop(motion->getID());
04675 
04676         // if motion is not looping, it could have stopped by running out of time
04677         // so we need to tell the server this
04678 //      llinfos << "Sending stop for motion " << motion->getName() << llendl;
04679         sendAnimationRequest( anim_state, ANIM_REQUEST_STOP );
04680 }
04681 
04682 void LLAgent::onAnimStop(const LLUUID& id)
04683 {
04684         // handle automatic state transitions (based on completion of animation playback)
04685         if (id == ANIM_AGENT_STAND)
04686         {
04687                 stopFidget();
04688         }
04689         else if (id == ANIM_AGENT_AWAY)
04690         {
04691                 clearAFK();
04692         }
04693         else if (id == ANIM_AGENT_STANDUP)
04694         {
04695                 // send stand up command
04696                 setControlFlags(AGENT_CONTROL_FINISH_ANIM);
04697 
04698                 // now trigger dusting self off animation
04699                 if (mAvatarObject.notNull() && !mAvatarObject->mBelowWater && rand() % 3 == 0)
04700                         sendAnimationRequest( ANIM_AGENT_BRUSH, ANIM_REQUEST_START );
04701         }
04702         else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND)
04703         {
04704                 setControlFlags(AGENT_CONTROL_FINISH_ANIM);
04705         }
04706 }
04707 
04708 BOOL LLAgent::isGodlike() const
04709 {
04710 #ifdef HACKED_GODLIKE_VIEWER
04711         return TRUE;
04712 #else
04713         if(mAdminOverride) return TRUE;
04714         return mGodLevel > GOD_NOT;
04715 #endif
04716 }
04717 
04718 U8 LLAgent::getGodLevel() const
04719 {
04720 #ifdef HACKED_GODLIKE_VIEWER
04721         return GOD_MAINTENANCE;
04722 #else
04723         if(mAdminOverride) return GOD_FULL;
04724         return mGodLevel;
04725 #endif
04726 }
04727 
04728 bool LLAgent::isTeen() const
04729 {
04730         return mAccess < SIM_ACCESS_MATURE;
04731 }
04732 
04733 void LLAgent::setTeen(bool teen)
04734 {
04735         if (teen)
04736         {
04737                 mAccess = SIM_ACCESS_PG;
04738         }
04739         else
04740         {
04741                 mAccess = SIM_ACCESS_MATURE;
04742         }
04743 }
04744 
04745 void LLAgent::buildFullname(std::string& name) const
04746 {
04747         if (mAvatarObject)
04748         {
04749                 name = mAvatarObject->getFullname();
04750         }
04751 }
04752 
04753 void LLAgent::buildFullnameAndTitle(std::string& name) const
04754 {
04755         if (isGroupMember())
04756         {
04757                 name = mGroupTitle;
04758                 name += ' ';
04759         }
04760         else
04761         {
04762                 name.erase(0, name.length());
04763         }
04764 
04765         if (mAvatarObject)
04766         {
04767                 name += mAvatarObject->getFullname();
04768         }
04769 }
04770 
04771 BOOL LLAgent::isInGroup(const LLUUID& group_id) const
04772 {
04773         S32 count = mGroups.count();
04774         for(S32 i = 0; i < count; ++i)
04775         {
04776                 if(mGroups.get(i).mID == group_id)
04777                 {
04778                         return TRUE;
04779                 }
04780         }
04781         return FALSE;
04782 }
04783 
04784 // This implementation should mirror LLAgentInfo::hasPowerInGroup
04785 BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const
04786 {
04787         // GP_NO_POWERS can also mean no power is enough to grant an ability.
04788         if (GP_NO_POWERS == power) return FALSE;
04789 
04790         S32 count = mGroups.count();
04791         for(S32 i = 0; i < count; ++i)
04792         {
04793                 if(mGroups.get(i).mID == group_id)
04794                 {
04795                         return (BOOL)((mGroups.get(i).mPowers & power) > 0);
04796                 }
04797         }
04798         return FALSE;
04799 }
04800 
04801 BOOL LLAgent::hasPowerInActiveGroup(U64 power) const
04802 {
04803         return (mGroupID.notNull() && (hasPowerInGroup(mGroupID, power)));
04804 }
04805 
04806 U64 LLAgent::getPowerInGroup(const LLUUID& group_id) const
04807 {
04808         S32 count = mGroups.count();
04809         for(S32 i = 0; i < count; ++i)
04810         {
04811                 if(mGroups.get(i).mID == group_id)
04812                 {
04813                         return (mGroups.get(i).mPowers);
04814                 }
04815         }
04816 
04817         return GP_NO_POWERS;
04818 }
04819 
04820 BOOL LLAgent::getGroupData(const LLUUID& group_id, LLGroupData& data) const
04821 {
04822         S32 count = mGroups.count();
04823         for(S32 i = 0; i < count; ++i)
04824         {
04825                 if(mGroups.get(i).mID == group_id)
04826                 {
04827                         data = mGroups.get(i);
04828                         return TRUE;
04829                 }
04830         }
04831         return FALSE;
04832 }
04833 
04834 S32 LLAgent::getGroupContribution(const LLUUID& group_id) const
04835 {
04836         S32 count = mGroups.count();
04837         for(S32 i = 0; i < count; ++i)
04838         {
04839                 if(mGroups.get(i).mID == group_id)
04840                 {
04841                         S32 contribution = mGroups.get(i).mContribution;
04842                         return contribution;
04843                 }
04844         }
04845         return 0;
04846 }
04847 
04848 BOOL LLAgent::setGroupContribution(const LLUUID& group_id, S32 contribution)
04849 {
04850         S32 count = mGroups.count();
04851         for(S32 i = 0; i < count; ++i)
04852         {
04853                 if(mGroups.get(i).mID == group_id)
04854                 {
04855                         mGroups.get(i).mContribution = contribution;
04856                         LLMessageSystem* msg = gMessageSystem;
04857                         msg->newMessage("SetGroupContribution");
04858                         msg->nextBlock("AgentData");
04859                         msg->addUUID("AgentID", gAgentID);
04860                         msg->addUUID("SessionID", gAgentSessionID);
04861                         msg->nextBlock("Data");
04862                         msg->addUUID("GroupID", group_id);
04863                         msg->addS32("Contribution", contribution);
04864                         sendReliableMessage();
04865                         return TRUE;
04866                 }
04867         }
04868         return FALSE;
04869 }
04870 
04871 BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile)
04872 {
04873         S32 count = mGroups.count();
04874         for(S32 i = 0; i < count; ++i)
04875         {
04876                 if(mGroups.get(i).mID == group_id)
04877                 {
04878                         mGroups.get(i).mAcceptNotices = accept_notices;
04879                         mGroups.get(i).mListInProfile = list_in_profile;
04880                         LLMessageSystem* msg = gMessageSystem;
04881                         msg->newMessage("SetGroupAcceptNotices");
04882                         msg->nextBlock("AgentData");
04883                         msg->addUUID("AgentID", gAgentID);
04884                         msg->addUUID("SessionID", gAgentSessionID);
04885                         msg->nextBlock("Data");
04886                         msg->addUUID("GroupID", group_id);
04887                         msg->addBOOL("AcceptNotices", accept_notices);
04888                         msg->nextBlock("NewData");
04889                         msg->addBOOL("ListInProfile", list_in_profile);
04890                         sendReliableMessage();
04891                         return TRUE;
04892                 }
04893         }
04894         return FALSE;
04895 }
04896 
04897 // utility to build a location string
04898 void LLAgent::buildLocationString(std::string& str)
04899 {
04900         const LLVector3& agent_pos_region = getPositionAgent();
04901         S32 pos_x = S32(agent_pos_region.mV[VX]);
04902         S32 pos_y = S32(agent_pos_region.mV[VY]);
04903         S32 pos_z = S32(agent_pos_region.mV[VZ]);
04904 
04905         // Round the numbers based on the velocity
04906         LLVector3 agent_velocity = getVelocity();
04907         F32 velocity_mag_sq = agent_velocity.magVecSquared();
04908 
04909         const F32 FLY_CUTOFF = 6.f;             // meters/sec
04910         const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
04911         const F32 WALK_CUTOFF = 1.5f;   // meters/sec
04912         const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
04913 
04914         if (velocity_mag_sq > FLY_CUTOFF_SQ)
04915         {
04916                 pos_x -= pos_x % 4;
04917                 pos_y -= pos_y % 4;
04918         }
04919         else if (velocity_mag_sq > WALK_CUTOFF_SQ)
04920         {
04921                 pos_x -= pos_x % 2;
04922                 pos_y -= pos_y % 2;
04923         }
04924 
04925         // create a defult name and description for the landmark
04926         std::string buffer;
04927         if( LLViewerParcelMgr::getInstance()->getAgentParcelName().empty() )
04928         {
04929                 // the parcel doesn't have a name
04930                 buffer = llformat("%.32s (%d, %d, %d)",
04931                                                   getRegion()->getName().c_str(),
04932                                                   pos_x, pos_y, pos_z);
04933         }
04934         else
04935         {
04936                 // the parcel has a name, so include it in the landmark name
04937                 buffer = llformat("%.32s, %.32s (%d, %d, %d)",
04938                                                   LLViewerParcelMgr::getInstance()->getAgentParcelName().c_str(),
04939                                                   getRegion()->getName().c_str(),
04940                                                   pos_x, pos_y, pos_z);
04941         }
04942         str = buffer;
04943 }
04944 
04945 LLQuaternion LLAgent::getHeadRotation()
04946 {
04947         if (mAvatarObject.isNull() || !mAvatarObject->mPelvisp || !mAvatarObject->mHeadp)
04948         {
04949                 return LLQuaternion::DEFAULT;
04950         }
04951 
04952         if (!gAgent.cameraMouselook())
04953         {
04954                 return mAvatarObject->getRotation();
04955         }
04956 
04957         // We must be in mouselook
04958         LLVector3 look_dir( LLViewerCamera::getInstance()->getAtAxis() );
04959         LLVector3 up = look_dir % mFrameAgent.getLeftAxis();
04960         LLVector3 left = up % look_dir;
04961 
04962         LLQuaternion rot(look_dir, left, up);
04963         if (mAvatarObject->getParent())
04964         {
04965                 rot = rot * ~mAvatarObject->getParent()->getRotation();
04966         }
04967 
04968         return rot;
04969 }
04970 
04971 void LLAgent::sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request)
04972 {
04973         if (gAgentID.isNull())
04974         {
04975                 return;
04976         }
04977 
04978         S32 num_valid_anims = 0;
04979 
04980         LLMessageSystem* msg = gMessageSystem;
04981         msg->newMessageFast(_PREHASH_AgentAnimation);
04982         msg->nextBlockFast(_PREHASH_AgentData);
04983         msg->addUUIDFast(_PREHASH_AgentID, getID());
04984         msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
04985 
04986         for (S32 i = 0; i < anim_ids.count(); i++)
04987         {
04988                 if (anim_ids[i].isNull())
04989                 {
04990                         continue;
04991                 }
04992                 msg->nextBlockFast(_PREHASH_AnimationList);
04993                 msg->addUUIDFast(_PREHASH_AnimID, (anim_ids[i]) );
04994                 msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE);
04995                 num_valid_anims++;
04996         }
04997 
04998         msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList);
04999         msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0);
05000         if (num_valid_anims)
05001         {
05002                 sendReliableMessage();
05003         }
05004 }
05005 
05006 void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request)
05007 {
05008         if (gAgentID.isNull() || anim_id.isNull() || !mRegionp)
05009         {
05010                 return;
05011         }
05012 
05013         LLMessageSystem* msg = gMessageSystem;
05014         msg->newMessageFast(_PREHASH_AgentAnimation);
05015         msg->nextBlockFast(_PREHASH_AgentData);
05016         msg->addUUIDFast(_PREHASH_AgentID, getID());
05017         msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
05018 
05019         msg->nextBlockFast(_PREHASH_AnimationList);
05020         msg->addUUIDFast(_PREHASH_AnimID, (anim_id) );
05021         msg->addBOOLFast(_PREHASH_StartAnim, (request == ANIM_REQUEST_START) ? TRUE : FALSE);
05022 
05023         msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList);
05024         msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0);
05025         sendReliableMessage();
05026 }
05027 
05028 void LLAgent::sendWalkRun(bool running)
05029 {
05030         LLMessageSystem* msgsys = gMessageSystem;
05031         if (msgsys)
05032         {
05033                 msgsys->newMessageFast(_PREHASH_SetAlwaysRun);
05034                 msgsys->nextBlockFast(_PREHASH_AgentData);
05035                 msgsys->addUUIDFast(_PREHASH_AgentID, getID());
05036                 msgsys->addUUIDFast(_PREHASH_SessionID, getSessionID());
05037                 msgsys->addBOOLFast(_PREHASH_AlwaysRun, BOOL(running) );
05038                 sendReliableMessage();
05039         }
05040 }
05041 
05042 void LLAgent::friendsChanged()
05043 {
05044         LLCollectProxyBuddies collector;
05045         LLAvatarTracker::instance().applyFunctor(collector);
05046         mProxyForAgents = collector.mProxy;
05047 }
05048 
05049 BOOL LLAgent::isGrantedProxy(const LLPermissions& perm)
05050 {
05051         return (mProxyForAgents.count(perm.getOwner()) > 0);
05052 }
05053 
05054 BOOL LLAgent::allowOperation(PermissionBit op,
05055                                                          const LLPermissions& perm,
05056                                                          U64 group_proxy_power,
05057                                                          U8 god_minimum)
05058 {
05059         // Check god level.
05060         if (getGodLevel() >= god_minimum) return TRUE;
05061 
05062         if (!perm.isOwned()) return FALSE;
05063 
05064         // A group member with group_proxy_power can act as owner.
05065         BOOL is_group_owned;
05066         LLUUID owner_id;
05067         perm.getOwnership(owner_id, is_group_owned);
05068         LLUUID group_id(perm.getGroup());
05069         LLUUID agent_proxy(getID());
05070 
05071         if (is_group_owned)
05072         {
05073                 if (hasPowerInGroup(group_id, group_proxy_power))
05074                 {
05075                         // Let the member assume the group's id for permission requests.
05076                         agent_proxy = owner_id;
05077                 }
05078         }
05079         else
05080         {
05081                 // Check for granted mod permissions.
05082                 if ((PERM_OWNER != op) && isGrantedProxy(perm))
05083                 {
05084                         agent_proxy = owner_id;
05085                 }
05086         }
05087 
05088         // This is the group id to use for permission requests.
05089         // Only group members may use this field.
05090         LLUUID group_proxy = LLUUID::null;
05091         if (group_id.notNull() && isInGroup(group_id))
05092         {
05093                 group_proxy = group_id;
05094         }
05095 
05096         // We now have max ownership information.
05097         if (PERM_OWNER == op)
05098         {
05099                 // This this was just a check for ownership, we can now return the answer.
05100                 return (agent_proxy == owner_id);
05101         }
05102 
05103         return perm.allowOperationBy(op, agent_proxy, group_proxy);
05104 }
05105 
05106 
05107 void LLAgent::getName(LLString& name)
05108 {
05109         // Note: assumes that name points to a buffer of at least DB_FULL_NAME_BUF_SIZE bytes.
05110         name.clear();
05111 
05112         if (mAvatarObject)
05113         {
05114                 LLNameValue *first_nv = mAvatarObject->getNVPair("FirstName");
05115                 LLNameValue *last_nv = mAvatarObject->getNVPair("LastName");
05116                 if (first_nv && last_nv)
05117                 {
05118                         name = first_nv->printData() + " " + last_nv->printData();
05119                 }
05120                 else
05121                 {
05122                         llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
05123                 }
05124         }
05125         else
05126         {
05127                 name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
05128         }
05129 }
05130 
05131 const LLColor4 &LLAgent::getEffectColor()
05132 {
05133         return mEffectColor;
05134 }
05135 
05136 void LLAgent::setEffectColor(const LLColor4 &color)
05137 {
05138         mEffectColor = color;
05139 }
05140 
05141 void LLAgent::initOriginGlobal(const LLVector3d &origin_global)
05142 {
05143         mAgentOriginGlobal = origin_global;
05144 }
05145 
05146 void update_group_floaters(const LLUUID& group_id)
05147 {
05148         LLFloaterGroupInfo::refreshGroup(group_id);
05149 
05150         // update avatar info
05151         LLFloaterAvatarInfo* fa = LLFloaterAvatarInfo::getInstance(gAgent.getID());
05152         if(fa)
05153         {
05154                 fa->resetGroupList();
05155         }
05156 
05157         if (gIMMgr)
05158         {
05159                 // update the talk view
05160                 gIMMgr->refresh();
05161         }
05162 
05163         gAgent.fireEvent(new LLEvent(&gAgent, "new group"), "");
05164 }
05165 
05166 // static
05167 void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **)
05168 {
05169         LLUUID  agent_id;
05170         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
05171 
05172         if (agent_id != gAgentID)
05173         {
05174                 llwarns << "processAgentDropGroup for agent other than me" << llendl;
05175                 return;
05176         }
05177 
05178         LLUUID  group_id;
05179         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
05180 
05181         // Remove the group if it already exists remove it and add the new data to pick up changes.
05182         LLGroupData gd;
05183         gd.mID = group_id;
05184         S32 index = gAgent.mGroups.find(gd);
05185         if (index != -1)
05186         {
05187                 gAgent.mGroups.remove(index);
05188                 if (gAgent.getGroupID() == group_id)
05189                 {
05190                         gAgent.mGroupID.setNull();
05191                         gAgent.mGroupPowers = 0;
05192                         gAgent.mGroupName[0] = '\0';
05193                         gAgent.mGroupTitle[0] = '\0';
05194                 }
05195                 
05196                 // refresh all group information
05197                 gAgent.sendAgentDataUpdateRequest();
05198 
05199                 LLGroupMgr::getInstance()->clearGroupData(group_id);
05200                 // close the floater for this group, if any.
05201                 LLFloaterGroupInfo::closeGroup(group_id);
05202                 // refresh the group panel of the search window, if necessary.
05203                 LLFloaterDirectory::refreshGroup(group_id);
05204         }
05205         else
05206         {
05207                 llwarns << "processAgentDropGroup, agent is not part of group " << group_id << llendl;
05208         }
05209 }
05210 
05211 class LLAgentDropGroupViewerNode : public LLHTTPNode
05212 {
05213         virtual void post(
05214                 LLHTTPNode::ResponsePtr response,
05215                 const LLSD& context,
05216                 const LLSD& input) const
05217         {
05218 
05219                 if (
05220                         !input.isMap() ||
05221                         !input.has("body") )
05222                 {
05223                         //what to do with badly formed message?
05224                         response->status(400);
05225                         response->result(LLSD("Invalid message parameters"));
05226                 }
05227 
05228                 LLSD body = input["body"];
05229                 if ( body.has("body") ) 
05230                 {
05231                         //stupid message system doubles up the "body"s
05232                         body = body["body"];
05233                 }
05234 
05235                 if (
05236                         body.has("AgentData") &&
05237                         body["AgentData"].isArray() &&
05238                         body["AgentData"][0].isMap() )
05239                 {
05240                         llinfos << "VALID DROP GROUP" << llendl;
05241 
05242                         //there is only one set of data in the AgentData block
05243                         LLSD agent_data = body["AgentData"][0];
05244                         LLUUID agent_id;
05245                         LLUUID group_id;
05246 
05247                         agent_id = agent_data["AgentID"].asUUID();
05248                         group_id = agent_data["GroupID"].asUUID();
05249 
05250                         if (agent_id != gAgentID)
05251                         {
05252                                 llwarns
05253                                         << "AgentDropGroup for agent other than me" << llendl;
05254 
05255                                 response->notFound();
05256                                 return;
05257                         }
05258 
05259                         // Remove the group if it already exists remove it
05260                         // and add the new data to pick up changes.
05261                         LLGroupData gd;
05262                         gd.mID = group_id;
05263                         S32 index = gAgent.mGroups.find(gd);
05264                         if (index != -1)
05265                         {
05266                                 gAgent.mGroups.remove(index);
05267                                 if (gAgent.getGroupID() == group_id)
05268                                 {
05269                                         gAgent.mGroupID.setNull();
05270                                         gAgent.mGroupPowers = 0;
05271                                         gAgent.mGroupName[0] = '\0';
05272                                         gAgent.mGroupTitle[0] = '\0';
05273                                 }
05274                 
05275                                 // refresh all group information
05276                                 gAgent.sendAgentDataUpdateRequest();
05277 
05278                                 LLGroupMgr::getInstance()->clearGroupData(group_id);
05279                                 // close the floater for this group, if any.
05280                                 LLFloaterGroupInfo::closeGroup(group_id);
05281                                 // refresh the group panel of the search window,
05282                                 //if necessary.
05283                                 LLFloaterDirectory::refreshGroup(group_id);
05284                         }
05285                         else
05286                         {
05287                                 llwarns
05288                                         << "AgentDropGroup, agent is not part of group "
05289                                         << group_id << llendl;
05290                         }
05291 
05292                         response->result(LLSD());
05293                 }
05294                 else
05295                 {
05296                         //what to do with badly formed message?
05297                         response->status(400);
05298                         response->result(LLSD("Invalid message parameters"));
05299                 }
05300         }
05301 };
05302 
05303 LLHTTPRegistration<LLAgentDropGroupViewerNode>
05304         gHTTPRegistrationAgentDropGroupViewerNode(
05305                 "/message/AgentDropGroup");
05306 
05307 // static
05308 void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **)
05309 {
05310         LLUUID  agent_id;
05311 
05312         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
05313 
05314         if (agent_id != gAgentID)
05315         {
05316                 llwarns << "processAgentGroupDataUpdate for agent other than me" << llendl;
05317                 return;
05318         }       
05319         
05320         S32 count = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
05321         LLGroupData group;
05322         S32 index = -1;
05323         bool need_floater_update = false;
05324         char group_name[DB_GROUP_NAME_BUF_SIZE];                /*Flawfinder: ignore*/
05325         for(S32 i = 0; i < count; ++i)
05326         {
05327                 msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group.mID, i);
05328                 msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupInsigniaID, group.mInsigniaID, i);
05329                 msg->getU64(_PREHASH_GroupData, "GroupPowers", group.mPowers, i);
05330                 msg->getBOOL(_PREHASH_GroupData, "AcceptNotices", group.mAcceptNotices, i);
05331                 msg->getS32(_PREHASH_GroupData, "Contribution", group.mContribution, i);
05332                 msg->getStringFast(_PREHASH_GroupData, _PREHASH_GroupName, DB_GROUP_NAME_BUF_SIZE, group_name, i);
05333                 group.mName.assign(group_name);
05334                 
05335                 if(group.mID.notNull())
05336                 {
05337                         need_floater_update = true;
05338                         // Remove the group if it already exists remove it and add the new data to pick up changes.
05339                         index = gAgent.mGroups.find(group);
05340                         if (index != -1)
05341                         {
05342                                 gAgent.mGroups.remove(index);
05343                         }
05344                         gAgent.mGroups.put(group);
05345                 }
05346                 if (need_floater_update)
05347                 {
05348                         update_group_floaters(group.mID);
05349                 }
05350         }
05351 
05352 }
05353 
05354 class LLAgentGroupDataUpdateViewerNode : public LLHTTPNode
05355 {
05356         virtual void post(
05357                 LLHTTPNode::ResponsePtr response,
05358                 const LLSD& context,
05359                 const LLSD& input) const
05360         {
05361                 LLSD body = input["body"];
05362                 if(body.has("body"))
05363                         body = body["body"];
05364                 LLUUID agent_id = body["AgentData"][0]["AgentID"].asUUID();
05365 
05366                 if (agent_id != gAgentID)
05367                 {
05368                         llwarns << "processAgentGroupDataUpdate for agent other than me" << llendl;
05369                         return;
05370                 }       
05371 
05372                 LLSD group_data = body["GroupData"];
05373 
05374                 LLSD::array_iterator iter_group =
05375                         group_data.beginArray();
05376                 LLSD::array_iterator end_group =
05377                         group_data.endArray();
05378                 int group_index = 0;
05379                 for(; iter_group != end_group; ++iter_group)
05380                 {
05381 
05382                         LLGroupData group;
05383                         S32 index = -1;
05384                         bool need_floater_update = false;
05385 
05386                         group.mID = (*iter_group)["GroupID"].asUUID();
05387                         group.mPowers = ll_U64_from_sd((*iter_group)["GroupPowers"]);
05388                         group.mAcceptNotices = (*iter_group)["AcceptNotices"].asBoolean();
05389                         group.mListInProfile = body["NewGroupData"][group_index]["ListInProfile"].asBoolean();
05390                         group.mInsigniaID = (*iter_group)["GroupInsigniaID"].asUUID();
05391                         group.mName = (*iter_group)["GroupName"].asString();
05392                         group.mContribution = (*iter_group)["Contribution"].asInteger();
05393 
05394                         group_index++;
05395 
05396                         if(group.mID.notNull())
05397                         {
05398                                 need_floater_update = true;
05399                                 // Remove the group if it already exists remove it and add the new data to pick up changes.
05400                                 index = gAgent.mGroups.find(group);
05401                                 if (index != -1)
05402                                 {
05403                                         gAgent.mGroups.remove(index);
05404                                 }
05405                                 gAgent.mGroups.put(group);
05406                         }
05407                         if (need_floater_update)
05408                         {
05409                                 update_group_floaters(group.mID);
05410                         }
05411                 }
05412         }
05413 };
05414 
05415 LLHTTPRegistration<LLAgentGroupDataUpdateViewerNode >
05416         gHTTPRegistrationAgentGroupDataUpdateViewerNode ("/message/AgentGroupDataUpdate"); 
05417 
05418 // static
05419 void LLAgent::processAgentDataUpdate(LLMessageSystem *msg, void **)
05420 {
05421         LLUUID  agent_id;
05422 
05423         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
05424 
05425         if (agent_id != gAgentID)
05426         {
05427                 llwarns << "processAgentDataUpdate for agent other than me" << llendl;
05428                 return;
05429         }
05430 
05431         msg->getStringFast(_PREHASH_AgentData, _PREHASH_GroupTitle, DB_GROUP_TITLE_BUF_SIZE, gAgent.mGroupTitle);
05432         LLUUID active_id;
05433         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_ActiveGroupID, active_id);
05434 
05435 
05436         if(active_id.notNull())
05437         {
05438                 gAgent.mGroupID = active_id;
05439                 msg->getU64(_PREHASH_AgentData, "GroupPowers", gAgent.mGroupPowers);
05440                 msg->getString(_PREHASH_AgentData, _PREHASH_GroupName, DB_GROUP_NAME_BUF_SIZE, gAgent.mGroupName);
05441         }
05442         else
05443         {
05444                 gAgent.mGroupID.setNull();
05445                 gAgent.mGroupPowers = 0;
05446                 gAgent.mGroupName[0] = '\0';
05447         }               
05448 
05449         update_group_floaters(active_id);
05450 }
05451 
05452 // static
05453 void LLAgent::processScriptControlChange(LLMessageSystem *msg, void **)
05454 {
05455         S32 block_count = msg->getNumberOfBlocks("Data");
05456         for (S32 block_index = 0; block_index < block_count; block_index++)
05457         {
05458                 BOOL take_controls;
05459                 U32     controls;
05460                 BOOL passon;
05461                 U32 i;
05462                 msg->getBOOL("Data", "TakeControls", take_controls, block_index);
05463                 if (take_controls)
05464                 {
05465                         // take controls
05466                         msg->getU32("Data", "Controls", controls, block_index );
05467                         msg->getBOOL("Data", "PassToAgent", passon, block_index );
05468                         U32 total_count = 0;
05469                         for (i = 0; i < TOTAL_CONTROLS; i++)
05470                         {
05471                                 if (controls & ( 1 << i))
05472                                 {
05473                                         if (passon)
05474                                         {
05475                                                 gAgent.mControlsTakenPassedOnCount[i]++;
05476                                         }
05477                                         else
05478                                         {
05479                                                 gAgent.mControlsTakenCount[i]++;
05480                                         }
05481                                         total_count++;
05482                                 }
05483                         }
05484                 
05485                         // Any control taken?  If so, might be first time.
05486                         if (total_count > 0)
05487                         {
05488                                 LLFirstUse::useOverrideKeys();
05489                         }
05490                 }
05491                 else
05492                 {
05493                         // release controls
05494                         msg->getU32("Data", "Controls", controls, block_index );
05495                         msg->getBOOL("Data", "PassToAgent", passon, block_index );
05496                         for (i = 0; i < TOTAL_CONTROLS; i++)
05497                         {
05498                                 if (controls & ( 1 << i))
05499                                 {
05500                                         if (passon)
05501                                         {
05502                                                 gAgent.mControlsTakenPassedOnCount[i]--;
05503                                                 if (gAgent.mControlsTakenPassedOnCount[i] < 0)
05504                                                 {
05505                                                         gAgent.mControlsTakenPassedOnCount[i] = 0;
05506                                                 }
05507                                         }
05508                                         else
05509                                         {
05510                                                 gAgent.mControlsTakenCount[i]--;
05511                                                 if (gAgent.mControlsTakenCount[i] < 0)
05512                                                 {
05513                                                         gAgent.mControlsTakenCount[i] = 0;
05514                                                 }
05515                                         }
05516                                 }
05517                         }
05518                 }
05519         }
05520 }
05521 
05522 /*
05523 // static
05524 void LLAgent::processControlTake(LLMessageSystem *msg, void **)
05525 {
05526         U32     controls;
05527         msg->getU32("Data", "Controls", controls );
05528         U32 passon;
05529         msg->getBOOL("Data", "PassToAgent", passon );
05530 
05531         S32 i;
05532         S32 total_count = 0;
05533         for (i = 0; i < TOTAL_CONTROLS; i++)
05534         {
05535                 if (controls & ( 1 << i))
05536                 {
05537                         if (passon)
05538                         {
05539                                 gAgent.mControlsTakenPassedOnCount[i]++;
05540                         }
05541                         else
05542                         {
05543                                 gAgent.mControlsTakenCount[i]++;
05544                         }
05545                         total_count++;
05546                 }
05547         }
05548 
05549         // Any control taken?  If so, might be first time.
05550         if (total_count > 0)
05551         {
05552                 LLFirstUse::useOverrideKeys();
05553         }
05554 }
05555 
05556 // static
05557 void LLAgent::processControlRelease(LLMessageSystem *msg, void **)
05558 {
05559         U32     controls;
05560         msg->getU32("Data", "Controls", controls );
05561         U32 passon;
05562         msg->getBOOL("Data", "PassToAgent", passon );
05563 
05564         S32 i;
05565         for (i = 0; i < TOTAL_CONTROLS; i++)
05566         {
05567                 if (controls & ( 1 << i))
05568                 {
05569                         if (passon)
05570                         {
05571                                 gAgent.mControlsTakenPassedOnCount[i]--;
05572                                 if (gAgent.mControlsTakenPassedOnCount[i] < 0)
05573                                 {
05574                                         gAgent.mControlsTakenPassedOnCount[i] = 0;
05575                                 }
05576                         }
05577                         else
05578                         {
05579                                 gAgent.mControlsTakenCount[i]--;
05580                                 if (gAgent.mControlsTakenCount[i] < 0)
05581                                 {
05582                                         gAgent.mControlsTakenCount[i] = 0;
05583                                 }
05584                         }
05585                 }
05586         }
05587 }
05588 */
05589 
05590 //static
05591 void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void **user_data)
05592 {
05593         gAgent.mNumPendingQueries--;
05594 
05595         LLVOAvatar* avatarp = gAgent.getAvatarObject();
05596         if (!avatarp || avatarp->isDead())
05597         {
05598                 llwarns << "No avatar for user in cached texture update!" << llendl;
05599                 return;
05600         }
05601 
05602         if (gAgent.cameraCustomizeAvatar())
05603         {
05604                 // ignore baked textures when in customize mode
05605                 return;
05606         }
05607 
05608         S32 query_id;
05609         mesgsys->getS32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, query_id);
05610 
05611         S32 num_texture_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_WearableData);
05612 
05613 
05614         S32 num_results = 0;
05615         for (S32 texture_block = 0; texture_block < num_texture_blocks; texture_block++)
05616         {
05617                 LLUUID texture_id;
05618                 U8 texture_index;
05619 
05620                 mesgsys->getUUIDFast(_PREHASH_WearableData, _PREHASH_TextureID, texture_id, texture_block);
05621                 mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block);
05622 
05623                 if (texture_id.notNull() 
05624                         && (S32)texture_index < BAKED_TEXTURE_COUNT 
05625                         && gAgent.mActiveCacheQueries[ texture_index ] == query_id)
05626                 {
05627                         //llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl;
05628                         avatarp->setCachedBakedTexture((LLVOAvatar::ETextureIndex)LLVOAvatar::sBakedTextureIndices[texture_index], texture_id);
05629                         //avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id );
05630                         gAgent.mActiveCacheQueries[ texture_index ] = 0;
05631                         num_results++;
05632                 }
05633         }
05634 
05635         llinfos << "Received cached texture response for " << num_results << " textures." << llendl;
05636 
05637         avatarp->updateMeshTextures();
05638 
05639         if (gAgent.mNumPendingQueries == 0)
05640         {
05641                 // RN: not sure why composites are disabled at this point
05642                 avatarp->setCompositeUpdatesEnabled(TRUE);
05643                 gAgent.sendAgentSetAppearance();
05644         }
05645 }
05646 
05647 BOOL LLAgent::anyControlGrabbed() const
05648 {
05649         U32 i;
05650         for (i = 0; i < TOTAL_CONTROLS; i++)
05651         {
05652                 if (gAgent.mControlsTakenCount[i] > 0)
05653                         return TRUE;
05654                 if (gAgent.mControlsTakenPassedOnCount[i] > 0)
05655                         return TRUE;
05656         }
05657         return FALSE;
05658 }
05659 
05660 BOOL LLAgent::isControlGrabbed(S32 control_index) const
05661 {
05662         return mControlsTakenCount[control_index] > 0;
05663 }
05664 
05665 void LLAgent::forceReleaseControls()
05666 {
05667         gMessageSystem->newMessage("ForceScriptControlRelease");
05668         gMessageSystem->nextBlock("AgentData");
05669         gMessageSystem->addUUID("AgentID", getID());
05670         gMessageSystem->addUUID("SessionID", getSessionID());
05671         sendReliableMessage();
05672 }
05673 
05674 void LLAgent::setHomePosRegion( const U64& region_handle, const LLVector3& pos_region)
05675 {
05676         mHaveHomePosition = TRUE;
05677         mHomeRegionHandle = region_handle;
05678         mHomePosRegion = pos_region;
05679 }
05680 
05681 BOOL LLAgent::getHomePosGlobal( LLVector3d* pos_global )
05682 {
05683         if(!mHaveHomePosition)
05684         {
05685                 return FALSE;
05686         }
05687         F32 x = 0;
05688         F32 y = 0;
05689         from_region_handle( mHomeRegionHandle, &x, &y);
05690         pos_global->setVec( x + mHomePosRegion.mV[VX], y + mHomePosRegion.mV[VY], mHomePosRegion.mV[VZ] );
05691         return TRUE;
05692 }
05693 
05694 void LLAgent::clearVisualParams(void *data)
05695 {
05696         LLVOAvatar* avatarp = gAgent.getAvatarObject();
05697         if (avatarp)
05698         {
05699                 avatarp->clearVisualParamWeights();
05700                 avatarp->updateVisualParams();
05701         }
05702 }
05703 
05704 //---------------------------------------------------------------------------
05705 // Teleport
05706 //---------------------------------------------------------------------------
05707 
05708 // teleportCore() - stuff to do on any teleport
05709 // protected
05710 bool LLAgent::teleportCore(bool is_local)
05711 {
05712         if(TELEPORT_NONE != mTeleportState)
05713         {
05714                 llwarns << "Attempt to teleport when already teleporting." << llendl;
05715                 return false;
05716         }
05717 
05718         // Stop all animation before actual teleporting 
05719         LLVOAvatar* avatarp = gAgent.getAvatarObject();
05720         if (avatarp)
05721         {
05722                 for ( LLVOAvatar::AnimIterator anim_it= avatarp->mPlayingAnimations.begin()
05723                         ; anim_it != avatarp->mPlayingAnimations.end()
05724                         ; anim_it++)
05725                 {
05726                         avatarp->stopMotion(anim_it->first);
05727                 }
05728                 avatarp->processAnimationStateChanges();
05729         }
05730 
05731         // Don't call LLFirstUse::useTeleport because we don't know
05732         // yet if the teleport will succeed.  Look in 
05733         // process_teleport_location_reply
05734 
05735         // close the map and find panels so we can see our destination
05736         LLFloaterWorldMap::hide(NULL);
05737         LLFloaterDirectory::hide(NULL);
05738 
05739         LLViewerParcelMgr::getInstance()->deselectLand();
05740 
05741         // Close all pie menus, deselect land, etc.
05742         // Don't change the camera until we know teleport succeeded. JC
05743         resetView(FALSE);
05744 
05745         // local logic
05746         LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TELEPORT_COUNT);
05747         if (!is_local)
05748         {
05749                 gTeleportDisplay = TRUE;
05750                 gAgent.setTeleportState( LLAgent::TELEPORT_START );
05751 
05752                 //release geometry from old location
05753                 gPipeline.resetVertexBuffers();
05754         }
05755         make_ui_sound("UISndTeleportOut");
05756         
05757         // MBW -- Let the voice client know a teleport has begun so it can leave the existing channel.
05758         // This was breaking the case of teleporting within a single sim.  Backing it out for now.
05759 //      gVoiceClient->leaveChannel();
05760         
05761         return true;
05762 }
05763 
05764 void LLAgent::teleportRequest(
05765         const U64& region_handle,
05766         const LLVector3& pos_local)
05767 {
05768         LLViewerRegion* regionp = getRegion();
05769         if(regionp && teleportCore())
05770         {
05771                 llinfos << "TeleportRequest: '" << region_handle << "':" << pos_local
05772                                 << llendl;
05773                 LLMessageSystem* msg = gMessageSystem;
05774                 msg->newMessage("TeleportLocationRequest");
05775                 msg->nextBlockFast(_PREHASH_AgentData);
05776                 msg->addUUIDFast(_PREHASH_AgentID, getID());
05777                 msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
05778                 msg->nextBlockFast(_PREHASH_Info);
05779                 msg->addU64("RegionHandle", region_handle);
05780                 msg->addVector3("Position", pos_local);
05781                 LLVector3 look_at(0,1,0);
05782                 msg->addVector3("LookAt", look_at);
05783                 sendReliableMessage();
05784         }
05785 }
05786 
05787 // Landmark ID = LLUUID::null means teleport home
05788 void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id)
05789 {
05790         LLViewerRegion *regionp = getRegion();
05791         if(regionp && teleportCore())
05792         {
05793                 LLMessageSystem* msg = gMessageSystem;
05794                 msg->newMessageFast(_PREHASH_TeleportLandmarkRequest);
05795                 msg->nextBlockFast(_PREHASH_Info);
05796                 msg->addUUIDFast(_PREHASH_AgentID, getID());
05797                 msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
05798                 msg->addUUIDFast(_PREHASH_LandmarkID, landmark_asset_id);
05799                 sendReliableMessage();
05800         }
05801 }
05802 
05803 void LLAgent::teleportViaLure(const LLUUID& lure_id, BOOL godlike)
05804 {
05805         LLViewerRegion* regionp = getRegion();
05806         if(regionp && teleportCore())
05807         {
05808                 U32 teleport_flags = 0x0;
05809                 if (godlike)
05810                 {
05811                         teleport_flags |= TELEPORT_FLAGS_VIA_GODLIKE_LURE;
05812                         teleport_flags |= TELEPORT_FLAGS_DISABLE_CANCEL;
05813                 }
05814                 else
05815                 {
05816                         teleport_flags |= TELEPORT_FLAGS_VIA_LURE;
05817                 }
05818 
05819                 // send the message
05820                 LLMessageSystem* msg = gMessageSystem;
05821                 msg->newMessageFast(_PREHASH_TeleportLureRequest);
05822                 msg->nextBlockFast(_PREHASH_Info);
05823                 msg->addUUIDFast(_PREHASH_AgentID, getID());
05824                 msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
05825                 msg->addUUIDFast(_PREHASH_LureID, lure_id);
05826                 // teleport_flags is a legacy field, now derived sim-side:
05827                 msg->addU32("TeleportFlags", teleport_flags);
05828                 sendReliableMessage();
05829         }       
05830 }
05831 
05832 
05833 // James Cook, July 28, 2005
05834 void LLAgent::teleportCancel()
05835 {
05836         LLViewerRegion* regionp = getRegion();
05837         if(regionp)
05838         {
05839                 // send the message
05840                 LLMessageSystem* msg = gMessageSystem;
05841                 msg->newMessage("TeleportCancel");
05842                 msg->nextBlockFast(_PREHASH_Info);
05843                 msg->addUUIDFast(_PREHASH_AgentID, getID());
05844                 msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
05845                 sendReliableMessage();
05846         }       
05847         gTeleportDisplay = FALSE;
05848         gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
05849 }
05850 
05851 
05852 void LLAgent::teleportViaLocation(const LLVector3d& pos_global)
05853 {
05854         LLViewerRegion* regionp = getRegion();
05855         LLSimInfo* info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
05856         if(regionp && info)
05857         {
05858                 U32 x_pos;
05859                 U32 y_pos;
05860                 from_region_handle(info->mHandle, &x_pos, &y_pos);
05861                 LLVector3 pos_local(
05862                         (F32)(pos_global.mdV[VX] - x_pos),
05863                         (F32)(pos_global.mdV[VY] - y_pos),
05864                         (F32)(pos_global.mdV[VZ]));
05865                 teleportRequest(info->mHandle, pos_local);
05866         }
05867         else if(regionp && 
05868                 teleportCore(regionp->getHandle() == to_region_handle_global((F32)pos_global.mdV[VX], (F32)pos_global.mdV[VY])))
05869         {
05870                 llwarns << "Using deprecated teleportlocationrequest." << llendl; 
05871                 // send the message
05872                 LLMessageSystem* msg = gMessageSystem;
05873                 msg->newMessageFast(_PREHASH_TeleportLocationRequest);
05874                 msg->nextBlockFast(_PREHASH_AgentData);
05875                 msg->addUUIDFast(_PREHASH_AgentID, getID());
05876                 msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
05877 
05878                 msg->nextBlockFast(_PREHASH_Info);
05879                 F32 width = regionp->getWidth();
05880                 LLVector3 pos(fmod((F32)pos_global.mdV[VX], width),
05881                                           fmod((F32)pos_global.mdV[VY], width),
05882                                           (F32)pos_global.mdV[VZ]);
05883                 F32 region_x = (F32)(pos_global.mdV[VX]);
05884                 F32 region_y = (F32)(pos_global.mdV[VY]);
05885                 U64 region_handle = to_region_handle_global(region_x, region_y);
05886                 msg->addU64Fast(_PREHASH_RegionHandle, region_handle);
05887                 msg->addVector3Fast(_PREHASH_Position, pos);
05888                 pos.mV[VX] += 1;
05889                 msg->addVector3Fast(_PREHASH_LookAt, pos);
05890                 sendReliableMessage();
05891         }
05892 }
05893 
05894 void LLAgent::setTeleportState(ETeleportState state)
05895 {
05896         mTeleportState = state;
05897         if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime"))
05898         {
05899                 LLFloaterSnapshot::hide(0);
05900         }
05901         if (mTeleportState == TELEPORT_MOVING)
05902         {
05903                 // We're outa here. Save "back" slurl.
05904                 mTeleportSourceSLURL = getSLURL();
05905         }
05906 }
05907 
05908 void LLAgent::fidget()
05909 {
05910         if (!getAFK())
05911         {
05912                 F32 curTime = mFidgetTimer.getElapsedTimeF32();
05913                 if (curTime > mNextFidgetTime)
05914                 {
05915                         // pick a random fidget anim here
05916                         S32 oldFidget = mCurrentFidget;
05917 
05918                         mCurrentFidget = ll_rand(NUM_AGENT_STAND_ANIMS);
05919 
05920                         if (mCurrentFidget != oldFidget)
05921                         {
05922                                 LLAgent::stopFidget();
05923 
05924                                 
05925                                 switch(mCurrentFidget)
05926                                 {
05927                                 case 0:
05928                                         mCurrentFidget = 0;
05929                                         break;
05930                                 case 1:
05931                                         sendAnimationRequest(ANIM_AGENT_STAND_1, ANIM_REQUEST_START);
05932                                         mCurrentFidget = 1;
05933                                         break;
05934                                 case 2:
05935                                         sendAnimationRequest(ANIM_AGENT_STAND_2, ANIM_REQUEST_START);
05936                                         mCurrentFidget = 2;
05937                                         break;
05938                                 case 3:
05939                                         sendAnimationRequest(ANIM_AGENT_STAND_3, ANIM_REQUEST_START);
05940                                         mCurrentFidget = 3;
05941                                         break;
05942                                 case 4:
05943                                         sendAnimationRequest(ANIM_AGENT_STAND_4, ANIM_REQUEST_START);
05944                                         mCurrentFidget = 4;
05945                                         break;
05946                                 }
05947                         }
05948 
05949                         // calculate next fidget time
05950                         mNextFidgetTime = curTime + ll_frand(MAX_FIDGET_TIME - MIN_FIDGET_TIME) + MIN_FIDGET_TIME;
05951                 }
05952         }
05953 }
05954 
05955 void LLAgent::stopFidget()
05956 {
05957         LLDynamicArray<LLUUID> anims;
05958         anims.put(ANIM_AGENT_STAND_1);
05959         anims.put(ANIM_AGENT_STAND_2);
05960         anims.put(ANIM_AGENT_STAND_3);
05961         anims.put(ANIM_AGENT_STAND_4);
05962 
05963         gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP);
05964 }
05965 
05966 
05967 void LLAgent::requestEnterGodMode()
05968 {
05969         LLMessageSystem* msg = gMessageSystem;
05970         msg->newMessageFast(_PREHASH_RequestGodlikePowers);
05971         msg->nextBlockFast(_PREHASH_AgentData);
05972         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
05973         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
05974         msg->nextBlockFast(_PREHASH_RequestBlock);
05975         msg->addBOOLFast(_PREHASH_Godlike, TRUE);
05976         msg->addUUIDFast(_PREHASH_Token, LLUUID::null);
05977 
05978         // simulators need to know about your request
05979         sendReliableMessage();
05980 }
05981 
05982 void LLAgent::requestLeaveGodMode()
05983 {
05984         LLMessageSystem* msg = gMessageSystem;
05985         msg->newMessageFast(_PREHASH_RequestGodlikePowers);
05986         msg->nextBlockFast(_PREHASH_AgentData);
05987         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
05988         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
05989         msg->nextBlockFast(_PREHASH_RequestBlock);
05990         msg->addBOOLFast(_PREHASH_Godlike, FALSE);
05991         msg->addUUIDFast(_PREHASH_Token, LLUUID::null);
05992 
05993         // simulator needs to know about your request
05994         sendReliableMessage();
05995 }
05996 
05997 // wearables
05998 LLAgent::createStandardWearablesAllDoneCallback::~createStandardWearablesAllDoneCallback()
05999 {
06000         gAgent.createStandardWearablesAllDone();
06001 }
06002 
06003 LLAgent::sendAgentWearablesUpdateCallback::~sendAgentWearablesUpdateCallback()
06004 {
06005         gAgent.sendAgentWearablesUpdate();
06006 }
06007 
06008 LLAgent::addWearableToAgentInventoryCallback::addWearableToAgentInventoryCallback(
06009         LLPointer<LLRefCount> cb, S32 index, LLWearable* wearable, U32 todo) :
06010         mIndex(index),
06011         mWearable(wearable),
06012         mTodo(todo),
06013         mCB(cb)
06014 {
06015 }
06016 
06017 void LLAgent::addWearableToAgentInventoryCallback::fire(const LLUUID& inv_item)
06018 {
06019         if (inv_item.isNull())
06020                 return;
06021 
06022         gAgent.addWearabletoAgentInventoryDone(mIndex, inv_item, mWearable);
06023 
06024         if (mTodo & CALL_UPDATE)
06025         {
06026                 gAgent.sendAgentWearablesUpdate();
06027         }
06028         if (mTodo & CALL_RECOVERDONE)
06029         {
06030                 gAgent.recoverMissingWearableDone();
06031         }
06032         /*
06033          * Do this for every one in the loop
06034          */
06035         if (mTodo & CALL_CREATESTANDARDDONE)
06036         {
06037                 gAgent.createStandardWearablesDone(mIndex);
06038         }
06039         if (mTodo & CALL_MAKENEWOUTFITDONE)
06040         {
06041                 gAgent.makeNewOutfitDone(mIndex);
06042         }
06043 }
06044 
06045 void LLAgent::addWearabletoAgentInventoryDone(
06046         S32 index,
06047         const LLUUID& item_id,
06048         LLWearable* wearable)
06049 {
06050         if (item_id.isNull())
06051                 return;
06052 
06053         LLUUID old_item_id = mWearableEntry[index].mItemID;
06054         mWearableEntry[index].mItemID = item_id;
06055         mWearableEntry[index].mWearable = wearable;
06056         if (old_item_id.notNull())
06057                 gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
06058         gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
06059         LLViewerInventoryItem* item = gInventory.getItem(item_id);
06060         if(item && wearable)
06061         {
06062                 // We're changing the asset id, so we both need to set it
06063                 // locally via setAssetUUID() and via setTransactionID() which
06064                 // will be decoded on the server. JC
06065                 item->setAssetUUID(wearable->getID());
06066                 item->setTransactionID(wearable->getTransactionID());
06067                 gInventory.addChangedMask(LLInventoryObserver::INTERNAL, item_id);
06068                 item->updateServer(FALSE);
06069         }
06070         gInventory.notifyObservers();
06071 }
06072 
06073 void LLAgent::sendAgentWearablesUpdate()
06074 {
06075         // First make sure that we have inventory items for each wearable
06076         S32 i;
06077         for(i=0; i < WT_COUNT; ++i)
06078         {
06079                 LLWearable* wearable = mWearableEntry[ i ].mWearable;
06080                 if (wearable)
06081                 {
06082                         if( mWearableEntry[ i ].mItemID.isNull() )
06083                         {
06084                                 LLPointer<LLInventoryCallback> cb =
06085                                         new addWearableToAgentInventoryCallback(
06086                                                 LLPointer<LLRefCount>(NULL),
06087                                                 i,
06088                                                 wearable,
06089                                                 addWearableToAgentInventoryCallback::CALL_NONE);
06090                                 addWearableToAgentInventory(cb, wearable);
06091                         }
06092                         else
06093                         {
06094                                 gInventory.addChangedMask( LLInventoryObserver::LABEL,
06095                                                 mWearableEntry[i].mItemID );
06096                         }
06097                 }
06098         }
06099 
06100         // Then make sure the inventory is in sync with the avatar.
06101         gInventory.notifyObservers();
06102 
06103         // Send the AgentIsNowWearing 
06104         gMessageSystem->newMessageFast(_PREHASH_AgentIsNowWearing);
06105 
06106         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
06107         gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
06108         gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
06109 
06110         lldebugs << "sendAgentWearablesUpdate()" << llendl;
06111         for(i=0; i < WT_COUNT; ++i)
06112         {
06113                 gMessageSystem->nextBlockFast(_PREHASH_WearableData);
06114 
06115                 U8 type_u8 = (U8)i;
06116                 gMessageSystem->addU8Fast(_PREHASH_WearableType, type_u8 );
06117 
06118                 LLWearable* wearable = mWearableEntry[ i ].mWearable;
06119                 if( wearable )
06120                 {
06121                         //llinfos << "Sending wearable " << wearable->getName() << llendl;
06122                         gMessageSystem->addUUIDFast(_PREHASH_ItemID, mWearableEntry[ i ].mItemID );
06123                 }
06124                 else
06125                 {
06126                         //llinfos << "Not wearing wearable type " << LLWearable::typeToTypeName((EWearableType)i) << llendl;
06127                         gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null );
06128                 }
06129 
06130                 lldebugs << "       " << LLWearable::typeToTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getID() : LLUUID::null) << llendl;
06131         }
06132         gAgent.sendReliableMessage();
06133 }
06134 
06135 void LLAgent::saveWearable( EWearableType type, BOOL send_update )
06136 {
06137         LLWearable* old_wearable = mWearableEntry[(S32)type].mWearable;
06138         if( old_wearable && (old_wearable->isDirty() || old_wearable->isOldVersion()) )
06139         {
06140                 LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable );
06141                 mWearableEntry[(S32)type].mWearable = new_wearable;
06142 
06143                 LLInventoryItem* item = gInventory.getItem(mWearableEntry[(S32)type].mItemID);
06144                 if( item )
06145                 {
06146                         // Update existing inventory item
06147                         LLPointer<LLViewerInventoryItem> template_item =
06148                                 new LLViewerInventoryItem(item->getUUID(),
06149                                                                                   item->getParentUUID(),
06150                                                                                   item->getPermissions(),
06151                                                                                   new_wearable->getID(),
06152                                                                                   new_wearable->getAssetType(),
06153                                                                                   item->getInventoryType(),
06154                                                                                   item->getName(),
06155                                                                                   item->getDescription(),
06156                                                                                   item->getSaleInfo(),
06157                                                                                   item->getFlags(),
06158                                                                                   item->getCreationDate());
06159                         template_item->setTransactionID(new_wearable->getTransactionID());
06160                         template_item->updateServer(FALSE);
06161                         gInventory.updateItem(template_item);
06162                 }
06163                 else
06164                 {
06165                         // Add a new inventory item (shouldn't ever happen here)
06166                         U32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
06167                         if (send_update)
06168                         {
06169                                 todo |= addWearableToAgentInventoryCallback::CALL_UPDATE;
06170                         }
06171                         LLPointer<LLInventoryCallback> cb =
06172                                 new addWearableToAgentInventoryCallback(
06173                                         LLPointer<LLRefCount>(NULL),
06174                                         (S32)type,
06175                                         new_wearable,
06176                                         todo);
06177                         addWearableToAgentInventory(cb, new_wearable);
06178                         return;
06179                 }
06180 
06181                 if( send_update )
06182                 {
06183                         sendAgentWearablesUpdate();
06184                 }
06185         }
06186 }
06187 
06188 void LLAgent::saveWearableAs(
06189         EWearableType type,
06190         const std::string& new_name,
06191         BOOL save_in_lost_and_found)
06192 {
06193         if(!isWearableCopyable(type))
06194         {
06195                 llwarns << "LLAgent::saveWearableAs() not copyable." << llendl;
06196                 return;
06197         }
06198         LLWearable* old_wearable = getWearable(type);
06199         if(!old_wearable)
06200         {
06201                 llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl;
06202                 return;
06203         }
06204         LLInventoryItem* item = gInventory.getItem(mWearableEntry[type].mItemID);
06205         if(!item)
06206         {
06207                 llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl;
06208                 return;
06209         }
06210         std::string trunc_name(new_name);
06211         LLString::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN);
06212         LLWearable* new_wearable = gWearableList.createCopyFromAvatar(
06213                 old_wearable,
06214                 trunc_name);
06215         LLPointer<LLInventoryCallback> cb =
06216                 new addWearableToAgentInventoryCallback(
06217                         LLPointer<LLRefCount>(NULL),
06218                         type,
06219                         new_wearable,
06220                         addWearableToAgentInventoryCallback::CALL_UPDATE);
06221         LLUUID category_id;
06222         if (save_in_lost_and_found)
06223         {
06224                 category_id = gInventory.findCategoryUUIDForType(
06225                         LLAssetType::AT_LOST_AND_FOUND);
06226         }
06227         else
06228         {
06229                 // put in same folder as original
06230                 category_id = item->getParentUUID();
06231         }
06232 
06233         copy_inventory_item(
06234                 gAgent.getID(),
06235                 item->getPermissions().getOwner(),
06236                 item->getUUID(),
06237                 category_id,
06238                 new_name,
06239                 cb);
06240 
06241 /*
06242         LLWearable* old_wearable = getWearable( type );
06243         if( old_wearable )
06244         {
06245                 LLString old_name = old_wearable->getName();
06246                 old_wearable->setName( new_name );
06247                 LLWearable* new_wearable = gWearableList.createCopyFromAvatar( old_wearable );
06248                 old_wearable->setName( old_name );
06249                         
06250                 LLUUID category_id;
06251                 LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID );
06252                 if( item )
06253                 {
06254                         new_wearable->setPermissions(item->getPermissions());
06255                         if (save_in_lost_and_found)
06256                         {
06257                                 category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
06258                         }
06259                         else
06260                         {
06261                                 // put in same folder as original
06262                                 category_id = item->getParentUUID();
06263                         }
06264                         LLInventoryView* view = LLInventoryView::getActiveInventory();
06265                         if(view)
06266                         {
06267                                 view->getPanel()->setSelection(item->getUUID(), TAKE_FOCUS_NO);
06268                         }
06269                 }
06270 
06271                 mWearableEntry[ type ].mWearable = new_wearable;
06272                 LLPointer<LLInventoryCallback> cb =
06273                         new addWearableToAgentInventoryCallback(
06274                                 LLPointer<LLRefCount>(NULL),
06275                                 type,
06276                                 addWearableToAgentInventoryCallback::CALL_UPDATE);
06277                 addWearableToAgentInventory(cb, new_wearable, category_id);
06278         }
06279 */
06280 }
06281 
06282 void LLAgent::revertWearable( EWearableType type )
06283 {
06284         LLWearable* wearable = mWearableEntry[(S32)type].mWearable;
06285         if( wearable )
06286         {
06287                 wearable->writeToAvatar( TRUE );
06288         }
06289         sendAgentSetAppearance();
06290 }
06291 
06292 void LLAgent::revertAllWearables()
06293 {
06294         for( S32 i=0; i < WT_COUNT; i++ )
06295         {
06296                 revertWearable( (EWearableType)i );
06297         }
06298 }
06299 
06300 void LLAgent::saveAllWearables()
06301 {
06302         //if(!gInventory.isLoaded())
06303         //{
06304         //      return;
06305         //}
06306 
06307         for( S32 i=0; i < WT_COUNT; i++ )
06308         {
06309                 saveWearable( (EWearableType)i, FALSE );
06310         }
06311         sendAgentWearablesUpdate();
06312 }
06313 
06314 // Called when the user changes the name of a wearable inventory item that is currenlty being worn.
06315 void LLAgent::setWearableName( const LLUUID& item_id, const std::string& new_name )
06316 {
06317         for( S32 i=0; i < WT_COUNT; i++ )
06318         {
06319                 if( mWearableEntry[i].mItemID == item_id )
06320                 {
06321                         LLWearable* old_wearable = mWearableEntry[i].mWearable;
06322                         llassert( old_wearable );
06323 
06324                         LLString old_name = old_wearable->getName();
06325                         old_wearable->setName( new_name );
06326                         LLWearable* new_wearable = gWearableList.createCopy( old_wearable );
06327                         LLInventoryItem* item = gInventory.getItem(item_id);
06328                         if(item)
06329                         {
06330                                 new_wearable->setPermissions(item->getPermissions());
06331                         }
06332                         old_wearable->setName( old_name );
06333 
06334                         mWearableEntry[i].mWearable = new_wearable;
06335                         sendAgentWearablesUpdate();
06336                         break;
06337                 }
06338         }
06339 }
06340 
06341 
06342 BOOL LLAgent::isWearableModifiable(EWearableType type)
06343 {
06344         LLUUID item_id = getWearableItem(type);
06345         if(!item_id.isNull())
06346         {
06347                 LLInventoryItem* item = gInventory.getItem(item_id);
06348                 if(item && item->getPermissions().allowModifyBy(gAgent.getID(),
06349                                                                                                                 gAgent.getGroupID()))
06350                 {
06351                         return TRUE;
06352                 }
06353         }
06354         return FALSE;
06355 }
06356 
06357 BOOL LLAgent::isWearableCopyable(EWearableType type)
06358 {
06359         LLUUID item_id = getWearableItem(type);
06360         if(!item_id.isNull())
06361         {
06362                 LLInventoryItem* item = gInventory.getItem(item_id);
06363                 if(item && item->getPermissions().allowCopyBy(gAgent.getID(),
06364                                                                                                           gAgent.getGroupID()))
06365                 {
06366                         return TRUE;
06367                 }
06368         }
06369         return FALSE;
06370 }
06371 
06372 U32 LLAgent::getWearablePermMask(EWearableType type)
06373 {
06374         LLUUID item_id = getWearableItem(type);
06375         if(!item_id.isNull())
06376         {
06377                 LLInventoryItem* item = gInventory.getItem(item_id);
06378                 if(item)
06379                 {
06380                         return item->getPermissions().getMaskOwner();
06381                 }
06382         }
06383         return PERM_NONE;
06384 }
06385 
06386 LLInventoryItem* LLAgent::getWearableInventoryItem(EWearableType type)
06387 {
06388         LLUUID item_id = getWearableItem(type);
06389         LLInventoryItem* item = NULL;
06390         if(item_id.notNull())
06391         {
06392                  item = gInventory.getItem(item_id);
06393         }
06394         return item;
06395 }
06396 
06397 LLWearable* LLAgent::getWearableFromWearableItem( const LLUUID& item_id )
06398 {
06399         for( S32 i=0; i < WT_COUNT; i++ )
06400         {
06401                 if( mWearableEntry[i].mItemID == item_id )
06402                 {
06403                         return mWearableEntry[i].mWearable;
06404                 }
06405         }
06406         return NULL;
06407 }
06408 
06409 
06410 void LLAgent::sendAgentWearablesRequest()
06411 {
06412         gMessageSystem->newMessageFast(_PREHASH_AgentWearablesRequest);
06413         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
06414         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
06415         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
06416         sendReliableMessage();
06417 }
06418 
06419 // Used to enable/disable menu items.
06420 // static
06421 BOOL LLAgent::selfHasWearable( void* userdata )
06422 {
06423         EWearableType type = (EWearableType)(intptr_t)userdata;
06424         return gAgent.getWearable( type ) != NULL;
06425 }
06426 
06427 BOOL LLAgent::isWearingItem( const LLUUID& item_id )
06428 {
06429         return (getWearableFromWearableItem( item_id ) != NULL);
06430 }
06431 
06432 
06433 // static
06434 void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void** user_data )
06435 {
06436         // We should only receive this message a single time.  Ignore subsequent AgentWearablesUpdates
06437         // that may result from AgentWearablesRequest having been sent more than once. 
06438         static BOOL first = TRUE;
06439         if( first )
06440         {
06441                 first = FALSE;
06442         }
06443         else
06444         {
06445                 return;
06446         }
06447         
06448         if (gNoRender)
06449         {
06450                 return;
06451         }
06452 
06453         LLUUID agent_id;
06454         gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
06455 
06456         LLVOAvatar* avatar = gAgent.getAvatarObject();
06457         if( avatar && (agent_id == avatar->getID()) )
06458         {
06459                 gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgent.mAgentWearablesUpdateSerialNum );
06460                 
06461                 S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
06462                 if( num_wearables < 4 )
06463                 {
06464                         // Transitional state.  Avatars should always have at least their body parts (hair, eyes, shape and skin).
06465                         // The fact that they don't have any here (only a dummy is sent) implies that this account existed
06466                         // before we had wearables, or that the database has gotten messed up.
06467                         // Deal with this by creating new body parts.
06468                         //avatar->createStandardWearables();
06469 
06470                         // no, deal with it by noting that we need to choose a
06471                         // gender.
06472                         gAgent.setGenderChosen(FALSE);
06473                         return;
06474                 }
06475 
06476                 //lldebugs << "processAgentInitialWearablesUpdate()" << llendl;
06477                 // Add wearables
06478                 LLUUID asset_id_array[ WT_COUNT ];
06479                 S32 i;
06480                 for( i=0; i < num_wearables; i++ )
06481                 {
06482                         U8 type_u8 = 0;
06483                         gMessageSystem->getU8Fast(_PREHASH_WearableData, _PREHASH_WearableType, type_u8, i );
06484                         if( type_u8 >= WT_COUNT )
06485                         {
06486                                 continue;
06487                         }
06488                         EWearableType type = (EWearableType) type_u8;
06489 
06490                         LLUUID item_id;
06491                         gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_ItemID, item_id, i );
06492 
06493                         LLUUID asset_id;
06494                         gMessageSystem->getUUIDFast(_PREHASH_WearableData, _PREHASH_AssetID, asset_id, i );
06495                         if( asset_id.isNull() )
06496                         {
06497                                 LLWearable::removeFromAvatar( type, FALSE );
06498                         }
06499                         else
06500                         {
06501                                 LLAssetType::EType asset_type = LLWearable::typeToAssetType( type );
06502                                 if( asset_type == LLAssetType::AT_NONE )
06503                                 {
06504                                         continue;
06505                                 }
06506 
06507                                 gAgent.mWearableEntry[type].mItemID = item_id;
06508                                 asset_id_array[type] = asset_id;
06509                         }
06510 
06511                         lldebugs << "       " << LLWearable::typeToTypeLabel(type) << llendl;
06512                 }
06513 
06514                 // now that we have the asset ids...request the wearable assets
06515                 for( i = 0; i < WT_COUNT; i++ )
06516                 {
06517                         if( !gAgent.mWearableEntry[i].mItemID.isNull() )
06518                         {
06519                                 gWearableList.getAsset( 
06520                                         asset_id_array[i],
06521                                         LLString::null,
06522                                         LLWearable::typeToAssetType( (EWearableType) i ), 
06523                                         LLAgent::onInitialWearableAssetArrived, (void*)(intptr_t)i );
06524                         }
06525                 }
06526         }
06527 }
06528 
06529 // A single wearable that the avatar was wearing on start-up has arrived from the database.
06530 // static
06531 void LLAgent::onInitialWearableAssetArrived( LLWearable* wearable, void* userdata )
06532 {
06533         EWearableType type = (EWearableType)(intptr_t)userdata;
06534 
06535         LLVOAvatar* avatar = gAgent.getAvatarObject();
06536         if( !avatar )
06537         {
06538                 return;
06539         }
06540 
06541         if( wearable )
06542         {
06543                 llassert( type == wearable->getType() );
06544                 gAgent.mWearableEntry[ type ].mWearable = wearable;
06545 
06546                 // disable composites if initial textures are baked
06547                 avatar->setupComposites();
06548                 gAgent.queryWearableCache();
06549 
06550                 wearable->writeToAvatar( FALSE );
06551                 avatar->setCompositeUpdatesEnabled(TRUE);
06552                 gInventory.addChangedMask( LLInventoryObserver::LABEL, gAgent.mWearableEntry[type].mItemID );
06553         }
06554         else
06555         {
06556                 // Somehow the asset doesn't exist in the database.
06557                 gAgent.recoverMissingWearable( type );
06558         }
06559 
06560         gInventory.notifyObservers();
06561 
06562         // Have all the wearables that the avatar was wearing at log-in arrived?
06563         if( !gAgent.mWearablesLoaded )
06564         {
06565                 gAgent.mWearablesLoaded = TRUE;
06566                 for( S32 i = 0; i < WT_COUNT; i++ )
06567                 {
06568                         if( !gAgent.mWearableEntry[i].mItemID.isNull() && !gAgent.mWearableEntry[i].mWearable )
06569                         {
06570                                 gAgent.mWearablesLoaded = FALSE;
06571                                 break;
06572                         }
06573                 }
06574         }
06575 
06576         if( gAgent.mWearablesLoaded )
06577         {
06578                 // Make sure that the server's idea of the avatar's wearables actually match the wearables.
06579                 gAgent.sendAgentSetAppearance();
06580 
06581                 // Check to see if there are any baked textures that we hadn't uploaded before we logged off last time.
06582                 // If there are any, schedule them to be uploaded as soon as the layer textures they depend on arrive.
06583                 if( !gAgent.cameraCustomizeAvatar() )
06584                 {
06585                         avatar->requestLayerSetUploads();
06586                 }
06587         }
06588 }
06589 
06590 // Normally, all wearables referred to "AgentWearablesUpdate" will correspond to actual assets in the
06591 // database.  If for some reason, we can't load one of those assets, we can try to reconstruct it so that
06592 // the user isn't left without a shape, for example.  (We can do that only after the inventory has loaded.)
06593 void LLAgent::recoverMissingWearable( EWearableType type )
06594 {
06595         // Try to recover by replacing missing wearable with a new one.
06596         LLNotifyBox::showXml("ReplacedMissingWearable");
06597         lldebugs << "Wearable " << LLWearable::typeToTypeLabel( type ) << " could not be downloaded.  Replaced inventory item with default wearable." << llendl;
06598         LLWearable* new_wearable = gWearableList.createNewWearable(type);
06599 
06600         S32 type_s32 = (S32) type;
06601         mWearableEntry[type_s32].mWearable = new_wearable;
06602         new_wearable->writeToAvatar( TRUE );
06603 
06604         // Add a new one in the lost and found folder.
06605         // (We used to overwrite the "not found" one, but that could potentially
06606         // destory content.) JC
06607         LLUUID lost_and_found_id = 
06608                 gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
06609         LLPointer<LLInventoryCallback> cb =
06610                 new addWearableToAgentInventoryCallback(
06611                         LLPointer<LLRefCount>(NULL),
06612                         type_s32,
06613                         new_wearable,
06614                         addWearableToAgentInventoryCallback::CALL_RECOVERDONE);
06615         addWearableToAgentInventory( cb, new_wearable, lost_and_found_id, TRUE);
06616 }
06617 
06618 void LLAgent::recoverMissingWearableDone()
06619 {
06620         // Have all the wearables that the avatar was wearing at log-in arrived or been fabricated?
06621         mWearablesLoaded = TRUE;
06622         for( S32 i = 0; i < WT_COUNT; i++ )
06623         {
06624                 if( !mWearableEntry[i].mItemID.isNull() && !mWearableEntry[i].mWearable )
06625                 {
06626                         mWearablesLoaded = FALSE;
06627                         break;
06628                 }
06629         }
06630 
06631         if( mWearablesLoaded )
06632         {
06633                 // Make sure that the server's idea of the avatar's wearables actually match the wearables.
06634                 sendAgentSetAppearance();
06635         }
06636         else
06637         {
06638                 gInventory.addChangedMask( LLInventoryObserver::LABEL, LLUUID::null );
06639                 gInventory.notifyObservers();
06640         }
06641 }
06642 
06643 void LLAgent::createStandardWearables(BOOL female)
06644 {
06645         llwarns << "Creating Standard " << (female ? "female" : "male" )
06646                         << " Wearables" << llendl;
06647 
06648         if (mAvatarObject.isNull())
06649         {
06650                 return;
06651         }
06652 
06653         if(female) mAvatarObject->setSex(SEX_FEMALE);
06654         else mAvatarObject->setSex(SEX_MALE);
06655 
06656         BOOL create[WT_COUNT] = 
06657         {
06658                 TRUE,  //WT_SHAPE
06659                 TRUE,  //WT_SKIN
06660                 TRUE,  //WT_HAIR
06661                 TRUE,  //WT_EYES
06662                 TRUE,  //WT_SHIRT
06663                 TRUE,  //WT_PANTS
06664                 TRUE,  //WT_SHOES
06665                 TRUE,  //WT_SOCKS
06666                 FALSE, //WT_JACKET
06667                 FALSE, //WT_GLOVES
06668                 TRUE,  //WT_UNDERSHIRT
06669                 TRUE,  //WT_UNDERPANTS
06670                 FALSE  //WT_SKIRT
06671         };
06672 
06673         for( S32 i=0; i < WT_COUNT; i++ )
06674         {
06675                 bool once = false;
06676                 LLPointer<LLRefCount> donecb = NULL;
06677                 if( create[i] )
06678                 {
06679                         if (!once)
06680                         {
06681                                 once = true;
06682                                 donecb = new createStandardWearablesAllDoneCallback;
06683                         }
06684                         llassert( mWearableEntry[i].mWearable == NULL );
06685                         LLWearable* wearable = gWearableList.createNewWearable((EWearableType)i);
06686                         mWearableEntry[i].mWearable = wearable;
06687                         // no need to update here...
06688                         LLPointer<LLInventoryCallback> cb =
06689                                 new addWearableToAgentInventoryCallback(
06690                                         donecb,
06691                                         i,
06692                                         wearable,
06693                                         addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE);
06694                         addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE);
06695                 }
06696         }
06697 }
06698 void LLAgent::createStandardWearablesDone(S32 index)
06699 {
06700         LLWearable* wearable = mWearableEntry[index].mWearable;
06701 
06702         if (wearable)
06703         {
06704                 wearable->writeToAvatar(TRUE);
06705         }
06706 }
06707 
06708 void LLAgent::createStandardWearablesAllDone()
06709 {
06710         // ... because sendAgentWearablesUpdate will notify inventory
06711         // observers.
06712         mWearablesLoaded = TRUE; 
06713         sendAgentWearablesUpdate();
06714         sendAgentSetAppearance();
06715 
06716         // Treat this as the first texture entry message, if none received yet
06717         mAvatarObject->onFirstTEMessageReceived();
06718 }
06719 
06720 void LLAgent::makeNewOutfit( 
06721         const std::string& new_folder_name,
06722         const LLDynamicArray<S32>& wearables_to_include,
06723         const LLDynamicArray<S32>& attachments_to_include,
06724         BOOL rename_clothing)
06725 {
06726         if (mAvatarObject.isNull())
06727         {
06728                 return;
06729         }
06730 
06731         // First, make a folder in the Clothes directory.
06732         LLUUID folder_id = gInventory.createNewCategory(
06733                 gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING),
06734                 LLAssetType::AT_NONE,
06735                 new_folder_name);
06736 
06737         bool found_first_item = false;
06738 
06740         // Wearables
06741 
06742         if( wearables_to_include.count() )
06743         {
06744                 // Then, iterate though each of the wearables and save copies of them in the folder.
06745                 S32 i;
06746                 S32 count = wearables_to_include.count();
06747                 LLDynamicArray<LLUUID> delete_items;
06748                 LLPointer<LLRefCount> cbdone = NULL;
06749                 for( i = 0; i < count; ++i )
06750                 {
06751                         S32 index = wearables_to_include[i];
06752                         LLWearable* old_wearable = mWearableEntry[ index ].mWearable;
06753                         if( old_wearable )
06754                         {
06755                                 std::string new_name;
06756                                 LLWearable* new_wearable;
06757                                 new_wearable = gWearableList.createCopy(old_wearable);
06758                                 if (rename_clothing)
06759                                 {
06760                                         new_name = new_folder_name;
06761                                         new_name.append(" ");
06762                                         new_name.append(old_wearable->getTypeLabel());
06763                                         LLString::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
06764                                         new_wearable->setName(new_name);
06765                                 }
06766 
06767                                 LLViewerInventoryItem* item = gInventory.getItem(mWearableEntry[index].mItemID);
06768                                 S32 todo = addWearableToAgentInventoryCallback::CALL_NONE;
06769                                 if (!found_first_item)
06770                                 {
06771                                         found_first_item = true;
06772                                         /* set the focus to the first item */
06773                                         todo |= addWearableToAgentInventoryCallback::CALL_MAKENEWOUTFITDONE;
06774                                         /* send the agent wearables update when done */
06775                                         cbdone = new sendAgentWearablesUpdateCallback;
06776                                 }
06777                                 LLPointer<LLInventoryCallback> cb =
06778                                         new addWearableToAgentInventoryCallback(
06779                                                 cbdone,
06780                                                 index,
06781                                                 new_wearable,
06782                                                 todo);
06783                                 if (isWearableCopyable((EWearableType)index))
06784                                 {
06785                                         copy_inventory_item(
06786                                                 gAgent.getID(),
06787                                                 item->getPermissions().getOwner(),
06788                                                 item->getUUID(),
06789                                                 folder_id,
06790                                                 new_name,
06791                                                 cb);
06792                                 }
06793                                 else
06794                                 {
06795                                         move_inventory_item(
06796                                                 gAgent.getID(),
06797                                                 gAgent.getSessionID(),
06798                                                 item->getUUID(),
06799                                                 folder_id,
06800                                                 new_name,
06801                                                 cb);
06802                                 }
06803                         }
06804                 }
06805                 gInventory.notifyObservers();
06806         }
06807 
06808 
06810         // Attachments
06811 
06812         if( attachments_to_include.count() )
06813         {
06814                 BOOL msg_started = FALSE;
06815                 LLMessageSystem* msg = gMessageSystem;
06816                 for( S32 i = 0; i < attachments_to_include.count(); i++ )
06817                 {
06818                         S32 attachment_pt = attachments_to_include[i];
06819                         LLViewerJointAttachment* attachment = get_if_there(mAvatarObject->mAttachmentPoints, attachment_pt, (LLViewerJointAttachment*)NULL );
06820                         if(!attachment) continue;
06821                         LLViewerObject* attached_object = attachment->getObject();
06822                         if(!attached_object) continue;
06823                         const LLUUID& item_id = attachment->getItemID();
06824                         if(item_id.isNull()) continue;
06825                         LLInventoryItem* item = gInventory.getItem(item_id);
06826                         if(!item) continue;
06827                         if(!msg_started)
06828                         {
06829                                 msg_started = TRUE;
06830                                 msg->newMessage("CreateNewOutfitAttachments");
06831                                 msg->nextBlock("AgentData");
06832                                 msg->addUUID("AgentID", getID());
06833                                 msg->addUUID("SessionID", getSessionID());
06834                                 msg->nextBlock("HeaderData");
06835                                 msg->addUUID("NewFolderID", folder_id);
06836                         }
06837                         msg->nextBlock("ObjectData");
06838                         msg->addUUID("OldItemID", item_id);
06839                         msg->addUUID("OldFolderID", item->getParentUUID());
06840                 }
06841 
06842                 if( msg_started )
06843                 {
06844                         sendReliableMessage();
06845                 }
06846 
06847         } 
06848 }
06849 
06850 void LLAgent::makeNewOutfitDone(S32 index)
06851 {
06852         LLUUID first_item_id = mWearableEntry[index].mItemID;
06853         // Open the inventory and select the first item we added.
06854         if( first_item_id.notNull() )
06855         {
06856                 LLInventoryView* view = LLInventoryView::getActiveInventory();
06857                 if(view)
06858                 {
06859                         view->getPanel()->setSelection(first_item_id, TAKE_FOCUS_NO);
06860                 }
06861         }
06862 }
06863 
06864 
06865 void LLAgent::addWearableToAgentInventory(
06866         LLPointer<LLInventoryCallback> cb,
06867         LLWearable* wearable,
06868         const LLUUID& category_id,
06869         BOOL notify)
06870 {
06871         create_inventory_item(
06872                 gAgent.getID(),
06873                 gAgent.getSessionID(),
06874                 category_id,
06875                 wearable->getTransactionID(),
06876                 wearable->getName(),
06877                 wearable->getDescription(),
06878                 wearable->getAssetType(),
06879                 LLInventoryType::IT_WEARABLE,
06880                 wearable->getType(),
06881                 wearable->getPermissions().getMaskNextOwner(),
06882                 cb);
06883 }
06884 
06885 //-----------------------------------------------------------------------------
06886 // sendAgentSetAppearance()
06887 //-----------------------------------------------------------------------------
06888 void LLAgent::sendAgentSetAppearance()
06889 {
06890         if (mAvatarObject.isNull()) return;
06891 
06892         if (mNumPendingQueries > 0 && !gAgent.cameraCustomizeAvatar()) 
06893         {
06894                 return;
06895         }
06896 
06897         llinfos << "TAT: Sent AgentSetAppearance: " <<
06898                 (( mAvatarObject->getTEImage( LLVOAvatar::TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR )  ? "HEAD " : "head " ) <<
06899                 (( mAvatarObject->getTEImage( LLVOAvatar::TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "UPPER " : "upper " ) <<
06900                 (( mAvatarObject->getTEImage( LLVOAvatar::TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "LOWER " : "lower " ) <<
06901                 (( mAvatarObject->getTEImage( LLVOAvatar::TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR )  ? "EYES" : "eyes" ) << llendl;
06902         //dumpAvatarTEs( "sendAgentSetAppearance()" );
06903 
06904         LLMessageSystem* msg = gMessageSystem;
06905         msg->newMessageFast(_PREHASH_AgentSetAppearance);
06906         msg->nextBlockFast(_PREHASH_AgentData);
06907         msg->addUUIDFast(_PREHASH_AgentID, getID());
06908         msg->addUUIDFast(_PREHASH_SessionID, getSessionID());
06909 
06910         // correct for the collision tolerance (to make it look like the 
06911         // agent is actually walking on the ground/object)
06912         // NOTE -- when we start correcting all of the other Havok geometry 
06913         // to compensate for the COLLISION_TOLERANCE ugliness we will have 
06914         // to tweak this number again
06915         LLVector3 body_size = mAvatarObject->mBodySize;
06916         msg->addVector3Fast(_PREHASH_Size, body_size);  
06917 
06918         // To guard against out of order packets
06919         // Note: always start by sending 1.  This resets the server's count. 0 on the server means "uninitialized"
06920         mAppearanceSerialNum++;
06921         msg->addU32Fast(_PREHASH_SerialNum, mAppearanceSerialNum );
06922 
06923         // is texture data current relative to wearables?
06924         // KLW - TAT this will probably need to check the local queue.
06925         BOOL textures_current = !mAvatarObject->hasPendingBakedUploads() && mWearablesLoaded;
06926 
06927         S32 baked_texture_index;
06928         for( baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++ )
06929         {
06930                 S32 tex_index = LLVOAvatar::sBakedTextureIndices[baked_texture_index];
06931 
06932                 // if we're not wearing a skirt, we don't need the texture to be baked
06933                 if (tex_index == LLVOAvatar::TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT))
06934                 {
06935                         continue;
06936                 }
06937 
06938                 // IMG_DEFAULT_AVATAR means not baked
06939                 if (mAvatarObject->getTEImage( tex_index)->getID() == IMG_DEFAULT_AVATAR)
06940                 {
06941                         textures_current = FALSE;
06942                         break;
06943                 }
06944         }
06945 
06946         // only update cache entries if we have all our baked textures
06947         if (textures_current)
06948         {
06949                 llinfos << "TAT: Sending cached texture data" << llendl;
06950                 for (baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++)
06951                 {
06952                         LLUUID hash;
06953 
06954                         for( S32 wearable_num = 0; wearable_num < MAX_WEARABLES_PER_LAYERSET; wearable_num++ )
06955                         {
06956                                 EWearableType wearable_type = WEARABLE_BAKE_TEXTURE_MAP[baked_texture_index][wearable_num];
06957 
06958                                 LLWearable* wearable = getWearable( wearable_type );
06959                                 if (wearable)
06960                                 {
06961                                         hash ^= wearable->getID();
06962                                 }
06963                         }
06964 
06965                         if (hash.notNull())
06966                         {
06967                                 hash ^= BAKED_TEXTURE_HASH[baked_texture_index];
06968                         }
06969 
06970                         S32 tex_index = LLVOAvatar::sBakedTextureIndices[baked_texture_index];
06971 
06972                         msg->nextBlockFast(_PREHASH_WearableData);
06973                         msg->addUUIDFast(_PREHASH_CacheID, hash);
06974                         msg->addU8Fast(_PREHASH_TextureIndex, (U8)tex_index);
06975                 }
06976         }
06977 
06978         msg->nextBlockFast(_PREHASH_ObjectData);
06979         mAvatarObject->packTEMessage( gMessageSystem );
06980 
06981         S32 transmitted_params = 0;
06982         for (LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarObject->getFirstVisualParam();
06983                  param;
06984                  param = (LLViewerVisualParam*)mAvatarObject->getNextVisualParam())
06985         {
06986                 F32 param_value = param->getWeight();
06987         
06988                 if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
06989                 {
06990                         msg->nextBlockFast(_PREHASH_VisualParam );
06991                         
06992                         // We don't send the param ids.  Instead, we assume that the receiver has the same params in the same sequence.
06993                         U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight());
06994                         msg->addU8Fast(_PREHASH_ParamValue, new_weight );
06995                         transmitted_params++;
06996                 }
06997         }
06998 
06999 //      llinfos << "Avatar XML num VisualParams transmitted = " << transmitted_params << llendl;
07000         sendReliableMessage();
07001 }
07002 
07003 void LLAgent::sendAgentDataUpdateRequest()
07004 {
07005         gMessageSystem->newMessageFast(_PREHASH_AgentDataUpdateRequest);
07006         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
07007         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
07008         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
07009         sendReliableMessage();
07010 }
07011 
07012 void LLAgent::removeWearable( EWearableType type )
07013 {
07014         LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
07015 
07016         if ( (gAgent.isTeen())
07017                  && (type == WT_UNDERSHIRT || type == WT_UNDERPANTS))
07018         {
07019                 // Can't take off underclothing in simple UI mode or on PG accounts
07020                 return;
07021         }
07022 
07023         if( old_wearable )
07024         {
07025                 if( old_wearable->isDirty() )
07026                 {
07027                         // Bring up view-modal dialog: Save changes? Yes, No, Cancel
07028                         gViewerWindow->alertXml("WearableSave", LLAgent::onRemoveWearableDialog, (void*)type );
07029                         return;
07030                 }
07031                 else
07032                 {
07033                         removeWearableFinal( type );
07034                 }
07035         }
07036 }
07037 
07038 // static 
07039 void LLAgent::onRemoveWearableDialog( S32 option, void* userdata )
07040 {
07041         EWearableType type = (EWearableType)(intptr_t)userdata;
07042         switch( option )
07043         {
07044         case 0:  // "Save"
07045                 gAgent.saveWearable( type );
07046                 gAgent.removeWearableFinal( type );
07047                 break;
07048 
07049         case 1:  // "Don't Save"
07050                 gAgent.removeWearableFinal( type );
07051                 break;
07052 
07053         case 2: // "Cancel"
07054                 break;
07055 
07056         default:
07057                 llassert(0);
07058                 break;
07059         }
07060 }
07061 
07062 // Called by removeWearable() and onRemoveWearableDialog() to actually do the removal.
07063 void LLAgent::removeWearableFinal( EWearableType type )
07064 {
07065         LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
07066 
07067         gInventory.addChangedMask( LLInventoryObserver::LABEL, mWearableEntry[type].mItemID );
07068 
07069         mWearableEntry[ type ].mWearable = NULL;
07070         mWearableEntry[ type ].mItemID.setNull();
07071 
07072         queryWearableCache();
07073 
07074         if( old_wearable )
07075         {
07076                 old_wearable->removeFromAvatar( TRUE );
07077         }
07078 
07079         // Update the server
07080         sendAgentWearablesUpdate(); 
07081         sendAgentSetAppearance();
07082         gInventory.notifyObservers();
07083 }
07084 
07085 void LLAgent::copyWearableToInventory( EWearableType type )
07086 {
07087         LLWearable* wearable = mWearableEntry[ type ].mWearable;
07088         if( wearable )
07089         {
07090                 // Save the old wearable if it has changed.
07091                 if( wearable->isDirty() )
07092                 {
07093                         wearable = gWearableList.createCopyFromAvatar( wearable );
07094                         mWearableEntry[ type ].mWearable = wearable;
07095                 }
07096 
07097                 // Make a new entry in the inventory.  (Put it in the same folder as the original item if possible.)
07098                 LLUUID category_id;
07099                 LLInventoryItem* item = gInventory.getItem( mWearableEntry[ type ].mItemID );
07100                 if( item )
07101                 {
07102                         category_id = item->getParentUUID();
07103                         wearable->setPermissions(item->getPermissions());
07104                 }
07105                 LLPointer<LLInventoryCallback> cb =
07106                         new addWearableToAgentInventoryCallback(
07107                                 LLPointer<LLRefCount>(NULL),
07108                                 type,
07109                                 wearable);
07110                 addWearableToAgentInventory(cb, wearable, category_id);
07111         }
07112 }
07113 
07114 
07115 // A little struct to let setWearable() communicate more than one value with onSetWearableDialog().
07116 struct LLSetWearableData
07117 {
07118         LLSetWearableData( const LLUUID& new_item_id, LLWearable* new_wearable ) :
07119                 mNewItemID( new_item_id ), mNewWearable( new_wearable ) {}
07120         LLUUID                          mNewItemID;
07121         LLWearable*                     mNewWearable;
07122 };
07123 
07124 BOOL LLAgent::needsReplacement(EWearableType  wearableType, S32 remove)
07125 {
07126         return TRUE;
07127         /*if (remove) return TRUE;
07128         
07129         return getWearable(wearableType) ? TRUE : FALSE;*/
07130 }
07131 
07132 // Assumes existing wearables are not dirty.
07133 void LLAgent::setWearableOutfit( 
07134         const LLInventoryItem::item_array_t& items,
07135         const LLDynamicArray< LLWearable* >& wearables,
07136         BOOL remove )
07137 {
07138         lldebugs << "setWearableOutfit() start" << llendl;
07139 
07140         BOOL wearables_to_remove[WT_COUNT];
07141         wearables_to_remove[WT_SHAPE]           = FALSE;
07142         wearables_to_remove[WT_SKIN]            = FALSE;
07143         wearables_to_remove[WT_HAIR]            = FALSE;
07144         wearables_to_remove[WT_EYES]            = FALSE;
07145         wearables_to_remove[WT_SHIRT]           = remove;
07146         wearables_to_remove[WT_PANTS]           = remove;
07147         wearables_to_remove[WT_SHOES]           = remove;
07148         wearables_to_remove[WT_SOCKS]           = remove;
07149         wearables_to_remove[WT_JACKET]          = remove;
07150         wearables_to_remove[WT_GLOVES]          = remove;
07151         wearables_to_remove[WT_UNDERSHIRT]      = (!gAgent.isTeen()) & remove;
07152         wearables_to_remove[WT_UNDERPANTS]      = (!gAgent.isTeen()) & remove;
07153         wearables_to_remove[WT_SKIRT]           = remove;
07154 
07155         S32 count = wearables.count();
07156         llassert( items.count() == count );
07157 
07158         S32 i;
07159         for( i = 0; i < count; i++ )
07160         {
07161                 LLWearable* new_wearable = wearables[i];
07162                 LLPointer<LLInventoryItem> new_item = items[i];
07163 
07164                 EWearableType type = new_wearable->getType();
07165                 wearables_to_remove[type] = FALSE;
07166 
07167                 LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
07168                 if( old_wearable )
07169                 {
07170                         const LLUUID& old_item_id = mWearableEntry[ type ].mItemID;
07171                         if( (old_wearable->getID() == new_wearable->getID()) &&
07172                                 (old_item_id == new_item->getUUID()) )
07173                         {
07174                                 lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl;
07175                                 continue;
07176                         }
07177 
07178                         gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
07179 
07180                         // Assumes existing wearables are not dirty.
07181                         if( old_wearable->isDirty() )
07182                         {
07183                                 llassert(0);
07184                                 continue;
07185                         }
07186                 }
07187 
07188                 mWearableEntry[ type ].mItemID = new_item->getUUID();
07189                 mWearableEntry[ type ].mWearable = new_wearable;
07190         }
07191 
07192         std::vector<LLWearable*> wearables_being_removed;
07193 
07194         for( i = 0; i < WT_COUNT; i++ )
07195         {
07196                 if( wearables_to_remove[i] )
07197                 {
07198                         wearables_being_removed.push_back(mWearableEntry[ i ].mWearable);
07199                         mWearableEntry[ i ].mWearable = NULL;
07200                         
07201                         gInventory.addChangedMask(LLInventoryObserver::LABEL, mWearableEntry[ i ].mItemID);
07202                         mWearableEntry[ i ].mItemID.setNull();
07203                 }
07204         }
07205 
07206         gInventory.notifyObservers();
07207 
07208         queryWearableCache();
07209 
07210         std::vector<LLWearable*>::iterator wearable_iter;
07211 
07212         for( wearable_iter = wearables_being_removed.begin(); 
07213                 wearable_iter != wearables_being_removed.end();
07214                 ++wearable_iter)
07215         {
07216                 LLWearable* wearablep = *wearable_iter;
07217                 if (wearablep)
07218                 {
07219                         wearablep->removeFromAvatar( TRUE );
07220                 }
07221         }
07222 
07223         for( i = 0; i < count; i++ )
07224         {
07225                 wearables[i]->writeToAvatar( TRUE );
07226         }
07227 
07228         LLFloaterCustomize::setCurrentWearableType( WT_SHAPE );
07229 
07230         // Start rendering & update the server
07231         mWearablesLoaded = TRUE; 
07232         sendAgentWearablesUpdate();
07233         sendAgentSetAppearance();
07234 
07235         lldebugs << "setWearableOutfit() end" << llendl;
07236 }
07237 
07238 
07239 // User has picked "wear on avatar" from a menu.
07240 void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
07241 {
07242         EWearableType type = new_wearable->getType();
07243 
07244         LLWearable* old_wearable = mWearableEntry[ type ].mWearable;
07245         if( old_wearable )
07246         {
07247                 const LLUUID& old_item_id = mWearableEntry[ type ].mItemID;
07248                 if( (old_wearable->getID() == new_wearable->getID()) &&
07249                         (old_item_id == new_item->getUUID()) )
07250                 {
07251                         lldebugs << "No change to wearable asset and item: " << LLWearable::typeToTypeName( type ) << llendl;
07252                         return;
07253                 }
07254 
07255                 if( old_wearable->isDirty() )
07256                 {
07257                         // Bring up modal dialog: Save changes? Yes, No, Cancel
07258                         gViewerWindow->alertXml( "WearableSave", LLAgent::onSetWearableDialog,
07259                                 new LLSetWearableData( new_item->getUUID(), new_wearable ));
07260                         return;
07261                 }
07262         }
07263 
07264         setWearableFinal( new_item, new_wearable );
07265 }
07266 
07267 // static 
07268 void LLAgent::onSetWearableDialog( S32 option, void* userdata )
07269 {
07270         LLSetWearableData* data = (LLSetWearableData*)userdata;
07271         LLInventoryItem* new_item = gInventory.getItem( data->mNewItemID );
07272         if( !new_item )
07273         {
07274                 delete data;
07275                 return;
07276         }
07277 
07278         switch( option )
07279         {
07280         case 0:  // "Save"
07281                 gAgent.saveWearable( data->mNewWearable->getType() );
07282                 gAgent.setWearableFinal( new_item, data->mNewWearable );
07283                 break;
07284 
07285         case 1:  // "Don't Save"
07286                 gAgent.setWearableFinal( new_item, data->mNewWearable );
07287                 break;
07288 
07289         case 2: // "Cancel"
07290                 break;
07291 
07292         default:
07293                 llassert(0);
07294                 break;
07295         }
07296 
07297         delete data;
07298 }
07299 
07300 // Called from setWearable() and onSetWearableDialog() to actually set the wearable.
07301 void LLAgent::setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable )
07302 {
07303         EWearableType type = new_wearable->getType();
07304 
07305         // Replace the old wearable with a new one.
07306         llassert( new_item->getAssetUUID() == new_wearable->getID() );
07307         LLUUID old_item_id = mWearableEntry[ type ].mItemID;
07308         mWearableEntry[ type ].mItemID = new_item->getUUID();
07309         mWearableEntry[ type ].mWearable = new_wearable;
07310 
07311         if (old_item_id.notNull())
07312         {
07313                 gInventory.addChangedMask( LLInventoryObserver::LABEL, old_item_id );
07314                 gInventory.notifyObservers();
07315         }
07316 
07317         //llinfos << "LLVOAvatar::setWearable()" << llendl;
07318         queryWearableCache();
07319         new_wearable->writeToAvatar( TRUE );
07320 
07321         // Update the server
07322         sendAgentWearablesUpdate();
07323         sendAgentSetAppearance();
07324 }
07325 
07326 void LLAgent::queryWearableCache()
07327 {
07328         if (!mWearablesLoaded)
07329         {
07330                 return;
07331         }
07332 
07333         // Look up affected baked textures.
07334         // If they exist:
07335         //              disallow updates for affected layersets (until dataserver responds with cache request.)
07336         //              If cache miss, turn updates back on and invalidate composite.
07337         //              If cache hit, modify baked texture entries.
07338         //
07339         // Cache requests contain list of hashes for each baked texture entry.
07340         // Response is list of valid baked texture assets. (same message)
07341 
07342         gMessageSystem->newMessageFast(_PREHASH_AgentCachedTexture);
07343         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
07344         gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
07345         gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
07346         gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID);
07347 
07348         S32 num_queries = 0;
07349         for (S32 baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++)
07350         {
07351                 LLUUID hash;
07352                 for (S32 wearable_num = 0; wearable_num < MAX_WEARABLES_PER_LAYERSET; wearable_num++)
07353                 {
07354                         EWearableType wearable_type = WEARABLE_BAKE_TEXTURE_MAP[baked_texture_index][wearable_num];
07355                                 
07356                         LLWearable* wearable = getWearable( wearable_type );
07357                         if (wearable)
07358                         {
07359                                 hash ^= wearable->getID();
07360                         }
07361                 }
07362                 if (hash.notNull())
07363                 {
07364                         hash ^= BAKED_TEXTURE_HASH[baked_texture_index];
07365                         num_queries++;
07366                         // *NOTE: make sure at least one request gets packed
07367 
07368                         //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_texture_index << llendl;
07369                         gMessageSystem->nextBlockFast(_PREHASH_WearableData);
07370                         gMessageSystem->addUUIDFast(_PREHASH_ID, hash);
07371                         gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_texture_index);
07372                 }
07373 
07374                 mActiveCacheQueries[ baked_texture_index ] = mTextureCacheQueryID;
07375         }
07376 
07377         llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
07378         gMessageSystem->sendReliable(getRegion()->getHost());
07379         mNumPendingQueries++;
07380         mTextureCacheQueryID++;
07381 }
07382 
07383 // User has picked "remove from avatar" from a menu.
07384 // static
07385 void LLAgent::userRemoveWearable( void* userdata )
07386 {
07387         EWearableType type = (EWearableType)(intptr_t)userdata;
07388         
07389         if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR ) ) //&&
07391         {
07392                 gAgent.removeWearable( type );
07393         }
07394 }
07395 
07396 void LLAgent::userRemoveAllClothes( void* userdata )
07397 {
07398         // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty.
07399         if( gFloaterCustomize )
07400         {
07401                 gFloaterCustomize->askToSaveAllIfDirty( LLAgent::userRemoveAllClothesStep2, NULL );
07402         }
07403         else
07404         {
07405                 LLAgent::userRemoveAllClothesStep2( TRUE, NULL );
07406         }
07407 }
07408 
07409 void LLAgent::userRemoveAllClothesStep2( BOOL proceed, void* userdata )
07410 {
07411         if( proceed )
07412         {
07413                 gAgent.removeWearable( WT_SHIRT );
07414                 gAgent.removeWearable( WT_PANTS );
07415                 gAgent.removeWearable( WT_SHOES );
07416                 gAgent.removeWearable( WT_SOCKS );
07417                 gAgent.removeWearable( WT_JACKET );
07418                 gAgent.removeWearable( WT_GLOVES );
07419                 gAgent.removeWearable( WT_UNDERSHIRT );
07420                 gAgent.removeWearable( WT_UNDERPANTS );
07421                 gAgent.removeWearable( WT_SKIRT );
07422         }
07423 }
07424 
07425 void LLAgent::userRemoveAllAttachments( void* userdata )
07426 {
07427         LLVOAvatar* avatarp = gAgent.getAvatarObject();
07428         if(!avatarp)
07429         {
07430                 llwarns << "No avatar found." << llendl;
07431                 return;
07432         }
07433 
07434         gMessageSystem->newMessage("ObjectDetach");
07435         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
07436         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
07437         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
07438 
07439         for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); 
07440                  iter != avatarp->mAttachmentPoints.end(); )
07441         {
07442                 LLVOAvatar::attachment_map_t::iterator curiter = iter++;
07443                 LLViewerJointAttachment* attachment = curiter->second;
07444                 LLViewerObject* objectp = attachment->getObject();
07445                 if (objectp)
07446                 {
07447                         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
07448                         gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, objectp->getLocalID());
07449                 }
07450         }
07451         gMessageSystem->sendReliable( gAgent.getRegionHost() );
07452 }
07453 
07454 void LLAgent::observeFriends()
07455 {
07456         if(!mFriendObserver)
07457         {
07458                 mFriendObserver = new LLAgentFriendObserver;
07459                 LLAvatarTracker::instance().addObserver(mFriendObserver);
07460                 friendsChanged();
07461         }
07462 }
07463 
07464 void LLAgent::parseTeleportMessages(const LLString& xml_filename)
07465 {
07466         LLXMLNodePtr root;
07467         BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
07468 
07469         if (!success || !root || !root->hasName( "teleport_messages" ))
07470         {
07471                 llerrs << "Problem reading teleport string XML file: " 
07472                            << xml_filename << llendl;
07473                 return;
07474         }
07475 
07476         for (LLXMLNode* message_set = root->getFirstChild();
07477                  message_set != NULL;
07478                  message_set = message_set->getNextSibling())
07479         {
07480                 if ( !message_set->hasName("message_set") ) continue;
07481 
07482                 std::map<LLString, LLString> *teleport_msg_map = NULL;
07483                 LLString message_set_name;
07484 
07485                 if ( message_set->getAttributeString("name", message_set_name) )
07486                 {
07487                         //now we loop over all the string in the set and add them
07488                         //to the appropriate set
07489                         if ( message_set_name == "errors" )
07490                         {
07491                                 teleport_msg_map = &sTeleportErrorMessages;
07492                         }
07493                         else if ( message_set_name == "progress" )
07494                         {
07495                                 teleport_msg_map = &sTeleportProgressMessages;
07496                         }
07497                 }
07498 
07499                 if ( !teleport_msg_map ) continue;
07500 
07501                 LLString message_name;
07502                 for (LLXMLNode* message_node = message_set->getFirstChild();
07503                          message_node != NULL;
07504                          message_node = message_node->getNextSibling())
07505                 {
07506                         if ( message_node->hasName("message") && 
07507                                  message_node->getAttributeString("name", message_name) )
07508                         {
07509                                 (*teleport_msg_map)[message_name] =
07510                                         message_node->getTextContents();
07511                         } //end if ( message exists and has a name)
07512                 } //end for (all message in set)
07513         }//end for (all message sets in xml file)
07514 }
07515 
07516 // EOF

Generated on Fri May 16 08:33:14 2008 for SecondLife by  doxygen 1.5.5