summaryrefslogtreecommitdiff
path: root/indra/newview/llvoavatar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r--indra/newview/llvoavatar.cpp2144
1 files changed, 1248 insertions, 896 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 176f8fb37b..c31714de5a 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1,35 +1,35 @@
/**
* @File llvoavatar.cpp
- * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject
+ * @brief Implementation of LLVOAvatar class which is a derivation of LLViewerObject
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
+#if LL_MSVC
+// disable warning about boost::lexical_cast returning uninitialized data
+// when it fails to parse the string
+#pragma warning (disable:4701)
+#endif
+
#include "llviewerprecompiledheaders.h"
#include "llvoavatar.h"
@@ -37,28 +37,32 @@
#include <stdio.h>
#include <ctype.h>
-#include "audioengine.h"
+#include "llaudioengine.h"
#include "noise.h"
+#include "sound_ids.h"
#include "llagent.h" // Get state values from here
+#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llanimationstates.h"
+#include "llavatarpropertiesprocessor.h"
#include "llviewercontrol.h"
#include "lldrawpoolavatar.h"
#include "lldriverparam.h"
#include "lleditingmotion.h"
#include "llemote.h"
-#include "llfirstuse.h"
+//#include "llfirstuse.h"
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llinventoryview.h"
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
#include "llmutelist.h"
-#include "llnotify.h"
+#include "llmoveview.h"
+#include "llnotificationsutil.h"
#include "llquantize.h"
+#include "llrand.h"
#include "llregionhandle.h"
#include "llresmgr.h"
#include "llselectmgr.h"
@@ -67,7 +71,7 @@
#include "lltexlayer.h"
#include "lltoolmorph.h"
#include "llviewercamera.h"
-#include "llviewerimagelist.h"
+#include "llviewertexturelist.h"
#include "llviewermenu.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
@@ -80,12 +84,24 @@
#include "llsky.h"
#include "llanimstatelabels.h"
#include "lltrans.h"
+#include "llappearancemgr.h"
#include "llgesturemgr.h" //needed to trigger the voice gesticulations
#include "llvoiceclient.h"
#include "llvoicevisualizer.h" // Ventrella
-#include "boost/lexical_cast.hpp"
+#include "lldebugmessagebox.h"
+extern F32 SPEED_ADJUST_MAX;
+extern F32 SPEED_ADJUST_MAX_SEC;
+extern F32 ANIM_SPEED_MAX;
+extern F32 ANIM_SPEED_MIN;
+
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+
+#include <boost/lexical_cast.hpp>
using namespace LLVOAvatarDefines;
@@ -160,7 +176,7 @@ const F32 TIME_BEFORE_MESH_CLEANUP = 5.f; // seconds
const S32 AVATAR_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing memory
const F32 FOOT_GROUND_COLLISION_TOLERANCE = 0.25f;
const F32 AVATAR_LOD_TWEAK_RANGE = 0.7f;
-const S32 MAX_BUBBLE_CHAT_LENGTH = 1023;
+const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN;
const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12;
const F32 CHAT_FADE_TIME = 8.0;
const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f;
@@ -170,8 +186,8 @@ const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0);
enum ERenderName
{
RENDER_NAME_NEVER,
- RENDER_NAME_FADE,
- RENDER_NAME_ALWAYS
+ RENDER_NAME_ALWAYS,
+ RENDER_NAME_FADE
};
//-----------------------------------------------------------------------------
@@ -573,7 +589,7 @@ LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;
LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;
LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL;
S32 LLVOAvatar::sFreezeCounter = 0;
-S32 LLVOAvatar::sMaxVisible = 50;
+U32 LLVOAvatar::sMaxVisible = 12;
F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
@@ -611,7 +627,6 @@ F32 LLVOAvatar::sGreyUpdateTime = 0.f;
// Helper functions
//-----------------------------------------------------------------------------
static F32 calc_bouncy_animation(F32 x);
-static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures);
//-----------------------------------------------------------------------------
// LLVOAvatar()
@@ -634,7 +649,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mWindFreq(0.f),
mRipplePhase( 0.f ),
mBelowWater(FALSE),
- mAppearanceAnimSetByUser(FALSE),
mLastAppearanceBlendTime(0.f),
mAppearanceAnimating(FALSE),
mNameString(),
@@ -644,6 +658,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNameMute(FALSE),
mRenderGroupTitles(sRenderGroupTitles),
mNameAppearance(FALSE),
+ mNameCloud(FALSE),
mFirstTEMessageReceived( FALSE ),
mFirstAppearanceMessageReceived( FALSE ),
mCulled( FALSE ),
@@ -653,8 +668,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mTexEyeColor( NULL ),
mNeedsSkin(FALSE),
mUpdatePeriod(1),
+ mFullyLoaded(FALSE),
+ mPreviousFullyLoaded(FALSE),
mFullyLoadedInitialized(FALSE),
- mSupportsAlphaLayers(FALSE)
+ mSupportsAlphaLayers(FALSE),
+ mLoadedCallbacksPaused(FALSE)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
//VTResume(); // VTune
@@ -676,12 +694,10 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mBakedTextureDatas[i].mIsUsed = false;
mBakedTextureDatas[i].mMaskTexName = 0;
mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i);
- mBakedTextureDatas[i].mMorphMasksValid = FALSE;
}
- mDirtyMesh = TRUE; // Dirty geometry, need to regenerate.
- mShadow0Facep = NULL;
- mShadow1Facep = NULL;
+ mDirtyMesh = 2; // Dirty geometry, need to regenerate.
+ mMeshTexturesDirty = FALSE;
mHeadp = NULL;
mIsBuilt = FALSE;
@@ -717,10 +733,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRippleTimeLast = 0.f;
- mShadowImagep = gImageList.getImageFromFile("foot_shadow.j2c");
- gGL.getTexUnit(0)->bind(mShadowImagep.get());
- mShadowImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
-
mInAir = FALSE;
mStepOnLand = TRUE;
@@ -730,8 +742,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mOohMorph = NULL;
mAahMorph = NULL;
- mCurrentGesticulationLevel = 0;
+ mCurrentGesticulationLevel = 0;
+ mRuthTimer.reset();
+ mRuthDebugTimer.reset();
+ mDebugExistenceTimer.reset();
}
//------------------------------------------------------------------------
@@ -739,12 +754,28 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
//------------------------------------------------------------------------
LLVOAvatar::~LLVOAvatar()
{
- lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
-
- if (isSelf())
+ if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
{
- gAgent.setAvatarObject(NULL);
+ if (!mFullyLoaded)
+ {
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left after " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds as cloud." << llendl;
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezLeftCloudNotification",args);
+ }
+ else
+ {
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left." << llendl;
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezLeftNotification",args);
+ }
+
}
+ lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl;
mRoot.removeAllChildren();
@@ -777,7 +808,8 @@ LLVOAvatar::~LLVOAvatar()
mMeshes.clear();
for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
- jointIter != mMeshLOD.end(); jointIter++)
+ jointIter != mMeshLOD.end();
+ ++jointIter)
{
LLViewerJoint* joint = (LLViewerJoint *) *jointIter;
std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer());
@@ -789,6 +821,7 @@ LLVOAvatar::~LLVOAvatar()
mDead = TRUE;
mAnimationSources.clear();
+ LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
lldebugs << "LLVOAvatar Destructor end" << llendl;
}
@@ -802,6 +835,7 @@ void LLVOAvatar::markDead()
sNumVisibleChatBubbles--;
}
mVoiceVisualizer->markDead();
+ LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;
LLViewerObject::markDead();
}
@@ -814,7 +848,7 @@ BOOL LLVOAvatar::isFullyBaked()
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex)
- && ( (i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ) )
+ && ( (i != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) ) )
{
return FALSE;
}
@@ -871,7 +905,7 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars)
// static
void LLVOAvatar::dumpBakedStatus()
{
- LLVector3d camera_pos_global = gAgent.getCameraPositionGlobal();
+ LLVector3d camera_pos_global = gAgentCamera.getCameraPositionGlobal();
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
@@ -928,7 +962,7 @@ void LLVOAvatar::dumpBakedStatus()
for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- iter++)
+ ++iter)
{
const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second;
const ETextureIndex index = baked_dict->mTextureIndex;
@@ -950,15 +984,14 @@ void LLVOAvatar::dumpBakedStatus()
//static
void LLVOAvatar::restoreGL()
{
- LLVOAvatar* self = gAgent.getAvatarObject();
- if (!self)
- return;
- self->setCompositeUpdatesEnabled(TRUE);
- for (U32 i = 0; i < self->mBakedTextureDatas.size(); i++)
+ if (!isAgentAvatarValid()) return;
+
+ gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
+ for (U32 i = 0; i < gAgentAvatarp->mBakedTextureDatas.size(); i++)
{
- self->invalidateComposite(self->mBakedTextureDatas[i].mTexLayerSet, FALSE);
+ gAgentAvatarp->invalidateComposite(gAgentAvatarp->mBakedTextureDatas[i].mTexLayerSet, FALSE);
}
- self->updateMeshTextures();
+ gAgentAvatarp->updateMeshTextures();
}
//static
@@ -982,7 +1015,7 @@ void LLVOAvatar::resetImpostors()
// static
void LLVOAvatar::deleteCachedImages(bool clearAll)
-{
+{
if (LLTexLayerSet::sHasCaches)
{
lldebugs << "Deleting layer set caches" << llendl;
@@ -1101,6 +1134,17 @@ void LLVOAvatar::initClass()
{
llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl;
}
+
+ gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_HAND_MOTION,"hand_motion");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_HEAD_ROT,"head_rot");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_PELVIS_FIX,"pelvis_fix");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust");
}
@@ -1120,7 +1164,7 @@ void LLVOAvatar::initInstance(void)
for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- iter++)
+ ++iter)
{
const EMeshIndex mesh_index = iter->first;
const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
@@ -1166,7 +1210,7 @@ void LLVOAvatar::initInstance(void)
//-------------------------------------------------------------------------
for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- iter++)
+ ++iter)
{
const EMeshIndex mesh_index = iter->first;
const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
@@ -1175,7 +1219,8 @@ void LLVOAvatar::initInstance(void)
if (baked_texture_index == BAKED_NUM_INDICES) continue;
for (std::vector<LLViewerJointMesh* >::iterator iter = mMeshLOD[mesh_index]->mMeshParts.begin();
- iter != mMeshLOD[mesh_index]->mMeshParts.end(); iter++)
+ iter != mMeshLOD[mesh_index]->mMeshParts.end();
+ ++iter)
{
LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter;
mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh);
@@ -1211,7 +1256,11 @@ void LLVOAvatar::initInstance(void)
registerMotion( ANIM_AGENT_EXPRESS_TOOTHSMILE, LLEmote::create );
registerMotion( ANIM_AGENT_EXPRESS_WINK, LLEmote::create );
registerMotion( ANIM_AGENT_EXPRESS_WORRY, LLEmote::create );
+ registerMotion( ANIM_AGENT_FEMALE_RUN_NEW, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_FEMALE_WALK_NEW, LLKeyframeWalkMotion::create );
registerMotion( ANIM_AGENT_RUN, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_RUN_NEW, LLKeyframeWalkMotion::create );
registerMotion( ANIM_AGENT_STAND, LLKeyframeStandMotion::create );
registerMotion( ANIM_AGENT_STAND_1, LLKeyframeStandMotion::create );
registerMotion( ANIM_AGENT_STAND_2, LLKeyframeStandMotion::create );
@@ -1221,6 +1270,7 @@ void LLVOAvatar::initInstance(void)
registerMotion( ANIM_AGENT_TURNLEFT, LLKeyframeWalkMotion::create );
registerMotion( ANIM_AGENT_TURNRIGHT, LLKeyframeWalkMotion::create );
registerMotion( ANIM_AGENT_WALK, LLKeyframeWalkMotion::create );
+ registerMotion( ANIM_AGENT_WALK_NEW, LLKeyframeWalkMotion::create );
// motions without a start/stop bit
registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create );
@@ -1256,7 +1306,8 @@ void LLVOAvatar::initInstance(void)
//VTPause(); // VTune
- mVoiceVisualizer->setVoiceEnabled( gVoiceClient->getVoiceEnabled( mID ) );
+ mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) );
+
}
const LLVector3 LLVOAvatar::getRenderPosition() const
@@ -1342,27 +1393,32 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax)
continue ;
}
- LLViewerObject* object = attachment->getObject();
- if (object && !object->isHUDAttachment())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
{
- LLSpatialBridge* bridge = drawable->getSpatialBridge();
- if (bridge)
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
{
- const LLVector3* ext = bridge->getSpatialExtents();
- LLVector3 distance = (ext[1] - ext[0]);
-
- // Only add the prim to spatial extents calculations if it isn't a megaprim.
- // max_attachment_span calculated at the start of the function
- // (currently 5 times our max prim size)
- if (distance.mV[0] < max_attachment_span
- && distance.mV[1] < max_attachment_span
- && distance.mV[2] < max_attachment_span)
+ LLSpatialBridge* bridge = drawable->getSpatialBridge();
+ if (bridge)
{
- update_min_max(newMin,newMax,ext[0]);
- update_min_max(newMin,newMax,ext[1]);
+ const LLVector3* ext = bridge->getSpatialExtents();
+ LLVector3 distance = (ext[1] - ext[0]);
+
+ // Only add the prim to spatial extents calculations if it isn't a megaprim.
+ // max_attachment_span calculated at the start of the function
+ // (currently 5 times our max prim size)
+ if (distance.mV[0] < max_attachment_span
+ && distance.mV[1] < max_attachment_span
+ && distance.mV[2] < max_attachment_span)
+ {
+ update_min_max(newMin,newMax,ext[0]);
+ update_min_max(newMin,newMax,ext[1]);
+ }
}
}
}
@@ -1400,7 +1456,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
LLVector3* normal,
LLVector3* bi_normal)
{
- if (isSelf() && !gAgent.needsRenderAvatar() || !LLPipeline::sPickAvatar)
+ if ((isSelf() && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar)
{
return FALSE;
}
@@ -1472,9 +1528,9 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)
//-------------------------------------------------------------------------
// parse the file
//-------------------------------------------------------------------------
- BOOL success = sSkeletonXMLTree.parseFile( filename, FALSE );
+ BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE );
- if (!success)
+ if (!parsesuccess)
{
llerrs << "Can't parse skeleton file: " << filename << llendl;
return FALSE;
@@ -1485,11 +1541,13 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)
if (!root)
{
llerrs << "No root node found in avatar skeleton file: " << filename << llendl;
+ return FALSE;
}
if( !root->hasName( "linden_skeleton" ) )
{
llerrs << "Invalid avatar skeleton file header: " << filename << llendl;
+ return FALSE;
}
std::string version;
@@ -1497,6 +1555,7 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)
if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") )
{
llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl;
+ return FALSE;
}
return TRUE;
@@ -1556,7 +1615,7 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent
// setup children
LLVOAvatarBoneInfo::child_list_t::const_iterator iter;
- for (iter = info->mChildList.begin(); iter != info->mChildList.end(); iter++)
+ for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
{
LLVOAvatarBoneInfo *child_info = *iter;
if (!setupBone(child_info, joint, volume_num, joint_num))
@@ -1599,7 +1658,7 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
S32 current_joint_num = 0;
S32 current_volume_num = 0;
LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
- for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); iter++)
+ for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter)
{
LLVOAvatarBoneInfo *info = *iter;
if (!setupBone(info, NULL, current_volume_num, current_joint_num))
@@ -1612,6 +1671,11 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)
return TRUE;
}
+LLVOAvatar* LLVOAvatar::asAvatar()
+{
+ return this;
+}
+
//-----------------------------------------------------------------------------
// LLVOAvatar::startDefaultMotions()
//-----------------------------------------------------------------------------
@@ -1657,11 +1721,11 @@ void LLVOAvatar::buildCharacter()
// clear mesh data
//-------------------------------------------------------------------------
for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin();
- jointIter != mMeshLOD.end(); jointIter++)
+ jointIter != mMeshLOD.end(); ++jointIter)
{
LLViewerJoint* joint = (LLViewerJoint*) *jointIter;
for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin();
- meshIter != joint->mMeshParts.end(); meshIter++)
+ meshIter != joint->mMeshParts.end(); ++meshIter)
{
LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter;
mesh->setMesh(NULL);
@@ -1806,7 +1870,8 @@ void LLVOAvatar::releaseMeshData()
// cleanup mesh data
for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin();
- iter != mMeshLOD.end(); iter++)
+ iter != mMeshLOD.end();
+ ++iter)
{
LLViewerJoint* joint = (LLViewerJoint*) *iter;
joint->setValid(FALSE, TRUE);
@@ -1825,10 +1890,10 @@ void LLVOAvatar::releaseMeshData()
}
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (!attachment->getIsHUDAttachment())
{
attachment->setAttachmentVisibility(FALSE);
@@ -1851,10 +1916,10 @@ void LLVOAvatar::restoreMeshData()
updateJointLODs();
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (!attachment->getIsHUDAttachment())
{
attachment->setAttachmentVisibility(TRUE);
@@ -1896,7 +1961,7 @@ void LLVOAvatar::updateMeshData()
}
if(num_vertices < 1)//skip empty meshes
{
- break ;
+ continue ;
}
if(last_v_num > 0)//put the last inserted part into next vertex buffer.
{
@@ -1918,6 +1983,8 @@ void LLVOAvatar::updateMeshData()
// resize immediately
facep->setSize(num_vertices, num_indices);
+ bool terse_update = false;
+
if(facep->mVertexBuffer.isNull())
{
facep->mVertexBuffer = new LLVertexBufferAvatar();
@@ -1925,8 +1992,16 @@ void LLVOAvatar::updateMeshData()
}
else
{
+ if (facep->mVertexBuffer->getRequestedIndices() == num_indices &&
+ facep->mVertexBuffer->getRequestedVerts() == num_vertices)
+ {
+ terse_update = true;
+ }
+ else
+ {
facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ;
}
+ }
facep->setGeomIndex(0);
facep->setIndicesIndex(0);
@@ -1940,7 +2015,7 @@ void LLVOAvatar::updateMeshData()
for(S32 k = j ; k < part_index ; k++)
{
- mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR);
+ mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR, terse_update);
}
stop_glerror();
@@ -2000,7 +2075,8 @@ void LLVOAvatar::computeBodySize()
ankle.mV[VZ] * knee_scale.mV[VZ] -
foot.mV[VZ] * ankle_scale.mV[VZ];
- mBodySize.mV[VZ] = mPelvisToFoot +
+ LLVector3 new_body_size;
+ new_body_size.mV[VZ] = mPelvisToFoot +
// the sqrt(2) correction below is an approximate
// correction to get to the top of the head
F_SQRT2 * (skull.mV[VZ] * head_scale.mV[VZ]) +
@@ -2010,8 +2086,19 @@ void LLVOAvatar::computeBodySize()
torso.mV[VZ] * pelvis_scale.mV[VZ];
// TODO -- measure the real depth and width
- mBodySize.mV[VX] = DEFAULT_AGENT_DEPTH;
- mBodySize.mV[VY] = DEFAULT_AGENT_WIDTH;
+ new_body_size.mV[VX] = DEFAULT_AGENT_DEPTH;
+ new_body_size.mV[VY] = DEFAULT_AGENT_WIDTH;
+
+ if (new_body_size != mBodySize)
+ {
+ mBodySize = new_body_size;
+
+ if (isSelf() && !LLAppearanceMgr::instance().isInUpdateAppearanceFromCOF())
+ { // notify simulator of change in size
+ // but not if we are in the middle of updating appearance
+ gAgent.sendAgentSetAppearance();
+ }
+ }
/* debug spam
std::cout << "skull = " << skull << std::endl; // adebug
@@ -2050,12 +2137,27 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys,
LLMemType mt(LLMemType::MTYPE_AVATAR);
LLVector3 old_vel = getVelocity();
+ const BOOL has_name = !getNVPair("FirstName");
+
// Do base class updates...
U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
+ // Print out arrival information once we have name of avatar.
+ if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
+ {
+ if (has_name && getNVPair("FirstName"))
+ {
+ mDebugExistenceTimer.reset();
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezArrivedNotification",args);
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' arrived." << llendl;
+ }
+ }
if(retval & LLViewerObject::INVALID_UPDATE)
{
- if(this == gAgent.getAvatarObject())
+ if (isSelf())
{
//tell sim to cancel this update
gAgent.teleportViaLocation(gAgent.getPositionGlobal());
@@ -2084,24 +2186,56 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid)
}
}
+static LLFastTimer::DeclareTimer FTM_AVATAR_UPDATE("Update Avatar");
+static LLFastTimer::DeclareTimer FTM_JOINT_UPDATE("Update Joints");
+
+//------------------------------------------------------------------------
+// LLVOAvatar::dumpAnimationState()
+//------------------------------------------------------------------------
+void LLVOAvatar::dumpAnimationState()
+{
+ llinfos << "==============================================" << llendl;
+ for (LLVOAvatar::AnimIterator it = mSignaledAnimations.begin(); it != mSignaledAnimations.end(); ++it)
+ {
+ LLUUID id = it->first;
+ std::string playtag = "";
+ if (mPlayingAnimations.find(id) != mPlayingAnimations.end())
+ {
+ playtag = "*";
+ }
+ llinfos << gAnimLibrary.animationName(id) << playtag << llendl;
+ }
+ for (LLVOAvatar::AnimIterator it = mPlayingAnimations.begin(); it != mPlayingAnimations.end(); ++it)
+ {
+ LLUUID id = it->first;
+ bool is_signaled = mSignaledAnimations.find(id) != mSignaledAnimations.end();
+ if (!is_signaled)
+ {
+ llinfos << gAnimLibrary.animationName(id) << "!S" << llendl;
+ }
+ }
+}
+
//------------------------------------------------------------------------
// idleUpdate()
//------------------------------------------------------------------------
BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
{
LLMemType mt(LLMemType::MTYPE_AVATAR);
- LLFastTimer t(LLFastTimer::FTM_AVATAR_UPDATE);
+ LLFastTimer t(FTM_AVATAR_UPDATE);
if (isDead())
{
llinfos << "Warning! Idle on dead avatar" << llendl;
return TRUE;
- }
+ }
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
{
return TRUE;
}
+
+ checkTextureLoading() ;
// force immediate pixel area update on avatars using last frames data (before drawable or camera updates)
setPixelAreaAndAngle(gAgent);
@@ -2109,7 +2243,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// force asynchronous drawable update
if(mDrawable.notNull() && !gNoRender)
{
- LLFastTimer t(LLFastTimer::FTM_JOINT_UPDATE);
+ LLFastTimer t(FTM_JOINT_UPDATE);
if (mIsSitting && getParent())
{
@@ -2163,30 +2297,37 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
// store off last frame's root position to be consistent with camera position
LLVector3 root_pos_last = mRoot.getWorldPosition();
BOOL detailed_update = updateCharacter(agent);
- BOOL voice_enabled = gVoiceClient->getVoiceEnabled( mID ) && gVoiceClient->inProximalChannel();
if (gNoRender)
{
return TRUE;
}
+ static LLUICachedControl<bool> visualizers_in_calls("ShowVoiceVisualizersInCalls", false);
+ bool voice_enabled = (visualizers_in_calls || LLVoiceClient::getInstance()->inProximalChannel()) &&
+ LLVoiceClient::getInstance()->getVoiceEnabled(mID);
+
idleUpdateVoiceVisualizer( voice_enabled );
idleUpdateMisc( detailed_update );
idleUpdateAppearanceAnimation();
- idleUpdateLipSync( voice_enabled );
- idleUpdateLoadingEffect();
- idleUpdateBelowWater(); // wind effect uses this
- idleUpdateWindEffect();
+ if (detailed_update)
+ {
+ idleUpdateLipSync( voice_enabled );
+ idleUpdateLoadingEffect();
+ idleUpdateBelowWater(); // wind effect uses this
+ idleUpdateWindEffect();
+ }
+
idleUpdateNameTag( root_pos_last );
idleUpdateRenderCost();
- idleUpdateTractorBeam();
+
return TRUE;
}
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
{
// disable voice visualizer when in mouselook
- mVoiceVisualizer->setVoiceEnabled( voice_enabled && !(isSelf() && gAgent.cameraMouselook()) );
+ mVoiceVisualizer->setVoiceEnabled( voice_enabled && !(isSelf() && gAgentCamera.cameraMouselook()) );
if ( voice_enabled )
{
//----------------------------------------------------------------
@@ -2214,7 +2355,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
else { llinfos << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << llendl; }
// this is the call that Karl S. created for triggering gestures from within the code.
- gGestureManager.triggerAndReviseString( gestureString );
+ LLGestureMgr::instance().triggerAndReviseString( gestureString );
}
}
@@ -2227,7 +2368,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
// Notice the calls to "gAwayTimer.reset()". This resets the timer that determines how long the avatar has been
// "away", so that the avatar doesn't lapse into away-mode (and slump over) while the user is still talking.
//-----------------------------------------------------------------------------------------------------------------
- if (gVoiceClient->getIsSpeaking( mID ))
+ if (LLVoiceClient::getInstance()->getIsSpeaking( mID ))
{
if (!mVoiceVisualizer->getCurrentlySpeaking())
{
@@ -2236,7 +2377,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
//printf( "gAwayTimer.reset();\n" );
}
- mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) );
+ mVoiceVisualizer->setSpeakingAmplitude( LLVoiceClient::getInstance()->getCurrentPower( mID ) );
if( isSelf() )
{
@@ -2271,6 +2412,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
}//if ( voiceEnabled )
}
+static LLFastTimer::DeclareTimer FTM_ATTACHMENT_UPDATE("Update Attachments");
+
void LLVOAvatar::idleUpdateMisc(bool detailed_update)
{
if (LLVOAvatar::sJointDebug)
@@ -2281,47 +2424,46 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
LLJoint::sNumUpdates = 0;
LLJoint::sNumTouches = 0;
- // *NOTE: this is necessary for the floating name text above your head.
- if (mDrawable.notNull())
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE);
- }
-
BOOL visible = isVisible() || mNeedsAnimUpdate;
// update attachments positions
if (detailed_update || !sUseImpostors)
{
- LLFastTimer t(LLFastTimer::FTM_ATTACHMENT_UPDATE);
+ LLFastTimer t(FTM_ATTACHMENT_UPDATE);
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject *attached_object = attachment->getObject();
+ LLViewerJointAttachment* attachment = iter->second;
- BOOL visibleAttachment = visible || (attached_object &&
- !(attached_object->mDrawable->getSpatialBridge() &&
- attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
-
- if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- // if selecting any attachments, update all of them as non-damped
- if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
- {
- gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
- }
- else
- {
- gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
- }
-
- LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
- if (bridge)
+ LLViewerObject* attached_object = (*attachment_iter);
+ BOOL visibleAttachment = visible || (attached_object &&
+ !(attached_object->mDrawable->getSpatialBridge() &&
+ attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
+
+ if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
{
- gPipeline.updateMoveNormalAsync(bridge);
+ // if selecting any attachments, update all of them as non-damped
+ if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() && LLSelectMgr::getInstance()->getSelection()->isAttachment())
+ {
+ gPipeline.updateMoveNormalAsync(attached_object->mDrawable);
+ }
+ else
+ {
+ gPipeline.updateMoveDampedAsync(attached_object->mDrawable);
+ }
+
+ LLSpatialBridge* bridge = attached_object->mDrawable->getSpatialBridge();
+ if (bridge)
+ {
+ gPipeline.updateMoveNormalAsync(bridge);
+ }
+ attached_object->updateText();
}
- attached_object->updateText();
}
}
}
@@ -2342,7 +2484,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
F32 old_angle = mImpostorAngle.mV[i];
F32 angle_diff = fabsf(cur_angle-old_angle);
- if (angle_diff > 3.14159f/512.f*distance*mUpdatePeriod)
+ if (angle_diff > F_PI/512.f*distance*mUpdatePeriod)
{
mNeedsImpostorUpdate = TRUE;
}
@@ -2392,9 +2534,9 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
param;
param = getNextVisualParam())
{
- if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+ if (param->isTweakable())
{
- param->stopAnimating(mAppearanceAnimSetByUser);
+ param->stopAnimating(FALSE);
}
}
updateVisualParams();
@@ -2405,28 +2547,20 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
}
else
{
- F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
- F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
- F32 morph_amt;
- if (last_blend_frac == 1.f)
- {
- morph_amt = 1.f;
- }
- else
- {
- morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
- }
-
+ F32 morph_amt = calcMorphAmount();
LLVisualParam *param;
- // animate only top level params
- for (param = getFirstVisualParam();
- param;
- param = getNextVisualParam())
+ if (!isSelf())
{
- if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
+ // animate only top level params for non-self avatars
+ for (param = getFirstVisualParam();
+ param;
+ param = getNextVisualParam())
{
- param->animate(morph_amt, mAppearanceAnimSetByUser);
+ if (param->isTweakable())
+ {
+ param->animate(morph_amt, FALSE);
+ }
}
}
@@ -2444,10 +2578,29 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
}
}
+F32 LLVOAvatar::calcMorphAmount()
+{
+ F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32();
+ F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME);
+ F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME);
+
+ F32 morph_amt;
+ if (last_blend_frac == 1.f)
+ {
+ morph_amt = 1.f;
+ }
+ else
+ {
+ morph_amt = (blend_frac - last_blend_frac) / (1.f - last_blend_frac);
+ }
+
+ return morph_amt;
+}
+
void LLVOAvatar::idleUpdateLipSync(bool voice_enabled)
{
// Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync
- if ( voice_enabled && (gVoiceClient->lipSyncEnabled()) && gVoiceClient->getIsSpeaking( mID ) )
+ if ( voice_enabled && (LLVoiceClient::getInstance()->lipSyncEnabled()) && LLVoiceClient::getInstance()->getIsSpeaking( mID ) )
{
F32 ooh_morph_amount = 0.0f;
F32 aah_morph_amount = 0.0f;
@@ -2481,9 +2634,21 @@ void LLVOAvatar::idleUpdateLoadingEffect()
// update visibility when avatar is partially loaded
if (updateIsFullyLoaded()) // changed?
{
+ if (isFullyLoaded() && isSelf())
+ {
+ static bool first_fully_visible = true;
+ if (first_fully_visible)
+ {
+ llinfos << "self isFullyLoaded, first_fully_visible" << llendl;
+
+ first_fully_visible = false;
+ LLAppearanceMgr::instance().onFirstFullyVisible();
+ }
+ }
if (isFullyLoaded())
{
deleteParticleSource();
+ updateLOD();
}
else
{
@@ -2499,11 +2664,11 @@ void LLVOAvatar::idleUpdateLoadingEffect()
particle_parameters.mPartData.mStartColor = LLColor4(1, 1, 1, 0.5f);
particle_parameters.mPartData.mEndColor = LLColor4(1, 1, 1, 0.0f);
particle_parameters.mPartData.mStartScale.mV[VX] = 0.8f;
- LLViewerImage* cloud = gImageList.getImageFromFile("cloud-particle.j2c");
+ LLViewerTexture* cloud = LLViewerTextureManager::getFetchedTextureFromFile("cloud-particle.j2c");
particle_parameters.mPartImageID = cloud->getID();
particle_parameters.mMaxAge = 0.f;
particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE;
- particle_parameters.mInnerAngle = 3.14159f;
+ particle_parameters.mInnerAngle = F_PI;
particle_parameters.mOuterAngle = 0.f;
particle_parameters.mBurstRate = 0.02f;
particle_parameters.mBurstRadius = 0.0f;
@@ -2581,7 +2746,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
{
// update chat bubble
//--------------------------------------------------------------------
- // draw text label over characters head
+ // draw text label over character's head
//--------------------------------------------------------------------
if (mChatTimer.getElapsedTimeF32() > BUBBLE_CHAT_TIME)
{
@@ -2602,8 +2767,9 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
if (isSelf())
{
render_name = render_name
- && !gAgent.cameraMouselook()
- && (visible_chat || !gSavedSettings.getBOOL("RenderNameHideSelf"));
+ && !gAgentCamera.cameraMouselook()
+ && (visible_chat || (gSavedSettings.getBOOL("RenderNameShowSelf")
+ && gSavedSettings.getS32("AvatarNameTagMode") ));
}
if ( render_name )
@@ -2660,7 +2826,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
new_name = TRUE;
}
- LLColor4 avatar_name_color = gSavedSkinSettings.getColor( "AvatarNameColor" );
+ LLColor4 avatar_name_color = LLUIColorTable::instance().getColor( "AvatarNameColor" );
avatar_name_color.setAlpha(alpha);
mNameText->setColor(avatar_name_color);
@@ -2699,17 +2865,33 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
if (mNameText.notNull() && firstname && lastname)
{
- BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end();
- BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
- BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
- BOOL is_muted;
- if (isSelf())
- {
- is_muted = FALSE;
- }
- else
+ const BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end();
+ const BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end();
+ const BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end();
+ const BOOL is_muted = isSelf() ? FALSE : LLMuteList::getInstance()->isMuted(getID());
+ const BOOL is_cloud = getIsCloud();
+
+ if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
{
- is_muted = LLMuteList::getInstance()->isMuted(getID());
+ if (is_appearance != mNameAppearance)
+ {
+ if (is_appearance)
+ {
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args);
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl;
+ }
+ else
+ {
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args);
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl;
+ }
+ }
}
if (mNameString.empty() ||
@@ -2717,7 +2899,9 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
(!title && !mTitle.empty()) ||
(title && mTitle != title->getString()) ||
(is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute)
- || is_appearance != mNameAppearance)
+ || is_appearance != mNameAppearance
+ || is_cloud != mNameCloud
+ )
{
std::string line;
if (!sRenderGroupTitles)
@@ -2771,7 +2955,12 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
line += ")";
}
- if (is_appearance)
+ if (is_cloud)
+ {
+ line += "\n";
+ line += "(" + LLTrans::getString("LoadingData") + ")";
+ }
+ else if (is_appearance)
{
line += "\n";
line += LLTrans::getString("AvatarEditingAppearance");
@@ -2780,6 +2969,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
mNameBusy = is_busy;
mNameMute = is_muted;
mNameAppearance = is_appearance;
+ mNameCloud = is_cloud;
mTitle = title ? title->getString() : "";
LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
mNameString = utf8str_to_wstring(line);
@@ -2802,7 +2992,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
std::deque<LLChat>::iterator chat_iter = mChats.begin();
mNameText->clearString();
- LLColor4 new_chat = gSavedSkinSettings.getColor( "AvatarNameColor" );
+ LLColor4 new_chat = LLUIColorTable::instance().getColor( "AvatarNameColor" );
LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f);
LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f);
if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)
@@ -2864,14 +3054,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
else
{
- if (gSavedSettings.getBOOL("SmallAvatarNames"))
- {
- mNameText->setFont(LLFontGL::getFontSansSerif());
- }
- else
- {
- mNameText->setFont(LLFontGL::getFontSansSerifBig());
- }
+ mNameText->setFont(LLFontGL::getFontSansSerif());
mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_CENTER);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
mNameText->setVisibleOffScreen(FALSE);
@@ -2891,14 +3074,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
}
-//--------------------------------------------------------------------
-// draw tractor beam when editing objects
-//--------------------------------------------------------------------
-// virtual
-void LLVOAvatar::idleUpdateTractorBeam()
-{
-}
-
void LLVOAvatar::idleUpdateBelowWater()
{
F32 avatar_height = (F32)(getPositionGlobal().mdV[VZ]);
@@ -2943,14 +3118,16 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
if (motionp->getName().empty())
{
output = llformat("%s - %d",
- motionp->getID().asString().c_str(),
- (U32)motionp->getPriority());
+ gAgent.isGodlikeWithoutAdminMenuFakery() ?
+ motionp->getID().asString().c_str() :
+ LLUUID::null.asString().c_str(),
+ (U32)motionp->getPriority());
}
else
{
output = llformat("%s - %d",
- motionp->getName().c_str(),
- (U32)motionp->getPriority());
+ motionp->getName().c_str(),
+ (U32)motionp->getPriority());
}
addDebugText(output);
}
@@ -2996,35 +3173,35 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{ // muted avatars update at 16 hz
mUpdatePeriod = 16;
}
- else if (visible && mVisibilityRank <= LLVOAvatar::sMaxVisible * 0.25f)
+ else if (mVisibilityRank <= LLVOAvatar::sMaxVisible)
{ //first 25% of max visible avatars are not impostored
mUpdatePeriod = 1;
}
- else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible * 0.75f)
- { //back 25% of max visible avatars are slow updating impostors
- mUpdatePeriod = 8;
- }
- else if (visible && mVisibilityRank > (U32) LLVOAvatar::sMaxVisible)
+ else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 4)
{ //background avatars are REALLY slow updating impostors
mUpdatePeriod = 16;
}
- else if (visible && mImpostorPixelArea <= impostor_area)
+ else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 3)
+ { //back 25% of max visible avatars are slow updating impostors
+ mUpdatePeriod = 8;
+ }
+ else if (mImpostorPixelArea <= impostor_area)
{ // stuff in between gets an update period based on pixel area
mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8);
}
- else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible * 0.25f)
- { // force nearby impostors in ultra crowded areas
- mUpdatePeriod = 2;
- }
else
- { // not impostored
- mUpdatePeriod = 1;
+ {
+ //nearby avatars, update the impostors more frequently.
+ mUpdatePeriod = 4;
}
visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE;
}
- if (!visible)
+ // don't early out for your own avatar, as we rely on your animations playing reliably
+ // for example, the "turn around" animation when entering customize avatar needs to trigger
+ // even when your avatar is offscreen
+ if (!visible && !isSelf())
{
updateMotions(LLCharacter::HIDDEN_UPDATE);
return FALSE;
@@ -3165,7 +3342,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
}
LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f));
- if (isSelf() && gAgent.cameraMouselook())
+ if (isSelf() && gAgentCamera.cameraMouselook())
{
// make sure fwdDir stays in same general direction as primdir
if (gAgent.getFlying())
@@ -3196,7 +3373,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// When moving very slow, the pelvis is allowed to deviate from the
// forward direction to allow it to hold it's position while the torso
// and head turn. Once in motion, it must conform however.
- BOOL self_in_mouselook = isSelf() && gAgent.cameraMouselook();
+ BOOL self_in_mouselook = isSelf() && gAgentCamera.cameraMouselook();
LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV );
F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, PELVIS_ROT_THRESHOLD_SLOW, PELVIS_ROT_THRESHOLD_FAST);
@@ -3374,7 +3551,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED,
// AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN );
- const F32 STEP_VOLUME = 0.5f;
+ const F32 STEP_VOLUME = 0.1f;
const LLUUID& step_sound_id = getStepSound();
LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent);
@@ -3514,19 +3691,25 @@ void LLVOAvatar::updateVisibility()
/*llinfos << "SPA: " << sel_pos_agent << llendl;
llinfos << "WPA: " << wrist_right_pos_agent << llendl;*/
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getObject())
+ LLViewerJointAttachment* attachment = iter->second;
+
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- if(attachment->getObject()->mDrawable->isVisible())
+ if (LLViewerObject *attached_object = (*attachment_iter))
{
- llinfos << attachment->getName() << " visible" << llendl;
- }
- else
- {
- llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
+ if(attached_object->mDrawable->isVisible())
+ {
+ llinfos << attachment->getName() << " visible" << llendl;
+ }
+ else
+ {
+ llinfos << attachment->getName() << " not visible at " << mDrawable->getWorldPosition() << " and radius " << mDrawable->getRadius() << llendl;
+ }
}
}
}
@@ -3563,6 +3746,16 @@ void LLVOAvatar::updateVisibility()
mVisible = visible;
}
+// private
+bool LLVOAvatar::shouldAlphaMask()
+{
+ const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked
+ && !LLDrawPoolAvatar::sSkipTransparent;
+
+ return should_alpha_mask;
+
+}
+
//-----------------------------------------------------------------------------
// renderSkinned()
//-----------------------------------------------------------------------------
@@ -3575,13 +3768,20 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
return num_indices;
}
- if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
+ LLFace* face = mDrawable->getFace(0);
+
+ bool needs_rebuild = !face || face->mVertexBuffer.isNull() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY);
+
+ if (needs_rebuild || mDirtyMesh)
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
+ if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4)
+ {
updateMeshData();
- mDirtyMesh = FALSE;
+ mDirtyMesh = 0;
mNeedsSkin = TRUE;
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
}
+ }
if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
{
@@ -3591,7 +3791,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry();
mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry();
- if( isWearingWearableType( WT_SKIRT ) )
+ if( isWearingWearableType( LLWearableType::WT_SKIRT ) )
{
mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry();
}
@@ -3696,8 +3896,8 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
if (pass == AVATAR_RENDER_PASS_SINGLE)
{
- const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha; // Don't alpha mask if "Highlight Transparent" checked
+ bool should_alpha_mask = shouldAlphaMask();
LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
if (should_alpha_mask)
@@ -3751,7 +3951,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
U32 LLVOAvatar::renderTransparent(BOOL first_pass)
{
U32 num_indices = 0;
- if( isWearingWearableType( WT_SKIRT ) && (mIsDummy || isTextureVisible(TEX_SKIRT_BAKED)) )
+ if( isWearingWearableType( LLWearableType::WT_SKIRT ) && (mIsDummy || isTextureVisible(TEX_SKIRT_BAKED)) )
{
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f);
num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE);
@@ -3773,7 +3973,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
}
// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)
// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible();
- if (getImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
+ if (getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE || LLDrawPoolAlpha::sShowDebugAlpha)
{
num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass, mIsDummy);
first_pass = FALSE;
@@ -3809,76 +4009,26 @@ U32 LLVOAvatar::renderRigid()
return 0;
}
- if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
- {
- // If the meshes need to be drawn, enable alpha masking but not blending
- bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha;
-
- LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
-
- if (should_alpha_mask)
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
- }
-
- num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
- num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ bool should_alpha_mask = shouldAlphaMask();
+ LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
- }
-
- return num_indices;
-}
-
-U32 LLVOAvatar::renderFootShadows()
-{
- U32 num_indices = 0;
-
- if (!mIsBuilt)
+ if (should_alpha_mask)
{
- return 0;
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
}
- if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
- {
- return 0;
- }
-
- if (!mIsBuilt)
- {
- return 0;
- }
-
- // Don't render foot shadows if your lower body is completely invisible.
- // (non-humanoid avatars rule!)
- if (!isTextureVisible(TEX_LOWER_BAKED))
- {
- return 0;
- }
-
- // Update the shadow, tractor, and text label geometry.
- if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor())
+ if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
{
- updateShadowFaces();
- mDrawable->clearState(LLDrawable::REBUILD_SHADOW);
+ num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
+ num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
}
- U32 foot_mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0;
-
- LLGLDepthTest test(GL_TRUE, GL_FALSE);
- //render foot shadows
- LLGLEnable blend(GL_BLEND);
- gGL.getTexUnit(0)->bind(mShadowImagep.get());
- glColor4fv(mShadow0Facep->getRenderColor().mV);
- mShadow0Facep->renderIndexed(foot_mask);
- glColor4fv(mShadow1Facep->getRenderColor().mV);
- mShadow1Facep->renderIndexed(foot_mask);
+ gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
return num_indices;
}
-U32 LLVOAvatar::renderImpostor(LLColor4U color)
+U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
{
if (!mImpostor.isComplete())
{
@@ -3898,7 +4048,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color)
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
gGL.color4ubv(color.mV);
- gGL.getTexUnit(0)->bind(&mImpostor);
+ gGL.getTexUnit(diffuse_channel)->bind(&mImpostor);
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0,0);
gGL.vertex3fv((pos+left-up).mV);
@@ -3917,7 +4067,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color)
//------------------------------------------------------------------------
// LLVOAvatar::updateTextures()
//------------------------------------------------------------------------
-void LLVOAvatar::updateTextures(LLAgent &agent)
+void LLVOAvatar::updateTextures()
{
BOOL render_avatar = TRUE;
@@ -3932,10 +4082,16 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
}
else
{
- render_avatar = isVisible() && !mCulled;
+ if(!isVisible())
+ {
+ return ;//do not update for invisible avatar.
+ }
+
+ render_avatar = !mCulled; //visible and not culled.
}
std::vector<BOOL> layer_baked;
+ // GL NOT ACTIVE HERE - *TODO
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex));
@@ -3945,7 +4101,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
{
if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded)
{
- gGL.getTexUnit(0)->bind(getImage(mBakedTextureDatas[i].mTextureIndex));
+ gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ));
}
}
}
@@ -3953,18 +4109,34 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
mMaxPixelArea = 0.f;
mMinPixelArea = 99999999.f;
mHasGrey = FALSE; // debug
- for (U32 index = 0; index < getNumTEs(); index++)
+ for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++)
{
- LLViewerImage *imagep = getImage(index);
- if (imagep)
+ LLWearableType::EType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index);
+ U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
+ const LLTextureEntry *te = getTE(texture_index);
+ const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
+ LLViewerFetchedTexture *imagep = NULL;
+ for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++)
+ {
+ imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE);
+ if (imagep)
+ {
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index);
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ if (texture_dict->mIsLocalTexture)
+ {
+ addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
+ }
+ }
+ }
+ if (isIndexBakedTexture((ETextureIndex) texture_index) && render_avatar)
{
- const LLTextureEntry *te = getTE(index);
- const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
const S32 boost_level = getAvatarBakedBoostLevel();
-
+ imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE);
// Spam if this is a baked texture, not set to default image, without valid host info
- if (isIndexBakedTexture((ETextureIndex)index)
+ if (isIndexBakedTexture((ETextureIndex)texture_index)
&& imagep->getID() != IMG_DEFAULT_AVATAR
+ && imagep->getID() != IMG_INVISIBLE
&& !imagep->getTargetHost().isOk())
{
LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
@@ -3973,25 +4145,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
<< " on host " << getRegion()->getHost() << llendl;
}
- /* switch(index)
- case TEX_HEAD_BODYPAINT:
- addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); */
- const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)index);
- if (texture_dict->mIsUsedByBakedTexture)
- {
- const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
- if (texture_dict->mIsLocalTexture)
- {
- addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
- }
- else if (texture_dict->mIsBakedTexture)
- {
- if (layer_baked[baked_index])
- {
- addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
- }
- }
- }
+ addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
}
}
@@ -3999,38 +4153,111 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
{
setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea)));
}
-
- if( render_avatar )
- {
- mShadowImagep->addTextureStats(mPixelArea);
- }
}
-void LLVOAvatar::addLocalTextureStats(ETextureIndex idx, LLViewerImage* imagep,
- F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index)
+void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture* imagep,
+ F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index )
{
// No local texture stats for non-self avatars
return;
}
-
-void LLVOAvatar::addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
+const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames.
+const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = S32_MAX ; //frames
+void LLVOAvatar::checkTextureLoading()
+{
+ static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds
+
+ BOOL pause = !isVisible() ;
+ if(!pause)
+ {
+ mInvisibleTimer.reset() ;
+ }
+ if(mLoadedCallbacksPaused == pause)
+ {
+ return ;
+ }
+
+ if(mCallbackTextureList.empty()) //when is self or no callbacks. Note: this list for self is always empty.
+ {
+ mLoadedCallbacksPaused = pause ;
+ return ; //nothing to check.
+ }
+
+ if(pause && mInvisibleTimer.getElapsedTimeF32() < MAX_INVISIBLE_WAITING_TIME)
+ {
+ return ; //have not been invisible for enough time.
+ }
+
+ for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin();
+ iter != mCallbackTextureList.end(); ++iter)
+ {
+ LLViewerFetchedTexture* tex = gTextureList.findImage(*iter) ;
+ if(tex)
+ {
+ if(pause)//pause texture fetching.
+ {
+ tex->pauseLoadedCallbacks(&mCallbackTextureList) ;
+
+ //set to terminate texture fetching after MAX_TEXTURE_UPDATE_INTERVAL frames.
+ tex->setMaxVirtualSizeResetInterval(MAX_TEXTURE_UPDATE_INTERVAL);
+ tex->resetMaxVirtualSizeResetCounter() ;
+ }
+ else//unpause
+ {
+ static const F32 START_AREA = 100.f ;
+
+ tex->unpauseLoadedCallbacks(&mCallbackTextureList) ;
+ tex->addTextureStats(START_AREA); //jump start the fetching again
+ }
+ }
+ }
+
+ if(!pause)
+ {
+ updateTextures() ; //refresh texture stats.
+ }
+ mLoadedCallbacksPaused = pause ;
+ return ;
+}
+
+const F32 SELF_ADDITIONAL_PRI = 0.75f ;
+const F32 ADDITIONAL_PRI = 0.5f;
+void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
{
+ //Note:
+ //if this function is not called for the last MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL frames,
+ //the texture pipeline will stop fetching this texture.
+
+ imagep->resetTextureStats();
+ imagep->setCanUseHTTP(false) ; //turn off http fetching for baked textures.
+ imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL);
+ imagep->resetMaxVirtualSizeResetCounter() ;
+
mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
- mMinPixelArea = llmin(pixel_area, mMinPixelArea);
+ mMinPixelArea = llmin(pixel_area, mMinPixelArea);
imagep->addTextureStats(pixel_area / texel_area_ratio);
imagep->setBoostLevel(boost_level);
+
+ if(boost_level != LLViewerTexture::BOOST_AVATAR_BAKED_SELF)
+ {
+ imagep->setAdditionalDecodePriority(ADDITIONAL_PRI) ;
+ }
+ else
+ {
+ imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
+ }
}
//virtual
-void LLVOAvatar::setImage(const U8 te, LLViewerImage *imagep)
+void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
{
setTEImage(te, imagep);
}
//virtual
-LLViewerImage* LLVOAvatar::getImage(const U8 te) const
+LLViewerTexture* LLVOAvatar::getImage(const U8 te, const U32 index) const
{
return getTEImage(te);
}
@@ -4243,7 +4470,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
}
else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)
{
- mIsSitting = TRUE;
+ sitDown(TRUE);
}
@@ -4260,7 +4487,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
{
if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)
{
- mIsSitting = FALSE;
+ sitDown(FALSE);
}
stopMotion(anim_id);
result = TRUE;
@@ -4293,34 +4520,79 @@ void LLVOAvatar::resetAnimations()
flushAllMotions();
}
-//-----------------------------------------------------------------------------
-// startMotion()
-// id is the asset if of the animation to start
-// time_offset is the offset into the animation at which to start playing
-//-----------------------------------------------------------------------------
-BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
+// Override selectively based on avatar sex and whether we're using new
+// animations.
+LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
{
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
+ BOOL use_new_walk_run = gSavedSettings.getBOOL("UseNewWalkRun");
+ LLUUID result = id;
+
// start special case female walk for female avatars
if (getSex() == SEX_FEMALE)
{
if (id == ANIM_AGENT_WALK)
{
- return LLCharacter::startMotion(ANIM_AGENT_FEMALE_WALK, time_offset);
+ if (use_new_walk_run)
+ result = ANIM_AGENT_FEMALE_WALK_NEW;
+ else
+ result = ANIM_AGENT_FEMALE_WALK;
+ }
+ else if (id == ANIM_AGENT_RUN)
+ {
+ // There is no old female run animation, so only override
+ // in one case.
+ if (use_new_walk_run)
+ result = ANIM_AGENT_FEMALE_RUN_NEW;
}
else if (id == ANIM_AGENT_SIT)
{
- return LLCharacter::startMotion(ANIM_AGENT_SIT_FEMALE, time_offset);
+ result = ANIM_AGENT_SIT_FEMALE;
}
}
+ else
+ {
+ // Male avatar.
+ if (id == ANIM_AGENT_WALK)
+ {
+ if (use_new_walk_run)
+ result = ANIM_AGENT_WALK_NEW;
+ }
+ else if (id == ANIM_AGENT_RUN)
+ {
+ if (use_new_walk_run)
+ result = ANIM_AGENT_RUN_NEW;
+ }
+
+ }
+
+ return result;
+
+}
+
+//-----------------------------------------------------------------------------
+// startMotion()
+// id is the asset if of the animation to start
+// time_offset is the offset into the animation at which to start playing
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
+{
+ LLMemType mt(LLMemType::MTYPE_AVATAR);
+
+ lldebugs << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << llendl;
+
+ LLUUID remap_id = remapMotionID(id);
+
+ if (remap_id != id)
+ {
+ lldebugs << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << llendl;
+ }
- if (isSelf() && id == ANIM_AGENT_AWAY)
+ if (isSelf() && remap_id == ANIM_AGENT_AWAY)
{
gAgent.setAFK();
}
- return LLCharacter::startMotion(id, time_offset);
+ return LLCharacter::startMotion(remap_id, time_offset);
}
//-----------------------------------------------------------------------------
@@ -4328,21 +4600,21 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
{
- if (isSelf())
- {
- gAgent.onAnimStop(id);
- }
+ lldebugs << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << llendl;
- if (id == ANIM_AGENT_WALK)
+ LLUUID remap_id = remapMotionID(id);
+
+ if (remap_id != id)
{
- LLCharacter::stopMotion(ANIM_AGENT_FEMALE_WALK, stop_immediate);
+ lldebugs << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << llendl;
}
- else if (id == ANIM_AGENT_SIT)
+
+ if (isSelf())
{
- LLCharacter::stopMotion(ANIM_AGENT_SIT_FEMALE, stop_immediate);
+ gAgent.onAnimStop(remap_id);
}
- return LLCharacter::stopMotion(id, stop_immediate);
+ return LLCharacter::stopMotion(remap_id, stop_immediate);
}
//-----------------------------------------------------------------------------
@@ -4611,9 +4883,11 @@ void LLVOAvatar::requestStopMotion( LLMotion* motion )
//-----------------------------------------------------------------------------
// loadAvatar()
//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar");
+
BOOL LLVOAvatar::loadAvatar()
{
-// LLFastTimer t(LLFastTimer::FTM_LOAD_AVATAR);
+// LLFastTimer t(FTM_LOAD_AVATAR);
// avatar_skeleton.xml
if( !buildSkeleton(sAvatarSkeletonInfo) )
@@ -4696,7 +4970,7 @@ BOOL LLVOAvatar::loadAvatar()
// avatar_lad.xml : <morph_masks>
for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
- iter++)
+ ++iter)
{
LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter;
@@ -4720,13 +4994,19 @@ BOOL LLVOAvatar::loadAvatar()
// avatar_lad.xml : <driver_parameters>
for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
iter != sAvatarXmlInfo->mDriverInfoList.end();
- iter++)
+ ++iter)
{
LLDriverParamInfo *info = *iter;
LLDriverParam* driver_param = new LLDriverParam( this );
if (driver_param->setInfo(info))
{
addVisualParam( driver_param );
+ LLVisualParam*(LLVOAvatar::*avatar_function)(S32)const = &LLVOAvatar::getVisualParam;
+ if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatar*)this,_1 ), false))
+ {
+ llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl;
+ continue;
+ }
}
else
{
@@ -4735,6 +5015,19 @@ BOOL LLVOAvatar::loadAvatar()
return FALSE;
}
}
+
+ // Uncomment to enable avatar_lad.xml debugging.
+ std::ofstream file;
+ file.open("avatar_lad.log");
+ for( LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam();
+ param;
+ param = (LLViewerVisualParam*) getNextVisualParam() )
+ {
+ param->getInfo()->toStream(file);
+ file << std::endl;
+ }
+
+ file.close();
return TRUE;
}
@@ -4747,7 +5040,8 @@ BOOL LLVOAvatar::loadSkeletonNode ()
mRoot.addChild( &mSkeleton[0] );
for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin();
- iter != mMeshLOD.end(); iter++)
+ iter != mMeshLOD.end();
+ ++iter)
{
LLViewerJoint *joint = (LLViewerJoint *) *iter;
joint->mUpdateXform = FALSE;
@@ -4783,7 +5077,8 @@ BOOL LLVOAvatar::loadSkeletonNode ()
{
LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
- iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); iter++)
+ iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end();
+ ++iter)
{
LLPolySkeletalDistortionInfo *info = *iter;
LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
@@ -4803,7 +5098,8 @@ BOOL LLVOAvatar::loadSkeletonNode ()
{
LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter;
for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin();
- iter != sAvatarXmlInfo->mAttachmentInfoList.end(); iter++)
+ iter != sAvatarXmlInfo->mAttachmentInfoList.end();
+ ++iter)
{
LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter;
if (!isSelf() && info->mJointName == "mScreen")
@@ -4884,7 +5180,7 @@ BOOL LLVOAvatar::loadMeshNodes()
{
for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end();
- meshinfo_iter++)
+ ++meshinfo_iter)
{
const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter;
const std::string &type = info->mType;
@@ -4900,7 +5196,7 @@ BOOL LLVOAvatar::loadMeshNodes()
mesh = &mHairMesh0; */
for (LLVOAvatarDictionary::Meshes::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- mesh_iter++)
+ ++mesh_iter)
{
const EMeshIndex mesh_index = mesh_iter->first;
const LLVOAvatarDictionary::MeshEntry *mesh_dict = mesh_iter->second;
@@ -4972,7 +5268,7 @@ BOOL LLVOAvatar::loadMeshNodes()
for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
xmlinfo_iter != info->mPolyMorphTargetInfoList.end();
- xmlinfo_iter++)
+ ++xmlinfo_iter)
{
const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
@@ -5006,7 +5302,7 @@ BOOL LLVOAvatar::loadLayersets()
BOOL success = TRUE;
for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin();
layerset_iter != sAvatarXmlInfo->mLayerInfoList.end();
- layerset_iter++)
+ ++layerset_iter)
{
// Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
LLTexLayerSetInfo *layerset_info = *layerset_iter;
@@ -5099,7 +5395,7 @@ BOOL LLVOAvatar::updateJointLODs()
{
if (isSelf())
{
- if(gAgent.cameraCustomizeAvatar() || gAgent.cameraMouselook())
+ if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook())
{
mAdjustedPixelArea = MAX_PIXEL_AREA;
}
@@ -5123,7 +5419,7 @@ BOOL LLVOAvatar::updateJointLODs()
if (res)
{
sNumLODChangesThisFrame++;
- dirtyMesh();
+ dirtyMesh(2);
return TRUE;
}
}
@@ -5147,28 +5443,29 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
mDrawable->addFace(poolp, NULL);
mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR);
- LLFace *facep;
-
- // Add faces for the foot shadows
- facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
- mShadow0Facep = facep;
-
- facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
- mShadow1Facep = facep;
-
mNumInitFaces = mDrawable->getNumFaces() ;
- dirtyMesh();
+ dirtyMesh(2);
return mDrawable;
}
+void LLVOAvatar::updateGL()
+{
+ if (mMeshTexturesDirty)
+ {
+ updateMeshTextures();
+ mMeshTexturesDirty = FALSE;
+ }
+}
+
//-----------------------------------------------------------------------------
// updateGeometry()
//-----------------------------------------------------------------------------
+static LLFastTimer::DeclareTimer FTM_UPDATE_AVATAR("Update Avatar");
BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
{
- LLFastTimer ftm(LLFastTimer::FTM_UPDATE_AVATAR);
+ LLFastTimer ftm(FTM_UPDATE_AVATAR);
if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
{
return TRUE;
@@ -5188,115 +5485,13 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
}
//-----------------------------------------------------------------------------
-// updateShadowFaces()
-//-----------------------------------------------------------------------------
-void LLVOAvatar::updateShadowFaces()
-{
- LLFace *face0p = mShadow0Facep;
- LLFace *face1p = mShadow1Facep;
-
- //
- // render avatar shadows
- //
- if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD)
- {
- face0p->setSize(0, 0);
- face1p->setSize(0, 0);
- return;
- }
-
- LLSprite sprite(mShadowImagep.notNull() ? mShadowImagep->getID() : LLUUID::null);
- sprite.setFollow(FALSE);
- const F32 cos_angle = gSky.getSunDirection().mV[2];
- F32 cos_elev = sqrt(1 - cos_angle * cos_angle);
- if (cos_angle < 0) cos_elev = -cos_elev;
- sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f);
- LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f);
-
- if (mShadowImagep->getHasGLTexture())
- {
- LLVector3 normal;
- LLVector3d shadow_pos;
- LLVector3 shadow_pos_agent;
- F32 foot_height;
-
- if (mFootLeftp)
- {
- LLVector3 joint_world_pos = mFootLeftp->getWorldPosition();
- // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
- // but we make an explicit ray trace call in expectation of future improvements
- resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
- gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
- shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
- foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
-
- // Pull sprite in direction of surface normal
- shadow_pos_agent += normal * SHADOW_OFFSET_AMT;
-
- // Render sprite
- sprite.setNormal(normal);
- if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
- {
- sprite.setColor(0.f, 0.f, 0.f, 0.f);
- }
- else
- {
- sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f));
- }
- sprite.setPosition(shadow_pos_agent);
-
- LLVector3 foot_to_knee = mKneeLeftp->getWorldPosition() - joint_world_pos;
- //foot_to_knee.normalize();
- foot_to_knee -= projected_vec(foot_to_knee, sun_vec);
- sprite.setYaw(azimuth(sun_vec - foot_to_knee));
-
- sprite.updateFace(*face0p);
- }
-
- if (mFootRightp)
- {
- LLVector3 joint_world_pos = mFootRightp->getWorldPosition();
- // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
- // but we make an explicit ray trace call in expectation of future improvements
- resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
- gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
- shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
- foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
-
- // Pull sprite in direction of surface normal
- shadow_pos_agent += normal * SHADOW_OFFSET_AMT;
-
- // Render sprite
- sprite.setNormal(normal);
- if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
- {
- sprite.setColor(0.f, 0.f, 0.f, 0.f);
- }
- else
- {
- sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f));
- }
- sprite.setPosition(shadow_pos_agent);
-
- LLVector3 foot_to_knee = mKneeRightp->getWorldPosition() - joint_world_pos;
- //foot_to_knee.normalize();
- foot_to_knee -= projected_vec(foot_to_knee, sun_vec);
- sprite.setYaw(azimuth(sun_vec - foot_to_knee));
-
- sprite.updateFace(*face1p);
- }
- }
-}
-
-//-----------------------------------------------------------------------------
// updateSexDependentLayerSets()
//-----------------------------------------------------------------------------
-void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user )
+void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
{
- invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, set_by_user );
- updateMeshTextures();
+ invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
}
//-----------------------------------------------------------------------------
@@ -5304,9 +5499,12 @@ void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user )
//-----------------------------------------------------------------------------
void LLVOAvatar::dirtyMesh()
{
- mDirtyMesh = TRUE;
+ dirtyMesh(1);
+}
+void LLVOAvatar::dirtyMesh(S32 priority)
+{
+ mDirtyMesh = llmax(mDirtyMesh, priority);
}
-
//-----------------------------------------------------------------------------
// hideSkirt()
//-----------------------------------------------------------------------------
@@ -5315,26 +5513,32 @@ void LLVOAvatar::hideSkirt()
mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE);
}
-void LLVOAvatar::setParent(LLViewerObject* parent)
+BOOL LLVOAvatar::setParent(LLViewerObject* parent)
{
+ BOOL ret ;
if (parent == NULL)
{
getOffObject();
- LLViewerObject::setParent(parent);
+ ret = LLViewerObject::setParent(parent);
if (isSelf())
{
- gAgent.resetCamera();
+ gAgentCamera.resetCamera();
}
}
else
{
- LLViewerObject::setParent(parent);
- sitOnObject(parent);
+ ret = LLViewerObject::setParent(parent);
+ if(ret)
+ {
+ sitOnObject(parent);
+ }
}
+ return ret ;
}
void LLVOAvatar::addChild(LLViewerObject *childp)
{
+ childp->extractAttachmentItemID(); // find the inventory item this object is associated with.
LLViewerObject::addChild(childp);
if (childp->mDrawable)
{
@@ -5349,18 +5553,30 @@ void LLVOAvatar::addChild(LLViewerObject *childp)
void LLVOAvatar::removeChild(LLViewerObject *childp)
{
LLViewerObject::removeChild(childp);
- detachObject(childp);
+ if (!detachObject(childp))
+ {
+ llwarns << "Calling detach on non-attached object " << llendl;
+ }
}
LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
{
S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState());
+ // This should never happen unless the server didn't process the attachment point
+ // correctly, but putting this check in here to be safe.
+ if (attachmentID & ATTACHMENT_ADD)
+ {
+ llwarns << "Got an attachment with ATTACHMENT_ADD mask, removing ( attach pt:" << attachmentID << " )" << llendl;
+ attachmentID &= ~ATTACHMENT_ADD;
+ }
+
LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
if (!attachment)
{
llwarns << "Object attachment point invalid: " << attachmentID << llendl;
+ attachment = get_if_there(mAttachmentPoints, 1, (LLViewerJointAttachment*)NULL); // Arbitrary using 1 (chest)
}
return attachment;
@@ -5369,7 +5585,7 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
//-----------------------------------------------------------------------------
// attachObject()
//-----------------------------------------------------------------------------
-LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
+const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
{
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
@@ -5388,6 +5604,39 @@ LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
}
//-----------------------------------------------------------------------------
+// attachObject()
+//-----------------------------------------------------------------------------
+U32 LLVOAvatar::getNumAttachments() const
+{
+ U32 num_attachments = 0;
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ const LLViewerJointAttachment *attachment_pt = (*iter).second;
+ num_attachments += attachment_pt->getNumObjects();
+ }
+ return num_attachments;
+}
+
+//-----------------------------------------------------------------------------
+// canAttachMoreObjects()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::canAttachMoreObjects() const
+{
+ return (getNumAttachments() < MAX_AGENT_ATTACHMENTS);
+}
+
+//-----------------------------------------------------------------------------
+// canAttachMoreObjects()
+// Returns true if we can attach <n> more objects.
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::canAttachMoreObjects(U32 n) const
+{
+ return (getNumAttachments() + n) <= MAX_AGENT_ATTACHMENTS;
+}
+
+//-----------------------------------------------------------------------------
// lazyAttach()
//-----------------------------------------------------------------------------
void LLVOAvatar::lazyAttach()
@@ -5412,16 +5661,21 @@ void LLVOAvatar::lazyAttach()
void LLVOAvatar::resetHUDAttachments()
{
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (attachment->getIsHUDAttachment())
{
- LLViewerObject* obj = attachment->getObject();
- if (obj && obj->mDrawable.notNull())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- gPipeline.markMoved(obj->mDrawable);
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && attached_object->mDrawable.notNull())
+ {
+ gPipeline.markMoved(attached_object->mDrawable);
+ }
}
}
}
@@ -5433,55 +5687,57 @@ void LLVOAvatar::resetHUDAttachments()
BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
{
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- // only one object per attachment point for now
- if (attachment->getObject() == viewer_object)
+ LLViewerJointAttachment* attachment = iter->second;
+
+ if (attachment->isObjectAttached(viewer_object))
{
- LLUUID item_id = attachment->getItemID();
attachment->removeObject(viewer_object);
- if (isSelf())
- {
- // the simulator should automatically handle
- // permission revocation
-
- stopMotionFromSource(viewer_object->getID());
- LLFollowCamMgr::setCameraActive(viewer_object->getID(), FALSE);
-
- LLViewerObject::const_child_list_t& child_list = viewer_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child_objectp = *iter;
- // the simulator should automatically handle
- // permissions revocation
-
- stopMotionFromSource(child_objectp->getID());
- LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE);
- }
-
- }
lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
- if (isSelf())
- {
- // Then make sure the inventory is in sync with the avatar.
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
- gInventory.notifyObservers();
- }
return TRUE;
}
}
-
return FALSE;
}
//-----------------------------------------------------------------------------
+// sitDown()
+//-----------------------------------------------------------------------------
+void LLVOAvatar::sitDown(BOOL bSitting)
+{
+ mIsSitting = bSitting;
+ if (isSelf())
+ {
+ // Update Movement Controls according to own Sitting mode
+ LLFloaterMove::setSittingMode(bSitting);
+ }
+}
+
+//-----------------------------------------------------------------------------
// sitOnObject()
//-----------------------------------------------------------------------------
void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
{
+ if (isSelf())
+ {
+ // Might be first sit
+ //LLFirstUse::useSit();
+
+ gAgent.setFlying(FALSE);
+ gAgentCamera.setThirdPersonHeadOffset(LLVector3::zero);
+ //interpolate to new camera position
+ gAgentCamera.startCameraAnimation();
+ // make sure we are not trying to autopilot
+ gAgent.stopAutoPilot();
+ gAgentCamera.setupSitCamera();
+ if (gAgentCamera.getForceMouselook())
+ {
+ gAgentCamera.changeCameraToMouselook();
+ }
+ }
+
if (mDrawable.isNull())
{
return;
@@ -5496,30 +5752,15 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot);
gPipeline.markMoved(mDrawable, TRUE);
- mIsSitting = TRUE;
+ // Notice that removing sitDown() from here causes avatars sitting on
+ // objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655.
+ sitDown(TRUE);
mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject
mRoot.setPosition(getPosition());
mRoot.updateWorldMatrixChildren();
stopMotion(ANIM_AGENT_BODY_NOISE);
- if (isSelf())
- {
- // Might be first sit
- LLFirstUse::useSit();
-
- gAgent.setFlying(FALSE);
- gAgent.setThirdPersonHeadOffset(LLVector3::zero);
- //interpolate to new camera position
- gAgent.startCameraAnimation();
- // make sure we are not trying to autopilot
- gAgent.stopAutoPilot();
- gAgent.setupSitCamera();
- if (gAgent.getForceMouselook())
- {
- gAgent.changeCameraToMouselook();
- }
- }
}
//-----------------------------------------------------------------------------
@@ -5541,7 +5782,7 @@ void LLVOAvatar::getOffObject()
LLViewerObject::const_child_list_t& child_list = sit_object->getChildren();
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ iter != child_list.end(); ++iter)
{
LLViewerObject* child_objectp = *iter;
@@ -5560,7 +5801,8 @@ void LLVOAvatar::getOffObject()
gPipeline.markMoved(mDrawable, TRUE);
- mIsSitting = FALSE;
+ sitDown(FALSE);
+
mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject
mRoot.setPosition(cur_position_world);
mRoot.setRotation(cur_rotation_world);
@@ -5581,9 +5823,9 @@ void LLVOAvatar::getOffObject()
//reset orientation
// mRoot.setRotation(avWorldRot);
- gAgent.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f));
+ gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f));
- gAgent.setSitCamera(LLUUID::null);
+ gAgentCamera.setSitCamera(LLUUID::null);
}
}
@@ -5638,7 +5880,7 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const
}
// virtual
-void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user )
+void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
{
}
@@ -5646,23 +5888,18 @@ void LLVOAvatar::invalidateAll()
{
}
-// virtual
-void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b )
-{
-}
-
-void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL set_by_user )
+void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake )
{
if (global_color == mTexSkinColor)
{
- invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, set_by_user );
+ invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
}
else if (global_color == mTexHairColor)
{
- invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user );
- invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, set_by_user );
+ invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
+ invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, upload_bake );
// ! BACKWARDS COMPATIBILITY !
// Fix for dealing with avatars from viewers that don't bake hair.
@@ -5678,7 +5915,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL
else if (global_color == mTexEyeColor)
{
// llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl;
- invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, set_by_user );
+ invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, upload_bake );
}
updateMeshTextures();
}
@@ -5689,30 +5926,70 @@ BOOL LLVOAvatar::isVisible() const
&& (mDrawable->isVisible() || mIsDummy);
}
-// call periodically to keep isFullyLoaded up to date.
-// returns true if the value has changed.
-BOOL LLVOAvatar::updateIsFullyLoaded()
+// Determine if we have enough avatar data to render
+BOOL LLVOAvatar::getIsCloud()
{
- // a "heuristic" to determine if we have enough avatar data to render
- // (to avoid rendering a "Ruth" - DEV-3168)
- BOOL loading = FALSE;
-
- // do we have a shape?
+ // Do we have a shape?
if (visualParamWeightsAreDefault())
{
- loading = TRUE;
+ return TRUE;
}
if (!isTextureDefined(TEX_LOWER_BAKED) ||
!isTextureDefined(TEX_UPPER_BAKED) ||
!isTextureDefined(TEX_HEAD_BAKED))
{
- loading = TRUE;
+ return TRUE;
}
-
+ return FALSE;
+}
+
+// call periodically to keep isFullyLoaded up to date.
+// returns true if the value has changed.
+BOOL LLVOAvatar::updateIsFullyLoaded()
+{
+ const BOOL loading = getIsCloud();
+ updateRuthTimer(loading);
return processFullyLoadedChange(loading);
}
+void LLVOAvatar::updateRuthTimer(bool loading)
+{
+ if (isSelf() || !loading)
+ {
+ return;
+ }
+
+ if (mPreviousFullyLoaded)
+ {
+ mRuthTimer.reset();
+ if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
+ {
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' became cloud." << llendl;
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezCloudNotification",args);
+ }
+ mRuthDebugTimer.reset();
+ }
+
+ const F32 LOADING_TIMEOUT__SECONDS = 120.f;
+ if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT__SECONDS)
+ {
+ llinfos << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' "
+ << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) "
+ << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) "
+ << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) "
+ << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )."
+ << llendl;
+
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
+ mRuthTimer.reset();
+ }
+}
+
BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
{
// we wait a little bit before giving the all clear,
@@ -5723,7 +6000,19 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE);
-
+ if (gSavedSettings.getBOOL("DebugAvatarRezTime"))
+ {
+ if (!mPreviousFullyLoaded && !loading && mFullyLoaded)
+ {
+ llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' resolved in " << (U32)mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl;
+ LLSD args;
+ args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32());
+ args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32());
+ args["NAME"] = getFullname();
+ LLNotificationsUtil::add("AvatarRezNotification",args);
+ }
+ }
+
// did our loading state "change" from last call?
const S32 UPDATE_RATE = 30;
BOOL changed =
@@ -5767,15 +6056,22 @@ void LLVOAvatar::updateMeshTextures()
// if user has never specified a texture, assign the default
for (U32 i=0; i < getNumTEs(); i++)
{
- const LLViewerImage* te_image = getImage(i);
+ const LLViewerTexture* te_image = getImage(i, 0);
if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT))
{
- setImage(i, gImageList.getImage(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR)); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
+ setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR), 0); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
}
}
- const BOOL self_customizing = isSelf() && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures
+ const BOOL self_customizing = isSelf() && gAgentCamera.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures
const BOOL other_culled = !isSelf() && mCulled;
+ LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ;
+ BOOL paused = FALSE;
+ if(!isSelf())
+ {
+ src_callback_list = &mCallbackTextureList ;
+ paused = mLoadedCallbacksPaused ;
+ }
std::vector<BOOL> is_layer_baked;
is_layer_baked.resize(mBakedTextureDatas.size(), false);
@@ -5792,10 +6088,14 @@ void LLVOAvatar::updateMeshTextures()
// When an avatar is changing clothes and not in Appearance mode,
// use the last-known good baked texture until it finish the first
// render of the new layerset.
+
+ const BOOL layerset_invalid = mBakedTextureDatas[i].mTexLayerSet
+ && ( !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized()
+ || !mBakedTextureDatas[i].mTexLayerSet->isLocalTextureDataAvailable() );
+
use_lkg_baked_layer[i] = (!is_layer_baked[i]
&& (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR)
- && mBakedTextureDatas[i].mTexLayerSet
- && !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized());
+ && layerset_invalid);
if (use_lkg_baked_layer[i])
{
mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE);
@@ -5813,6 +6113,9 @@ void LLVOAvatar::updateMeshTextures()
}
+ // Turn on alpha masking correctly for yourself and other avatars on 1.23+
+ mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR];
+
// Baked textures should be requested from the sim this avatar is on. JC
const LLHost target_host = getObjectHost();
if (!target_host.isOk())
@@ -5824,7 +6127,7 @@ void LLVOAvatar::updateMeshTextures()
{
if (use_lkg_baked_layer[i] && !self_customizing )
{
- LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host );
+ LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host );
mBakedTextureDatas[i].mIsUsed = TRUE;
for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
{
@@ -5833,7 +6136,7 @@ void LLVOAvatar::updateMeshTextures()
}
else if (!self_customizing && is_layer_baked[i])
{
- LLViewerImage* baked_img = getImage( mBakedTextureDatas[i].mTextureIndex );
+ LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex )
{
// Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
@@ -5842,16 +6145,17 @@ void LLVOAvatar::updateMeshTextures()
else
{
mBakedTextureDatas[i].mIsLoaded = FALSE;
- if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
- {
- baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
+ if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
+ {
+ baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ),
+ src_callback_list, paused);
}
- baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
+ baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ),
+ src_callback_list, paused );
}
}
else if (mBakedTextureDatas[i].mTexLayerSet
- && !other_culled
- && (i != BAKED_HAIR || is_layer_baked[i] || isSelf())) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers.
+ && !other_culled)
{
mBakedTextureDatas[i].mTexLayerSet->createComposite();
mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE );
@@ -5862,13 +6166,14 @@ void LLVOAvatar::updateMeshTextures()
}
}
}
-
- // ! BACKWARDS COMPATIBILITY !
- // Workaround for viewing avatars from old viewers that haven't baked hair textures.
+
+ // set texture and color of hair manually if we are not using a baked image.
+ // This can happen while loading hair for yourself, or for clients that did not
+ // bake a hair texture. Still needed for yourself after 1.22 is depricated.
if (!is_layer_baked[BAKED_HAIR] || self_customizing)
{
const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1);
- LLViewerImage* hair_img = getImage( TEX_HAIR );
+ LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 );
for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
{
mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
@@ -5876,23 +6181,24 @@ void LLVOAvatar::updateMeshTextures()
}
}
- // Turn on alpha masking correctly for yourself and other avatars on 1.23+
- mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR];
for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- baked_iter++)
+ ++baked_iter)
{
const EBakedTextureIndex baked_index = baked_iter->first;
const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
local_tex_iter != baked_dict->mLocalTextures.end();
- local_tex_iter++)
+ ++local_tex_iter)
{
const ETextureIndex texture_index = *local_tex_iter;
const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled;
- setLocalTexture(texture_index, getImage(texture_index), is_baked_ready );
+ if (isSelf())
+ {
+ setBakedReady(texture_index, is_baked_ready);
+ }
}
}
removeMissingBakedTextures();
@@ -5902,7 +6208,14 @@ void LLVOAvatar::updateMeshTextures()
//-----------------------------------------------------------------------------
// setLocalTexture()
//-----------------------------------------------------------------------------
-void LLVOAvatar::setLocalTexture(ETextureIndex type, LLViewerImage* tex, BOOL baked_version_exists, U32 index)
+void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, BOOL baked_version_ready, U32 index )
+{
+ // invalid for anyone but self
+ llassert(0);
+}
+
+//virtual
+void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
{
// invalid for anyone but self
llassert(0);
@@ -5947,28 +6260,6 @@ void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* mor
}
}
-// invalidates morph masks for a given layer. Don't pass a parameter to invalidate all morph masks.
-void LLVOAvatar::invalidateMorphMasks(LLVOAvatarDefines::EBakedTextureIndex index)
-{
- setMorphMasksValid(FALSE, index);
-}
-
-// updates morph masks to be a value for a given layer. Don't pass an argument to set value for all morph masks
-void LLVOAvatar::setMorphMasksValid(BOOL new_status, LLVOAvatarDefines::EBakedTextureIndex index)
-{
- if (index == BAKED_NUM_INDICES)
- {
- for (U8 tex = 0; tex < (U8)BAKED_NUM_INDICES; tex++)
- {
- mBakedTextureDatas[tex].mMorphMasksValid = new_status;
- }
- }
- else if (index < BAKED_NUM_INDICES)
- {
- mBakedTextureDatas[index].mMorphMasksValid = new_status;
- }
-}
-
// returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise
BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index)
{
@@ -5977,9 +6268,20 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde
return FALSE;
}
- if (!mBakedTextureDatas[index].mMaskedMorphs.empty() && !mBakedTextureDatas[index].mMorphMasksValid)
+ if (!mBakedTextureDatas[index].mMaskedMorphs.empty())
{
- return TRUE;
+ if (isSelf())
+ {
+ LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet;
+ if (layer_set)
+ {
+ return !layer_set->isMorphValid();
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
}
return FALSE;
@@ -5994,7 +6296,7 @@ void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_com
}
for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin();
- iter != mBakedTextureDatas[index].mMaskedMorphs.end(); iter++)
+ iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter)
{
const LLMaskedMorph* maskedMorph = (*iter);
maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
@@ -6013,9 +6315,9 @@ void LLVOAvatar::releaseComponentTextures()
{
// ! BACKWARDS COMPATIBILITY !
// Detect if the baked hair texture actually wasn't sent, and if so set to default
- if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED)->getID() == getImage(TEX_SKIRT_BAKED)->getID())
+ if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID())
{
- if (getImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE)
+ if (getImage(TEX_HAIR_BAKED,0)->getID() != IMG_INVISIBLE)
{
// Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default
setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR);
@@ -6027,7 +6329,7 @@ void LLVOAvatar::releaseComponentTextures()
const LLVOAvatarDictionary::BakedEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
// skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID
if (!isTextureDefined(bakedDicEntry->mTextureIndex)
- && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ))
+ && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) ))
{
continue;
}
@@ -6040,65 +6342,74 @@ void LLVOAvatar::releaseComponentTextures()
}
}
-BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
+//static
+BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name )
{
switch( te )
{
case TEX_UPPER_SHIRT:
- param_name[0] = "shirt_red";
- param_name[1] = "shirt_green";
- param_name[2] = "shirt_blue";
+ param_name[0] = 803; //"shirt_red";
+ param_name[1] = 804; //"shirt_green";
+ param_name[2] = 805; //"shirt_blue";
break;
case TEX_LOWER_PANTS:
- param_name[0] = "pants_red";
- param_name[1] = "pants_green";
- param_name[2] = "pants_blue";
+ param_name[0] = 806; //"pants_red";
+ param_name[1] = 807; //"pants_green";
+ param_name[2] = 808; //"pants_blue";
break;
case TEX_LOWER_SHOES:
- param_name[0] = "shoes_red";
- param_name[1] = "shoes_green";
- param_name[2] = "shoes_blue";
+ param_name[0] = 812; //"shoes_red";
+ param_name[1] = 813; //"shoes_green";
+ param_name[2] = 817; //"shoes_blue";
break;
case TEX_LOWER_SOCKS:
- param_name[0] = "socks_red";
- param_name[1] = "socks_green";
- param_name[2] = "socks_blue";
+ param_name[0] = 818; //"socks_red";
+ param_name[1] = 819; //"socks_green";
+ param_name[2] = 820; //"socks_blue";
break;
case TEX_UPPER_JACKET:
case TEX_LOWER_JACKET:
- param_name[0] = "jacket_red";
- param_name[1] = "jacket_green";
- param_name[2] = "jacket_blue";
+ param_name[0] = 834; //"jacket_red";
+ param_name[1] = 835; //"jacket_green";
+ param_name[2] = 836; //"jacket_blue";
break;
case TEX_UPPER_GLOVES:
- param_name[0] = "gloves_red";
- param_name[1] = "gloves_green";
- param_name[2] = "gloves_blue";
+ param_name[0] = 827; //"gloves_red";
+ param_name[1] = 829; //"gloves_green";
+ param_name[2] = 830; //"gloves_blue";
break;
case TEX_UPPER_UNDERSHIRT:
- param_name[0] = "undershirt_red";
- param_name[1] = "undershirt_green";
- param_name[2] = "undershirt_blue";
+ param_name[0] = 821; //"undershirt_red";
+ param_name[1] = 822; //"undershirt_green";
+ param_name[2] = 823; //"undershirt_blue";
break;
case TEX_LOWER_UNDERPANTS:
- param_name[0] = "underpants_red";
- param_name[1] = "underpants_green";
- param_name[2] = "underpants_blue";
+ param_name[0] = 824; //"underpants_red";
+ param_name[1] = 825; //"underpants_green";
+ param_name[2] = 826; //"underpants_blue";
break;
case TEX_SKIRT:
- param_name[0] = "skirt_red";
- param_name[1] = "skirt_green";
- param_name[2] = "skirt_blue";
+ param_name[0] = 921; //"skirt_red";
+ param_name[1] = 922; //"skirt_green";
+ param_name[2] = 923; //"skirt_blue";
break;
+ case TEX_HEAD_TATTOO:
+ case TEX_LOWER_TATTOO:
+ case TEX_UPPER_TATTOO:
+ param_name[0] = 1071; //"tattoo_red";
+ param_name[1] = 1072; //"tattoo_green";
+ param_name[2] = 1073; //"tattoo_blue";
+ break;
+
default:
llassert(0);
return FALSE;
@@ -6107,21 +6418,21 @@ BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
return TRUE;
}
-void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user )
+void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
{
- const char* param_name[3];
+ U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
- setVisualParamWeight( param_name[0], new_color.mV[VX], set_by_user );
- setVisualParamWeight( param_name[1], new_color.mV[VY], set_by_user );
- setVisualParamWeight( param_name[2], new_color.mV[VZ], set_by_user );
+ setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
+ setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
+ setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
}
}
LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te )
{
LLColor4 color;
- const char* param_name[3];
+ U32 param_name[3];
if( teToColorParams( te, param_name ) )
{
color.mV[VX] = getVisualParamWeight( param_name[0] );
@@ -6137,18 +6448,16 @@ LLColor4 LLVOAvatar::getDummyColor()
return DUMMY_COLOR;
}
-void LLVOAvatar::dumpAvatarTEs( const std::string& context )
+void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const
{
- /* const char* te_name[] = {
- "TEX_HEAD_BODYPAINT ",
- "TEX_UPPER_SHIRT ", */
llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl;
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
- const LLViewerImage* te_image = getImage(iter->first);
+ // TODO: MULTI-WEARABLE: handle multiple textures for self
+ const LLViewerTexture* te_image = getImage(iter->first,0);
if( !te_image )
{
llinfos << " " << texture_dict->mName << ": null ptr" << llendl;
@@ -6173,45 +6482,31 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context )
}
// Unlike most wearable functions, this works for both self and other.
-BOOL LLVOAvatar::isWearingWearableType(EWearableType type) const
+BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const
{
if (mIsDummy) return TRUE;
switch(type)
{
- case WT_SHAPE:
- case WT_SKIN:
- case WT_HAIR:
- case WT_EYES:
+ case LLWearableType::WT_SHAPE:
+ case LLWearableType::WT_SKIN:
+ case LLWearableType::WT_HAIR:
+ case LLWearableType::WT_EYES:
return TRUE; // everyone has all bodyparts
default:
break; // Do nothing
}
/* switch(type)
- case WT_SHIRT:
+ case LLWearableType::WT_SHIRT:
indicator_te = TEX_UPPER_SHIRT; */
for (LLVOAvatarDictionary::Textures::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- tex_iter++)
+ ++tex_iter)
{
- const LLVOAvatarDefines::ETextureIndex index = tex_iter->first;
const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second;
if (texture_dict->mWearableType == type)
{
- // If you're checking your own clothing, check the component texture
- if (isSelf())
- {
- if (isTextureDefined(index))
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
-
// If you're checking another avatar's clothing, you don't have component textures.
// Thus, you must check to see if the corresponding baked texture is defined.
// NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing
@@ -6238,10 +6533,10 @@ void LLVOAvatar::clampAttachmentPositions()
return;
}
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ LLViewerJointAttachment* attachment = iter->second;
if (attachment)
{
attachment->clampObjectPosition();
@@ -6252,11 +6547,11 @@ void LLVOAvatar::clampAttachmentPositions()
BOOL LLVOAvatar::hasHUDAttachment() const
{
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() && attachment->getObject())
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0)
{
return TRUE;
}
@@ -6268,24 +6563,34 @@ LLBBox LLVOAvatar::getHUDBBox() const
{
LLBBox bbox;
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- if (attachment->getIsHUDAttachment() && attachment->getObject())
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getIsHUDAttachment())
{
- LLViewerObject* hud_object = attachment->getObject();
-
- // initialize bounding box to contain identity orientation and center point for attached object
- bbox.addPointLocal(hud_object->getPosition());
- // add rotated bounding box for attached object
- bbox.addBBoxAgent(hud_object->getBoundingBoxAgent());
- LLViewerObject::const_child_list_t& child_list = hud_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLViewerObject* child_objectp = *iter;
- bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object == NULL)
+ {
+ llwarns << "HUD attached object is NULL!" << llendl;
+ continue;
+ }
+ // initialize bounding box to contain identity orientation and center point for attached object
+ bbox.addPointLocal(attached_object->getPosition());
+ // add rotated bounding box for attached object
+ bbox.addBBoxAgent(attached_object->getBoundingBoxAgent());
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end();
+ ++iter)
+ {
+ const LLViewerObject* child_objectp = *iter;
+ bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
+ }
}
}
}
@@ -6306,6 +6611,14 @@ void LLVOAvatar::onFirstTEMessageReceived()
{
mFirstTEMessageReceived = TRUE;
+ LLLoadedCallbackEntry::source_callback_list_t* src_callback_list = NULL ;
+ BOOL paused = FALSE ;
+ if(!isSelf())
+ {
+ src_callback_list = &mCallbackTextureList ;
+ paused = mLoadedCallbacksPaused ;
+ }
+
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
const BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
@@ -6314,21 +6627,59 @@ void LLVOAvatar::onFirstTEMessageReceived()
// (That is, don't do a transition from unbaked to baked.)
if (layer_baked)
{
- LLViewerImage* image = getImage( mBakedTextureDatas[i].mTextureIndex );
+ LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
mBakedTextureDatas[i].mLastTextureIndex = image->getID();
// If we have more than one texture for the other baked layers, we'll want to call this for them too.
- if ( (i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER) )
+ if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
{
- image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
+ image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ),
+ src_callback_list, paused);
}
- image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
+ image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ),
+ src_callback_list, paused );
}
}
- updateMeshTextures();
+ mMeshTexturesDirty = TRUE;
+ gPipeline.markGLRebuild(this);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// bool visualParamWeightsAreDefault()
+//-----------------------------------------------------------------------------
+bool LLVOAvatar::visualParamWeightsAreDefault()
+{
+ bool rtn = true;
+
+ bool is_wearing_skirt = isWearingWearableType(LLWearableType::WT_SKIRT);
+ for (LLVisualParam *param = getFirstVisualParam();
+ param;
+ param = getNextVisualParam())
+ {
+ if (param->isTweakable())
+ {
+ LLViewerVisualParam* vparam = dynamic_cast<LLViewerVisualParam*>(param);
+ llassert(vparam);
+ bool is_skirt_param = vparam &&
+ LLWearableType::WT_SKIRT == vparam->getWearableType();
+ if (param->getWeight() != param->getDefaultWeight() &&
+ // we have to not care whether skirt weights are default, if we're not actually wearing a skirt
+ (is_wearing_skirt || !is_skirt_param))
+ {
+ //llinfos << "param '" << param->getName() << "'=" << param->getWeight() << " which differs from default=" << param->getDefaultWeight() << llendl;
+ rtn = false;
+ break;
+ }
+ }
}
+
+ //llinfos << "params are default ? " << int(rtn) << llendl;
+
+ return rtn;
}
+
//-----------------------------------------------------------------------------
// processAvatarAppearance()
//-----------------------------------------------------------------------------
@@ -6376,17 +6727,20 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
&& mBakedTextureDatas[baked_index].mLastTextureIndex != IMG_DEFAULT
&& baked_index != BAKED_SKIRT)
{
- setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, gImageList.getImage(mBakedTextureDatas[baked_index].mLastTextureIndex));
+ setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,
+ LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
}
- if( !mFirstTEMessageReceived )
+ if( !is_first_appearance_message )
{
onFirstTEMessageReceived();
}
setCompositeUpdatesEnabled( FALSE );
+ mMeshTexturesDirty = TRUE;
+ gPipeline.markGLRebuild(this);
// ! BACKWARDS COMPATIBILITY !
// Non-self avatars will no longer have component textures
@@ -6394,17 +6748,17 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
{
releaseComponentTextures();
}
-
- updateMeshTextures(); // enables updates for laysets without baked textures.
-
+
// parse visual params
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
- if( num_blocks > 1 )
+ bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
+ if( num_blocks > 1 && !drop_visual_params_debug)
{
BOOL params_changed = FALSE;
BOOL interp_params = FALSE;
LLVisualParam* param = getFirstVisualParam();
+ llassert(param); // if this ever fires, we should do the same as when num_blocks<=1
if (!param)
{
llwarns << "No visual params!" << llendl;
@@ -6413,15 +6767,15 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
{
for( S32 i = 0; i < num_blocks; i++ )
{
- while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) )
+ while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) ) // should not be any of group VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
{
param = getNextVisualParam();
}
if( !param )
{
- llwarns << "Number of params in AvatarAppearance msg does not match number of params in avatar xml file." << llendl;
- return;
+ // more visual params supplied than expected - just process what we know about
+ break;
}
U8 value;
@@ -6446,21 +6800,17 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
}
}
- while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) )
+ const S32 expected_tweakable_count = getVisualParamCountInGroup(VISUAL_PARAM_GROUP_TWEAKABLE); // don't worry about VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT
+ if (num_blocks != expected_tweakable_count)
{
- param = getNextVisualParam();
- }
- if( param )
- {
- llwarns << "Number of params in AvatarAppearance msg does not match number of params in avatar xml file." << llendl;
- return;
+ llinfos << "Number of params in AvatarAppearance msg (" << num_blocks << ") does not match number of tweakable params in avatar xml file (" << expected_tweakable_count << "). Processing what we can. object: " << getID() << llendl;
}
if (params_changed)
{
if (interp_params)
{
- startAppearanceAnimation(FALSE, FALSE);
+ startAppearanceAnimation();
}
updateVisualParams();
@@ -6470,16 +6820,39 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
updateSexDependentLayerSets( FALSE );
}
}
+
+ llassert( getSex() == ((getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE) );
}
else
{
- llwarns << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl;
+ // AvatarAppearance message arrived without visual params
+ if (drop_visual_params_debug)
+ {
+ llinfos << "Debug-faked lack of parameters on AvatarAppearance for object: " << getID() << llendl;
+ }
+ else
+ {
+ llinfos << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl;
+ }
+
+ const F32 LOADING_TIMEOUT_SECONDS = 60.f;
+ // this isn't really a problem if we already have a non-default shape
+ if (visualParamWeightsAreDefault() && mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT_SECONDS)
+ {
+ // re-request appearance, hoping that it comes back with a shape next time
+ llinfos << "Re-requesting AvatarAppearance for object: " << getID() << llendl;
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
+ mRuthTimer.reset();
+ }
+ else
+ {
+ llinfos << "That's okay, we already have a non-default shape for object: " << getID() << llendl;
+ // we don't really care.
+ }
}
setCompositeUpdatesEnabled( TRUE );
- llassert( getSex() == ((getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE) );
-
// If all of the avatars are completely baked, release the global image caches to conserve memory.
LLVOAvatar::cullAvatarsByPixelArea();
@@ -6513,7 +6886,7 @@ void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names )
names->put( "enter_away_from_keyboard_state" );
}
-void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
+void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
{
if (!userdata) return;
@@ -6559,15 +6932,15 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
BOOL found_texture_id = false;
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
if (texture_dict->mIsUsedByBakedTexture)
{
const ETextureIndex texture_index = iter->first;
- const LLViewerImage *baked_img = self->getImage(texture_index);
- if (id == baked_img->getID())
+ const LLViewerTexture *baked_img = self->getImage(texture_index, 0);
+ if (baked_img && id == baked_img->getID())
{
const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index);
@@ -6576,7 +6949,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
{
LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));
}
-
self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;
found_texture_id = true;
break;
@@ -6604,7 +6976,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi,
}
// static
-void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
+void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
{
LLUUID *avatar_idp = (LLUUID *)userdata;
LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp);
@@ -6619,7 +6991,7 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_v
}
}
-void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
+void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
{
//llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl;
@@ -6654,7 +7026,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
mHeadMesh1.setTexture( head_baked ); */
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- LLViewerImage* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex );
+ LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
if (id == image_baked->getID())
{
mBakedTextureDatas[i].mIsLoaded = true;
@@ -6666,14 +7038,14 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
}
if (mBakedTextureDatas[i].mTexLayerSet)
{
- mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
+ //mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
}
const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
local_tex_iter != baked_dict->mLocalTextures.end();
- local_tex_iter++)
+ ++local_tex_iter)
{
- setLocalTexture(*local_tex_iter, getImage(*local_tex_iter), TRUE);
+ if (isSelf()) setBakedReady(*local_tex_iter, TRUE);
}
// ! BACKWARDS COMPATIBILITY !
@@ -6695,8 +7067,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
// static
void LLVOAvatar::dumpArchetypeXML( void* )
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- LLAPRFile outfile ;
+ LLAPRFile outfile;
outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB );
apr_file_t* file = outfile.getFileHandle() ;
if (!file)
@@ -6709,16 +7080,16 @@ void LLVOAvatar::dumpArchetypeXML( void* )
apr_file_printf( file, "\n\t<archetype name=\"???\">\n" );
// only body parts, not clothing.
- for (S32 type = WT_SHAPE; type <= WT_EYES; type++)
+ for (S32 type = LLWearableType::WT_SHAPE; type <= LLWearableType::WT_EYES; type++)
{
- const std::string& wearable_name = LLWearableDictionary::getTypeName((EWearableType)type);
+ const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type);
apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() );
- for (LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam())
+ for (LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->getNextVisualParam())
{
LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
if( (viewer_param->getWearableType() == type) &&
- (viewer_param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) )
+ (viewer_param->isTweakable() ) )
{
apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" value=\"%.3f\"/>\n",
viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight());
@@ -6729,7 +7100,8 @@ void LLVOAvatar::dumpArchetypeXML( void* )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type)
{
- LLViewerImage* te_image = avatar->getImage((ETextureIndex)te);
+ // MULTIPLE_WEARABLES: extend to multiple wearables?
+ LLViewerTexture* te_image = ((LLVOAvatar *)(gAgentAvatarp))->getImage((ETextureIndex)te, 0);
if( te_image )
{
std::string uuid_str;
@@ -6790,7 +7162,7 @@ void LLVOAvatar::cullAvatarsByPixelArea()
std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater());
// Update the avatars that have changed status
- U32 rank = 0;
+ U32 rank = 2; //1 is reserved for self.
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
{
@@ -6814,7 +7186,7 @@ void LLVOAvatar::cullAvatarsByPixelArea()
if (inst->isSelf())
{
- inst->setVisibilityRank(0);
+ inst->setVisibilityRank(1);
}
else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible())
{
@@ -6845,11 +7217,10 @@ void LLVOAvatar::cullAvatarsByPixelArea()
}
}
-void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound)
+void LLVOAvatar::startAppearanceAnimation()
{
if(!mAppearanceAnimating)
{
- mAppearanceAnimSetByUser = set_by_user;
mAppearanceAnimating = TRUE;
mAppearanceMorphTimer.reset();
mLastAppearanceBlendTime = 0.f;
@@ -7406,21 +7777,23 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)
BOOL LLVOAvatar::updateLOD()
{
+ if (isImpostor())
+ {
+ return TRUE;
+ }
+
BOOL res = updateJointLODs();
LLFace* facep = mDrawable->getFace(0);
- if (facep->mVertexBuffer.isNull() ||
- LLVertexBuffer::sEnableVBOs &&
- ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) !=
- (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))
+ if (facep->mVertexBuffer.isNull())
{
- mDirtyMesh = TRUE;
+ dirtyMesh(2);
}
- if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
+ if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
{ //LOD changed or new mesh created, allocate new vertex buffer if needed
updateMeshData();
- mDirtyMesh = FALSE;
+ mDirtyMesh = 0;
mNeedsSkin = TRUE;
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
}
@@ -7497,41 +7870,100 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di
void LLVOAvatar::idleUpdateRenderCost()
{
+ static const U32 ARC_BODY_PART_COST = 20;
+ static const U32 ARC_LIMIT = 2048;
+
+ static std::set<LLUUID> all_textures;
+
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
{
return;
}
- U32 shame = 1;
-
+ U32 cost = 0;
std::set<LLUUID> textures;
+ for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
+ {
+ const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
+ ETextureIndex tex_index = baked_dict->mTextureIndex;
+ if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
+ {
+ if (isTextureVisible(tex_index))
+ {
+ cost +=ARC_BODY_PART_COST;
+ }
+ }
+ }
+
for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
iter != mAttachmentPoints.end();
++iter)
{
LLViewerJointAttachment* attachment = iter->second;
- LLViewerObject* object = attachment->getObject();
- if (object && !object->isHUDAttachment())
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
{
- shame += 10;
- LLVOVolume* volume = drawable->getVOVolume();
- if (volume)
+ const LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
{
- shame += calc_shame(volume, textures);
+ const LLVOVolume* volume = drawable->getVOVolume();
+ if (volume)
+ {
+ cost += volume->getRenderCost(textures);
+ }
}
}
}
- }
+ }
+ // Diagnostic output to identify all avatar-related textures.
+ // Does not affect rendering cost calculation.
+ // Could be wrapped in a debug option if output becomes problematic.
+ if (isSelf())
+ {
+ // print any attachment textures we didn't already know about.
+ for (std::set<LLUUID>::iterator it = textures.begin(); it != textures.end(); ++it)
+ {
+ LLUUID image_id = *it;
+ if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
+ continue;
+ if (all_textures.find(image_id) == all_textures.end())
+ {
+ // attachment texture not previously seen.
+ llinfos << "attachment_texture: " << image_id.asString() << llendl;
+ all_textures.insert(image_id);
+ }
+ }
- shame += textures.size() * 5;
+ // print any avatar textures we didn't already know about
+ for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
+ iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
+ ++iter)
+ {
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
+ // TODO: MULTI-WEARABLE: handle multiple textures for self
+ const LLViewerTexture* te_image = getImage(iter->first,0);
+ if (!te_image)
+ continue;
+ LLUUID image_id = te_image->getID();
+ if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR)
+ continue;
+ if (all_textures.find(image_id) == all_textures.end())
+ {
+ llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl;
+ all_textures.insert(image_id);
+ }
+ }
+ }
+ cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
- setDebugText(llformat("%d", shame));
- F32 green = 1.f-llclamp(((F32) shame-1024.f)/1024.f, 0.f, 1.f);
- F32 red = llmin((F32) shame/1024.f, 1.f);
+ setDebugText(llformat("%d", cost));
+ F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
+ F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
mText->setColor(LLColor4(red,green,0,1));
}
@@ -7555,7 +7987,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const ETextureIndex index = iter->first;
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
@@ -7573,109 +8005,6 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
}
-U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
-{
- if (!volume)
- {
- return 0;
- }
-
- U32 shame = 0;
-
- U32 invisi = 0;
- U32 shiny = 0;
- U32 glow = 0;
- U32 alpha = 0;
- U32 flexi = 0;
- U32 animtex = 0;
- U32 particles = 0;
- U32 scale = 0;
- U32 bump = 0;
- U32 planar = 0;
-
- if (volume->isFlexible())
- {
- flexi = 1;
- }
- if (volume->isParticleSource())
- {
- particles = 1;
- }
-
- const LLVector3& sc = volume->getScale();
- scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
-
- LLDrawable* drawablep = volume->mDrawable;
-
- if (volume->isSculpted())
- {
- LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID sculpt_id = sculpt_params->getSculptTexture();
- textures.insert(sculpt_id);
- }
-
- for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
- {
- LLFace* face = drawablep->getFace(i);
- const LLTextureEntry* te = face->getTextureEntry();
- LLViewerImage* img = face->getTexture();
-
- textures.insert(img->getID());
-
- if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
- {
- alpha++;
- }
- else if (img->getPrimaryFormat() == GL_ALPHA)
- {
- invisi = 1;
- }
-
- if (te)
- {
- if (te->getBumpmap())
- {
- bump = 1;
- }
- if (te->getShiny())
- {
- shiny = 1;
- }
- if (te->getGlow() > 0.f)
- {
- glow = 1;
- }
- if (face->mTextureMatrix != NULL)
- {
- animtex++;
- }
- if (te->getTexGen())
- {
- planar++;
- }
- }
- }
-
- shame += invisi + shiny + glow + alpha*4 + flexi*8 + animtex*4 + particles*16+bump*4+scale+planar;
-
- LLViewerObject::const_child_list_t& child_list = volume->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); iter++)
- {
- LLViewerObject* child_objectp = *iter;
- LLDrawable* child_drawablep = child_objectp->mDrawable;
- if (child_drawablep)
- {
- LLVOVolume* child_volumep = child_drawablep->getVOVolume();
- if (child_volumep)
- {
- shame += calc_shame(child_volumep, textures);
- }
- }
- }
-
- return shame;
-}
//virtual
S32 LLVOAvatar::getTexImageSize() const
@@ -7700,7 +8029,30 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index
return FALSE;
}
- return (getImage(te)->getID() != IMG_DEFAULT_AVATAR &&
- getImage(te)->getID() != IMG_DEFAULT);
+ return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR &&
+ getImage(te, index)->getID() != IMG_DEFAULT);
+}
+
+//virtual
+BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index) const
+{
+ if (isIndexLocalTexture(type))
+ {
+ return isTextureDefined(type, index);
+ }
+ else
+ {
+ // baked textures can use TE images directly
+ return ((isTextureDefined(type) || isSelf())
+ && (getTEImage(type)->getID() != IMG_INVISIBLE
+ || LLDrawPoolAlpha::sShowDebugAlpha));
+ }
+}
+
+//virtual
+BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const
+{
+ // non-self avatars don't have wearables
+ return FALSE;
}