diff options
Diffstat (limited to 'indra/newview')
36 files changed, 2579 insertions, 3322 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9ec54f1851..76be212c95 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -203,7 +203,6 @@ set(viewer_SOURCE_FILES llfollowcam.cpp llframestats.cpp llframestatview.cpp - llgenepool.cpp llgesturemgr.cpp llgivemoney.cpp llglsandbox.cpp @@ -406,6 +405,7 @@ set(viewer_SOURCE_FILES llvlcomposition.cpp llvlmanager.cpp llvoavatar.cpp + llvoavatardefines.cpp llvocache.cpp llvoclouds.cpp llvograss.cpp @@ -605,7 +605,6 @@ set(viewer_HEADER_FILES llfollowcam.h llframestats.h llframestatview.h - llgenepool.h llgesturemgr.h llgivemoney.h llgroupmgr.h @@ -810,6 +809,7 @@ set(viewer_HEADER_FILES llvlcomposition.h llvlmanager.h llvoavatar.h + llvoavatardefines.h llvocache.h llvoclouds.h llvograss.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e964799e4c..993033aa2c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -561,17 +561,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>AvatarCompositeLimit</key> - <map> - <key>Comment</key> - <string>Maximum number of avatars to display appearance changes on the fly</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>S32</string> - <key>Value</key> - <integer>5</integer> - </map> <key>AvatarFeathering</key> <map> <key>Comment</key> @@ -6152,6 +6141,17 @@ <key>Value</key> <integer>35</integer> </map> + <key>RenderAvatarInvisible</key> + <map> + <key>Comment</key> + <string>Set your avatar as Invisible</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderAvatarVP</key> <map> <key>Comment</key> @@ -9922,6 +9922,17 @@ <key>Value</key> <string>c80260ba-41fd-8a46-768a-6bf236360e3a</string> </map> + <key>UploadBakedTexOld</key> + <map> + <key>Comment</key> + <string>Forces the baked texture pipeline to upload using the old method.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>UseAltKeyForMenus</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 569de267e7..d4978566da 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -133,6 +133,8 @@ #include "llviewerjoystick.h" #include "llfollowcam.h" +using namespace LLVOAvatarDefines; + extern LLMenuBarGL* gMenuBarView; //drone wandering constants @@ -207,26 +209,6 @@ const F32 MIN_RADIUS_ALPHA_SIZZLE = 0.5f; const F64 CHAT_AGE_FAST_RATE = 3.0; -const S32 MAX_WEARABLES_PER_LAYERSET = 7; - -const EWearableType WEARABLE_BAKE_TEXTURE_MAP[BAKED_TEXTURE_COUNT][MAX_WEARABLES_PER_LAYERSET] = -{ - { WT_SHAPE, WT_SKIN, WT_HAIR, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID }, // TEX_HEAD_BAKED - { WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_INVALID }, // TEX_UPPER_BAKED - { WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS }, // TEX_LOWER_BAKED - { WT_EYES, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID }, // TEX_EYES_BAKED - { WT_SKIRT, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID, WT_INVALID } // TEX_SKIRT_BAKED -}; - -const LLUUID BAKED_TEXTURE_HASH[BAKED_TEXTURE_COUNT] = -{ - LLUUID("18ded8d6-bcfc-e415-8539-944c0f5ea7a6"), - LLUUID("338c29e3-3024-4dbb-998d-7c04cf4fa88f"), - LLUUID("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f"), - LLUUID("b2cf28af-b840-1071-3c6a-78085d8128b5"), - LLUUID("ea800387-ea1a-14e0-56cb-24f2022f969a") -}; - // The agent instance. LLAgent gAgent; @@ -424,8 +406,8 @@ LLAgent::LLAgent() : mControlsTakenPassedOnCount[i] = 0; } - mActiveCacheQueries = new S32[BAKED_TEXTURE_COUNT]; - for (i = 0; i < (U32)BAKED_TEXTURE_COUNT; i++) + mActiveCacheQueries = new S32[BAKED_NUM_INDICES]; + for (i = 0; i < (U32)BAKED_NUM_INDICES; i++) { mActiveCacheQueries[i] = 0; } @@ -5756,11 +5738,11 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * mesgsys->getU8Fast(_PREHASH_WearableData, _PREHASH_TextureIndex, texture_index, texture_block); if (texture_id.notNull() - && (S32)texture_index < BAKED_TEXTURE_COUNT + && (S32)texture_index < BAKED_NUM_INDICES && gAgent.mActiveCacheQueries[ texture_index ] == query_id) { //llinfos << "Received cached texture " << (U32)texture_index << ": " << texture_id << llendl; - avatarp->setCachedBakedTexture((LLVOAvatar::ETextureIndex)LLVOAvatar::sBakedTextureIndices[texture_index], texture_id); + avatarp->setCachedBakedTexture(getTextureIndex((EBakedTextureIndex)texture_index), texture_id); //avatarp->setTETexture( LLVOAvatar::sBakedTextureIndices[texture_index], texture_id ); gAgent.mActiveCacheQueries[ texture_index ] = 0; num_results++; @@ -7053,11 +7035,8 @@ void LLAgent::sendAgentSetAppearance() return; } - llinfos << "TAT: Sent AgentSetAppearance: " << - (( mAvatarObject->getTEImage( LLVOAvatar::TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "HEAD " : "head " ) << - (( mAvatarObject->getTEImage( LLVOAvatar::TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "UPPER " : "upper " ) << - (( mAvatarObject->getTEImage( LLVOAvatar::TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "LOWER " : "lower " ) << - (( mAvatarObject->getTEImage( LLVOAvatar::TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "EYES" : "eyes" ) << llendl; + + llinfos << "TAT: Sent AgentSetAppearance: " << mAvatarObject->getBakedStatusForPrintout() << llendl; //dumpAvatarTEs( "sendAgentSetAppearance()" ); LLMessageSystem* msg = gMessageSystem; @@ -7071,7 +7050,7 @@ void LLAgent::sendAgentSetAppearance() // NOTE -- when we start correcting all of the other Havok geometry // to compensate for the COLLISION_TOLERANCE ugliness we will have // to tweak this number again - LLVector3 body_size = mAvatarObject->mBodySize; + const LLVector3 body_size = mAvatarObject->mBodySize; msg->addVector3Fast(_PREHASH_Size, body_size); // To guard against out of order packets @@ -7083,19 +7062,18 @@ void LLAgent::sendAgentSetAppearance() // KLW - TAT this will probably need to check the local queue. BOOL textures_current = !mAvatarObject->hasPendingBakedUploads() && mWearablesLoaded; - S32 baked_texture_index; - for( baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++ ) + for(U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) { - S32 tex_index = LLVOAvatar::sBakedTextureIndices[baked_texture_index]; + const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index); // if we're not wearing a skirt, we don't need the texture to be baked - if (tex_index == LLVOAvatar::TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT)) + if (texture_index == TEX_SKIRT_BAKED && !mAvatarObject->isWearingWearableType(WT_SKIRT)) { continue; } // IMG_DEFAULT_AVATAR means not baked - if (mAvatarObject->getTEImage( tex_index)->getID() == IMG_DEFAULT_AVATAR) + if (!mAvatarObject->isTextureDefined(texture_index)) { textures_current = FALSE; break; @@ -7106,50 +7084,56 @@ void LLAgent::sendAgentSetAppearance() if (textures_current) { llinfos << "TAT: Sending cached texture data" << llendl; - for (baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++) + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { + const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index); LLUUID hash; - - for( S32 wearable_num = 0; wearable_num < MAX_WEARABLES_PER_LAYERSET; wearable_num++ ) + for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++) { - EWearableType wearable_type = WEARABLE_BAKE_TEXTURE_MAP[baked_texture_index][wearable_num]; - - LLWearable* wearable = getWearable( wearable_type ); + // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num]; + const EWearableType wearable_type = wearable_dict->mWearablesVec[i]; + const LLWearable* wearable = getWearable(wearable_type); if (wearable) { hash ^= wearable->getID(); } } - if (hash.notNull()) { - hash ^= BAKED_TEXTURE_HASH[baked_texture_index]; + hash ^= wearable_dict->mHashID; } - S32 tex_index = LLVOAvatar::sBakedTextureIndices[baked_texture_index]; + const ETextureIndex texture_index = getTextureIndex((EBakedTextureIndex)baked_index); msg->nextBlockFast(_PREHASH_WearableData); msg->addUUIDFast(_PREHASH_CacheID, hash); - msg->addU8Fast(_PREHASH_TextureIndex, (U8)tex_index); + msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index); } + msg->nextBlockFast(_PREHASH_ObjectData); + mAvatarObject->packTEMessage( gMessageSystem ); + } + else + { + // If the textures aren't baked, send NULL for texture IDs + // This means the baked texture IDs on the server will be untouched. + // Once all textures are baked, another AvatarAppearance message will be sent to update the TEs + msg->nextBlockFast(_PREHASH_ObjectData); + gMessageSystem->addBinaryDataFast(_PREHASH_TextureEntry, NULL, 0); } - msg->nextBlockFast(_PREHASH_ObjectData); - mAvatarObject->packTEMessage( gMessageSystem ); S32 transmitted_params = 0; for (LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarObject->getFirstVisualParam(); param; param = (LLViewerVisualParam*)mAvatarObject->getNextVisualParam()) { - F32 param_value = param->getWeight(); - if (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) { msg->nextBlockFast(_PREHASH_VisualParam ); // We don't send the param ids. Instead, we assume that the receiver has the same params in the same sequence. - U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight()); + const F32 param_value = param->getWeight(); + const U8 new_weight = F32_to_U8(param_value, param->getMinWeight(), param->getMaxWeight()); msg->addU8Fast(_PREHASH_ParamValue, new_weight ); transmitted_params++; } @@ -7388,8 +7372,6 @@ void LLAgent::setWearableOutfit( wearables[i]->writeToAvatar( TRUE ); } - LLFloaterCustomize::setCurrentWearableType( WT_SHAPE ); - // Start rendering & update the server mWearablesLoaded = TRUE; sendAgentWearablesUpdate(); @@ -7511,14 +7493,15 @@ void LLAgent::queryWearableCache() gMessageSystem->addS32Fast(_PREHASH_SerialNum, mTextureCacheQueryID); S32 num_queries = 0; - for (S32 baked_texture_index = 0; baked_texture_index < BAKED_TEXTURE_COUNT; baked_texture_index++) + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++ ) { + const LLVOAvatarDictionary::WearableDictionaryEntry *wearable_dict = LLVOAvatarDictionary::getInstance()->getWearable((EBakedTextureIndex)baked_index); LLUUID hash; - for (S32 wearable_num = 0; wearable_num < MAX_WEARABLES_PER_LAYERSET; wearable_num++) + for (U8 i=0; i < wearable_dict->mWearablesVec.size(); i++) { - EWearableType wearable_type = WEARABLE_BAKE_TEXTURE_MAP[baked_texture_index][wearable_num]; - - LLWearable* wearable = getWearable( wearable_type ); + // EWearableType wearable_type = gBakedWearableMap[baked_index][wearable_num]; + const EWearableType wearable_type = wearable_dict->mWearablesVec[i]; + const LLWearable* wearable = getWearable(wearable_type); if (wearable) { hash ^= wearable->getID(); @@ -7526,17 +7509,17 @@ void LLAgent::queryWearableCache() } if (hash.notNull()) { - hash ^= BAKED_TEXTURE_HASH[baked_texture_index]; + hash ^= wearable_dict->mHashID; num_queries++; // *NOTE: make sure at least one request gets packed - //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_texture_index << llendl; + //llinfos << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << llendl; gMessageSystem->nextBlockFast(_PREHASH_WearableData); gMessageSystem->addUUIDFast(_PREHASH_ID, hash); - gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_texture_index); + gMessageSystem->addU8Fast(_PREHASH_TextureIndex, (U8)baked_index); } - mActiveCacheQueries[ baked_texture_index ] = mTextureCacheQueryID; + mActiveCacheQueries[ baked_index ] = mTextureCacheQueryID; } llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl; @@ -7563,7 +7546,7 @@ void LLAgent::userRemoveAllClothes( void* userdata ) // We have to do this up front to avoid having to deal with the case of multiple wearables being dirty. if( gFloaterCustomize ) { - gFloaterCustomize->askToSaveAllIfDirty( LLAgent::userRemoveAllClothesStep2, NULL ); + gFloaterCustomize->askToSaveIfDirty( LLAgent::userRemoveAllClothesStep2, NULL ); } else { diff --git a/indra/newview/llappearance.h b/indra/newview/llappearance.h index 949b9e59fc..9018150146 100644 --- a/indra/newview/llappearance.h +++ b/indra/newview/llappearance.h @@ -44,14 +44,14 @@ public: void addParam( S32 id, F32 value ) { mParamMap[id] = value; } F32 getParam( S32 id, F32 defval ) { return get_if_there(mParamMap, id, defval ); } - void addTexture( S32 te, const LLUUID& uuid ) { if( te < LLVOAvatar::TEX_NUM_ENTRIES ) mTextures[te] = uuid; } - const LLUUID& getTexture( S32 te ) { return ( te < LLVOAvatar::TEX_NUM_ENTRIES ) ? mTextures[te] : LLUUID::null; } + void addTexture( S32 te, const LLUUID& uuid ) { if( te < LLVOAvatarDefines::TEX_NUM_INDICES ) mTextures[te] = uuid; } + const LLUUID& getTexture( S32 te ) { return ( te < LLVOAvatarDefines::TEX_NUM_INDICES ) ? mTextures[te] : LLUUID::null; } - void clear() { mParamMap.clear(); for( S32 i=0; i<LLVOAvatar::TEX_NUM_ENTRIES; i++ ) mTextures[i].setNull(); } + void clear() { mParamMap.clear(); for( S32 i=0; i<LLVOAvatarDefines::TEX_NUM_INDICES; i++ ) mTextures[i].setNull(); } typedef std::map<S32, F32> param_map_t; param_map_t mParamMap; - LLUUID mTextures[LLVOAvatar::TEX_NUM_ENTRIES]; + LLUUID mTextures[LLVOAvatarDefines::TEX_NUM_INDICES]; }; #endif // LL_LLAPPEARANCE_H diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 9dd0668787..481a6ceb26 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -56,6 +56,7 @@ #include "llviewerobjectlist.h" #include "llviewermenufile.h" #include "llviewerwindow.h" +#include "lltexlayer.h" // When uploading multiple files, don't display any of them when uploading more than this number. static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5; @@ -139,6 +140,7 @@ void LLAssetUploadResponder::result(const LLSD& content) if (mFileName.empty()) { // rename the file in the VFS to the actual asset id + // llinfos << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << llendl; gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType); } uploadComplete(content); @@ -332,6 +334,48 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) } } +LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type, + LLBakedUploadData * baked_upload_data) + : LLAssetUploadResponder(post_data, vfile_id, asset_type), + mBakedUploadData(baked_upload_data) +{ +} + +LLSendTexLayerResponder::~LLSendTexLayerResponder() +{ + // mBakedUploadData is normally deleted by calls to LLTexLayerSetBuffer::onTextureUploadComplete() below + if (mBakedUploadData) + { // ...but delete it in the case where uploadComplete() is never called + delete mBakedUploadData; + mBakedUploadData = NULL; + } +} + + +// Baked texture upload completed +void LLSendTexLayerResponder::uploadComplete(const LLSD& content) +{ + LLUUID item_id = mPostData["item_id"]; + + std::string result = content["state"]; + LLUUID new_id = content["new_asset"]; + + llinfos << "LLSendTexLayerResponder::result from capabilities: " << result << llendl; + if (result == "complete" + && mBakedUploadData != NULL) + { // Invoke + LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, 0, LL_EXSTAT_NONE); + mBakedUploadData = NULL; // deleted in onTextureUploadComplete() + } + else + { // Invoke the original callback with an error result + LLTexLayerSetBuffer::onTextureUploadComplete(new_id, (void*) mBakedUploadData, -1, LL_EXSTAT_NONE); + mBakedUploadData = NULL; // deleted in onTextureUploadComplete() + } +} + LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, const LLUUID& vfile_id, diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 42b3a9d27d..9ab571ae99 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -71,6 +71,22 @@ public: virtual void uploadComplete(const LLSD& content); }; +class LLBakedUploadData; +class LLSendTexLayerResponder : public LLAssetUploadResponder +{ +public: + LLSendTexLayerResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type, + LLBakedUploadData * baked_upload_data); + + ~LLSendTexLayerResponder(); + + virtual void uploadComplete(const LLSD& content); + + LLBakedUploadData * mBakedUploadData; +}; + class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder { public: diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 9db9197500..0de21f03f2 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -758,7 +758,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->renderCollisionVolumes(); } - if (avatarp->mIsSelf && LLAgent::sDebugDisplayTarget) + if (avatarp->isSelf() && LLAgent::sDebugDisplayTarget) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); LLVector3 pos = avatarp->getPositionAgent(); diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 0dc95ff536..1e2630e1fb 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -114,7 +114,12 @@ public: static BOOL sSkipTransparent; }; - +class LLVertexBufferAvatar : public LLVertexBuffer +{ +public: + LLVertexBufferAvatar(); + virtual void setupVertexBuffer(U32 data_mask) const; +}; extern S32 AVATAR_OFFSET_POS; extern S32 AVATAR_OFFSET_NORMAL; diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 747b685b5e..162456b8ce 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -1041,7 +1041,7 @@ LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture mDummyAvatar->updateJointLODs(); mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); mDummyAvatar->startMotion(ANIM_AGENT_STAND, BASE_ANIM_TIME_OFFSET); - mDummyAvatar->mSkirtLOD.setVisible(FALSE, TRUE); + mDummyAvatar->hideSkirt(); gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance()); // stop extraneous animations diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 6ff34fbfb9..e81b5d7fce 100644 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -40,6 +40,8 @@ #include "llviewerobjectlist.h" #include "llvoavatar.h" +using namespace LLVOAvatarDefines; + LLFloaterAvatarTextures::LLFloaterAvatarTextures(const LLUUID& id) : LLFloater(std::string("avatar_texture_debug")), mID(id) @@ -68,26 +70,11 @@ LLFloaterAvatarTextures* LLFloaterAvatarTextures::show(const LLUUID &id) BOOL LLFloaterAvatarTextures::postBuild() { - mBakedHead = getChild<LLTextureCtrl>("baked_head"); - mBakedEyes = getChild<LLTextureCtrl>("baked_eyes"); - mBakedUpper = getChild<LLTextureCtrl>("baked_upper_body"); - mBakedLower = getChild<LLTextureCtrl>("baked_lower_body"); - mBakedSkirt = getChild<LLTextureCtrl>("baked_skirt"); - mHair = getChild<LLTextureCtrl>("hair"); - mMakeup = getChild<LLTextureCtrl>("head_bodypaint"); - mEye = getChild<LLTextureCtrl>("eye_texture"); - mShirt = getChild<LLTextureCtrl>("shirt"); - mUpperTattoo = getChild<LLTextureCtrl>("upper_bodypaint"); - mUpperJacket = getChild<LLTextureCtrl>("upper_jacket"); - mGloves = getChild<LLTextureCtrl>("gloves"); - mUndershirt = getChild<LLTextureCtrl>("undershirt"); - mPants = getChild<LLTextureCtrl>("pants"); - mLowerTattoo = getChild<LLTextureCtrl>("lower_bodypaint"); - mShoes = getChild<LLTextureCtrl>("shoes"); - mSocks = getChild<LLTextureCtrl>("socks"); - mJacket = getChild<LLTextureCtrl>("jacket"); - mUnderpants = getChild<LLTextureCtrl>("underpants"); - mSkirt = getChild<LLTextureCtrl>("skirt_texture"); + for (U32 i=0; i < TEX_NUM_INDICES; i++) + { + const std::string tex_name = LLVOAvatarDictionary::getInstance()->getTexture(ETextureIndex(i))->mName; + mTextures[i] = getChild<LLTextureCtrl>(tex_name); + } mTitle = getTitle(); childSetAction("Dump", onClickDump, this); @@ -105,7 +92,7 @@ void LLFloaterAvatarTextures::draw() #if !LL_RELEASE_FOR_DOWNLOAD static void update_texture_ctrl(LLVOAvatar* avatarp, LLTextureCtrl* ctrl, - LLVOAvatar::ETextureIndex te) + ETextureIndex te) { LLUUID id = avatarp->getTE(te)->getID(); if (id == IMG_DEFAULT_AVATAR) @@ -148,29 +135,10 @@ void LLFloaterAvatarTextures::refresh() { setTitle(mTitle + ": " + fullname); } - update_texture_ctrl(avatarp, mBakedHead, LLVOAvatar::TEX_HEAD_BAKED); - update_texture_ctrl(avatarp, mBakedEyes, LLVOAvatar::TEX_EYES_BAKED); - update_texture_ctrl(avatarp, mBakedUpper, LLVOAvatar::TEX_UPPER_BAKED); - update_texture_ctrl(avatarp, mBakedLower, LLVOAvatar::TEX_LOWER_BAKED); - update_texture_ctrl(avatarp, mBakedSkirt, LLVOAvatar::TEX_SKIRT_BAKED); - - update_texture_ctrl(avatarp, mMakeup, LLVOAvatar::TEX_HEAD_BODYPAINT); - update_texture_ctrl(avatarp, mHair, LLVOAvatar::TEX_HAIR); - update_texture_ctrl(avatarp, mEye, LLVOAvatar::TEX_EYES_IRIS); - - update_texture_ctrl(avatarp, mShirt, LLVOAvatar::TEX_UPPER_SHIRT); - update_texture_ctrl(avatarp, mUpperTattoo, LLVOAvatar::TEX_UPPER_BODYPAINT); - update_texture_ctrl(avatarp, mUpperJacket, LLVOAvatar::TEX_UPPER_JACKET); - update_texture_ctrl(avatarp, mGloves, LLVOAvatar::TEX_UPPER_GLOVES); - update_texture_ctrl(avatarp, mUndershirt, LLVOAvatar::TEX_UPPER_UNDERSHIRT); - - update_texture_ctrl(avatarp, mPants, LLVOAvatar::TEX_LOWER_PANTS); - update_texture_ctrl(avatarp, mLowerTattoo, LLVOAvatar::TEX_LOWER_BODYPAINT); - update_texture_ctrl(avatarp, mShoes, LLVOAvatar::TEX_LOWER_SHOES); - update_texture_ctrl(avatarp, mSocks, LLVOAvatar::TEX_LOWER_SOCKS); - update_texture_ctrl(avatarp, mJacket, LLVOAvatar::TEX_LOWER_JACKET); - update_texture_ctrl(avatarp, mUnderpants, LLVOAvatar::TEX_LOWER_UNDERPANTS); - update_texture_ctrl(avatarp, mSkirt, LLVOAvatar::TEX_SKIRT); + for (U32 i=0; i < TEX_NUM_INDICES; i++) + { + update_texture_ctrl(avatarp, mTextures[i], ETextureIndex(i)); + } } else { diff --git a/indra/newview/llfloateravatartextures.h b/indra/newview/llfloateravatartextures.h index fbcf47bf7d..4138edeb4d 100644 --- a/indra/newview/llfloateravatartextures.h +++ b/indra/newview/llfloateravatartextures.h @@ -36,6 +36,7 @@ #include "llfloater.h" #include "lluuid.h" #include "llstring.h" +#include "llvoavatardefines.h" class LLTextureCtrl; @@ -58,26 +59,7 @@ private: private: LLUUID mID; std::string mTitle; - LLTextureCtrl* mBakedHead; - LLTextureCtrl* mBakedEyes; - LLTextureCtrl* mBakedUpper; - LLTextureCtrl* mBakedLower; - LLTextureCtrl* mBakedSkirt; - LLTextureCtrl* mHair; - LLTextureCtrl* mMakeup; - LLTextureCtrl* mEye; - LLTextureCtrl* mShirt; - LLTextureCtrl* mUpperTattoo; - LLTextureCtrl* mUpperJacket; - LLTextureCtrl* mGloves; - LLTextureCtrl* mUndershirt; - LLTextureCtrl* mPants; - LLTextureCtrl* mLowerTattoo; - LLTextureCtrl* mShoes; - LLTextureCtrl* mSocks; - LLTextureCtrl* mJacket; - LLTextureCtrl* mUnderpants; - LLTextureCtrl* mSkirt; + LLTextureCtrl* mTextures[LLVOAvatarDefines::TEX_NUM_INDICES]; }; #endif diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 2e59240c49..6497821349 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -1072,16 +1072,20 @@ void LLHUDText::renderAllHUD() LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); - - LLGLEnable color_mat(GL_COLOR_MATERIAL); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); - - VisibleTextObjectIterator text_it; - for (text_it = sVisibleHUDTextObjects.begin(); text_it != sVisibleHUDTextObjects.end(); ++text_it) { - (*text_it)->renderText(FALSE); + LLGLEnable color_mat(GL_COLOR_MATERIAL); + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + + VisibleTextObjectIterator text_it; + + for (text_it = sVisibleHUDTextObjects.begin(); text_it != sVisibleHUDTextObjects.end(); ++text_it) + { + (*text_it)->renderText(FALSE); + } } + + LLVertexBuffer::unbind(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3ac7deb3df..0aa406dff1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3883,7 +3883,7 @@ void wear_inventory_category_on_avatar( LLInventoryCategory* category, BOOL appe if( gFloaterCustomize ) { - gFloaterCustomize->askToSaveAllIfDirty( + gFloaterCustomize->askToSaveIfDirty( wear_inventory_category_on_avatar_step2, userdata); } @@ -4154,7 +4154,7 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category ) if( gFloaterCustomize ) { - gFloaterCustomize->askToSaveAllIfDirty( + gFloaterCustomize->askToSaveIfDirty( remove_inventory_category_from_avatar_step2, uuid); } diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 031f4ab304..cdcd68de38 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -241,7 +241,7 @@ void LLProgressView::onCancelButtonClicked(void*) void LLProgressView::onClickMessage(void* data) { LLProgressView* viewp = (LLProgressView*)data; - if ( ! viewp->mMessage.empty() ) + if ( viewp != NULL && ! viewp->mMessage.empty() ) { std::string url_to_open( "" ); diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 6a7ba7b7f4..b376eed814 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -47,6 +47,7 @@ #include "llvfile.h" #include "llviewerimagelist.h" #include "llviewerimagelist.h" +#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llvoavatar.h" @@ -54,9 +55,12 @@ #include "pipeline.h" #include "v4coloru.h" #include "llrender.h" +#include "llassetuploadresponders.h" //#include "../tools/imdebug/imdebug.h" +using namespace LLVOAvatarDefines; + // static S32 LLTexLayerSetBuffer::sGLByteCount = 0; S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; @@ -64,11 +68,12 @@ S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0; //----------------------------------------------------------------------------- // LLBakedUploadData() //----------------------------------------------------------------------------- -LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer ) : +LLBakedUploadData::LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer, const LLUUID & id ) : mAvatar( avatar ), - mLayerSetBuffer( layerset_buffer ) + mLayerSetBuffer( layerset_buffer ), + mID(id) { - mID.generate(); + mStartTime = LLFrameTimer::getTotalTime(); // Record starting time for( S32 i = 0; i < WT_COUNT; i++ ) { LLWearable* wearable = gAgent.getWearable( (EWearableType)i); @@ -221,7 +226,7 @@ BOOL LLTexLayerSetBuffer::needsRender() BOOL needs_update = gAgent.mNumPendingQueries == 0 && (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; if (needs_update) { - BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == LLVOAvatar::TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); + BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); if (invalid_skirt) { // we were trying to create a skirt texture @@ -393,7 +398,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[5*i + 3] = baked_color_data[4*i + 3] < 255 ? baked_color_data[4*i + 3] : baked_bump_data[4*i]; + baked_image_data[5*i + 3] = baked_color_data[4*i + 3]; // alpha should be correct for eyelashes. baked_image_data[5*i + 4] = baked_mask_data[i]; i++; } @@ -409,7 +414,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) baked_image_data[5*i + 0] = baked_color_data[4*i + 0]; baked_image_data[5*i + 1] = baked_color_data[4*i + 1]; baked_image_data[5*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[5*i + 3] = baked_bump_data[4*i]; + baked_image_data[5*i + 3] = 255; // reserve for alpha baked_image_data[5*i + 4] = baked_mask_data[i]; i++; } @@ -418,7 +423,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) } else { - if (mTexLayerSet->getBodyRegion() == "skirt") + if (mTexLayerSet->getBodyRegion() == "skirt" || mTexLayerSet->getBodyRegion() == "hair") { S32 i = 0; for( S32 u = 0; u < mWidth; u++ ) @@ -443,7 +448,7 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) baked_image_data[4*i + 0] = baked_color_data[4*i + 0]; baked_image_data[4*i + 1] = baked_color_data[4*i + 1]; baked_image_data[4*i + 2] = baked_color_data[4*i + 2]; - baked_image_data[4*i + 3] = baked_mask_data[i]; + baked_image_data[4*i + 3] = 255; // eyes should have no mask - reserve for alpha i++; } } @@ -479,16 +484,34 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) if( valid ) { - LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this ); - mUploadID = baked_upload_data->mID; - - gAssetStorage->storeAssetData(tid, - LLAssetType::AT_TEXTURE, - LLTexLayerSetBuffer::onTextureUploadComplete, - baked_upload_data, - TRUE, // temp_file - FALSE, // is_priority - TRUE); // store_local + // baked_upload_data is owned by the responder and deleted after the request completes + LLBakedUploadData* baked_upload_data = new LLBakedUploadData( gAgent.getAvatarObject(), this, asset_id ); + mUploadID = asset_id; + + // upload the image + std::string url = gAgent.getRegion()->getCapability("UploadBakedTexture"); + + if(!url.empty() + && !LLPipeline::sForceOldBakedUpload) // Toggle the debug setting UploadBakedTexOld to change between the new caps method and old method + { + llinfos << "Baked texture upload via capability of " << mUploadID << " to " << url << llendl; + + LLSD body = LLSD::emptyMap(); + LLHTTPClient::post(url, body, new LLSendTexLayerResponder(body, mUploadID, LLAssetType::AT_TEXTURE, baked_upload_data)); + // Responder will call LLTexLayerSetBuffer::onTextureUploadComplete() + } + else + { + llinfos << "Baked texture upload via Asset Store." << llendl; + // gAssetStorage->storeAssetData(mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)this, FALSE); + gAssetStorage->storeAssetData(tid, + LLAssetType::AT_TEXTURE, + LLTexLayerSetBuffer::onTextureUploadComplete, + baked_upload_data, + TRUE, // temp_file + TRUE, // is_priority + TRUE); // store_local + } mNeedsUpload = FALSE; } @@ -541,15 +564,10 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* user if( result >= 0 ) { - LLVOAvatar::ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet ); - if( !gAgent.cameraCustomizeAvatar() ) - { - avatar->setNewBakedTexture( baked_te, uuid ); - } - else - { - llinfos << "LLTexLayerSetBuffer::onTextureUploadComplete() when in Customize Avatar" << llendl; - } + ETextureIndex baked_te = avatar->getBakedTE( layerset_buffer->mTexLayerSet ); + U64 now = LLFrameTimer::getTotalTime(); // Record starting time + llinfos << "Baked texture upload took " << (S32)((now - baked_upload_data->mStartTime) / 1000) << " ms" << llendl; + avatar->setNewBakedTexture( baked_te, uuid ); } else { @@ -800,6 +818,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) { LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->bind(image_gl); + gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE ); gl_rect_2d_simple_tex( width, height ); } else @@ -807,9 +826,10 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) success = FALSE; } } + gGL.flush(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.flush(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); gGL.setColorMask(true, true); gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -895,7 +915,7 @@ void LLTexLayerSet::createComposite() S32 width = mInfo->mWidth; S32 height = mInfo->mHeight; // Composite other avatars at reduced resolution - if( !mAvatar->mIsSelf ) + if( !mAvatar->isSelf() ) { width /= 2; height /= 2; @@ -1049,59 +1069,63 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) if( "upper_shirt" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_UPPER_SHIRT; + mLocalTexture = TEX_UPPER_SHIRT; } else if( "upper_bodypaint" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_UPPER_BODYPAINT; + mLocalTexture = TEX_UPPER_BODYPAINT; } else if( "lower_pants" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_LOWER_PANTS; + mLocalTexture = TEX_LOWER_PANTS; } else if( "lower_bodypaint" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_LOWER_BODYPAINT; + mLocalTexture = TEX_LOWER_BODYPAINT; } else if( "lower_shoes" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SHOES; + mLocalTexture = TEX_LOWER_SHOES; } else if( "head_bodypaint" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_HEAD_BODYPAINT; + mLocalTexture = TEX_HEAD_BODYPAINT; } else if( "lower_socks" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_LOWER_SOCKS; + mLocalTexture = TEX_LOWER_SOCKS; } else if( "upper_jacket" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_UPPER_JACKET; + mLocalTexture = TEX_UPPER_JACKET; } else if( "lower_jacket" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_LOWER_JACKET; + mLocalTexture = TEX_LOWER_JACKET; } else if( "upper_gloves" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_UPPER_GLOVES; + mLocalTexture = TEX_UPPER_GLOVES; } else if( "upper_undershirt" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_UPPER_UNDERSHIRT; + mLocalTexture = TEX_UPPER_UNDERSHIRT; } else if( "lower_underpants" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_LOWER_UNDERPANTS; + mLocalTexture = TEX_LOWER_UNDERPANTS; } else if( "eyes_iris" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_EYES_IRIS; + mLocalTexture = TEX_EYES_IRIS; } else if( "skirt" == local_texture ) { - mLocalTexture = LLVOAvatar::LOCTEX_SKIRT; + mLocalTexture = TEX_SKIRT; + } + else if( "hair_grain" == local_texture ) + { + mLocalTexture = TEX_HAIR; } else { @@ -1364,7 +1388,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) { { LLImageGL* image_gl = NULL; - if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) ) + if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) { if( image_gl ) { @@ -1434,7 +1458,7 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) U8* LLTexLayer::getAlphaData() { LLCRC alpha_mask_crc; - const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture); + const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) @@ -1563,7 +1587,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 { { LLImageGL* image_gl = NULL; - if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) ) + if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) { if( image_gl && (image_gl->getComponents() == 4) ) { @@ -1627,7 +1651,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 if (!mMorphMasksValid && !mMaskedMorphs.empty()) { LLCRC alpha_mask_crc; - const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID(getInfo()->mLocalTexture); + const LLUUID& uuid = mTexLayerSet->getAvatar()->getLocalTextureID((ETextureIndex)getInfo()->mLocalTexture); alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); for( alpha_list_t::iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++ ) @@ -1648,7 +1672,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 else { // clear out a slot if we have filled our cache - S32 max_cache_entries = getTexLayerSet()->getAvatar()->mIsSelf ? 4 : 1; + S32 max_cache_entries = getTexLayerSet()->getAvatar()->isSelf() ? 4 : 1; while ((S32)mAlphaCache.size() >= max_cache_entries) { iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry @@ -1701,7 +1725,7 @@ BOOL LLTexLayer::renderImageRaw( U8* in_data, S32 in_width, S32 in_height, S32 i format = GL_ALPHA; } - if( (in_width != VOAVATAR_SCRATCH_TEX_WIDTH) || (in_height != VOAVATAR_SCRATCH_TEX_HEIGHT) ) + if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) ) { LLGLSNoAlphaTest gls_no_alpha_test; @@ -1918,8 +1942,13 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user) LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar(); if( avatar->getSex() & getSex() ) { + if ( gAgent.cameraCustomizeAvatar() ) + { + set_by_user = FALSE; + } avatar->invalidateComposite( mTexLayer->getTexLayerSet(), set_by_user ); mTexLayer->invalidateMorphMasks(); + avatar->updateMeshTextures(); } } } @@ -2053,7 +2082,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) // Don't keep the cache for other people's avatars // (It's not really a "cache" in that case, but the logic is the same) - if( !mTexLayer->getTexLayerSet()->getAvatar()->mIsSelf ) + if( !mTexLayer->getTexLayerSet()->getAvatar()->isSelf() ) { mCachedProcessedImageGL = NULL; } diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 5ab8c91f72..18e6d6b24f 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -537,13 +537,14 @@ public: class LLBakedUploadData { public: - LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer ); + LLBakedUploadData( LLVOAvatar* avatar, LLTexLayerSetBuffer* layerset_buffer, const LLUUID & id); ~LLBakedUploadData() {} LLUUID mID; LLVOAvatar* mAvatar; // just backlink, don't LLPointer LLTexLayerSetBuffer* mLayerSetBuffer; LLUUID mWearableAssets[WT_COUNT]; + U64 mStartTime; // Used to measure time baked texture upload requires }; extern LLTexStaticImageList gTexStaticImageList; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index db864765b1..fcad86e498 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -955,7 +955,7 @@ void LLToolDragAndDrop::pickCallback(const LLPickInfo& pick_info) if(hit_obj->isAvatar()) { - if(((LLVOAvatar*) hit_obj)->mIsSelf) + if(((LLVOAvatar*) hit_obj)->isSelf()) { target = DT_SELF; hit_face = -1; diff --git a/indra/newview/lltoolfocus.cpp b/indra/newview/lltoolfocus.cpp index 6069f1ffc6..351c02b4c0 100644 --- a/indra/newview/lltoolfocus.cpp +++ b/indra/newview/lltoolfocus.cpp @@ -221,7 +221,7 @@ void LLToolCamera::pickCallback(const LLPickInfo& pick_info) gViewerWindow->getLeftMouseDown() && !gSavedSettings.getBOOL("FreezeTime") && (hit_obj == gAgent.getAvatarObject() || - (hit_obj && hit_obj->isAttachment() && LLVOAvatar::findAvatarFromAttachment(hit_obj)->mIsSelf))) + (hit_obj && hit_obj->isAttachment() && LLVOAvatar::findAvatarFromAttachment(hit_obj)->isSelf()))) { LLToolCamera::getInstance()->mMouseSteering = TRUE; } diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index f15f0f44b0..75e19645a6 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -237,7 +237,11 @@ BOOL LLVisualParamHint::render() { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); + gGL.setAlphaRejectSettings(LLRender::CF_ALWAYS); + gGL.setSceneBlendType(LLRender::BT_REPLACE); avatarPoolp->renderAvatars(avatarp); // renders only one avatar + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight); gGL.color4f(1,1,1,1); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 6b99cfbeaf..c0d3466fab 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -119,6 +119,12 @@ static bool handleSetShaderChanged(const LLSD& newvalue) return true; } +static bool handleSetSelfInvisible( const LLSD& newvalue) +{ + LLVOAvatar::onChangeSelfInvisible( newvalue.asBoolean() ); + return true; +} + static bool handleReleaseGLBufferChanged(const LLSD& newvalue) { if (gPipeline.isInit()) @@ -205,16 +211,6 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue) return true; } -const S32 MAX_USER_COMPOSITE_LIMIT = 100; -const S32 MIN_USER_COMPOSITE_LIMIT = 0; - -static bool handleCompositeLimitChanged(const LLSD& newvalue) -{ - S32 composite_limit = llmax(MIN_USER_COMPOSITE_LIMIT, llmin((S32)newvalue.asInteger(), MAX_USER_COMPOSITE_LIMIT)); - LLVOAvatar::sMaxOtherAvatarsToComposite = composite_limit; - return true; -} - static bool handleVideoMemoryChanged(const LLSD& newvalue) { gImageList.updateMaxResidentTexMem(newvalue.asInteger()); @@ -297,6 +293,13 @@ static bool handleUseOcclusionChanged(const LLSD& newvalue) return true; } +static bool handleUploadBakedTexOldChanged(const LLSD& newvalue) +{ + LLPipeline::sForceOldBakedUpload = newvalue.asBoolean(); + return true; +} + + static bool handleNumpadControlChanged(const LLSD& newvalue) { if (gKeyboard) @@ -453,6 +456,7 @@ void settings_setup_listeners() gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("RenderAvatarMaxVisible")->getSignal()->connect(boost::bind(&handleAvatarMaxVisibleChanged, _1)); + gSavedSettings.getControl("RenderAvatarInvisible")->getSignal()->connect(boost::bind(&handleSetSelfInvisible, _1)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _1)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1)); @@ -474,11 +478,11 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _1)); gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _1)); gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); - gSavedSettings.getControl("AvatarCompositeLimit")->getSignal()->connect(boost::bind(&handleCompositeLimitChanged, _1)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _1)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _1)); gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _1)); gSavedSettings.getControl("ConsoleMaxLines")->getSignal()->connect(boost::bind(&handleConsoleMaxLinesChanged, _1)); + gSavedSettings.getControl("UploadBakedTexOld")->getSignal()->connect(boost::bind(&handleUploadBakedTexOldChanged, _1)); gSavedSettings.getControl("UseOcclusion")->getSignal()->connect(boost::bind(&handleUseOcclusionChanged, _1)); gSavedSettings.getControl("AudioLevelMaster")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioLevelSFX")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index 89490e08bf..1cc062dbd2 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -514,6 +514,16 @@ void LLViewerJoint::setVisible(BOOL visible, BOOL recursive) } } + +void LLViewerJoint::setMeshesToChildren() +{ + removeAllChildren(); + for (std::vector<LLViewerJointMesh*>::iterator iter = mMeshParts.begin(); + iter != mMeshParts.end(); iter++) + { + addChild((LLViewerJointMesh *) *iter); + } +} //----------------------------------------------------------------------------- // LLViewerJointCollisionVolume() //----------------------------------------------------------------------------- diff --git a/indra/newview/llviewerjoint.h b/indra/newview/llviewerjoint.h index 0430a91833..a07902e582 100644 --- a/indra/newview/llviewerjoint.h +++ b/indra/newview/llviewerjoint.h @@ -40,6 +40,7 @@ #include "llapr.h" class LLFace; +class LLViewerJointMesh; //----------------------------------------------------------------------------- // class LLViewerJoint @@ -133,8 +134,13 @@ public: void setVisible( BOOL visible, BOOL recursive ); + // Takes meshes in mMeshParts and sets each one as a child joint + void setMeshesToChildren(); + public: static BOOL sDisableLOD; + std::vector<LLViewerJointMesh*> mMeshParts; + void setMeshID( S32 id ) {mMeshID = id;} protected: BOOL mValid; @@ -142,6 +148,7 @@ protected: F32 mMinPixelArea; PickName mPickName; BOOL mVisible; + S32 mMeshID; }; class LLViewerJointCollisionVolume : public LLViewerJoint diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 4cacc5c97b..c0e02921cf 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -558,7 +558,12 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) } else { - llwarns << "Layerset without composite" << llendl; + // This warning will always trigger if you've hacked the avatar to show as incomplete. + // Ignore the warning if that's the case. + if (!gSavedSettings.getBOOL("RenderUnloadedAvatar")) + { + llwarns << "Layerset without composite" << llendl; + } gGL.getTexUnit(0)->bind(gImageList.getImage(IMG_DEFAULT)); } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index de16bbf8a1..47a887e909 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -212,6 +212,7 @@ #include "lltexlayer.h" +using namespace LLVOAvatarDefines; void init_client_menu(LLMenuGL* menu); void init_server_menu(LLMenuGL* menu); @@ -1313,8 +1314,6 @@ void init_debug_rendering_menu(LLMenuGL* menu) menu->createJumpKeys(); } -extern BOOL gDebugAvatarRotation; - void init_debug_avatar_menu(LLMenuGL* menu) { LLMenuGL* sub_menu = new LLMenuGL("Grab Baked Texture"); @@ -1361,7 +1360,7 @@ void init_debug_avatar_menu(LLMenuGL* menu) //menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane)); menu->append(new LLMenuItemToggleGL("Show Collision Skeleton", &LLVOAvatar::sShowCollisionVolumes)); menu->append(new LLMenuItemToggleGL( "Display Agent Target", &LLAgent::sDebugDisplayTarget)); - menu->append(new LLMenuItemToggleGL( "Debug Rotation", &gDebugAvatarRotation)); + menu->append(new LLMenuItemToggleGL( "Debug Rotation", &LLVOAvatar::sDebugAvatarRotation)); menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); menu->append(new LLMenuItemCallGL("Rebake Textures", handle_rebake_textures, NULL, NULL, 'R', MASK_ALT | MASK_CONTROL )); #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -1373,11 +1372,12 @@ void init_debug_avatar_menu(LLMenuGL* menu) void init_debug_baked_texture_menu(LLMenuGL* menu) { - menu->append(new LLMenuItemCallGL("Iris", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_EYES_BAKED)); - menu->append(new LLMenuItemCallGL("Head", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_HEAD_BAKED)); - menu->append(new LLMenuItemCallGL("Upper Body", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_UPPER_BAKED)); - menu->append(new LLMenuItemCallGL("Lower Body", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_LOWER_BAKED)); - menu->append(new LLMenuItemCallGL("Skirt", handle_grab_texture, enable_grab_texture, (void*) LLVOAvatar::TEX_SKIRT_BAKED)); + menu->append(new LLMenuItemCallGL("Iris", handle_grab_texture, enable_grab_texture, (void*) TEX_EYES_BAKED)); + menu->append(new LLMenuItemCallGL("Head", handle_grab_texture, enable_grab_texture, (void*) TEX_HEAD_BAKED)); + menu->append(new LLMenuItemCallGL("Upper Body", handle_grab_texture, enable_grab_texture, (void*) TEX_UPPER_BAKED)); + menu->append(new LLMenuItemCallGL("Lower Body", handle_grab_texture, enable_grab_texture, (void*) TEX_LOWER_BAKED)); + menu->append(new LLMenuItemCallGL("Skirt", handle_grab_texture, enable_grab_texture, (void*) TEX_SKIRT_BAKED)); + menu->append(new LLMenuItemCallGL("Hair", handle_grab_texture, enable_grab_texture, (void*) TEX_HAIR_BAKED)); menu->createJumpKeys(); } @@ -3082,7 +3082,7 @@ void handle_reset_view() if( (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgent.getCameraMode()) && gFloaterCustomize ) { // Show dialog box if needed. - gFloaterCustomize->askToSaveAllIfDirty( reset_view_final, NULL ); + gFloaterCustomize->askToSaveIfDirty( reset_view_final, NULL ); } else { @@ -6727,12 +6727,12 @@ void handle_debug_avatar_textures(void*) void handle_grab_texture(void* data) { - LLVOAvatar::ETextureIndex index = (LLVOAvatar::ETextureIndex)((intptr_t)data); + ETextureIndex index = (ETextureIndex)((intptr_t)data); LLVOAvatar* avatar = gAgent.getAvatarObject(); if ( avatar ) { const LLUUID& asset_id = avatar->grabLocalTexture(index); - llinfos << "Adding baked texture " << asset_id << " to inventory." << llendl; + LL_INFOS("texture") << "Adding baked texture " << asset_id << " to inventory." << llendl; LLAssetType::EType asset_type = LLAssetType::AT_TEXTURE; LLInventoryType::EType inv_type = LLInventoryType::IT_TEXTURE; LLUUID folder_id(gInventory.findCategoryUUIDForType(asset_type)); @@ -6741,21 +6741,24 @@ void handle_grab_texture(void* data) std::string name = "Baked "; switch (index) { - case LLVOAvatar::TEX_EYES_BAKED: + case TEX_EYES_BAKED: name.append("Iris"); break; - case LLVOAvatar::TEX_HEAD_BAKED: + case TEX_HEAD_BAKED: name.append("Head"); break; - case LLVOAvatar::TEX_UPPER_BAKED: + case TEX_UPPER_BAKED: name.append("Upper Body"); break; - case LLVOAvatar::TEX_LOWER_BAKED: + case TEX_LOWER_BAKED: name.append("Lower Body"); break; - case LLVOAvatar::TEX_SKIRT_BAKED: + case TEX_SKIRT_BAKED: name.append("Skirt"); break; + case TEX_HAIR_BAKED: + name.append("Hair"); + break; default: name.append("Unknown"); break; @@ -6817,7 +6820,7 @@ void handle_grab_texture(void* data) BOOL enable_grab_texture(void* data) { - LLVOAvatar::ETextureIndex index = (LLVOAvatar::ETextureIndex)((intptr_t)data); + ETextureIndex index = (ETextureIndex)((intptr_t)data); LLVOAvatar* avatar = gAgent.getAvatarObject(); if ( avatar ) { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c840557f01..77b69d0ad4 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3671,7 +3671,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) avatarp->mSignaledAnimations.clear(); - if (avatarp->mIsSelf) + if (avatarp->isSelf()) { LLUUID object_id; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index e4ddbd42dd..4a81c06efb 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1889,7 +1889,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if ( gShowObjectUpdates ) { - if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->mIsSelf)) + if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf())) && mRegionp) { LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 50fe66ea5e..e822c81500 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1420,6 +1420,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("ServerReleaseNotes"); capabilityNames.append("StartGroupProposal"); + capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("UpdateAgentLanguage"); capabilityNames.append("UpdateGestureAgentInventory"); capabilityNames.append("UpdateNotecardAgentInventory"); @@ -1427,8 +1428,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("UpdateGestureTaskInventory"); capabilityNames.append("UpdateNotecardTaskInventory"); capabilityNames.append("UpdateScriptTask"); + capabilityNames.append("UploadBakedTexture"); capabilityNames.append("ViewerStartAuction"); - capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("ViewerStats"); // Please add new capabilities alphabetically to reduce // merge conflicts. diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3757923e27..8d20e4e91c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -32,175 +32,112 @@ #include "llviewerprecompiledheaders.h" -#include <algorithm> -#include <vector> -#include "llstl.h" - #include "llvoavatar.h" -#include "llrender.h" +#include <stdio.h> +#include <ctype.h> + #include "audioengine.h" -#include "imageids.h" -#include "indra_constants.h" -#include "llchat.h" -#include "llfontgl.h" -#include "llprimitive.h" -#include "lltextureentry.h" -#include "message.h" #include "noise.h" -#include "sound_ids.h" -#include "lltimer.h" -#include "timing.h" -#include "llagent.h" // Get state values from here +#include "llagent.h" // Get state values from here #include "llviewercontrol.h" -#include "llcriticaldamp.h" -#include "lldir.h" -#include "lldrawable.h" #include "lldrawpoolavatar.h" -#include "lldrawpoolalpha.h" -#include "lldrawpoolbump.h" #include "lldriverparam.h" #include "lleditingmotion.h" #include "llemote.h" -#include "llface.h" -#include "llfasttimer.h" #include "llfirstuse.h" -#include "llfloatercustomize.h" -#include "llfloatertools.h" -#include "llgldbg.h" -#include "llhandmotion.h" #include "llheadrotmotion.h" -#include "llhudeffectbeam.h" -#include "llhudeffectlookat.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" -#include "llhudtext.h" -#include "llinventorymodel.h" #include "llinventoryview.h" #include "llkeyframefallmotion.h" -#include "llkeyframemotion.h" -#include "llkeyframemotionparam.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" -#include "llmenugl.h" #include "llmutelist.h" -#include "llnetmap.h" -#include "llnotify.h" -#include "llquantize.h" -#include "llregionhandle.h" -#include "llresmgr.h" #include "llselectmgr.h" -#include "llsky.h" #include "llsprite.h" -#include "llstatusbar.h" #include "lltargetingmotion.h" #include "lltexlayer.h" -#include "lltoolgrab.h" // for needsRenderBeam -#include "lltoolmgr.h" // for needsRenderBeam +#include "lltoolgrab.h" // for needsRenderBeam +#include "lltoolmgr.h" // for needsRenderBeam #include "lltoolmorph.h" #include "llviewercamera.h" #include "llviewerimagelist.h" -#include "llviewerinventory.h" #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" -#include "llviewerregion.h" #include "llviewerstats.h" -#include "llviewerwindow.h" -#include "llvosky.h" #include "llvovolume.h" -#include "llwearable.h" -#include "llwearablelist.h" #include "llworld.h" #include "pipeline.h" -#include "llspatialpartition.h" #include "llviewershadermgr.h" -#include "llappviewer.h" #include "llsky.h" #include "llanimstatelabels.h" - -//#include "vtune/vtuneapi.h" - #include "llgesturemgr.h" //needed to trigger the voice gesticulations -#include "llvoicevisualizer.h" #include "llvoiceclient.h" +#include "llvoicevisualizer.h" // Ventrella -LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; -LLVOAvatarSkeletonInfo* LLVOAvatar::sSkeletonInfo = NULL; -LLVOAvatarInfo* LLVOAvatar::sAvatarInfo = NULL; +#include "boost/lexical_cast.hpp" + +using namespace LLVOAvatarDefines; -BOOL gDebugAvatarRotation = FALSE; -S32 LLVOAvatar::sFreezeCounter = 0 ; +//----------------------------------------------------------------------------- +// Global constants +//----------------------------------------------------------------------------- +const LLUUID ANIM_AGENT_BODY_NOISE = LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise" +const LLUUID ANIM_AGENT_BREATHE_ROT = LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8"); //"breathe_rot" +const LLUUID ANIM_AGENT_EDITING = LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb"); //"editing" +const LLUUID ANIM_AGENT_EYE = LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea"); //"eye" +const LLUUID ANIM_AGENT_FLY_ADJUST = LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e"); //"fly_adjust" +const LLUUID ANIM_AGENT_HAND_MOTION = LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578"); //"hand_motion" +const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d"); //"head_rot" +const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix" +const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target" +const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" -//extern BOOL gVelocityInterpolate; //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- -const F32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024; +const std::string AVATAR_DEFAULT_CHAR = "avatar"; -F32 SHADOW_OFFSET_AMT = 0.03f; +const S32 MIN_PIXEL_AREA_FOR_COMPOSITE = 1024; +const F32 SHADOW_OFFSET_AMT = 0.03f; -#define DELTA_TIME_MIN 0.01f // we clamp measured deltaTime to this -#define DELTA_TIME_MAX 0.2f // range to insure stability of computations. +const F32 DELTA_TIME_MIN = 0.01f; // we clamp measured deltaTime to this +const F32 DELTA_TIME_MAX = 0.2f; // range to insure stability of computations. const F32 PELVIS_LAG_FLYING = 0.22f;// pelvis follow half life while flying - const F32 PELVIS_LAG_WALKING = 0.4f; // ...while walking - const F32 PELVIS_LAG_MOUSELOOK = 0.15f; const F32 MOUSELOOK_PELVIS_FOLLOW_FACTOR = 0.5f; - const F32 PELVIS_LAG_WHEN_FOLLOW_CAM_IS_ON = 0.0001f; // not zero! - something gets divided by this! -#define PELVIS_ROT_THRESHOLD_SLOW 60.0f // amount of deviation allowed between -#define PELVIS_ROT_THRESHOLD_FAST 2.0f // the pelvis and the view direction +const F32 PELVIS_ROT_THRESHOLD_SLOW = 60.0f; // amount of deviation allowed between +const F32 PELVIS_ROT_THRESHOLD_FAST = 2.0f; // the pelvis and the view direction // when moving fast & slow - -const F32 MIN_SPEED_PELVIS_FOLLOW = 0.1f; - -#define TORSO_NOISE_AMOUNT 1.f // Amount of deviation from up-axis, in degrees -#define TORSO_NOISE_SPEED 0.2f // Time scale factor on torso noise. +const F32 TORSO_NOISE_AMOUNT = 1.0f; // Amount of deviation from up-axis, in degrees +const F32 TORSO_NOISE_SPEED = 0.2f; // Time scale factor on torso noise. const F32 BREATHE_ROT_MOTION_STRENGTH = 0.05f; - const F32 BREATHE_SCALE_MOTION_STRENGTH = 0.005f; -#define PELVIS_NOISE_FACTOR 0.5f // amount of random noise - -#define AUDIO_STEP_PRI 0xC0000000 -#define AUDIO_STEP_LO_SPEED 0.01f // as average speed goes from lo to hi, -#define AUDIO_STEP_HI_SPEED 3.0f // from lo to hi -#define AUDIO_STEP_LO_GAIN 0.15f // the resulting gain will ramp linearly -#define AUDIO_STEP_HI_GAIN 0.15f - -const F32 DAMPED_MOTION_TIME_SCALE = 0.15f; - -const F32 LOOKAT_CAMERA_DIST_SQUARED = 25.f; - -#define AVATAR_HEADER "Linden Avatar 1.0" -#define AVATAR_SECTION "[avatar]" - -#define AVATAR_DEFAULT_CHAR "avatar" - const F32 MIN_SHADOW_HEIGHT = 0.f; const F32 MAX_SHADOW_HEIGHT = 0.3f; -#define MIN_REQUIRED_PIXEL_AREA_BODY_NOISE (10000.f) -#define MIN_REQUIRED_PIXEL_AREA_BREATHE (10000.f) -#define MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX (40.f) +const S32 MIN_REQUIRED_PIXEL_AREA_BODY_NOISE = 10000; +const S32 MIN_REQUIRED_PIXEL_AREA_BREATHE = 10000; +const S32 MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX = 40; -const S32 LOCTEX_IMAGE_SIZE_SELF = 512; -const S32 LOCTEX_IMAGE_AREA_SELF = LOCTEX_IMAGE_SIZE_SELF * LOCTEX_IMAGE_SIZE_SELF; -const S32 LOCTEX_IMAGE_SIZE_OTHER = LOCTEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!mIsSelf) avatars -const S32 LOCTEX_IMAGE_AREA_OTHER = LOCTEX_IMAGE_SIZE_OTHER * LOCTEX_IMAGE_SIZE_OTHER; +const S32 TEX_IMAGE_SIZE_SELF = 512; +const S32 TEX_IMAGE_AREA_SELF = TEX_IMAGE_SIZE_SELF * TEX_IMAGE_SIZE_SELF; +const S32 TEX_IMAGE_SIZE_OTHER = TEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!mIsSelf) avatars +const S32 TEX_IMAGE_AREA_OTHER = TEX_IMAGE_SIZE_OTHER * TEX_IMAGE_SIZE_OTHER; const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f; const S32 MORPH_MASK_REQUESTED_DISCARD = 0; -const S32 MIN_PIXEL_AREA_BUMP = 500; // Discard level at which to switch to baked textures // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB @@ -210,95 +147,34 @@ const F32 FOOT_COLLIDE_FUDGE = 0.04f; const F32 HOVER_EFFECT_MAX_SPEED = 3.f; const F32 HOVER_EFFECT_STRENGTH = 0.f; -F32 UNDERWATER_EFFECT_STRENGTH = 0.1f; +const F32 UNDERWATER_EFFECT_STRENGTH = 0.1f; const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f; const F32 APPEARANCE_MORPH_TIME = 0.65f; -const F32 CAMERA_SHAKE_ACCEL_THRESHOLD_SQUARED = 5.f * 5.f; 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_LOD_CHANGES_PER_FRAME = 2; const S32 MAX_BUBBLE_CHAT_LENGTH = 1023; const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12; const F32 CHAT_FADE_TIME = 8.0; const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; -const S32 MAX_BUBBLES = 7; -S32 LLVOAvatar::sMaxVisible = 50; - -LLVOAvatar::ETextureIndex LLVOAvatar::sBakedTextureIndices[BAKED_TEXTURE_COUNT] = +enum ERenderName { - LLVOAvatar::TEX_HEAD_BAKED, - LLVOAvatar::TEX_UPPER_BAKED, - LLVOAvatar::TEX_LOWER_BAKED, - LLVOAvatar::TEX_EYES_BAKED, - LLVOAvatar::TEX_SKIRT_BAKED + RENDER_NAME_NEVER, + RENDER_NAME_FADE, + RENDER_NAME_ALWAYS }; //----------------------------------------------------------------------------- -// Utility functions -//----------------------------------------------------------------------------- - -static F32 calc_bouncy_animation(F32 x) -{ - return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; -} - -BOOL LLLineSegmentCapsuleIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& p1, const LLVector3& p2, const F32& radius, LLVector3& result) -{ - return FALSE; -} - -//----------------------------------------------------------------------------- -// Static Data +// Callback data //----------------------------------------------------------------------------- -S32 LLVOAvatar::sMaxOtherAvatarsToComposite = 1; // Only this many avatars (other than yourself) can be composited at a time. Set in initClass(). -LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames; -LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime; -S32 LLVOAvatar::sScratchTexBytes = 0; -F32 LLVOAvatar::sRenderDistance = 256.f; -S32 LLVOAvatar::sNumVisibleAvatars = 0; -S32 LLVOAvatar::sNumLODChangesThisFrame = 0; - -LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); -LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = -{ - LLUUID(SND_STONE_RUBBER), - LLUUID(SND_METAL_RUBBER), - LLUUID(SND_GLASS_RUBBER), - LLUUID(SND_WOOD_RUBBER), - LLUUID(SND_FLESH_RUBBER), - LLUUID(SND_RUBBER_PLASTIC), - LLUUID(SND_RUBBER_RUBBER) -}; - -// static -S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; -BOOL LLVOAvatar::sRenderGroupTitles = TRUE; -S32 LLVOAvatar::sNumVisibleChatBubbles = 0; -BOOL LLVOAvatar::sDebugInvisible = FALSE; -BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; -BOOL LLVOAvatar::sShowAnimationDebug = FALSE; -BOOL LLVOAvatar::sShowFootPlane = FALSE; -BOOL LLVOAvatar::sShowCollisionVolumes = FALSE; -BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; -F32 LLVOAvatar::sLODFactor = 1.f; -BOOL LLVOAvatar::sUseImpostors = FALSE; -BOOL LLVOAvatar::sJointDebug = FALSE; -S32 LLVOAvatar::sCurJoint = 0; -S32 LLVOAvatar::sCurVolume = 0; -F32 LLVOAvatar::sUnbakedTime = 0.f; -F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; -F32 LLVOAvatar::sGreyTime = 0.f; -F32 LLVOAvatar::sGreyUpdateTime = 0.f; - struct LLAvatarTexData { - LLAvatarTexData( const LLUUID& id, LLVOAvatar::ELocTexIndex index ) + LLAvatarTexData( const LLUUID& id, ETextureIndex index ) : mAvatarID(id), mIndex(index) {} LLUUID mAvatarID; - LLVOAvatar::ELocTexIndex mIndex; + ETextureIndex mIndex; }; struct LLTextureMaskData @@ -309,6 +185,142 @@ struct LLTextureMaskData S32 mLastDiscardLevel; }; +/********************************************************************************* + ** ** + ** Begin LLVOAvatar Support classes + ** + **/ + +//------------------------------------------------------------------------ +// LLVOBoneInfo +// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. +//------------------------------------------------------------------------ +class LLVOAvatarBoneInfo +{ + friend class LLVOAvatar; + friend class LLVOAvatarSkeletonInfo; +public: + LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} + ~LLVOAvatarBoneInfo() + { + std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); + } + BOOL parseXml(LLXmlTreeNode* node); + +private: + std::string mName; + BOOL mIsJoint; + LLVector3 mPos; + LLVector3 mRot; + LLVector3 mScale; + LLVector3 mPivot; + typedef std::vector<LLVOAvatarBoneInfo*> child_list_t; + child_list_t mChildList; +}; + +//------------------------------------------------------------------------ +// LLVOAvatarSkeletonInfo +// Overall avatar skeleton +//------------------------------------------------------------------------ +class LLVOAvatarSkeletonInfo +{ + friend class LLVOAvatar; +public: + LLVOAvatarSkeletonInfo() : + mNumBones(0), mNumCollisionVolumes(0) {} + ~LLVOAvatarSkeletonInfo() + { + std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); + } + BOOL parseXml(LLXmlTreeNode* node); + S32 getNumBones() const { return mNumBones; } + S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } + +private: + S32 mNumBones; + S32 mNumCollisionVolumes; + typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + + +//------------------------------------------------------------------------ +// LLVOAvatarXmlInfo +// One instance (in LLVOAvatar) with common data parsed from the XML files +//------------------------------------------------------------------------ +class LLVOAvatarXmlInfo +{ + friend class LLVOAvatar; +public: + LLVOAvatarXmlInfo(); + ~LLVOAvatarXmlInfo(); + +private: + BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); + BOOL parseXmlMeshNodes(LLXmlTreeNode* root); + BOOL parseXmlColorNodes(LLXmlTreeNode* root); + BOOL parseXmlLayerNodes(LLXmlTreeNode* root); + BOOL parseXmlDriverNodes(LLXmlTreeNode* root); + + struct LLVOAvatarMeshInfo + { + typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t; + typedef std::vector<morph_info_pair_t> morph_info_list_t; + + LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} + ~LLVOAvatarMeshInfo() + { + morph_info_list_t::iterator iter; + for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) + { + delete iter->first; + } + mPolyMorphTargetInfoList.clear(); + } + + std::string mType; + S32 mLOD; + std::string mMeshFileName; + std::string mReferenceMeshName; + F32 mMinPixelArea; + morph_info_list_t mPolyMorphTargetInfoList; + }; + typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t; + mesh_info_list_t mMeshInfoList; + + typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t; + skeletal_distortion_info_list_t mSkeletalDistortionInfoList; + + struct LLVOAvatarAttachmentInfo + { + LLVOAvatarAttachmentInfo() + : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), + mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} + std::string mName; + std::string mJointName; + LLVector3 mPosition; + LLVector3 mRotationEuler; + S32 mGroup; + S32 mAttachmentID; + S32 mPieMenuSlice; + BOOL mVisibleFirstPerson; + BOOL mIsHUDAttachment; + BOOL mHasPosition; + BOOL mHasRotation; + }; + typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t; + attachment_info_list_t mAttachmentInfoList; + + LLTexGlobalColorInfo *mTexSkinColorInfo; + LLTexGlobalColorInfo *mTexHairColorInfo; + LLTexGlobalColorInfo *mTexEyeColorInfo; + + typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t; + layer_info_list_t mLayerInfoList; + + typedef std::vector<LLDriverParamInfo*> driver_info_list_t; + driver_info_list_t mDriverInfoList; +}; //----------------------------------------------------------------------------- // class LLBodyNoiseMotion @@ -322,7 +334,6 @@ public: : LLMotion(id) { mName = "body_noise"; - mTorsoState = new LLJointState; } @@ -409,7 +420,7 @@ public: // called when a motion is deactivated virtual void onDeactivate() {} -public: +private: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- @@ -430,12 +441,11 @@ public: mCharacter(NULL) { mName = "breathe_rot"; - mChestState = new LLJointState; } // Destructor - virtual ~LLBreatheMotionRot() { } + virtual ~LLBreatheMotionRot() {} public: //------------------------------------------------------------------------- @@ -518,7 +528,7 @@ public: // called when a motion is deactivated virtual void onDeactivate() {} -public: +private: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- @@ -615,7 +625,7 @@ public: // called when a motion is deactivated virtual void onDeactivate() {} -public: +private: //------------------------------------------------------------------------- // joint states to be animated //------------------------------------------------------------------------- @@ -623,20 +633,74 @@ public: LLCharacter* mCharacter; }; +/** + ** + ** End LLVOAvatar Support classes + ** ** + *********************************************************************************/ + + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +LLXmlTree LLVOAvatar::sXMLTree; +LLXmlTree LLVOAvatar::sSkeletonXMLTree; +BOOL LLVOAvatar::sDebugAvatarRotation = FALSE; +LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; +LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; +LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; +S32 LLVOAvatar::sFreezeCounter = 0; +S32 LLVOAvatar::sMaxVisible = 50; +LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames; +LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime; +S32 LLVOAvatar::sScratchTexBytes = 0; +F32 LLVOAvatar::sRenderDistance = 256.f; +S32 LLVOAvatar::sNumVisibleAvatars = 0; +S32 LLVOAvatar::sNumLODChangesThisFrame = 0; + +const LLUUID LLVOAvatar::sStepSoundOnLand = LLUUID("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); +const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = +{ + LLUUID(SND_STONE_RUBBER), + LLUUID(SND_METAL_RUBBER), + LLUUID(SND_GLASS_RUBBER), + LLUUID(SND_WOOD_RUBBER), + LLUUID(SND_FLESH_RUBBER), + LLUUID(SND_RUBBER_PLASTIC), + LLUUID(SND_RUBBER_RUBBER) +}; + +S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; +BOOL LLVOAvatar::sRenderGroupTitles = TRUE; +S32 LLVOAvatar::sNumVisibleChatBubbles = 0; +BOOL LLVOAvatar::sDebugInvisible = FALSE; +BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; +BOOL LLVOAvatar::sShowAnimationDebug = FALSE; +BOOL LLVOAvatar::sShowFootPlane = FALSE; +BOOL LLVOAvatar::sShowCollisionVolumes = FALSE; +BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; +F32 LLVOAvatar::sLODFactor = 1.f; +BOOL LLVOAvatar::sUseImpostors = FALSE; +BOOL LLVOAvatar::sJointDebug = FALSE; + +F32 LLVOAvatar::sUnbakedTime = 0.f; +F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; +F32 LLVOAvatar::sGreyTime = 0.f; +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() //----------------------------------------------------------------------------- -LLVOAvatar::LLVOAvatar( - const LLUUID& id, - const LLPCode pcode, - LLViewerRegion* regionp) - : +LLVOAvatar::LLVOAvatar(const LLUUID& id, + const LLPCode pcode, + LLViewerRegion* regionp) : LLViewerObject(id, pcode, regionp), - mLastHeadBakedID( IMG_DEFAULT_AVATAR ), - mLastUpperBodyBakedID( IMG_DEFAULT_AVATAR ), - mLastLowerBodyBakedID( IMG_DEFAULT_AVATAR ), - mLastEyesBakedID( IMG_DEFAULT_AVATAR ), - mLastSkirtBakedID( IMG_DEFAULT_AVATAR ), mIsDummy(FALSE), mSpecialRenderMode(0), mTurning(FALSE), @@ -654,12 +718,6 @@ LLVOAvatar::LLVOAvatar( mAppearanceAnimSetByUser(FALSE), mLastAppearanceBlendTime(0.f), mAppearanceAnimating(FALSE), - mHeadLayerSet( NULL ), - mUpperBodyLayerSet( NULL ), - mLowerBodyLayerSet( NULL ), - mEyesLayerSet( NULL ), - mSkirtLayerSet( NULL ), - mRenderPriority(1.0f), mNameString(), mTitle(), mNameAway(FALSE), @@ -671,17 +729,6 @@ LLVOAvatar::LLVOAvatar( mRegionCrossingCount(0), mFirstTEMessageReceived( FALSE ), mFirstAppearanceMessageReceived( FALSE ), - mHeadBakedLoaded(FALSE), - mHeadMaskDiscard(-1), - mUpperBakedLoaded(FALSE), - mUpperMaskDiscard(-1), - mLowerBakedLoaded(FALSE), - mLowerMaskDiscard(-1), - mEyesBakedLoaded(FALSE), - mSkirtBakedLoaded(FALSE), - mHeadMaskTexName(0), - mUpperMaskTexName(0), - mLowerMaskTexName(0), mCulled( FALSE ), mVisibilityRank(0), mTexSkinColor( NULL ), @@ -689,24 +736,36 @@ LLVOAvatar::LLVOAvatar( mTexEyeColor( NULL ), mNeedsSkin(FALSE), mUpdatePeriod(1), - mFullyLoadedInitialized(FALSE) + mFullyLoadedInitialized(FALSE), + mHasBakedHair( FALSE ) { LLMemType mt(LLMemType::MTYPE_AVATAR); - //VTResume(); // VTune // mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline - bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job + const bool needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; mPelvisp = NULL; - for( S32 i=0; i<LOCTEX_NUM_ENTRIES; i++ ) + for( S32 i=0; i<TEX_NUM_INDICES; i++ ) + { + if (isIndexLocalTexture((ETextureIndex)i)) + { + mLocalTextureData[(ETextureIndex)i] = LocalTextureData(); + } + } + + mBakedTextureData.resize(BAKED_NUM_INDICES); + for (U32 i = 0; i < mBakedTextureData.size(); i++ ) { - mLocalTextureBaked[i] = FALSE; - mLocalTextureDiscard[i] = MAX_DISCARD_LEVEL+1; + mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; + mBakedTextureData[i].mTexLayerSet = NULL; + mBakedTextureData[i].mIsLoaded = false; + mBakedTextureData[i].mMaskTexName = 0; + mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); } mDirtyMesh = TRUE; // Dirty geometry, need to regenerate. @@ -744,7 +803,7 @@ LLVOAvatar::LLVOAvatar( mImpostorDistance = 0; mImpostorPixelArea = 0; - setNumTEs(TEX_NUM_ENTRIES); + setNumTEs(TEX_NUM_INDICES); mbCanSelect = TRUE; @@ -777,118 +836,71 @@ LLVOAvatar::LLVOAvatar( //------------------------------------------------------------------------- mRoot.setName( "mRoot" ); - // skinned mesh objects - mHairLOD.setName("mHairLOD"); - mHairMesh0.setName("mHairMesh0"); - mHairMesh0.setMeshID(MESH_ID_HAIR); - mHairMesh1.setName("mHairMesh1"); - mHairMesh2.setName("mHairMesh2"); - mHairMesh3.setName("mHairMesh3"); - mHairMesh4.setName("mHairMesh4"); - mHairMesh5.setName("mHairMesh5"); - - mHairMesh0.setIsTransparent(TRUE); - mHairMesh1.setIsTransparent(TRUE); - mHairMesh2.setIsTransparent(TRUE); - mHairMesh3.setIsTransparent(TRUE); - mHairMesh4.setIsTransparent(TRUE); - mHairMesh5.setIsTransparent(TRUE); - - mHeadLOD.setName("mHeadLOD"); - mHeadMesh0.setName("mHeadMesh0"); - mHeadMesh0.setMeshID(MESH_ID_HEAD); - mHeadMesh1.setName("mHeadMesh1"); - mHeadMesh2.setName("mHeadMesh2"); - mHeadMesh3.setName("mHeadMesh3"); - mHeadMesh4.setName("mHeadMesh4"); - - mEyeLashLOD.setName("mEyeLashLOD"); - mEyeLashMesh0.setName("mEyeLashMesh0"); - mEyeLashMesh0.setMeshID(MESH_ID_HEAD); - mEyeLashMesh0.setIsTransparent(TRUE); - - mUpperBodyLOD.setName("mUpperBodyLOD"); - mUpperBodyMesh0.setName("mUpperBodyMesh0"); - mUpperBodyMesh0.setMeshID(MESH_ID_UPPER_BODY); - mUpperBodyMesh1.setName("mUpperBodyMesh1"); - mUpperBodyMesh2.setName("mUpperBodyMesh2"); - mUpperBodyMesh3.setName("mUpperBodyMesh3"); - mUpperBodyMesh4.setName("mUpperBodyMesh4"); - - mLowerBodyLOD.setName("mLowerBodyLOD"); - mLowerBodyMesh0.setName("mLowerBodyMesh0"); - mLowerBodyMesh0.setMeshID(MESH_ID_LOWER_BODY); - mLowerBodyMesh1.setName("mLowerBodyMesh1"); - mLowerBodyMesh2.setName("mLowerBodyMesh2"); - mLowerBodyMesh3.setName("mLowerBodyMesh3"); - mLowerBodyMesh4.setName("mLowerBodyMesh4"); - - mEyeBallLeftLOD.setName("mEyeBallLeftLOD"); - mEyeBallLeftMesh0.setName("mEyeBallLeftMesh0"); - mEyeBallLeftMesh1.setName("mEyeBallLeftMesh1"); - - mEyeBallRightLOD.setName("mEyeBallRightLOD"); - mEyeBallRightMesh0.setName("mEyeBallRightMesh0"); - mEyeBallRightMesh1.setName("mEyeBallRightMesh1"); - - mSkirtLOD.setName("mSkirtLOD"); - mSkirtMesh0.setName("mSkirtMesh0"); - mSkirtMesh0.setMeshID(MESH_ID_SKIRT); - mSkirtMesh1.setName("mSkirtMesh1"); - mSkirtMesh2.setName("mSkirtMesh2"); - mSkirtMesh3.setName("mSkirtMesh3"); - mSkirtMesh4.setName("mSkirtMesh4"); - - mSkirtMesh0.setIsTransparent(TRUE); - mSkirtMesh1.setIsTransparent(TRUE); - mSkirtMesh2.setIsTransparent(TRUE); - mSkirtMesh3.setIsTransparent(TRUE); - mSkirtMesh4.setIsTransparent(TRUE); - - // set the pick names for the avatar - mHeadMesh0.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh1.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh2.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh3.setPickName( LLViewerJoint::PN_0 ); - mHeadMesh4.setPickName( LLViewerJoint::PN_0 ); - mEyeLashMesh0.setPickName( LLViewerJoint::PN_0 ); - - mUpperBodyMesh0.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh1.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh2.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh3.setPickName( LLViewerJoint::PN_1 ); - mUpperBodyMesh4.setPickName( LLViewerJoint::PN_1 ); - - mLowerBodyMesh0.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh1.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh2.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh3.setPickName( LLViewerJoint::PN_2 ); - mLowerBodyMesh4.setPickName( LLViewerJoint::PN_2 ); - - mEyeBallLeftMesh0.setPickName( LLViewerJoint::PN_3 ); - mEyeBallLeftMesh1.setPickName( LLViewerJoint::PN_3 ); - mEyeBallRightMesh0.setPickName( LLViewerJoint::PN_3 ); - mEyeBallRightMesh1.setPickName( LLViewerJoint::PN_3 ); - - mHairMesh0.setPickName( LLViewerJoint::PN_4); - mHairMesh1.setPickName( LLViewerJoint::PN_4); - mHairMesh2.setPickName( LLViewerJoint::PN_4); - mHairMesh3.setPickName( LLViewerJoint::PN_4); - mHairMesh4.setPickName( LLViewerJoint::PN_4); - mHairMesh5.setPickName( LLViewerJoint::PN_4); - - mSkirtMesh0.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh1.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh2.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh3.setPickName( LLViewerJoint::PN_5 ); - mSkirtMesh4.setPickName( LLViewerJoint::PN_5 ); - - // material settings - - mEyeBallLeftMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - mEyeBallLeftMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - mEyeBallRightMesh0.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); - mEyeBallRightMesh1.setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); + for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); + iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + iter++) + { + const EMeshIndex mesh_index = iter->first; + const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = iter->second; + + LLViewerJoint* joint = new LLViewerJoint(); + joint->setName(mesh_dict->mName); + joint->setMeshID(mesh_index); + mMeshLOD.push_back(joint); + + /* mHairLOD.setName("mHairLOD"); + mHairMesh0.setName("mHairMesh0"); + mHairMesh0.setMeshID(MESH_ID_HAIR); + mHairMesh1.setName("mHairMesh1"); */ + for (U32 lod = 0; lod < mesh_dict->mLOD; lod++) + { + LLViewerJointMesh* mesh = new LLViewerJointMesh(); + std::string mesh_name = "m" + mesh_dict->mName + boost::lexical_cast<std::string>(lod); + // We pre-pended an m - need to capitalize first character for camelCase + mesh_name[1] = toupper(mesh_name[1]); + mesh->setName(mesh_name); + mesh->setMeshID(mesh_index); + mesh->setPickName(mesh_dict->mPickName); + switch((int)mesh_index) + { + case MESH_ID_HAIR: + mesh->setIsTransparent(TRUE); + break; + case MESH_ID_SKIRT: + mesh->setIsTransparent(TRUE); + break; + case MESH_ID_EYEBALL_LEFT: + case MESH_ID_EYEBALL_RIGHT: + mesh->setSpecular( LLColor4( 1.0f, 1.0f, 1.0f, 1.0f ), 1.f ); + break; + } + + joint->mMeshParts.push_back(mesh); + } + } + + //------------------------------------------------------------------------- + // associate baked textures with meshes + //------------------------------------------------------------------------- + for (LLVOAvatarDictionary::mesh_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); + iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + iter++) + { + const EMeshIndex mesh_index = iter->first; + const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = iter->second; + const EBakedTextureIndex baked_texture_index = mesh_dict->mBakedID; + + // Skip it if there's no associated baked texture. + 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++) + { + LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter; + mBakedTextureData[(int)baked_texture_index].mMeshes.push_back(mesh); + } + } + //------------------------------------------------------------------------- // register motions @@ -987,20 +999,11 @@ LLVOAvatar::~LLVOAvatar() mNumJoints = 0; - delete mHeadLayerSet; - mHeadLayerSet = NULL; - - delete mUpperBodyLayerSet; - mUpperBodyLayerSet = NULL; - - delete mLowerBodyLayerSet; - mLowerBodyLayerSet = NULL; - - delete mEyesLayerSet; - mEyesLayerSet = NULL; - - delete mSkirtLayerSet; - mSkirtLayerSet = NULL; + for (U32 i = 0; i < mBakedTextureData.size(); i++) + { + delete mBakedTextureData[i].mTexLayerSet; + mBakedTextureData[i].mTexLayerSet = NULL; + } std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); mAttachmentPoints.clear(); @@ -1014,6 +1017,16 @@ LLVOAvatar::~LLVOAvatar() std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); mMeshes.clear(); + + for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); jointIter++) + { + LLViewerJoint* joint = (LLViewerJoint *) *jointIter; + std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); + joint->mMeshParts.clear(); + } + std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); + mMeshLOD.clear(); mDead = TRUE; @@ -1045,45 +1058,34 @@ BOOL LLVOAvatar::isFullyBaked() { if (mIsDummy) return TRUE; if (getNumTEs() == 0) return FALSE; - - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - if (isWearingWearableType(WT_SKIRT)) - { - return head_baked && upper_baked && lower_baked && eyes_baked && skirt_baked; - } - else + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return head_baked && upper_baked && lower_baked && eyes_baked; + if (!isTextureDefined(mBakedTextureData[i].mTextureIndex) + && ( (i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ) ) + { + return FALSE; + } } + return TRUE; } -void LLVOAvatar::deleteLayerSetCaches() +void LLVOAvatar::deleteLayerSetCaches(bool clearAll) { - if( mHeadLayerSet ) mHeadLayerSet->deleteCaches(); - if( mUpperBodyLayerSet ) mUpperBodyLayerSet->deleteCaches(); - if( mLowerBodyLayerSet ) mLowerBodyLayerSet->deleteCaches(); - if( mEyesLayerSet ) mEyesLayerSet->deleteCaches(); - if( mSkirtLayerSet ) mSkirtLayerSet->deleteCaches(); - - if(mUpperMaskTexName) - { - glDeleteTextures(1, (GLuint*)&mUpperMaskTexName); - mUpperMaskTexName = 0 ; - } - if(mHeadMaskTexName) - { - glDeleteTextures(1, (GLuint*)&mHeadMaskTexName); - mHeadMaskTexName = 0 ; - } - if(mLowerMaskTexName) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - glDeleteTextures(1, (GLuint*)&mLowerMaskTexName); - mLowerMaskTexName = 0 ; + if (mBakedTextureData[i].mTexLayerSet) + { + if ((i != BAKED_HAIR || mIsSelf) && !clearAll) // Backwards compatibility - can be removed after hair baking is mandatory on the grid + { + mBakedTextureData[i].mTexLayerSet->deleteCaches(); + } + } + if (mBakedTextureData[i].mMaskTexName) + { + glDeleteTextures(1, (GLuint*)&(mBakedTextureData[i].mMaskTexName)); + mBakedTextureData[i].mMaskTexName = 0 ; + } } } @@ -1154,7 +1156,7 @@ void LLVOAvatar::dumpBakedStatus() llcont << " DEAD ("<< inst->getNumRefs() << " refs)"; } - if( inst->mIsSelf ) + if( inst->isSelf() ) { llcont << " (self)"; } @@ -1181,130 +1183,26 @@ void LLVOAvatar::dumpBakedStatus() else { llcont << " Unbaked ("; - if( inst->getTEImage( TEX_HEAD_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " head"; - } - - if( inst->getTEImage( TEX_UPPER_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " upper"; - } - - if( inst->getTEImage( TEX_LOWER_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " lower"; - } - - if( inst->getTEImage( TEX_EYES_BAKED )->getID() == IMG_DEFAULT_AVATAR ) - { - llcont << " eyes"; - } - - if (inst->isWearingWearableType(WT_SKIRT)) + + for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + iter++) { - if( inst->getTEImage( TEX_SKIRT_BAKED )->getID() == IMG_DEFAULT_AVATAR ) + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second; + const ETextureIndex index = baked_dict->mTextureIndex; + if (!inst->isTextureDefined(index)) { - llcont << " skirt"; + llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName; } } - llcont << " ) " << inst->getUnbakedPixelAreaRank() << "/" << LLVOAvatar::sMaxOtherAvatarsToComposite; + llcont << " ) " << inst->getUnbakedPixelAreaRank(); if( inst->isCulled() ) { llcont << " culled"; } } llcont << llendl; -/* - if( inst->isDead() ) - { - llinfos << "DEAD LIST " << llendl; - - - for( S32 i = 0; i < inst->mOwners.count(); i++ ) - { - llinfos << i << llendl; - LLPointer<LLViewerObject>* owner = (LLPointer<LLViewerObject>*)(inst->mOwners[i]); - LLPointer<LLViewerObject>* cur; - if( !owner->mName.isEmpty() ) - { - llinfos << " " << owner->mName << llendl; - } - - LLViewerObject* key_vo; - for( key_vo = gObjectList.mActiveObjects.getFirstKey(); key_vo; key_vo = gObjectList.mActiveObjects.getNextKey() ) - { - cur = &(gObjectList.mActiveObjects.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mActiveObjects" << llendl; - } - } - - for( key_vo = gObjectList.mAvatarObjects.getFirstKey(); key_vo; key_vo = gObjectList.mAvatarObjects.getNextKey() ) - { - cur = &(gObjectList.mAvatarObjects.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mAvatarObjects" << llendl; - } - } - - LLUUID id; - for( id = gObjectList.mDeadObjects.getFirstKey(); id; id = gObjectList.mDeadObjects.getNextKey() ) - { - cur = &(gObjectList.mDeadObjects.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mDeadObjects" << llendl; - } - } - - - for( id = gObjectList.mUUIDObjectMap.getFirstKey(); id; id = gObjectList.mUUIDObjectMap.getNextKey() ) - { - cur = &(gObjectList.mUUIDObjectMap.getCurrentDataWithoutIncrement()); - if( cur == owner ) - { - llinfos << " gObjectList.mUUIDObjectMap" << llendl; - } - } - - S32 j; - S32 k; - for( j = 0; j < 16; j++ ) - { - for( k = 0; k < 10; k++ ) - { - cur = &(gObjectList.mCloseObjects[j][k]); - if( cur == owner ) - { - llinfos << " gObjectList.mCloseObjects" << llendl; - } - } - } - - for( j = 0; j < gObjectList.mObjects.count(); j++ ) - { - cur = &(gObjectList.mObjects[j]); - if( cur == owner ) - { - llinfos << " gObjectList.mObjects" << llendl; - } - } - - for( j = 0; j < gObjectList.mMapObjects.count(); j++ ) - { - cur = &(gObjectList.mMapObjects[j]); - if( cur == owner ) - { - llinfos << " gObjectList.mMapObjects" << llendl; - } - } - } - } - */ } } @@ -1316,11 +1214,10 @@ void LLVOAvatar::restoreGL() { LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->setCompositeUpdatesEnabled( TRUE ); - inst->invalidateComposite( inst->mHeadLayerSet, FALSE ); - inst->invalidateComposite( inst->mLowerBodyLayerSet, FALSE ); - inst->invalidateComposite( inst->mUpperBodyLayerSet, FALSE ); - inst->invalidateComposite( inst->mEyesLayerSet, FALSE ); - inst->invalidateComposite( inst->mSkirtLayerSet, FALSE ); + for (U32 i = 0; i < inst->mBakedTextureData.size(); i++) + { + inst->invalidateComposite( inst->mBakedTextureData[i].mTexLayerSet, FALSE ); + } inst->updateMeshTextures(); } } @@ -1345,7 +1242,7 @@ void LLVOAvatar::resetImpostors() } // static -void LLVOAvatar::deleteCachedImages() +void LLVOAvatar::deleteCachedImages(bool clearAll) { if (LLTexLayerSet::sHasCaches) { @@ -1354,12 +1251,12 @@ void LLVOAvatar::deleteCachedImages() iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; - inst->deleteLayerSetCaches(); + inst->deleteLayerSetCaches(clearAll); } LLTexLayerSet::sHasCaches = FALSE; } - for( LLGLuint * namep = sScratchTexNames.getFirstData(); + for( LLGLuint* namep = sScratchTexNames.getFirstData(); namep; namep = sScratchTexNames.getNextData() ) { @@ -1387,8 +1284,6 @@ void LLVOAvatar::deleteCachedImages() //------------------------------------------------------------------------ void LLVOAvatar::initClass() { - LLVOAvatar::sMaxOtherAvatarsToComposite = gSavedSettings.getS32("AvatarCompositeLimit"); - std::string xmlFile; xmlFile = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR) + "_lad.xml"; @@ -1452,44 +1347,45 @@ void LLVOAvatar::initClass() // Process XML data // avatar_skeleton.xml - llassert(!sSkeletonInfo); - sSkeletonInfo = new LLVOAvatarSkeletonInfo; - if (!sSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) + llassert(!sAvatarSkeletonInfo); + sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) { llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; } // parse avatar_lad.xml - llassert(!sAvatarInfo); - sAvatarInfo = new LLVOAvatarInfo; - if (!sAvatarInfo->parseXmlSkeletonNode(root)) + llassert(!sAvatarXmlInfo); + sAvatarXmlInfo = new LLVOAvatarXmlInfo; + if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlMeshNodes(root)) + if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlColorNodes(root)) + if (!sAvatarXmlInfo->parseXmlColorNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlLayerNodes(root)) + if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } - if (!sAvatarInfo->parseXmlDriverNodes(root)) + if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) { llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } + } void LLVOAvatar::cleanupClass() { - delete sAvatarInfo; - sAvatarInfo = NULL; - delete sSkeletonInfo; - sSkeletonInfo = NULL; + delete sAvatarXmlInfo; + sAvatarXmlInfo = NULL; + delete sAvatarSkeletonInfo; + sAvatarSkeletonInfo = NULL; sSkeletonXMLTree.cleanup(); sXMLTree.cleanup(); } @@ -1552,7 +1448,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) newMax = pos + buffer; //stretch bounding box by joint positions - for (mesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i) + for (polymesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i) { LLPolyMesh* mesh = i->second; for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++) @@ -1571,7 +1467,7 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) { LLViewerJointAttachment* attachment = iter->second; - if(!attachment->getValid()) + if (!attachment->getValid()) { continue ; } @@ -1688,7 +1584,6 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e return FALSE; } - //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- @@ -1732,7 +1627,7 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename) //----------------------------------------------------------------------------- // setupBone() //----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) +BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -1740,7 +1635,7 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) if (info->mIsJoint) { - joint = (LLViewerJoint*)getCharacterJoint(sCurJoint); + joint = (LLViewerJoint*)getCharacterJoint(joint_num); if (!joint) { llwarns << "Too many bones" << llendl; @@ -1750,12 +1645,12 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) } else // collision volume { - if (sCurVolume >= (S32)mNumCollisionVolumes) + if (volume_num >= (S32)mNumCollisionVolumes) { llwarns << "Too many bones" << llendl; return FALSE; } - joint = (LLViewerJoint*)(&mCollisionVolumes[sCurVolume]); + joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); joint->setName( info->mName ); } @@ -1777,19 +1672,19 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) if (info->mIsJoint) { joint->setSkinOffset( info->mPivot ); - sCurJoint++; + joint_num++; } else // collision volume { - sCurVolume++; + volume_num++; } // setup children - LLVOAvatarBoneInfo::child_list_t::iterator iter; + LLVOAvatarBoneInfo::child_list_t::const_iterator iter; for (iter = info->mChildList.begin(); iter != info->mChildList.end(); iter++) { LLVOAvatarBoneInfo *child_info = *iter; - if (!setupBone(child_info, joint)) + if (!setupBone(child_info, joint, volume_num, joint_num)) { return FALSE; } @@ -1801,7 +1696,7 @@ BOOL LLVOAvatar::setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent) //----------------------------------------------------------------------------- // buildSkeleton() //----------------------------------------------------------------------------- -BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info) +BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) { LLMemType mt(LLMemType::MTYPE_AVATAR); @@ -1826,14 +1721,13 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info) } } - sCurJoint = 0; - sCurVolume = 0; - - LLVOAvatarSkeletonInfo::bone_info_list_t::iterator iter; + 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++) { LLVOAvatarBoneInfo *info = *iter; - if (!setupBone(info, NULL)) + if (!setupBone(info, NULL, current_volume_num, current_joint_num)) { llerrs << "Error parsing bone in skeleton file" << llendl; return FALSE; @@ -1899,43 +1793,17 @@ void LLVOAvatar::buildCharacter() //------------------------------------------------------------------------- // clear mesh data //------------------------------------------------------------------------- - mHairMesh0.setMesh(NULL); - mHairMesh1.setMesh(NULL); - mHairMesh2.setMesh(NULL); - mHairMesh3.setMesh(NULL); - mHairMesh4.setMesh(NULL); - mHairMesh5.setMesh(NULL); - - mHeadMesh0.setMesh(NULL); - mHeadMesh1.setMesh(NULL); - mHeadMesh2.setMesh(NULL); - mHeadMesh3.setMesh(NULL); - mHeadMesh4.setMesh(NULL); - - mEyeLashMesh0.setMesh(NULL); - - mUpperBodyMesh0.setMesh(NULL); - mUpperBodyMesh1.setMesh(NULL); - mUpperBodyMesh2.setMesh(NULL); - mUpperBodyMesh3.setMesh(NULL); - mUpperBodyMesh4.setMesh(NULL); - - mLowerBodyMesh0.setMesh(NULL); - mLowerBodyMesh1.setMesh(NULL); - mLowerBodyMesh2.setMesh(NULL); - mLowerBodyMesh3.setMesh(NULL); - mLowerBodyMesh4.setMesh(NULL); - - mEyeBallLeftMesh0.setMesh(NULL); - mEyeBallLeftMesh1.setMesh(NULL); - mEyeBallRightMesh0.setMesh(NULL); - mEyeBallRightMesh1.setMesh(NULL); - - mSkirtMesh0.setMesh(NULL); - mSkirtMesh1.setMesh(NULL); - mSkirtMesh2.setMesh(NULL); - mSkirtMesh3.setMesh(NULL); - mSkirtMesh4.setMesh(NULL); + for (std::vector<LLViewerJoint*>::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); jointIter++) + { + LLViewerJoint* joint = (LLViewerJoint*) *jointIter; + for (std::vector<LLViewerJointMesh*>::iterator meshIter = joint->mMeshParts.begin(); + meshIter != joint->mMeshParts.end(); meshIter++) + { + LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter; + mesh->setMesh(NULL); + } + } //------------------------------------------------------------------------- // (re)load our skeleton and meshes @@ -2046,7 +1914,12 @@ void LLVOAvatar::buildCharacter() } startDefaultMotions(); - + + //------------------------------------------------------------------------- + // restart any currently active motions + //------------------------------------------------------------------------- + processAnimationStateChanges(); + mIsBuilt = TRUE; stop_glerror(); @@ -2260,21 +2133,18 @@ void LLVOAvatar::releaseMeshData() //llinfos << "Releasing" << llendl; // cleanup mesh data - mHairLOD.setValid(FALSE, TRUE); - mHeadLOD.setValid(FALSE, TRUE); - mEyeLashLOD.setValid(FALSE, TRUE); - mUpperBodyLOD.setValid(FALSE, TRUE); - mLowerBodyLOD.setValid(FALSE, TRUE); - mEyeBallLeftLOD.setValid(FALSE, TRUE); - mEyeBallRightLOD.setValid(FALSE, TRUE); - mSkirtLOD.setValid(FALSE, TRUE); + for (std::vector<LLViewerJoint*>::iterator iter = mMeshLOD.begin(); + iter != mMeshLOD.end(); iter++) + { + LLViewerJoint* joint = (LLViewerJoint*) *iter; + joint->setValid(FALSE, TRUE); + } //cleanup data if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); facep->setSize(0, 0); - for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) { facep = mDrawable->getFace(i); @@ -2337,34 +2207,25 @@ void LLVOAvatar::updateMeshData() { stop_glerror(); - LLViewerJoint* av_parts[8] ; - av_parts[0] = &mEyeBallLeftLOD ; - av_parts[1] = &mEyeBallRightLOD ; - av_parts[2] = &mEyeLashLOD ; - av_parts[3] = &mHeadLOD ; - av_parts[4] = &mLowerBodyLOD ; - av_parts[5] = &mSkirtLOD ; - av_parts[6] = &mUpperBodyLOD ; - av_parts[7] = &mHairLOD ; - S32 f_num = 0 ; const U32 VERTEX_NUMBER_THRESHOLD = 128 ;//small number of this means each part of an avatar has its own vertex buffer. + const S32 num_parts = mMeshLOD.size(); // this order is determined by number of LODS // if a mesh earlier in this list changed LODs while a later mesh doesn't, // the later mesh's index offset will be inaccurate - for(S32 part_index = 0 ; part_index < 8 ;) + for(S32 part_index = 0 ; part_index < num_parts ;) { S32 j = part_index ; U32 last_v_num = 0, num_vertices = 0 ; U32 last_i_num = 0, num_indices = 0 ; - while(part_index < 8 && num_vertices < VERTEX_NUMBER_THRESHOLD) + while(part_index < num_parts && num_vertices < VERTEX_NUMBER_THRESHOLD) { last_v_num = num_vertices ; last_i_num = num_indices ; - av_parts[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mMeshLOD[part_index++]->updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); } if(num_vertices < 1)//skip empty meshes { @@ -2412,7 +2273,7 @@ void LLVOAvatar::updateMeshData() for(S32 k = j ; k < part_index ; k++) { - av_parts[k]->updateFaceData(facep, mAdjustedPixelArea, (k == 7)); + mMeshLOD[k]->updateFaceData(facep, mAdjustedPixelArea, k == MESH_ID_HAIR); } stop_glerror(); @@ -2536,27 +2397,6 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, //llinfos << getRotation() << llendl; //llinfos << getPosition() << llendl; - if (update_type == OUT_FULL ) - { - if( !mIsSelf || !mFirstTEMessageReceived ) - { -// dumpAvatarTEs( "PRE processUpdateMessage()" ); - unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); -// dumpAvatarTEs( "POST processUpdateMessage()" ); - - if( !mFirstTEMessageReceived ) - { - onFirstTEMessageReceived(); - } - - // Disable updates to composites. We'll decide whether we need to do - // any updates after we find out whether this update message has any - // "baked" (pre-composited) textures. - setCompositeUpdatesEnabled( FALSE ); - updateMeshTextures(); - setCompositeUpdatesEnabled( TRUE ); - } - } return retval; } @@ -2566,7 +2406,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) { // The core setTETexture() method requests images, so we need // to redirect certain avatar texture requests to different sims. - if (isTextureIndexBaked(te)) + if (isIndexBakedTexture((ETextureIndex)te)) { LLHost target_host = getObjectHost(); return setTETextureCore(te, uuid, target_host); @@ -2865,15 +2705,12 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } } - if (mDrawable.notNull()) + mDrawable->movePartition(); + + //force a move if sitting on an active object + if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) { - mDrawable->movePartition(); - - //force a move if sitting on an active object - if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) - { - gPipeline.markMoved(mDrawable, TRUE); - } + gPipeline.markMoved(mDrawable, TRUE); } } @@ -3765,7 +3602,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) F32 root_roll, root_pitch, root_yaw; root_rotation.getEulerAngles(&root_roll, &root_pitch, &root_yaw); - if (gDebugAvatarRotation) + if (sDebugAvatarRotation) { llinfos << "root_roll " << RAD_TO_DEG * root_roll << " root_pitch " << RAD_TO_DEG * root_pitch @@ -3955,7 +3792,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); const F32 STEP_VOLUME = 0.5f; - LLUUID& step_sound_id = getStepSound(); + const LLUUID& step_sound_id = getStepSound(); LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); @@ -4189,19 +4026,19 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (mNeedsSkin) { //generate animated mesh - mLowerBodyLOD.updateJointGeometry(); - mUpperBodyLOD.updateJointGeometry(); + mMeshLOD[MESH_ID_LOWER_BODY]->updateJointGeometry(); + mMeshLOD[MESH_ID_UPPER_BODY]->updateJointGeometry(); if( isWearingWearableType( WT_SKIRT ) ) { - mSkirtLOD.updateJointGeometry(); + mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry(); } if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - mEyeLashLOD.updateJointGeometry(); - mHeadLOD.updateJointGeometry(); - mHairLOD.updateJointGeometry(); + mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry(); + mMeshLOD[MESH_ID_HEAD]->updateJointGeometry(); + mMeshLOD[MESH_ID_HAIR]->updateJointGeometry(); } mNeedsSkin = FALSE; @@ -4289,7 +4126,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) gGL.flush(); } //-------------------------------------------------------------------- - // render all geomety attached to the skeleton + // render all geometry attached to the skeleton //-------------------------------------------------------------------- static LLStat render_stat; @@ -4297,18 +4134,42 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { + bool should_alpha_mask = mHasBakedHair && isTextureDefined(TEX_HEAD_BAKED) && isTextureDefined(TEX_UPPER_BAKED) + && isTextureDefined(TEX_LOWER_BAKED) && mBakedTextureData[BAKED_HEAD].mIsLoaded + && mBakedTextureData[BAKED_UPPER].mIsLoaded && mBakedTextureData[BAKED_LOWER].mIsLoaded; + LLGLState test(GL_ALPHA_TEST, should_alpha_mask); + + if (should_alpha_mask) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + } + BOOL first_pass = TRUE; if (!LLDrawPoolAvatar::sSkipOpaque) { if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - num_indices += mHeadLOD.render(mAdjustedPixelArea); + if (isTextureVisible(TEX_HEAD_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea); + first_pass = FALSE; + } + } + if (isTextureVisible(TEX_UPPER_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass); + first_pass = FALSE; + } + + if (isTextureVisible(TEX_LOWER_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass); first_pass = FALSE; } - num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); - num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); } + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { LLGLEnable blend(GL_BLEND); @@ -4329,10 +4190,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) U32 LLVOAvatar::renderTransparent(BOOL first_pass) { U32 num_indices = 0; - if( isWearingWearableType( WT_SKIRT ) ) + if( isWearingWearableType( WT_SKIRT ) && isTextureVisible(TEX_SKIRT_BAKED) ) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); - num_indices += mSkirtLOD.render(mAdjustedPixelArea, FALSE); + num_indices += mMeshLOD[MESH_ID_SKIRT]->render(mAdjustedPixelArea, FALSE); first_pass = FALSE; gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } @@ -4343,8 +4204,17 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } - num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass); - num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE); + + if (isTextureVisible(TEX_HEAD_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_EYELASH]->render(mAdjustedPixelArea, first_pass); + first_pass = FALSE; + } + if (isTextureVisible(TEX_HAIR_BAKED)) + { + num_indices += mMeshLOD[MESH_ID_HAIR]->render(mAdjustedPixelArea, first_pass); + first_pass = FALSE; + } if (LLPipeline::sImpostorRender) { gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); @@ -4376,8 +4246,22 @@ U32 LLVOAvatar::renderRigid() return 0; } - num_indices += mEyeBallLeftLOD.render(mAdjustedPixelArea); - num_indices += mEyeBallRightLOD.render(mAdjustedPixelArea); + if (isTextureVisible(TEX_EYES_BAKED)) + { + // If the meshes need to be drawn, enable alpha masking but not blending + bool should_alpha_mask = mHasBakedHair && mBakedTextureData[BAKED_EYES].mIsLoaded; + 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); + num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea); + + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } return num_indices; } @@ -4400,6 +4284,13 @@ U32 LLVOAvatar::renderFootShadows() { 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()) @@ -4470,12 +4361,6 @@ void LLVOAvatar::updateTextures(LLAgent &agent) { return; } - - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); if( mIsSelf ) { @@ -4486,30 +4371,18 @@ void LLVOAvatar::updateTextures(LLAgent &agent) render_avatar = isVisible() && !mCulled; } - // bind the texture so that they'll be decoded - // slightly inefficient, we can short-circuit this - // if we have to - if( render_avatar && !gGLManager.mIsDisabled ) + std::vector<bool> layer_baked; + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - if( head_baked && ! mHeadBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_HEAD_BAKED )); - } - if( upper_baked && ! mUpperBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_UPPER_BAKED )); - } - if( lower_baked && ! mLowerBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_LOWER_BAKED )); - } - if( eyes_baked && ! mEyesBakedLoaded ) - { - gGL.getTexUnit(0)->bind(getTEImage( TEX_EYES_BAKED )); - } - if( skirt_baked && ! mSkirtBakedLoaded ) + layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex)); + // bind the texture so that they'll be decoded slightly + // inefficient, we can short-circuit this if we have to + if( render_avatar && !gGLManager.mIsDisabled ) { - gGL.getTexUnit(0)->bind(getTEImage( TEX_SKIRT_BAKED )); + if (layer_baked[i] && !mBakedTextureData[i].mIsLoaded) + { + gGL.getTexUnit(0)->bind(getTEImage( mBakedTextureData[i].mTextureIndex )); + } } } @@ -4541,9 +4414,9 @@ void LLVOAvatar::updateTextures(LLAgent &agent) mMaxPixelArea = 0.f; mMinPixelArea = 99999999.f; mHasGrey = FALSE; // debug - for (U32 i = 0; i < getNumTEs(); i++) + for (U32 index = 0; index < getNumTEs(); index++) { - LLViewerImage *imagep = getTEImage(i); + LLViewerImage *imagep = getTEImage(index); if (imagep) { // Debugging code - maybe non-self avatars are downloading textures? @@ -4555,131 +4428,39 @@ void LLVOAvatar::updateTextures(LLAgent &agent) // << " desired " << imagep->getDesiredDiscardLevel() // << llendl; - const LLTextureEntry *te = getTE(i); + const LLTextureEntry *te = getTE(index); F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); S32 boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_BAKED_SELF : LLViewerImage::BOOST_AVATAR_BAKED; // Spam if this is a baked texture, not set to default image, without valid host info - if (isTextureIndexBaked(i) + if (isIndexBakedTexture((ETextureIndex)index) && imagep->getID() != IMG_DEFAULT_AVATAR && !imagep->getTargetHost().isOk()) { - llwarns << "LLVOAvatar::updateTextures No host for texture " + LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture " << imagep->getID() << " for avatar " << (mIsSelf ? "<myself>" : getID().asString()) << " on host " << getRegion()->getHost() << llendl; } - - switch( i ) - { - // Head - case TEX_HEAD_BODYPAINT: - addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); - break; - - // Upper - case TEX_UPPER_JACKET: - addLocalTextureStats( LOCTEX_UPPER_JACKET, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_SHIRT: - addLocalTextureStats( LOCTEX_UPPER_SHIRT, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_GLOVES: - addLocalTextureStats( LOCTEX_UPPER_GLOVES, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_UNDERSHIRT: - addLocalTextureStats( LOCTEX_UPPER_UNDERSHIRT, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - - case TEX_UPPER_BODYPAINT: - addLocalTextureStats( LOCTEX_UPPER_BODYPAINT, imagep, texel_area_ratio, render_avatar, upper_baked ); - break; - // Lower - case TEX_LOWER_JACKET: - addLocalTextureStats( LOCTEX_LOWER_JACKET, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_PANTS: - addLocalTextureStats( LOCTEX_LOWER_PANTS, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_SHOES: - addLocalTextureStats( LOCTEX_LOWER_SHOES, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_SOCKS: - addLocalTextureStats( LOCTEX_LOWER_SOCKS, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_UNDERPANTS: - addLocalTextureStats( LOCTEX_LOWER_UNDERPANTS, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - case TEX_LOWER_BODYPAINT: - addLocalTextureStats( LOCTEX_LOWER_BODYPAINT, imagep, texel_area_ratio, render_avatar, lower_baked ); - break; - - // Eyes - case TEX_EYES_IRIS: - addLocalTextureStats( LOCTEX_EYES_IRIS, imagep, texel_area_ratio, render_avatar, eyes_baked ); - break; - - // Skirt - case TEX_SKIRT: - addLocalTextureStats( LOCTEX_SKIRT, imagep, texel_area_ratio, render_avatar, skirt_baked ); - break; - - // Baked - case TEX_HEAD_BAKED: - if (head_baked) - { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - break; - - case TEX_UPPER_BAKED: - if (upper_baked) - { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - break; - - case TEX_LOWER_BAKED: - if (lower_baked) - { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - } - break; - - case TEX_EYES_BAKED: - if (eyes_baked) + /* switch(index) + case TEX_HEAD_BODYPAINT: + addLocalTextureStats( LOCTEX_HEAD_BODYPAINT, imagep, texel_area_ratio, render_avatar, head_baked ); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)index); + if (texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + if (texture_dict->mIsLocalTexture) { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + addLocalTextureStats((ETextureIndex)index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]); } - break; - - case TEX_SKIRT_BAKED: - if (skirt_baked) + else if (texture_dict->mIsBakedTexture) { - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + if (layer_baked[baked_index]) + { + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); + } } - break; - - case TEX_HAIR: - // Hair is neither a local texture used for baking, nor the output - // of the baking process. It's just a texture that happens to be - // used to draw avatars. Hence BOOST_AVATAR. JC - boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_SELF : LLViewerImage::BOOST_AVATAR; - addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); - break; - - default: - llassert(0); - break; } } } @@ -4696,22 +4477,24 @@ void LLVOAvatar::updateTextures(LLAgent &agent) } -void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerImage* imagep, +void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerImage* imagep, F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked ) { + if (!isIndexLocalTexture(idx)) return; + if (!covered_by_baked && render_avatar) // render_avatar is always true if mIsSelf { - if (mLocalTexture[ idx ].notNull() && mLocalTexture[idx]->getID() != IMG_DEFAULT_AVATAR) + if (getLocalTextureID(idx) != IMG_DEFAULT_AVATAR) { F32 desired_pixels; if( mIsSelf ) { - desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_SELF ); + desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF); } else { - desired_pixels = llmin(mPixelArea, (F32)LOCTEX_IMAGE_AREA_OTHER ); + desired_pixels = llmin(mPixelArea, (F32)TEX_IMAGE_AREA_OTHER ); imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR); } imagep->addTextureStats( desired_pixels / texel_area_ratio ); @@ -4722,11 +4505,8 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma } else { - if (mLocalTexture[idx]->getID() == IMG_DEFAULT_AVATAR) - { - // texture asset is missing - mHasGrey = TRUE; // for statistics gathering - } + // texture asset is missing + mHasGrey = TRUE; // for statistics gathering } } } @@ -4794,7 +4574,7 @@ void LLVOAvatar::resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos //----------------------------------------------------------------------------- // getStepSound() //----------------------------------------------------------------------------- -LLUUID& LLVOAvatar::getStepSound() +const LLUUID& LLVOAvatar::getStepSound() const { if ( mStepOnLand ) { @@ -5232,7 +5012,7 @@ F32 LLVOAvatar::getPixelArea() const //----------------------------------------------------------------------------- LLPolyMesh* LLVOAvatar::getHeadMesh() { - return mHeadMesh0.getMesh(); + return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh(); } @@ -5241,7 +5021,7 @@ LLPolyMesh* LLVOAvatar::getHeadMesh() //----------------------------------------------------------------------------- LLPolyMesh* LLVOAvatar::getUpperBodyMesh() { - return mUpperBodyMesh0.getMesh(); + return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh(); } @@ -5340,7 +5120,7 @@ BOOL LLVOAvatar::loadAvatar() // LLFastTimer t(LLFastTimer::FTM_LOAD_AVATAR); // avatar_skeleton.xml - if( !buildSkeleton(sSkeletonInfo) ) + if( !buildSkeleton(sAvatarSkeletonInfo) ) { llwarns << "avatar file: buildSkeleton() failed" << llendl; return FALSE; @@ -5361,10 +5141,10 @@ BOOL LLVOAvatar::loadAvatar() } // avatar_lad.xml : <global_color> - if( sAvatarInfo->mTexSkinColorInfo ) + if( sAvatarXmlInfo->mTexSkinColorInfo ) { mTexSkinColor = new LLTexGlobalColor( this ); - if( !mTexSkinColor->setInfo( sAvatarInfo->mTexSkinColorInfo ) ) + if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) { llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl; return FALSE; @@ -5375,10 +5155,10 @@ BOOL LLVOAvatar::loadAvatar() llwarns << "<global_color> name=\"skin_color\" not found" << llendl; return FALSE; } - if( sAvatarInfo->mTexHairColorInfo ) + if( sAvatarXmlInfo->mTexHairColorInfo ) { mTexHairColor = new LLTexGlobalColor( this ); - if( !mTexHairColor->setInfo( sAvatarInfo->mTexHairColorInfo ) ) + if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) { llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl; return FALSE; @@ -5389,10 +5169,10 @@ BOOL LLVOAvatar::loadAvatar() llwarns << "<global_color> name=\"hair_color\" not found" << llendl; return FALSE; } - if( sAvatarInfo->mTexEyeColorInfo ) + if( sAvatarXmlInfo->mTexEyeColorInfo ) { mTexEyeColor = new LLTexGlobalColor( this ); - if( !mTexEyeColor->setInfo( sAvatarInfo->mTexEyeColorInfo ) ) + if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) { llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl; return FALSE; @@ -5405,15 +5185,15 @@ BOOL LLVOAvatar::loadAvatar() } // avatar_lad.xml : <layer_set> - if (sAvatarInfo->mLayerInfoList.empty()) + if (sAvatarXmlInfo->mLayerInfoList.empty()) { llwarns << "avatar file: missing <layer_set> node" << llendl; } else { - LLVOAvatarInfo::layer_info_list_t::iterator iter; - for (iter = sAvatarInfo->mLayerInfoList.begin(); - iter != sAvatarInfo->mLayerInfoList.end(); iter++) + LLVOAvatarXmlInfo::layer_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mLayerInfoList.begin(); + iter != sAvatarXmlInfo->mLayerInfoList.end(); iter++) { LLTexLayerSetInfo *info = *iter; LLTexLayerSet* layer_set = new LLTexLayerSet( this ); @@ -5424,27 +5204,20 @@ BOOL LLVOAvatar::loadAvatar() llwarns << "avatar file: layer_set->parseData() failed" << llendl; return FALSE; } - if( layer_set->isBodyRegion( "head" ) ) + bool found_baked_entry = false; + for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + baked_iter++) { - mHeadLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "upper_body" ) ) - { - mUpperBodyLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "lower_body" ) ) - { - mLowerBodyLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "eyes" ) ) - { - mEyesLayerSet = layer_set; - } - else if( layer_set->isBodyRegion( "skirt" ) ) - { - mSkirtLayerSet = layer_set; + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; + if (layer_set->isBodyRegion(baked_dict->mName)) + { + mBakedTextureData[baked_iter->first].mTexLayerSet = layer_set; + found_baked_entry = true; + break; + } } - else + if (!found_baked_entry) { llwarns << "<layer_set> has invalid body_region attribute" << llendl; delete layer_set; @@ -5455,9 +5228,9 @@ BOOL LLVOAvatar::loadAvatar() // avatar_lad.xml : <driver_parameters> { - LLVOAvatarInfo::driver_info_list_t::iterator iter; - for (iter = sAvatarInfo->mDriverInfoList.begin(); - iter != sAvatarInfo->mDriverInfoList.end(); iter++) + LLVOAvatarXmlInfo::driver_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mDriverInfoList.begin(); + iter != sAvatarXmlInfo->mDriverInfoList.end(); iter++) { LLDriverParamInfo *info = *iter; LLDriverParam* driver_param = new LLDriverParam( this ); @@ -5484,78 +5257,44 @@ BOOL LLVOAvatar::loadSkeletonNode () { mRoot.addChild( &mSkeleton[0] ); - mRoot.addChild( &mHeadLOD ); - mHeadLOD.mUpdateXform = FALSE; - mHeadLOD.addChild( &mHeadMesh0 ); - mHeadLOD.addChild( &mHeadMesh1 ); - mHeadLOD.addChild( &mHeadMesh2 ); - mHeadLOD.addChild( &mHeadMesh3 ); - mHeadLOD.addChild( &mHeadMesh4 ); - - mRoot.addChild( &mEyeLashLOD ); - mEyeLashLOD.mUpdateXform = FALSE; - mEyeLashLOD.addChild( &mEyeLashMesh0 ); - - mRoot.addChild( &mUpperBodyLOD ); - mUpperBodyLOD.mUpdateXform = FALSE; - mUpperBodyLOD.addChild( &mUpperBodyMesh0 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh1 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh2 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh3 ); - mUpperBodyLOD.addChild( &mUpperBodyMesh4 ); - - mRoot.addChild( &mLowerBodyLOD ); - mLowerBodyLOD.mUpdateXform = FALSE; - mLowerBodyLOD.addChild( &mLowerBodyMesh0 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh1 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh2 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh3 ); - mLowerBodyLOD.addChild( &mLowerBodyMesh4 ); - - mRoot.addChild( &mSkirtLOD ); - mSkirtLOD.mUpdateXform = FALSE; - mSkirtLOD.addChild( &mSkirtMesh0 ); - mSkirtLOD.addChild( &mSkirtMesh1 ); - mSkirtLOD.addChild( &mSkirtMesh2 ); - mSkirtLOD.addChild( &mSkirtMesh3 ); - mSkirtLOD.addChild( &mSkirtMesh4 ); + for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin(); + iter != mMeshLOD.end(); iter++) + { + LLViewerJoint *joint = (LLViewerJoint *) *iter; + joint->mUpdateXform = FALSE; + joint->setMeshesToChildren(); + } + + mRoot.addChild(mMeshLOD[MESH_ID_HEAD]); + mRoot.addChild(mMeshLOD[MESH_ID_EYELASH]); + mRoot.addChild(mMeshLOD[MESH_ID_UPPER_BODY]); + mRoot.addChild(mMeshLOD[MESH_ID_LOWER_BODY]); + mRoot.addChild(mMeshLOD[MESH_ID_SKIRT]); + mRoot.addChild(mMeshLOD[MESH_ID_HEAD]); LLViewerJoint *skull = (LLViewerJoint*)mRoot.findJoint("mSkull"); if (skull) { - skull->addChild( &mHairLOD ); - mHairLOD.mUpdateXform = FALSE; - mHairLOD.addChild( &mHairMesh0 ); - mHairLOD.addChild( &mHairMesh1 ); - mHairLOD.addChild( &mHairMesh2 ); - mHairLOD.addChild( &mHairMesh3 ); - mHairLOD.addChild( &mHairMesh4 ); - mHairLOD.addChild( &mHairMesh5 ); + skull->addChild(mMeshLOD[MESH_ID_HAIR] ); } LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft"); if (eyeL) { - eyeL->addChild( &mEyeBallLeftLOD ); - mEyeBallLeftLOD.mUpdateXform = FALSE; - mEyeBallLeftLOD.addChild( &mEyeBallLeftMesh0 ); - mEyeBallLeftLOD.addChild( &mEyeBallLeftMesh1 ); + eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); } LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight"); if (eyeR) { - eyeR->addChild( &mEyeBallRightLOD ); - mEyeBallRightLOD.mUpdateXform = FALSE; - mEyeBallRightLOD.addChild( &mEyeBallRightMesh0 ); - mEyeBallRightLOD.addChild( &mEyeBallRightMesh1 ); + eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); } // SKELETAL DISTORTIONS { - LLVOAvatarInfo::skeletal_distortion_info_list_t::iterator iter; - for (iter = sAvatarInfo->mSkeletalDistortionInfoList.begin(); - iter != sAvatarInfo->mSkeletalDistortionInfoList.end(); iter++) + LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin(); + iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end(); iter++) { LLPolySkeletalDistortionInfo *info = *iter; LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); @@ -5573,11 +5312,11 @@ BOOL LLVOAvatar::loadSkeletonNode () // ATTACHMENTS { - LLVOAvatarInfo::attachment_info_list_t::iterator iter; - for (iter = sAvatarInfo->mAttachmentInfoList.begin(); - iter != sAvatarInfo->mAttachmentInfoList.end(); iter++) + LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter; + for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin(); + iter != sAvatarXmlInfo->mAttachmentInfoList.end(); iter++) { - LLVOAvatarInfo::LLVOAvatarAttachmentInfo *info = *iter; + LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter; if (!isSelf() && info->mJointName == "mScreen") { //don't process screen joint for other avatars continue; @@ -5654,174 +5393,49 @@ BOOL LLVOAvatar::loadSkeletonNode () //----------------------------------------------------------------------------- BOOL LLVOAvatar::loadMeshNodes() { - LLVOAvatarInfo::mesh_info_list_t::iterator iter; - for (iter = sAvatarInfo->mMeshInfoList.begin(); - iter != sAvatarInfo->mMeshInfoList.end(); iter++) + for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin(); + meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end(); + meshinfo_iter++) { - LLVOAvatarInfo::LLVOAvatarMeshInfo *info = *iter; - std::string &type = info->mType; + const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter; + const std::string &type = info->mType; S32 lod = info->mLOD; LLViewerJointMesh* mesh = NULL; - if (type == "hairMesh") - { - switch (lod) - { - case 0: - mesh = &mHairMesh0; - break; - case 1: - mesh = &mHairMesh1; - break; - case 2: - mesh = &mHairMesh2; - break; - case 3: - mesh = &mHairMesh3; - break; - case 4: - mesh = &mHairMesh4; - break; - case 5: - mesh = &mHairMesh5; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "headMesh") - { - switch (lod) - { + U8 mesh_id = 0; + BOOL found_mesh_id = FALSE; + + /* if (type == "hairMesh") + switch(lod) case 0: - mesh = &mHeadMesh0; - break; - case 1: - mesh = &mHeadMesh1; - break; - case 2: - mesh = &mHeadMesh2; - break; - case 3: - mesh = &mHeadMesh3; - break; - case 4: - mesh = &mHeadMesh4; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "upperBodyMesh") + mesh = &mHairMesh0; */ + for (LLVOAvatarDictionary::mesh_map_t::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin(); + mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end(); + mesh_iter++) { - switch (lod) + const EMeshIndex mesh_index = mesh_iter->first; + const LLVOAvatarDictionary::MeshDictionaryEntry *mesh_dict = mesh_iter->second; + if (type.compare(mesh_dict->mName) == 0) { - case 0: - mesh = &mUpperBodyMesh0; - break; - case 1: - mesh = &mUpperBodyMesh1; - break; - case 2: - mesh = &mUpperBodyMesh2; - break; - case 3: - mesh = &mUpperBodyMesh3; - break; - case 4: - mesh = &mUpperBodyMesh4; + mesh_id = mesh_index; + found_mesh_id = TRUE; break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; } } - else if (type == "lowerBodyMesh") - { - switch (lod) - { - case 0: - mesh = &mLowerBodyMesh0; - break; - case 1: - mesh = &mLowerBodyMesh1; - break; - case 2: - mesh = &mLowerBodyMesh2; - break; - case 3: - mesh = &mLowerBodyMesh3; - break; - case 4: - mesh = &mLowerBodyMesh4; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "skirtMesh") - { - switch (lod) - { - case 0: - mesh = &mSkirtMesh0; - break; - case 1: - mesh = &mSkirtMesh1; - break; - case 2: - mesh = &mSkirtMesh2; - break; - case 3: - mesh = &mSkirtMesh3; - break; - case 4: - mesh = &mSkirtMesh4; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; - } - } - else if (type == "eyelashMesh") - { - mesh = &mEyeLashMesh0; - } - else if (type == "eyeBallLeftMesh") + + if (found_mesh_id) { - switch (lod) + if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) { - case 0: - mesh = &mEyeBallLeftMesh0; - break; - case 1: - mesh = &mEyeBallLeftMesh1; - break; - default: - llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; - return FALSE; + mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; } - } - else if (type == "eyeBallRightMesh") - { - switch (lod) + else { - case 0: - mesh = &mEyeBallRightMesh0; - break; - case 1: - mesh = &mEyeBallRightMesh1; - break; - default: llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl; return FALSE; } } - - if( !mesh ) + else { llwarns << "Ignoring unrecognized mesh type: " << type << llendl; return FALSE; @@ -5837,15 +5451,16 @@ BOOL LLVOAvatar::loadMeshNodes() if (!info->mReferenceMeshName.empty()) { - mesh_map_t::iterator iter = mMeshes.find(info->mReferenceMeshName); - if (iter != mMeshes.end()) + polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName); + if (polymesh_iter != mMeshes.end()) { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, iter->second); + poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second); poly_mesh->setAvatar(this); } else { // This should never happen + LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; } } else @@ -5864,14 +5479,13 @@ BOOL LLVOAvatar::loadMeshNodes() mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); mesh->setMesh( poly_mesh ); - mesh->setLOD( info->mMinPixelArea ); - LLVOAvatarInfo::LLVOAvatarMeshInfo::morph_info_list_t::iterator iter; - for (iter = info->mPolyMorphTargetInfoList.begin(); - iter != info->mPolyMorphTargetInfoList.end(); iter++) + for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin(); + xmlinfo_iter != info->mPolyMorphTargetInfoList.end(); + xmlinfo_iter++) { - LLVOAvatarInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*iter); + const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter); LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); if (!param->setInfo(info_pair->first)) { @@ -5961,7 +5575,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) // We always want to look good to ourselves if( mIsSelf ) { - mPixelArea = llmax( mPixelArea, F32(LOCTEX_IMAGE_SIZE_SELF / 16) ); + mPixelArea = llmax( mPixelArea, F32(TEX_IMAGE_SIZE_SELF / 16) ); } } @@ -6078,7 +5692,7 @@ void LLVOAvatar::updateShadowFaces() // // render avatar shadows // - if (mInAir || mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD) + if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD) { face0p->setSize(0, 0); face1p->setSize(0, 0); @@ -6173,9 +5787,9 @@ void LLVOAvatar::updateShadowFaces() //----------------------------------------------------------------------------- void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user ) { - invalidateComposite( mHeadLayerSet, set_by_user ); - invalidateComposite( mLowerBodyLayerSet, set_by_user ); - invalidateComposite( mUpperBodyLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user ); updateMeshTextures(); } @@ -6188,74 +5802,32 @@ void LLVOAvatar::dirtyMesh() } //----------------------------------------------------------------------------- -// requestLayerSetUpdate() +// hideSkirt() //----------------------------------------------------------------------------- -void LLVOAvatar::requestLayerSetUpdate( LLVOAvatar::ELocTexIndex i ) +void LLVOAvatar::hideSkirt() { - switch( i ) - { - case LOCTEX_HEAD_BODYPAINT: - if( mHeadLayerSet ) - { - mHeadLayerSet->requestUpdate(); - } - break; - - case LOCTEX_UPPER_BODYPAINT: - case LOCTEX_UPPER_SHIRT: - case LOCTEX_UPPER_GLOVES: - case LOCTEX_UPPER_UNDERSHIRT: - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->requestUpdate(); - } - break; - - case LOCTEX_LOWER_BODYPAINT: - case LOCTEX_LOWER_PANTS: - case LOCTEX_LOWER_SHOES: - case LOCTEX_LOWER_SOCKS: - case LOCTEX_LOWER_UNDERPANTS: - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->requestUpdate(); - } - break; - - case LOCTEX_EYES_IRIS: - if( mEyesLayerSet ) - { - mEyesLayerSet->requestUpdate(); - } - break; - - - case LOCTEX_SKIRT: - if( mSkirtLayerSet ) - { - mSkirtLayerSet->requestUpdate(); - } - break; - - - case LOCTEX_UPPER_JACKET: - case LOCTEX_LOWER_JACKET: - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->requestUpdate(); - } + mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE); +} - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->requestUpdate(); - } - break; - case LOCTEX_NUM_ENTRIES: - llerrs << "Bogus texture value " << i << llendl; - break; +//----------------------------------------------------------------------------- +// requestLayerSetUpdate() +//----------------------------------------------------------------------------- +void LLVOAvatar::requestLayerSetUpdate(ETextureIndex index ) +{ + /* switch(index) + case LOCTEX_UPPER_BODYPAINT: + case LOCTEX_UPPER_SHIRT: + if( mUpperBodyLayerSet ) + mUpperBodyLayerSet->requestUpdate(); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) + return; + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + if (mBakedTextureData[baked_index].mTexLayerSet) + { + mBakedTextureData[baked_index].mTexLayerSet->requestUpdate(); } - } void LLVOAvatar::setParent(LLViewerObject* parent) @@ -6616,6 +6188,7 @@ const std::string LLVOAvatar::getAttachedPointName(const LLUUID& inv_item_id) // static // onLocalTextureLoaded() //----------------------------------------------------------------------------- + void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src_raw, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { //llinfos << "onLocalTextureLoaded: " << src_vi->getID() << llendl; @@ -6625,37 +6198,47 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLIm if (success) { LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID); - LLVOAvatar::ELocTexIndex idx = data->mIndex; - if( self && - (!self->mLocalTextureBaked[ idx ]) && - (self->mLocalTexture[ idx ].notNull()) && - (self->mLocalTexture[ idx ]->getID() == src_id) && - (discard_level < self->mLocalTextureDiscard[idx])) - { - self->mLocalTextureDiscard[idx] = discard_level; - self->requestLayerSetUpdate( idx ); - if( self->mIsSelf && gAgent.cameraCustomizeAvatar() ) - { - LLVisualParamHint::requestHintUpdates(); + if (self) + { + ETextureIndex index = data->mIndex; + if (!self->isIndexLocalTexture(index)) return; + LocalTextureData &local_tex_data = self->mLocalTextureData[index]; + if(!local_tex_data.mIsBakedReady && + local_tex_data.mImage.notNull() && + (local_tex_data.mImage->getID() == src_id) && + discard_level < local_tex_data.mDiscard) + { + local_tex_data.mDiscard = discard_level; + if ( self->isSelf() && !gAgent.cameraCustomizeAvatar() ) + { + self->requestLayerSetUpdate( index ); + } + else if( self->isSelf() && gAgent.cameraCustomizeAvatar() ) + { + LLVisualParamHint::requestHintUpdates(); + } + self->updateMeshTextures(); } - self->updateMeshTextures(); } } else if (final) { LLVOAvatar *self = (LLVOAvatar *)gObjectList.findObject(data->mAvatarID); - LLVOAvatar::ELocTexIndex idx = data->mIndex; - // Failed: asset is missing - if( self && - (!self->mLocalTextureBaked[ idx ]) && - (self->mLocalTexture[ idx ].notNull()) && - (self->mLocalTexture[ idx ]->getID() == src_id)) + if (self) { - self->mLocalTextureDiscard[idx] = 0; // we check that it's missing later - self->requestLayerSetUpdate( idx ); - self->updateMeshTextures(); + ETextureIndex index = data->mIndex; + if (!self->isIndexLocalTexture(index)) return; + LocalTextureData &local_tex_data = self->mLocalTextureData[index]; + // Failed: asset is missing + if(!local_tex_data.mIsBakedReady && + local_tex_data.mImage.notNull() && + local_tex_data.mImage->getID() == src_id) + { + local_tex_data.mDiscard = 0; + self->requestLayerSetUpdate( index ); + self->updateMeshTextures(); + } } - } if( final || !success ) @@ -6666,29 +6249,13 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerImage *src_vi, LLIm void LLVOAvatar::updateComposites() { - if( mHeadLayerSet ) - { - mHeadLayerSet->updateComposite(); - } - - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->updateComposite(); - } - - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->updateComposite(); - } - - if( mEyesLayerSet ) - { - mEyesLayerSet->updateComposite(); - } - - if( mSkirtLayerSet && isWearingWearableType( WT_SKIRT )) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mSkirtLayerSet->updateComposite(); + if ( mBakedTextureData[i].mTexLayerSet + && ((i != BAKED_SKIRT) || isWearingWearableType( WT_SKIRT )) ) + { + mBakedTextureData[i].mTexLayerSet->updateComposite(); + } } } @@ -6740,6 +6307,10 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user { layer_name = "eyes"; } + else if (layerset == mHairLayerSet) + { + layer_name = "hair"; + } else if (layerset == mSkirtLayerSet) { layer_name = "skirt"; @@ -6758,47 +6329,52 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user llassert( mIsSelf ); ETextureIndex baked_te = getBakedTE( layerset ); - if( gAgent.cameraCustomizeAvatar() ) - { - mSavedTE[ baked_te ].setNull(); - } - else - { - setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) ); - layerset->requestUpload(); - } + setTEImage( baked_te, gImageList.getImage(IMG_DEFAULT_AVATAR) ); + layerset->requestUpload(); } } +void LLVOAvatar::invalidateAll() +{ + for (U32 i = 0; i < mBakedTextureData.size(); i++) + { + invalidateComposite(mBakedTextureData[i].mTexLayerSet, TRUE); + } + updateMeshTextures(); +} void LLVOAvatar::onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user ) { if( global_color == mTexSkinColor ) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( skin color )" << llendl; - invalidateComposite( mHeadLayerSet, set_by_user ); - invalidateComposite( mUpperBodyLayerSet, set_by_user ); - invalidateComposite( mLowerBodyLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user ); } else if( global_color == mTexHairColor ) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( hair color )" << llendl; - invalidateComposite( mHeadLayerSet, set_by_user ); - - LLColor4 color = mTexHairColor->getColor(); - mHairMesh0.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh1.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh2.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh3.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh4.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh5.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_HAIR].mTexLayerSet, set_by_user ); + + // ! BACKWARDS COMPATIBILITY ! + // Fix for dealing with avatars from viewers that don't bake hair. + if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex)) + { + LLColor4 color = mTexHairColor->getColor(); + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) + { + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + } + } } else if( global_color == mTexEyeColor ) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; - invalidateComposite( mEyesLayerSet, set_by_user ); + invalidateComposite( mBakedTextureData[BAKED_EYES].mTexLayerSet, set_by_user ); } updateMeshTextures(); } @@ -6807,9 +6383,9 @@ void LLVOAvatar::forceBakeAllTextures(bool slam_for_debug) { llinfos << "TAT: forced full rebake. " << llendl; - for (S32 i = 0; i < BAKED_TEXTURE_COUNT; i++) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - ETextureIndex baked_index = sBakedTextureIndices[i]; + ETextureIndex baked_index = mBakedTextureData[i].mTextureIndex; LLTexLayerSet* layer_set = getLayerSet(baked_index); if (layer_set) { @@ -6846,20 +6422,30 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**) // If this is a texture corresponding to one of our baked entries, // just rebake that layer set. BOOL found = FALSE; - for (S32 i = 0; i < BAKED_TEXTURE_COUNT; i++) + + /* ETextureIndex baked_texture_indices[BAKED_NUM_INDICES] = + TEX_HEAD_BAKED, + TEX_UPPER_BAKED, */ + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - ETextureIndex baked_index = sBakedTextureIndices[i]; - if (texture_id == self->getTEImage(baked_index)->getID()) + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (text_dict->mIsBakedTexture) { - LLTexLayerSet* layer_set = self->getLayerSet(baked_index); - if (layer_set) + if (texture_id == self->getTEImage(index)->getID()) { - llinfos << "TAT: rebake - matched entry " << (S32)baked_index << llendl; - // Apparently set_by_user == force upload - BOOL set_by_user = TRUE; - self->invalidateComposite(layer_set, set_by_user); - found = TRUE; - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + LLTexLayerSet* layer_set = self->getLayerSet(index); + if (layer_set) + { + llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; + // Apparently set_by_user == force upload + BOOL set_by_user = TRUE; + self->invalidateComposite(layer_set, set_by_user); + found = TRUE; + LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + } } } } @@ -6877,48 +6463,48 @@ void LLVOAvatar::processRebakeAvatarTextures(LLMessageSystem* msg, void**) } -BOOL LLVOAvatar::getLocalTextureRaw(S32 index, LLImageRaw* image_raw) +BOOL LLVOAvatar::getLocalTextureRaw(ETextureIndex index, LLImageRaw* image_raw) { + if (!isIndexLocalTexture(index)) return FALSE; + BOOL success = FALSE; - if( (0 <= index) && (index < LOCTEX_NUM_ENTRIES) ) + if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR) { - if (mLocalTexture[ index ].isNull() || mLocalTexture[ index ]->getID() == IMG_DEFAULT_AVATAR ) + success = TRUE; + } + else + { + LocalTextureData &local_tex_data = mLocalTextureData[index]; + if(local_tex_data.mImage->readBackRaw(-1, image_raw, false)) { success = TRUE; } else { - if( mLocalTexture[ index ]->readBackRaw(-1, image_raw, false) ) - { - success = TRUE; - } - else - { - // No data loaded yet - setLocalTexture( (ELocTexIndex)index, getTEImage( index ), FALSE ); - } + // No data loaded yet + setLocalTexture( (ETextureIndex)index, getTEImage( index ), FALSE ); } } return success; } -BOOL LLVOAvatar::getLocalTextureGL(S32 index, LLImageGL** image_gl_pp) +BOOL LLVOAvatar::getLocalTextureGL(ETextureIndex index, LLImageGL** image_gl_pp) { + if (!isIndexLocalTexture(index)) return FALSE; + BOOL success = FALSE; *image_gl_pp = NULL; - if( (0 <= index) && (index < LOCTEX_NUM_ENTRIES) ) + if (getLocalTextureID(index) == IMG_DEFAULT_AVATAR) { - if( mLocalTexture[ index ].isNull() || mLocalTexture[ index ]->getID() == IMG_DEFAULT_AVATAR) - { - success = TRUE; - } - else - { - *image_gl_pp = mLocalTexture[ index ]; - success = TRUE; - } + success = TRUE; + } + else + { + LocalTextureData &local_tex_data = mLocalTextureData[index]; + *image_gl_pp = local_tex_data.mImage; + success = TRUE; } if( !success ) @@ -6928,11 +6514,13 @@ BOOL LLVOAvatar::getLocalTextureGL(S32 index, LLImageGL** image_gl_pp) return success; } -const LLUUID& LLVOAvatar::getLocalTextureID( S32 index ) +const LLUUID& LLVOAvatar::getLocalTextureID(ETextureIndex index) { - if (index >= 0 && mLocalTexture[index].notNull()) + if (!isIndexLocalTexture(index)) return IMG_DEFAULT_AVATAR; + + if (mLocalTextureData[index].mImage.notNull()) { - return mLocalTexture[index]->getID(); + return mLocalTextureData[index].mImage->getID(); } else { @@ -6977,8 +6565,15 @@ BOOL LLVOAvatar::updateIsFullyLoaded() loading = TRUE; } - // are our texture settings still default? - if ((getTEImage( TEX_HAIR )->getID() == IMG_DEFAULT)) + // + if (mIsSelf) + { + if (!isTextureDefined(TEX_HAIR)) + { + loading = TRUE; + } + } + else if (!isTextureDefined(TEX_LOWER_BAKED) || !isTextureDefined(TEX_UPPER_BAKED) || !isTextureDefined(TEX_HEAD_BAKED)) { loading = TRUE; } @@ -6998,14 +6593,14 @@ BOOL LLVOAvatar::updateIsFullyLoaded() // texture info for our shirt/pants, stay unloaded: if (!mPreviousFullyLoaded) { - if ((!isLocalTextureDataAvailable(mLowerBodyLayerSet)) && - (getTEImage(TEX_LOWER_BAKED)->getID() == IMG_DEFAULT_AVATAR)) + if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_LOWER].mTexLayerSet)) && + (!isTextureDefined(TEX_LOWER_BAKED))) { loading = TRUE; } - if ((!isLocalTextureDataAvailable(mUpperBodyLayerSet)) && - (getTEImage(TEX_UPPER_BAKED)->getID() == IMG_DEFAULT_AVATAR)) + if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_UPPER].mTexLayerSet)) && + (!isTextureDefined(TEX_UPPER_BAKED))) { loading = TRUE; } @@ -7057,9 +6652,10 @@ LLMotion* LLVOAvatar::findMotion(const LLUUID& id) void LLVOAvatar::getLocalTextureByteCount( S32* gl_bytes ) { *gl_bytes = 0; - for( S32 i = 0; i < LOCTEX_NUM_ENTRIES; i++ ) + for( S32 i = 0; i < TEX_NUM_INDICES; i++ ) { - LLViewerImage* image_gl = mLocalTexture[i]; + if (!isIndexLocalTexture((ETextureIndex)i)) continue; + LLViewerImage* image_gl = mLocalTextureData[(ETextureIndex)i].mImage; if( image_gl ) { S32 bytes = (S32)image_gl->getWidth() * image_gl->getHeight() * image_gl->getComponents(); @@ -7122,7 +6718,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) default: llassert(0); components = 4; internal_format = GL_RGBA8; break; } - *texture_bytes = components * VOAVATAR_SCRATCH_TEX_WIDTH * VOAVATAR_SCRATCH_TEX_HEIGHT; + *texture_bytes = components * SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT; if( LLVOAvatar::sScratchTexNames.checkData( format ) ) { @@ -7142,7 +6738,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) LLImageGL::setManualImage( GL_TEXTURE_2D, 0, internal_format, - VOAVATAR_SCRATCH_TEX_WIDTH, VOAVATAR_SCRATCH_TEX_HEIGHT, + SCRATCH_TEX_WIDTH, SCRATCH_TEX_HEIGHT, format, GL_UNSIGNED_BYTE, NULL ); stop_glerror(); @@ -7174,7 +6770,7 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ) return; } - if( te >= TEX_NUM_ENTRIES ) + if( te >= TEX_NUM_INDICES ) { llassert(0); return; @@ -7185,7 +6781,7 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ) return; } - if (isTextureIndexBaked(te)) + if (isIndexBakedTexture((ETextureIndex)te)) { llassert(0); return; @@ -7208,32 +6804,13 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ) void LLVOAvatar::setupComposites() { - // Don't invalidate the baked textures we had on start-up. - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - if (mHeadLayerSet) - { - mHeadLayerSet->setUpdatesEnabled( !head_baked ); - } - if (mUpperBodyLayerSet) - { - mUpperBodyLayerSet->setUpdatesEnabled( !upper_baked ); - } - if (mLowerBodyLayerSet) - { - mLowerBodyLayerSet->setUpdatesEnabled( !lower_baked ); - } - if (mEyesLayerSet) - { - mEyesLayerSet->setUpdatesEnabled( !eyes_baked ); - } - if (mSkirtLayerSet) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mSkirtLayerSet->setUpdatesEnabled( !skirt_baked ); + bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); + if (mBakedTextureData[i].mTexLayerSet) + { + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( !layer_baked ); + } } } @@ -7243,447 +6820,193 @@ void LLVOAvatar::setupComposites() //----------------------------------------------------------------------------- void LLVOAvatar::updateMeshTextures() { -// llinfos << "updateMeshTextures" << llendl; - if (gNoRender) - { - return; - } + // llinfos << "updateMeshTextures" << llendl; + if (gNoRender) return; + // if user has never specified a texture, assign the default - LLViewerImage* default_tex = gImageList.getImage(IMG_DEFAULT); - U8 num_TEs = getNumTEs(); - for (U32 i=0; i<num_TEs; i++) + for (U32 i=0; i < getNumTEs(); i++) { - LLViewerImage* te_image = getTEImage(i); - if( (NULL == te_image) || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT) ) + const LLViewerImage* te_image = getTEImage(i); + if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT)) { - if( TEX_HAIR == i ) - { - setTEImage(i, default_tex ); - } - else - { - setTEImage(i, gImageList.getImage(IMG_DEFAULT_AVATAR)); // a special texture that's never rendered. - } + setTEImage(i, gImageList.getImage(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR)); // IMG_DEFAULT_AVATAR = a special texture that's never rendered. } } - // During face edit mode, we don't use baked textures - BOOL self_customize = mIsSelf && gAgent.cameraCustomizeAvatar(); - - BOOL head_baked = (getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = (getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = (getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = (getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = (getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - // Nothing should be baked if we're in customize avatar mode. - llassert( !( self_customize && - ( head_baked || upper_baked || lower_baked || eyes_baked ) ) ); - - BOOL use_lkg_head_baked = FALSE; - BOOL use_lkg_upper_baked = FALSE; - BOOL use_lkg_lower_baked = FALSE; - BOOL use_lkg_eyes_baked = FALSE; - BOOL use_lkg_skirt_baked = FALSE; - - BOOL other_culled = !mIsSelf && mCulled; - if( other_culled ) - { - use_lkg_head_baked = !head_baked && (mLastHeadBakedID != IMG_DEFAULT_AVATAR); - use_lkg_upper_baked = !upper_baked && (mLastUpperBodyBakedID != IMG_DEFAULT_AVATAR); - use_lkg_lower_baked = !lower_baked && (mLastLowerBodyBakedID != IMG_DEFAULT_AVATAR); - use_lkg_eyes_baked = !eyes_baked && (mLastEyesBakedID != IMG_DEFAULT_AVATAR); - use_lkg_skirt_baked = !skirt_baked && (mLastSkirtBakedID != IMG_DEFAULT_AVATAR); - - if( mHeadLayerSet ) - { - mHeadLayerSet->destroyComposite(); - } - - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->destroyComposite(); - } - - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->destroyComposite(); - } + const BOOL self_customizing = mIsSelf && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures + const BOOL other_culled = !mIsSelf && mCulled; - if( mEyesLayerSet ) - { - mEyesLayerSet->destroyComposite(); - } + std::vector<bool> is_layer_baked; + is_layer_baked.resize(mBakedTextureData.size(), false); - if( mSkirtLayerSet ) - { - mSkirtLayerSet->destroyComposite(); - } + std::vector<bool> use_lkg_baked_layer; // lkg = "last known good" + use_lkg_baked_layer.resize(mBakedTextureData.size(), false); - } - else - if( !self_customize ) + for (U32 i=0; i < mBakedTextureData.size(); i++) { - // When you're changing clothes and you're not in Appearance mode, - // use the last-known good baked texture until you finish the first - // render of the new layerset. - use_lkg_head_baked = !head_baked && (mLastHeadBakedID != IMG_DEFAULT_AVATAR) && mHeadLayerSet && !mHeadLayerSet->getComposite()->isInitialized(); - use_lkg_upper_baked = !upper_baked && (mLastUpperBodyBakedID != IMG_DEFAULT_AVATAR) && mUpperBodyLayerSet && !mUpperBodyLayerSet->getComposite()->isInitialized(); - use_lkg_lower_baked = !lower_baked && (mLastLowerBodyBakedID != IMG_DEFAULT_AVATAR) && mLowerBodyLayerSet && !mLowerBodyLayerSet->getComposite()->isInitialized(); - use_lkg_eyes_baked = !eyes_baked && (mLastEyesBakedID != IMG_DEFAULT_AVATAR) && mEyesLayerSet && !mEyesLayerSet->getComposite()->isInitialized(); - use_lkg_skirt_baked = !skirt_baked && (mLastSkirtBakedID != IMG_DEFAULT_AVATAR) && mSkirtLayerSet && !mSkirtLayerSet->getComposite()->isInitialized(); - - if( use_lkg_head_baked ) - { - mHeadLayerSet->setUpdatesEnabled( TRUE ); - } + is_layer_baked[i] = isTextureDefined(mBakedTextureData[i].mTextureIndex); - if( use_lkg_upper_baked ) + if (!other_culled) { - mUpperBodyLayerSet->setUpdatesEnabled( TRUE ); - } - - if( use_lkg_lower_baked ) - { - mLowerBodyLayerSet->setUpdatesEnabled( TRUE ); + // 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. + use_lkg_baked_layer[i] = (!is_layer_baked[i] + && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) + && mBakedTextureData[i].mTexLayerSet + && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized()); + if (use_lkg_baked_layer[i]) + { + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled(TRUE); + } } - - if( use_lkg_eyes_baked ) + else { - mEyesLayerSet->setUpdatesEnabled( TRUE ); + use_lkg_baked_layer[i] = (!is_layer_baked[i] + && mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR); + if (mBakedTextureData[i].mTexLayerSet) + { + mBakedTextureData[i].mTexLayerSet->destroyComposite(); + } } - if( use_lkg_skirt_baked ) - { - mSkirtLayerSet->setUpdatesEnabled( TRUE ); - } } // Baked textures should be requested from the sim this avatar is on. JC - LLHost target_host = getObjectHost(); + const LLHost target_host = getObjectHost(); if (!target_host.isOk()) { llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl; } - - // Head - if( use_lkg_head_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastHeadBakedID, target_host ); - mHeadMesh0.setTexture( baked ); - mHeadMesh1.setTexture( baked ); - mHeadMesh2.setTexture( baked ); - mHeadMesh3.setTexture( baked ); - mHeadMesh4.setTexture( baked ); - mEyeLashMesh0.setTexture( baked ); - } - else - if( !self_customize && head_baked ) - { - LLViewerImage* baked = getTEImage( TEX_HEAD_BAKED ); - if( baked->getID() == mLastHeadBakedID ) - { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); - } - else - { - mHeadBakedLoaded = FALSE; - mHeadMaskDiscard = -1; - baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); - } - } - else - if( mHeadLayerSet && !other_culled ) - { - mHeadLayerSet->createComposite(); - mHeadLayerSet->setUpdatesEnabled( TRUE ); - mHeadMesh0.setLayerSet( mHeadLayerSet ); - mHeadMesh1.setLayerSet( mHeadLayerSet ); - mHeadMesh2.setLayerSet( mHeadLayerSet ); - mHeadMesh3.setLayerSet( mHeadLayerSet ); - mHeadMesh4.setLayerSet( mHeadLayerSet ); - mEyeLashMesh0.setLayerSet( mHeadLayerSet ); - } - else - { - mHeadMesh0.setTexture( default_tex ); - mHeadMesh1.setTexture( default_tex ); - mHeadMesh2.setTexture( default_tex ); - mHeadMesh3.setTexture( default_tex ); - mHeadMesh4.setTexture( default_tex ); - mEyeLashMesh0.setTexture( default_tex ); - } - // Upper body - if( use_lkg_upper_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastUpperBodyBakedID, target_host ); - mUpperBodyMesh0.setTexture( baked ); - mUpperBodyMesh1.setTexture( baked ); - mUpperBodyMesh2.setTexture( baked ); - mUpperBodyMesh3.setTexture( baked ); - mUpperBodyMesh4.setTexture( baked ); - } - else - if( !self_customize && upper_baked ) + for (U32 i=0; i < mBakedTextureData.size(); i++) { - LLViewerImage* baked = getTEImage( TEX_UPPER_BAKED ); - - if( baked->getID() == mLastUpperBodyBakedID ) + if (use_lkg_baked_layer[i]) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); - } - else - { - mUpperBakedLoaded = FALSE; - mUpperMaskDiscard = -1; - baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + LLViewerImage* baked_img = gImageList.getImageFromHost( mBakedTextureData[i].mLastTextureIndex, target_host ); + for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) + { + mBakedTextureData[i].mMeshes[k]->setTexture( baked_img ); + } } - } - else - if( mUpperBodyLayerSet && !other_culled ) - { - mUpperBodyLayerSet->createComposite(); - mUpperBodyLayerSet->setUpdatesEnabled( TRUE ); - mUpperBodyMesh0.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh1.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh2.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh3.setLayerSet( mUpperBodyLayerSet ); - mUpperBodyMesh4.setLayerSet( mUpperBodyLayerSet ); - } - else - { - mUpperBodyMesh0.setTexture( default_tex ); - mUpperBodyMesh1.setTexture( default_tex ); - mUpperBodyMesh2.setTexture( default_tex ); - mUpperBodyMesh3.setTexture( default_tex ); - mUpperBodyMesh4.setTexture( default_tex ); - } - - // Lower body - if( use_lkg_lower_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastLowerBodyBakedID, target_host ); - mLowerBodyMesh0.setTexture( baked ); - mLowerBodyMesh1.setTexture( baked ); - mLowerBodyMesh2.setTexture( baked ); - mLowerBodyMesh3.setTexture( baked ); - mLowerBodyMesh4.setTexture( baked ); - } - else - if( !self_customize && lower_baked ) - { - LLViewerImage* baked = getTEImage( TEX_LOWER_BAKED ); - if( baked->getID() == mLastLowerBodyBakedID ) + else if (!self_customizing && is_layer_baked[i]) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); + LLViewerImage* baked_img = getTEImage( mBakedTextureData[i].mTextureIndex ); + if( baked_img->getID() == mBakedTextureData[i].mLastTextureIndex ) + { + // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). + useBakedTexture( baked_img->getID() ); + } + else + { + mBakedTextureData[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 )); + } + baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + } } - else + else if (mBakedTextureData[i].mTexLayerSet + && !other_culled + && (i != BAKED_HAIR || is_layer_baked[i] || mIsSelf)) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers. { - mLowerBakedLoaded = FALSE; - mLowerMaskDiscard = -1; - baked->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + mBakedTextureData[i].mTexLayerSet->createComposite(); + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE ); + for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) + { + mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet ); + } } } - else - if( mLowerBodyLayerSet && !other_culled ) - { - mLowerBodyLayerSet->createComposite(); - mLowerBodyLayerSet->setUpdatesEnabled( TRUE ); - mLowerBodyMesh0.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh1.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh2.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh3.setLayerSet( mLowerBodyLayerSet ); - mLowerBodyMesh4.setLayerSet( mLowerBodyLayerSet ); - } - else - { - mLowerBodyMesh0.setTexture( default_tex ); - mLowerBodyMesh1.setTexture( default_tex ); - mLowerBodyMesh2.setTexture( default_tex ); - mLowerBodyMesh3.setTexture( default_tex ); - mLowerBodyMesh4.setTexture( default_tex ); - } - - // Eyes - if( use_lkg_eyes_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastEyesBakedID, target_host ); - mEyeBallLeftMesh0.setTexture( baked ); - mEyeBallLeftMesh1.setTexture( baked ); - mEyeBallRightMesh0.setTexture( baked ); - mEyeBallRightMesh1.setTexture( baked ); - } - else - if( !self_customize && eyes_baked ) + + // ! BACKWARDS COMPATIBILITY ! + // Workaround for viewing avatars from old viewers that haven't baked hair textures. + // if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex)) + if (!is_layer_baked[BAKED_HAIR]) { - LLViewerImage* baked = getTEImage( TEX_EYES_BAKED ); - if( baked->getID() == mLastEyesBakedID ) - { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); - } - else + const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); + LLViewerImage* hair_img = getTEImage( TEX_HAIR ); + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) { - mEyesBakedLoaded = FALSE; - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); } - } - else - if( mEyesLayerSet && !other_culled ) - { - mEyesLayerSet->createComposite(); - mEyesLayerSet->setUpdatesEnabled( TRUE ); - mEyeBallLeftMesh0.setLayerSet( mEyesLayerSet ); - mEyeBallLeftMesh1.setLayerSet( mEyesLayerSet ); - mEyeBallRightMesh0.setLayerSet( mEyesLayerSet ); - mEyeBallRightMesh1.setLayerSet( mEyesLayerSet ); - } - else + mHasBakedHair = FALSE; + } + else { - mEyeBallLeftMesh0.setTexture( default_tex ); - mEyeBallLeftMesh1.setTexture( default_tex ); - mEyeBallRightMesh0.setTexture( default_tex ); - mEyeBallRightMesh1.setTexture( default_tex ); - } - - // Skirt - if( use_lkg_skirt_baked ) - { - LLViewerImage* baked = gImageList.getImageFromHost( mLastSkirtBakedID, target_host ); - mSkirtMesh0.setTexture( baked ); - mSkirtMesh1.setTexture( baked ); - mSkirtMesh2.setTexture( baked ); - mSkirtMesh3.setTexture( baked ); - mSkirtMesh4.setTexture( baked ); - } - else - if( !self_customize && skirt_baked ) - { - LLViewerImage* baked = getTEImage( TEX_SKIRT_BAKED ); - if( baked->getID() == mLastSkirtBakedID ) + for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) { - // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). - useBakedTexture( baked->getID() ); + mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); } - else + mHasBakedHair = TRUE; + } + + /* // Head + BOOL head_baked_ready = (is_layer_baked[BAKED_HEAD] && mBakedTextureData[BAKED_HEAD].mIsLoaded) || other_culled; + setLocalTexture( TEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); */ + for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + baked_iter++) + { + const EBakedTextureIndex baked_index = baked_iter->first; + const LLVOAvatarDictionary::BakedDictionaryEntry *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++) { - mSkirtBakedLoaded = FALSE; - baked->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) ); + const ETextureIndex texture_index = *local_tex_iter; + const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureData[baked_index].mIsLoaded) || other_culled; + setLocalTexture(texture_index, getTEImage(texture_index), is_baked_ready ); } } - else - if( mSkirtLayerSet && !other_culled) - { - mSkirtLayerSet->createComposite(); - mSkirtLayerSet->setUpdatesEnabled( TRUE ); - mSkirtMesh0.setLayerSet( mSkirtLayerSet ); - mSkirtMesh1.setLayerSet( mSkirtLayerSet ); - mSkirtMesh2.setLayerSet( mSkirtLayerSet ); - mSkirtMesh3.setLayerSet( mSkirtLayerSet ); - mSkirtMesh4.setLayerSet( mSkirtLayerSet ); - } - else - { - mSkirtMesh0.setTexture( default_tex ); - mSkirtMesh1.setTexture( default_tex ); - mSkirtMesh2.setTexture( default_tex ); - mSkirtMesh3.setTexture( default_tex ); - mSkirtMesh4.setTexture( default_tex ); - } - - mHairMesh0.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh1.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh2.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh3.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh4.setTexture( getTEImage( TEX_HAIR ) ); - mHairMesh5.setTexture( getTEImage( TEX_HAIR ) ); - - if( mTexHairColor ) - { - LLColor4 color = mTexHairColor->getColor(); - mHairMesh0.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh1.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh2.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh3.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh4.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mHairMesh5.setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - } - - // Head - BOOL head_baked_ready = (head_baked && mHeadBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); - - // Upper body - BOOL upper_baked_ready = (upper_baked && mUpperBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_UPPER_SHIRT, getTEImage( TEX_UPPER_SHIRT ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_BODYPAINT, getTEImage( TEX_UPPER_BODYPAINT ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_JACKET, getTEImage( TEX_UPPER_JACKET ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_GLOVES, getTEImage( TEX_UPPER_GLOVES ), upper_baked_ready ); - setLocalTexture( LOCTEX_UPPER_UNDERSHIRT, getTEImage( TEX_UPPER_UNDERSHIRT ), upper_baked_ready ); - - // Lower body - BOOL lower_baked_ready = (lower_baked && mLowerBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_LOWER_PANTS, getTEImage( TEX_LOWER_PANTS ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_BODYPAINT, getTEImage( TEX_LOWER_BODYPAINT ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_SHOES, getTEImage( TEX_LOWER_SHOES ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_SOCKS, getTEImage( TEX_LOWER_SOCKS ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_JACKET, getTEImage( TEX_LOWER_JACKET ), lower_baked_ready ); - setLocalTexture( LOCTEX_LOWER_UNDERPANTS, getTEImage( TEX_LOWER_UNDERPANTS ), lower_baked_ready ); - - // Eyes - BOOL eyes_baked_ready = (eyes_baked && mEyesBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_EYES_IRIS, getTEImage( TEX_EYES_IRIS ), eyes_baked_ready ); - - // Skirt - BOOL skirt_baked_ready = (skirt_baked && mSkirtBakedLoaded) || other_culled; - setLocalTexture( LOCTEX_SKIRT, getTEImage( TEX_SKIRT ), skirt_baked_ready ); - removeMissingBakedTextures(); } //----------------------------------------------------------------------------- // setLocalTexture() //----------------------------------------------------------------------------- -void LLVOAvatar::setLocalTexture( ELocTexIndex idx, LLViewerImage* tex, BOOL baked_version_ready ) +void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerImage* tex, BOOL baked_version_ready ) { + if (!isIndexLocalTexture(index)) return; + S32 desired_discard = mIsSelf ? 0 : 2; + LocalTextureData &local_tex_data = mLocalTextureData[index]; if (!baked_version_ready) { - if (tex != mLocalTexture[idx] || mLocalTextureBaked[idx]) + if (tex != local_tex_data.mImage || local_tex_data.mIsBakedReady) { - mLocalTextureDiscard[idx] = MAX_DISCARD_LEVEL+1; + local_tex_data.mDiscard = MAX_DISCARD_LEVEL+1; } if (tex->getID() != IMG_DEFAULT_AVATAR) { - if (mLocalTextureDiscard[idx] > desired_discard) + if (local_tex_data.mDiscard > desired_discard) { S32 tex_discard = tex->getDiscardLevel(); if (tex_discard >= 0 && tex_discard <= desired_discard) { - mLocalTextureDiscard[idx] = tex_discard; - requestLayerSetUpdate( idx ); - if( mIsSelf && gAgent.cameraCustomizeAvatar() ) + local_tex_data.mDiscard = tex_discard; + if( mIsSelf && !gAgent.cameraCustomizeAvatar() ) + { + requestLayerSetUpdate( index ); + } + else if( mIsSelf && gAgent.cameraCustomizeAvatar() ) { LLVisualParamHint::requestHintUpdates(); } } else { - tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), idx) ); + tex->setLoadedCallback( onLocalTextureLoaded, desired_discard, TRUE, FALSE, new LLAvatarTexData(getID(), index) ); } } tex->setMinDiscardLevel(desired_discard); } } - mLocalTextureBaked[idx] = baked_version_ready; - mLocalTexture[idx] = tex; + local_tex_data.mIsBakedReady = baked_version_ready; + local_tex_data.mImage = tex; } //----------------------------------------------------------------------------- @@ -7691,35 +7014,13 @@ void LLVOAvatar::setLocalTexture( ELocTexIndex idx, LLViewerImage* tex, BOOL bak //----------------------------------------------------------------------------- void LLVOAvatar::requestLayerSetUploads() { - BOOL upper_baked = (getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = (getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL head_baked = (getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = (getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = (getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - if( !head_baked && mHeadLayerSet ) - { - mHeadLayerSet->requestUpload(); - } - - if( !upper_baked && mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->requestUpload(); - } - - if( !lower_baked && mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->requestUpload(); - } - - if( !eyes_baked && mEyesLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mEyesLayerSet->requestUpload(); - } - - if( !skirt_baked && mSkirtLayerSet ) - { - mSkirtLayerSet->requestUpload(); + bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); + if ( !layer_baked && mBakedTextureData[i].mTexLayerSet ) + { + mBakedTextureData[i].mTexLayerSet->requestUpload(); + } } } @@ -7729,31 +7030,13 @@ void LLVOAvatar::requestLayerSetUploads() //----------------------------------------------------------------------------- void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b ) { - if( mHeadLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mHeadLayerSet->setUpdatesEnabled( b ); - } - - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->setUpdatesEnabled( b ); - } - - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->setUpdatesEnabled( b ); - } - - if( mEyesLayerSet ) - { - mEyesLayerSet->setUpdatesEnabled( b ); - } - - if( mSkirtLayerSet ) - { - mSkirtLayerSet->setUpdatesEnabled( b ); + if (mBakedTextureData[i].mTexLayerSet ) + { + mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( b ); + } } - } void LLVOAvatar::addChat(const LLChat& chat) @@ -7785,14 +7068,16 @@ void LLVOAvatar::clearChat() mChats.clear(); } -S32 LLVOAvatar::getLocalDiscardLevel( S32 index ) +S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) { + if (!isIndexLocalTexture(index)) return FALSE; + + LocalTextureData &local_tex_data = mLocalTextureData[index]; if (index >= 0 - && mLocalTexture[index].notNull() - && (mLocalTexture[index]->getID() != IMG_DEFAULT_AVATAR) - && !mLocalTexture[index]->isMissingAsset()) + && getLocalTextureID(index) != IMG_DEFAULT_AVATAR + && !local_tex_data.mImage->isMissingAsset()) { - return mLocalTexture[index]->getDiscardLevel(); + return local_tex_data.mImage->getDiscardLevel(); } else { @@ -7803,39 +7088,27 @@ S32 LLVOAvatar::getLocalDiscardLevel( S32 index ) //----------------------------------------------------------------------------- // isLocalTextureDataFinal() -// Returns true is the highest quality discard level exists for every texture +// Returns true if the highest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset ) { - if( layerset == mHeadLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_HEAD_BODYPAINT ) == 0; - } - else if( layerset == mUpperBodyLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return getLocalDiscardLevel( LOCTEX_UPPER_SHIRT ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_BODYPAINT ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_JACKET ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_GLOVES ) == 0 && - getLocalDiscardLevel( LOCTEX_UPPER_UNDERSHIRT ) == 0; - } - else if( layerset == mLowerBodyLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_LOWER_PANTS ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_BODYPAINT ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SHOES ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SOCKS ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_JACKET ) == 0 && - getLocalDiscardLevel( LOCTEX_LOWER_UNDERPANTS ) == 0; - } - else if( layerset == mEyesLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_EYES_IRIS ) == 0; - } - else if( layerset == mSkirtLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_SKIRT ) == 0; + if (layerset == mBakedTextureData[i].mTexLayerSet) + { + const LLVOAvatarDictionary::BakedDictionaryEntry *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++) + { + if (getLocalDiscardLevel(*local_tex_iter) != 0) + { + return FALSE; + } + } + return TRUE; + } } llassert(0); @@ -7844,41 +7117,31 @@ BOOL LLVOAvatar::isLocalTextureDataFinal( LLTexLayerSet* layerset ) //----------------------------------------------------------------------------- // isLocalTextureDataAvailable() -// Returns true is at least the lowest quality discard level exists for every texture +// Returns true if at least the lowest quality discard level exists for every texture // in the layerset. //----------------------------------------------------------------------------- BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset ) { - if( layerset == mHeadLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_HEAD_BODYPAINT ) >= 0; - } - else if( layerset == mUpperBodyLayerSet ) + /* if( layerset == mBakedTextureData[BAKED_HEAD].mTexLayerSet ) + return getLocalDiscardLevel( TEX_HEAD_BODYPAINT ) >= 0; */ + for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + baked_iter++) { - return getLocalDiscardLevel( LOCTEX_UPPER_SHIRT ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_BODYPAINT ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_JACKET ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_GLOVES ) >= 0 && - getLocalDiscardLevel( LOCTEX_UPPER_UNDERSHIRT ) >= 0; - } - else if( layerset == mLowerBodyLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_LOWER_PANTS ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_BODYPAINT ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SHOES ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_SOCKS ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_JACKET ) >= 0 && - getLocalDiscardLevel( LOCTEX_LOWER_UNDERPANTS ) >= 0; - } - else if( layerset == mEyesLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_EYES_IRIS ) >= 0; - } - else if( layerset == mSkirtLayerSet ) - { - return getLocalDiscardLevel( LOCTEX_SKIRT ) >= 0; + const EBakedTextureIndex baked_index = baked_iter->first; + if (layerset == mBakedTextureData[baked_index].mTexLayerSet) + { + bool ret = true; + const LLVOAvatarDictionary::BakedDictionaryEntry *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++) + { + ret &= (getLocalDiscardLevel(*local_tex_iter) >= 0); + } + return ret; + } } - llassert(0); return FALSE; } @@ -7888,31 +7151,14 @@ BOOL LLVOAvatar::isLocalTextureDataAvailable( LLTexLayerSet* layerset ) // getBakedTE() // Used by the LayerSet. (Layer sets don't in general know what textures depend on them.) //----------------------------------------------------------------------------- -LLVOAvatar::ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset ) +ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset ) { - if( layerset == mHeadLayerSet ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return TEX_HEAD_BAKED; - } - else - if( layerset == mUpperBodyLayerSet ) - { - return TEX_UPPER_BAKED; - } - else - if( layerset == mLowerBodyLayerSet ) - { - return TEX_LOWER_BAKED; - } - else - if( layerset == mEyesLayerSet ) - { - return TEX_EYES_BAKED; - } - else - if( layerset == mSkirtLayerSet ) - { - return TEX_SKIRT_BAKED; + if (layerset == mBakedTextureData[i].mTexLayerSet ) + { + return mBakedTextureData[i].mTextureIndex; + } } llassert(0); @@ -7933,26 +7179,17 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) LLVOAvatar::cullAvatarsByPixelArea(); - switch( te ) + /* switch(te) + case TEX_HEAD_BAKED: + llinfos << "New baked texture: HEAD" << llendl; */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(te); + if (text_dict->mIsBakedTexture) + { + llinfos << "New baked texture: " << text_dict->mName << " UUID: " << uuid <<llendl; + } + else { - case TEX_HEAD_BAKED: - llinfos << "New baked texture: HEAD" << llendl; - break; - case TEX_UPPER_BAKED: - llinfos << "New baked texture: UPPER" << llendl; - break; - case TEX_LOWER_BAKED: - llinfos << "New baked texture: LOWER" << llendl; - break; - case TEX_EYES_BAKED: - llinfos << "New baked texture: EYES" << llendl; - break; - case TEX_SKIRT_BAKED: - llinfos << "New baked texture: SKIRT" << llendl; - break; - default: llwarns << "New baked texture: unknown te " << te << llendl; - break; } // dumpAvatarTEs( "setNewBakedTexture() send" ); @@ -7965,28 +7202,15 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) bool LLVOAvatar::hasPendingBakedUploads() { - bool head_pending = (mHeadLayerSet && mHeadLayerSet->getComposite()->uploadPending()); - bool upper_pending = (mUpperBodyLayerSet && mUpperBodyLayerSet->getComposite()->uploadPending()); - bool lower_pending = (mLowerBodyLayerSet && mLowerBodyLayerSet->getComposite()->uploadPending()); - bool eyes_pending = (mEyesLayerSet && mEyesLayerSet->getComposite()->uploadPending()); - bool skirt_pending = (mSkirtLayerSet && mSkirtLayerSet->getComposite()->uploadPending()); - - //llinfos << "TAT: LLVOAvatar::hasPendingBakedUploads()" - // << " head_pending " << head_pending - // << " upper_pending " << upper_pending - // << " lower_pending " << lower_pending - // << " eyes_pending " << eyes_pending - // << " skirt_pending " << skirt_pending - // << llendl; - - if (head_pending || upper_pending || lower_pending || eyes_pending || skirt_pending) - { - return true; - } - else + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - return false; + bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); + if (upload_pending) + { + return true; + } } + return false; } //----------------------------------------------------------------------------- @@ -7997,56 +7221,50 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) { setTETexture( te, uuid ); - switch(te) + /* switch(te) + case TEX_HEAD_BAKED: + if( mHeadLayerSet ) + mHeadLayerSet->cancelUpload(); */ + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - case TEX_HEAD_BAKED: - if( mHeadLayerSet ) + if ( mBakedTextureData[i].mTextureIndex == te && mBakedTextureData[i].mTexLayerSet) { - mHeadLayerSet->cancelUpload(); - } - break; - case TEX_UPPER_BAKED: - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->cancelUpload(); + mBakedTextureData[i].mTexLayerSet->cancelUpload(); } - break; - case TEX_LOWER_BAKED: - if( mLowerBodyLayerSet ) + } +} + +//----------------------------------------------------------------------------- +// releaseUnneccesaryTextures() +// release any component texture UUIDs for which we have a baked texture +//----------------------------------------------------------------------------- +void LLVOAvatar::releaseUnnecessaryTextures() +{ + // Backwards Compat: detect if the baked hair texture actually wasn't sent, and if so set to default + if (isTextureDefined(TEX_HAIR_BAKED) && getTEImage(TEX_HAIR_BAKED)->getID() == getTEImage(TEX_SKIRT_BAKED)->getID()) + { + if (getTEImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE) { - mLowerBodyLayerSet->cancelUpload(); + // 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); } - break; - case TEX_EYES_BAKED: - if( mEyesLayerSet ) + } + + for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) + { + const LLVOAvatarDictionary::BakedDictionaryEntry * 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) )) { - mEyesLayerSet->cancelUpload(); + continue; } - break; - case TEX_SKIRT_BAKED: - if( mSkirtLayerSet ) + + for (U8 texture = 0; texture < bakedDicEntry->mLocalTextures.size(); texture++) { - mSkirtLayerSet->cancelUpload(); + const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture]; + setTETexture(te, IMG_DEFAULT_AVATAR); } - break; - - case TEX_HEAD_BODYPAINT: - case TEX_UPPER_SHIRT: - case TEX_LOWER_PANTS: - case TEX_EYES_IRIS: - case TEX_HAIR: - case TEX_UPPER_BODYPAINT: - case TEX_LOWER_BODYPAINT: - case TEX_LOWER_SHOES: - case TEX_LOWER_SOCKS: - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - case TEX_UPPER_GLOVES: - case TEX_UPPER_UNDERSHIRT: - case TEX_LOWER_UNDERPANTS: - case TEX_SKIRT: - case TEX_NUM_ENTRIES: - break; } } @@ -8056,21 +7274,9 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) //----------------------------------------------------------------------------- void LLVOAvatar::onCustomizeStart() { - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ ) - { - S32 tex_index = sBakedTextureIndices[i]; - avatar->mSavedTE[ tex_index ] = avatar->getTEImage(tex_index)->getID(); - avatar->setTEImage( tex_index, gImageList.getImage(IMG_DEFAULT_AVATAR) ); - } - - avatar->updateMeshTextures(); - -// avatar->dumpAvatarTEs( "onCustomizeStart() send" ); - gAgent.sendAgentSetAppearance(); - } + // We're no longer doing any baking or invalidating on entering + // appearance editing mode. Leaving function in place in case + // further changes require us to do something at this point - Nyx } //----------------------------------------------------------------------------- @@ -8079,29 +7285,31 @@ void LLVOAvatar::onCustomizeStart() //----------------------------------------------------------------------------- void LLVOAvatar::onCustomizeEnd() { - LLVOAvatar* avatar = gAgent.getAvatarObject(); - if( !avatar ) return; + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + avatarp->invalidateAll(); + avatarp->requestLayerSetUploads(); + } +} - LLHost target_host = avatar->getObjectHost(); - for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ ) +void LLVOAvatar::onChangeSelfInvisible(BOOL newvalue) +{ + LLVOAvatar *avatarp = gAgent.getAvatarObject(); + if (avatarp) + { + if (newvalue) { - S32 tex_index = sBakedTextureIndices[i]; - const LLUUID& saved = avatar->mSavedTE[ tex_index ]; - if( !saved.isNull() ) - { - avatar->setTEImage( tex_index, gImageList.getImageFromHost( saved, target_host ) ); - } + // we have just requested to set the avatar's baked textures to invisible + avatarp->setInvisible(TRUE); } - - avatar->updateMeshTextures(); - - if( !LLApp::isExiting()) + else { - avatar->requestLayerSetUploads(); + avatarp->setInvisible(FALSE); } - - gAgent.sendAgentSetAppearance(); } +} + BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] ) { @@ -8181,7 +7389,7 @@ void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, B } } -LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) +LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) { LLColor4 color; const char* param_name[3]; @@ -8198,56 +7406,36 @@ LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) void LLVOAvatar::dumpAvatarTEs( const std::string& context ) -{ +{ + /* const char* te_name[] = { + "TEX_HEAD_BODYPAINT ", + "TEX_UPPER_SHIRT ", */ llinfos << (mIsSelf ? "Self: " : "Other: ") << context << llendl; - for( S32 i=0; i<TEX_NUM_ENTRIES; i++ ) + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - const char* te_name[] = { - "TEX_HEAD_BODYPAINT ", - "TEX_UPPER_SHIRT ", - "TEX_LOWER_PANTS ", - "TEX_EYES_IRIS ", - "TEX_HAIR ", - "TEX_UPPER_BODYPAINT ", - "TEX_LOWER_BODYPAINT ", - "TEX_LOWER_SHOES ", - "TEX_HEAD_BAKED ", - "TEX_UPPER_BAKED ", - "TEX_LOWER_BAKED ", - "TEX_EYES_BAKED ", - "TEX_LOWER_SOCKS ", - "TEX_UPPER_JACKET ", - "TEX_LOWER_JACKET ", - "TEX_UPPER_GLOVES ", - "TEX_UPPER_UNDERSHIRT ", - "TEX_LOWER_UNDERPANTS ", - "TEX_SKIRT ", - "TEX_SKIRT_BAKED " - }; - - LLViewerImage* te_image = getTEImage(i); + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + const LLViewerImage* te_image = getTEImage(iter->first); if( !te_image ) { - llinfos << " " << te_name[i] << ": null ptr" << llendl; + llinfos << " " << text_dict->mName << ": null ptr" << llendl; } - else - if( te_image->getID().isNull() ) + else if( te_image->getID().isNull() ) { - llinfos << " " << te_name[i] << ": null UUID" << llendl; + llinfos << " " << text_dict->mName << ": null UUID" << llendl; } - else - if( te_image->getID() == IMG_DEFAULT ) + else if( te_image->getID() == IMG_DEFAULT ) { - llinfos << " " << te_name[i] << ": IMG_DEFAULT" << llendl; + llinfos << " " << text_dict->mName << ": IMG_DEFAULT" << llendl; } - else - if( te_image->getID() == IMG_DEFAULT_AVATAR ) + else if( te_image->getID() == IMG_DEFAULT_AVATAR ) { - llinfos << " " << te_name[i] << ": IMG_DEFAULT_AVATAR" << llendl; + llinfos << " " << text_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl; } else { - llinfos << " " << te_name[i] << ": " << te_image->getID() << llendl; + llinfos << " " << text_dict->mName << ": " << te_image->getID() << llendl; } } } @@ -8290,80 +7478,51 @@ void LLVOAvatar::updateAttachmentVisibility(U32 camera_mode) // Given a texture entry, determine which wearable type owns it. // static -LLUUID LLVOAvatar::getDefaultTEImageID( S32 te ) +LLUUID LLVOAvatar::getDefaultTEImageID(ETextureIndex index ) { - switch( te ) + /* switch( index ) + case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + const std::string &default_image_name = text_dict->mDefaultImageName; + if (default_image_name == "") { - case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); - case TEX_LOWER_PANTS: return LLUUID( gSavedSettings.getString("UIImgDefaultPantsUUID") ); - case TEX_EYES_IRIS: return LLUUID( gSavedSettings.getString("UIImgDefaultEyesUUID") ); - case TEX_HAIR: return LLUUID( gSavedSettings.getString("UIImgDefaultHairUUID") ); - case TEX_LOWER_SHOES: return LLUUID( gSavedSettings.getString("UIImgDefaultShoesUUID") ); - case TEX_LOWER_SOCKS: return LLUUID( gSavedSettings.getString("UIImgDefaultSocksUUID") ); - case TEX_UPPER_GLOVES: return LLUUID( gSavedSettings.getString("UIImgDefaultGlovesUUID") ); - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: return LLUUID( gSavedSettings.getString("UIImgDefaultJacketUUID") ); - - case TEX_UPPER_UNDERSHIRT: - case TEX_LOWER_UNDERPANTS: return LLUUID( gSavedSettings.getString("UIImgDefaultUnderwearUUID") ); - - case TEX_SKIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultSkirtUUID") ); - - default: return IMG_DEFAULT_AVATAR; + return IMG_DEFAULT_AVATAR; + } + else + { + return LLUUID(gSavedSettings.getString(default_image_name)); } } +void LLVOAvatar::setInvisible(BOOL newvalue) +{ + if (newvalue) + { + setCompositeUpdatesEnabled(FALSE); + for (U32 i = 0; i < mBakedTextureData.size(); i++ ) + { + setNewBakedTexture(mBakedTextureData[i].mTextureIndex, IMG_INVISIBLE); + } + gAgent.sendAgentSetAppearance(); + } + else + { + setCompositeUpdatesEnabled(TRUE); + invalidateAll(); + requestLayerSetUploads(); + gAgent.sendAgentSetAppearance(); + } +} // Given a texture entry, determine which wearable type owns it. // static -EWearableType LLVOAvatar::getTEWearableType( S32 te ) +EWearableType LLVOAvatar::getTEWearableType(ETextureIndex index ) { - switch( te ) - { - case TEX_UPPER_SHIRT: - return WT_SHIRT; - - case TEX_LOWER_PANTS: - return WT_PANTS; - - case TEX_EYES_IRIS: - return WT_EYES; - - case TEX_HAIR: - return WT_HAIR; - - case TEX_HEAD_BODYPAINT: - case TEX_UPPER_BODYPAINT: - case TEX_LOWER_BODYPAINT: - return WT_SKIN; - - case TEX_LOWER_SHOES: - return WT_SHOES; - - case TEX_LOWER_SOCKS: - return WT_SOCKS; - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - return WT_JACKET; - - case TEX_UPPER_GLOVES: - return WT_GLOVES; - - case TEX_UPPER_UNDERSHIRT: - return WT_UNDERSHIRT; - - case TEX_LOWER_UNDERPANTS: - return WT_UNDERPANTS; - - case TEX_SKIRT: - return WT_SKIRT; - - default: - return WT_INVALID; - } + /* switch(index) + case TEX_UPPER_SHIRT: + return WT_SHIRT; */ + return LLVOAvatarDictionary::getInstance()->getTexture(index)->mWearableType; } // Unlike most wearable functions, this works for both self and other. @@ -8371,57 +7530,68 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type ) { if (mIsDummy) return TRUE; - ETextureIndex indicator_te; switch( type ) { - case WT_SHIRT: - indicator_te = TEX_UPPER_SHIRT; - break; - - case WT_PANTS: - indicator_te = TEX_LOWER_PANTS; - break; - - case WT_SHOES: - indicator_te = TEX_LOWER_SHOES; - break; - - case WT_SOCKS: - indicator_te = TEX_LOWER_SOCKS; - break; - - case WT_JACKET: - indicator_te = TEX_UPPER_JACKET; - // Note: no need to test both upper and lower jacket - break; - - case WT_GLOVES: - indicator_te = TEX_UPPER_GLOVES; - break; - - case WT_UNDERSHIRT: - indicator_te = TEX_UPPER_UNDERSHIRT; - break; - - case WT_UNDERPANTS: - indicator_te = TEX_LOWER_UNDERPANTS; - break; - - case WT_SKIRT: - indicator_te = TEX_SKIRT; - break; - case WT_SHAPE: case WT_SKIN: case WT_HAIR: case WT_EYES: return TRUE; // everyone has all bodyparts - default: - return FALSE; + break; // Do nothing } - return ( getTEImage(indicator_te)->getID() != IMG_DEFAULT_AVATAR ); + /* switch(type) + case WT_SHIRT: + indicator_te = TEX_UPPER_SHIRT; */ + for (LLVOAvatarDictionary::texture_map_t::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + tex_iter++) + { + const LLVOAvatarDefines::ETextureIndex index = tex_iter->first; + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = tex_iter->second; + if (text_dict->mWearableType == type) + { + // If you're checking your own clothing, check the component texture + if (mIsSelf) + { + 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 + // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that + // gets baked into a texture that always exists (upper or lower). + const std::string name = text_dict->mName; + for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); + iter++) + { + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second; + if (baked_dict->mName == name) + { + if (isTextureDefined(baked_dict->mTextureIndex)) + { + return TRUE; + } + else + { + return FALSE; + } + } + } + return FALSE; + } + } + return FALSE; } @@ -8446,12 +7616,12 @@ void LLVOAvatar::clampAttachmentPositions() } } -BOOL LLVOAvatar::hasHUDAttachment() +BOOL LLVOAvatar::hasHUDAttachment() const { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ) { - attachment_map_t::iterator curiter = iter++; + attachment_map_t::const_iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; if (attachment->getIsHUDAttachment() && attachment->getObject()) { @@ -8461,13 +7631,13 @@ BOOL LLVOAvatar::hasHUDAttachment() return FALSE; } -LLBBox LLVOAvatar::getHUDBBox() +LLBBox LLVOAvatar::getHUDBBox() const { LLBBox bbox; - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ) { - attachment_map_t::iterator curiter = iter++; + attachment_map_t::const_iterator curiter = iter++; LLViewerJointAttachment* attachment = curiter->second; if (attachment->getIsHUDAttachment() && attachment->getObject()) { @@ -8503,50 +7673,23 @@ void LLVOAvatar::onFirstTEMessageReceived() { mFirstTEMessageReceived = TRUE; - BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL eyes_baked = ( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - BOOL skirt_baked = ( getTEImage( TEX_SKIRT_BAKED )->getID() != IMG_DEFAULT_AVATAR ); - - // Use any baked textures that we have even if they haven't downloaded yet. - // (That is, don't do a transition from unbaked to baked.) - if( head_baked ) - { - mLastHeadBakedID = getTEImage( TEX_HEAD_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_HEAD_BAKED ); - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } - - if( upper_baked ) + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mLastUpperBodyBakedID = getTEImage( TEX_UPPER_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_UPPER_BAKED ); - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } - - if( lower_baked ) - { - mLastLowerBodyBakedID = getTEImage( TEX_LOWER_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_LOWER_BAKED ); - image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } - - if( eyes_baked ) - { - mLastEyesBakedID = getTEImage( TEX_EYES_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_EYES_BAKED ); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); - } + bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); - if( skirt_baked ) - { - mLastSkirtBakedID = getTEImage( TEX_SKIRT_BAKED )->getID(); - LLViewerImage* image = getTEImage( TEX_SKIRT_BAKED ); - image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); + // Use any baked textures that we have even if they haven't downloaded yet. + // (That is, don't do a transition from unbaked to baked.) + if (layer_baked) + { + LLViewerImage* image = getTEImage( mBakedTextureData[i].mTextureIndex ); + mBakedTextureData[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) ) + { + image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID )); + } + image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) ); + } } updateMeshTextures(); @@ -8593,11 +7736,13 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) unpackTEMessage(mesgsys, _PREHASH_ObjectData); // dumpAvatarTEs( "POST processAvatarAppearance()" ); -// llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): " ) << -// (( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "HEAD " : "head " ) << -// (( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "UPPER " : "upper " ) << -// (( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "LOWER " : "lower " ) << -// (( getTEImage( TEX_EYES_BAKED )->getID() != IMG_DEFAULT_AVATAR ) ? "EYES" : "eyes" ) << llendl; + //llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): ") << std::endl << + // (isTextureDefined(TEX_HEAD_BAKED) ? "HEAD " : "head " ) << (getTEImage(TEX_HEAD_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_UPPER_BAKED) ? "UPPER " : "upper " ) << (getTEImage(TEX_UPPER_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_LOWER_BAKED) ? "LOWER " : "lower " ) << (getTEImage(TEX_LOWER_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_SKIRT_BAKED) ? "SKIRT " : "skirt " ) << (getTEImage(TEX_SKIRT_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_HAIR_BAKED) ? "HAIR" : "hair " ) << (getTEImage(TEX_HAIR_BAKED)->getID()) << std::endl << + // (isTextureDefined(TEX_EYES_BAKED) ? "EYES" : "eyes" ) << (getTEImage(TEX_EYES_BAKED)->getID()) << llendl ; if( !mFirstTEMessageReceived ) { @@ -8605,6 +7750,12 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } setCompositeUpdatesEnabled( FALSE ); + + if (!mIsSelf) + { + releaseUnnecessaryTextures(); + } + updateMeshTextures(); // enables updates for laysets without baked textures. // parse visual params @@ -8652,7 +7803,6 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) param->setAnimationTarget(newWeight, FALSE); } } - param = getNextVisualParam(); } } @@ -8726,28 +7876,20 @@ void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names ) void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - //llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl; - LLMemType mt(LLMemType::MTYPE_AVATAR); - - LLUUID id = src_vi->getID(); + if (!userdata) return; - if (!userdata) - { - return; - } + //llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl; + const LLMemType mt(LLMemType::MTYPE_AVATAR); + const LLUUID id = src_vi->getID(); LLTextureMaskData* maskData = (LLTextureMaskData*) userdata; LLVOAvatar* self = (LLVOAvatar*) gObjectList.findObject( maskData->mAvatarID ); // if discard level is 2 less than last discard level we processed, or we hit 0, // then generate morph masks - if( self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0) ) + if(self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0)) { - LLViewerImage* head_baked = self->getTEImage( TEX_HEAD_BAKED ); - LLViewerImage* upper_baked = self->getTEImage( TEX_UPPER_BAKED ); - LLViewerImage* lower_baked = self->getTEImage( TEX_LOWER_BAKED ); - - if( aux_src && aux_src->getComponents() == 1 ) + if(aux_src && aux_src->getComponents() == 1) { if (!aux_src->getData()) { @@ -8770,70 +7912,49 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - if( id == head_baked->getID() ) - { - if (self->mHeadLayerSet) - { - //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl; - self->mHeadLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; - self->mHeadMaskDiscard = discard_level; - if (self->mHeadMaskTexName) - { - LLImageGL::deleteTextures(1, &self->mHeadMaskTexName); - } - self->mHeadMaskTexName = gl_name; - } - else - { - llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl; - } - } - else - if( id == upper_baked->getID() ) - { - if ( self->mUpperBodyLayerSet) - { - //llinfos << "onBakedTextureMasksLoaded for upper body " << id << " discard = " << discard_level << llendl; - self->mUpperBodyLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; - self->mUpperMaskDiscard = discard_level; - if (self->mUpperMaskTexName) - { - LLImageGL::deleteTextures(1, &self->mUpperMaskTexName); - } - self->mUpperMaskTexName = gl_name; - } - else - { - llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl; - } - } - else - if( id == lower_baked->getID() ) + /* if( id == head_baked->getID() ) + if (self->mBakedTextureData[BAKED_HEAD].mTexLayerSet) + //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl; + self->mBakedTextureData[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + maskData->mLastDiscardLevel = discard_level; */ + bool found_texture_id = false; + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) { - if ( self->mLowerBodyLayerSet ) + + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (text_dict->mIsUsedByBakedTexture) { - //llinfos << "onBakedTextureMasksLoaded for lower body " << id << " discard = " << discard_level << llendl; - self->mLowerBodyLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); - maskData->mLastDiscardLevel = discard_level; - self->mLowerMaskDiscard = discard_level; - if (self->mLowerMaskTexName) + const ETextureIndex texture_index = iter->first; + const LLViewerImage *baked_img = self->getTEImage(texture_index); + if (id == baked_img->getID()) { - LLImageGL::deleteTextures(1, &self->mLowerMaskTexName); + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + if (self->mBakedTextureData[baked_index].mTexLayerSet) + { + //llinfos << "onBakedTextureMasksLoaded for " << text_dict->mName << " " << id << " discard = " << discard_level << llendl; + self->mBakedTextureData[baked_index].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + maskData->mLastDiscardLevel = discard_level; + if (self->mBakedTextureData[baked_index].mMaskTexName) + { + LLImageGL::deleteTextures(1, &(self->mBakedTextureData[baked_index].mMaskTexName)); + } + self->mBakedTextureData[baked_index].mMaskTexName = gl_name; + } + else + { + llwarns << "onBakedTextureMasksLoaded: no LayerSet for " << text_dict->mName << "." << llendl; + } + found_texture_id = true; + break; } - self->mLowerMaskTexName = gl_name; - } - else - { - llwarns << "onBakedTextureMasksLoaded: no mHeadLayerSet." << llendl; } } - else + if (!found_texture_id) { llinfos << "onBakedTextureMasksLoaded(): unexpected image id: " << id << llendl; } - self->dirtyMesh(); } else @@ -8848,7 +7969,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, { delete maskData; } - } // static @@ -8895,109 +8015,34 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLIma // Called when baked texture is loaded and also when we start up with a baked texture void LLVOAvatar::useBakedTexture( const LLUUID& id ) { -// llinfos << "useBakedTexture" << llendl; - LLViewerImage* head_baked = getTEImage( TEX_HEAD_BAKED ); - LLViewerImage* upper_baked = getTEImage( TEX_UPPER_BAKED ); - LLViewerImage* lower_baked = getTEImage( TEX_LOWER_BAKED ); - LLViewerImage* eyes_baked = getTEImage( TEX_EYES_BAKED ); - LLViewerImage* skirt_baked = getTEImage( TEX_SKIRT_BAKED ); - - if( id == head_baked->getID() ) - { - mHeadBakedLoaded = TRUE; - - mLastHeadBakedID = id; - mHeadMesh0.setTexture( head_baked ); - mHeadMesh1.setTexture( head_baked ); - mHeadMesh2.setTexture( head_baked ); - mHeadMesh3.setTexture( head_baked ); - mHeadMesh4.setTexture( head_baked ); - mEyeLashMesh0.setTexture( head_baked ); - if( mHeadLayerSet ) - { - mHeadLayerSet->destroyComposite(); - } - setLocalTexture( LOCTEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), TRUE ); - } - else - if( id == upper_baked->getID() ) - { - mUpperBakedLoaded = TRUE; - - mLastUpperBodyBakedID = id; - mUpperBodyMesh0.setTexture( upper_baked ); - mUpperBodyMesh1.setTexture( upper_baked ); - mUpperBodyMesh2.setTexture( upper_baked ); - mUpperBodyMesh3.setTexture( upper_baked ); - mUpperBodyMesh4.setTexture( upper_baked ); - if( mUpperBodyLayerSet ) - { - mUpperBodyLayerSet->destroyComposite(); - } - - setLocalTexture( LOCTEX_UPPER_SHIRT, getTEImage( TEX_UPPER_SHIRT ), TRUE ); - setLocalTexture( LOCTEX_UPPER_BODYPAINT, getTEImage( TEX_UPPER_BODYPAINT ), TRUE ); - setLocalTexture( LOCTEX_UPPER_JACKET, getTEImage( TEX_UPPER_JACKET ), TRUE ); - setLocalTexture( LOCTEX_UPPER_GLOVES, getTEImage( TEX_UPPER_GLOVES ), TRUE ); - setLocalTexture( LOCTEX_UPPER_UNDERSHIRT, getTEImage( TEX_UPPER_UNDERSHIRT ), TRUE ); - } - else - if( id == lower_baked->getID() ) - { - mLowerBakedLoaded = TRUE; - - mLastLowerBodyBakedID = id; - mLowerBodyMesh0.setTexture( lower_baked ); - mLowerBodyMesh1.setTexture( lower_baked ); - mLowerBodyMesh2.setTexture( lower_baked ); - mLowerBodyMesh3.setTexture( lower_baked ); - mLowerBodyMesh4.setTexture( lower_baked ); - if( mLowerBodyLayerSet ) - { - mLowerBodyLayerSet->destroyComposite(); - } - - setLocalTexture( LOCTEX_LOWER_PANTS, getTEImage( TEX_LOWER_PANTS ), TRUE ); - setLocalTexture( LOCTEX_LOWER_BODYPAINT, getTEImage( TEX_LOWER_BODYPAINT ), TRUE ); - setLocalTexture( LOCTEX_LOWER_SHOES, getTEImage( TEX_LOWER_SHOES ), TRUE ); - setLocalTexture( LOCTEX_LOWER_SOCKS, getTEImage( TEX_LOWER_SOCKS ), TRUE ); - setLocalTexture( LOCTEX_LOWER_JACKET, getTEImage( TEX_LOWER_JACKET ), TRUE ); - setLocalTexture( LOCTEX_LOWER_UNDERPANTS, getTEImage( TEX_LOWER_UNDERPANTS ), TRUE ); - } - else - if( id == eyes_baked->getID() ) - { - mEyesBakedLoaded = TRUE; - - mLastEyesBakedID = id; - mEyeBallLeftMesh0.setTexture( eyes_baked ); - mEyeBallLeftMesh1.setTexture( eyes_baked ); - mEyeBallRightMesh0.setTexture( eyes_baked ); - mEyeBallRightMesh1.setTexture( eyes_baked ); - if( mEyesLayerSet ) - { - mEyesLayerSet->destroyComposite(); - } - - setLocalTexture( LOCTEX_EYES_IRIS, getTEImage( TEX_EYES_IRIS ), TRUE ); - } - else - if( id == skirt_baked->getID() ) + /* if(id == head_baked->getID()) + mHeadBakedLoaded = TRUE; + mLastHeadBakedID = id; + mHeadMesh0.setTexture( head_baked ); + mHeadMesh1.setTexture( head_baked ); */ + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - mSkirtBakedLoaded = TRUE; - - mLastSkirtBakedID = id; - mSkirtMesh0.setTexture( skirt_baked ); - mSkirtMesh1.setTexture( skirt_baked ); - mSkirtMesh2.setTexture( skirt_baked ); - mSkirtMesh3.setTexture( skirt_baked ); - mSkirtMesh4.setTexture( skirt_baked ); - if( mSkirtLayerSet ) + LLViewerImage* image_baked = getTEImage( mBakedTextureData[i].mTextureIndex ); + if (id == image_baked->getID()) { - mSkirtLayerSet->destroyComposite(); + mBakedTextureData[i].mIsLoaded = true; + mBakedTextureData[i].mLastTextureIndex = id; + for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++) + { + mBakedTextureData[i].mMeshes[k]->setTexture( image_baked ); + } + if (mBakedTextureData[i].mTexLayerSet) + { + mBakedTextureData[i].mTexLayerSet->destroyComposite(); + } + const LLVOAvatarDictionary::BakedDictionaryEntry *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++) + { + setLocalTexture(*local_tex_iter, getTEImage(*local_tex_iter), TRUE); + } } - - setLocalTexture( LOCTEX_SKIRT, getTEImage( TEX_SKIRT ), TRUE ); } dirtyMesh(); @@ -9036,11 +8081,11 @@ void LLVOAvatar::dumpArchetypeXML( void* ) } } - for( S32 te = 0; te < TEX_NUM_ENTRIES; te++ ) + for(U8 te = 0; te < TEX_NUM_INDICES; te++) { - if( LLVOAvatar::getTEWearableType( te ) == type ) + if( LLVOAvatar::getTEWearableType((ETextureIndex)te) == type ) { - LLViewerImage* te_image = avatar->getTEImage( te ); + LLViewerImage* te_image = avatar->getTEImage((ETextureIndex)te); if( te_image ) { std::string uuid_str; @@ -9093,39 +8138,39 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() return 0; } +struct CompareScreenAreaGreater +{ + bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) + { + return lhs->getPixelArea() > rhs->getPixelArea(); + } +}; + // static void LLVOAvatar::cullAvatarsByPixelArea() { std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); // Update the avatars that have changed status - S32 comp_rank = 1; U32 rank = 0; for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; BOOL culled; - if( inst->isDead() ) - { - culled = TRUE; - } - else if( inst->isSelf() || inst->isFullyBaked() ) + if (inst->isSelf() || inst->isFullyBaked()) { culled = FALSE; } - else + else { - culled = (comp_rank > LLVOAvatar::sMaxOtherAvatarsToComposite) || (inst->mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE); - comp_rank++; + culled = TRUE; } - if( inst->mCulled != culled ) + if (inst->mCulled != culled) { inst->mCulled = culled; - lldebugs << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << llendl; - inst->updateMeshTextures(); } @@ -9140,9 +8185,9 @@ void LLVOAvatar::cullAvatarsByPixelArea() } S32 grey_avatars = 0; - if( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) ) + if ( LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars) ) { - LLVOAvatar::deleteCachedImages(); + LLVOAvatar::deleteCachedImages(false); } else { @@ -9174,52 +8219,31 @@ const LLUUID& LLVOAvatar::grabLocalTexture(ETextureIndex index) BOOL LLVOAvatar::canGrabLocalTexture(ETextureIndex index) { // Check if the texture hasn't been baked yet. - if ( getTEImage( index )->getID() == IMG_DEFAULT_AVATAR ) + if (!isTextureDefined(index)) { lldebugs << "getTEImage( " << (U32) index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl; return FALSE; } + if (gAgent.isGodlike()) + return TRUE; + // Check permissions of textures that show up in the // baked texture. We don't want people copying people's // work via baked textures. - std::vector<ETextureIndex> textures; - switch (index) - { - case TEX_EYES_BAKED: - textures.push_back(TEX_EYES_IRIS); - break; - case TEX_HEAD_BAKED: - textures.push_back(TEX_HEAD_BODYPAINT); - break; - case TEX_UPPER_BAKED: - textures.push_back(TEX_UPPER_BODYPAINT); - textures.push_back(TEX_UPPER_UNDERSHIRT); - textures.push_back(TEX_UPPER_SHIRT); - textures.push_back(TEX_UPPER_JACKET); - textures.push_back(TEX_UPPER_GLOVES); - break; - case TEX_LOWER_BAKED: - textures.push_back(TEX_LOWER_BODYPAINT); - textures.push_back(TEX_LOWER_UNDERPANTS); - textures.push_back(TEX_LOWER_PANTS); - textures.push_back(TEX_LOWER_JACKET); - textures.push_back(TEX_LOWER_SOCKS); - textures.push_back(TEX_LOWER_SHOES); - break; - case TEX_SKIRT_BAKED: - textures.push_back(TEX_SKIRT); - break; - default: - return FALSE; - break; - } - - std::vector<ETextureIndex>::iterator iter = textures.begin(); - std::vector<ETextureIndex>::iterator end = textures.end(); - for (; iter != end; ++iter) - { - ETextureIndex t_index = (*iter); + /* switch(index) + case TEX_EYES_BAKED: + textures.push_back(TEX_EYES_IRIS); */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (!text_dict->mIsUsedByBakedTexture) return FALSE; + + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index); + for (texture_vec_t::const_iterator iter = baked_dict->mLocalTextures.begin(); + iter != baked_dict->mLocalTextures.end(); + iter++) + { + const ETextureIndex t_index = (*iter); lldebugs << "Checking index " << (U32) t_index << llendl; const LLUUID& texture_id = getTEImage( t_index )->getID(); if (texture_id != IMG_DEFAULT_AVATAR) @@ -9266,62 +8290,43 @@ void LLVOAvatar::dumpLocalTextures() { llinfos << "Local Textures:" << llendl; - const char* names[] = { - "Shirt ", - "UpperTatoo", - "Pants ", - "LowerTatoo", - "Head Tatoo", - "Shoes ", - "Socks ", - "Upper Jckt", - "Lower Jckt", - "Gloves ", - "Undershirt", - "Underpants", - "Iris ", - "Skirt "}; - - ETextureIndex baked_equiv[] = { - TEX_UPPER_BAKED, - TEX_UPPER_BAKED, - TEX_LOWER_BAKED, - TEX_LOWER_BAKED, - TEX_HEAD_BAKED, - TEX_LOWER_BAKED, - TEX_LOWER_BAKED, - TEX_UPPER_BAKED, - TEX_LOWER_BAKED, - TEX_UPPER_BAKED, + /* ETextureIndex baked_equiv[] = { TEX_UPPER_BAKED, - TEX_LOWER_BAKED, - TEX_EYES_BAKED, - TEX_SKIRT_BAKED }; + if (isTextureDefined(baked_equiv[i])) */ + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) + { + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (!text_dict->mIsLocalTexture || !text_dict->mIsUsedByBakedTexture) + continue; + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + const ETextureIndex baked_equiv = LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex; - for( S32 i = 0; i < LOCTEX_NUM_ENTRIES; i++ ) - { - if( getTEImage( baked_equiv[i] )->getID() != IMG_DEFAULT_AVATAR ) + const std::string &name = text_dict->mName; + const LocalTextureData &local_tex_data = mLocalTextureData[iter->first]; + if (isTextureDefined(baked_equiv)) { #if LL_RELEASE_FOR_DOWNLOAD // End users don't get to trivially see avatar texture IDs, makes textures // easier to steal. JC - llinfos << "LocTex " << names[i] << ": Baked " << llendl; + llinfos << "LocTex " << name << ": Baked " << llendl; #else - llinfos << "LocTex " << names[i] << ": Baked " << getTEImage( baked_equiv[i] )->getID() << llendl; + llinfos << "LocTex " << name << ": Baked " << getTEImage( baked_equiv )->getID() << llendl; #endif } - else if (mLocalTexture[i].notNull()) + else if (local_tex_data.mImage.notNull()) { - if( mLocalTexture[i]->getID() == IMG_DEFAULT_AVATAR ) + if( local_tex_data.mImage->getID() == IMG_DEFAULT_AVATAR ) { - llinfos << "LocTex " << names[i] << ": None" << llendl; + llinfos << "LocTex " << name << ": None" << llendl; } else { - LLViewerImage* image = mLocalTexture[i]; + const LLViewerImage* image = local_tex_data.mImage; - llinfos << "LocTex " << names[i] << ": " + llinfos << "LocTex " << name << ": " << "Discard " << image->getDiscardLevel() << ", " << "(" << image->getWidth() << ", " << image->getHeight() << ") " #if !LL_RELEASE_FOR_DOWNLOAD @@ -9335,7 +8340,7 @@ void LLVOAvatar::dumpLocalTextures() } else { - llinfos << "LocTex " << names[i] << ": No LLViewerImage" << llendl; + llinfos << "LocTex " << name << ": No LLViewerImage" << llendl; } } } @@ -9354,30 +8359,25 @@ void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound) void LLVOAvatar::removeMissingBakedTextures() { - if (!mIsSelf) - { - return; - } - BOOL removed = FALSE; + if (!mIsSelf) return; - for( S32 i = 0; i < BAKED_TEXTURE_COUNT; i++ ) + BOOL removed = FALSE; + for (U32 i = 0; i < mBakedTextureData.size(); i++) { - S32 te = sBakedTextureIndices[i]; - - if( getTEImage( te )->isMissingAsset() ) + const S32 te = mBakedTextureData[i].mTextureIndex; + if (getTEImage(te)->isMissingAsset()) { - setTEImage( te, gImageList.getImage(IMG_DEFAULT_AVATAR) ); + setTEImage(te, gImageList.getImage(IMG_DEFAULT_AVATAR)); removed = TRUE; } } - if( removed ) + if (removed) { - invalidateComposite( mEyesLayerSet, FALSE ); - invalidateComposite( mHeadLayerSet, FALSE ); - invalidateComposite( mUpperBodyLayerSet, FALSE ); - invalidateComposite( mLowerBodyLayerSet, FALSE ); - invalidateComposite( mSkirtLayerSet, FALSE ); + for(U32 i = 0; i < mBakedTextureData.size(); i++) + { + invalidateComposite(mBakedTextureData[i].mTexLayerSet, FALSE); + } updateMeshTextures(); requestLayerSetUploads(); } @@ -9385,15 +8385,15 @@ void LLVOAvatar::removeMissingBakedTextures() //----------------------------------------------------------------------------- -// LLVOAvatarInfo +// LLVOAvatarXmlInfo //----------------------------------------------------------------------------- -LLVOAvatarInfo::LLVOAvatarInfo() +LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) { } -LLVOAvatarInfo::~LLVOAvatarInfo() +LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() { std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); @@ -9514,7 +8514,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) { LLXmlTreeNode* node = root->getChildByName( "skeleton" ); if( !node ) @@ -9620,7 +8620,7 @@ BOOL LLVOAvatarInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlMeshNodes(): parses <mesh> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); node; @@ -9710,7 +8710,7 @@ BOOL LLVOAvatarInfo::parseXmlMeshNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlColorNodes(): parses <global_color> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlColorNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); color_node; @@ -9772,7 +8772,7 @@ BOOL LLVOAvatarInfo::parseXmlColorNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlLayerNodes(): parses <layer_set> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); layer_node; @@ -9796,7 +8796,7 @@ BOOL LLVOAvatarInfo::parseXmlLayerNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +BOOL LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) { LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); if( driver ) @@ -9874,41 +8874,17 @@ std::string LLVOAvatar::getFullname() const LLTexLayerSet* LLVOAvatar::getLayerSet(ETextureIndex index) const { - switch( index ) + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = LLVOAvatarDictionary::getInstance()->getTexture(index); + if (text_dict->mIsUsedByBakedTexture) { - case TEX_HEAD_BAKED: - case TEX_HEAD_BODYPAINT: - return mHeadLayerSet; - - case TEX_UPPER_BAKED: - case TEX_UPPER_SHIRT: - case TEX_UPPER_BODYPAINT: - case TEX_UPPER_JACKET: - case TEX_UPPER_GLOVES: - case TEX_UPPER_UNDERSHIRT: - return mUpperBodyLayerSet; - - case TEX_LOWER_BAKED: - case TEX_LOWER_PANTS: - case TEX_LOWER_BODYPAINT: - case TEX_LOWER_SHOES: - case TEX_LOWER_SOCKS: - case TEX_LOWER_JACKET: - case TEX_LOWER_UNDERPANTS: - return mLowerBodyLayerSet; - - case TEX_EYES_BAKED: - case TEX_EYES_IRIS: - return mEyesLayerSet; - - case TEX_SKIRT_BAKED: - case TEX_SKIRT: - return mSkirtLayerSet; - - case TEX_HAIR: - default: - return NULL; + const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; + return mBakedTextureData[baked_index].mTexLayerSet; } + return NULL; } LLHost LLVOAvatar::getObjectHost() const @@ -9929,15 +8905,15 @@ void LLVOAvatar::updateFreezeCounter(S32 counter) { if(counter) { - sFreezeCounter = counter ; + sFreezeCounter = counter; } else if(sFreezeCounter > 0) { - sFreezeCounter-- ; + sFreezeCounter--; } else { - sFreezeCounter = 0 ; + sFreezeCounter = 0; } } @@ -9989,7 +8965,7 @@ void LLVOAvatar::updateImpostors() BOOL LLVOAvatar::isImpostor() const { - return (sUseImpostors && mUpdatePeriod >= VOAVATAR_IMPOSTOR_PERIOD) ? TRUE : FALSE; + return (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD) ? TRUE : FALSE; } @@ -10018,7 +8994,7 @@ void LLVOAvatar::cacheImpostorValues() getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance); } -void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) +void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const { const LLVector3* ext = mDrawable->getSpatialExtents(); extents[0] = ext[0]; @@ -10032,6 +9008,85 @@ void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& di angle.mV[2] = da; } +void LLVOAvatar::idleUpdateRenderCost() +{ + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) + { + return; + } + + U32 shame = 1; + + std::set<LLUUID> textures; + + attachment_map_t::const_iterator iter; + for (iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + LLViewerObject* object = attachment->getObject(); + if (object && !object->isHUDAttachment()) + { + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + shame += 10; + LLVOVolume* volume = drawable->getVOVolume(); + if (volume) + { + shame += calc_shame(volume, textures); + } + } + } + } + + shame += textures.size() * 5; + + 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); + mText->setColor(LLColor4(red,green,0,1)); +} + +// static +BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) +{ + if (index < 0 || index >= TEX_NUM_INDICES) return false; + return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsLocalTexture; +} + +// static +BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) +{ + if (index < 0 || index >= TEX_NUM_INDICES) return false; + return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsBakedTexture; +} + +const std::string LLVOAvatar::getBakedStatusForPrintout() const +{ + std::string line; + + for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); + iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); + iter++) + { + const ETextureIndex index = iter->first; + const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; + if (text_dict->mIsBakedTexture) + { + line += text_dict->mName; + if (isTextureDefined(index)) + { + line += "_baked"; + } + line += " "; + } + } + return line; +} + + U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures) { if (!volume) @@ -10136,45 +9191,11 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures) return shame; } -void LLVOAvatar::idleUpdateRenderCost() -{ - if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) - { - return; - } - - U32 shame = 1; - - std::set<LLUUID> textures; - - attachment_map_t::const_iterator iter; - for (iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; - LLViewerObject* object = attachment->getObject(); - if (object && !object->isHUDAttachment()) - { - LLDrawable* drawable = object->mDrawable; - if (drawable) - { - shame += 10; - LLVOVolume* volume = drawable->getVOVolume(); - if (volume) - { - shame += calc_shame(volume, textures); - } - } - } - } - - shame += textures.size() * 5; +//----------------------------------------------------------------------------- +// Utility functions +//----------------------------------------------------------------------------- - 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); - mText->setColor(LLColor4(red,green,0,1)); +F32 calc_bouncy_animation(F32 x) +{ + return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f; } - - diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 14f7bd6dcc..bdb32319f8 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -1,4 +1,4 @@ -/** +/** * @file llvoavatar.h * @brief Declaration of LLVOAvatar class which is a derivation fo * LLViewerObject @@ -34,210 +34,40 @@ #ifndef LL_LLVOAVATAR_H #define LL_LLVOAVATAR_H -// May help Visual Studio avoid opening this file. - -#include <set> #include <map> -#include <algorithm> #include <deque> +#include <string> +#include <vector> #include "llchat.h" #include "llviewerobject.h" -#include "lljointsolverrp3.h" +#include "llcharacter.h" #include "llviewerjointmesh.h" #include "llviewerjointattachment.h" -#include "llcharacter.h" -#include "material_codes.h" -#include "llanimationstates.h" -#include "v4coloru.h" -#include "llstring.h" -#include "llframetimer.h" -#include "llxmltree.h" -#include "llwearable.h" #include "llrendertarget.h" +#include "llwearable.h" +#include "llvoavatardefines.h" + +extern const LLUUID ANIM_AGENT_BODY_NOISE; +extern const LLUUID ANIM_AGENT_BREATHE_ROT; +extern const LLUUID ANIM_AGENT_EDITING; +extern const LLUUID ANIM_AGENT_EYE; +extern const LLUUID ANIM_AGENT_FLY_ADJUST; +extern const LLUUID ANIM_AGENT_HAND_MOTION; +extern const LLUUID ANIM_AGENT_HEAD_ROT; +extern const LLUUID ANIM_AGENT_PELVIS_FIX; +extern const LLUUID ANIM_AGENT_TARGET; +extern const LLUUID ANIM_AGENT_WALK_ADJUST; -//Ventrella -//#include "llvoiceclient.h" -#include "llvoicevisualizer.h" -//End Ventrella - -const S32 VOAVATAR_SCRATCH_TEX_WIDTH = 512; -const S32 VOAVATAR_SCRATCH_TEX_HEIGHT = 512; -const S32 VOAVATAR_IMPOSTOR_PERIOD = 2; - -const LLUUID ANIM_AGENT_BODY_NOISE = LLUUID("9aa8b0a6-0c6f-9518-c7c3-4f41f2c001ad"); //"body_noise" -const LLUUID ANIM_AGENT_BREATHE_ROT = LLUUID("4c5a103e-b830-2f1c-16bc-224aa0ad5bc8"); //"breathe_rot" -const LLUUID ANIM_AGENT_EDITING = LLUUID("2a8eba1d-a7f8-5596-d44a-b4977bf8c8bb"); //"editing" -const LLUUID ANIM_AGENT_EYE = LLUUID("5c780ea8-1cd1-c463-a128-48c023f6fbea"); //"eye" -const LLUUID ANIM_AGENT_FLY_ADJUST = LLUUID("db95561f-f1b0-9f9a-7224-b12f71af126e"); //"fly_adjust" -const LLUUID ANIM_AGENT_HAND_MOTION = LLUUID("ce986325-0ba7-6e6e-cc24-b17c4b795578"); //"hand_motion" -const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d"); //"head_rot" -const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix" -const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target" -const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust" - -class LLChat; -class LLXmlTreeNode; class LLTexLayerSet; -class LLTexGlobalColor; -class LLTexGlobalColorInfo; -class LLTexLayerSetInfo; -class LLDriverParamInfo; - +class LLVoiceVisualizer; class LLHUDText; class LLHUDEffectSpiral; +class LLTexGlobalColor; -class LLVertexBufferAvatar : public LLVertexBuffer -{ -public: - LLVertexBufferAvatar(); - virtual void setupVertexBuffer(U32 data_mask) const; -}; - -typedef enum e_mesh_id -{ - MESH_ID_HAIR, - MESH_ID_HEAD, - MESH_ID_UPPER_BODY, - MESH_ID_LOWER_BODY, - MESH_ID_SKIRT -} eMeshID; - -typedef enum e_render_name -{ - RENDER_NAME_NEVER, - RENDER_NAME_FADE, - RENDER_NAME_ALWAYS -} eRenderName; - -const S32 BAKED_TEXTURE_COUNT = 5; // number of values in ETextureIndex that are pre-composited - -//------------------------------------------------------------------------ -// LLVOAvatar Support classes -//------------------------------------------------------------------------ - -class LLVOAvatarBoneInfo -{ - friend class LLVOAvatar; - friend class LLVOAvatarSkeletonInfo; -public: - LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} - ~LLVOAvatarBoneInfo() - { - std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); - -protected: - std::string mName; - BOOL mIsJoint; - LLVector3 mPos; - LLVector3 mRot; - LLVector3 mScale; - LLVector3 mPivot; - typedef std::vector<LLVOAvatarBoneInfo*> child_list_t; - child_list_t mChildList; -}; - -class LLVOAvatarSkeletonInfo -{ - friend class LLVOAvatar; -public: - LLVOAvatarSkeletonInfo() : - mNumBones(0), mNumCollisionVolumes(0) {} - ~LLVOAvatarSkeletonInfo() - { - std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); - } - BOOL parseXml(LLXmlTreeNode* node); - S32 getNumBones() { return mNumBones; } - S32 getNumCollisionVolumes() { return mNumCollisionVolumes; } - -protected: - S32 mNumBones; - S32 mNumCollisionVolumes; - typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t; - bone_info_list_t mBoneInfoList; -}; - - -//------------------------------------------------------------------------ -// LLVOAvatarInfo -// One instance (in LLVOAvatar) with common data parsed from the XML files -//------------------------------------------------------------------------ -class LLVOAvatarInfo -{ - friend class LLVOAvatar; -public: - LLVOAvatarInfo(); - ~LLVOAvatarInfo(); - -protected: - BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); - BOOL parseXmlMeshNodes(LLXmlTreeNode* root); - BOOL parseXmlColorNodes(LLXmlTreeNode* root); - BOOL parseXmlLayerNodes(LLXmlTreeNode* root); - BOOL parseXmlDriverNodes(LLXmlTreeNode* root); - - struct LLVOAvatarMeshInfo - { - typedef std::pair<LLPolyMorphTargetInfo*,BOOL> morph_info_pair_t; - typedef std::vector<morph_info_pair_t> morph_info_list_t; - - LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} - ~LLVOAvatarMeshInfo() - { - morph_info_list_t::iterator iter; - for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) - { - delete iter->first; - } - mPolyMorphTargetInfoList.clear(); - } - - std::string mType; - S32 mLOD; - std::string mMeshFileName; - std::string mReferenceMeshName; - F32 mMinPixelArea; - morph_info_list_t mPolyMorphTargetInfoList; - }; - typedef std::vector<LLVOAvatarMeshInfo*> mesh_info_list_t; - mesh_info_list_t mMeshInfoList; - - typedef std::vector<LLPolySkeletalDistortionInfo*> skeletal_distortion_info_list_t; - skeletal_distortion_info_list_t mSkeletalDistortionInfoList; - - struct LLVOAvatarAttachmentInfo - { - LLVOAvatarAttachmentInfo() - : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), - mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} - std::string mName; - std::string mJointName; - LLVector3 mPosition; - LLVector3 mRotationEuler; - S32 mGroup; - S32 mAttachmentID; - S32 mPieMenuSlice; - BOOL mVisibleFirstPerson; - BOOL mIsHUDAttachment; - BOOL mHasPosition; - BOOL mHasRotation; - }; - typedef std::vector<LLVOAvatarAttachmentInfo*> attachment_info_list_t; - attachment_info_list_t mAttachmentInfoList; - - LLTexGlobalColorInfo *mTexSkinColorInfo; - LLTexGlobalColorInfo *mTexHairColorInfo; - LLTexGlobalColorInfo *mTexEyeColorInfo; - - typedef std::vector<LLTexLayerSetInfo*> layer_info_list_t; - layer_info_list_t mLayerInfoList; - - typedef std::vector<LLDriverParamInfo*> driver_info_list_t; - driver_info_list_t mDriverInfoList; -}; +class LLVOAvatarBoneInfo; +class LLVOAvatarSkeletonInfo; +class LLVOAvatarXmlInfo; //------------------------------------------------------------------------ // LLVOAvatar @@ -246,44 +76,28 @@ class LLVOAvatar : public LLViewerObject, public LLCharacter { -protected: +protected: virtual ~LLVOAvatar(); public: - - struct CompareScreenAreaGreater - { - bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) - { - return lhs->getPixelArea() > rhs->getPixelArea(); - } - }; - - enum - { - VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | - (1 << LLVertexBuffer::TYPE_NORMAL) | - (1 << LLVertexBuffer::TYPE_TEXCOORD0) | - (1 << LLVertexBuffer::TYPE_WEIGHT) | - (1 << LLVertexBuffer::TYPE_CLOTHWEIGHT) - }; - LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); /*virtual*/ void markDead(); + void startDefaultMotions(); static void updateImpostors(); //-------------------------------------------------------------------- // LLViewerObject interface //-------------------------------------------------------------------- - static void initClass(); // Initialize data that's only inited once per class. - static void cleanupClass(); // Cleanup data that's only inited once per class. +public: + static void initClass(); // Initialize data that's only init'd once per class. + static void cleanupClass(); // Cleanup data that's only init'd once per class. static BOOL parseSkeletonFile(const std::string& filename); - virtual U32 processUpdateMessage( LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp); + virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); void idleUpdateVoiceVisualizer(bool voice_enabled); void idleUpdateMisc(bool detailed_update); @@ -296,12 +110,11 @@ public: void idleUpdateTractorBeam(); void idleUpdateBelowWater(); +public: virtual BOOL updateLOD(); - void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } - /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. + /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. // Graphical stuff for objects - maybe broken out into render class later? - U32 renderFootShadows(); U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255)); U32 renderRigid(); @@ -310,13 +123,13 @@ public: void renderCollisionVolumes(); /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - S32* face_hit = NULL, // which face was hit - LLVector3* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector3* normal = NULL, // return the surface normal at the intersection point - LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point + S32 face = -1, // which face to check, -1 = ALL_SIDES + BOOL pick_transparent = FALSE, + S32* face_hit = NULL, // which face was hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point ); /*virtual*/ void updateTextures(LLAgent &agent); @@ -328,19 +141,18 @@ public: void updateVisibility(); void updateAttachmentVisibility(U32 camera_mode); void clampAttachmentPositions(); - S32 getAttachmentCount(); // Warning: order(N) not order(1) + S32 getAttachmentCount(); // Warning: order(N) not order(1) - BOOL hasHUDAttachment(); - LLBBox getHUDBBox(); -// void renderHUD(BOOL for_select); // old + // HUD functions + BOOL hasHUDAttachment() const; + LLBBox getHUDBBox() const; void rebuildHUD(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); - /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - void updateShadowFaces(); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - BOOL updateJointLODs(); + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); + BOOL updateJointLODs(); virtual void updateRegion(LLViewerRegion *regionp); @@ -352,57 +164,14 @@ public: BOOL needsImpostorUpdate() const; const LLVector3& getImpostorOffset() const; const LLVector2& getImpostorDim() const; - void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance); + void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const; void cacheImpostorValues(); void setImpostorDim(const LLVector2& dim); //-------------------------------------------------------------------- - // texture entry assignment - //-------------------------------------------------------------------- - enum ETextureIndex - { - TEX_HEAD_BODYPAINT = 0, - TEX_UPPER_SHIRT = 1, - TEX_LOWER_PANTS = 2, - TEX_EYES_IRIS = 3, - TEX_HAIR = 4, - TEX_UPPER_BODYPAINT = 5, - TEX_LOWER_BODYPAINT = 6, - TEX_LOWER_SHOES = 7, - TEX_HEAD_BAKED = 8, // Pre-composited - TEX_UPPER_BAKED = 9, // Pre-composited - TEX_LOWER_BAKED = 10, // Pre-composited - TEX_EYES_BAKED = 11, // Pre-composited - TEX_LOWER_SOCKS = 12, - TEX_UPPER_JACKET = 13, - TEX_LOWER_JACKET = 14, - TEX_UPPER_GLOVES = 15, - TEX_UPPER_UNDERSHIRT = 16, - TEX_LOWER_UNDERPANTS = 17, - TEX_SKIRT = 18, - TEX_SKIRT_BAKED = 19, // Pre-composited - TEX_NUM_ENTRIES = 20 - }; - // Note: if TEX_NUM_ENTRIES changes, update AGENT_TEXTURES in llagentinfo.h, mTextureIndexBaked, and BAKED_TEXTURE_COUNT - - static BOOL isTextureIndexBaked( S32 i ) - { - switch(i) - { - case TEX_HEAD_BAKED: - case TEX_UPPER_BAKED: - case TEX_LOWER_BAKED: - case TEX_EYES_BAKED: - case TEX_SKIRT_BAKED: - return TRUE; - default: - return FALSE; - } - } - - //-------------------------------------------------------------------- // LLCharacter interface //-------------------------------------------------------------------- +public: virtual const char *getAnimationPrefix() { return "avatar"; } virtual LLJoint *getRootJoint() { return &mRoot; } virtual LLVector3 getCharacterPosition(); @@ -417,8 +186,8 @@ public: virtual F32 getPixelArea() const; virtual LLPolyMesh* getHeadMesh(); virtual LLPolyMesh* getUpperBodyMesh(); - virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); - virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position); + virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); + virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position); virtual void updateVisualParams(); virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE); @@ -433,30 +202,35 @@ public: //-------------------------------------------------------------------- // Other public functions //-------------------------------------------------------------------- - BOOL allocateCollisionVolumes( U32 num ); - void resetHUDAttachments(); - static void getAnimLabels( LLDynamicArray<std::string>* labels ); - static void getAnimNames( LLDynamicArray<std::string>* names ); - +public: static void onCustomizeStart(); static void onCustomizeEnd(); - void getLocalTextureByteCount( S32* gl_byte_count ); +public: static void dumpTotalLocalTextureByteCount(); +protected: + void getLocalTextureByteCount( S32* gl_byte_count ); + +public: LLMotion* findMotion(const LLUUID& id); BOOL isVisible(); - BOOL isSelf() { return mIsSelf; } - BOOL isCulled() { return mCulled; } - - S32 getUnbakedPixelAreaRank(); - void setVisibilityRank(U32 rank); - U32 getVisibilityRank(); + BOOL isSelf() const { return mIsSelf; } + BOOL isCulled() const { return mCulled; } + +public: static void cullAvatarsByPixelArea(); + void setVisibilityRank(U32 rank); + U32 getVisibilityRank(); // unused +protected: + S32 getUnbakedPixelAreaRank(); +public: void dumpLocalTextures(); - const LLUUID& grabLocalTexture(ETextureIndex index); - BOOL canGrabLocalTexture(ETextureIndex index); + const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex index); + BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex index); + BOOL isTextureDefined(U8 te) const; + BOOL isTextureVisible(U8 te) const; void startAppearanceAnimation(BOOL set_by_user, BOOL play_sound); void setCompositeUpdatesEnabled(BOOL b); @@ -469,46 +243,31 @@ public: // Returns "FirstName LastName" std::string getFullname() const; - //-------------------------------------------------------------------- - // internal (pseudo-private) functions - //-------------------------------------------------------------------- - F32 getPelvisToFoot() { return mPelvisToFoot; } - - void startDefaultMotions(); - void buildCharacter(); - void releaseMeshData(); - void restoreMeshData(); - void updateMeshData(); - - void computeBodySize(); - BOOL updateCharacter(LLAgent &agent); void updateHeadOffset(); - LLUUID& getStepSound(); + F32 getPelvisToFoot() const { return mPelvisToFoot; } + +public: + BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims); void processAnimationStateChanges(); +protected: BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start); void resetAnimations(); - BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims); - BOOL needsRenderBeam(); - - // Utility functions +public: void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm); void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm); - + void slamPosition(); // Slam position to transmitted position (for teleport); - BOOL loadAvatar(); - BOOL setupBone(LLVOAvatarBoneInfo* info, LLViewerJoint* parent); - BOOL buildSkeleton(LLVOAvatarSkeletonInfo *info); - // morph targets and such void processAvatarAppearance( LLMessageSystem* mesgsys ); void onFirstTEMessageReceived(); void updateSexDependentLayerSets( BOOL set_by_user ); void dirtyMesh(); // Dirty the avatar mesh + void hideSkirt(); virtual void setParent(LLViewerObject* parent); virtual void addChild(LLViewerObject *childp); @@ -531,410 +290,309 @@ public: void updateMeshTextures(); //-------------------------------------------------------------------- - // local textures for compositing. - //-------------------------------------------------------------------- - enum ELocTexIndex - { - LOCTEX_UPPER_SHIRT = 0, - LOCTEX_UPPER_BODYPAINT = 1, - LOCTEX_LOWER_PANTS = 2, - LOCTEX_LOWER_BODYPAINT = 3, - LOCTEX_HEAD_BODYPAINT = 4, - LOCTEX_LOWER_SHOES = 5, - LOCTEX_LOWER_SOCKS = 6, - LOCTEX_UPPER_JACKET = 7, - LOCTEX_LOWER_JACKET = 8, - LOCTEX_UPPER_GLOVES = 9, - LOCTEX_UPPER_UNDERSHIRT = 10, - LOCTEX_LOWER_UNDERPANTS = 11, - LOCTEX_EYES_IRIS = 12, - LOCTEX_SKIRT = 13, - LOCTEX_NUM_ENTRIES = 14 - }; - - //-------------------------------------------------------------------- // texture compositing (used only by the LLTexLayer series of classes) //-------------------------------------------------------------------- +public: LLColor4 getGlobalColor( const std::string& color_name ); BOOL isLocalTextureDataAvailable( LLTexLayerSet* layerset ); BOOL isLocalTextureDataFinal( LLTexLayerSet* layerset ); - ETextureIndex getBakedTE( LLTexLayerSet* layerset ); + LLVOAvatarDefines::ETextureIndex getBakedTE( LLTexLayerSet* layerset ); void updateComposites(); void onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user ); - BOOL getLocalTextureRaw( S32 index, LLImageRaw* image_raw_pp ); - BOOL getLocalTextureGL( S32 index, LLImageGL** image_gl_pp ); - const LLUUID& getLocalTextureID( S32 index ); + BOOL getLocalTextureRaw( LLVOAvatarDefines::ETextureIndex index, LLImageRaw* image_raw_pp ); + BOOL getLocalTextureGL( LLVOAvatarDefines::ETextureIndex index, LLImageGL** image_gl_pp ); + const LLUUID& getLocalTextureID( LLVOAvatarDefines::ETextureIndex index ); LLGLuint getScratchTexName( LLGLenum format, U32* texture_bytes ); BOOL bindScratchTexture( LLGLenum format ); void invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user ); + void invalidateAll(); void forceBakeAllTextures(bool slam_for_debug = false); static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); - void setNewBakedTexture( ETextureIndex i, const LLUUID& uuid ); - void setCachedBakedTexture( ETextureIndex i, const LLUUID& uuid ); + void setNewBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); + void setCachedBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); + void releaseUnnecessaryTextures(); void requestLayerSetUploads(); bool hasPendingBakedUploads(); static void onLocalTextureLoaded( BOOL succcess, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); static void dumpArchetypeXML( void* ); static void dumpScratchTextureByteCount(); static void dumpBakedStatus(); - static void deleteCachedImages(); + static void deleteCachedImages(bool clearAll=true); static void destroyGL(); static void restoreGL(); static void resetImpostors(); - static enum EWearableType getTEWearableType( S32 te ); - static LLUUID getDefaultTEImageID( S32 te ); + static enum EWearableType getTEWearableType(LLVOAvatarDefines::ETextureIndex te ); + static LLUUID getDefaultTEImageID(LLVOAvatarDefines::ETextureIndex te ); + static void onChangeSelfInvisible(BOOL newvalue); + void setInvisible(BOOL newvalue); + + //-------------------------------------------------------------------- // Clothing colors (conventience functions to access visual parameters //-------------------------------------------------------------------- - void setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user ); - LLColor4 getClothesColor( ETextureIndex te ); - BOOL teToColorParams( ETextureIndex te, const char* param_name[3] ); +public: + void setClothesColor( LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user ); + LLColor4 getClothesColor( LLVOAvatarDefines::ETextureIndex te ); + BOOL teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] ); BOOL isWearingWearableType( EWearableType type ); //-------------------------------------------------------------------- // texture compositing //-------------------------------------------------------------------- +public: void setLocTexTE( U8 te, LLViewerImage* image, BOOL set_by_user ); void setupComposites(); //-------------------------------------------------------------------- - // member variables - //-------------------------------------------------------------------- - - BOOL mDirtyMesh; - - LLFace *mShadow0Facep; - LLFace *mShadow1Facep; - - LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations - - //-------------------------------------------------------------------- - // State of deferred character building + // Handling partially loaded avatars (Ruth) //-------------------------------------------------------------------- - BOOL mIsBuilt; +public: + BOOL isFullyLoaded(); + BOOL updateIsFullyLoaded(); +private: + BOOL mFullyLoaded; + BOOL mPreviousFullyLoaded; + BOOL mFullyLoadedInitialized; + S32 mFullyLoadedFrameCounter; + LLFrameTimer mFullyLoadedTimer; //-------------------------------------------------------------------- - // skeleton for skinned avatar + // Collision Volumes //-------------------------------------------------------------------- - S32 mNumJoints; - LLViewerJoint *mSkeleton; - +public: S32 mNumCollisionVolumes; LLViewerJointCollisionVolume* mCollisionVolumes; //-------------------------------------------------------------------- // cached pointers to well known joints //-------------------------------------------------------------------- - LLViewerJoint *mPelvisp; - LLViewerJoint *mTorsop; - LLViewerJoint *mChestp; - LLViewerJoint *mNeckp; - LLViewerJoint *mHeadp; - LLViewerJoint *mSkullp; - LLViewerJoint *mEyeLeftp; - LLViewerJoint *mEyeRightp; - LLViewerJoint *mHipLeftp; - LLViewerJoint *mHipRightp; - LLViewerJoint *mKneeLeftp; - LLViewerJoint *mKneeRightp; - LLViewerJoint *mAnkleLeftp; - LLViewerJoint *mAnkleRightp; - LLViewerJoint *mFootLeftp; - LLViewerJoint *mFootRightp; - LLViewerJoint *mWristLeftp; - LLViewerJoint *mWristRightp; - - //-------------------------------------------------------------------- - // special purpose joint for HUD attachments - //-------------------------------------------------------------------- - LLViewerJoint *mScreenp; - - //-------------------------------------------------------------------- - // mesh objects for skinned avatar - //-------------------------------------------------------------------- - LLViewerJoint mHairLOD; - LLViewerJointMesh mHairMesh0; - LLViewerJointMesh mHairMesh1; - LLViewerJointMesh mHairMesh2; - LLViewerJointMesh mHairMesh3; - LLViewerJointMesh mHairMesh4; - LLViewerJointMesh mHairMesh5; - - LLViewerJoint mHeadLOD; - LLViewerJointMesh mHeadMesh0; - LLViewerJointMesh mHeadMesh1; - LLViewerJointMesh mHeadMesh2; - LLViewerJointMesh mHeadMesh3; - LLViewerJointMesh mHeadMesh4; - - LLViewerJoint mEyeLashLOD; - LLViewerJointMesh mEyeLashMesh0; - - LLViewerJoint mUpperBodyLOD; - LLViewerJointMesh mUpperBodyMesh0; - LLViewerJointMesh mUpperBodyMesh1; - LLViewerJointMesh mUpperBodyMesh2; - LLViewerJointMesh mUpperBodyMesh3; - LLViewerJointMesh mUpperBodyMesh4; - - LLViewerJoint mLowerBodyLOD; - LLViewerJointMesh mLowerBodyMesh0; - LLViewerJointMesh mLowerBodyMesh1; - LLViewerJointMesh mLowerBodyMesh2; - LLViewerJointMesh mLowerBodyMesh3; - LLViewerJointMesh mLowerBodyMesh4; - - LLViewerJoint mEyeBallLeftLOD; - LLViewerJointMesh mEyeBallLeftMesh0; - LLViewerJointMesh mEyeBallLeftMesh1; - - LLViewerJoint mEyeBallRightLOD; - LLViewerJointMesh mEyeBallRightMesh0; - LLViewerJointMesh mEyeBallRightMesh1; - - LLViewerJoint mSkirtLOD; - LLViewerJointMesh mSkirtMesh0; - LLViewerJointMesh mSkirtMesh1; - LLViewerJointMesh mSkirtMesh2; - LLViewerJointMesh mSkirtMesh3; - LLViewerJointMesh mSkirtMesh4; - - typedef std::multimap<std::string, LLPolyMesh*> mesh_map_t; - mesh_map_t mMeshes; - - S32 mNumInitFaces ; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. - //-------------------------------------------------------------------- - // true if this avatar is for this viewers agent - //-------------------------------------------------------------------- - BOOL mIsSelf; - - //-------------------------------------------------------------------- - // texture ids and pointers - //-------------------------------------------------------------------- - LLPointer<LLViewerImage> mShadowImagep; - - LLUUID mLastHeadBakedID; - LLUUID mLastUpperBodyBakedID; - LLUUID mLastLowerBodyBakedID; - LLUUID mLastEyesBakedID; - LLUUID mLastSkirtBakedID; +public: + LLViewerJoint* mPelvisp; + LLViewerJoint* mTorsop; + LLViewerJoint* mChestp; + LLViewerJoint* mNeckp; + LLViewerJoint* mHeadp; + LLViewerJoint* mSkullp; + LLViewerJoint* mEyeLeftp; + LLViewerJoint* mEyeRightp; + LLViewerJoint* mHipLeftp; + LLViewerJoint* mHipRightp; + LLViewerJoint* mKneeLeftp; + LLViewerJoint* mKneeRightp; + LLViewerJoint* mAnkleLeftp; + LLViewerJoint* mAnkleRightp; + LLViewerJoint* mFootLeftp; + LLViewerJoint* mFootRightp; + LLViewerJoint* mWristLeftp; + LLViewerJoint* mWristRightp; //-------------------------------------------------------------------- // impostor state //-------------------------------------------------------------------- +public: LLRenderTarget mImpostor; + BOOL mNeedsImpostorUpdate; +private: LLVector3 mImpostorOffset; LLVector2 mImpostorDim; - BOOL mNeedsImpostorUpdate; BOOL mNeedsAnimUpdate; LLVector3 mImpostorExtents[2]; LLVector3 mImpostorAngle; F32 mImpostorDistance; F32 mImpostorPixelArea; LLVector3 mLastAnimExtents[2]; - + //-------------------------------------------------------------------- // Misc Render State //-------------------------------------------------------------------- +public: BOOL mIsDummy; // For special views S32 mSpecialRenderMode; // Special lighting //-------------------------------------------------------------------- - // Animation timer - //-------------------------------------------------------------------- - LLTimer mAnimTimer; - F32 mTimeLast; - - //-------------------------------------------------------------------- - // Measures speed (for diagnostics mostly). - //-------------------------------------------------------------------- - F32 mSpeedAccum; - - //-------------------------------------------------------------------- // animation state data //-------------------------------------------------------------------- +public: typedef std::map<LLUUID, S32>::iterator AnimIterator; - std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value - std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value + std::map<LLUUID, S32> mSignaledAnimations; // requested state of Animation name/value + std::map<LLUUID, S32> mPlayingAnimations; // current state of Animation name/value typedef std::multimap<LLUUID, LLUUID> AnimationSourceMap; typedef AnimationSourceMap::iterator AnimSourceIterator; - AnimationSourceMap mAnimationSources; // object ids that triggered anim ids - - BOOL mTurning; // controls hysteresis on avatar rotation - - //-------------------------------------------------------------------- - // misc. animation related state - //-------------------------------------------------------------------- - F32 mSpeed; + AnimationSourceMap mAnimationSources; // object ids that triggered anim ids //-------------------------------------------------------------------- - // Shadow stuff + // Shadowing //-------------------------------------------------------------------- +public: + void updateShadowFaces(); LLDrawable* mShadow; - BOOL mInAir; - LLFrameTimer mTimeInAir; +private: + LLFace* mShadow0Facep; + LLFace* mShadow1Facep; + LLPointer<LLViewerImage> mShadowImagep; //-------------------------------------------------------------------- // Keeps track of foot step state for generating sounds //-------------------------------------------------------------------- +public: + void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } + LLVector4 mFootPlane; +private: BOOL mWasOnGroundLeft; BOOL mWasOnGroundRight; - LLVector4 mFootPlane; - - //-------------------------------------------------------------------- - // Keep track of the material being stepped on - //-------------------------------------------------------------------- - BOOL mStepOnLand; - U8 mStepMaterial; - LLVector3 mStepObjectVelocity; //-------------------------------------------------------------------- // Pelvis height adjustment members. //-------------------------------------------------------------------- - F32 mPelvisToFoot; +public: LLVector3 mBodySize; S32 mLastSkeletonSerialNum; - - //-------------------------------------------------------------------- - // current head position - //-------------------------------------------------------------------- - LLVector3 mHeadOffset; - - //-------------------------------------------------------------------- - // avatar skeleton - //-------------------------------------------------------------------- - LLViewerJoint mRoot; - - //-------------------------------------------------------------------- - // sitting state - //-------------------------------------------------------------------- - BOOL mIsSitting; +private: + F32 mPelvisToFoot; //-------------------------------------------------------------------- // Display the name, then optionally fade it out //-------------------------------------------------------------------- - LLFrameTimer mTimeVisible; +public: + LLFrameTimer mChatTimer; LLPointer<LLHUDText> mNameText; +private: + LLFrameTimer mTimeVisible; std::deque<LLChat> mChats; - LLFrameTimer mChatTimer; BOOL mTyping; LLFrameTimer mTypingTimer; //-------------------------------------------------------------------- - // destroy mesh data after being invisible for a while - //-------------------------------------------------------------------- - BOOL mMeshValid; - BOOL mVisible; - LLFrameTimer mMeshInvisibleTime; - - //-------------------------------------------------------------------- // wind rippling in clothes //-------------------------------------------------------------------- +public: LLVector4 mWindVec; - F32 mWindFreq; F32 mRipplePhase; + BOOL mBelowWater; +private: + F32 mWindFreq; LLFrameTimer mRippleTimer; F32 mRippleTimeLast; LLVector3 mRippleAccel; LLVector3 mLastVel; - BOOL mBelowWater; //-------------------------------------------------------------------- // appearance morphing //-------------------------------------------------------------------- +public: + BOOL mAppearanceAnimating; +private: LLFrameTimer mAppearanceMorphTimer; BOOL mAppearanceAnimSetByUser; F32 mLastAppearanceBlendTime; - BOOL mAppearanceAnimating; - - //-------------------------------------------------------------------- - // we're morphing for lip sync - //-------------------------------------------------------------------- - bool mLipSyncActive; //-------------------------------------------------------------------- - // cached pointers morphs for lip sync + // Attachments //-------------------------------------------------------------------- - LLVisualParam *mOohMorph; - LLVisualParam *mAahMorph; +public: + // map of attachment points, by ID + typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t; + attachment_map_t mAttachmentPoints; + std::vector<LLPointer<LLViewerObject> > mPendingAttachment; //-------------------------------------------------------------------- - // static members + // static preferences that are controlled by user settings/menus //-------------------------------------------------------------------- +public: + static S32 sRenderName; + static BOOL sRenderGroupTitles; static S32 sMaxVisible; static F32 sRenderDistance; //distance at which avatars will render (affected by control "RenderAvatarMaxVisible") - static S32 sCurJoint; - static S32 sCurVolume; static BOOL sShowAnimationDebug; // show animation debug info static BOOL sUseImpostors; //use impostors for far away avatars static BOOL sShowFootPlane; // show foot collision plane reported by server static BOOL sShowCollisionVolumes; // show skeletal collision volumes static BOOL sVisibleInFirstPerson; - static S32 sMaxOtherAvatarsToComposite; - static S32 sNumLODChangesThisFrame; - - // global table of sound ids per material, and the ground - static LLUUID sStepSounds[LL_MCODE_END]; - static LLUUID sStepSoundOnLand; - - static S32 sRenderName; - static BOOL sRenderGroupTitles; static S32 sNumVisibleChatBubbles; static BOOL sDebugInvisible; static BOOL sShowAttachmentPoints; + static F32 sLODFactor; // user-settable LOD factor + static BOOL sJointDebug; // output total number of joints being touched for each avatar + static BOOL sDebugAvatarRotation; + + static S32 sNumVisibleAvatars; // Number of instances of this class + + //-------------------------------------------------------------------- + // Miscellaneous public variables. + //-------------------------------------------------------------------- +public: + BOOL mInAir; + LLFrameTimer mTimeInAir; + LLVector3 mHeadOffset; // current head position + LLViewerJoint mRoot; // avatar skeleton + BOOL mIsSitting; // sitting state + + //-------------------------------------------------------------------- + // Private member variables. + //-------------------------------------------------------------------- +private: + BOOL mIsSelf; // True if this avatar is for this viewer's agent + + LLViewerJoint *mScreenp; // special purpose joint for HUD attachments + BOOL mIsBuilt; // state of deferred character building + F32 mSpeedAccum; // measures speed (for diagnostics mostly). + + + // LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations + BOOL mDirtyMesh; + BOOL mTurning; // controls hysteresis on avatar rotation + F32 mSpeed; // misc. animation repeated state - // Number of instances of this class - static S32 sNumVisibleAvatars; + // Keep track of the material being stepped on + BOOL mStepOnLand; + U8 mStepMaterial; + LLVector3 mStepObjectVelocity; + + // Destroy mesh data after being invisible for a while + BOOL mMeshValid; + BOOL mVisible; + LLFrameTimer mMeshInvisibleTime; + + // Lip synch morph stuff + bool mLipSyncActive; // we're morphing for lip sync + LLVisualParam* mOohMorph; // cached pointers morphs for lip sync + LLVisualParam* mAahMorph; // cached pointers morphs for lip sync + + // Skeleton for skinned avatar + S32 mNumJoints; + LLViewerJoint* mSkeleton; // Scratch textures used for compositing static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; static S32 sScratchTexBytes; - // map of attachment points, by ID - typedef std::map<S32, LLViewerJointAttachment*> attachment_map_t; - attachment_map_t mAttachmentPoints; + // Global table of sound ids per material, and the ground + const static LLUUID sStepSounds[LL_MCODE_END]; + const static LLUUID sStepSoundOnLand; - std::vector<LLPointer<LLViewerObject> > mPendingAttachment; - - // xml parse tree of avatar config file + // Xml parse tree of avatar config file static LLXmlTree sXMLTree; - // xml parse tree of avatar skeleton file + // Xml parse tree of avatar skeleton file static LLXmlTree sSkeletonXMLTree; - // user-settable LOD factor - static F32 sLODFactor; - - // output total number of joints being touched for each avatar - static BOOL sJointDebug; - static ETextureIndex sBakedTextureIndices[BAKED_TEXTURE_COUNT]; - - static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars - static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) - static F32 sGreyTime; // Total seconds with >=1 grey avatars - static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) + // Voice Visualizer is responsible for detecting the user's voice signal, and when the + // user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations + LLVoiceVisualizer* mVoiceVisualizer; + int mCurrentGesticulationLevel; - //-------------------------------------------------------------------- - // Texture Layer Sets and Global Colors - //-------------------------------------------------------------------- - LLTexLayerSet* mHeadLayerSet; - LLTexLayerSet* mUpperBodyLayerSet; - LLTexLayerSet* mLowerBodyLayerSet; - LLTexLayerSet* mEyesLayerSet; - LLTexLayerSet* mSkirtLayerSet; - + // Animation timer + LLTimer mAnimTimer; + F32 mTimeLast; -protected: LLPointer<LLHUDEffectSpiral> mBeam; LLFrameTimer mBeamTimer; - LLFrameTimer mEditEffectTimer; - F32 mRenderPriority; F32 mAdjustedPixelArea; LLWString mNameString; @@ -954,27 +612,11 @@ protected: //-------------------------------------------------------------------- // local textures for compositing. //-------------------------------------------------------------------- - - LLPointer<LLViewerImage> mLocalTexture[ LOCTEX_NUM_ENTRIES ]; - BOOL mLocalTextureBaked[ LOCTEX_NUM_ENTRIES ]; // Texture is covered by a baked texture - S32 mLocalTextureDiscard[ LOCTEX_NUM_ENTRIES ]; - LLUUID mSavedTE[ TEX_NUM_ENTRIES ]; +private: + LLUUID mSavedTE[ LLVOAvatarDefines::TEX_NUM_INDICES ]; BOOL mFirstTEMessageReceived; BOOL mFirstAppearanceMessageReceived; - - BOOL mHeadBakedLoaded; - S32 mHeadMaskDiscard; - BOOL mUpperBakedLoaded; - S32 mUpperMaskDiscard; - BOOL mLowerBakedLoaded; - S32 mLowerMaskDiscard; - BOOL mEyesBakedLoaded; - BOOL mSkirtBakedLoaded; - - //RN: testing 2 pass rendering - U32 mHeadMaskTexName; - U32 mUpperMaskTexName; - U32 mLowerMaskTexName; + BOOL mHasBakedHair; BOOL mCulled; U32 mVisibilityRank; @@ -985,6 +627,7 @@ protected: //-------------------------------------------------------------------- // Global Colors //-------------------------------------------------------------------- +private: LLTexGlobalColor* mTexSkinColor; LLTexGlobalColor* mTexHairColor; LLTexGlobalColor* mTexEyeColor; @@ -992,61 +635,127 @@ protected: BOOL mNeedsSkin; //if TRUE, avatar has been animated and verts have not been updated S32 mUpdatePeriod; - static LLVOAvatarSkeletonInfo* sSkeletonInfo; - static LLVOAvatarInfo* sAvatarInfo; - - //-------------------------------------------------------------------- - // Handling partially loaded avatars (Ruth) + // Internal functions //-------------------------------------------------------------------- -public: - BOOL isFullyLoaded(); - BOOL updateIsFullyLoaded(); -private: - BOOL mFullyLoaded; - BOOL mPreviousFullyLoaded; - BOOL mFullyLoadedInitialized; - S32 mFullyLoadedFrameCounter; - LLFrameTimer mFullyLoadedTimer; - protected: + void buildCharacter(); + void releaseMeshData(); + void restoreMeshData(); + void updateMeshData(); + void computeBodySize(); + const LLUUID& getStepSound() const; + BOOL needsRenderBeam(); + + BOOL allocateCollisionVolumes( U32 num ); + void resetHUDAttachments(); + static void getAnimLabels( LLDynamicArray<std::string>* labels ); + static void getAnimNames( LLDynamicArray<std::string>* names ); + //-------------------------------------------------------------------- + // Textures and Layers + //-------------------------------------------------------------------- +protected: BOOL loadSkeletonNode(); BOOL loadMeshNodes(); - BOOL isFullyBaked(); - void deleteLayerSetCaches(); + void deleteLayerSetCaches(bool clearAll = true); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); - static void onBakedTextureMasksLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); - - void setLocalTexture(ELocTexIndex i, LLViewerImage* tex, BOOL baked_version_exits); - - void requestLayerSetUpdate(LLVOAvatar::ELocTexIndex i); - void addLocalTextureStats(LLVOAvatar::ELocTexIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); + void setLocalTexture(LLVOAvatarDefines::ETextureIndex i, LLViewerImage* tex, BOOL baked_version_exits); + void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); + void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); void addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level); static void onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); static void onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); void useBakedTexture(const LLUUID& id); void dumpAvatarTEs(const std::string& context); void removeMissingBakedTextures(); - LLTexLayerSet* getLayerSet(ETextureIndex index) const; + LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; LLHost getObjectHost() const; - S32 getLocalDiscardLevel( S32 index); + S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex index); +public: + static void updateFreezeCounter(S32 counter = 0 ); +private: + static S32 sFreezeCounter; + //----------------------------------------------------------------------------------------------- + // Avatar skeleton setup. + //----------------------------------------------------------------------------------------------- +private: + BOOL loadAvatar(); + BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); //----------------------------------------------------------------------------------------------- - // the Voice Visualizer is responsible for detecting the user's voice signal, and when the - // user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations + // Per-avatar information about texture data. + // To-do: Move this to private implementation class //----------------------------------------------------------------------------------------------- - private: - LLVoiceVisualizer * mVoiceVisualizer; - int mCurrentGesticulationLevel; +private: + struct BakedTextureData + { + LLUUID mLastTextureIndex; + LLTexLayerSet* mTexLayerSet; + bool mIsLoaded; + LLVOAvatarDefines::ETextureIndex mTextureIndex; + U32 mMaskTexName; + // Stores pointers to the joint meshes that this baked texture deals with + std::vector< LLViewerJointMesh * > mMeshes; // std::vector<LLViewerJointMesh> mJoints[i]->mMeshParts + }; + typedef std::vector<BakedTextureData> bakedtexturedata_vec_t; + bakedtexturedata_vec_t mBakedTextureData; + + struct LocalTextureData + { + LocalTextureData() : mIsBakedReady(FALSE), mDiscard(MAX_DISCARD_LEVEL+1), mImage(NULL) + {} + LLPointer<LLViewerImage> mImage; + BOOL mIsBakedReady; + S32 mDiscard; + }; + typedef std::map<LLVOAvatarDefines::ETextureIndex, LocalTextureData> localtexture_map_t; + localtexture_map_t mLocalTextureData; + + typedef std::multimap<std::string, LLPolyMesh*> polymesh_map_t; + polymesh_map_t mMeshes; + std::vector<LLViewerJoint *> mMeshLOD; + S32 mNumInitFaces ; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. + //----------------------------------------------------------------------------------------------- + // Static texture/mesh/baked dictionary for avatars + //----------------------------------------------------------------------------------------------- +public: + static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); + static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); private: - static S32 sFreezeCounter ; + static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } + static LLVOAvatarDefines::LLVOAvatarDictionary *sAvatarDictionary; + static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; + static LLVOAvatarXmlInfo* sAvatarXmlInfo; + + //----------------------------------------------------------------------------------------------- + // Diagnostics + //----------------------------------------------------------------------------------------------- public: - static void updateFreezeCounter(S32 counter = 0 ) ; + static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars + static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) + static F32 sGreyTime; // Total seconds with >=1 grey avatars + static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) + + const std::string getBakedStatusForPrintout() const; }; +//----------------------------------------------------------------------------------------------- +// Inlines +//----------------------------------------------------------------------------------------------- +inline BOOL LLVOAvatar::isTextureDefined(U8 te) const +{ + return (getTEImage(te)->getID() != IMG_DEFAULT_AVATAR && getTEImage(te)->getID() != IMG_DEFAULT); +} + +inline BOOL LLVOAvatar::isTextureVisible(U8 te) const +{ + return (!isTextureDefined(te) || getTEImage(te)->getID() != IMG_INVISIBLE); +} + #endif // LL_VO_AVATAR_H diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp new file mode 100644 index 0000000000..19ad90a8e2 --- /dev/null +++ b/indra/newview/llvoavatardefines.cpp @@ -0,0 +1,227 @@ +/** + * @file llvoavatar.cpp + * @brief Implementation of LLVOAvatar class which is a derivation fo LLViewerObject + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llvoavatardefines.h" + +const S32 LLVOAvatarDefines::SCRATCH_TEX_WIDTH = 512; +const S32 LLVOAvatarDefines::SCRATCH_TEX_HEIGHT = 512; +const S32 LLVOAvatarDefines::IMPOSTOR_PERIOD = 2; + +using namespace LLVOAvatarDefines; + +/********************************************************************************* + * Edit this function to add/remove/change textures and mesh definitions for avatars. + */ +void LLVOAvatarDictionary::initData() +{ + // Textures + mTextureMap[TEX_HEAD_BODYPAINT] = new TextureDictionaryEntry("head bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN); + mTextureMap[TEX_UPPER_SHIRT] = new TextureDictionaryEntry("shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", WT_SHIRT); + mTextureMap[TEX_LOWER_PANTS] = new TextureDictionaryEntry("pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", WT_PANTS); + mTextureMap[TEX_EYES_IRIS] = new TextureDictionaryEntry("iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", WT_EYES); + mTextureMap[TEX_HAIR] = new TextureDictionaryEntry("hair", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", WT_HAIR); + mTextureMap[TEX_UPPER_BODYPAINT] = new TextureDictionaryEntry("upper bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN); + mTextureMap[TEX_LOWER_BODYPAINT] = new TextureDictionaryEntry("lower bodypaint", TRUE, BAKED_NUM_INDICES, "", WT_SKIN); + mTextureMap[TEX_LOWER_SHOES] = new TextureDictionaryEntry("shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", WT_SHOES); + mTextureMap[TEX_LOWER_SOCKS] = new TextureDictionaryEntry("socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", WT_SOCKS); + mTextureMap[TEX_UPPER_JACKET] = new TextureDictionaryEntry("upper jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET); + mTextureMap[TEX_LOWER_JACKET] = new TextureDictionaryEntry("lower jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", WT_JACKET); + mTextureMap[TEX_UPPER_GLOVES] = new TextureDictionaryEntry("gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", WT_GLOVES); + mTextureMap[TEX_UPPER_UNDERSHIRT] = new TextureDictionaryEntry("undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERSHIRT); + mTextureMap[TEX_LOWER_UNDERPANTS] = new TextureDictionaryEntry("underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", WT_UNDERPANTS); + mTextureMap[TEX_SKIRT] = new TextureDictionaryEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", WT_SKIRT); + mTextureMap[TEX_HEAD_BAKED] = new TextureDictionaryEntry("head-baked", FALSE, BAKED_HEAD); + mTextureMap[TEX_UPPER_BAKED] = new TextureDictionaryEntry("upper-baked", FALSE, BAKED_UPPER); + mTextureMap[TEX_LOWER_BAKED] = new TextureDictionaryEntry("lower-baked", FALSE, BAKED_LOWER); + mTextureMap[TEX_EYES_BAKED] = new TextureDictionaryEntry("eyes-baked", FALSE, BAKED_EYES); + mTextureMap[TEX_HAIR_BAKED] = new TextureDictionaryEntry("hair-baked", FALSE, BAKED_HAIR); + mTextureMap[TEX_SKIRT_BAKED] = new TextureDictionaryEntry("skirt-baked", FALSE, BAKED_SKIRT); + + // Baked textures + mBakedTextureMap[BAKED_HEAD] = new BakedDictionaryEntry(TEX_HEAD_BAKED, "head", 1, TEX_HEAD_BODYPAINT); + mBakedTextureMap[BAKED_UPPER] = new BakedDictionaryEntry(TEX_UPPER_BAKED, "upper_body", 5, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT,TEX_UPPER_JACKET,TEX_UPPER_GLOVES,TEX_UPPER_UNDERSHIRT); + mBakedTextureMap[BAKED_LOWER] = new BakedDictionaryEntry(TEX_LOWER_BAKED, "lower_body", 6, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES,TEX_LOWER_SOCKS,TEX_LOWER_JACKET,TEX_LOWER_UNDERPANTS); + mBakedTextureMap[BAKED_EYES] = new BakedDictionaryEntry(TEX_EYES_BAKED, "eyes", 1, TEX_EYES_IRIS); + mBakedTextureMap[BAKED_SKIRT] = new BakedDictionaryEntry(TEX_SKIRT_BAKED, "skirt", 1, TEX_SKIRT); + mBakedTextureMap[BAKED_HAIR] = new BakedDictionaryEntry(TEX_HAIR_BAKED, "hair", 1, TEX_HAIR); + + // Meshes + mMeshMap[MESH_ID_HAIR] = new MeshDictionaryEntry(BAKED_HAIR, "hairMesh", 6, LLViewerJoint::PN_4); + mMeshMap[MESH_ID_HEAD] = new MeshDictionaryEntry(BAKED_HEAD, "headMesh", 5, LLViewerJoint::PN_5); + mMeshMap[MESH_ID_EYELASH] = new MeshDictionaryEntry(BAKED_HEAD, "eyelashMesh", 1, LLViewerJoint::PN_0); // no baked mesh associated currently + mMeshMap[MESH_ID_UPPER_BODY] = new MeshDictionaryEntry(BAKED_UPPER, "upperBodyMesh", 5, LLViewerJoint::PN_1); + mMeshMap[MESH_ID_LOWER_BODY] = new MeshDictionaryEntry(BAKED_LOWER, "lowerBodyMesh", 5, LLViewerJoint::PN_2); + mMeshMap[MESH_ID_EYEBALL_LEFT] = new MeshDictionaryEntry(BAKED_EYES, "eyeBallLeftMesh", 2, LLViewerJoint::PN_3); + mMeshMap[MESH_ID_EYEBALL_RIGHT] = new MeshDictionaryEntry(BAKED_EYES, "eyeBallRightMesh", 2, LLViewerJoint::PN_3); + mMeshMap[MESH_ID_SKIRT] = new MeshDictionaryEntry(BAKED_SKIRT, "skirtMesh", 5, LLViewerJoint::PN_5); + + // Wearables + mWearableMap[BAKED_HEAD] = new WearableDictionaryEntry("18ded8d6-bcfc-e415-8539-944c0f5ea7a6", 3, WT_SHAPE, WT_SKIN, WT_HAIR); + mWearableMap[BAKED_UPPER] = new WearableDictionaryEntry("338c29e3-3024-4dbb-998d-7c04cf4fa88f", 6, WT_SHAPE, WT_SKIN, WT_SHIRT, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT); + mWearableMap[BAKED_LOWER] = new WearableDictionaryEntry("91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f", 7, WT_SHAPE, WT_SKIN, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_UNDERPANTS); + mWearableMap[BAKED_EYES] = new WearableDictionaryEntry("b2cf28af-b840-1071-3c6a-78085d8128b5", 1, WT_EYES); + mWearableMap[BAKED_SKIRT] = new WearableDictionaryEntry("ea800387-ea1a-14e0-56cb-24f2022f969a", 1, WT_SKIRT); + mWearableMap[BAKED_HAIR] = new WearableDictionaryEntry("0af1ef7c-ad24-11dd-8790-001f5bf833e8", 1, WT_HAIR); +} + +/* + * + *********************************************************************************/ + +LLVOAvatarDictionary::LLVOAvatarDictionary() +{ + initData(); + createAssociations(); +} + +// Baked textures are composites of textures; for each such composited texture, +// map it to the baked texture. +void LLVOAvatarDictionary::createAssociations() +{ + for (baked_map_t::const_iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++) + { + const EBakedTextureIndex baked_index = (iter->first); + const BakedDictionaryEntry *dict = (iter->second); + + // For each texture that this baked texture index affects, associate those textures + // with this baked texture index. + for (texture_vec_t::const_iterator local_texture_iter = dict->mLocalTextures.begin(); + local_texture_iter != dict->mLocalTextures.end(); + local_texture_iter++) + { + const ETextureIndex local_texture_index = (ETextureIndex) *local_texture_iter; + mTextureMap[local_texture_index]->mIsUsedByBakedTexture = true; + mTextureMap[local_texture_index]->mBakedTextureIndex = baked_index; + } + } + +} + +LLVOAvatarDictionary::TextureDictionaryEntry::TextureDictionaryEntry(const std::string &name, + bool is_local_texture, + EBakedTextureIndex baked_texture_index, + const std::string &default_image_name, + EWearableType wearable_type) : + mName(name), + mIsLocalTexture(is_local_texture), + mIsBakedTexture(!is_local_texture), + mIsUsedByBakedTexture(baked_texture_index != BAKED_NUM_INDICES), + mBakedTextureIndex(baked_texture_index), + mDefaultImageName(default_image_name), + mWearableType(wearable_type) +{ +} + +LLVOAvatarDictionary::MeshDictionaryEntry::MeshDictionaryEntry(EBakedTextureIndex baked_index, + const std::string &name, + U8 level, + LLViewerJoint::PickName pick) : + mBakedID(baked_index), + mName(name), + mLOD(level), + mPickName(pick) +{ +} +LLVOAvatarDictionary::BakedDictionaryEntry::BakedDictionaryEntry(ETextureIndex tex_index, + const std::string &name, + U32 num_local_textures, ... ) : + mName(name), + mTextureIndex(tex_index) + +{ + va_list argp; + va_start(argp, num_local_textures); + for (U8 i=0; i < num_local_textures; i++) + { + ETextureIndex t = (ETextureIndex)va_arg(argp,int); + mLocalTextures.push_back(t); + } +} + +LLVOAvatarDictionary::WearableDictionaryEntry::WearableDictionaryEntry(const std::string &hash_name, + U32 num_wearables, ... ) : + mHashID(LLUUID(hash_name)) +{ + va_list argp; + va_start(argp, num_wearables); + for (U8 i=0; i < num_wearables; i++) + { + EWearableType t = (EWearableType)va_arg(argp,int); + mWearablesVec.push_back(t); + } +} + +//virtual +LLVOAvatarDictionary::~LLVOAvatarDictionary() +{ + for (mesh_map_t::iterator iter = mMeshMap.begin(); iter != mMeshMap.end(); iter++) + delete (iter->second); + for (baked_map_t::iterator iter = mBakedTextureMap.begin(); iter != mBakedTextureMap.end(); iter++) + delete (iter->second); + for (texture_map_t::iterator iter = mTextureMap.begin(); iter != mTextureMap.end(); iter++) + delete (iter->second); +} + +const LLVOAvatarDictionary::MeshDictionaryEntry *LLVOAvatarDictionary::getMesh(EMeshIndex index) const +{ + mesh_map_t::const_iterator mesh_iter = mMeshMap.find(index); + if (mesh_iter == mMeshMap.end()) return NULL; + return mesh_iter->second; +} + +const LLVOAvatarDictionary::BakedDictionaryEntry *LLVOAvatarDictionary::getBakedTexture(EBakedTextureIndex index) const +{ + baked_map_t::const_iterator baked_iter = mBakedTextureMap.find(index); + if (baked_iter == mBakedTextureMap.end()) return NULL; + return baked_iter->second; +} + +const LLVOAvatarDictionary::TextureDictionaryEntry *LLVOAvatarDictionary::getTexture(ETextureIndex index) const +{ + texture_map_t::const_iterator texture_iter = mTextureMap.find(index); + if (texture_iter == mTextureMap.end()) return NULL; + return texture_iter->second; +} + +const LLVOAvatarDictionary::WearableDictionaryEntry *LLVOAvatarDictionary::getWearable(EBakedTextureIndex index) const +{ + wearable_map_t::const_iterator wearable_iter = mWearableMap.find(index); + if (wearable_iter == mWearableMap.end()) return NULL; + return wearable_iter->second; +} + + + +ETextureIndex LLVOAvatarDefines::getTextureIndex(EBakedTextureIndex index) +{ + return LLVOAvatarDictionary::getInstance()->getBakedTexture(index)->mTextureIndex; +} diff --git a/indra/newview/llvoavatardefines.h b/indra/newview/llvoavatardefines.h new file mode 100644 index 0000000000..bc1a1f1c1f --- /dev/null +++ b/indra/newview/llvoavatardefines.h @@ -0,0 +1,209 @@ +/** + * @file llvoavatar.h + * @brief Declaration of LLVOAvatar class which is a derivation fo + * LLViewerObject + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLVOAVATAR_DEFINES_H +#define LLVOAVATAR_DEFINES_H + +#include <vector> +#include "llwearable.h" +#include "llviewerjoint.h" + +namespace LLVOAvatarDefines +{ + +extern const S32 SCRATCH_TEX_WIDTH; +extern const S32 SCRATCH_TEX_HEIGHT; +extern const S32 IMPOSTOR_PERIOD; + +//-------------------------------------------------------------------- +// texture entry assignment +//-------------------------------------------------------------------- +enum ETextureIndex +{ + TEX_HEAD_BODYPAINT = 0, + TEX_UPPER_SHIRT, + TEX_LOWER_PANTS, + TEX_EYES_IRIS, + TEX_HAIR, + TEX_UPPER_BODYPAINT, + TEX_LOWER_BODYPAINT, + TEX_LOWER_SHOES, + TEX_HEAD_BAKED, // Pre-composited + TEX_UPPER_BAKED, // Pre-composited + TEX_LOWER_BAKED, // Pre-composited + TEX_EYES_BAKED, // Pre-composited + TEX_LOWER_SOCKS, + TEX_UPPER_JACKET, + TEX_LOWER_JACKET, + TEX_UPPER_GLOVES, + TEX_UPPER_UNDERSHIRT, + TEX_LOWER_UNDERPANTS, + TEX_SKIRT, + TEX_SKIRT_BAKED, // Pre-composited + TEX_HAIR_BAKED, // Pre-composited + TEX_NUM_INDICES +}; // "Note: if TEX_NUM_ENTRIES changes, update AGENT_TEXTURES in llagentinfo.h, mTextureIndexBaked, and BAKED_TEXTURE_COUNT" +// Seraph - Above comment about order is probably obsolete. + +typedef std::vector<ETextureIndex> texture_vec_t; + +enum EBakedTextureIndex +{ + BAKED_HEAD = 0, + BAKED_UPPER, + BAKED_LOWER, + BAKED_EYES, + BAKED_SKIRT, + BAKED_HAIR, + BAKED_NUM_INDICES +}; +typedef std::vector<EBakedTextureIndex> bakedtexture_vec_t; + +// Reference IDs for each mesh. Used as indices for vector of joints +enum EMeshIndex +{ + MESH_ID_HAIR = 0, + MESH_ID_HEAD, + MESH_ID_EYELASH, + MESH_ID_UPPER_BODY, + MESH_ID_LOWER_BODY, + MESH_ID_EYEBALL_LEFT, + MESH_ID_EYEBALL_RIGHT, + MESH_ID_SKIRT, + MESH_ID_NUM_INDICES +}; +typedef std::vector<EMeshIndex> mesh_vec_t; + +typedef std::vector<EWearableType> wearables_vec_t; + +//-------------------------------------------------------------------------------- +// Convenience Functions +//-------------------------------------------------------------------------------- + +// Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED +ETextureIndex getTextureIndex(EBakedTextureIndex t); + + + +//------------------------------------------------------------------------ +// LLVOAvatarDictionary +// +// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e. +// information that is common to all avatars. +// +// This holds const data - it is initialized once and the contents never change after that. +//------------------------------------------------------------------------ +class LLVOAvatarDictionary : public LLSingleton<LLVOAvatarDictionary> +{ +public: + LLVOAvatarDictionary(); + virtual ~LLVOAvatarDictionary(); + + struct TextureDictionaryEntry + { + TextureDictionaryEntry(const std::string &name, + bool is_local_texture, + EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, + const std::string &default_image_name = "", + EWearableType wearable_type = WT_INVALID); + const std::string mName; + const std::string mDefaultImageName; + const EWearableType mWearableType; + // It's either a local texture xor baked + BOOL mIsLocalTexture; + BOOL mIsBakedTexture; + // If it's a local texture, it may be used by a baked texture + BOOL mIsUsedByBakedTexture; + EBakedTextureIndex mBakedTextureIndex; + }; + + struct MeshDictionaryEntry + { + MeshDictionaryEntry(EBakedTextureIndex baked_index, + const std::string &name, + U8 level, + LLViewerJoint::PickName pick); + const std::string mName; // names of mesh types as they are used in avatar_lad.xml + // Levels of Detail for each mesh. Must match levels of detail present in avatar_lad.xml + // Otherwise meshes will be unable to be found, or levels of detail will be ignored + const U8 mLOD; + const EBakedTextureIndex mBakedID; + const LLViewerJoint::PickName mPickName; + }; + + struct BakedDictionaryEntry + { + BakedDictionaryEntry(ETextureIndex tex_index, + const std::string &name, + U32 num_local_textures, ... ); + const ETextureIndex mTextureIndex; + const std::string mName; + texture_vec_t mLocalTextures; + }; + + struct WearableDictionaryEntry + { + WearableDictionaryEntry(const std::string &hash_name, + U32 num_wearables, ... ); + const LLUUID mHashID; + wearables_vec_t mWearablesVec; + }; + + typedef std::map<EBakedTextureIndex, BakedDictionaryEntry*> baked_map_t; + typedef std::map<ETextureIndex, TextureDictionaryEntry*> texture_map_t; + typedef std::map<EMeshIndex, MeshDictionaryEntry*> mesh_map_t; + typedef std::map<EBakedTextureIndex, WearableDictionaryEntry*> wearable_map_t; + + const MeshDictionaryEntry *getMesh(EMeshIndex index) const; + const BakedDictionaryEntry *getBakedTexture(EBakedTextureIndex index) const; + const TextureDictionaryEntry *getTexture(ETextureIndex index) const; + const WearableDictionaryEntry *getWearable(EBakedTextureIndex index) const; + + const texture_map_t &getTextures() const { return mTextureMap; } + const baked_map_t &getBakedTextures() const { return mBakedTextureMap; } + const mesh_map_t &getMeshes() const { return mMeshMap; } + const wearable_map_t &getWearables() const { return mWearableMap; } + +private: + void initData(); + void createAssociations(); + + texture_map_t mTextureMap; + baked_map_t mBakedTextureMap; + mesh_map_t mMeshMap; + wearable_map_t mWearableMap; + +}; // End LLVOAvatarDictionary + +} // End namespace LLVOAvatarDefines + +#endif diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index d69830b5c3..a5f4dc934a 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -49,6 +49,8 @@ #include "llvoavatar.h" #include "llwearable.h" +using namespace LLVOAvatarDefines; + // static S32 LLWearable::sCurrentDefinitionVersion = 1; @@ -392,6 +394,7 @@ BOOL LLWearable::importFile( LLFILE* file ) } else { + mType = WT_COUNT; llwarns << "Bad Wearable asset: bad type #" << type << llendl; return FALSE; } @@ -501,9 +504,9 @@ BOOL LLWearable::isOldVersion() S32 te_count = 0; - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == mType ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType ) { te_count++; if( !is_in_map(mTEMap, te ) ) @@ -555,9 +558,9 @@ BOOL LLWearable::isDirty() } } - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == mType ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType ) { LLViewerImage* avatar_image = avatar->getTEImage( te ); if( !avatar_image ) @@ -565,7 +568,7 @@ BOOL LLWearable::isDirty() llassert( 0 ); continue; } - const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID( te ) ); + const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) ); if( avatar_image->getID() != image_id ) { return TRUE; @@ -607,11 +610,11 @@ void LLWearable::setParamsToDefaults() void LLWearable::setTexturesToDefaults() { mTEMap.clear(); - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == mType ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType ) { - mTEMap[te] = LLVOAvatar::getDefaultTEImageID( te ); + mTEMap[te] = LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ); } } } @@ -654,11 +657,11 @@ void LLWearable::writeToAvatar( BOOL set_by_user ) } // Pull texture entries - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == mType ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType ) { - const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID( te ) ); + const LLUUID& image_id = get_if_there(mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) ); LLViewerImage* image = gImageList.getImage( image_id ); avatar->setLocTexTE( te, image, set_by_user ); } @@ -731,9 +734,9 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user ) // Pull textures LLViewerImage* image = gImageList.getImage( IMG_DEFAULT_AVATAR ); - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == type ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == type ) { avatar->setLocTexTE( te, image, set_by_user ); } @@ -777,9 +780,9 @@ void LLWearable::readFromAvatar() } mTEMap.clear(); - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == mType ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType ) { LLViewerImage* image = avatar->getTEImage( te ); if( image ) @@ -828,11 +831,11 @@ void LLWearable::copyDataFrom( LLWearable* src ) } // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) - for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ ) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) { - if( LLVOAvatar::getTEWearableType( te ) == mType ) + if( LLVOAvatar::getTEWearableType((ETextureIndex) te ) == mType ) { - const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatar::getDefaultTEImageID( te ) ); + const LLUUID& image_id = get_if_there(src->mTEMap, te, LLVOAvatar::getDefaultTEImageID((ETextureIndex) te ) ); mTEMap[te] = image_id; } } diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h index dc1a6744e0..683a8fa928 100644 --- a/indra/newview/llwearable.h +++ b/indra/newview/llwearable.h @@ -66,8 +66,8 @@ class LLWearable public: ~LLWearable(); - const LLAssetID& getID() { return mAssetID; } - const LLTransactionID& getTransactionID() { return mTransactionID; } + const LLAssetID& getID() const { return mAssetID; } + const LLTransactionID& getTransactionID() const { return mTransactionID; } BOOL isDirty(); BOOL isOldVersion(); @@ -84,16 +84,16 @@ public: void setType( EWearableType type ) { mType = type; } void setName( const std::string& name ) { mName = name; } - const std::string& getName() { return mName; } + const std::string& getName() const { return mName; } void setDescription( const std::string& desc ) { mDescription = desc; } - const std::string& getDescription() { return mDescription; } + const std::string& getDescription() const { return mDescription; } void setPermissions( const LLPermissions& p ) { mPermissions = p; } - const LLPermissions& getPermissions() { return mPermissions; } + const LLPermissions& getPermissions() const { return mPermissions; } void setSaleInfo( const LLSaleInfo& info ) { mSaleInfo = info; } - const LLSaleInfo& getSaleInfo() { return mSaleInfo; } + const LLSaleInfo& getSaleInfo() const { return mSaleInfo; } const std::string& getTypeLabel() const { return LLWearable::sTypeLabel[ mType ]; } const std::string& getTypeName() const { return LLWearable::sTypeName[ mType ]; } diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 083d7e1581..512c03fa4d 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -102,6 +102,7 @@ void LLWearableList::getAsset( const LLAssetID& assetID, const std::string& wear // static void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID& uuid, void* userdata, S32 status, LLExtStat ext_status ) { + BOOL isNewWearable = FALSE; LLWearableArrivedData* data = (LLWearableArrivedData*) userdata; LLWearable* wearable = NULL; // NULL indicates failure @@ -124,6 +125,10 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID bool res = wearable->importFile( fp ); if (!res) { + if (wearable->getType() == WT_COUNT) + { + isNewWearable = TRUE; + } delete wearable; wearable = NULL; } @@ -184,7 +189,11 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID LLSD args; // *TODO:translate args["TYPE"] = LLAssetType::lookupHumanReadable(data->mAssetType); - if (data->mName.empty()) + if (isNewWearable) + { + LLNotifications::instance().add("InvalidWearable"); + } + else if (data->mName.empty()) { LLNotifications::instance().add("FailedToFindWearableUnnamed", args); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3a5e41e3ca..d90eaa9d9b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -232,6 +232,7 @@ BOOL LLPipeline::sRenderParticleBeacons = FALSE; BOOL LLPipeline::sRenderSoundBeacons = FALSE; BOOL LLPipeline::sRenderBeacons = FALSE; BOOL LLPipeline::sRenderHighlight = TRUE; +BOOL LLPipeline::sForceOldBakedUpload = FALSE; S32 LLPipeline::sUseOcclusion = 0; BOOL LLPipeline::sDelayVBUpdate = TRUE; BOOL LLPipeline::sFastAlpha = TRUE; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index e8673c7d4c..ca0f4af1ac 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -391,6 +391,7 @@ public: static S32 sCompiles; static BOOL sShowHUDAttachments; + static BOOL sForceOldBakedUpload; // If true will not use capabilities to upload baked textures. static S32 sUseOcclusion; // 0 = no occlusion, 1 = read only, 2 = read/write static BOOL sDelayVBUpdate; static BOOL sFastAlpha; |