From 74c8b028d42a8c5b080bb861e427f38cedd4ad7c Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Fri, 15 Dec 2023 18:26:14 +0100 Subject: SL-20743 Use LLMutex in LLImageBase for internal data thread-safety --- indra/llappearance/llavatarappearance.h | 2 +- indra/llappearance/llpolymorph.cpp | 4 ++-- indra/llappearance/llpolymorph.h | 4 ++-- indra/llappearance/lltexlayer.cpp | 2 +- indra/llappearance/lltexlayer.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index e3444efcf6..787235b235 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -232,7 +232,7 @@ public: //-------------------------------------------------------------------- public: void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer); - virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; + virtual void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; /** Rendering ** ** diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 965b999bd4..223b2b7f1c 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -659,7 +659,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- // applyMask() //----------------------------------------------------------------------------- -void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) +void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) { LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; @@ -780,7 +780,7 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) +void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) // BOOL debugImg = FALSE; diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 29cd373636..954f01811a 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -84,7 +84,7 @@ public: LLPolyVertexMask(const LLPolyVertexMask& pOther); ~LLPolyVertexMask(); - void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); + void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); F32* getMorphMaskWeights(); @@ -170,7 +170,7 @@ public: /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); - void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); + void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); void addPendingMorphMask() { mNumMorphMasksPending++; } void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index ff894eeed3..e426615f1c 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -528,7 +528,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, gGL.setSceneBlendType(LLRender::BT_ALPHA); } -void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components) +void LLTexLayerSet::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components) { mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); } diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 74b421d3ee..ff95d7f5e9 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -203,7 +203,7 @@ public: void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); BOOL isBodyRegion(const std::string& region) const; - void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components); + void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components); BOOL isMorphValid() const; virtual void requestUpdate() = 0; void invalidateMorphMasks(); -- cgit v1.2.3 From 2b31dad40026d8078ea30d0da0656a4078d0f5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 9 Feb 2024 22:26:02 +0100 Subject: miscellaneous: BOOL (int) to real bool --- indra/llappearance/llwearable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 10d668d0af..fdf167aa94 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -307,7 +307,7 @@ LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, // permissions. Thus, we read that out, and fix legacy // objects. It's possible this op would fail, but it should pick // up the vast majority of the tasks. - BOOL has_perm_mask = FALSE; + bool has_perm_mask = false; U32 perm_mask = 0; if( !mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask) ) { -- cgit v1.2.3 From 70f8dc7a4f4be217fea5439e474fc75e567c23c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Sat, 10 Feb 2024 22:37:52 +0100 Subject: miscellaneous: BOOL (int) to real bool --- indra/llappearance/llavatarappearance.cpp | 226 +++++++++++------------ indra/llappearance/llavatarappearance.h | 54 +++--- indra/llappearance/llavatarappearancedefines.cpp | 6 +- indra/llappearance/llavatarappearancedefines.h | 2 +- indra/llappearance/llavatarjoint.h | 4 +- indra/llappearance/llavatarjointmesh.cpp | 4 +- indra/llappearance/lldriverparam.cpp | 12 +- indra/llappearance/lllocaltextureobject.cpp | 16 +- indra/llappearance/llpolymesh.cpp | 44 ++--- indra/llappearance/llpolymorph.cpp | 34 ++-- indra/llappearance/llpolyskeletaldistortion.cpp | 12 +- indra/llappearance/lltexglobalcolor.cpp | 10 +- indra/llappearance/lltexlayer.cpp | 68 +++---- indra/llappearance/lltexlayerparams.cpp | 30 +-- indra/llappearance/llviewervisualparam.cpp | 14 +- indra/llappearance/llwearable.cpp | 10 +- indra/llappearance/llwearabledata.cpp | 12 +- indra/llappearance/llwearabletype.cpp | 4 +- 18 files changed, 281 insertions(+), 281 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 18b03c1f89..1dbca29a86 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -84,13 +84,13 @@ public: std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); mChildren.clear(); } - BOOL parseXml(LLXmlTreeNode* node); + bool parseXml(LLXmlTreeNode* node); private: std::string mName; std::string mSupport; std::string mAliases; - BOOL mIsJoint; + bool mIsJoint; LLVector3 mPos; LLVector3 mEnd; LLVector3 mRot; @@ -115,7 +115,7 @@ public: std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); mBoneInfoList.clear(); } - BOOL parseXml(LLXmlTreeNode* node); + bool parseXml(LLXmlTreeNode* node); S32 getNumBones() const { return mNumBones; } S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } @@ -345,7 +345,7 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml"); } LLXmlTree xml_tree; - BOOL success = xml_tree.parseFile( avatar_file_name, FALSE ); + bool success = xml_tree.parseFile( avatar_file_name, FALSE ); if (!success) { LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL; @@ -575,17 +575,17 @@ void LLAvatarAppearance::computeBodySize() //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree) +bool LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree) { //------------------------------------------------------------------------- // parse the file //------------------------------------------------------------------------- - BOOL parsesuccess = skeleton_xml_tree.parseFile( filename, FALSE ); + bool parsesuccess = skeleton_xml_tree.parseFile( filename, FALSE ); if (!parsesuccess) { LL_ERRS() << "Can't parse skeleton file: " << filename << LL_ENDL; - return FALSE; + return false; } // now sanity check xml file @@ -593,13 +593,13 @@ BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTre if (!root) { LL_ERRS() << "No root node found in avatar skeleton file: " << filename << LL_ENDL; - return FALSE; + return false; } if( !root->hasName( "linden_skeleton" ) ) { LL_ERRS() << "Invalid avatar skeleton file header: " << filename << LL_ENDL; - return FALSE; + return false; } std::string version; @@ -607,16 +607,16 @@ BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTre if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) { LL_ERRS() << "Invalid avatar skeleton file version: " << version << " in file: " << filename << LL_ENDL; - return FALSE; + return false; } - return TRUE; + return true; } //----------------------------------------------------------------------------- // setupBone() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num) +bool LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num) { LLJoint* joint = NULL; @@ -632,7 +632,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent if (!joint) { LL_WARNS() << "Too many bones" << LL_ENDL; - return FALSE; + return false; } joint->setName( info->mName ); } @@ -641,7 +641,7 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent if (volume_num >= (S32)mNumCollisionVolumes) { LL_WARNS() << "Too many collision volumes" << LL_ENDL; - return FALSE; + return false; } joint = (&mCollisionVolumes[volume_num]); joint->setName( info->mName ); @@ -681,17 +681,17 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent { if (!setupBone(child_info, joint, volume_num, joint_num)) { - return FALSE; + return false; } } - return TRUE; + return true; } //----------------------------------------------------------------------------- // allocateCharacterJoints() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num ) +bool LLAvatarAppearance::allocateCharacterJoints( U32 num ) { if (mSkeleton.size() != num) { @@ -700,14 +700,14 @@ BOOL LLAvatarAppearance::allocateCharacterJoints( U32 num ) mNumBones = num; } - return TRUE; + return true; } //----------------------------------------------------------------------------- // buildSkeleton() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) +bool LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) { LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL; @@ -715,7 +715,7 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) if (!allocateCharacterJoints(info->mNumBones)) { LL_ERRS() << "Can't allocate " << info->mNumBones << " joints" << LL_ENDL; - return FALSE; + return false; } // allocate volumes @@ -724,7 +724,7 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) { LL_ERRS() << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << LL_ENDL; - return FALSE; + return false; } } @@ -735,11 +735,11 @@ BOOL LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) if (!setupBone(bone_info, NULL, current_volume_num, current_joint_num)) { LL_ERRS() << "Error parsing bone in skeleton file" << LL_ENDL; - return FALSE; + return false; } } - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -822,7 +822,7 @@ void LLAvatarAppearance::buildCharacter() //------------------------------------------------------------------------- LLTimer timer; - BOOL status = loadAvatar(); + bool status = loadAvatar(); stop_glerror(); // gPrintMessagesThisFrame = TRUE; @@ -900,7 +900,7 @@ void LLAvatarAppearance::buildCharacter() } -BOOL LLAvatarAppearance::loadAvatar() +bool LLAvatarAppearance::loadAvatar() { // LL_RECORD_BLOCK_TIME(FTM_LOAD_AVATAR); @@ -908,7 +908,7 @@ BOOL LLAvatarAppearance::loadAvatar() if( !buildSkeleton(sAvatarSkeletonInfo) ) { LL_ERRS() << "avatar file: buildSkeleton() failed" << LL_ENDL; - return FALSE; + return false; } // initialize mJointAliasMap @@ -918,14 +918,14 @@ BOOL LLAvatarAppearance::loadAvatar() if( !loadSkeletonNode() ) { LL_ERRS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL; - return FALSE; + return false; } // avatar_lad.xml : if( !loadMeshNodes() ) { LL_ERRS() << "avatar file: loadNodeMesh() failed" << LL_ENDL; - return FALSE; + return false; } // avatar_lad.xml : @@ -935,13 +935,13 @@ BOOL LLAvatarAppearance::loadAvatar() if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) { LL_ERRS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL; - return FALSE; + return false; } } else { LL_ERRS() << " name=\"skin_color\" not found" << LL_ENDL; - return FALSE; + return false; } if( sAvatarXmlInfo->mTexHairColorInfo ) { @@ -949,13 +949,13 @@ BOOL LLAvatarAppearance::loadAvatar() if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) { LL_ERRS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL; - return FALSE; + return false; } } else { LL_ERRS() << " name=\"hair_color\" not found" << LL_ENDL; - return FALSE; + return false; } if( sAvatarXmlInfo->mTexEyeColorInfo ) { @@ -963,26 +963,26 @@ BOOL LLAvatarAppearance::loadAvatar() if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) { LL_ERRS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL; - return FALSE; + return false; } } else { LL_ERRS() << " name=\"eye_color\" not found" << LL_ENDL; - return FALSE; + return false; } // avatar_lad.xml : if (sAvatarXmlInfo->mLayerInfoList.empty()) { LL_ERRS() << "avatar file: missing node" << LL_ENDL; - return FALSE; + return false; } if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) { LL_ERRS() << "avatar file: missing node" << LL_ENDL; - return FALSE; + return false; } // avatar_lad.xml : @@ -996,7 +996,7 @@ BOOL LLAvatarAppearance::loadAvatar() morph_param = getVisualParam(name->c_str()); if (morph_param) { - BOOL invert = info->mInvert; + bool invert = info->mInvert; addMaskedMorph(baked, morph_param, invert, info->mLayer); } } @@ -1024,17 +1024,17 @@ BOOL LLAvatarAppearance::loadAvatar() { delete driver_param; LL_WARNS() << "avatar file: driver_param->parseData() failed" << LL_ENDL; - return FALSE; + return false; } } - return TRUE; + return true; } //----------------------------------------------------------------------------- // loadSkeletonNode(): loads node from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::loadSkeletonNode () +bool LLAvatarAppearance::loadSkeletonNode () { mRoot->addChild( mSkeleton[0] ); @@ -1078,7 +1078,7 @@ BOOL LLAvatarAppearance::loadSkeletonNode () if (!param->setInfo(info)) { delete param; - return FALSE; + return false; } else { @@ -1089,13 +1089,13 @@ BOOL LLAvatarAppearance::loadSkeletonNode () } - return TRUE; + return true; } //----------------------------------------------------------------------------- // loadMeshNodes(): loads nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::loadMeshNodes() +bool LLAvatarAppearance::loadMeshNodes() { for (const LLAvatarXmlInfo::LLAvatarMeshInfo* info : sAvatarXmlInfo->mMeshInfoList) { @@ -1104,7 +1104,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() LLAvatarJointMesh* mesh = NULL; U8 mesh_id = 0; - BOOL found_mesh_id = FALSE; + bool found_mesh_id = FALSE; /* if (type == "hairMesh") switch(lod) @@ -1131,13 +1131,13 @@ BOOL LLAvatarAppearance::loadMeshNodes() else { LL_WARNS() << "Avatar file: has invalid lod setting " << lod << LL_ENDL; - return FALSE; + return false; } } else { LL_WARNS() << "Ignoring unrecognized mesh type: " << type << LL_ENDL; - return FALSE; + return false; } // LL_INFOS() << "Parsing mesh data for " << type << "..." << LL_ENDL; @@ -1160,7 +1160,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() { // This should never happen LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL; - return FALSE; + return false; } } else @@ -1172,7 +1172,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() if( !poly_mesh ) { LL_WARNS() << "Failed to load mesh of type " << type << LL_ENDL; - return FALSE; + return false; } // Multimap insert @@ -1187,7 +1187,7 @@ BOOL LLAvatarAppearance::loadMeshNodes() if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair.first)) { delete param; - return FALSE; + return false; } else { @@ -1205,15 +1205,15 @@ BOOL LLAvatarAppearance::loadMeshNodes() } } - return TRUE; + return true; } //----------------------------------------------------------------------------- // loadLayerSets() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::loadLayersets() +bool LLAvatarAppearance::loadLayersets() { - BOOL success = TRUE; + bool success = true; for (LLTexLayerSetInfo* layerset_info : sAvatarXmlInfo->mLayerInfoList) { if (isSelf()) @@ -1226,7 +1226,7 @@ BOOL LLAvatarAppearance::loadLayersets() stop_glerror(); delete layer_set; LL_WARNS() << "avatar file: layer_set->setInfo() failed" << LL_ENDL; - return FALSE; + return false; } // scan baked textures and associate the layerset with the appropriate one @@ -1248,7 +1248,7 @@ BOOL LLAvatarAppearance::loadLayersets() { LL_WARNS() << " has invalid body_region attribute" << LL_ENDL; delete layer_set; - return FALSE; + return false; } // scan morph masks and let any affected layers know they have an associated morph @@ -1355,19 +1355,19 @@ LLPolyMesh* LLAvatarAppearance::getUpperBodyMesh() // virtual -BOOL LLAvatarAppearance::isValid() const +bool LLAvatarAppearance::isValid() const { // This should only be called on ourself. if (!isSelf()) { LL_ERRS() << "Called LLAvatarAppearance::isValid() on when isSelf() == false" << LL_ENDL; } - return TRUE; + return true; } // adds a morph mask to the appropriate baked texture structure -void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer) +void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, bool invert, std::string layer) { if (index < BAKED_NUM_INDICES) { @@ -1378,7 +1378,7 @@ void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* //static -BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) +bool LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) { switch( te ) { @@ -1462,10 +1462,10 @@ BOOL LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) default: llassert(0); - return FALSE; + return false; } - return TRUE; + return true; } void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color) @@ -1521,7 +1521,7 @@ LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) con // Unlike most wearable functions, this works for both self and other. // virtual -BOOL LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const +bool LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const { return mWearableData->getWearableCount(type) > 0; } @@ -1538,7 +1538,7 @@ LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_in //----------------------------------------------------------------------------- // allocateCollisionVolumes() //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num ) +bool LLAvatarAppearance::allocateCollisionVolumes( U32 num ) { if (mNumCollisionVolumes !=num) { @@ -1549,18 +1549,18 @@ BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num ) if (!mCollisionVolumes) { LL_WARNS() << "Failed to allocate collision volumes" << LL_ENDL; - return FALSE; + return false; } mNumCollisionVolumes = num; } - return TRUE; + return true; } //----------------------------------------------------------------------------- // LLAvatarBoneInfo::parseXml() //----------------------------------------------------------------------------- -BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) { if (node->hasName("bone")) { @@ -1569,7 +1569,7 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) if (!node->getFastAttributeString(name_string, mName)) { LL_WARNS() << "Bone without name" << LL_ENDL; - return FALSE; + return false; } static LLStdStringHandle aliases_string = LLXmlTree::addAttributeString("aliases"); @@ -1587,28 +1587,28 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) else { LL_WARNS() << "Invalid node " << node->getName() << LL_ENDL; - return FALSE; + return false; } static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); if (!node->getFastAttributeVector3(pos_string, mPos)) { LL_WARNS() << "Bone without position" << LL_ENDL; - return FALSE; + return false; } static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); if (!node->getFastAttributeVector3(rot_string, mRot)) { LL_WARNS() << "Bone without rotation" << LL_ENDL; - return FALSE; + return false; } static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); if (!node->getFastAttributeVector3(scale_string, mScale)) { LL_WARNS() << "Bone without scale" << LL_ENDL; - return FALSE; + return false; } static LLStdStringHandle end_string = LLXmlTree::addAttributeString("end"); @@ -1631,7 +1631,7 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) if (!node->getFastAttributeVector3(pivot_string, mPivot)) { LL_WARNS() << "Bone without pivot" << LL_ENDL; - return FALSE; + return false; } } @@ -1643,23 +1643,23 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) if (!child_info->parseXml(child)) { delete child_info; - return FALSE; + return false; } mChildren.push_back(child_info); } - return TRUE; + return true; } //----------------------------------------------------------------------------- // LLAvatarSkeletonInfo::parseXml() //----------------------------------------------------------------------------- -BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) { static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); if (!node->getFastAttributeS32(num_bones_string, mNumBones)) { LL_WARNS() << "Couldn't find number of bones." << LL_ENDL; - return FALSE; + return false; } static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); @@ -1673,11 +1673,11 @@ BOOL LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) { delete info; LL_WARNS() << "Error parsing bone in skeleton file" << LL_ENDL; - return FALSE; + return false; } mBoneInfoList.push_back(info); } - return TRUE; + return true; } //Make aliases for joint and push to map. @@ -1745,13 +1745,13 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) { LLXmlTreeNode* node = root->getChildByName( "skeleton" ); if( !node ) { LL_WARNS() << "avatar file: missing " << LL_ENDL; - return FALSE; + return false; } LLXmlTreeNode* child; @@ -1771,14 +1771,14 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "Unknown param type." << LL_ENDL; } - return FALSE; + return false; } LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; if (!info->parseXml(child)) { delete info; - return FALSE; + return false; } mSkeletalDistortionInfoList.push_back(info); @@ -1796,7 +1796,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No name supplied for attachment point." << LL_ENDL; delete info; - return FALSE; + return false; } static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); @@ -1804,7 +1804,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No bone declared in attachment point " << info->mName << LL_ENDL; delete info; - return FALSE; + return false; } static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); @@ -1830,7 +1830,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro { LL_WARNS() << "No id supplied for attachment point " << info->mName << LL_ENDL; delete info; - return FALSE; + return false; } static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); @@ -1845,13 +1845,13 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro mAttachmentInfoList.push_back(info); } - return TRUE; + return true; } //----------------------------------------------------------------------------- // parseXmlMeshNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); node; @@ -1865,7 +1865,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { LL_WARNS() << "Avatar file: is missing type attribute. Ignoring element. " << LL_ENDL; delete info; - return FALSE; // Ignore this element + return false; // Ignore this element } static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); @@ -1873,7 +1873,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { LL_WARNS() << "Avatar file: is missing lod attribute. Ignoring element. " << LL_ENDL; delete info; - return FALSE; // Ignore this element + return false; // Ignore this element } static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); @@ -1881,7 +1881,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { LL_WARNS() << "Avatar file: is missing file_name attribute. Ignoring: " << info->mType << LL_ENDL; delete info; - return FALSE; // Ignore this element + return false; // Ignore this element } static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); @@ -1916,7 +1916,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { LL_WARNS() << "Unknown param type." << LL_ENDL; } - return FALSE; + return false; } LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); @@ -1926,7 +1926,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) delete info; return -1; } - BOOL shared = FALSE; + BOOL shared = false; static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); child->getFastAttributeBOOL(shared_string, shared); @@ -1935,13 +1935,13 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) mMeshInfoList.push_back(info); } - return TRUE; + return true; } //----------------------------------------------------------------------------- // parseXmlColorNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); color_node; @@ -1956,14 +1956,14 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root if (mTexSkinColorInfo) { LL_WARNS() << "avatar file: multiple instances of skin_color" << LL_ENDL; - return FALSE; + return false; } mTexSkinColorInfo = new LLTexGlobalColorInfo; if( !mTexSkinColorInfo->parseXml( color_node ) ) { delete_and_clear(mTexSkinColorInfo); LL_WARNS() << "avatar file: mTexSkinColor->parseXml() failed" << LL_ENDL; - return FALSE; + return false; } } else if( global_color_name == "hair_color" ) @@ -1971,14 +1971,14 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root if (mTexHairColorInfo) { LL_WARNS() << "avatar file: multiple instances of hair_color" << LL_ENDL; - return FALSE; + return false; } mTexHairColorInfo = new LLTexGlobalColorInfo; if( !mTexHairColorInfo->parseXml( color_node ) ) { delete_and_clear(mTexHairColorInfo); LL_WARNS() << "avatar file: mTexHairColor->parseXml() failed" << LL_ENDL; - return FALSE; + return false; } } else if( global_color_name == "eye_color" ) @@ -1986,24 +1986,24 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root if (mTexEyeColorInfo) { LL_WARNS() << "avatar file: multiple instances of eye_color" << LL_ENDL; - return FALSE; + return false; } mTexEyeColorInfo = new LLTexGlobalColorInfo; if( !mTexEyeColorInfo->parseXml( color_node ) ) { LL_WARNS() << "avatar file: mTexEyeColor->parseXml() failed" << LL_ENDL; - return FALSE; + return false; } } } } - return TRUE; + return true; } //----------------------------------------------------------------------------- // parseXmlLayerNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); layer_node; @@ -2018,16 +2018,16 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root { delete layer_info; LL_WARNS() << "avatar file: layer_set->parseXml() failed" << LL_ENDL; - return FALSE; + return false; } } - return TRUE; + return true; } //----------------------------------------------------------------------------- // parseXmlDriverNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) { LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); if( driver ) @@ -2047,23 +2047,23 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* roo { delete driver_info; LL_WARNS() << "avatar file: driver_param->parseXml() failed" << LL_ENDL; - return FALSE; + return false; } } } } - return TRUE; + return true; } //----------------------------------------------------------------------------- // parseXmlDriverNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) { LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); if( !masks ) { - return FALSE; + return false; } for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); @@ -2077,7 +2077,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No name supplied for morph mask." << LL_ENDL; delete info; - return FALSE; + return false; } static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); @@ -2085,7 +2085,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No region supplied for morph mask." << LL_ENDL; delete info; - return FALSE; + return false; } static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); @@ -2093,7 +2093,7 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root { LL_WARNS() << "No layer supplied for morph mask." << LL_ENDL; delete info; - return FALSE; + return false; } // optional parameter. don't throw a warning if not present. @@ -2103,12 +2103,12 @@ BOOL LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root mMorphMaskInfoList.push_back(info); } - return TRUE; + return true; } //virtual LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer) : - mMorphTarget(morph_target), + mMorphTarget(morph_target), mInvert(invert), mLayer(layer) { diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 787235b235..f3c74c052f 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -71,9 +71,9 @@ public: static void cleanupClass(); // Cleanup data that's only init'd once per class. virtual void initInstance(); // Called after construction to initialize the instance. S32 mInitFlags; - virtual BOOL loadSkeletonNode(); - BOOL loadMeshNodes(); - BOOL loadLayersets(); + virtual bool loadSkeletonNode(); + bool loadMeshNodes(); + bool loadLayersets(); /** Initialization @@ -108,9 +108,9 @@ public: **/ public: virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent - virtual BOOL isValid() const; - virtual BOOL isUsingLocalAppearance() const = 0; - virtual BOOL isEditingAppearance() const = 0; + virtual bool isValid() const; + virtual bool isUsingLocalAppearance() const = 0; + virtual bool isEditingAppearance() const = 0; bool isBuilt() const { return mIsBuilt; } @@ -156,16 +156,16 @@ public: protected: - static BOOL parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); + static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); virtual void buildCharacter(); - virtual BOOL loadAvatar(); + virtual bool loadAvatar(); - BOOL setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); - BOOL allocateCharacterJoints(U32 num); - BOOL buildSkeleton(const LLAvatarSkeletonInfo *info); + bool setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + bool allocateCharacterJoints(U32 num); + bool buildSkeleton(const LLAvatarSkeletonInfo *info); void clearSkeleton(); - BOOL mIsBuilt; // state of deferred character building + bool mIsBuilt; // state of deferred character building avatar_joint_list_t mSkeleton; LLVector3OverrideMap mPelvisFixups; joint_alias_map_t mJointAliasMap; @@ -225,13 +225,13 @@ protected: ** RENDERING **/ public: - BOOL mIsDummy; // for special views and animated object controllers; local to viewer + bool mIsDummy; // for special views and animated object controllers; local to viewer //-------------------------------------------------------------------- // Morph masks //-------------------------------------------------------------------- public: - void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer); + void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, bool invert, std::string layer); virtual void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; /** Rendering @@ -279,7 +279,7 @@ protected: public: void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color); LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); - static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); + static bool teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); //-------------------------------------------------------------------- // Global colors @@ -309,8 +309,8 @@ public: public: LLWearableData* getWearableData() { return mWearableData; } const LLWearableData* getWearableData() const { return mWearableData; } - virtual BOOL isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0; - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; + virtual bool isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0; + virtual bool isWearingWearableType(LLWearableType::EType type ) const; private: LLWearableData* mWearableData; @@ -356,7 +356,7 @@ public: S32 mNumCollisionVolumes; LLAvatarJointCollisionVolume* mCollisionVolumes; protected: - BOOL allocateCollisionVolumes(U32 num); + bool allocateCollisionVolumes(U32 num); /** Physics ** ** @@ -372,12 +372,12 @@ protected: LLAvatarXmlInfo(); ~LLAvatarXmlInfo(); - BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); - BOOL parseXmlMeshNodes(LLXmlTreeNode* root); - BOOL parseXmlColorNodes(LLXmlTreeNode* root); - BOOL parseXmlLayerNodes(LLXmlTreeNode* root); - BOOL parseXmlDriverNodes(LLXmlTreeNode* root); - BOOL parseXmlMorphNodes(LLXmlTreeNode* root); + bool parseXmlSkeletonNode(LLXmlTreeNode* root); + bool parseXmlMeshNodes(LLXmlTreeNode* root); + bool parseXmlColorNodes(LLXmlTreeNode* root); + bool parseXmlLayerNodes(LLXmlTreeNode* root); + bool parseXmlDriverNodes(LLXmlTreeNode* root); + bool parseXmlMorphNodes(LLXmlTreeNode* root); struct LLAvatarMeshInfo { @@ -421,8 +421,8 @@ protected: S32 mPieMenuSlice; BOOL mVisibleFirstPerson; BOOL mIsHUDAttachment; - BOOL mHasPosition; - BOOL mHasRotation; + bool mHasPosition; + bool mHasRotation; }; typedef std::vector attachment_info_list_t; attachment_info_list_t mAttachmentInfoList; @@ -458,7 +458,7 @@ protected: LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer); LLVisualParam *mMorphTarget; - BOOL mInvert; + bool mInvert; std::string mLayer; }; /** Support Classes diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index 8759c387e8..f3f26be4b9 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -303,15 +303,15 @@ LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIn } // static -BOOL LLAvatarAppearanceDictionary::isBakedImageId(const LLUUID& id) +bool LLAvatarAppearanceDictionary::isBakedImageId(const LLUUID& id) { if ((id == IMG_USE_BAKED_EYES) || (id == IMG_USE_BAKED_HAIR) || (id == IMG_USE_BAKED_HEAD) || (id == IMG_USE_BAKED_LOWER) || (id == IMG_USE_BAKED_SKIRT) || (id == IMG_USE_BAKED_UPPER) || (id == IMG_USE_BAKED_LEFTARM) || (id == IMG_USE_BAKED_LEFTLEG) || (id == IMG_USE_BAKED_AUX1) || (id == IMG_USE_BAKED_AUX2) || (id == IMG_USE_BAKED_AUX3) ) { - return TRUE; + return true; } - return FALSE; + return false; } // static diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 49dfbebeea..b90c6664cc 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -244,7 +244,7 @@ public: // Given a texture entry, determine which wearable type owns it. LLWearableType::EType getTEWearableType(ETextureIndex index) const; - static BOOL isBakedImageId(const LLUUID& id); + static bool isBakedImageId(const LLUUID& id); static EBakedTextureIndex assetIdToBakedTextureIndex(const LLUUID& id); static LLUUID localTextureIndexToMagicId(ETextureIndex t); diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index fec91503c7..61b4e2b0a1 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -62,7 +62,7 @@ public: virtual BOOL isTransparent() { return mIsTransparent; } // Returns true if this object should inherit scale modifiers from its immediate parent - virtual BOOL inheritScale() { return FALSE; } + virtual BOOL inheritScale() { return false; } enum Components { @@ -127,7 +127,7 @@ public: LLAvatarJointCollisionVolume(); virtual ~LLAvatarJointCollisionVolume() {}; - /*virtual*/ BOOL inheritScale() { return TRUE; } + /*virtual*/ BOOL inheritScale() { return true; } /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); void renderCollision(); diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index ed39f78d28..7a6da9d33f 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -119,7 +119,7 @@ BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor(joint)); mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset; - return TRUE; + return true; } @@ -186,7 +186,7 @@ BOOL LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) { mSkinJoints = new LLSkinJoint[ numSkinJoints ]; mNumSkinJoints = numSkinJoints; - return TRUE; + return true; } //----------------------------------------------------------------------------- diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index f46d0324a5..52d060571e 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -46,11 +46,11 @@ BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node) llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) ); if( !LLViewerVisualParamInfo::parseXml( node )) - return FALSE; + return false; LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" ); if( !param_driver_node ) - return FALSE; + return false; for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" ); child; @@ -90,10 +90,10 @@ BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node) else { LL_ERRS() << " Unable to resolve driven parameter: " << driven_id << LL_ENDL; - return FALSE; + return false; } } - return TRUE; + return true; } //virtual @@ -191,14 +191,14 @@ BOOL LLDriverParam::setInfo(LLDriverParamInfo *info) { llassert(mInfo == NULL); if (info->mID < 0) - return FALSE; + return false; mInfo = info; mID = info->mID; info->mDriverParam = this; setWeight(getDefaultWeight()); - return TRUE; + return true; } /*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index ab50db3a5a..7c17942c56 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -136,7 +136,7 @@ BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) { if (index >= getNumTexLayers() ) { - return FALSE; + return false; } if (new_tex_layer == NULL) @@ -153,47 +153,47 @@ BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) } mTexLayers[index] = layer; - return TRUE; + return true; } BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) { if (new_tex_layer == NULL) { - return FALSE; + return false; } LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable); layer->setLTO(this); mTexLayers.push_back(layer); - return TRUE; + return true; } BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) { if (new_tex_layer == NULL) { - return FALSE; + return false; } LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable); layer->setLTO(this); mTexLayers.push_back(layer); - return TRUE; + return true; } BOOL LLLocalTextureObject::removeTexLayer(U32 index) { if (index >= getNumTexLayers()) { - return FALSE; + return false; } tex_layer_vec_t::iterator iter = mTexLayers.begin(); iter += index; delete *iter; mTexLayers.erase(iter); - return TRUE; + return true; } void LLLocalTextureObject::setID(LLUUID new_id) diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index dab14851c8..8bfc6572d7 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -243,7 +243,7 @@ BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) mWeights[i] = 0.f; } mNumVertices = numVertices; - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -254,7 +254,7 @@ BOOL LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) mFaces = new LLPolyFace[ numFaces ]; mNumFaces = numFaces; mNumTriangleIndices = mNumFaces * 3; - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -264,7 +264,7 @@ BOOL LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) { mJointNames = new std::string[ numJointNames ]; mNumJointNames = numJointNames; - return TRUE; + return true; } //-------------------------------------------------------------------- @@ -278,13 +278,13 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if(fileName.empty()) { LL_ERRS() << "Filename is Empty!" << LL_ENDL; - return FALSE; + return false; } LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ if (!fp) { LL_ERRS() << "can't open: " << fileName << LL_ENDL; - return FALSE; + return false; } //------------------------------------------------------------------------- @@ -317,7 +317,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read HasWeights flag from " << fileName << LL_ENDL; - return FALSE; + return false; } if (!isLOD()) { @@ -332,7 +332,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read HasDetailTexCoords flag from " << fileName << LL_ENDL; - return FALSE; + return false; } //---------------------------------------------------------------- @@ -344,7 +344,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << "can't read Position from " << fileName << LL_ENDL; - return FALSE; + return false; } setPosition( position ); @@ -357,7 +357,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << "can't read RotationAngles from " << fileName << LL_ENDL; - return FALSE; + return false; } U8 rotationOrder; @@ -366,7 +366,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read RotationOrder from " << fileName << LL_ENDL; - return FALSE; + return false; } rotationOrder = 0; @@ -385,7 +385,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << "can't read Scale from " << fileName << LL_ENDL; - return FALSE; + return false; } setScale( scale ); @@ -406,7 +406,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read NumVertices from " << fileName << LL_ENDL; - return FALSE; + return false; } allocateVertexData( numVertices ); @@ -421,7 +421,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << "can't read Coordinates from " << fileName << LL_ENDL; - return FALSE; + return false; } } @@ -435,7 +435,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << " can't read Normals from " << fileName << LL_ENDL; - return FALSE; + return false; } } @@ -449,7 +449,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << " can't read Binormals from " << fileName << LL_ENDL; - return FALSE; + return false; } } @@ -461,7 +461,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != numVertices) { LL_ERRS() << "can't read TexCoords from " << fileName << LL_ENDL; - return FALSE; + return false; } //---------------------------------------------------------------- @@ -474,7 +474,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != numVertices) { LL_ERRS() << "can't read DetailTexCoords from " << fileName << LL_ENDL; - return FALSE; + return false; } } @@ -488,7 +488,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != numVertices) { LL_ERRS() << "can't read Weights from " << fileName << LL_ENDL; - return FALSE; + return false; } } } @@ -502,7 +502,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read NumFaces from " << fileName << LL_ENDL; - return FALSE; + return false; } allocateFaceData( numFaces ); @@ -520,7 +520,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 3) { LL_ERRS() << "can't read Face[" << i << "] from " << fileName << LL_ENDL; - return FALSE; + return false; } if (mReferenceData) { @@ -577,7 +577,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read NumSkinJoints from " << fileName << LL_ENDL; - return FALSE; + return false; } allocateJointNames( numSkinJoints ); } @@ -593,7 +593,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) if (numRead != 1) { LL_ERRS() << "can't read Skin[" << i << "].Name from " << fileName << LL_ENDL; - return FALSE; + return false; } std::string *jn = &mJointNames[i]; diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 223b2b7f1c..c2f0289432 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -114,7 +114,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 1) { LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL; - return FALSE; + return false; } //------------------------------------------------------------------------- @@ -151,14 +151,14 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 1) { LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL; - return FALSE; + return false; } if (mVertexIndices[v] > 10000) { // Bad install? These are usually .llm files from 'character' fodler LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; - return FALSE; + return false; } @@ -167,7 +167,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 3) { LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL; - return FALSE; + return false; } F32 magnitude = mCoords[v].getLength3().getF32(); @@ -187,7 +187,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 3) { LL_WARNS() << "Can't read morph target normal" << LL_ENDL; - return FALSE; + return false; } numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); @@ -195,7 +195,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 3) { LL_WARNS() << "Can't read morph target binormal" << LL_ENDL; - return FALSE; + return false; } @@ -204,7 +204,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) if (numRead != 2) { LL_WARNS() << "Can't read morph target uv" << LL_ENDL; - return FALSE; + return false; } mNumIndices++; @@ -213,7 +213,7 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) mAvgDistortion.mul(1.f/(F32)mNumIndices); mAvgDistortion.normalize3fast(); - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -265,14 +265,14 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; + return false; // Get mixed-case name static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if( !node->getFastAttributeString( name_string, mMorphName ) ) { LL_WARNS() << "Avatar file: is missing name attribute" << LL_ENDL; - return FALSE; // Continue, ignoring this tag + return false; // Continue, ignoring this tag } static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); @@ -284,7 +284,7 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) { LL_WARNS() << "Failed to getChildByName(\"param_morph\")" << LL_ENDL; - return FALSE; + return false; } for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); @@ -310,7 +310,7 @@ BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) } } - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -357,7 +357,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { llassert(mInfo == NULL); if (info->mID < 0) - return FALSE; + return false; mInfo = info; mID = info->mID; setWeight(getDefaultWeight()); @@ -394,9 +394,9 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) if (!mMorphData) { LL_WARNS() << "No morph target named " << morph_param_name << " found in mesh." << LL_ENDL; - return FALSE; // Continue, ignoring this tag + return false; // Continue, ignoring this tag } - return TRUE; + return true; } /*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const @@ -416,9 +416,9 @@ BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) if (!setInfo(info)) { delete info; - return FALSE; + return false; } - return TRUE; + return true; } #endif diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index 586e631ded..d3401cb08f 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -50,7 +50,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; + return false; LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); @@ -58,7 +58,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) { LL_WARNS() << "Failed to getChildByName(\"param_skeleton\")" << LL_ENDL; - return FALSE; + return false; } for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) @@ -98,7 +98,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) continue; } } - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -137,7 +137,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) { if (info->mID < 0) { - return FALSE; + return false; } mInfo = info; mID = info->mID; @@ -151,7 +151,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) // There's no point continuing after this error - means // that either the skeleton or lad file is broken. LL_WARNS() << "Joint " << bone_info.mBoneName << " not found." << LL_ENDL; - return FALSE; + return false; } // store it @@ -174,7 +174,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) mJointOffsets[joint] = bone_info.mPositionDeformation; } } - return TRUE; + return true; } /*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index 75815482c9..9017067f98 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -61,12 +61,12 @@ BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) if (!param_color->setInfo(color_info, TRUE)) { mInfo = NULL; - return FALSE; + return false; } mParamGlobalColorList.push_back(param_color); } - return TRUE; + return true; } LLColor4 LLTexGlobalColor::getColor() const @@ -142,7 +142,7 @@ BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) if (!node->getFastAttributeString(name_string, mName)) { LL_WARNS() << " element is missing name attribute." << LL_ENDL; - return FALSE; + return false; } // sub-element for (LLXmlTreeNode* child = node->getChildByName("param"); @@ -156,10 +156,10 @@ BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) if (!info->parseXml(child)) { delete info; - return FALSE; + return false; } mParamColorInfoList.push_back(info); } } - return TRUE; + return true; } diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index e426615f1c..91f5ba1996 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -190,7 +190,7 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) llassert( node->hasName( "layer_set" ) ); if( !node->hasName( "layer_set" ) ) { - return FALSE; + return false; } // body_region @@ -198,20 +198,20 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) if( !node->getFastAttributeString( body_region_string, mBodyRegion ) ) { LL_WARNS() << " is missing body_region attribute" << LL_ENDL; - return FALSE; + return false; } // width, height static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width"); if( !node->getFastAttributeS32( width_string, mWidth ) ) { - return FALSE; + return false; } static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height"); if( !node->getFastAttributeS32( height_string, mHeight ) ) { - return FALSE; + return false; } // Optional alpha component to apply after all compositing is complete. @@ -230,11 +230,11 @@ BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) if( !info->parseXml( child )) { delete info; - return FALSE; + return false; } mLayerInfoList.push_back( info ); } - return TRUE; + return true; } // creates visual params without generating layersets or layers @@ -299,7 +299,7 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) if (!layer->setInfo(layer_info, NULL)) { mInfo = NULL; - return FALSE; + return false; } if (!layer->isVisibilityMask()) { @@ -315,7 +315,7 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) stop_glerror(); - return TRUE; + return true; } #if 0 // obsolete @@ -330,14 +330,14 @@ BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node) if (!info->parseXml(node)) { delete info; - return FALSE; + return false; } if (!setInfo(info)) { delete info; - return FALSE; + return false; } - return TRUE; + return true; } #endif @@ -539,10 +539,10 @@ BOOL LLTexLayerSet::isMorphValid() const { if (layer && !layer->isMorphValid()) { - return FALSE; + return false; } } - return TRUE; + return true; } void LLTexLayerSet::invalidateMorphMasks() @@ -587,7 +587,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if( !node->getFastAttributeString( name_string, mName ) ) { - return FALSE; + return false; } static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels"); @@ -657,13 +657,13 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) if (mLocalTexture == TEX_NUM_INDICES) { LL_WARNS() << " element has invalid local_texture attribute: " << mName << " " << local_texture_name << LL_ENDL; - return FALSE; + return false; } } else { LL_WARNS() << " element is missing a required attribute. " << mName << LL_ENDL; - return FALSE; + return false; } } @@ -694,7 +694,7 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) if (!info->parseXml(child)) { delete info; - return FALSE; + return false; } mParamColorInfoList.push_back(info); } @@ -705,18 +705,18 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) if (!info->parseXml(child)) { delete info; - return FALSE; + return false; } mParamAlphaInfoList.push_back(info); } } - return TRUE; + return true; } BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) { - BOOL success = TRUE; + BOOL success = true; for (LLTexLayerParamColorInfo* color_info : mParamColorInfoList) { LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); @@ -781,7 +781,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab if (!param_color->setInfo(color_info, TRUE)) { mInfo = NULL; - return FALSE; + return false; } } else @@ -790,7 +790,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab if (!param_color) { mInfo = NULL; - return FALSE; + return false; } } mParamColorList.push_back( param_color ); @@ -806,7 +806,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab if (!param_alpha->setInfo(alpha_info, TRUE)) { mInfo = NULL; - return FALSE; + return false; } } else @@ -815,13 +815,13 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab if (!param_alpha) { mInfo = NULL; - return FALSE; + return false; } } mParamAlphaList.push_back( param_alpha ); } - return TRUE; + return true; } /*virtual*/ void LLTexLayerInterface::requestUpdate() @@ -1223,29 +1223,29 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const } calculateTexLayerColor(mParamColorList, *net_color); - return TRUE; + return true; } if( !getGlobalColor().empty() ) { net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getGlobalColor() ) ); - return TRUE; + return true; } if( getInfo()->mFixedColor.mV[VW] ) { net_color->setVec( getInfo()->mFixedColor ); - return TRUE; + return true; } net_color->setToWhite(); - return FALSE; // No need to draw a separate colored polygon + return false; // No need to draw a separate colored polygon } BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { - BOOL success = TRUE; + BOOL success = true; gGL.flush(); @@ -1519,11 +1519,11 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 { if (mLocalTextureObject->getID() == IMG_INVISIBLE) { - return TRUE; + return true; } } - return FALSE; + return false; } LLUUID LLTexLayer::getUUID() const @@ -1726,12 +1726,12 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const { if (layer->isInvisibleAlphaMask()) { - return TRUE; + return true; } } } - return FALSE; + return false; } diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 604e0124cb..16369533ca 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -79,7 +79,7 @@ BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appeara this->setParamLocation(mAvatarAppearance->isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); } - return TRUE; + return true; } @@ -235,7 +235,7 @@ BOOL LLTexLayerParamAlpha::getSkip() const { if (!mTexLayer) { - return TRUE; + return true; } const LLAvatarAppearance *appearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); @@ -245,24 +245,24 @@ BOOL LLTexLayerParamAlpha::getSkip() const F32 effective_weight = (appearance->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); if (is_approx_zero(effective_weight)) { - return TRUE; + return true; } } LLWearableType::EType type = (LLWearableType::EType)getWearableType(); if ((type != LLWearableType::WT_INVALID) && !appearance->isWearingWearableType(type)) { - return TRUE; + return true; } - return FALSE; + return false; } BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) { LL_PROFILE_ZONE_SCOPED; - BOOL success = TRUE; + BOOL success = true; if (!mTexLayer) { @@ -300,7 +300,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) { LL_WARNS() << "Unable to load static file: " << info->mStaticImageFileName << LL_ENDL; mStaticImageInvalid = TRUE; // don't try again. - return FALSE; + return false; } } @@ -383,12 +383,12 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) llassert(node->hasName("param") && node->getChildByName("param_alpha")); if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; + return false; LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha"); if (!param_alpha_node) { - return FALSE; + return false; } static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); @@ -410,7 +410,7 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); param_alpha_node->getFastAttributeF32(domain_string, mDomain); - return TRUE; + return true; } @@ -543,12 +543,12 @@ BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) llassert(node->hasName("param") && node->getChildByName("param_color")); if (!LLViewerVisualParamInfo::parseXml(node)) - return FALSE; + return false; LLXmlTreeNode* param_color_node = node->getChildByName("param_color"); if (!param_color_node) { - return FALSE; + return false; } std::string op_string; @@ -581,14 +581,14 @@ BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) if (!mNumColors) { LL_WARNS() << " is missing sub-elements" << LL_ENDL; - return FALSE; + return false; } if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1)) { LL_WARNS() << " with operation\"blend\" must have exactly one " << LL_ENDL; - return FALSE; + return false; } - return TRUE; + return true; } diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index fb0d12f0af..07786e3c0c 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -62,7 +62,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) llassert( node->hasName( "param" ) ); if (!LLVisualParamInfo::parseXml(node)) - return FALSE; + return false; // VIEWER SPECIFIC PARAMS @@ -107,7 +107,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) params_loaded++; - return TRUE; + return true; } /*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out) @@ -150,11 +150,11 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) { llassert(mInfo == NULL); if (info->mID < 0) - return FALSE; + return false; mInfo = info; mID = info->mID; setWeight(getDefaultWeight()); - return TRUE; + return true; } /* @@ -166,14 +166,14 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) //----------------------------------------------------------------------------- // parseData() //----------------------------------------------------------------------------- -BOOL LLViewerVisualParam::parseData(LLXmlTreeNode *node) +bool LLViewerVisualParam::parseData(LLXmlTreeNode *node) { LLViewerVisualParamInfo* info = new LLViewerVisualParamInfo; info->parseXml(node); if (!setInfo(info)) - return FALSE; + return false; - return TRUE; + return true; } */ diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index fdf167aa94..db7db32b3e 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -95,7 +95,7 @@ BOOL LLWearable::exportFile(const std::string& filename) const // virtual BOOL LLWearable::exportStream( std::ostream& output_stream ) const { - if (!output_stream.good()) return FALSE; + if (!output_stream.good()) return false; // header and version output_stream << "LLWearable version " << mDefinitionVersion << "\n"; @@ -107,13 +107,13 @@ BOOL LLWearable::exportStream( std::ostream& output_stream ) const // permissions if( !mPermissions.exportLegacyStream( output_stream ) ) { - return FALSE; + return false; } // sale info if( !mSaleInfo.exportLegacyStream( output_stream ) ) { - return FALSE; + return false; } // wearable type @@ -139,7 +139,7 @@ BOOL LLWearable::exportStream( std::ostream& output_stream ) const const LLUUID& image_id = te_pair.second->getID(); output_stream << te << " " << image_id << "\n"; } - return TRUE; + return true; } void LLWearable::createVisualParams(LLAvatarAppearance *avatarp) @@ -473,7 +473,7 @@ BOOL LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, { if (!input_stream.good()) { - return FALSE; + return false; } do diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 9fbbc57c87..2a0b77ee39 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -204,7 +204,7 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou { if (wearable == NULL) { - return FALSE; + return false; } const LLWearableType::EType type = wearable->getType(); @@ -212,7 +212,7 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou if (wearable_iter == mWearableDatas.end()) { LL_WARNS() << "tried to get wearable index with an invalid type!" << LL_ENDL; - return FALSE; + return false; } const wearableentry_vec_t& wearable_vec = wearable_iter->second; for(U32 index = 0; index < wearable_vec.size(); index++) @@ -220,11 +220,11 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou if (wearable_vec[index] == wearable) { index_found = index; - return TRUE; + return true; } } - return FALSE; + return false; } U32 LLWearableData::getClothingLayerCount() const @@ -255,13 +255,13 @@ BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const } else { - return FALSE; + return false; } } BOOL LLWearableData::isOnTop(LLWearable* wearable) const { - if (!wearable) return FALSE; + if (!wearable) return false; const LLWearableType::EType type = wearable->getType(); return ( getTopWearable(type) == wearable ); } diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 4ac611b1de..056f7cf888 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -115,14 +115,14 @@ LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType typ BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) { const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return FALSE; + if (!entry) return false; return entry->mDisableCameraSwitch; } BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) { const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return FALSE; + if (!entry) return false; return entry->mAllowMultiwear; } -- cgit v1.2.3 From 4419bb870986c6900fc096338622d27b999cd771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Sun, 11 Feb 2024 01:23:28 +0100 Subject: more misc: BOOL (int) to real bool --- indra/llappearance/llavatarjoint.cpp | 6 +++--- indra/llappearance/llavatarjoint.h | 6 +++--- indra/llappearance/llavatarjointmesh.cpp | 4 ++-- indra/llappearance/llavatarjointmesh.h | 4 ++-- indra/llappearance/lldriverparam.cpp | 2 +- indra/llappearance/lldriverparam.h | 2 +- indra/llappearance/llpolymorph.cpp | 2 +- indra/llappearance/llpolymorph.h | 2 +- indra/llappearance/llpolyskeletaldistortion.cpp | 6 +++--- indra/llappearance/llpolyskeletaldistortion.h | 2 +- indra/llappearance/lltexglobalcolor.cpp | 2 +- indra/llappearance/lltexglobalcolor.h | 2 +- indra/llappearance/lltexlayer.cpp | 6 +++--- indra/llappearance/lltexlayer.h | 2 +- indra/llappearance/lltexlayerparams.cpp | 4 ++-- indra/llappearance/lltexlayerparams.h | 4 ++-- indra/llappearance/llviewervisualparam.cpp | 2 +- indra/llappearance/llviewervisualparam.h | 2 +- 18 files changed, 30 insertions(+), 30 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp index 9300b08b7b..a1f775c801 100644 --- a/indra/llappearance/llavatarjoint.cpp +++ b/indra/llappearance/llavatarjoint.cpp @@ -167,10 +167,10 @@ void LLAvatarJoint::updateJointGeometry() } -BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate) +bool LLAvatarJoint::updateLOD(F32 pixel_area, bool activate) { - BOOL lod_changed = FALSE; - BOOL found_lod = FALSE; + bool lod_changed = FALSE; + bool found_lod = FALSE; for (LLJoint* child : mChildren) { diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index 61b4e2b0a1..052852fa3d 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -62,7 +62,7 @@ public: virtual BOOL isTransparent() { return mIsTransparent; } // Returns true if this object should inherit scale modifiers from its immediate parent - virtual BOOL inheritScale() { return false; } + virtual bool inheritScale() { return false; } enum Components { @@ -99,7 +99,7 @@ public: virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ) = 0; virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); - virtual BOOL updateLOD(F32 pixel_area, BOOL activate); + virtual bool updateLOD(F32 pixel_area, bool activate); virtual void updateJointGeometry(); virtual void dump(); @@ -127,7 +127,7 @@ public: LLAvatarJointCollisionVolume(); virtual ~LLAvatarJointCollisionVolume() {}; - /*virtual*/ BOOL inheritScale() { return true; } + /*virtual*/ bool inheritScale() { return true; } /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); void renderCollision(); diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 7a6da9d33f..97539afba6 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -102,7 +102,7 @@ LLSkinJoint::~LLSkinJoint() //----------------------------------------------------------------------------- // LLSkinJoint::setupSkinJoint() //----------------------------------------------------------------------------- -BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) +bool LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) { // find the named joint mJoint = joint; @@ -182,7 +182,7 @@ LLAvatarJointMesh::~LLAvatarJointMesh() //----------------------------------------------------------------------------- // LLAvatarJointMesh::allocateSkinData() //----------------------------------------------------------------------------- -BOOL LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) +bool LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) { mSkinJoints = new LLSkinJoint[ numSkinJoints ]; mNumSkinJoints = numSkinJoints; diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 5980b29b46..1f12c3986f 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -49,7 +49,7 @@ class LLSkinJoint public: LLSkinJoint(); ~LLSkinJoint(); - BOOL setupSkinJoint( LLAvatarJoint *joint); + bool setupSkinJoint( LLAvatarJoint *joint); LLAvatarJoint *mJoint; LLVector3 mRootToJointSkinOffset; @@ -135,7 +135,7 @@ public: private: // Allocate skin data - BOOL allocateSkinData( U32 numSkinJoints ); + bool allocateSkinData( U32 numSkinJoints ); // Free skin data void freeSkinData(); diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index 52d060571e..84b7c9ac41 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -41,7 +41,7 @@ LLDriverParamInfo::LLDriverParamInfo() : { } -BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node) +bool LLDriverParamInfo::parseXml(LLXmlTreeNode* node) { llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) ); diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index a6261b507b..915faf6b5d 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -65,7 +65,7 @@ public: LLDriverParamInfo(); /*virtual*/ ~LLDriverParamInfo() {}; - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + /*virtual*/ bool parseXml(LLXmlTreeNode* node); /*virtual*/ void toStream(std::ostream &out); diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index c2f0289432..697beb239e 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -260,7 +260,7 @@ LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() { } -BOOL LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) +bool LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) { llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 954f01811a..8388898dd6 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -129,7 +129,7 @@ public: LLPolyMorphTargetInfo(); /*virtual*/ ~LLPolyMorphTargetInfo() {}; - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + /*virtual*/ bool parseXml(LLXmlTreeNode* node); protected: std::string mMorphName; diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index d3401cb08f..d730bab107 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -45,7 +45,7 @@ LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() { } -BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) +bool LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) { llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); @@ -68,7 +68,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) std::string name; LLVector3 scale; LLVector3 pos; - BOOL haspos = FALSE; + BOOL haspos = false; static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if (!bone->getFastAttributeString(name_string, name)) @@ -88,7 +88,7 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); if (bone->getFastAttributeVector3(offset_string, pos)) { - haspos = TRUE; + haspos = true; } mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); } diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index 585d85f055..4aa053b924 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -71,7 +71,7 @@ public: LLPolySkeletalDistortionInfo(); /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + /*virtual*/ bool parseXml(LLXmlTreeNode* node); protected: typedef std::vector bone_info_list_t; diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index 9017067f98..eea7639cd8 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -135,7 +135,7 @@ LLTexGlobalColorInfo::~LLTexGlobalColorInfo() mParamColorInfoList.clear(); } -BOOL LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) +bool LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) { // name attribute static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h index 3b426053de..94cb979255 100644 --- a/indra/llappearance/lltexglobalcolor.h +++ b/indra/llappearance/lltexglobalcolor.h @@ -62,7 +62,7 @@ public: LLTexGlobalColorInfo(); ~LLTexGlobalColorInfo(); - BOOL parseXml(LLXmlTreeNode* node); + bool parseXml(LLXmlTreeNode* node); private: param_color_info_list_t mParamColorInfoList; diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 91f5ba1996..73ce5257e5 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -59,7 +59,7 @@ public: LLTexLayerInfo(); ~LLTexLayerInfo(); - BOOL parseXml(LLXmlTreeNode* node); + bool parseXml(LLXmlTreeNode* node); BOOL createVisualParams(LLAvatarAppearance *appearance); BOOL isUserSettable() { return mLocalTexture != -1; } S32 getLocalTexture() const { return mLocalTexture; } @@ -185,7 +185,7 @@ LLTexLayerSetInfo::~LLTexLayerSetInfo( ) mLayerInfoList.clear(); } -BOOL LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) +bool LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) { llassert( node->hasName( "layer_set" ) ); if( !node->hasName( "layer_set" ) ) @@ -579,7 +579,7 @@ LLTexLayerInfo::~LLTexLayerInfo( ) mParamAlphaInfoList.clear(); } -BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node) +bool LLTexLayerInfo::parseXml(LLXmlTreeNode* node) { llassert( node->hasName( "layer" ) ); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index ff95d7f5e9..2cca2b6b12 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -243,7 +243,7 @@ class LLTexLayerSetInfo public: LLTexLayerSetInfo(); ~LLTexLayerSetInfo(); - BOOL parseXml(LLXmlTreeNode* node); + bool parseXml(LLXmlTreeNode* node); void createVisualParams(LLAvatarAppearance *appearance); S32 getWidth() const { return mWidth; } S32 getHeight() const { return mHeight; } diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 16369533ca..4cfbdc01c1 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -378,7 +378,7 @@ LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() : { } -BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) +bool LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) { llassert(node->hasName("param") && node->getChildByName("param_alpha")); @@ -538,7 +538,7 @@ LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() : { } -BOOL LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) +bool LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) { llassert(node->hasName("param") && node->getChildByName("param_color")); diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index 000f55685e..1dbfd0b3d6 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -120,7 +120,7 @@ public: LLTexLayerParamAlphaInfo(); /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + /*virtual*/ bool parseXml(LLXmlTreeNode* node); private: std::string mStaticImageFileName; @@ -189,7 +189,7 @@ class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo public: LLTexLayerParamColorInfo(); virtual ~LLTexLayerParamColorInfo() {}; - BOOL parseXml( LLXmlTreeNode* node ); + bool parseXml( LLXmlTreeNode* node ); LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; } private: enum { MAX_COLOR_VALUES = 20 }; diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index 07786e3c0c..43fb8fab5e 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -57,7 +57,7 @@ LLViewerVisualParamInfo::~LLViewerVisualParamInfo() //----------------------------------------------------------------------------- // parseXml() //----------------------------------------------------------------------------- -BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) +bool LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) { llassert( node->hasName( "param" ) ); diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index 1a710c0ca6..9ad3e6eae8 100644 --- a/indra/llappearance/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h @@ -43,7 +43,7 @@ public: LLViewerVisualParamInfo(); /*virtual*/ ~LLViewerVisualParamInfo(); - /*virtual*/ BOOL parseXml(LLXmlTreeNode* node); + /*virtual*/ bool parseXml(LLXmlTreeNode* node); /*virtual*/ void toStream(std::ostream &out); -- cgit v1.2.3 From 1839def9dc6064a865f6cd05d1509358a53ac9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Sun, 11 Feb 2024 16:50:22 +0100 Subject: even more misc: BOOL (int) to real bool --- indra/llappearance/llavatarjoint.cpp | 6 +++--- indra/llappearance/llavatarjointmesh.cpp | 14 +++++++------- indra/llappearance/llavatarjointmesh.h | 6 +++--- indra/llappearance/lldriverparam.cpp | 12 ++++++------ indra/llappearance/lldriverparam.h | 4 ++-- indra/llappearance/lllocaltextureobject.cpp | 10 +++++----- indra/llappearance/lllocaltextureobject.h | 10 +++++----- indra/llappearance/llpolymesh.cpp | 12 ++++++------ indra/llappearance/llpolymesh.h | 8 ++++---- indra/llappearance/llpolymorph.cpp | 6 +++--- indra/llappearance/llpolymorph.h | 4 ++-- indra/llappearance/llpolyskeletaldistortion.cpp | 2 +- indra/llappearance/llpolyskeletaldistortion.h | 2 +- indra/llappearance/lltexglobalcolor.cpp | 2 +- indra/llappearance/lltexglobalcolor.h | 2 +- 15 files changed, 50 insertions(+), 50 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp index a1f775c801..e7bd831b49 100644 --- a/indra/llappearance/llavatarjoint.cpp +++ b/indra/llappearance/llavatarjoint.cpp @@ -169,8 +169,8 @@ void LLAvatarJoint::updateJointGeometry() bool LLAvatarJoint::updateLOD(F32 pixel_area, bool activate) { - bool lod_changed = FALSE; - bool found_lod = FALSE; + bool lod_changed = false; + bool found_lod = false; for (LLJoint* child : mChildren) { @@ -187,7 +187,7 @@ bool LLAvatarJoint::updateLOD(F32 pixel_area, bool activate) if (pixel_area >= jointLOD || sDisableLOD) { lod_changed |= joint->updateLOD(pixel_area, TRUE); - found_lod = TRUE; + found_lod = true; } else { diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 97539afba6..f34e23a966 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -129,7 +129,7 @@ bool LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -BOOL LLAvatarJointMesh::sPipelineRender = FALSE; +bool LLAvatarJointMesh::sPipelineRender = false; U32 LLAvatarJointMesh::sClothingMaskImageName = 0; LLColor4 LLAvatarJointMesh::sClothingInnerColor; @@ -149,7 +149,7 @@ LLAvatarJointMesh::LLAvatarJointMesh() mColor[2] = 1.0f; mColor[3] = 1.0f; mShiny = 0.0f; - mCullBackFaces = TRUE; + mCullBackFaces = true; mMesh = NULL; @@ -159,11 +159,11 @@ LLAvatarJointMesh::LLAvatarJointMesh() mFace = NULL; mMeshID = 0; - mUpdateXform = FALSE; + mUpdateXform = false; - mValid = FALSE; + mValid = false; - mIsTransparent = FALSE; + mIsTransparent = false; } @@ -252,7 +252,7 @@ void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) } -BOOL LLAvatarJointMesh::hasGLTexture() const +bool LLAvatarJointMesh::hasGLTexture() const { return mTexture.notNull() && mTexture->hasGLTexture(); } @@ -272,7 +272,7 @@ void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set ) } } -BOOL LLAvatarJointMesh::hasComposite() const +bool LLAvatarJointMesh::hasComposite() const { return (mLayerSet && mLayerSet->hasComposite()); } diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 1f12c3986f..a3f6a61218 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -79,7 +79,7 @@ protected: S32 mMeshID; public: - static BOOL sPipelineRender; + static bool sPipelineRender; //RN: this is here for testing purposes static U32 sClothingMaskImageName; static LLColor4 sClothingInnerColor; @@ -104,14 +104,14 @@ public: // Sets the shape texture void setTexture( LLGLTexture *texture ); - BOOL hasGLTexture() const; + bool hasGLTexture() const; void setTestTexture( U32 name ) { mTestImageName = name; } // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) void setLayerSet( LLTexLayerSet* layer_set ); - BOOL hasComposite() const; + bool hasComposite() const; // Gets the poly mesh LLPolyMesh *getMesh(); diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index 84b7c9ac41..83f2ab1266 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -187,7 +187,7 @@ LLDriverParam::~LLDriverParam() { } -BOOL LLDriverParam::setInfo(LLDriverParamInfo *info) +bool LLDriverParam::setInfo(LLDriverParamInfo *info) { llassert(mInfo == NULL); if (info->mID < 0) @@ -466,20 +466,20 @@ void LLDriverParam::stopAnimating() } /*virtual*/ -BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params) +bool LLDriverParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params) { - BOOL success = TRUE; + BOOL success = true; for (LLDrivenEntryInfo& driven_info : getInfo()->mDrivenInfoList) { S32 driven_id = driven_info.mDrivenID; // check for already existing links. Do not overwrite. - BOOL found = FALSE; + bool found = false; for (auto& driven : mDriven) { if (driven.mInfo->mDrivenID == driven_id) { - found = TRUE; + found = true; } } @@ -494,7 +494,7 @@ BOOL LLDriverParam::linkDrivenParams(visual_param_mapper mapper, BOOL only_cross } else { - success = FALSE; + success = false; } } } diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index 915faf6b5d..610cd8c5e5 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -90,7 +90,7 @@ public: // Special: These functions are overridden by child classes LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } // This sets mInfo and calls initialization functions - BOOL setInfo(LLDriverParamInfo* info); + bool setInfo(LLDriverParamInfo* info); LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } @@ -104,7 +104,7 @@ public: /*virtual*/ void setWeight(F32 weight); /*virtual*/ void setAnimationTarget(F32 target_value); /*virtual*/ void stopAnimating(); - /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); + /*virtual*/ bool linkDrivenParams(visual_param_mapper mapper, bool only_cross_params); /*virtual*/ void resetDrivenParams(); // LLViewerVisualParam Virtual functions diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index 7c17942c56..ff82e4e8e3 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -122,7 +122,7 @@ S32 LLLocalTextureObject::getDiscard() const return mDiscard; } -BOOL LLLocalTextureObject::getBakedReady() const +bool LLLocalTextureObject::getBakedReady() const { return mIsBakedReady; } @@ -132,7 +132,7 @@ void LLLocalTextureObject::setImage(LLGLTexture* new_image) mImage = new_image; } -BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) +bool LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) { if (index >= getNumTexLayers() ) { @@ -156,7 +156,7 @@ BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) return true; } -BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) +bool LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) { if (new_tex_layer == NULL) { @@ -169,7 +169,7 @@ BOOL LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *we return true; } -BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) +bool LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) { if (new_tex_layer == NULL) { @@ -182,7 +182,7 @@ BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWear return true; } -BOOL LLLocalTextureObject::removeTexLayer(U32 index) +bool LLLocalTextureObject::removeTexLayer(U32 index) { if (index >= getNumTexLayers()) { diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h index 9b9f41fd19..5ca503baf4 100644 --- a/indra/llappearance/lllocaltextureobject.h +++ b/indra/llappearance/lllocaltextureobject.h @@ -53,13 +53,13 @@ public: U32 getNumTexLayers() const; LLUUID getID() const; S32 getDiscard() const; - BOOL getBakedReady() const; + bool getBakedReady() const; void setImage(LLGLTexture* new_image); - BOOL setTexLayer(LLTexLayer *new_tex_layer, U32 index); - BOOL addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); - BOOL addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); - BOOL removeTexLayer(U32 index); + bool setTexLayer(LLTexLayer *new_tex_layer, U32 index); + bool addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); + bool addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); + bool removeTexLayer(U32 index); void setID(LLUUID new_id); void setDiscard(S32 new_discard); diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 8bfc6572d7..a51d4dec7e 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -225,7 +225,7 @@ U32 LLPolyMeshSharedData::getNumKB() //----------------------------------------------------------------------------- // LLPolyMeshSharedData::allocateVertexData() //----------------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) +bool LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { U32 i; mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); @@ -249,7 +249,7 @@ BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) //----------------------------------------------------------------------------- // LLPolyMeshSharedData::allocateFaceData() //----------------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) +bool LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) { mFaces = new LLPolyFace[ numFaces ]; mNumFaces = numFaces; @@ -260,7 +260,7 @@ BOOL LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) //----------------------------------------------------------------------------- // LLPolyMeshSharedData::allocateJointNames() //----------------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) +bool LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) { mJointNames = new std::string[ numJointNames ]; mNumJointNames = numJointNames; @@ -270,7 +270,7 @@ BOOL LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) //-------------------------------------------------------------------- // LLPolyMeshSharedData::loadMesh() //-------------------------------------------------------------------- -BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) +bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) { //------------------------------------------------------------------------- // Open the file @@ -299,7 +299,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) //------------------------------------------------------------------------- // Check for proper binary header //------------------------------------------------------------------------- - BOOL status = FALSE; + bool status = false; if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ { LL_DEBUGS() << "Loading " << fileName << LL_ENDL; @@ -321,7 +321,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) } if (!isLOD()) { - mHasWeights = (hasWeights==0) ? FALSE : TRUE; + mHasWeights = (hasWeights==0) ? false : true; } //---------------------------------------------------------------- diff --git a/indra/llappearance/llpolymesh.h b/indra/llappearance/llpolymesh.h index 83659d9514..040868ea2a 100644 --- a/indra/llappearance/llpolymesh.h +++ b/indra/llappearance/llpolymesh.h @@ -119,17 +119,17 @@ private: void setRotation( const LLQuaternion &rot ) { mRotation = rot; } void setScale( const LLVector3 &scale ) { mScale = scale; } - BOOL allocateVertexData( U32 numVertices ); + bool allocateVertexData( U32 numVertices ); - BOOL allocateFaceData( U32 numFaces ); + bool allocateFaceData( U32 numFaces ); - BOOL allocateJointNames( U32 numJointNames ); + bool allocateJointNames( U32 numJointNames ); // Retrieve the number of KB of memory used by this instance U32 getNumKB(); // Load mesh data from file - BOOL loadMesh( const std::string& fileName ); + bool loadMesh( const std::string& fileName ); public: void genIndices(S32 offset); diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 697beb239e..73811a550c 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -104,7 +104,7 @@ LLPolyMorphData::~LLPolyMorphData() //----------------------------------------------------------------------------- // loadBinary() //----------------------------------------------------------------------------- -BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) +bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) { S32 numVertices; S32 numRead; @@ -353,7 +353,7 @@ LLPolyMorphTarget::~LLPolyMorphTarget() //----------------------------------------------------------------------------- // setInfo() //----------------------------------------------------------------------------- -BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) +bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { llassert(mInfo == NULL); if (info->mID < 0) @@ -408,7 +408,7 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) //----------------------------------------------------------------------------- // parseData() //----------------------------------------------------------------------------- -BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) +bool LLPolyMorphTarget::parseData(LLXmlTreeNode* node) { LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 8388898dd6..f52e9dce8d 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -49,7 +49,7 @@ public: ~LLPolyMorphData(); LLPolyMorphData(const LLPolyMorphData &rhs); - BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); + bool loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); const std::string& getName() { return mName; } public: @@ -154,7 +154,7 @@ public: // Special: These functions are overridden by child classes LLPolyMorphTargetInfo* getInfo() const { return (LLPolyMorphTargetInfo*)mInfo; } // This sets mInfo and calls initialization functions - BOOL setInfo(LLPolyMorphTargetInfo *info); + bool setInfo(LLPolyMorphTargetInfo *info); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index d730bab107..e8405ddb1f 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -133,7 +133,7 @@ LLPolySkeletalDistortion::~LLPolySkeletalDistortion() { } -BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) +bool LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) { if (info->mID < 0) { diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index 4aa053b924..83d9b90d69 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -92,7 +92,7 @@ public: // Special: These functions are overridden by child classes LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } // This sets mInfo and calls initialization functions - BOOL setInfo(LLPolySkeletalDistortionInfo *info); + bool setInfo(LLPolySkeletalDistortionInfo *info); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index eea7639cd8..b450b1284e 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -48,7 +48,7 @@ LLTexGlobalColor::~LLTexGlobalColor() //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); } -BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) +bool LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) { llassert(mInfo == NULL); mInfo = info; diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h index 94cb979255..52c80fc943 100644 --- a/indra/llappearance/lltexglobalcolor.h +++ b/indra/llappearance/lltexglobalcolor.h @@ -42,7 +42,7 @@ public: LLTexGlobalColorInfo* getInfo() const { return mInfo; } // This sets mInfo and calls initialization functions - BOOL setInfo(LLTexGlobalColorInfo *info); + bool setInfo(LLTexGlobalColorInfo *info); LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } LLColor4 getColor() const; -- cgit v1.2.3 From 2d8654db9cff989c4a9927207dc25d4cb480912a Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Mon, 12 Feb 2024 23:17:03 +0200 Subject: VS build fix: missed values --- indra/llappearance/llavatarappearance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 1dbca29a86..7d9d2ba24c 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -1924,7 +1924,7 @@ bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { delete morphinfo; delete info; - return -1; + return false; } BOOL shared = false; static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); -- cgit v1.2.3 From 9e854b697a06abed2a0917fb6120445f176764f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20N=C3=A6sbye=20Christensen?= Date: Fri, 16 Feb 2024 19:29:51 +0100 Subject: misc: BOOL to bool --- indra/llappearance/llavatarappearance.cpp | 44 +++--- indra/llappearance/llavatarappearance.h | 16 +-- indra/llappearance/llavatarappearancedefines.cpp | 100 +++++++------- indra/llappearance/llavatarappearancedefines.h | 6 +- indra/llappearance/llavatarjoint.cpp | 30 ++--- indra/llappearance/llavatarjoint.h | 24 ++-- indra/llappearance/llavatarjointmesh.cpp | 2 +- indra/llappearance/llavatarjointmesh.h | 4 +- indra/llappearance/lldriverparam.cpp | 4 +- indra/llappearance/lllocaltextureobject.cpp | 6 +- indra/llappearance/lllocaltextureobject.h | 4 +- indra/llappearance/llpolymesh.cpp | 10 +- indra/llappearance/llpolymesh.h | 12 +- indra/llappearance/llpolymorph.cpp | 12 +- indra/llappearance/llpolymorph.h | 12 +- indra/llappearance/llpolyskeletaldistortion.cpp | 2 +- indra/llappearance/llpolyskeletaldistortion.h | 6 +- indra/llappearance/lltexglobalcolor.cpp | 2 +- indra/llappearance/lltexlayer.cpp | 162 +++++++++++------------ indra/llappearance/lltexlayer.h | 70 +++++----- indra/llappearance/lltexlayerparams.cpp | 42 +++--- indra/llappearance/lltexlayerparams.h | 20 +-- indra/llappearance/llviewervisualparam.cpp | 8 +- indra/llappearance/llviewervisualparam.h | 12 +- indra/llappearance/llwearable.cpp | 8 +- indra/llappearance/llwearable.h | 6 +- indra/llappearance/llwearabledata.cpp | 14 +- indra/llappearance/llwearabledata.h | 8 +- indra/llappearance/llwearabletype.cpp | 46 +++---- indra/llappearance/llwearabletype.h | 12 +- 30 files changed, 352 insertions(+), 352 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 7d9d2ba24c..43ee78519d 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -78,7 +78,7 @@ class LLAvatarBoneInfo friend class LLAvatarAppearance; friend class LLAvatarSkeletonInfo; public: - LLAvatarBoneInfo() : mIsJoint(FALSE) {} + LLAvatarBoneInfo() : mIsJoint(false) {} ~LLAvatarBoneInfo() { std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); @@ -178,7 +178,7 @@ LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* LLAvatarAppearance::sAv LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : LLCharacter(), - mIsDummy(FALSE), + mIsDummy(false), mTexSkinColor( NULL ), mTexHairColor( NULL ), mTexEyeColor( NULL ), @@ -189,7 +189,7 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : mNumBones(0), mNumCollisionVolumes(0), mCollisionVolumes(NULL), - mIsBuilt(FALSE), + mIsBuilt(false), mInitFlags(0) { llassert_always(mWearableData); @@ -236,14 +236,14 @@ void LLAvatarAppearance::initInstance() mesh->setName(mesh_name); mesh->setMeshID(mesh_index); mesh->setPickName(mesh_dict->mPickName); - mesh->setIsTransparent(FALSE); + mesh->setIsTransparent(false); switch((S32)mesh_index) { case MESH_ID_HAIR: - mesh->setIsTransparent(TRUE); + mesh->setIsTransparent(true); break; case MESH_ID_SKIRT: - mesh->setIsTransparent(TRUE); + mesh->setIsTransparent(true); break; case MESH_ID_EYEBALL_LEFT: case MESH_ID_EYEBALL_RIGHT: @@ -345,7 +345,7 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml"); } LLXmlTree xml_tree; - bool success = xml_tree.parseFile( avatar_file_name, FALSE ); + bool success = xml_tree.parseFile( avatar_file_name, false ); if (!success) { LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL; @@ -580,7 +580,7 @@ bool LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTre //------------------------------------------------------------------------- // parse the file //------------------------------------------------------------------------- - bool parsesuccess = skeleton_xml_tree.parseFile( filename, FALSE ); + bool parsesuccess = skeleton_xml_tree.parseFile( filename, false ); if (!parsesuccess) { @@ -804,7 +804,7 @@ void LLAvatarAppearance::buildCharacter() //------------------------------------------------------------------------- mRoot->removeAllChildren(); mJointMap.clear(); - mIsBuilt = FALSE; + mIsBuilt = false; //------------------------------------------------------------------------- // clear mesh data @@ -825,7 +825,7 @@ void LLAvatarAppearance::buildCharacter() bool status = loadAvatar(); stop_glerror(); -// gPrintMessagesThisFrame = TRUE; +// gPrintMessagesThisFrame = true; LL_DEBUGS() << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << LL_ENDL; if (!status) @@ -895,7 +895,7 @@ void LLAvatarAppearance::buildCharacter() // SL-315 mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); - mIsBuilt = TRUE; + mIsBuilt = true; stop_glerror(); } @@ -1041,7 +1041,7 @@ bool LLAvatarAppearance::loadSkeletonNode () // make meshes children before calling parent version of the function for (LLAvatarJoint* joint : mMeshLOD) { - joint->mUpdateXform = FALSE; + joint->mUpdateXform = false; joint->setMeshesToChildren(); } @@ -1104,7 +1104,7 @@ bool LLAvatarAppearance::loadMeshNodes() LLAvatarJointMesh* mesh = NULL; U8 mesh_id = 0; - bool found_mesh_id = FALSE; + bool found_mesh_id = false; /* if (type == "hairMesh") switch(lod) @@ -1117,7 +1117,7 @@ bool LLAvatarAppearance::loadMeshNodes() if (type.compare(mesh_dict->mName) == 0) { mesh_id = mesh_index; - found_mesh_id = TRUE; + found_mesh_id = true; break; } } @@ -1257,12 +1257,12 @@ bool LLAvatarAppearance::loadLayersets() LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); if (layer) { - layer->setHasMorph(TRUE); + layer->setHasMorph(true); } else { LL_WARNS() << "Could not find layer named " << morph->mLayer << " to set morph flag" << LL_ENDL; - success = FALSE; + success = false; } } } @@ -1564,7 +1564,7 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) { if (node->hasName("bone")) { - mIsJoint = TRUE; + mIsJoint = true; static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if (!node->getFastAttributeString(name_string, mName)) { @@ -1577,7 +1577,7 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) } else if (node->hasName("collision_volume")) { - mIsJoint = FALSE; + mIsJoint = false; static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if (!node->getFastAttributeString(name_string, mName)) { @@ -1810,13 +1810,13 @@ bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* ro static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); if (child->getFastAttributeVector3(position_string, info->mPosition)) { - info->mHasPosition = TRUE; + info->mHasPosition = true; } static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) { - info->mHasRotation = TRUE; + info->mHasRotation = true; } static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); if (child->getFastAttributeS32(group_string, info->mGroup)) @@ -1926,7 +1926,7 @@ bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) delete info; return false; } - BOOL shared = false; + bool shared = false; static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); child->getFastAttributeBOOL(shared_string, shared); @@ -2107,7 +2107,7 @@ bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root } //virtual -LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer) : +LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, bool invert, std::string layer) : mMorphTarget(morph_target), mInvert(invert), mLayer(layer) diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index f3c74c052f..dd16a27a3c 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -381,7 +381,7 @@ protected: struct LLAvatarMeshInfo { - typedef std::pair morph_info_pair_t; // LLPolyMorphTargetInfo stored here + typedef std::pair morph_info_pair_t; // LLPolyMorphTargetInfo stored here typedef std::vector morph_info_list_t; LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} @@ -410,8 +410,8 @@ protected: struct LLAvatarAttachmentInfo { LLAvatarAttachmentInfo() - : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), - mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} + : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(false), + mIsHUDAttachment(false), mHasPosition(false), mHasRotation(false) {} std::string mName; std::string mJointName; LLVector3 mPosition; @@ -419,8 +419,8 @@ protected: S32 mGroup; S32 mAttachmentID; S32 mPieMenuSlice; - BOOL mVisibleFirstPerson; - BOOL mIsHUDAttachment; + bool mVisibleFirstPerson; + bool mIsHUDAttachment; bool mHasPosition; bool mHasRotation; }; @@ -440,11 +440,11 @@ protected: struct LLAvatarMorphInfo { LLAvatarMorphInfo() - : mInvert(FALSE) {} + : mInvert(false) {} std::string mName; std::string mRegion; std::string mLayer; - BOOL mInvert; + bool mInvert; }; typedef std::vector morph_info_list_t; @@ -455,7 +455,7 @@ protected: class LLMaskedMorph { public: - LLMaskedMorph(LLVisualParam *morph_target, BOOL invert, std::string layer); + LLMaskedMorph(LLVisualParam *morph_target, bool invert, std::string layer); LLVisualParam *mMorphTarget; bool mInvert; diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index f3f26be4b9..7af1c37824 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -39,56 +39,56 @@ using namespace LLAvatarAppearanceDefines; LLAvatarAppearanceDictionary::Textures::Textures() { - addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); - addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); - addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", TRUE, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); - addEntry(TEX_HAIR, new TextureEntry("hair_grain", TRUE, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); - addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", TRUE, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); - addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); - addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", TRUE, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", TRUE, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); - addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); - addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", TRUE, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); - addEntry(TEX_SKIRT, new TextureEntry("skirt", TRUE, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); - - addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", TRUE, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - - addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - - addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new TextureEntry("head_universal_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new TextureEntry("upper_universal_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new TextureEntry("lower_universal_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_SKIRT_TATTOO, new TextureEntry("skirt_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_HAIR_TATTOO, new TextureEntry("hair_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_EYES_TATTOO, new TextureEntry("eyes_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_LEFT_ARM_TATTOO, new TextureEntry("leftarm_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_LEFT_LEG_TATTOO, new TextureEntry("leftleg_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_AUX1_TATTOO, new TextureEntry("aux1_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_AUX2_TATTOO, new TextureEntry("aux2_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_AUX3_TATTOO, new TextureEntry("aux3_tattoo", TRUE, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - - - addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", FALSE, BAKED_HEAD, "head")); - addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", FALSE, BAKED_UPPER, "upper")); - addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", FALSE, BAKED_LOWER, "lower")); - addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", FALSE, BAKED_EYES, "eyes")); - addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", FALSE, BAKED_HAIR, "hair")); - addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", FALSE, BAKED_SKIRT, "skirt")); - addEntry(TEX_LEFT_ARM_BAKED, new TextureEntry("leftarm-baked", FALSE, BAKED_LEFT_ARM, "leftarm")); - addEntry(TEX_LEFT_LEG_BAKED, new TextureEntry("leftleg-baked", FALSE, BAKED_LEFT_LEG, "leftleg")); - addEntry(TEX_AUX1_BAKED, new TextureEntry("aux1-baked", FALSE, BAKED_AUX1, "aux1")); - addEntry(TEX_AUX2_BAKED, new TextureEntry("aux2-baked", FALSE, BAKED_AUX2, "aux2")); - addEntry(TEX_AUX3_BAKED, new TextureEntry("aux3-baked", FALSE, BAKED_AUX3, "aux3")); + addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", true, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); + addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", true, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); + addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", true, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); + addEntry(TEX_HAIR, new TextureEntry("hair_grain", true, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); + addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", true, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); + addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", true, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); + addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", true, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", true, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", true, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); + addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", true, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); + addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", true, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); + addEntry(TEX_SKIRT, new TextureEntry("skirt", true, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); + + addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + + addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + + addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new TextureEntry("head_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new TextureEntry("upper_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new TextureEntry("lower_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_SKIRT_TATTOO, new TextureEntry("skirt_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_HAIR_TATTOO, new TextureEntry("hair_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_EYES_TATTOO, new TextureEntry("eyes_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LEFT_ARM_TATTOO, new TextureEntry("leftarm_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LEFT_LEG_TATTOO, new TextureEntry("leftleg_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX1_TATTOO, new TextureEntry("aux1_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX2_TATTOO, new TextureEntry("aux2_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX3_TATTOO, new TextureEntry("aux3_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + + + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", false, BAKED_HEAD, "head")); + addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", false, BAKED_UPPER, "upper")); + addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", false, BAKED_LOWER, "lower")); + addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", false, BAKED_EYES, "eyes")); + addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", false, BAKED_HAIR, "hair")); + addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", false, BAKED_SKIRT, "skirt")); + addEntry(TEX_LEFT_ARM_BAKED, new TextureEntry("leftarm-baked", false, BAKED_LEFT_ARM, "leftarm")); + addEntry(TEX_LEFT_LEG_BAKED, new TextureEntry("leftleg-baked", false, BAKED_LEFT_LEG, "leftleg")); + addEntry(TEX_AUX1_BAKED, new TextureEntry("aux1-baked", false, BAKED_AUX1, "aux1")); + addEntry(TEX_AUX2_BAKED, new TextureEntry("aux2-baked", false, BAKED_AUX2, "aux2")); + addEntry(TEX_AUX3_BAKED, new TextureEntry("aux3-baked", false, BAKED_AUX3, "aux3")); } LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index b90c6664cc..21c0dedeba 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -167,10 +167,10 @@ public: const std::string mDefaultImageName; const LLWearableType::EType mWearableType; // It's either a local texture xor baked - BOOL mIsLocalTexture; - BOOL mIsBakedTexture; + bool mIsLocalTexture; + bool mIsBakedTexture; // If it's a local texture, it may be used by a baked texture - BOOL mIsUsedByBakedTexture; + bool mIsUsedByBakedTexture; EBakedTextureIndex mBakedTextureIndex; }; diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp index e7bd831b49..579381958c 100644 --- a/indra/llappearance/llavatarjoint.cpp +++ b/indra/llappearance/llavatarjoint.cpp @@ -40,7 +40,7 @@ const F32 DEFAULT_AVATAR_JOINT_LOD = 0.0f; //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -BOOL LLAvatarJoint::sDisableLOD = FALSE; +bool LLAvatarJoint::sDisableLOD = false; //----------------------------------------------------------------------------- // LLAvatarJoint() @@ -66,13 +66,13 @@ LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) : void LLAvatarJoint::init() { - mValid = FALSE; + mValid = false; mComponents = SC_JOINT | SC_BONE | SC_AXES; mMinPixelArea = DEFAULT_AVATAR_JOINT_LOD; mPickName = PN_DEFAULT; - mVisible = TRUE; + mVisible = true; mMeshID = 0; - mIsTransparent = FALSE; + mIsTransparent = false; } @@ -88,7 +88,7 @@ LLAvatarJoint::~LLAvatarJoint() //-------------------------------------------------------------------- // setValid() //-------------------------------------------------------------------- -void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) +void LLAvatarJoint::setValid( bool valid, bool recursive ) { //---------------------------------------------------------------- // set visibility for this joint @@ -103,7 +103,7 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) for (LLJoint* child : mChildren) { LLAvatarJoint* joint = static_cast(child); - joint->setValid(valid, TRUE); + joint->setValid(valid, true); } } @@ -112,7 +112,7 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive ) //-------------------------------------------------------------------- // setSkeletonComponents() //-------------------------------------------------------------------- -void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive ) +void LLAvatarJoint::setSkeletonComponents( U32 comp, bool recursive ) { mComponents = comp; if (recursive) @@ -125,7 +125,7 @@ void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive ) } } -void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive) +void LLAvatarJoint::setVisible(bool visible, bool recursive) { mVisible = visible; @@ -148,7 +148,7 @@ void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pix } } -void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update) +void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, bool damp_wind, bool terse_update) { for (LLJoint* child : mChildren) { @@ -180,18 +180,18 @@ bool LLAvatarJoint::updateLOD(F32 pixel_area, bool activate) if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) { // we've already found a joint to enable, so enable the rest as alternatives - lod_changed |= joint->updateLOD(pixel_area, TRUE); + lod_changed |= joint->updateLOD(pixel_area, true); } else { if (pixel_area >= jointLOD || sDisableLOD) { - lod_changed |= joint->updateLOD(pixel_area, TRUE); + lod_changed |= joint->updateLOD(pixel_area, true); found_lod = true; } else { - lod_changed |= joint->updateLOD(pixel_area, FALSE); + lod_changed |= joint->updateLOD(pixel_area, false); } } } @@ -222,11 +222,11 @@ void LLAvatarJoint::setMeshesToChildren() LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume() { - mUpdateXform = FALSE; + mUpdateXform = false; } /*virtual*/ -U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) +U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, bool first_pass, bool is_dummy ) { LL_ERRS() << "Cannot call render() on LLAvatarJointCollisionVolume" << LL_ENDL; return 0; @@ -234,7 +234,7 @@ U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, BOOL first_pass, BOOL i LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset) { - mUpdateXform = TRUE; + mUpdateXform = true; LLVector3 result = offset; result.scaleVec(getScale()); diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index 052852fa3d..09269bbc3f 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -52,14 +52,14 @@ public: virtual ~LLAvatarJoint(); // Gets the validity of this joint - BOOL getValid() { return mValid; } + bool getValid() { return mValid; } // Sets the validity of this joint - virtual void setValid( BOOL valid, BOOL recursive=FALSE ); + virtual void setValid( bool valid, bool recursive=false ); // Returns true if this object is transparent. // This is used to determine in which order to draw objects. - virtual BOOL isTransparent() { return mIsTransparent; } + virtual bool isTransparent() { return mIsTransparent; } // Returns true if this object should inherit scale modifiers from its immediate parent virtual bool inheritScale() { return false; } @@ -72,7 +72,7 @@ public: }; // Selects which skeleton components to draw - void setSkeletonComponents( U32 comp, BOOL recursive = TRUE ); + void setSkeletonComponents( U32 comp, bool recursive = true ); // Returns which skeleton components are enables for drawing U32 getSkeletonComponents() { return mComponents; } @@ -90,34 +90,34 @@ public: void setPickName(LLJointPickName name) { mPickName = name; } LLJointPickName getPickName() { return mPickName; } - void setVisible( BOOL visible, BOOL recursive ); + void setVisible( bool visible, bool recursive ); // Takes meshes in mMeshParts and sets each one as a child joint void setMeshesToChildren(); // LLViewerJoint interface - virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ) = 0; + virtual U32 render( F32 pixelArea, bool first_pass = true, bool is_dummy = false ) = 0; virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE, bool terse_update = false); + virtual void updateFaceData(LLFace *face, F32 pixel_area, bool damp_wind = false, bool terse_update = false); virtual bool updateLOD(F32 pixel_area, bool activate); virtual void updateJointGeometry(); virtual void dump(); public: - static BOOL sDisableLOD; + static bool sDisableLOD; avatar_joint_mesh_list_t mMeshParts; //LLViewerJointMesh* void setMeshID( S32 id ) {mMeshID = id;} protected: void init(); - BOOL mValid; - BOOL mIsTransparent; + bool mValid; + bool mIsTransparent; U32 mComponents; F32 mMinPixelArea; LLJointPickName mPickName; - BOOL mVisible; + bool mVisible; S32 mMeshID; }; @@ -128,7 +128,7 @@ public: virtual ~LLAvatarJointCollisionVolume() {}; /*virtual*/ bool inheritScale() { return true; } - /*virtual*/ U32 render( F32 pixelArea, BOOL first_pass = TRUE, BOOL is_dummy = FALSE ); + /*virtual*/ U32 render( F32 pixelArea, bool first_pass = true, bool is_dummy = false ); void renderCollision(); diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index f34e23a966..9b2a1d9b4c 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -247,7 +247,7 @@ void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) { mLayerSet = NULL; //texture->bindTexture(0); - //texture->setClamp(TRUE, TRUE); + //texture->setClamp(true, true); } } diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index a3f6a61218..57cf5a26f8 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -69,7 +69,7 @@ protected: LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar U32 mTestImageName; // handle to a temporary texture for previewing uploads LLPolyMesh* mMesh; // ptr to a global polymesh - BOOL mCullBackFaces; // true by default + bool mCullBackFaces; // true by default LLFace* mFace; // ptr to a face w/ AGP copy of mesh U32 mFaceIndexCount; @@ -131,7 +131,7 @@ public: // Gets ID for picking S32 getMeshID() { return mMeshID; } - void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } + void setIsTransparent(bool is_transparent) { mIsTransparent = is_transparent; } private: // Allocate skin data diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index 83f2ab1266..e832176ae8 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -461,14 +461,14 @@ void LLDriverParam::stopAnimating() for(LLDrivenEntry& driven : mDriven) { - driven.mParam->setAnimating(FALSE); + driven.mParam->setAnimating(false); } } /*virtual*/ bool LLDriverParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params) { - BOOL success = true; + bool success = true; for (LLDrivenEntryInfo& driven_info : getInfo()->mDrivenInfoList) { S32 driven_id = driven_info.mDrivenID; diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index ff82e4e8e3..84c0fd8380 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -36,14 +36,14 @@ LLLocalTextureObject::LLLocalTextureObject() : - mIsBakedReady(FALSE), + mIsBakedReady(false), mDiscard(MAX_DISCARD_LEVEL+1) { mImage = NULL; } LLLocalTextureObject::LLLocalTextureObject(LLGLTexture* image, const LLUUID& id) : - mIsBakedReady(FALSE), + mIsBakedReady(false), mDiscard(MAX_DISCARD_LEVEL+1) { mImage = image; @@ -206,7 +206,7 @@ void LLLocalTextureObject::setDiscard(S32 new_discard) mDiscard = new_discard; } -void LLLocalTextureObject::setBakedReady(BOOL ready) +void LLLocalTextureObject::setBakedReady(bool ready) { mIsBakedReady = ready; } diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h index 5ca503baf4..a5118ffde3 100644 --- a/indra/llappearance/lllocaltextureobject.h +++ b/indra/llappearance/lllocaltextureobject.h @@ -63,7 +63,7 @@ public: void setID(LLUUID new_id); void setDiscard(S32 new_discard); - void setBakedReady(BOOL ready); + void setBakedReady(bool ready); protected: @@ -78,7 +78,7 @@ private: LLUUID mID; - BOOL mIsBakedReady; + bool mIsBakedReady; S32 mDiscard; }; diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index a51d4dec7e..42a37c4e16 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -72,8 +72,8 @@ LLPolyMeshSharedData::LLPolyMeshSharedData() mTexCoords = NULL; mDetailTexCoords = NULL; mWeights = NULL; - mHasWeights = FALSE; - mHasDetailTexCoords = FALSE; + mHasWeights = false; + mHasDetailTexCoords = false; mNumFaces = 0; mFaces = NULL; @@ -615,7 +615,7 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) std::string morph_name(morphName); LLPolyMorphData* morph_data = new LLPolyMorphData(morph_name); - BOOL result = morph_data->loadBinary(fp, this); + bool result = morph_data->loadBinary(fp, this); if (!result) { @@ -705,12 +705,12 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) } } - status = TRUE; + status = true; } else { LL_ERRS() << "invalid mesh file header: " << fileName << LL_ENDL; - status = FALSE; + status = false; } if (0 == mNumJointNames) diff --git a/indra/llappearance/llpolymesh.h b/indra/llappearance/llpolymesh.h index 040868ea2a..e0822bf0e7 100644 --- a/indra/llappearance/llpolymesh.h +++ b/indra/llappearance/llpolymesh.h @@ -79,8 +79,8 @@ private: LLVector2 *mDetailTexCoords; F32 *mWeights; - BOOL mHasWeights; - BOOL mHasDetailTexCoords; + bool mHasWeights; + bool mHasDetailTexCoords; // face data S32 mNumFaces; @@ -138,7 +138,7 @@ public: const S32 *getSharedVert(S32 vert); - BOOL isLOD() { return (mReferenceData != NULL); } + bool isLOD() { return (mReferenceData != NULL); } }; @@ -204,13 +204,13 @@ public: } // Returns whether or not the mesh has detail texture coords - BOOL hasDetailTexCoords() { + bool hasDetailTexCoords() { llassert (mSharedData); return mSharedData->mHasDetailTexCoords; } // Returns whether or not the mesh has vertex weights - BOOL hasWeights() const{ + bool hasWeights() const{ llassert (mSharedData); return mSharedData->mHasWeights; } @@ -316,7 +316,7 @@ public: // Get indices U32* getIndices() { return mSharedData ? mSharedData->mTriangleIndices : NULL; } - BOOL isLOD() { return mSharedData && mSharedData->isLOD(); } + bool isLOD() { return mSharedData && mSharedData->isLOD(); } void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; } LLAvatarAppearance* getAvatar() { return mAvatarp; } diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 73811a550c..4b94ed48b1 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -256,7 +256,7 @@ void LLPolyMorphData::freeData() // LLPolyMorphTargetInfo() //----------------------------------------------------------------------------- LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() - : mIsClothingMorph(FALSE) + : mIsClothingMorph(false) { } @@ -659,7 +659,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- // applyMask() //----------------------------------------------------------------------------- -void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) +void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert) { LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; @@ -749,7 +749,7 @@ void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) : mWeights(new F32[morph_data->mNumIndices]), mMorphData(morph_data), - mWeightsGenerated(FALSE) + mWeightsGenerated(false) { llassert(mMorphData != NULL); llassert(mMorphData->mNumIndices > 0); @@ -780,10 +780,10 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) +void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) -// BOOL debugImg = FALSE; +// bool debugImg = false; // if (debugImg) // { // if (invert) @@ -827,7 +827,7 @@ void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 he clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; } } - mWeightsGenerated = TRUE; + mWeightsGenerated = true; } //----------------------------------------------------------------------------- diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index f52e9dce8d..5544344036 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -84,14 +84,14 @@ public: LLPolyVertexMask(const LLPolyVertexMask& pOther); ~LLPolyVertexMask(); - void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); + void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights); F32* getMorphMaskWeights(); protected: F32* mWeights; LLPolyMorphData *mMorphData; - BOOL mWeightsGenerated; + bool mWeightsGenerated; }; @@ -133,7 +133,7 @@ public: protected: std::string mMorphName; - BOOL mIsClothingMorph; + bool mIsClothingMorph; typedef std::vector volume_info_list_t; volume_info_list_t mVolumeInfoList; }; @@ -159,7 +159,7 @@ public: /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + ///*virtual*/ bool parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ); // LLViewerVisualParam Virtual functions @@ -170,7 +170,7 @@ public: /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); - void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); + void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, bool invert); void addPendingMorphMask() { mNumMorphMasksPending++; } void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() @@ -183,7 +183,7 @@ protected: LLPolyVertexMask * mVertMask; ESex mLastSex; // number of morph masks that haven't been generated, must be 0 before this morph is applied - BOOL mNumMorphMasksPending; + BOOL mNumMorphMasksPending; typedef std::vector volume_list_t; volume_list_t mVolumeMorphs; diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index e8405ddb1f..3dd21ff62b 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -68,7 +68,7 @@ bool LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) std::string name; LLVector3 scale; LLVector3 pos; - BOOL haspos = false; + bool haspos = false; static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); if (!bone->getFastAttributeString(name_string, name)) diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index 83d9b90d69..4c69f7e70a 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -51,7 +51,7 @@ class LLAvatarAppearance; //----------------------------------------------------------------------------- struct LLPolySkeletalBoneInfo { - LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, BOOL haspos) + LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, bool haspos) : mBoneName(name), mScaleDeformation(scale), mPositionDeformation(pos), @@ -59,7 +59,7 @@ struct LLPolySkeletalBoneInfo std::string mBoneName; LLVector3 mScaleDeformation; LLVector3 mPositionDeformation; - BOOL mHasPositionDeformation; + bool mHasPositionDeformation; }; class alignas(16) LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo @@ -97,7 +97,7 @@ public: /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + ///*virtual*/ bool parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ); // LLViewerVisualParam Virtual functions diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index b450b1284e..cd416d6791 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -58,7 +58,7 @@ bool LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) for (LLTexLayerParamColorInfo* color_info : mInfo->mParamColorInfoList) { LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); - if (!param_color->setInfo(color_info, TRUE)) + if (!param_color->setInfo(color_info, true)) { mInfo = NULL; return false; diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 73ce5257e5..15a031f90c 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -60,16 +60,16 @@ public: ~LLTexLayerInfo(); bool parseXml(LLXmlTreeNode* node); - BOOL createVisualParams(LLAvatarAppearance *appearance); - BOOL isUserSettable() { return mLocalTexture != -1; } + bool createVisualParams(LLAvatarAppearance *appearance); + bool isUserSettable() { return mLocalTexture != -1; } S32 getLocalTexture() const { return mLocalTexture; } - BOOL getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } + bool getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } std::string getName() const { return mName; } private: std::string mName; - BOOL mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, + bool mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, LLTexLayerInterface::ERenderPass mRenderPass; std::string mGlobalColor; @@ -77,11 +77,11 @@ private: S32 mLocalTexture; std::string mStaticImageFileName; - BOOL mStaticImageIsMask; - BOOL mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask - BOOL mIsVisibilityMask; + bool mStaticImageIsMask; + bool mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask + bool mIsVisibilityMask; - typedef std::vector< std::pair< std::string,BOOL > > morph_name_list_t; + typedef std::vector< std::pair< std::string,bool > > morph_name_list_t; morph_name_list_t mMorphNameList; param_color_info_list_t mParamColorInfoList; param_alpha_info_list_t mParamAlphaInfoList; @@ -130,17 +130,17 @@ void LLTexLayerSetBuffer::preRenderTexLayerSet() } // virtual -void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success) +void LLTexLayerSetBuffer::postRenderTexLayerSet(bool success) { popProjection(); } -BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) +bool LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) { // Default color mask for tex layer render gGL.setColorMask(true, true); - BOOL success = TRUE; + bool success = true; gAlphaMaskProgram.bind(); gAlphaMaskProgram.setMinimumAlpha(0.004f); @@ -175,7 +175,7 @@ LLTexLayerSetInfo::LLTexLayerSetInfo() : mBodyRegion( "" ), mWidth( 512 ), mHeight( 512 ), - mClearAlpha( TRUE ) + mClearAlpha( true ) { } @@ -252,11 +252,11 @@ void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance) // An ordered set of texture layers that get composited into a single texture. //----------------------------------------------------------------------------- -BOOL LLTexLayerSet::sHasCaches = FALSE; +bool LLTexLayerSet::sHasCaches = false; LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) : mAvatarAppearance( appearance ), - mIsVisible( TRUE ), + mIsVisible( true ), mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD), mInfo( NULL ) { @@ -277,7 +277,7 @@ LLTexLayerSet::~LLTexLayerSet() // setInfo //----------------------------------------------------------------------------- -BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) +bool LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) { llassert(mInfo == NULL); mInfo = info; @@ -323,7 +323,7 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) // parseData //----------------------------------------------------------------------------- -BOOL LLTexLayerSet::parseData(LLXmlTreeNode* node) +bool LLTexLayerSet::parseData(LLXmlTreeNode* node) { LLTexLayerSetInfo *info = new LLTexLayerSetInfo; @@ -354,10 +354,10 @@ void LLTexLayerSet::deleteCaches() } -BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) +bool LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) { - BOOL success = TRUE; - mIsVisible = TRUE; + bool success = true; + mIsVisible = true; if (mMaskLayerList.size() > 0) { @@ -365,7 +365,7 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* { if (layer->isInvisibleAlphaMask()) { - mIsVisible = FALSE; + mIsVisible = false; } } } @@ -425,8 +425,8 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* } -BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const -{ +bool LLTexLayerSet::isBodyRegion(const std::string& region) const +{ return mInfo->mBodyRegion == region; } @@ -484,7 +484,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, { gGL.flush(); { - LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, TRUE); + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, true); if( tex ) { LLGLSUIDefault gls_ui; @@ -533,7 +533,7 @@ void LLTexLayerSet::applyMorphMask(const U8* tex_data, S32 width, S32 height, S3 mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); } -BOOL LLTexLayerSet::isMorphValid() const +bool LLTexLayerSet::isMorphValid() const { for(const LLTexLayerInterface* layer : mLayerList) { @@ -561,13 +561,13 @@ void LLTexLayerSet::invalidateMorphMasks() // LLTexLayerInfo //----------------------------------------------------------------------------- LLTexLayerInfo::LLTexLayerInfo() : - mWriteAllChannels( FALSE ), + mWriteAllChannels( false ), mRenderPass(LLTexLayer::RP_COLOR), mFixedColor( 0.f, 0.f, 0.f, 0.f ), mLocalTexture( -1 ), - mStaticImageIsMask( FALSE ), - mUseLocalTextureAlphaOnly(FALSE), - mIsVisibilityMask(FALSE) + mStaticImageIsMask( false ), + mUseLocalTextureAlphaOnly(false), + mIsVisibilityMask(false) { } @@ -609,7 +609,7 @@ bool LLTexLayerInfo::parseXml(LLXmlTreeNode* node) node->getFastAttributeString( global_color_string, mGlobalColor ); // Visibility mask (optional) - BOOL is_visibility; + bool is_visibility; static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask"); if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility)) { @@ -675,10 +675,10 @@ bool LLTexLayerInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name"); if (maskNode->getFastAttributeString(morph_name_string, morph_name)) { - BOOL invert = FALSE; + bool invert = false; static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); maskNode->getFastAttributeBOOL(invert_string, invert); - mMorphNameList.push_back(std::pair(morph_name,invert)); + mMorphNameList.push_back(std::pair(morph_name,invert)); } } @@ -714,28 +714,28 @@ bool LLTexLayerInfo::parseXml(LLXmlTreeNode* node) return true; } -BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) +bool LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) { - BOOL success = true; + bool success = true; for (LLTexLayerParamColorInfo* color_info : mParamColorInfoList) { LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); - if (!param_color->setInfo(color_info, TRUE)) + if (!param_color->setInfo(color_info, true)) { LL_WARNS() << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << LL_ENDL; delete param_color; - success = FALSE; + success = false; } } for (LLTexLayerParamAlphaInfo* alpha_info : mParamAlphaInfoList) { LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance); - if (!param_alpha->setInfo(alpha_info, TRUE)) + if (!param_alpha->setInfo(alpha_info, true)) { LL_WARNS() << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << LL_ENDL; delete param_alpha; - success = FALSE; + success = false; } } @@ -744,9 +744,9 @@ BOOL LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): mTexLayerSet( layer_set ), - mMorphMasksValid( FALSE ), + mMorphMasksValid( false ), mInfo(NULL), - mHasMorph(FALSE) + mHasMorph(false) { } @@ -760,7 +760,7 @@ LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWea mHasMorph = layer.mHasMorph; } -BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions +bool LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions { // setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer. // Not a critical warning, but could be useful for debugging later issues. -Nyx @@ -778,7 +778,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab if (!wearable) { param_color = new LLTexLayerParamColor(this); - if (!param_color->setInfo(color_info, TRUE)) + if (!param_color->setInfo(color_info, true)) { mInfo = NULL; return false; @@ -803,7 +803,7 @@ BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearab if (!wearable) { param_alpha = new LLTexLayerParamAlpha( this ); - if (!param_alpha->setInfo(alpha_info, TRUE)) + if (!param_alpha->setInfo(alpha_info, true)) { mInfo = NULL; return false; @@ -893,14 +893,14 @@ const std::string& LLTexLayerInterface::getGlobalColor() const return mInfo->mGlobalColor; } -BOOL LLTexLayerInterface::isVisibilityMask() const +bool LLTexLayerInterface::isVisibilityMask() const { return mInfo->mIsVisibilityMask; } void LLTexLayerInterface::invalidateMorphMasks() { - mMorphMasksValid = FALSE; + mMorphMasksValid = false; } LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const @@ -980,7 +980,7 @@ void LLTexLayer::asLLSD(LLSD& sd) const // setInfo //----------------------------------------------------------------------------- -BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +bool LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) { return LLTexLayerInterface::setInfo(info, wearable); } @@ -1020,14 +1020,14 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL } } -BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) +bool LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) { // *TODO: Is this correct? //gPipeline.disableLights(); stop_glerror(); LLColor4 net_color; - BOOL color_specified = findNetColor(&net_color); + bool color_specified = findNetColor(&net_color); if (mTexLayerSet->getAvatarAppearance()->mIsDummy) { @@ -1035,7 +1035,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou net_color = LLAvatarAppearance::getDummyColor(); } - BOOL success = TRUE; + bool success = true; // If you can't see the layer, don't render it. if( is_approx_zero( net_color.mV[VW] ) ) @@ -1043,7 +1043,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou return success; } - BOOL alpha_mask_specified = FALSE; + bool alpha_mask_specified = false; param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); if( iter != mParamAlphaList.end() ) { @@ -1051,7 +1051,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou // However, we can't do this optimization if we have morph masks that need updating. /* if (!mHasMorph) { - BOOL skip_layer = TRUE; + bool skip_layer = true; while( iter != mParamAlphaList.end() ) { @@ -1059,7 +1059,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou if( !param->getSkip() ) { - skip_layer = FALSE; + skip_layer = false; break; } @@ -1074,7 +1074,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou const bool force_render = true; renderMorphMasks(x, y, width, height, net_color, bound_target, force_render); - alpha_mask_specified = TRUE; + alpha_mask_specified = true; gGL.flush(); gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); } @@ -1115,7 +1115,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->bind(tex, true); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); @@ -1130,7 +1130,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou } // else // { -// success = FALSE; +// success = false; // } } } @@ -1141,13 +1141,13 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); if( tex ) { - gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->bind(tex, true); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } else { - success = FALSE; + success = false; } } } @@ -1199,7 +1199,7 @@ const U8* LLTexLayer::getAlphaData() const return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; } -BOOL LLTexLayer::findNetColor(LLColor4* net_color) const +bool LLTexLayer::findNetColor(LLColor4* net_color) const { // Color is either: // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) @@ -1243,9 +1243,9 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const return false; // No need to draw a separate colored polygon } -BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) +bool LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) { - BOOL success = true; + bool success = true; gGL.flush(); @@ -1255,14 +1255,14 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) if( tex ) { gAlphaMaskProgram.setMinimumAlpha(0.f); - gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->bind(tex, true); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gAlphaMaskProgram.setMinimumAlpha(0.004f); } else { - success = FALSE; + success = false; } } else @@ -1297,7 +1297,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC return; } LL_PROFILE_ZONE_SCOPED; - BOOL success = TRUE; + bool success = true; llassert( !mParamAlphaList.empty() ); @@ -1342,7 +1342,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->bind(tex, true); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); gl_rect_2d_simple_tex( width, height ); @@ -1359,7 +1359,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { if( (tex->getComponents() == 4) || (tex->getComponents() == 1) ) { - gGL.getTexUnit(0)->bind(tex, TRUE); + gGL.getTexUnit(0)->bind(tex, true); gl_rect_2d_simple_tex( width, height ); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } @@ -1480,7 +1480,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); - mMorphMasksValid = TRUE; + mMorphMasksValid = true; getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); } } @@ -1513,7 +1513,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 } } -/*virtual*/ BOOL LLTexLayer::isInvisibleAlphaMask() const +/*virtual*/ bool LLTexLayer::isInvisibleAlphaMask() const { if (mLocalTextureObject) { @@ -1582,7 +1582,7 @@ LLTexLayerTemplate::~LLTexLayerTemplate() // setInfo //----------------------------------------------------------------------------- -/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +/*virtual*/ bool LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) { return LLTexLayerInterface::setInfo(info, wearable); } @@ -1631,14 +1631,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return layer; } -/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) +/*virtual*/ bool LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) { if(!mInfo) { - return FALSE ; + return false ; } - BOOL success = TRUE; + bool success = true; updateWearableCache(); for (LLWearable* wearable : mWearableCache) { @@ -1663,9 +1663,9 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const return success; } -/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer +/*virtual*/ bool LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer { - BOOL success = TRUE; + bool success = true; U32 num_wearables = updateWearableCache(); for (U32 i = 0; i < num_wearables; i++) { @@ -1689,8 +1689,8 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const } } -/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval) -{ +/*virtual*/ void LLTexLayerTemplate::setHasMorph(bool newval) +{ mHasMorph = newval; U32 num_wearables = updateWearableCache(); for (U32 i = 0; i < num_wearables; i++) @@ -1716,7 +1716,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const } } -/*virtual*/ BOOL LLTexLayerTemplate::isInvisibleAlphaMask() const +/*virtual*/ bool LLTexLayerTemplate::isInvisibleAlphaMask() const { U32 num_wearables = updateWearableCache(); for (U32 i = 0; i < num_wearables; i++) @@ -1853,7 +1853,7 @@ LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. -LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, BOOL is_mask) +LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, bool is_mask) { LL_PROFILE_ZONE_SCOPED; LLPointer tex; @@ -1867,7 +1867,7 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, else { llassert(gTextureManagerBridgep); - tex = gTextureManagerBridgep->getLocalTexture( FALSE ); + tex = gTextureManagerBridgep->getLocalTexture( false ); LLPointer image_raw = new LLImageRaw; if( loadImageRaw( file_name, image_raw ) ) { @@ -1883,7 +1883,7 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); } - tex->createGLTexture(0, image_raw, 0, TRUE, LLGLTexture::LOCAL); + tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL); gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); @@ -1901,11 +1901,11 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, } // Reads a .tga file, decodes it, and puts the decoded data in image_raw. -// Returns TRUE if successful. -BOOL LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) +// Returns true if successful. +bool LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) { LL_PROFILE_ZONE_SCOPED; - BOOL success = FALSE; + bool success = false; std::string path; path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); LLPointer image_tga = new LLImageTGA( path ); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 2cca2b6b12..bc55db01fc 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -65,13 +65,13 @@ public: LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); virtual ~LLTexLayerInterface() {} - virtual BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; + virtual bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; virtual void deleteCaches() = 0; - virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; - virtual BOOL isInvisibleAlphaMask() const = 0; + virtual bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; + virtual bool isInvisibleAlphaMask() const = 0; const LLTexLayerInfo* getInfo() const { return mInfo; } - virtual BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions + virtual bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions LLWearableType::EType getWearableType() const; LLAvatarAppearanceDefines::ETextureIndex getLocalTextureIndex() const; @@ -80,16 +80,16 @@ public: LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; } void invalidateMorphMasks(); - virtual void setHasMorph(BOOL newval) { mHasMorph = newval; } - BOOL hasMorph() const { return mHasMorph; } - BOOL isMorphValid() const { return mMorphMasksValid; } + virtual void setHasMorph(bool newval) { mHasMorph = newval; } + bool hasMorph() const { return mHasMorph; } + bool isMorphValid() const { return mMorphMasksValid; } void requestUpdate(); virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0; - BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); } + bool hasAlphaParams() const { return !mParamAlphaList.empty(); } ERenderPass getRenderPass() const; - BOOL isVisibilityMask() const; + bool isVisibilityMask() const; virtual void asLLSD(LLSD& sd) const {} @@ -100,8 +100,8 @@ protected: protected: LLTexLayerSet* const mTexLayerSet; const LLTexLayerInfo* mInfo; - BOOL mMorphMasksValid; - BOOL mHasMorph; + bool mMorphMasksValid; + bool mHasMorph; // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. param_color_list_t mParamColorList; @@ -121,13 +121,13 @@ public: LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); LLTexLayerTemplate(const LLTexLayerTemplate &layer); /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); - /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + /*virtual*/ bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions + /*virtual*/ bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); - /*virtual*/ void setHasMorph(BOOL newval); + /*virtual*/ void setHasMorph(bool newval); /*virtual*/ void deleteCaches(); - /*virtual*/ BOOL isInvisibleAlphaMask() const; + /*virtual*/ bool isInvisibleAlphaMask() const; protected: U32 updateWearableCache() const; LLTexLayer* getLayer(U32 i) const; @@ -151,18 +151,18 @@ public: LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable); /*virtual*/ ~LLTexLayer(); - /*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions + /*virtual*/ bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); /*virtual*/ void deleteCaches(); const U8* getAlphaData() const; - BOOL findNetColor(LLColor4* color) const; - /*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + bool findNetColor(LLColor4* color) const; + /*virtual*/ bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render); void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); - /*virtual*/ BOOL isInvisibleAlphaMask() const; + /*virtual*/ bool isInvisibleAlphaMask() const; void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } LLLocalTextureObject* getLTO() { return mLocalTextureObject; } @@ -197,14 +197,14 @@ public: void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target); const LLTexLayerSetInfo* getInfo() const { return mInfo; } - BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions + bool setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions - BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); + bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); - BOOL isBodyRegion(const std::string& region) const; + bool isBodyRegion(const std::string& region) const; void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components); - BOOL isMorphValid() const; + bool isMorphValid() const; virtual void requestUpdate() = 0; void invalidateMorphMasks(); void deleteCaches(); @@ -213,12 +213,12 @@ public: LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } const std::string getBodyRegionName() const; - BOOL hasComposite() const { return (mComposite.notNull()); } + bool hasComposite() const { return (mComposite.notNull()); } LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() const { return mBakedTexIndex; } void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } - BOOL isVisible() const { return mIsVisible; } + bool isVisible() const { return mIsVisible; } - static BOOL sHasCaches; + static bool sHasCaches; protected: typedef std::vector layer_list_t; @@ -226,7 +226,7 @@ protected: layer_list_t mMaskLayerList; LLPointer mComposite; LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. - BOOL mIsVisible; + bool mIsVisible; LLAvatarAppearanceDefines::EBakedTextureIndex mBakedTexIndex; const LLTexLayerSetInfo* mInfo; @@ -252,7 +252,7 @@ protected: S32 mWidth; S32 mHeight; std::string mStaticAlphaFileName; - BOOL mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) + bool mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) typedef std::vector layer_info_list_t; layer_info_list_t mLayerInfoList; }; @@ -274,13 +274,13 @@ protected: void pushProjection() const; void popProjection() const; virtual void preRenderTexLayerSet(); - virtual void midRenderTexLayerSet(BOOL success) {} - virtual void postRenderTexLayerSet(BOOL success); + virtual void midRenderTexLayerSet(bool success) {} + virtual void postRenderTexLayerSet(bool success); virtual S32 getCompositeOriginX() const = 0; virtual S32 getCompositeOriginY() const = 0; virtual S32 getCompositeWidth() const = 0; virtual S32 getCompositeHeight() const = 0; - BOOL renderTexLayerSet(LLRenderTarget* bound_target); + bool renderTexLayerSet(LLRenderTarget* bound_target); LLTexLayerSet* const mTexLayerSet; }; @@ -294,12 +294,12 @@ class LLTexLayerStaticImageList : public LLSingleton LLSINGLETON(LLTexLayerStaticImageList); ~LLTexLayerStaticImageList(); public: - LLGLTexture* getTexture(const std::string& file_name, BOOL is_mask); + LLGLTexture* getTexture(const std::string& file_name, bool is_mask); LLImageTGA* getImageTGA(const std::string& file_name); void deleteCachedImages(); void dumpByteCount() const; protected: - BOOL loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); + bool loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); private: LLStringTable mImageNames; typedef std::map > texture_map_t; diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 4cfbdc01c1..8ad718a506 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -69,7 +69,7 @@ LLTexLayerParam::LLTexLayerParam(const LLTexLayerParam& pOther) { } -BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance) +bool LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, bool add_to_appearance) { LLViewerVisualParam::setInfo(info); @@ -123,8 +123,8 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) mCachedProcessedTexture(NULL), mStaticImageTGA(), mStaticImageRaw(), - mNeedsCreateTexture(FALSE), - mStaticImageInvalid(FALSE), + mNeedsCreateTexture(false), + mStaticImageInvalid(false), mAvgDistortionVec(1.f, 1.f, 1.f), mCachedEffectiveWeight(0.f) { @@ -136,8 +136,8 @@ LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) mCachedProcessedTexture(NULL), mStaticImageTGA(), mStaticImageRaw(), - mNeedsCreateTexture(FALSE), - mStaticImageInvalid(FALSE), + mNeedsCreateTexture(false), + mStaticImageInvalid(false), mAvgDistortionVec(1.f, 1.f, 1.f), mCachedEffectiveWeight(0.f) { @@ -173,10 +173,10 @@ void LLTexLayerParamAlpha::deleteCaches() mStaticImageTGA = NULL; // deletes image mCachedProcessedTexture = NULL; mStaticImageRaw = NULL; - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; } -BOOL LLTexLayerParamAlpha::getMultiplyBlend() const +bool LLTexLayerParamAlpha::getMultiplyBlend() const { return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; } @@ -216,7 +216,7 @@ void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value) mTargetWeight = target_value; setWeight(target_value); - mIsAnimating = TRUE; + mIsAnimating = true; if (mNext) { mNext->setAnimationTarget(target_value); @@ -231,7 +231,7 @@ void LLTexLayerParamAlpha::animate(F32 delta) } } -BOOL LLTexLayerParamAlpha::getSkip() const +bool LLTexLayerParamAlpha::getSkip() const { if (!mTexLayer) { @@ -259,10 +259,10 @@ BOOL LLTexLayerParamAlpha::getSkip() const } -BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) +bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) { LL_PROFILE_ZONE_SCOPED; - BOOL success = true; + bool success = true; if (!mTexLayer) { @@ -270,7 +270,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) } F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatarAppearance()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); - BOOL weight_changed = effective_weight != mCachedEffectiveWeight; + bool weight_changed = effective_weight != mCachedEffectiveWeight; if (getSkip()) { return success; @@ -294,12 +294,12 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // Don't load the image file until we actually need it the first time. Like now. mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName); // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? TRUE : FALSE; + LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? true : false; if (mStaticImageTGA.isNull()) { LL_WARNS() << "Unable to load static file: " << info->mStaticImageFileName << LL_ENDL; - mStaticImageInvalid = TRUE; // don't try again. + mStaticImageInvalid = true; // don't try again. return false; } } @@ -316,10 +316,10 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) if (!mCachedProcessedTexture) { llassert(gTextureManagerBridgep); - mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, FALSE); + mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, false); // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? TRUE : FALSE; + LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? true : false; mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA); } @@ -328,7 +328,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) mStaticImageRaw = NULL; mStaticImageRaw = new LLImageRaw; mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight); - mNeedsCreateTexture = TRUE; + mNeedsCreateTexture = true; LL_DEBUGS() << "Built Cached Alpha: " << info->mStaticImageFileName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << "Domain: " << info->mDomain << " Weight: " << effective_weight << LL_ENDL; } @@ -339,7 +339,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) if (mNeedsCreateTexture) { mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = false; gGL.getTexUnit(0)->bind(mCachedProcessedTexture); mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -372,8 +372,8 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // LLTexLayerParamAlphaInfo //----------------------------------------------------------------------------- LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() : - mMultiplyBlend(FALSE), - mSkipIfZeroWeight(FALSE), + mMultiplyBlend(false), + mSkipIfZeroWeight(false), mDomain(0.f) { } @@ -514,7 +514,7 @@ void LLTexLayerParamColor::setAnimationTarget(F32 target_value) // set value first then set interpolating flag to ignore further updates mTargetWeight = target_value; setWeight(target_value); - mIsAnimating = TRUE; + mIsAnimating = true; if (mNext) { mNext->setAnimationTarget(target_value); diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index 1dbfd0b3d6..3767a9627f 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -48,7 +48,7 @@ class LLTexLayerParam : public LLViewerVisualParam public: LLTexLayerParam(LLTexLayerInterface *layer); LLTexLayerParam(LLAvatarAppearance *appearance); - /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_appearance); + /*virtual*/ bool setInfo(LLViewerVisualParamInfo *info, bool add_to_appearance); /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; protected: @@ -74,7 +74,7 @@ public: /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + ///*virtual*/ bool parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex avatar_sex ) {} /*virtual*/ void setWeight(F32 weight); /*virtual*/ void setAnimationTarget(F32 target_value); @@ -89,10 +89,10 @@ public: /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions - BOOL render( S32 x, S32 y, S32 width, S32 height ); - BOOL getSkip() const; + bool render( S32 x, S32 y, S32 width, S32 height ); + bool getSkip() const; void deleteCaches(); - BOOL getMultiplyBlend() const; + bool getMultiplyBlend() const; private: LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther); @@ -100,8 +100,8 @@ private: LLPointer mCachedProcessedTexture; LLPointer mStaticImageTGA; LLPointer mStaticImageRaw; - std::atomic mNeedsCreateTexture; - BOOL mStaticImageInvalid; + std::atomic mNeedsCreateTexture; + bool mStaticImageInvalid; LL_ALIGN_16(LLVector4a mAvgDistortionVec); F32 mCachedEffectiveWeight; @@ -124,8 +124,8 @@ public: private: std::string mStaticImageFileName; - BOOL mMultiplyBlend; - BOOL mSkipIfZeroWeight; + bool mMultiplyBlend; + bool mSkipIfZeroWeight; F32 mDomain; }; // @@ -157,7 +157,7 @@ public: /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + ///*virtual*/ bool parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex avatar_sex ) {} /*virtual*/ void setWeight(F32 weight); /*virtual*/ void setAnimationTarget(F32 target_value); diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index 43fb8fab5e..30a244be93 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -39,12 +39,12 @@ LLViewerVisualParamInfo::LLViewerVisualParamInfo() : mWearableType( LLWearableType::WT_INVALID ), - mCrossWearable(FALSE), + mCrossWearable(false), mCamDist( 0.5f ), mCamAngle( 0.f ), mCamElevation( 0.f ), mEditGroupDisplayOrder( 0 ), - mShowSimple(FALSE), + mShowSimple(false), mSimpleMin(0.f), mSimpleMax(100.f) { @@ -82,7 +82,7 @@ bool LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable"); if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable)) { - mCrossWearable = FALSE; + mCrossWearable = false; } // Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails). @@ -146,7 +146,7 @@ LLViewerVisualParam::~LLViewerVisualParam() // setInfo() //----------------------------------------------------------------------------- -BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) +bool LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) { llassert(mInfo == NULL); if (info->mID < 0) diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index 9ad3e6eae8..42c32aa319 100644 --- a/indra/llappearance/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h @@ -49,13 +49,13 @@ public: protected: S32 mWearableType; - BOOL mCrossWearable; + bool mCrossWearable; std::string mEditGroup; F32 mCamDist; F32 mCamAngle; // degrees F32 mCamElevation; F32 mEditGroupDisplayOrder; - BOOL mShowSimple; // show edit controls when in "simple ui" mode? + bool mShowSimple; // show edit controls when in "simple ui" mode? F32 mSimpleMin; // when in simple UI, apply this minimum, range 0.f to 100.f F32 mSimpleMax; // when in simple UI, apply this maximum, range 0.f to 100.f }; @@ -75,12 +75,12 @@ public: // Special: These functions are overridden by child classes LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; }; // This sets mInfo and calls initialization functions - BOOL setInfo(LLViewerVisualParamInfo *info); + bool setInfo(LLViewerVisualParamInfo *info); virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; // LLVisualParam Virtual functions - ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + ///*virtual*/ bool parseData(LLXmlTreeNode* node); // New Virtual functions virtual F32 getTotalDistortion() = 0; @@ -99,11 +99,11 @@ public: F32 getCameraAngle() const { return getInfo()->mCamAngle; } // degrees F32 getCameraElevation() const { return getInfo()->mCamElevation; } - BOOL getShowSimple() const { return getInfo()->mShowSimple; } + bool getShowSimple() const { return getInfo()->mShowSimple; } F32 getSimpleMin() const { return getInfo()->mSimpleMin; } F32 getSimpleMax() const { return getInfo()->mSimpleMax; } - BOOL getCrossWearable() const { return getInfo()->mCrossWearable; } + bool getCrossWearable() const { return getInfo()->mCrossWearable; } protected: LLViewerVisualParam(const LLViewerVisualParam& pOther); diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index db7db32b3e..853b850fed 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -86,14 +86,14 @@ LLAssetType::EType LLWearable::getAssetType() const return LLWearableType::getInstance()->getAssetType(mType); } -BOOL LLWearable::exportFile(const std::string& filename) const +bool LLWearable::exportFile(const std::string& filename) const { llofstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); return ofs.is_open() && exportStream(ofs); } // virtual -BOOL LLWearable::exportStream( std::ostream& output_stream ) const +bool LLWearable::exportStream( std::ostream& output_stream ) const { if (!output_stream.good()) return false; @@ -469,7 +469,7 @@ LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, return LLWearable::SUCCESS; } -BOOL LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size) +bool LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size) { if (!input_stream.good()) { @@ -636,7 +636,7 @@ void LLWearable::addVisualParam(LLVisualParam *param) { delete mVisualParamIndexMap[param->getID()]; } - param->setIsDummy(FALSE); + param->setIsDummy(false); param->setParamLocation(LOC_WEARABLE); mVisualParamIndexMap[param->getID()] = param; mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index d86db236a3..ccdb3273f2 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -80,9 +80,9 @@ public: SUCCESS, BAD_HEADER }; - BOOL exportFile(const std::string& filename) const; + bool exportFile(const std::string& filename) const; EImportResult importFile(const std::string& filename, LLAvatarAppearance* avatarp ); - virtual BOOL exportStream( std::ostream& output_stream ) const; + virtual bool exportStream( std::ostream& output_stream ) const; virtual EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } @@ -118,7 +118,7 @@ protected: void destroyTextures(); void createVisualParams(LLAvatarAppearance *avatarp); void createLayers(S32 te, LLAvatarAppearance *avatarp); - BOOL getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size); + bool getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size); static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created. diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 2a0b77ee39..db5c93352a 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -86,7 +86,7 @@ void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LL { wearable_vec[index] = wearable; old_wearable->setUpdated(); - const BOOL removed = FALSE; + const bool removed = false; wearableUpdated(wearable, removed); } } @@ -105,14 +105,14 @@ void LLWearableData::pushWearable(const LLWearableType::EType type, mWearableDatas[type].push_back(wearable); if (trigger_updated) { - const BOOL removed = FALSE; + const bool removed = false; wearableUpdated(wearable, removed); } } } // virtual -void LLWearableData::wearableUpdated(LLWearable *wearable, BOOL removed) +void LLWearableData::wearableUpdated(LLWearable *wearable, bool removed) { wearable->setUpdated(); if (!removed) @@ -144,7 +144,7 @@ void LLWearableData::eraseWearable(const LLWearableType::EType type, U32 index) if (wearable) { mWearableDatas[type].erase(mWearableDatas[type].begin() + index); - const BOOL removed = TRUE; + const bool removed = true; wearableUpdated(wearable, removed); } } @@ -200,7 +200,7 @@ void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type) } -BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const +bool LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const { if (wearable == NULL) { @@ -242,7 +242,7 @@ U32 LLWearableData::getClothingLayerCount() const return count; } -BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const +bool LLWearableData::canAddWearable(const LLWearableType::EType type) const { LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type); if (a_type==LLAssetType::AT_CLOTHING) @@ -259,7 +259,7 @@ BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const } } -BOOL LLWearableData::isOnTop(LLWearable* wearable) const +bool LLWearableData::isOnTop(LLWearable* wearable) const { if (!wearable) return false; const LLWearableType::EType type = wearable->getType(); diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h index b8e0bf8bd1..2fe9ae2302 100644 --- a/indra/llappearance/llwearabledata.h +++ b/indra/llappearance/llwearabledata.h @@ -60,11 +60,11 @@ public: const LLWearable* getBottomWearable(const LLWearableType::EType type) const; U32 getWearableCount(const LLWearableType::EType type) const; U32 getWearableCount(const U32 tex_index) const; - BOOL getWearableIndex(const LLWearable *wearable, U32& index) const; + bool getWearableIndex(const LLWearable *wearable, U32& index) const; U32 getClothingLayerCount() const; - BOOL canAddWearable(const LLWearableType::EType type) const; + bool canAddWearable(const LLWearableType::EType type) const; - BOOL isOnTop(LLWearable* wearable) const; + bool isOnTop(LLWearable* wearable) const; static const U32 MAX_CLOTHING_LAYERS = 60; @@ -76,7 +76,7 @@ protected: void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); void pushWearable(const LLWearableType::EType type, LLWearable *wearable, bool trigger_updated = true); - virtual void wearableUpdated(LLWearable *wearable, BOOL removed); + virtual void wearableUpdated(LLWearable *wearable, bool removed); void eraseWearable(LLWearable *wearable); void eraseWearable(const LLWearableType::EType type, U32 index); void clearWearableType(const LLWearableType::EType type); diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 056f7cf888..c561502a3d 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -32,27 +32,27 @@ LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans) { - addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE)); - addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE)); - addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE)); - addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE)); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE)); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE)); - addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE)); - addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE)); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE)); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE)); - addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE)); - addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE)); - - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE)); - - addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE)); - addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE)); + addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, false, false)); + addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, false, false)); + addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, false, false)); + addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, false, false)); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, false, true)); + addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, false, true)); + addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, false, true)); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, false, true)); + addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, false, true)); + addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, false, true)); + addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, false, true)); + addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, false, true)); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, false, true)); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, false, true)); + addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, false, true)); + addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, false, true)); + + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, true, true)); + + addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, false, false)); + addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, false, false)); } @@ -112,14 +112,14 @@ LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType typ return entry->mIconName; } -BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) +bool LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) { const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return false; return entry->mDisableCameraSwitch; } -BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type) +bool LLWearableType::getAllowMultiwear(LLWearableType::EType type) { const WearableEntry *entry = mDictionary.lookup(type); if (!entry) return false; diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 793a33cc87..d2a85581bc 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -72,8 +72,8 @@ public: LLAssetType::EType getAssetType(EType type); EType typeNameToType(const std::string& type_name); LLInventoryType::EIconName getIconName(EType type); - BOOL getDisableCameraSwitch(EType type); - BOOL getAllowMultiwear(EType type); + bool getDisableCameraSwitch(EType type); + bool getAllowMultiwear(EType type); static EType inventoryFlagsToWearableType(U32 flags); @@ -85,8 +85,8 @@ private: const std::string& default_new_name, LLAssetType::EType assetType, LLInventoryType::EIconName iconName, - BOOL disable_camera_switch = FALSE, - BOOL allow_multiwear = TRUE) : + bool disable_camera_switch = false, + bool allow_multiwear = true) : LLDictionaryEntry(name), mAssetType(assetType), mDefaultNewName(default_new_name), @@ -101,8 +101,8 @@ private: const std::string mLabel; const std::string mDefaultNewName; LLInventoryType::EIconName mIconName; - BOOL mDisableCameraSwitch; - BOOL mAllowMultiwear; + bool mDisableCameraSwitch; + bool mAllowMultiwear; }; class LLWearableDictionary : public LLDictionary -- cgit v1.2.3 From 088f2f4f6545ebc2ee01945938a40ae5c87ad27a Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 17 Feb 2024 00:51:13 +0100 Subject: More BOOL to bool replacements primarily in llappearance and llxml --- indra/llappearance/llavatarappearancedefines.h | 2 +- indra/llappearance/llavatarjointmesh.h | 3 --- indra/llappearance/llpolymorph.h | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 21c0dedeba..0bba3ddfcc 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -40,7 +40,7 @@ namespace LLAvatarAppearanceDefines extern const S32 SCRATCH_TEX_WIDTH; extern const S32 SCRATCH_TEX_HEIGHT; -static const U32 AVATAR_HOVER = 11001; +static constexpr U32 AVATAR_HOVER = 11001; //-------------------------------------------------------------------- // Enums diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 57cf5a26f8..0d815643e9 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -122,9 +122,6 @@ public: // Sets up joint matrix data for rendering void setupJoint(LLAvatarJoint* current_joint); - // Render time method to upload batches of joint matrices - void uploadJointMatrices(); - // Sets ID for picking void setMeshID( S32 id ) {mMeshID = id;} diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 5544344036..a932433819 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -183,7 +183,7 @@ protected: LLPolyVertexMask * mVertMask; ESex mLastSex; // number of morph masks that haven't been generated, must be 0 before this morph is applied - BOOL mNumMorphMasksPending; + S32 mNumMorphMasksPending; typedef std::vector volume_list_t; volume_list_t mVolumeMorphs; -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/llappearance/llpolymesh.cpp | 2 +- indra/llappearance/lltexlayerparams.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 42a37c4e16..e4e9e8d550 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -321,7 +321,7 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) } if (!isLOD()) { - mHasWeights = (hasWeights==0) ? false : true; + mHasWeights = hasWeights > 0; } //---------------------------------------------------------------- diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 8ad718a506..19eb0c784d 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -294,7 +294,7 @@ bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // Don't load the image file until we actually need it the first time. Like now. mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName); // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull() ? true : false; + LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull(); if (mStaticImageTGA.isNull()) { @@ -319,7 +319,7 @@ bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, false); // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mCachedProcessedTexture ? true : false; + LLTexLayerSet::sHasCaches |= mCachedProcessedTexture.notNull(); mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA); } -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/llappearance/llavatarappearance.cpp | 4162 +++++++++++----------- indra/llappearance/llavatarappearance.h | 942 ++--- indra/llappearance/llavatarappearancedefines.cpp | 826 ++--- indra/llappearance/llavatarappearancedefines.h | 510 +-- indra/llappearance/llavatarjoint.cpp | 632 ++-- indra/llappearance/llavatarjoint.h | 280 +- indra/llappearance/llavatarjointmesh.cpp | 780 ++-- indra/llappearance/llavatarjointmesh.h | 282 +- indra/llappearance/lldriverparam.cpp | 1244 +++---- indra/llappearance/lldriverparam.h | 278 +- indra/llappearance/lllocaltextureobject.cpp | 424 +-- indra/llappearance/lllocaltextureobject.h | 172 +- indra/llappearance/llpolymesh.cpp | 2080 +++++------ indra/llappearance/llpolymesh.h | 736 ++-- indra/llappearance/llpolymorph.cpp | 1688 ++++----- indra/llappearance/llpolymorph.h | 386 +- indra/llappearance/llpolyskeletaldistortion.cpp | 594 +-- indra/llappearance/llpolyskeletaldistortion.h | 246 +- indra/llappearance/lltexglobalcolor.cpp | 330 +- indra/llappearance/lltexglobalcolor.h | 170 +- indra/llappearance/lltexlayer.cpp | 3840 ++++++++++---------- indra/llappearance/lltexlayer.h | 626 ++-- indra/llappearance/lltexlayerparams.cpp | 1188 +++--- indra/llappearance/lltexlayerparams.h | 412 +-- indra/llappearance/llviewervisualparam.cpp | 358 +- indra/llappearance/llviewervisualparam.h | 224 +- indra/llappearance/llwearable.cpp | 1546 ++++---- indra/llappearance/llwearable.h | 276 +- indra/llappearance/llwearabledata.cpp | 688 ++-- indra/llappearance/llwearabledata.h | 204 +- indra/llappearance/llwearabletype.cpp | 268 +- indra/llappearance/llwearabletype.h | 236 +- 32 files changed, 13314 insertions(+), 13314 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index ed023c670b..f06845f084 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -1,2081 +1,2081 @@ -/** - * @File llavatarappearance.cpp - * @brief Implementation of LLAvatarAppearance class - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llavatarappearance.h" -#include "llavatarappearancedefines.h" -#include "llavatarjointmesh.h" -#include "llstl.h" -#include "lldir.h" -#include "llpolymorph.h" -#include "llpolymesh.h" -#include "llpolyskeletaldistortion.h" -#include "llstl.h" -#include "lltexglobalcolor.h" -#include "llwearabledata.h" -#include "boost/bind.hpp" -#include "boost/tokenizer.hpp" - -using namespace LLAvatarAppearanceDefines; - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -const std::string AVATAR_DEFAULT_CHAR = "avatar"; -const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); - -/********************************************************************************* - ** ** - ** Begin private LLAvatarAppearance Support classes - ** - **/ - -//------------------------------------------------------------------------ -// LLAvatarBoneInfo -// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. -//------------------------------------------------------------------------ -class LLAvatarBoneInfo -{ - friend class LLAvatarAppearance; - friend class LLAvatarSkeletonInfo; -public: - LLAvatarBoneInfo() : mIsJoint(false) {} - ~LLAvatarBoneInfo() - { - std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); - mChildren.clear(); - } - bool parseXml(LLXmlTreeNode* node); - -private: - std::string mName; - std::string mSupport; - std::string mAliases; - bool mIsJoint; - LLVector3 mPos; - LLVector3 mEnd; - LLVector3 mRot; - LLVector3 mScale; - LLVector3 mPivot; - typedef std::vector bones_t; - bones_t mChildren; -}; - -//------------------------------------------------------------------------ -// LLAvatarSkeletonInfo -// Overall avatar skeleton -//------------------------------------------------------------------------ -class LLAvatarSkeletonInfo -{ - friend class LLAvatarAppearance; -public: - LLAvatarSkeletonInfo() : - mNumBones(0), mNumCollisionVolumes(0) {} - ~LLAvatarSkeletonInfo() - { - std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); - mBoneInfoList.clear(); - } - bool parseXml(LLXmlTreeNode* node); - S32 getNumBones() const { return mNumBones; } - S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } - -private: - S32 mNumBones; - S32 mNumCollisionVolumes; - LLAvatarAppearance::joint_alias_map_t mJointAliasMap; - typedef std::vector bone_info_list_t; - bone_info_list_t mBoneInfoList; -}; - -//----------------------------------------------------------------------------- -// LLAvatarXmlInfo -//----------------------------------------------------------------------------- - -LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo() - : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) -{ -} - -LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo() -{ - std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); - mMeshInfoList.clear(); - - std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); - mSkeletalDistortionInfoList.clear(); - - std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); - mAttachmentInfoList.clear(); - - delete_and_clear(mTexSkinColorInfo); - delete_and_clear(mTexHairColorInfo); - delete_and_clear(mTexEyeColorInfo); - - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); - mLayerInfoList.clear(); - - std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); - mDriverInfoList.clear(); - - std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); - mMorphMaskInfoList.clear(); -} - - -/** - ** - ** End LLAvatarAppearance Support classes - ** ** - *********************************************************************************/ - -//----------------------------------------------------------------------------- -// Static Data -//----------------------------------------------------------------------------- -LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL; -LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL; -LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* LLAvatarAppearance::sAvatarDictionary = NULL; - - -LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : - LLCharacter(), - mIsDummy(false), - mTexSkinColor( NULL ), - mTexHairColor( NULL ), - mTexEyeColor( NULL ), - mPelvisToFoot(0.f), - mHeadOffset(), - mRoot(NULL), - mWearableData(wearable_data), - mNumBones(0), - mNumCollisionVolumes(0), - mCollisionVolumes(NULL), - mIsBuilt(false), - mInitFlags(0) -{ - llassert_always(mWearableData); - mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); - for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) - { - mBakedTextureDatas[i].mLastTextureID = IMG_DEFAULT_AVATAR; - mBakedTextureDatas[i].mTexLayerSet = NULL; - mBakedTextureDatas[i].mIsLoaded = false; - mBakedTextureDatas[i].mIsUsed = false; - mBakedTextureDatas[i].mMaskTexName = 0; - mBakedTextureDatas[i].mTextureIndex = sAvatarDictionary->bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); - } -} - -// virtual -void LLAvatarAppearance::initInstance() -{ - //------------------------------------------------------------------------- - // initialize joint, mesh and shape members - //------------------------------------------------------------------------- - mRoot = createAvatarJoint(); - mRoot->setName( "mRoot" ); - - for (const LLAvatarAppearanceDictionary::MeshEntries::value_type& mesh_pair : sAvatarDictionary->getMeshEntries()) - { - const EMeshIndex mesh_index = mesh_pair.first; - const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_pair.second; - LLAvatarJoint* joint = createAvatarJoint(); - 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++) - { - LLAvatarJointMesh* mesh = createAvatarJointMesh(); - std::string mesh_name = "m" + mesh_dict->mName + std::to_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); - mesh->setIsTransparent(false); - switch((S32)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 (const LLAvatarAppearanceDictionary::MeshEntries::value_type& mesh_pair : sAvatarDictionary->getMeshEntries()) - { - const EMeshIndex mesh_index = mesh_pair.first; - const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_pair.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 (LLAvatarJointMesh* mesh : mMeshLOD[mesh_index]->mMeshParts) - { - mBakedTextureDatas[(S32)baked_texture_index].mJointMeshes.push_back(mesh); - } - } - - buildCharacter(); - - mInitFlags |= 1<<0; - -} - -// virtual -LLAvatarAppearance::~LLAvatarAppearance() -{ - delete_and_clear(mTexSkinColor); - delete_and_clear(mTexHairColor); - delete_and_clear(mTexEyeColor); - - for (U32 i = 0; i < mBakedTextureDatas.size(); i++) - { - delete_and_clear(mBakedTextureDatas[i].mTexLayerSet); - mBakedTextureDatas[i].mJointMeshes.clear(); - - for (LLMaskedMorph* masked_morph : mBakedTextureDatas[i].mMaskedMorphs) - { - delete masked_morph; - } - } - - if (mRoot) - { - mRoot->removeAllChildren(); - delete mRoot; - mRoot = nullptr; - } - mJointMap.clear(); - - clearSkeleton(); - delete_and_clear_array(mCollisionVolumes); - - std::for_each(mPolyMeshes.begin(), mPolyMeshes.end(), DeletePairedPointer()); - mPolyMeshes.clear(); - - for (LLAvatarJoint* joint : mMeshLOD) - { - std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); - joint->mMeshParts.clear(); - } - std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); - mMeshLOD.clear(); -} - -//static -void LLAvatarAppearance::initClass() -{ - initClass("",""); -} - -//static -void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, const std::string& skeleton_file_name_arg) -{ - // init dictionary (don't repeat on second login attempt) - if (!sAvatarDictionary) - { - sAvatarDictionary = new LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary(); - } - - std::string avatar_file_name; - - if (!avatar_file_name_arg.empty()) - { - avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,avatar_file_name_arg); - } - else - { - avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml"); - } - LLXmlTree xml_tree; - bool success = xml_tree.parseFile( avatar_file_name, false ); - if (!success) - { - LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL; - } - - // now sanity check xml file - LLXmlTreeNode* root = xml_tree.getRoot(); - if (!root) - { - LL_ERRS() << "No root node found in avatar configuration file: " << avatar_file_name << LL_ENDL; - return; - } - - //------------------------------------------------------------------------- - // (root) - //------------------------------------------------------------------------- - if( !root->hasName( "linden_avatar" ) ) - { - LL_ERRS() << "Invalid avatar file header: " << avatar_file_name << LL_ENDL; - } - - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) - { - LL_ERRS() << "Invalid avatar file version: " << version << " in file: " << avatar_file_name << LL_ENDL; - } - - S32 wearable_def_version = 1; - static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version"); - root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); - LLWearable::setCurrentDefinitionVersion( wearable_def_version ); - - std::string mesh_file_name; - - LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); - if (!skeleton_node) - { - LL_ERRS() << "No skeleton in avatar configuration file: " << avatar_file_name << LL_ENDL; - return; - } - - std::string skeleton_file_name = skeleton_file_name_arg; - if (skeleton_file_name.empty()) - { - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) - { - LL_ERRS() << "No file name in skeleton node in avatar config file: " << avatar_file_name << LL_ENDL; - } - } - - std::string skeleton_path; - LLXmlTree skeleton_xml_tree; - skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); - if (!parseSkeletonFile(skeleton_path, skeleton_xml_tree)) - { - LL_ERRS() << "Error parsing skeleton file: " << skeleton_path << LL_ENDL; - } - - // Process XML data - - // avatar_skeleton.xml - if (sAvatarSkeletonInfo) - { //this can happen if a login attempt failed - delete sAvatarSkeletonInfo; - } - sAvatarSkeletonInfo = new LLAvatarSkeletonInfo; - if (!sAvatarSkeletonInfo->parseXml(skeleton_xml_tree.getRoot())) - { - LL_ERRS() << "Error parsing skeleton XML file: " << skeleton_path << LL_ENDL; - } - // parse avatar_lad.xml - if (sAvatarXmlInfo) - { //this can happen if a login attempt failed - delete_and_clear(sAvatarXmlInfo); - } - sAvatarXmlInfo = new LLAvatarXmlInfo; - if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) - { - LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; - } - if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) - { - LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; - } - if (!sAvatarXmlInfo->parseXmlColorNodes(root)) - { - LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; - } - if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) - { - LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; - } - if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) - { - LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; - } - if (!sAvatarXmlInfo->parseXmlMorphNodes(root)) - { - LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; - } -} - -void LLAvatarAppearance::cleanupClass() -{ - delete_and_clear(sAvatarXmlInfo); - delete_and_clear(sAvatarDictionary); - delete_and_clear(sAvatarSkeletonInfo); -} - -using namespace LLAvatarAppearanceDefines; - -void LLAvatarAppearance::compareJointStateMaps(joint_state_map_t& last_state, - joint_state_map_t& curr_state) -{ - if (!last_state.empty() && (last_state != curr_state)) - { - S32 diff_count = 0; - for (joint_state_map_t::value_type& pair : last_state) - { - const std::string& key = pair.first; - if (last_state[key] != curr_state[key]) - { - LL_DEBUGS("AvatarBodySize") << "BodySize change " << key << " " << last_state[key] << "->" << curr_state[key] << LL_ENDL; - diff_count++; - } - } - if (diff_count > 0) - { - LL_DEBUGS("AvatarBodySize") << "Total of BodySize changes " << diff_count << LL_ENDL; - } - - } -} - -//------------------------------------------------------------------------ -// The viewer can only suggest a good size for the agent, -// the simulator will keep it inside a reasonable range. -void LLAvatarAppearance::computeBodySize() -{ - mLastBodySizeState = mCurrBodySizeState; - - mCurrBodySizeState["mPelvis scale"] = mPelvisp->getScale(); - mCurrBodySizeState["mSkull pos"] = mSkullp->getPosition(); - mCurrBodySizeState["mSkull scale"] = mSkullp->getScale(); - mCurrBodySizeState["mNeck pos"] = mNeckp->getPosition(); - mCurrBodySizeState["mNeck scale"] = mNeckp->getScale(); - mCurrBodySizeState["mChest pos"] = mChestp->getPosition(); - mCurrBodySizeState["mChest scale"] = mChestp->getScale(); - mCurrBodySizeState["mHead pos"] = mHeadp->getPosition(); - mCurrBodySizeState["mHead scale"] = mHeadp->getScale(); - mCurrBodySizeState["mTorso pos"] = mTorsop->getPosition(); - mCurrBodySizeState["mTorso scale"] = mTorsop->getScale(); - mCurrBodySizeState["mHipLeft pos"] = mHipLeftp->getPosition(); - mCurrBodySizeState["mHipLeft scale"] = mHipLeftp->getScale(); - mCurrBodySizeState["mKneeLeft pos"] = mKneeLeftp->getPosition(); - mCurrBodySizeState["mKneeLeft scale"] = mKneeLeftp->getScale(); - mCurrBodySizeState["mAnkleLeft pos"] = mAnkleLeftp->getPosition(); - mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale(); - mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition(); - - F32 old_height = mBodySize.mV[VZ]; - F32 old_offset = mAvatarOffset.mV[VZ]; - - // TODO: Measure the real depth and width - mPelvisToFoot = computePelvisToFoot(); - F32 new_height = computeBodyHeight(); - mBodySize.set(DEFAULT_AGENT_DEPTH, DEFAULT_AGENT_WIDTH, new_height); - F32 new_offset = getVisualParamWeight(AVATAR_HOVER); - mAvatarOffset.set(0, 0, new_offset); - - if (mBodySize.mV[VZ] != old_height || new_offset != old_offset) - { - compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState); - } -} - -F32 LLAvatarAppearance::computeBodyHeight() -{ - F32 result = mPelvisToFoot + - // all these relative positions usually are positive - mPelvisp->getScale().mV[VZ] * mTorsop->getPosition().mV[VZ] + - mTorsop->getScale().mV[VZ] * mChestp->getPosition().mV[VZ] + - mChestp->getScale().mV[VZ] * mNeckp->getPosition().mV[VZ] + - mNeckp->getScale().mV[VZ] * mHeadp->getPosition().mV[VZ] + - mHeadp->getScale().mV[VZ] * mSkullp->getPosition().mV[VZ] * 2; - return result; -} - -F32 LLAvatarAppearance::computePelvisToFoot() -{ - F32 result = - // all these relative positions usually are negative - mPelvisp->getScale().mV[VZ] * mHipLeftp->getPosition().mV[VZ] + - mHipLeftp->getScale().mV[VZ] * mKneeLeftp->getPosition().mV[VZ] + - mKneeLeftp->getScale().mV[VZ] * mAnkleLeftp->getPosition().mV[VZ] + - mAnkleLeftp->getScale().mV[VZ] * mFootLeftp->getPosition().mV[VZ] / 2; - return -result; -} - -//----------------------------------------------------------------------------- -// parseSkeletonFile() -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree) -{ - //------------------------------------------------------------------------- - // parse the file - //------------------------------------------------------------------------- - bool parsesuccess = skeleton_xml_tree.parseFile( filename, false ); - - if (!parsesuccess) - { - LL_ERRS() << "Can't parse skeleton file: " << filename << LL_ENDL; - return false; - } - - // now sanity check xml file - LLXmlTreeNode* root = skeleton_xml_tree.getRoot(); - if (!root) - { - LL_ERRS() << "No root node found in avatar skeleton file: " << filename << LL_ENDL; - return false; - } - - if( !root->hasName( "linden_skeleton" ) ) - { - LL_ERRS() << "Invalid avatar skeleton file header: " << filename << LL_ENDL; - return false; - } - - std::string version; - static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); - if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) - { - LL_ERRS() << "Invalid avatar skeleton file version: " << version << " in file: " << filename << LL_ENDL; - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// setupBone() -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num) -{ - LLJoint* joint = NULL; - - LL_DEBUGS("BVH") << "bone info: name " << info->mName - << " isJoint " << info->mIsJoint - << " volume_num " << volume_num - << " joint_num " << joint_num - << LL_ENDL; - - if (info->mIsJoint) - { - joint = getCharacterJoint(joint_num); - if (!joint) - { - LL_WARNS() << "Too many bones" << LL_ENDL; - return false; - } - joint->setName( info->mName ); - } - else // collision volume - { - if (volume_num >= (S32)mNumCollisionVolumes) - { - LL_WARNS() << "Too many collision volumes" << LL_ENDL; - return false; - } - joint = (&mCollisionVolumes[volume_num]); - joint->setName( info->mName ); - } - - // add to parent - if (parent && (joint->getParent()!=parent)) - { - parent->addChild( joint ); - } - - // SL-315 - joint->setPosition(info->mPos); - joint->setDefaultPosition(info->mPos); - joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], - info->mRot.mV[VZ], LLQuaternion::XYZ)); - joint->setScale(info->mScale); - joint->setDefaultScale(info->mScale); - joint->setSupport(info->mSupport); - joint->setEnd(info->mEnd); - - if (info->mIsJoint) - { - joint->setSkinOffset( info->mPivot ); - joint->setJointNum(joint_num); - joint_num++; - } - else // collision volume - { - joint->setJointNum(mNumBones+volume_num); - volume_num++; - } - - - // setup children - for (LLAvatarBoneInfo* child_info : info->mChildren) - { - if (!setupBone(child_info, joint, volume_num, joint_num)) - { - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// allocateCharacterJoints() -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::allocateCharacterJoints( U32 num ) -{ - if (mSkeleton.size() != num) - { - clearSkeleton(); - mSkeleton = avatar_joint_list_t(num,NULL); - mNumBones = num; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// buildSkeleton() -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) -{ - LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL; - - // allocate joints - if (!allocateCharacterJoints(info->mNumBones)) - { - LL_ERRS() << "Can't allocate " << info->mNumBones << " joints" << LL_ENDL; - return false; - } - - // allocate volumes - if (info->mNumCollisionVolumes) - { - if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) - { - LL_ERRS() << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << LL_ENDL; - return false; - } - } - - S32 current_joint_num = 0; - S32 current_volume_num = 0; - for (LLAvatarBoneInfo* bone_info : info->mBoneInfoList) - { - if (!setupBone(bone_info, NULL, current_volume_num, current_joint_num)) - { - LL_ERRS() << "Error parsing bone in skeleton file" << LL_ENDL; - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// clearSkeleton() -//----------------------------------------------------------------------------- -void LLAvatarAppearance::clearSkeleton() -{ - std::for_each(mSkeleton.begin(), mSkeleton.end(), DeletePointer()); - mSkeleton.clear(); -} - -//------------------------------------------------------------------------ -// addPelvisFixup -//------------------------------------------------------------------------ -void LLAvatarAppearance::addPelvisFixup( F32 fixup, const LLUUID& mesh_id ) -{ - LLVector3 pos(0.0,0.0,fixup); - mPelvisFixups.add(mesh_id,pos); -} - -//------------------------------------------------------------------------ -// addPelvisFixup -//------------------------------------------------------------------------ -void LLAvatarAppearance::removePelvisFixup( const LLUUID& mesh_id ) -{ - mPelvisFixups.remove(mesh_id); -} - -//------------------------------------------------------------------------ -// hasPelvisFixup -//------------------------------------------------------------------------ -bool LLAvatarAppearance::hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const -{ - LLVector3 pos; - if (mPelvisFixups.findActiveOverride(mesh_id,pos)) - { - fixup = pos[2]; - return true; - } - return false; -} - -bool LLAvatarAppearance::hasPelvisFixup( F32& fixup ) const -{ - LLUUID mesh_id; - return hasPelvisFixup( fixup, mesh_id ); -} -//----------------------------------------------------------------------------- -// LLAvatarAppearance::buildCharacter() -// Deferred initialization and rebuild of the avatar. -//----------------------------------------------------------------------------- -void LLAvatarAppearance::buildCharacter() -{ - //------------------------------------------------------------------------- - // remove all references to our existing skeleton - // so we can rebuild it - //------------------------------------------------------------------------- - flushAllMotions(); - - //------------------------------------------------------------------------- - // remove all of mRoot's children - //------------------------------------------------------------------------- - mRoot->removeAllChildren(); - mJointMap.clear(); - mIsBuilt = false; - - //------------------------------------------------------------------------- - // clear mesh data - //------------------------------------------------------------------------- - for (LLAvatarJoint* joint : mMeshLOD) - { - for (LLAvatarJointMesh* mesh : joint->mMeshParts) - { - mesh->setMesh(NULL); - } - } - - //------------------------------------------------------------------------- - // (re)load our skeleton and meshes - //------------------------------------------------------------------------- - LLTimer timer; - - bool status = loadAvatar(); - stop_glerror(); - -// gPrintMessagesThisFrame = true; - LL_DEBUGS() << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << LL_ENDL; - - if (!status) - { - if (isSelf()) - { - LL_ERRS() << "Unable to load user's avatar" << LL_ENDL; - } - else - { - LL_WARNS() << "Unable to load other's avatar" << LL_ENDL; - } - return; - } - - //------------------------------------------------------------------------- - // initialize "well known" joint pointers - //------------------------------------------------------------------------- - mPelvisp = mRoot->findJoint("mPelvis"); - mTorsop = mRoot->findJoint("mTorso"); - mChestp = mRoot->findJoint("mChest"); - mNeckp = mRoot->findJoint("mNeck"); - mHeadp = mRoot->findJoint("mHead"); - mSkullp = mRoot->findJoint("mSkull"); - mHipLeftp = mRoot->findJoint("mHipLeft"); - mHipRightp = mRoot->findJoint("mHipRight"); - mKneeLeftp = mRoot->findJoint("mKneeLeft"); - mKneeRightp = mRoot->findJoint("mKneeRight"); - mAnkleLeftp = mRoot->findJoint("mAnkleLeft"); - mAnkleRightp = mRoot->findJoint("mAnkleRight"); - mFootLeftp = mRoot->findJoint("mFootLeft"); - mFootRightp = mRoot->findJoint("mFootRight"); - mWristLeftp = mRoot->findJoint("mWristLeft"); - mWristRightp = mRoot->findJoint("mWristRight"); - mEyeLeftp = mRoot->findJoint("mEyeLeft"); - mEyeRightp = mRoot->findJoint("mEyeRight"); - - //------------------------------------------------------------------------- - // Make sure "well known" pointers exist - //------------------------------------------------------------------------- - if (!(mPelvisp && - mTorsop && - mChestp && - mNeckp && - mHeadp && - mSkullp && - mHipLeftp && - mHipRightp && - mKneeLeftp && - mKneeRightp && - mAnkleLeftp && - mAnkleRightp && - mFootLeftp && - mFootRightp && - mWristLeftp && - mWristRightp && - mEyeLeftp && - mEyeRightp)) - { - LL_ERRS() << "Failed to create avatar." << LL_ENDL; - return; - } - - //------------------------------------------------------------------------- - // initialize the pelvis - //------------------------------------------------------------------------- - // SL-315 - mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); - - mIsBuilt = true; - stop_glerror(); - -} - -bool LLAvatarAppearance::loadAvatar() -{ -// LL_RECORD_BLOCK_TIME(FTM_LOAD_AVATAR); - - // avatar_skeleton.xml - if( !buildSkeleton(sAvatarSkeletonInfo) ) - { - LL_ERRS() << "avatar file: buildSkeleton() failed" << LL_ENDL; - return false; - } - - // initialize mJointAliasMap - getJointAliases(); - - // avatar_lad.xml : - if( !loadSkeletonNode() ) - { - LL_ERRS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL; - return false; - } - - // avatar_lad.xml : - if( !loadMeshNodes() ) - { - LL_ERRS() << "avatar file: loadNodeMesh() failed" << LL_ENDL; - return false; - } - - // avatar_lad.xml : - if( sAvatarXmlInfo->mTexSkinColorInfo ) - { - mTexSkinColor = new LLTexGlobalColor( this ); - if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) - { - LL_ERRS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL; - return false; - } - } - else - { - LL_ERRS() << " name=\"skin_color\" not found" << LL_ENDL; - return false; - } - if( sAvatarXmlInfo->mTexHairColorInfo ) - { - mTexHairColor = new LLTexGlobalColor( this ); - if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) - { - LL_ERRS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL; - return false; - } - } - else - { - LL_ERRS() << " name=\"hair_color\" not found" << LL_ENDL; - return false; - } - if( sAvatarXmlInfo->mTexEyeColorInfo ) - { - mTexEyeColor = new LLTexGlobalColor( this ); - if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) - { - LL_ERRS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL; - return false; - } - } - else - { - LL_ERRS() << " name=\"eye_color\" not found" << LL_ENDL; - return false; - } - - // avatar_lad.xml : - if (sAvatarXmlInfo->mLayerInfoList.empty()) - { - LL_ERRS() << "avatar file: missing node" << LL_ENDL; - return false; - } - - if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) - { - LL_ERRS() << "avatar file: missing node" << LL_ENDL; - return false; - } - - // avatar_lad.xml : - for (LLAvatarXmlInfo::LLAvatarMorphInfo* info : sAvatarXmlInfo->mMorphMaskInfoList) - { - EBakedTextureIndex baked = sAvatarDictionary->findBakedByRegionName(info->mRegion); - if (baked != BAKED_NUM_INDICES) - { - LLVisualParam* morph_param; - const std::string *name = &info->mName; - morph_param = getVisualParam(name->c_str()); - if (morph_param) - { - bool invert = info->mInvert; - addMaskedMorph(baked, morph_param, invert, info->mLayer); - } - } - - } - - loadLayersets(); - - // avatar_lad.xml : - for (LLDriverParamInfo* info : sAvatarXmlInfo->mDriverInfoList) - { - LLDriverParam* driver_param = new LLDriverParam( this ); - if (driver_param->setInfo(info)) - { - addVisualParam( driver_param ); - driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); - LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; - if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) - { - LL_WARNS() << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << LL_ENDL; - continue; - } - } - else - { - delete driver_param; - LL_WARNS() << "avatar file: driver_param->parseData() failed" << LL_ENDL; - return false; - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// loadSkeletonNode(): loads node from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::loadSkeletonNode () -{ - mRoot->addChild( mSkeleton[0] ); - - // make meshes children before calling parent version of the function - for (LLAvatarJoint* joint : mMeshLOD) - { - 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]); - - LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull"); - if (skull) - { - skull->addChild(mMeshLOD[MESH_ID_HAIR] ); - } - - LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft"); - if (eyeL) - { - eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); - } - - LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight"); - if (eyeR) - { - eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); - } - - // SKELETAL DISTORTIONS - { - for (LLViewerVisualParamInfo* visual_param_info : sAvatarXmlInfo->mSkeletalDistortionInfoList) - { - LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)visual_param_info; - LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); - if (!param->setInfo(info)) - { - delete param; - return false; - } - else - { - addVisualParam(param); - param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); - } - } - } - - - return true; -} - -//----------------------------------------------------------------------------- -// loadMeshNodes(): loads nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::loadMeshNodes() -{ - for (const LLAvatarXmlInfo::LLAvatarMeshInfo* info : sAvatarXmlInfo->mMeshInfoList) - { - const std::string &type = info->mType; - S32 lod = info->mLOD; - - LLAvatarJointMesh* mesh = NULL; - U8 mesh_id = 0; - bool found_mesh_id = false; - - /* if (type == "hairMesh") - switch(lod) - case 0: - mesh = &mHairMesh0; */ - for (const LLAvatarAppearanceDictionary::MeshEntries::value_type& mesh_pair : sAvatarDictionary->getMeshEntries()) - { - const EMeshIndex mesh_index = mesh_pair.first; - const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_pair.second; - if (type.compare(mesh_dict->mName) == 0) - { - mesh_id = mesh_index; - found_mesh_id = true; - break; - } - } - - if (found_mesh_id) - { - if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) - { - mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; - } - else - { - LL_WARNS() << "Avatar file: has invalid lod setting " << lod << LL_ENDL; - return false; - } - } - else - { - LL_WARNS() << "Ignoring unrecognized mesh type: " << type << LL_ENDL; - return false; - } - - // LL_INFOS() << "Parsing mesh data for " << type << "..." << LL_ENDL; - - // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. - // Do not touch!!! - mesh->setColor( LLColor4::white ); - - LLPolyMesh *poly_mesh = NULL; - - if (!info->mReferenceMeshName.empty()) - { - polymesh_map_t::const_iterator polymesh_iter = mPolyMeshes.find(info->mReferenceMeshName); - if (polymesh_iter != mPolyMeshes.end()) - { - 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; - return false; - } - } - else - { - poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName); - poly_mesh->setAvatar(this); - } - - if( !poly_mesh ) - { - LL_WARNS() << "Failed to load mesh of type " << type << LL_ENDL; - return false; - } - - // Multimap insert - mPolyMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); - - mesh->setMesh( poly_mesh ); - mesh->setLOD( info->mMinPixelArea ); - - for (const LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_pair_t& info_pair : info->mPolyMorphTargetInfoList) - { - LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); - if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair.first)) - { - delete param; - return false; - } - else - { - if (info_pair.second) - { - addSharedVisualParam(param); - param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); - } - else - { - addVisualParam(param); - param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); - } - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// loadLayerSets() -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::loadLayersets() -{ - bool success = true; - for (LLTexLayerSetInfo* layerset_info : sAvatarXmlInfo->mLayerInfoList) - { - if (isSelf()) - { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. - LLTexLayerSet* layer_set = createTexLayerSet(); - - if (!layer_set->setInfo(layerset_info)) - { - stop_glerror(); - delete layer_set; - LL_WARNS() << "avatar file: layer_set->setInfo() failed" << LL_ENDL; - return false; - } - - // scan baked textures and associate the layerset with the appropriate one - EBakedTextureIndex baked_index = BAKED_NUM_INDICES; - for (const LLAvatarAppearanceDictionary::BakedTextures::value_type& baked_pair : sAvatarDictionary->getBakedTextures()) - { - const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_pair.second; - if (layer_set->isBodyRegion(baked_dict->mName)) - { - baked_index = baked_pair.first; - // ensure both structures are aware of each other - mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; - layer_set->setBakedTexIndex(baked_index); - break; - } - } - // if no baked texture was found, warn and cleanup - if (baked_index == BAKED_NUM_INDICES) - { - LL_WARNS() << " has invalid body_region attribute" << LL_ENDL; - delete layer_set; - return false; - } - - // scan morph masks and let any affected layers know they have an associated morph - for (LLMaskedMorph* morph : mBakedTextureDatas[baked_index].mMaskedMorphs) - { - LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); - if (layer) - { - layer->setHasMorph(true); - } - else - { - LL_WARNS() << "Could not find layer named " << morph->mLayer << " to set morph flag" << LL_ENDL; - success = false; - } - } - } - else // !isSelf() - { - // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. - layerset_info->createVisualParams(this); - } - } - return success; -} - -//----------------------------------------------------------------------------- -// getCharacterJoint() -//----------------------------------------------------------------------------- -LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num ) -{ - if ((S32)num >= mSkeleton.size() - || (S32)num < 0) - { - return NULL; - } - if (!mSkeleton[num]) - { - mSkeleton[num] = createAvatarJoint(); - } - return mSkeleton[num]; -} - - -//----------------------------------------------------------------------------- -// getVolumePos() -//----------------------------------------------------------------------------- -LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_offset) -{ - if (joint_index > mNumCollisionVolumes) - { - return LLVector3::zero; - } - - return mCollisionVolumes[joint_index].getVolumePos(volume_offset); -} - -//----------------------------------------------------------------------------- -// findCollisionVolume() -//----------------------------------------------------------------------------- -LLJoint* LLAvatarAppearance::findCollisionVolume(S32 volume_id) -{ - if ((volume_id < 0) || (volume_id >= mNumCollisionVolumes)) - { - return NULL; - } - - return &mCollisionVolumes[volume_id]; -} - -//----------------------------------------------------------------------------- -// findCollisionVolume() -//----------------------------------------------------------------------------- -S32 LLAvatarAppearance::getCollisionVolumeID(std::string &name) -{ - for (S32 i = 0; i < mNumCollisionVolumes; i++) - { - if (mCollisionVolumes[i].getName() == name) - { - return i; - } - } - - return -1; -} - -//----------------------------------------------------------------------------- -// LLAvatarAppearance::getHeadMesh() -//----------------------------------------------------------------------------- -LLPolyMesh* LLAvatarAppearance::getHeadMesh() -{ - return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh(); -} - - -//----------------------------------------------------------------------------- -// LLAvatarAppearance::getUpperBodyMesh() -//----------------------------------------------------------------------------- -LLPolyMesh* LLAvatarAppearance::getUpperBodyMesh() -{ - return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh(); -} - - - -// virtual -bool LLAvatarAppearance::isValid() const -{ - // This should only be called on ourself. - if (!isSelf()) - { - LL_ERRS() << "Called LLAvatarAppearance::isValid() on when isSelf() == false" << LL_ENDL; - } - return true; -} - - -// adds a morph mask to the appropriate baked texture structure -void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, bool invert, std::string layer) -{ - if (index < BAKED_NUM_INDICES) - { - LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer); - mBakedTextureDatas[index].mMaskedMorphs.push_front(morph); - } -} - - -//static -bool LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) -{ - switch( te ) - { - case TEX_UPPER_SHIRT: - param_name[0] = 803; //"shirt_red"; - param_name[1] = 804; //"shirt_green"; - param_name[2] = 805; //"shirt_blue"; - break; - - case TEX_LOWER_PANTS: - param_name[0] = 806; //"pants_red"; - param_name[1] = 807; //"pants_green"; - param_name[2] = 808; //"pants_blue"; - break; - - case TEX_LOWER_SHOES: - param_name[0] = 812; //"shoes_red"; - param_name[1] = 813; //"shoes_green"; - param_name[2] = 817; //"shoes_blue"; - break; - - case TEX_LOWER_SOCKS: - param_name[0] = 818; //"socks_red"; - param_name[1] = 819; //"socks_green"; - param_name[2] = 820; //"socks_blue"; - break; - - case TEX_UPPER_JACKET: - case TEX_LOWER_JACKET: - param_name[0] = 834; //"jacket_red"; - param_name[1] = 835; //"jacket_green"; - param_name[2] = 836; //"jacket_blue"; - break; - - case TEX_UPPER_GLOVES: - param_name[0] = 827; //"gloves_red"; - param_name[1] = 829; //"gloves_green"; - param_name[2] = 830; //"gloves_blue"; - break; - - case TEX_UPPER_UNDERSHIRT: - param_name[0] = 821; //"undershirt_red"; - param_name[1] = 822; //"undershirt_green"; - param_name[2] = 823; //"undershirt_blue"; - break; - - case TEX_LOWER_UNDERPANTS: - param_name[0] = 824; //"underpants_red"; - param_name[1] = 825; //"underpants_green"; - param_name[2] = 826; //"underpants_blue"; - break; - - case TEX_SKIRT: - param_name[0] = 921; //"skirt_red"; - param_name[1] = 922; //"skirt_green"; - param_name[2] = 923; //"skirt_blue"; - break; - - case TEX_HEAD_TATTOO: - case TEX_LOWER_TATTOO: - case TEX_UPPER_TATTOO: - param_name[0] = 1071; //"tattoo_red"; - param_name[1] = 1072; //"tattoo_green"; - param_name[2] = 1073; //"tattoo_blue"; - break; - case TEX_HEAD_UNIVERSAL_TATTOO: - case TEX_UPPER_UNIVERSAL_TATTOO: - case TEX_LOWER_UNIVERSAL_TATTOO: - case TEX_SKIRT_TATTOO: - case TEX_HAIR_TATTOO: - case TEX_EYES_TATTOO: - case TEX_LEFT_ARM_TATTOO: - case TEX_LEFT_LEG_TATTOO: - case TEX_AUX1_TATTOO: - case TEX_AUX2_TATTOO: - case TEX_AUX3_TATTOO: - param_name[0] = 1238; //"tattoo_universal_red"; - param_name[1] = 1239; //"tattoo_universal_green"; - param_name[2] = 1240; //"tattoo_universal_blue"; - break; - - default: - llassert(0); - return false; - } - - return true; -} - -void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color) -{ - U32 param_name[3]; - if( teToColorParams( te, param_name ) ) - { - setVisualParamWeight( param_name[0], new_color.mV[VX]); - setVisualParamWeight( param_name[1], new_color.mV[VY]); - setVisualParamWeight( param_name[2], new_color.mV[VZ]); - } -} - -LLColor4 LLAvatarAppearance::getClothesColor( ETextureIndex te ) -{ - LLColor4 color; - U32 param_name[3]; - if( teToColorParams( te, param_name ) ) - { - color.mV[VX] = getVisualParamWeight( param_name[0] ); - color.mV[VY] = getVisualParamWeight( param_name[1] ); - color.mV[VZ] = getVisualParamWeight( param_name[2] ); - } - return color; -} - -// static -LLColor4 LLAvatarAppearance::getDummyColor() -{ - return DUMMY_COLOR; -} - -LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) const -{ - if (color_name=="skin_color" && mTexSkinColor) - { - return mTexSkinColor->getColor(); - } - else if(color_name=="hair_color" && mTexHairColor) - { - return mTexHairColor->getColor(); - } - if(color_name=="eye_color" && mTexEyeColor) - { - return mTexEyeColor->getColor(); - } - else - { -// return LLColor4( .5f, .5f, .5f, .5f ); - return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color - } -} - -// Unlike most wearable functions, this works for both self and other. -// virtual -bool LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const -{ - return mWearableData->getWearableCount(type) > 0; -} - -LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_index) const -{ - /* switch(index) - case TEX_HEAD_BAKED: - case TEX_HEAD_BODYPAINT: - return mHeadLayerSet; */ - return mBakedTextureDatas[baked_index].mTexLayerSet; -} - -//----------------------------------------------------------------------------- -// allocateCollisionVolumes() -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::allocateCollisionVolumes( U32 num ) -{ - if (mNumCollisionVolumes !=num) - { - delete_and_clear_array(mCollisionVolumes); - mNumCollisionVolumes = 0; - - mCollisionVolumes = new LLAvatarJointCollisionVolume[num]; - if (!mCollisionVolumes) - { - LL_WARNS() << "Failed to allocate collision volumes" << LL_ENDL; - return false; - } - - mNumCollisionVolumes = num; - } - return true; -} - -//----------------------------------------------------------------------------- -// LLAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ - if (node->hasName("bone")) - { - mIsJoint = true; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - LL_WARNS() << "Bone without name" << LL_ENDL; - return false; - } - - static LLStdStringHandle aliases_string = LLXmlTree::addAttributeString("aliases"); - node->getFastAttributeString(aliases_string, mAliases ); //Aliases are not required. - } - else if (node->hasName("collision_volume")) - { - mIsJoint = false; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - mName = "Collision Volume"; - } - } - else - { - LL_WARNS() << "Invalid node " << node->getName() << LL_ENDL; - return false; - } - - static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); - if (!node->getFastAttributeVector3(pos_string, mPos)) - { - LL_WARNS() << "Bone without position" << LL_ENDL; - return false; - } - - static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); - if (!node->getFastAttributeVector3(rot_string, mRot)) - { - LL_WARNS() << "Bone without rotation" << LL_ENDL; - return false; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!node->getFastAttributeVector3(scale_string, mScale)) - { - LL_WARNS() << "Bone without scale" << LL_ENDL; - return false; - } - - static LLStdStringHandle end_string = LLXmlTree::addAttributeString("end"); - if (!node->getFastAttributeVector3(end_string, mEnd)) - { - LL_WARNS() << "Bone without end " << mName << LL_ENDL; - mEnd = LLVector3(0.0f, 0.0f, 0.0f); - } - - static LLStdStringHandle support_string = LLXmlTree::addAttributeString("support"); - if (!node->getFastAttributeString(support_string,mSupport)) - { - LL_WARNS() << "Bone without support " << mName << LL_ENDL; - mSupport = "base"; - } - - if (mIsJoint) - { - static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); - if (!node->getFastAttributeVector3(pivot_string, mPivot)) - { - LL_WARNS() << "Bone without pivot" << LL_ENDL; - return false; - } - } - - // parse children - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLAvatarBoneInfo *child_info = new LLAvatarBoneInfo; - if (!child_info->parseXml(child)) - { - delete child_info; - return false; - } - mChildren.push_back(child_info); - } - return true; -} - -//----------------------------------------------------------------------------- -// LLAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ - static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); - if (!node->getFastAttributeS32(num_bones_string, mNumBones)) - { - LL_WARNS() << "Couldn't find number of bones." << LL_ENDL; - return false; - } - - static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); - node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - - LLXmlTreeNode* child; - for( child = node->getFirstChild(); child; child = node->getNextChild() ) - { - LLAvatarBoneInfo *info = new LLAvatarBoneInfo; - if (!info->parseXml(child)) - { - delete info; - LL_WARNS() << "Error parsing bone in skeleton file" << LL_ENDL; - return false; - } - mBoneInfoList.push_back(info); - } - return true; -} - -//Make aliases for joint and push to map. -void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info) -{ - if (! bone_info->mIsJoint ) - { - return; - } - - std::string bone_name = bone_info->mName; - mJointAliasMap[bone_name] = bone_name; //Actual name is a valid alias. - - std::string aliases = bone_info->mAliases; - - boost::char_separator sep(" "); - boost::tokenizer > tok(aliases, sep); - for(const std::string& i : tok) - { - if ( mJointAliasMap.find(i) != mJointAliasMap.end() ) - { - LL_WARNS() << "avatar skeleton: Joint alias \"" << i << "\" remapped from " << mJointAliasMap[i] << " to " << bone_name << LL_ENDL; - } - mJointAliasMap[i] = bone_name; - } - - for (LLAvatarBoneInfo* bone : bone_info->mChildren) - { - makeJointAliases(bone); - } -} - -const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases () -{ - LLAvatarAppearance::joint_alias_map_t alias_map; - if (mJointAliasMap.empty()) - { - - for (LLAvatarBoneInfo* bone_info : sAvatarSkeletonInfo->mBoneInfoList) - { - //LLAvatarBoneInfo *bone_info = *iter; - makeJointAliases(bone_info); - } - - for (LLAvatarXmlInfo::LLAvatarAttachmentInfo* info : sAvatarXmlInfo->mAttachmentInfoList) - { - std::string bone_name = info->mName; - - // Also accept the name with spaces substituted with - // underscores. This gives a mechanism for referencing such joints - // in daes, which don't allow spaces. - std::string sub_space_to_underscore = bone_name; - LLStringUtil::replaceChar(sub_space_to_underscore, ' ', '_'); - if (sub_space_to_underscore != bone_name) - { - mJointAliasMap[sub_space_to_underscore] = bone_name; - } - } - } - - return mJointAliasMap; -} - - -//----------------------------------------------------------------------------- -// parseXmlSkeletonNode(): parses nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) -{ - LLXmlTreeNode* node = root->getChildByName( "skeleton" ); - if( !node ) - { - LL_WARNS() << "avatar file: missing " << LL_ENDL; - return false; - } - - LLXmlTreeNode* child; - - // SKELETON DISTORTIONS - for (child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if (!child->getChildByName("param_skeleton")) - { - if (child->getChildByName("param_morph")) - { - LL_WARNS() << "Can't specify morph param in skeleton definition." << LL_ENDL; - } - else - { - LL_WARNS() << "Unknown param type." << LL_ENDL; - } - return false; - } - - LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; - if (!info->parseXml(child)) - { - delete info; - return false; - } - - mSkeletalDistortionInfoList.push_back(info); - } - - // ATTACHMENT POINTS - for (child = node->getChildByName( "attachment_point" ); - child; - child = node->getNextNamedChild()) - { - LLAvatarAttachmentInfo* info = new LLAvatarAttachmentInfo(); - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!child->getFastAttributeString(name_string, info->mName)) - { - LL_WARNS() << "No name supplied for attachment point." << LL_ENDL; - delete info; - return false; - } - - static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); - if (!child->getFastAttributeString(joint_string, info->mJointName)) - { - LL_WARNS() << "No bone declared in attachment point " << info->mName << LL_ENDL; - delete info; - return false; - } - - static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); - if (child->getFastAttributeVector3(position_string, info->mPosition)) - { - info->mHasPosition = true; - } - - static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); - if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) - { - info->mHasRotation = true; - } - static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); - if (child->getFastAttributeS32(group_string, info->mGroup)) - { - if (info->mGroup == -1) - info->mGroup = -1111; // -1 = none parsed, < -1 = bad value - } - - static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); - if (!child->getFastAttributeS32(id_string, info->mAttachmentID)) - { - LL_WARNS() << "No id supplied for attachment point " << info->mName << LL_ENDL; - delete info; - return false; - } - - static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); - child->getFastAttributeS32(slot_string, info->mPieMenuSlice); - - static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person"); - child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson); - - static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud"); - child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment); - - mAttachmentInfoList.push_back(info); - } - - return true; -} - -//----------------------------------------------------------------------------- -// parseXmlMeshNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) -{ - for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); - node; - node = root->getNextNamedChild()) - { - LLAvatarMeshInfo *info = new LLAvatarMeshInfo; - - // attribute: type - static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type"); - if( !node->getFastAttributeString( type_string, info->mType ) ) - { - LL_WARNS() << "Avatar file: is missing type attribute. Ignoring element. " << LL_ENDL; - delete info; - return false; // Ignore this element - } - - static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); - if (!node->getFastAttributeS32( lod_string, info->mLOD )) - { - LL_WARNS() << "Avatar file: is missing lod attribute. Ignoring element. " << LL_ENDL; - delete info; - return false; // Ignore this element - } - - static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); - if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) ) - { - LL_WARNS() << "Avatar file: is missing file_name attribute. Ignoring: " << info->mType << LL_ENDL; - delete info; - return false; // Ignore this element - } - - static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); - node->getFastAttributeString( reference_string, info->mReferenceMeshName ); - - // attribute: min_pixel_area - static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area"); - static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width"); - if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea )) - { - F32 min_pixel_area = 0.1f; - if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area )) - { - // this is square root of pixel area (sensible to use linear space in defining lods) - min_pixel_area = min_pixel_area * min_pixel_area; - } - info->mMinPixelArea = min_pixel_area; - } - - // Parse visual params for this node only if we haven't already - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if (!child->getChildByName("param_morph")) - { - if (child->getChildByName("param_skeleton")) - { - LL_WARNS() << "Can't specify skeleton param in a mesh definition." << LL_ENDL; - } - else - { - LL_WARNS() << "Unknown param type." << LL_ENDL; - } - return false; - } - - LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); - if (!morphinfo->parseXml(child)) - { - delete morphinfo; - delete info; - return false; - } - bool shared = false; - static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); - child->getFastAttributeBOOL(shared_string, shared); - - info->mPolyMorphTargetInfoList.push_back(LLAvatarMeshInfo::morph_info_pair_t(morphinfo, shared)); - } - - mMeshInfoList.push_back(info); - } - return true; -} - -//----------------------------------------------------------------------------- -// parseXmlColorNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) -{ - for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); - color_node; - color_node = root->getNextNamedChild()) - { - std::string global_color_name; - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (color_node->getFastAttributeString( name_string, global_color_name ) ) - { - if( global_color_name == "skin_color" ) - { - if (mTexSkinColorInfo) - { - LL_WARNS() << "avatar file: multiple instances of skin_color" << LL_ENDL; - return false; - } - mTexSkinColorInfo = new LLTexGlobalColorInfo; - if( !mTexSkinColorInfo->parseXml( color_node ) ) - { - delete_and_clear(mTexSkinColorInfo); - LL_WARNS() << "avatar file: mTexSkinColor->parseXml() failed" << LL_ENDL; - return false; - } - } - else if( global_color_name == "hair_color" ) - { - if (mTexHairColorInfo) - { - LL_WARNS() << "avatar file: multiple instances of hair_color" << LL_ENDL; - return false; - } - mTexHairColorInfo = new LLTexGlobalColorInfo; - if( !mTexHairColorInfo->parseXml( color_node ) ) - { - delete_and_clear(mTexHairColorInfo); - LL_WARNS() << "avatar file: mTexHairColor->parseXml() failed" << LL_ENDL; - return false; - } - } - else if( global_color_name == "eye_color" ) - { - if (mTexEyeColorInfo) - { - LL_WARNS() << "avatar file: multiple instances of eye_color" << LL_ENDL; - return false; - } - mTexEyeColorInfo = new LLTexGlobalColorInfo; - if( !mTexEyeColorInfo->parseXml( color_node ) ) - { - LL_WARNS() << "avatar file: mTexEyeColor->parseXml() failed" << LL_ENDL; - return false; - } - } - } - } - return true; -} - -//----------------------------------------------------------------------------- -// parseXmlLayerNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) -{ - for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); - layer_node; - layer_node = root->getNextNamedChild()) - { - LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo(); - if( layer_info->parseXml( layer_node ) ) - { - mLayerInfoList.push_back(layer_info); - } - else - { - delete layer_info; - LL_WARNS() << "avatar file: layer_set->parseXml() failed" << LL_ENDL; - return false; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// parseXmlDriverNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) -{ - LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); - if( driver ) - { - for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" ); - grand_child; - grand_child = driver->getNextNamedChild()) - { - if( grand_child->getChildByName( "param_driver" ) ) - { - LLDriverParamInfo* driver_info = new LLDriverParamInfo(); - if( driver_info->parseXml( grand_child ) ) - { - mDriverInfoList.push_back(driver_info); - } - else - { - delete driver_info; - LL_WARNS() << "avatar file: driver_param->parseXml() failed" << LL_ENDL; - return false; - } - } - } - } - return true; -} - -//----------------------------------------------------------------------------- -// parseXmlDriverNodes(): parses nodes from XML tree -//----------------------------------------------------------------------------- -bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) -{ - LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); - if( !masks ) - { - return false; - } - - for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); - grand_child; - grand_child = masks->getNextNamedChild()) - { - LLAvatarMorphInfo* info = new LLAvatarMorphInfo(); - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); - if (!grand_child->getFastAttributeString(name_string, info->mName)) - { - LL_WARNS() << "No name supplied for morph mask." << LL_ENDL; - delete info; - return false; - } - - static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); - if (!grand_child->getFastAttributeString(region_string, info->mRegion)) - { - LL_WARNS() << "No region supplied for morph mask." << LL_ENDL; - delete info; - return false; - } - - static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); - if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) - { - LL_WARNS() << "No layer supplied for morph mask." << LL_ENDL; - delete info; - return false; - } - - // optional parameter. don't throw a warning if not present. - static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); - grand_child->getFastAttributeBOOL(invert_string, info->mInvert); - - mMorphMaskInfoList.push_back(info); - } - - return true; -} - -//virtual -LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, bool invert, std::string layer) : - mMorphTarget(morph_target), - mInvert(invert), - mLayer(layer) -{ - LLPolyMorphTarget *target = dynamic_cast(morph_target); - if (target) - { - target->addPendingMorphMask(); - } -} +/** + * @File llavatarappearance.cpp + * @brief Implementation of LLAvatarAppearance class + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "llavatarjointmesh.h" +#include "llstl.h" +#include "lldir.h" +#include "llpolymorph.h" +#include "llpolymesh.h" +#include "llpolyskeletaldistortion.h" +#include "llstl.h" +#include "lltexglobalcolor.h" +#include "llwearabledata.h" +#include "boost/bind.hpp" +#include "boost/tokenizer.hpp" + +using namespace LLAvatarAppearanceDefines; + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +const std::string AVATAR_DEFAULT_CHAR = "avatar"; +const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); + +/********************************************************************************* + ** ** + ** Begin private LLAvatarAppearance Support classes + ** + **/ + +//------------------------------------------------------------------------ +// LLAvatarBoneInfo +// Trans/Scale/Rot etc. info about each avatar bone. Used by LLVOAvatarSkeleton. +//------------------------------------------------------------------------ +class LLAvatarBoneInfo +{ + friend class LLAvatarAppearance; + friend class LLAvatarSkeletonInfo; +public: + LLAvatarBoneInfo() : mIsJoint(false) {} + ~LLAvatarBoneInfo() + { + std::for_each(mChildren.begin(), mChildren.end(), DeletePointer()); + mChildren.clear(); + } + bool parseXml(LLXmlTreeNode* node); + +private: + std::string mName; + std::string mSupport; + std::string mAliases; + bool mIsJoint; + LLVector3 mPos; + LLVector3 mEnd; + LLVector3 mRot; + LLVector3 mScale; + LLVector3 mPivot; + typedef std::vector bones_t; + bones_t mChildren; +}; + +//------------------------------------------------------------------------ +// LLAvatarSkeletonInfo +// Overall avatar skeleton +//------------------------------------------------------------------------ +class LLAvatarSkeletonInfo +{ + friend class LLAvatarAppearance; +public: + LLAvatarSkeletonInfo() : + mNumBones(0), mNumCollisionVolumes(0) {} + ~LLAvatarSkeletonInfo() + { + std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); + mBoneInfoList.clear(); + } + bool parseXml(LLXmlTreeNode* node); + S32 getNumBones() const { return mNumBones; } + S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } + +private: + S32 mNumBones; + S32 mNumCollisionVolumes; + LLAvatarAppearance::joint_alias_map_t mJointAliasMap; + typedef std::vector bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + +//----------------------------------------------------------------------------- +// LLAvatarXmlInfo +//----------------------------------------------------------------------------- + +LLAvatarAppearance::LLAvatarXmlInfo::LLAvatarXmlInfo() + : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) +{ +} + +LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo() +{ + std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); + mMeshInfoList.clear(); + + std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); + mSkeletalDistortionInfoList.clear(); + + std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer()); + mAttachmentInfoList.clear(); + + delete_and_clear(mTexSkinColorInfo); + delete_and_clear(mTexHairColorInfo); + delete_and_clear(mTexEyeColorInfo); + + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + mLayerInfoList.clear(); + + std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer()); + mDriverInfoList.clear(); + + std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer()); + mMorphMaskInfoList.clear(); +} + + +/** + ** + ** End LLAvatarAppearance Support classes + ** ** + *********************************************************************************/ + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL; +LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL; +LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* LLAvatarAppearance::sAvatarDictionary = NULL; + + +LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : + LLCharacter(), + mIsDummy(false), + mTexSkinColor( NULL ), + mTexHairColor( NULL ), + mTexEyeColor( NULL ), + mPelvisToFoot(0.f), + mHeadOffset(), + mRoot(NULL), + mWearableData(wearable_data), + mNumBones(0), + mNumCollisionVolumes(0), + mCollisionVolumes(NULL), + mIsBuilt(false), + mInitFlags(0) +{ + llassert_always(mWearableData); + mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) + { + mBakedTextureDatas[i].mLastTextureID = IMG_DEFAULT_AVATAR; + mBakedTextureDatas[i].mTexLayerSet = NULL; + mBakedTextureDatas[i].mIsLoaded = false; + mBakedTextureDatas[i].mIsUsed = false; + mBakedTextureDatas[i].mMaskTexName = 0; + mBakedTextureDatas[i].mTextureIndex = sAvatarDictionary->bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i); + } +} + +// virtual +void LLAvatarAppearance::initInstance() +{ + //------------------------------------------------------------------------- + // initialize joint, mesh and shape members + //------------------------------------------------------------------------- + mRoot = createAvatarJoint(); + mRoot->setName( "mRoot" ); + + for (const LLAvatarAppearanceDictionary::MeshEntries::value_type& mesh_pair : sAvatarDictionary->getMeshEntries()) + { + const EMeshIndex mesh_index = mesh_pair.first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_pair.second; + LLAvatarJoint* joint = createAvatarJoint(); + 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++) + { + LLAvatarJointMesh* mesh = createAvatarJointMesh(); + std::string mesh_name = "m" + mesh_dict->mName + std::to_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); + mesh->setIsTransparent(false); + switch((S32)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 (const LLAvatarAppearanceDictionary::MeshEntries::value_type& mesh_pair : sAvatarDictionary->getMeshEntries()) + { + const EMeshIndex mesh_index = mesh_pair.first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_pair.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 (LLAvatarJointMesh* mesh : mMeshLOD[mesh_index]->mMeshParts) + { + mBakedTextureDatas[(S32)baked_texture_index].mJointMeshes.push_back(mesh); + } + } + + buildCharacter(); + + mInitFlags |= 1<<0; + +} + +// virtual +LLAvatarAppearance::~LLAvatarAppearance() +{ + delete_and_clear(mTexSkinColor); + delete_and_clear(mTexHairColor); + delete_and_clear(mTexEyeColor); + + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) + { + delete_and_clear(mBakedTextureDatas[i].mTexLayerSet); + mBakedTextureDatas[i].mJointMeshes.clear(); + + for (LLMaskedMorph* masked_morph : mBakedTextureDatas[i].mMaskedMorphs) + { + delete masked_morph; + } + } + + if (mRoot) + { + mRoot->removeAllChildren(); + delete mRoot; + mRoot = nullptr; + } + mJointMap.clear(); + + clearSkeleton(); + delete_and_clear_array(mCollisionVolumes); + + std::for_each(mPolyMeshes.begin(), mPolyMeshes.end(), DeletePairedPointer()); + mPolyMeshes.clear(); + + for (LLAvatarJoint* joint : mMeshLOD) + { + std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); + joint->mMeshParts.clear(); + } + std::for_each(mMeshLOD.begin(), mMeshLOD.end(), DeletePointer()); + mMeshLOD.clear(); +} + +//static +void LLAvatarAppearance::initClass() +{ + initClass("",""); +} + +//static +void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, const std::string& skeleton_file_name_arg) +{ + // init dictionary (don't repeat on second login attempt) + if (!sAvatarDictionary) + { + sAvatarDictionary = new LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary(); + } + + std::string avatar_file_name; + + if (!avatar_file_name_arg.empty()) + { + avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,avatar_file_name_arg); + } + else + { + avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml"); + } + LLXmlTree xml_tree; + bool success = xml_tree.parseFile( avatar_file_name, false ); + if (!success) + { + LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL; + } + + // now sanity check xml file + LLXmlTreeNode* root = xml_tree.getRoot(); + if (!root) + { + LL_ERRS() << "No root node found in avatar configuration file: " << avatar_file_name << LL_ENDL; + return; + } + + //------------------------------------------------------------------------- + // (root) + //------------------------------------------------------------------------- + if( !root->hasName( "linden_avatar" ) ) + { + LL_ERRS() << "Invalid avatar file header: " << avatar_file_name << LL_ENDL; + } + + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) + { + LL_ERRS() << "Invalid avatar file version: " << version << " in file: " << avatar_file_name << LL_ENDL; + } + + S32 wearable_def_version = 1; + static LLStdStringHandle wearable_definition_version_string = LLXmlTree::addAttributeString("wearable_definition_version"); + root->getFastAttributeS32( wearable_definition_version_string, wearable_def_version ); + LLWearable::setCurrentDefinitionVersion( wearable_def_version ); + + std::string mesh_file_name; + + LLXmlTreeNode* skeleton_node = root->getChildByName( "skeleton" ); + if (!skeleton_node) + { + LL_ERRS() << "No skeleton in avatar configuration file: " << avatar_file_name << LL_ENDL; + return; + } + + std::string skeleton_file_name = skeleton_file_name_arg; + if (skeleton_file_name.empty()) + { + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if (!skeleton_node->getFastAttributeString(file_name_string, skeleton_file_name)) + { + LL_ERRS() << "No file name in skeleton node in avatar config file: " << avatar_file_name << LL_ENDL; + } + } + + std::string skeleton_path; + LLXmlTree skeleton_xml_tree; + skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name); + if (!parseSkeletonFile(skeleton_path, skeleton_xml_tree)) + { + LL_ERRS() << "Error parsing skeleton file: " << skeleton_path << LL_ENDL; + } + + // Process XML data + + // avatar_skeleton.xml + if (sAvatarSkeletonInfo) + { //this can happen if a login attempt failed + delete sAvatarSkeletonInfo; + } + sAvatarSkeletonInfo = new LLAvatarSkeletonInfo; + if (!sAvatarSkeletonInfo->parseXml(skeleton_xml_tree.getRoot())) + { + LL_ERRS() << "Error parsing skeleton XML file: " << skeleton_path << LL_ENDL; + } + // parse avatar_lad.xml + if (sAvatarXmlInfo) + { //this can happen if a login attempt failed + delete_and_clear(sAvatarXmlInfo); + } + sAvatarXmlInfo = new LLAvatarXmlInfo; + if (!sAvatarXmlInfo->parseXmlSkeletonNode(root)) + { + LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; + } + if (!sAvatarXmlInfo->parseXmlMeshNodes(root)) + { + LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; + } + if (!sAvatarXmlInfo->parseXmlColorNodes(root)) + { + LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; + } + if (!sAvatarXmlInfo->parseXmlLayerNodes(root)) + { + LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; + } + if (!sAvatarXmlInfo->parseXmlDriverNodes(root)) + { + LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; + } + if (!sAvatarXmlInfo->parseXmlMorphNodes(root)) + { + LL_ERRS() << "Error parsing skeleton node in avatar XML file: " << skeleton_path << LL_ENDL; + } +} + +void LLAvatarAppearance::cleanupClass() +{ + delete_and_clear(sAvatarXmlInfo); + delete_and_clear(sAvatarDictionary); + delete_and_clear(sAvatarSkeletonInfo); +} + +using namespace LLAvatarAppearanceDefines; + +void LLAvatarAppearance::compareJointStateMaps(joint_state_map_t& last_state, + joint_state_map_t& curr_state) +{ + if (!last_state.empty() && (last_state != curr_state)) + { + S32 diff_count = 0; + for (joint_state_map_t::value_type& pair : last_state) + { + const std::string& key = pair.first; + if (last_state[key] != curr_state[key]) + { + LL_DEBUGS("AvatarBodySize") << "BodySize change " << key << " " << last_state[key] << "->" << curr_state[key] << LL_ENDL; + diff_count++; + } + } + if (diff_count > 0) + { + LL_DEBUGS("AvatarBodySize") << "Total of BodySize changes " << diff_count << LL_ENDL; + } + + } +} + +//------------------------------------------------------------------------ +// The viewer can only suggest a good size for the agent, +// the simulator will keep it inside a reasonable range. +void LLAvatarAppearance::computeBodySize() +{ + mLastBodySizeState = mCurrBodySizeState; + + mCurrBodySizeState["mPelvis scale"] = mPelvisp->getScale(); + mCurrBodySizeState["mSkull pos"] = mSkullp->getPosition(); + mCurrBodySizeState["mSkull scale"] = mSkullp->getScale(); + mCurrBodySizeState["mNeck pos"] = mNeckp->getPosition(); + mCurrBodySizeState["mNeck scale"] = mNeckp->getScale(); + mCurrBodySizeState["mChest pos"] = mChestp->getPosition(); + mCurrBodySizeState["mChest scale"] = mChestp->getScale(); + mCurrBodySizeState["mHead pos"] = mHeadp->getPosition(); + mCurrBodySizeState["mHead scale"] = mHeadp->getScale(); + mCurrBodySizeState["mTorso pos"] = mTorsop->getPosition(); + mCurrBodySizeState["mTorso scale"] = mTorsop->getScale(); + mCurrBodySizeState["mHipLeft pos"] = mHipLeftp->getPosition(); + mCurrBodySizeState["mHipLeft scale"] = mHipLeftp->getScale(); + mCurrBodySizeState["mKneeLeft pos"] = mKneeLeftp->getPosition(); + mCurrBodySizeState["mKneeLeft scale"] = mKneeLeftp->getScale(); + mCurrBodySizeState["mAnkleLeft pos"] = mAnkleLeftp->getPosition(); + mCurrBodySizeState["mAnkleLeft scale"] = mAnkleLeftp->getScale(); + mCurrBodySizeState["mFootLeft pos"] = mFootLeftp->getPosition(); + + F32 old_height = mBodySize.mV[VZ]; + F32 old_offset = mAvatarOffset.mV[VZ]; + + // TODO: Measure the real depth and width + mPelvisToFoot = computePelvisToFoot(); + F32 new_height = computeBodyHeight(); + mBodySize.set(DEFAULT_AGENT_DEPTH, DEFAULT_AGENT_WIDTH, new_height); + F32 new_offset = getVisualParamWeight(AVATAR_HOVER); + mAvatarOffset.set(0, 0, new_offset); + + if (mBodySize.mV[VZ] != old_height || new_offset != old_offset) + { + compareJointStateMaps(mLastBodySizeState, mCurrBodySizeState); + } +} + +F32 LLAvatarAppearance::computeBodyHeight() +{ + F32 result = mPelvisToFoot + + // all these relative positions usually are positive + mPelvisp->getScale().mV[VZ] * mTorsop->getPosition().mV[VZ] + + mTorsop->getScale().mV[VZ] * mChestp->getPosition().mV[VZ] + + mChestp->getScale().mV[VZ] * mNeckp->getPosition().mV[VZ] + + mNeckp->getScale().mV[VZ] * mHeadp->getPosition().mV[VZ] + + mHeadp->getScale().mV[VZ] * mSkullp->getPosition().mV[VZ] * 2; + return result; +} + +F32 LLAvatarAppearance::computePelvisToFoot() +{ + F32 result = + // all these relative positions usually are negative + mPelvisp->getScale().mV[VZ] * mHipLeftp->getPosition().mV[VZ] + + mHipLeftp->getScale().mV[VZ] * mKneeLeftp->getPosition().mV[VZ] + + mKneeLeftp->getScale().mV[VZ] * mAnkleLeftp->getPosition().mV[VZ] + + mAnkleLeftp->getScale().mV[VZ] * mFootLeftp->getPosition().mV[VZ] / 2; + return -result; +} + +//----------------------------------------------------------------------------- +// parseSkeletonFile() +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree) +{ + //------------------------------------------------------------------------- + // parse the file + //------------------------------------------------------------------------- + bool parsesuccess = skeleton_xml_tree.parseFile( filename, false ); + + if (!parsesuccess) + { + LL_ERRS() << "Can't parse skeleton file: " << filename << LL_ENDL; + return false; + } + + // now sanity check xml file + LLXmlTreeNode* root = skeleton_xml_tree.getRoot(); + if (!root) + { + LL_ERRS() << "No root node found in avatar skeleton file: " << filename << LL_ENDL; + return false; + } + + if( !root->hasName( "linden_skeleton" ) ) + { + LL_ERRS() << "Invalid avatar skeleton file header: " << filename << LL_ENDL; + return false; + } + + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if( !root->getFastAttributeString( version_string, version ) || ((version != "1.0") && (version != "2.0"))) + { + LL_ERRS() << "Invalid avatar skeleton file version: " << version << " in file: " << filename << LL_ENDL; + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// setupBone() +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 &volume_num, S32 &joint_num) +{ + LLJoint* joint = NULL; + + LL_DEBUGS("BVH") << "bone info: name " << info->mName + << " isJoint " << info->mIsJoint + << " volume_num " << volume_num + << " joint_num " << joint_num + << LL_ENDL; + + if (info->mIsJoint) + { + joint = getCharacterJoint(joint_num); + if (!joint) + { + LL_WARNS() << "Too many bones" << LL_ENDL; + return false; + } + joint->setName( info->mName ); + } + else // collision volume + { + if (volume_num >= (S32)mNumCollisionVolumes) + { + LL_WARNS() << "Too many collision volumes" << LL_ENDL; + return false; + } + joint = (&mCollisionVolumes[volume_num]); + joint->setName( info->mName ); + } + + // add to parent + if (parent && (joint->getParent()!=parent)) + { + parent->addChild( joint ); + } + + // SL-315 + joint->setPosition(info->mPos); + joint->setDefaultPosition(info->mPos); + joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], + info->mRot.mV[VZ], LLQuaternion::XYZ)); + joint->setScale(info->mScale); + joint->setDefaultScale(info->mScale); + joint->setSupport(info->mSupport); + joint->setEnd(info->mEnd); + + if (info->mIsJoint) + { + joint->setSkinOffset( info->mPivot ); + joint->setJointNum(joint_num); + joint_num++; + } + else // collision volume + { + joint->setJointNum(mNumBones+volume_num); + volume_num++; + } + + + // setup children + for (LLAvatarBoneInfo* child_info : info->mChildren) + { + if (!setupBone(child_info, joint, volume_num, joint_num)) + { + return false; + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// allocateCharacterJoints() +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::allocateCharacterJoints( U32 num ) +{ + if (mSkeleton.size() != num) + { + clearSkeleton(); + mSkeleton = avatar_joint_list_t(num,NULL); + mNumBones = num; + } + + return true; +} + + +//----------------------------------------------------------------------------- +// buildSkeleton() +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::buildSkeleton(const LLAvatarSkeletonInfo *info) +{ + LL_DEBUGS("BVH") << "numBones " << info->mNumBones << " numCollisionVolumes " << info->mNumCollisionVolumes << LL_ENDL; + + // allocate joints + if (!allocateCharacterJoints(info->mNumBones)) + { + LL_ERRS() << "Can't allocate " << info->mNumBones << " joints" << LL_ENDL; + return false; + } + + // allocate volumes + if (info->mNumCollisionVolumes) + { + if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) + { + LL_ERRS() << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << LL_ENDL; + return false; + } + } + + S32 current_joint_num = 0; + S32 current_volume_num = 0; + for (LLAvatarBoneInfo* bone_info : info->mBoneInfoList) + { + if (!setupBone(bone_info, NULL, current_volume_num, current_joint_num)) + { + LL_ERRS() << "Error parsing bone in skeleton file" << LL_ENDL; + return false; + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// clearSkeleton() +//----------------------------------------------------------------------------- +void LLAvatarAppearance::clearSkeleton() +{ + std::for_each(mSkeleton.begin(), mSkeleton.end(), DeletePointer()); + mSkeleton.clear(); +} + +//------------------------------------------------------------------------ +// addPelvisFixup +//------------------------------------------------------------------------ +void LLAvatarAppearance::addPelvisFixup( F32 fixup, const LLUUID& mesh_id ) +{ + LLVector3 pos(0.0,0.0,fixup); + mPelvisFixups.add(mesh_id,pos); +} + +//------------------------------------------------------------------------ +// addPelvisFixup +//------------------------------------------------------------------------ +void LLAvatarAppearance::removePelvisFixup( const LLUUID& mesh_id ) +{ + mPelvisFixups.remove(mesh_id); +} + +//------------------------------------------------------------------------ +// hasPelvisFixup +//------------------------------------------------------------------------ +bool LLAvatarAppearance::hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const +{ + LLVector3 pos; + if (mPelvisFixups.findActiveOverride(mesh_id,pos)) + { + fixup = pos[2]; + return true; + } + return false; +} + +bool LLAvatarAppearance::hasPelvisFixup( F32& fixup ) const +{ + LLUUID mesh_id; + return hasPelvisFixup( fixup, mesh_id ); +} +//----------------------------------------------------------------------------- +// LLAvatarAppearance::buildCharacter() +// Deferred initialization and rebuild of the avatar. +//----------------------------------------------------------------------------- +void LLAvatarAppearance::buildCharacter() +{ + //------------------------------------------------------------------------- + // remove all references to our existing skeleton + // so we can rebuild it + //------------------------------------------------------------------------- + flushAllMotions(); + + //------------------------------------------------------------------------- + // remove all of mRoot's children + //------------------------------------------------------------------------- + mRoot->removeAllChildren(); + mJointMap.clear(); + mIsBuilt = false; + + //------------------------------------------------------------------------- + // clear mesh data + //------------------------------------------------------------------------- + for (LLAvatarJoint* joint : mMeshLOD) + { + for (LLAvatarJointMesh* mesh : joint->mMeshParts) + { + mesh->setMesh(NULL); + } + } + + //------------------------------------------------------------------------- + // (re)load our skeleton and meshes + //------------------------------------------------------------------------- + LLTimer timer; + + bool status = loadAvatar(); + stop_glerror(); + +// gPrintMessagesThisFrame = true; + LL_DEBUGS() << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << LL_ENDL; + + if (!status) + { + if (isSelf()) + { + LL_ERRS() << "Unable to load user's avatar" << LL_ENDL; + } + else + { + LL_WARNS() << "Unable to load other's avatar" << LL_ENDL; + } + return; + } + + //------------------------------------------------------------------------- + // initialize "well known" joint pointers + //------------------------------------------------------------------------- + mPelvisp = mRoot->findJoint("mPelvis"); + mTorsop = mRoot->findJoint("mTorso"); + mChestp = mRoot->findJoint("mChest"); + mNeckp = mRoot->findJoint("mNeck"); + mHeadp = mRoot->findJoint("mHead"); + mSkullp = mRoot->findJoint("mSkull"); + mHipLeftp = mRoot->findJoint("mHipLeft"); + mHipRightp = mRoot->findJoint("mHipRight"); + mKneeLeftp = mRoot->findJoint("mKneeLeft"); + mKneeRightp = mRoot->findJoint("mKneeRight"); + mAnkleLeftp = mRoot->findJoint("mAnkleLeft"); + mAnkleRightp = mRoot->findJoint("mAnkleRight"); + mFootLeftp = mRoot->findJoint("mFootLeft"); + mFootRightp = mRoot->findJoint("mFootRight"); + mWristLeftp = mRoot->findJoint("mWristLeft"); + mWristRightp = mRoot->findJoint("mWristRight"); + mEyeLeftp = mRoot->findJoint("mEyeLeft"); + mEyeRightp = mRoot->findJoint("mEyeRight"); + + //------------------------------------------------------------------------- + // Make sure "well known" pointers exist + //------------------------------------------------------------------------- + if (!(mPelvisp && + mTorsop && + mChestp && + mNeckp && + mHeadp && + mSkullp && + mHipLeftp && + mHipRightp && + mKneeLeftp && + mKneeRightp && + mAnkleLeftp && + mAnkleRightp && + mFootLeftp && + mFootRightp && + mWristLeftp && + mWristRightp && + mEyeLeftp && + mEyeRightp)) + { + LL_ERRS() << "Failed to create avatar." << LL_ENDL; + return; + } + + //------------------------------------------------------------------------- + // initialize the pelvis + //------------------------------------------------------------------------- + // SL-315 + mPelvisp->setPosition( LLVector3(0.0f, 0.0f, 0.0f) ); + + mIsBuilt = true; + stop_glerror(); + +} + +bool LLAvatarAppearance::loadAvatar() +{ +// LL_RECORD_BLOCK_TIME(FTM_LOAD_AVATAR); + + // avatar_skeleton.xml + if( !buildSkeleton(sAvatarSkeletonInfo) ) + { + LL_ERRS() << "avatar file: buildSkeleton() failed" << LL_ENDL; + return false; + } + + // initialize mJointAliasMap + getJointAliases(); + + // avatar_lad.xml : + if( !loadSkeletonNode() ) + { + LL_ERRS() << "avatar file: loadNodeSkeleton() failed" << LL_ENDL; + return false; + } + + // avatar_lad.xml : + if( !loadMeshNodes() ) + { + LL_ERRS() << "avatar file: loadNodeMesh() failed" << LL_ENDL; + return false; + } + + // avatar_lad.xml : + if( sAvatarXmlInfo->mTexSkinColorInfo ) + { + mTexSkinColor = new LLTexGlobalColor( this ); + if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) ) + { + LL_ERRS() << "avatar file: mTexSkinColor->setInfo() failed" << LL_ENDL; + return false; + } + } + else + { + LL_ERRS() << " name=\"skin_color\" not found" << LL_ENDL; + return false; + } + if( sAvatarXmlInfo->mTexHairColorInfo ) + { + mTexHairColor = new LLTexGlobalColor( this ); + if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) ) + { + LL_ERRS() << "avatar file: mTexHairColor->setInfo() failed" << LL_ENDL; + return false; + } + } + else + { + LL_ERRS() << " name=\"hair_color\" not found" << LL_ENDL; + return false; + } + if( sAvatarXmlInfo->mTexEyeColorInfo ) + { + mTexEyeColor = new LLTexGlobalColor( this ); + if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) ) + { + LL_ERRS() << "avatar file: mTexEyeColor->setInfo() failed" << LL_ENDL; + return false; + } + } + else + { + LL_ERRS() << " name=\"eye_color\" not found" << LL_ENDL; + return false; + } + + // avatar_lad.xml : + if (sAvatarXmlInfo->mLayerInfoList.empty()) + { + LL_ERRS() << "avatar file: missing node" << LL_ENDL; + return false; + } + + if (sAvatarXmlInfo->mMorphMaskInfoList.empty()) + { + LL_ERRS() << "avatar file: missing node" << LL_ENDL; + return false; + } + + // avatar_lad.xml : + for (LLAvatarXmlInfo::LLAvatarMorphInfo* info : sAvatarXmlInfo->mMorphMaskInfoList) + { + EBakedTextureIndex baked = sAvatarDictionary->findBakedByRegionName(info->mRegion); + if (baked != BAKED_NUM_INDICES) + { + LLVisualParam* morph_param; + const std::string *name = &info->mName; + morph_param = getVisualParam(name->c_str()); + if (morph_param) + { + bool invert = info->mInvert; + addMaskedMorph(baked, morph_param, invert, info->mLayer); + } + } + + } + + loadLayersets(); + + // avatar_lad.xml : + for (LLDriverParamInfo* info : sAvatarXmlInfo->mDriverInfoList) + { + LLDriverParam* driver_param = new LLDriverParam( this ); + if (driver_param->setInfo(info)) + { + addVisualParam( driver_param ); + driver_param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + LLVisualParam*(LLAvatarAppearance::*avatar_function)(S32)const = &LLAvatarAppearance::getVisualParam; + if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLAvatarAppearance*)this,_1 ), false)) + { + LL_WARNS() << "could not link driven params for avatar " << getID().asString() << " param id: " << driver_param->getID() << LL_ENDL; + continue; + } + } + else + { + delete driver_param; + LL_WARNS() << "avatar file: driver_param->parseData() failed" << LL_ENDL; + return false; + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// loadSkeletonNode(): loads node from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::loadSkeletonNode () +{ + mRoot->addChild( mSkeleton[0] ); + + // make meshes children before calling parent version of the function + for (LLAvatarJoint* joint : mMeshLOD) + { + 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]); + + LLAvatarJoint *skull = (LLAvatarJoint*)mRoot->findJoint("mSkull"); + if (skull) + { + skull->addChild(mMeshLOD[MESH_ID_HAIR] ); + } + + LLAvatarJoint *eyeL = (LLAvatarJoint*)mRoot->findJoint("mEyeLeft"); + if (eyeL) + { + eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] ); + } + + LLAvatarJoint *eyeR = (LLAvatarJoint*)mRoot->findJoint("mEyeRight"); + if (eyeR) + { + eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] ); + } + + // SKELETAL DISTORTIONS + { + for (LLViewerVisualParamInfo* visual_param_info : sAvatarXmlInfo->mSkeletalDistortionInfoList) + { + LLPolySkeletalDistortionInfo *info = (LLPolySkeletalDistortionInfo*)visual_param_info; + LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this); + if (!param->setInfo(info)) + { + delete param; + return false; + } + else + { + addVisualParam(param); + param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + } + } + + + return true; +} + +//----------------------------------------------------------------------------- +// loadMeshNodes(): loads nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::loadMeshNodes() +{ + for (const LLAvatarXmlInfo::LLAvatarMeshInfo* info : sAvatarXmlInfo->mMeshInfoList) + { + const std::string &type = info->mType; + S32 lod = info->mLOD; + + LLAvatarJointMesh* mesh = NULL; + U8 mesh_id = 0; + bool found_mesh_id = false; + + /* if (type == "hairMesh") + switch(lod) + case 0: + mesh = &mHairMesh0; */ + for (const LLAvatarAppearanceDictionary::MeshEntries::value_type& mesh_pair : sAvatarDictionary->getMeshEntries()) + { + const EMeshIndex mesh_index = mesh_pair.first; + const LLAvatarAppearanceDictionary::MeshEntry *mesh_dict = mesh_pair.second; + if (type.compare(mesh_dict->mName) == 0) + { + mesh_id = mesh_index; + found_mesh_id = true; + break; + } + } + + if (found_mesh_id) + { + if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size()) + { + mesh = mMeshLOD[mesh_id]->mMeshParts[lod]; + } + else + { + LL_WARNS() << "Avatar file: has invalid lod setting " << lod << LL_ENDL; + return false; + } + } + else + { + LL_WARNS() << "Ignoring unrecognized mesh type: " << type << LL_ENDL; + return false; + } + + // LL_INFOS() << "Parsing mesh data for " << type << "..." << LL_ENDL; + + // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings. + // Do not touch!!! + mesh->setColor( LLColor4::white ); + + LLPolyMesh *poly_mesh = NULL; + + if (!info->mReferenceMeshName.empty()) + { + polymesh_map_t::const_iterator polymesh_iter = mPolyMeshes.find(info->mReferenceMeshName); + if (polymesh_iter != mPolyMeshes.end()) + { + 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; + return false; + } + } + else + { + poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName); + poly_mesh->setAvatar(this); + } + + if( !poly_mesh ) + { + LL_WARNS() << "Failed to load mesh of type " << type << LL_ENDL; + return false; + } + + // Multimap insert + mPolyMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh)); + + mesh->setMesh( poly_mesh ); + mesh->setLOD( info->mMinPixelArea ); + + for (const LLAvatarXmlInfo::LLAvatarMeshInfo::morph_info_pair_t& info_pair : info->mPolyMorphTargetInfoList) + { + LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh()); + if (!param->setInfo((LLPolyMorphTargetInfo*)info_pair.first)) + { + delete param; + return false; + } + else + { + if (info_pair.second) + { + addSharedVisualParam(param); + param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + else + { + addVisualParam(param); + param->setParamLocation(isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + } + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// loadLayerSets() +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::loadLayersets() +{ + bool success = true; + for (LLTexLayerSetInfo* layerset_info : sAvatarXmlInfo->mLayerInfoList) + { + if (isSelf()) + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + LLTexLayerSet* layer_set = createTexLayerSet(); + + if (!layer_set->setInfo(layerset_info)) + { + stop_glerror(); + delete layer_set; + LL_WARNS() << "avatar file: layer_set->setInfo() failed" << LL_ENDL; + return false; + } + + // scan baked textures and associate the layerset with the appropriate one + EBakedTextureIndex baked_index = BAKED_NUM_INDICES; + for (const LLAvatarAppearanceDictionary::BakedTextures::value_type& baked_pair : sAvatarDictionary->getBakedTextures()) + { + const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_pair.second; + if (layer_set->isBodyRegion(baked_dict->mName)) + { + baked_index = baked_pair.first; + // ensure both structures are aware of each other + mBakedTextureDatas[baked_index].mTexLayerSet = layer_set; + layer_set->setBakedTexIndex(baked_index); + break; + } + } + // if no baked texture was found, warn and cleanup + if (baked_index == BAKED_NUM_INDICES) + { + LL_WARNS() << " has invalid body_region attribute" << LL_ENDL; + delete layer_set; + return false; + } + + // scan morph masks and let any affected layers know they have an associated morph + for (LLMaskedMorph* morph : mBakedTextureDatas[baked_index].mMaskedMorphs) + { + LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer); + if (layer) + { + layer->setHasMorph(true); + } + else + { + LL_WARNS() << "Could not find layer named " << morph->mLayer << " to set morph flag" << LL_ENDL; + success = false; + } + } + } + else // !isSelf() + { + // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such. + layerset_info->createVisualParams(this); + } + } + return success; +} + +//----------------------------------------------------------------------------- +// getCharacterJoint() +//----------------------------------------------------------------------------- +LLJoint *LLAvatarAppearance::getCharacterJoint( U32 num ) +{ + if ((S32)num >= mSkeleton.size() + || (S32)num < 0) + { + return NULL; + } + if (!mSkeleton[num]) + { + mSkeleton[num] = createAvatarJoint(); + } + return mSkeleton[num]; +} + + +//----------------------------------------------------------------------------- +// getVolumePos() +//----------------------------------------------------------------------------- +LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_offset) +{ + if (joint_index > mNumCollisionVolumes) + { + return LLVector3::zero; + } + + return mCollisionVolumes[joint_index].getVolumePos(volume_offset); +} + +//----------------------------------------------------------------------------- +// findCollisionVolume() +//----------------------------------------------------------------------------- +LLJoint* LLAvatarAppearance::findCollisionVolume(S32 volume_id) +{ + if ((volume_id < 0) || (volume_id >= mNumCollisionVolumes)) + { + return NULL; + } + + return &mCollisionVolumes[volume_id]; +} + +//----------------------------------------------------------------------------- +// findCollisionVolume() +//----------------------------------------------------------------------------- +S32 LLAvatarAppearance::getCollisionVolumeID(std::string &name) +{ + for (S32 i = 0; i < mNumCollisionVolumes; i++) + { + if (mCollisionVolumes[i].getName() == name) + { + return i; + } + } + + return -1; +} + +//----------------------------------------------------------------------------- +// LLAvatarAppearance::getHeadMesh() +//----------------------------------------------------------------------------- +LLPolyMesh* LLAvatarAppearance::getHeadMesh() +{ + return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh(); +} + + +//----------------------------------------------------------------------------- +// LLAvatarAppearance::getUpperBodyMesh() +//----------------------------------------------------------------------------- +LLPolyMesh* LLAvatarAppearance::getUpperBodyMesh() +{ + return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh(); +} + + + +// virtual +bool LLAvatarAppearance::isValid() const +{ + // This should only be called on ourself. + if (!isSelf()) + { + LL_ERRS() << "Called LLAvatarAppearance::isValid() on when isSelf() == false" << LL_ENDL; + } + return true; +} + + +// adds a morph mask to the appropriate baked texture structure +void LLAvatarAppearance::addMaskedMorph(EBakedTextureIndex index, LLVisualParam* morph_target, bool invert, std::string layer) +{ + if (index < BAKED_NUM_INDICES) + { + LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer); + mBakedTextureDatas[index].mMaskedMorphs.push_front(morph); + } +} + + +//static +bool LLAvatarAppearance::teToColorParams( ETextureIndex te, U32 *param_name ) +{ + switch( te ) + { + case TEX_UPPER_SHIRT: + param_name[0] = 803; //"shirt_red"; + param_name[1] = 804; //"shirt_green"; + param_name[2] = 805; //"shirt_blue"; + break; + + case TEX_LOWER_PANTS: + param_name[0] = 806; //"pants_red"; + param_name[1] = 807; //"pants_green"; + param_name[2] = 808; //"pants_blue"; + break; + + case TEX_LOWER_SHOES: + param_name[0] = 812; //"shoes_red"; + param_name[1] = 813; //"shoes_green"; + param_name[2] = 817; //"shoes_blue"; + break; + + case TEX_LOWER_SOCKS: + param_name[0] = 818; //"socks_red"; + param_name[1] = 819; //"socks_green"; + param_name[2] = 820; //"socks_blue"; + break; + + case TEX_UPPER_JACKET: + case TEX_LOWER_JACKET: + param_name[0] = 834; //"jacket_red"; + param_name[1] = 835; //"jacket_green"; + param_name[2] = 836; //"jacket_blue"; + break; + + case TEX_UPPER_GLOVES: + param_name[0] = 827; //"gloves_red"; + param_name[1] = 829; //"gloves_green"; + param_name[2] = 830; //"gloves_blue"; + break; + + case TEX_UPPER_UNDERSHIRT: + param_name[0] = 821; //"undershirt_red"; + param_name[1] = 822; //"undershirt_green"; + param_name[2] = 823; //"undershirt_blue"; + break; + + case TEX_LOWER_UNDERPANTS: + param_name[0] = 824; //"underpants_red"; + param_name[1] = 825; //"underpants_green"; + param_name[2] = 826; //"underpants_blue"; + break; + + case TEX_SKIRT: + param_name[0] = 921; //"skirt_red"; + param_name[1] = 922; //"skirt_green"; + param_name[2] = 923; //"skirt_blue"; + break; + + case TEX_HEAD_TATTOO: + case TEX_LOWER_TATTOO: + case TEX_UPPER_TATTOO: + param_name[0] = 1071; //"tattoo_red"; + param_name[1] = 1072; //"tattoo_green"; + param_name[2] = 1073; //"tattoo_blue"; + break; + case TEX_HEAD_UNIVERSAL_TATTOO: + case TEX_UPPER_UNIVERSAL_TATTOO: + case TEX_LOWER_UNIVERSAL_TATTOO: + case TEX_SKIRT_TATTOO: + case TEX_HAIR_TATTOO: + case TEX_EYES_TATTOO: + case TEX_LEFT_ARM_TATTOO: + case TEX_LEFT_LEG_TATTOO: + case TEX_AUX1_TATTOO: + case TEX_AUX2_TATTOO: + case TEX_AUX3_TATTOO: + param_name[0] = 1238; //"tattoo_universal_red"; + param_name[1] = 1239; //"tattoo_universal_green"; + param_name[2] = 1240; //"tattoo_universal_blue"; + break; + + default: + llassert(0); + return false; + } + + return true; +} + +void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_color) +{ + U32 param_name[3]; + if( teToColorParams( te, param_name ) ) + { + setVisualParamWeight( param_name[0], new_color.mV[VX]); + setVisualParamWeight( param_name[1], new_color.mV[VY]); + setVisualParamWeight( param_name[2], new_color.mV[VZ]); + } +} + +LLColor4 LLAvatarAppearance::getClothesColor( ETextureIndex te ) +{ + LLColor4 color; + U32 param_name[3]; + if( teToColorParams( te, param_name ) ) + { + color.mV[VX] = getVisualParamWeight( param_name[0] ); + color.mV[VY] = getVisualParamWeight( param_name[1] ); + color.mV[VZ] = getVisualParamWeight( param_name[2] ); + } + return color; +} + +// static +LLColor4 LLAvatarAppearance::getDummyColor() +{ + return DUMMY_COLOR; +} + +LLColor4 LLAvatarAppearance::getGlobalColor( const std::string& color_name ) const +{ + if (color_name=="skin_color" && mTexSkinColor) + { + return mTexSkinColor->getColor(); + } + else if(color_name=="hair_color" && mTexHairColor) + { + return mTexHairColor->getColor(); + } + if(color_name=="eye_color" && mTexEyeColor) + { + return mTexEyeColor->getColor(); + } + else + { +// return LLColor4( .5f, .5f, .5f, .5f ); + return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color + } +} + +// Unlike most wearable functions, this works for both self and other. +// virtual +bool LLAvatarAppearance::isWearingWearableType(LLWearableType::EType type) const +{ + return mWearableData->getWearableCount(type) > 0; +} + +LLTexLayerSet* LLAvatarAppearance::getAvatarLayerSet(EBakedTextureIndex baked_index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + return mBakedTextureDatas[baked_index].mTexLayerSet; +} + +//----------------------------------------------------------------------------- +// allocateCollisionVolumes() +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::allocateCollisionVolumes( U32 num ) +{ + if (mNumCollisionVolumes !=num) + { + delete_and_clear_array(mCollisionVolumes); + mNumCollisionVolumes = 0; + + mCollisionVolumes = new LLAvatarJointCollisionVolume[num]; + if (!mCollisionVolumes) + { + LL_WARNS() << "Failed to allocate collision volumes" << LL_ENDL; + return false; + } + + mNumCollisionVolumes = num; + } + return true; +} + +//----------------------------------------------------------------------------- +// LLAvatarBoneInfo::parseXml() +//----------------------------------------------------------------------------- +bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +{ + if (node->hasName("bone")) + { + mIsJoint = true; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + LL_WARNS() << "Bone without name" << LL_ENDL; + return false; + } + + static LLStdStringHandle aliases_string = LLXmlTree::addAttributeString("aliases"); + node->getFastAttributeString(aliases_string, mAliases ); //Aliases are not required. + } + else if (node->hasName("collision_volume")) + { + mIsJoint = false; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + mName = "Collision Volume"; + } + } + else + { + LL_WARNS() << "Invalid node " << node->getName() << LL_ENDL; + return false; + } + + static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); + if (!node->getFastAttributeVector3(pos_string, mPos)) + { + LL_WARNS() << "Bone without position" << LL_ENDL; + return false; + } + + static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); + if (!node->getFastAttributeVector3(rot_string, mRot)) + { + LL_WARNS() << "Bone without rotation" << LL_ENDL; + return false; + } + + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + if (!node->getFastAttributeVector3(scale_string, mScale)) + { + LL_WARNS() << "Bone without scale" << LL_ENDL; + return false; + } + + static LLStdStringHandle end_string = LLXmlTree::addAttributeString("end"); + if (!node->getFastAttributeVector3(end_string, mEnd)) + { + LL_WARNS() << "Bone without end " << mName << LL_ENDL; + mEnd = LLVector3(0.0f, 0.0f, 0.0f); + } + + static LLStdStringHandle support_string = LLXmlTree::addAttributeString("support"); + if (!node->getFastAttributeString(support_string,mSupport)) + { + LL_WARNS() << "Bone without support " << mName << LL_ENDL; + mSupport = "base"; + } + + if (mIsJoint) + { + static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); + if (!node->getFastAttributeVector3(pivot_string, mPivot)) + { + LL_WARNS() << "Bone without pivot" << LL_ENDL; + return false; + } + } + + // parse children + LLXmlTreeNode* child; + for( child = node->getFirstChild(); child; child = node->getNextChild() ) + { + LLAvatarBoneInfo *child_info = new LLAvatarBoneInfo; + if (!child_info->parseXml(child)) + { + delete child_info; + return false; + } + mChildren.push_back(child_info); + } + return true; +} + +//----------------------------------------------------------------------------- +// LLAvatarSkeletonInfo::parseXml() +//----------------------------------------------------------------------------- +bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +{ + static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); + if (!node->getFastAttributeS32(num_bones_string, mNumBones)) + { + LL_WARNS() << "Couldn't find number of bones." << LL_ENDL; + return false; + } + + static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); + node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); + + LLXmlTreeNode* child; + for( child = node->getFirstChild(); child; child = node->getNextChild() ) + { + LLAvatarBoneInfo *info = new LLAvatarBoneInfo; + if (!info->parseXml(child)) + { + delete info; + LL_WARNS() << "Error parsing bone in skeleton file" << LL_ENDL; + return false; + } + mBoneInfoList.push_back(info); + } + return true; +} + +//Make aliases for joint and push to map. +void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info) +{ + if (! bone_info->mIsJoint ) + { + return; + } + + std::string bone_name = bone_info->mName; + mJointAliasMap[bone_name] = bone_name; //Actual name is a valid alias. + + std::string aliases = bone_info->mAliases; + + boost::char_separator sep(" "); + boost::tokenizer > tok(aliases, sep); + for(const std::string& i : tok) + { + if ( mJointAliasMap.find(i) != mJointAliasMap.end() ) + { + LL_WARNS() << "avatar skeleton: Joint alias \"" << i << "\" remapped from " << mJointAliasMap[i] << " to " << bone_name << LL_ENDL; + } + mJointAliasMap[i] = bone_name; + } + + for (LLAvatarBoneInfo* bone : bone_info->mChildren) + { + makeJointAliases(bone); + } +} + +const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases () +{ + LLAvatarAppearance::joint_alias_map_t alias_map; + if (mJointAliasMap.empty()) + { + + for (LLAvatarBoneInfo* bone_info : sAvatarSkeletonInfo->mBoneInfoList) + { + //LLAvatarBoneInfo *bone_info = *iter; + makeJointAliases(bone_info); + } + + for (LLAvatarXmlInfo::LLAvatarAttachmentInfo* info : sAvatarXmlInfo->mAttachmentInfoList) + { + std::string bone_name = info->mName; + + // Also accept the name with spaces substituted with + // underscores. This gives a mechanism for referencing such joints + // in daes, which don't allow spaces. + std::string sub_space_to_underscore = bone_name; + LLStringUtil::replaceChar(sub_space_to_underscore, ' ', '_'); + if (sub_space_to_underscore != bone_name) + { + mJointAliasMap[sub_space_to_underscore] = bone_name; + } + } + } + + return mJointAliasMap; +} + + +//----------------------------------------------------------------------------- +// parseXmlSkeletonNode(): parses nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +{ + LLXmlTreeNode* node = root->getChildByName( "skeleton" ); + if( !node ) + { + LL_WARNS() << "avatar file: missing " << LL_ENDL; + return false; + } + + LLXmlTreeNode* child; + + // SKELETON DISTORTIONS + for (child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if (!child->getChildByName("param_skeleton")) + { + if (child->getChildByName("param_morph")) + { + LL_WARNS() << "Can't specify morph param in skeleton definition." << LL_ENDL; + } + else + { + LL_WARNS() << "Unknown param type." << LL_ENDL; + } + return false; + } + + LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo; + if (!info->parseXml(child)) + { + delete info; + return false; + } + + mSkeletalDistortionInfoList.push_back(info); + } + + // ATTACHMENT POINTS + for (child = node->getChildByName( "attachment_point" ); + child; + child = node->getNextNamedChild()) + { + LLAvatarAttachmentInfo* info = new LLAvatarAttachmentInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!child->getFastAttributeString(name_string, info->mName)) + { + LL_WARNS() << "No name supplied for attachment point." << LL_ENDL; + delete info; + return false; + } + + static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint"); + if (!child->getFastAttributeString(joint_string, info->mJointName)) + { + LL_WARNS() << "No bone declared in attachment point " << info->mName << LL_ENDL; + delete info; + return false; + } + + static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position"); + if (child->getFastAttributeVector3(position_string, info->mPosition)) + { + info->mHasPosition = true; + } + + static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation"); + if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler)) + { + info->mHasRotation = true; + } + static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); + if (child->getFastAttributeS32(group_string, info->mGroup)) + { + if (info->mGroup == -1) + info->mGroup = -1111; // -1 = none parsed, < -1 = bad value + } + + static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); + if (!child->getFastAttributeS32(id_string, info->mAttachmentID)) + { + LL_WARNS() << "No id supplied for attachment point " << info->mName << LL_ENDL; + delete info; + return false; + } + + static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice"); + child->getFastAttributeS32(slot_string, info->mPieMenuSlice); + + static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person"); + child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson); + + static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud"); + child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment); + + mAttachmentInfoList.push_back(info); + } + + return true; +} + +//----------------------------------------------------------------------------- +// parseXmlMeshNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); + node; + node = root->getNextNamedChild()) + { + LLAvatarMeshInfo *info = new LLAvatarMeshInfo; + + // attribute: type + static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type"); + if( !node->getFastAttributeString( type_string, info->mType ) ) + { + LL_WARNS() << "Avatar file: is missing type attribute. Ignoring element. " << LL_ENDL; + delete info; + return false; // Ignore this element + } + + static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod"); + if (!node->getFastAttributeS32( lod_string, info->mLOD )) + { + LL_WARNS() << "Avatar file: is missing lod attribute. Ignoring element. " << LL_ENDL; + delete info; + return false; // Ignore this element + } + + static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name"); + if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) ) + { + LL_WARNS() << "Avatar file: is missing file_name attribute. Ignoring: " << info->mType << LL_ENDL; + delete info; + return false; // Ignore this element + } + + static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference"); + node->getFastAttributeString( reference_string, info->mReferenceMeshName ); + + // attribute: min_pixel_area + static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area"); + static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width"); + if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea )) + { + F32 min_pixel_area = 0.1f; + if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area )) + { + // this is square root of pixel area (sensible to use linear space in defining lods) + min_pixel_area = min_pixel_area * min_pixel_area; + } + info->mMinPixelArea = min_pixel_area; + } + + // Parse visual params for this node only if we haven't already + for (LLXmlTreeNode* child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if (!child->getChildByName("param_morph")) + { + if (child->getChildByName("param_skeleton")) + { + LL_WARNS() << "Can't specify skeleton param in a mesh definition." << LL_ENDL; + } + else + { + LL_WARNS() << "Unknown param type." << LL_ENDL; + } + return false; + } + + LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo(); + if (!morphinfo->parseXml(child)) + { + delete morphinfo; + delete info; + return false; + } + bool shared = false; + static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared"); + child->getFastAttributeBOOL(shared_string, shared); + + info->mPolyMorphTargetInfoList.push_back(LLAvatarMeshInfo::morph_info_pair_t(morphinfo, shared)); + } + + mMeshInfoList.push_back(info); + } + return true; +} + +//----------------------------------------------------------------------------- +// parseXmlColorNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); + color_node; + color_node = root->getNextNamedChild()) + { + std::string global_color_name; + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (color_node->getFastAttributeString( name_string, global_color_name ) ) + { + if( global_color_name == "skin_color" ) + { + if (mTexSkinColorInfo) + { + LL_WARNS() << "avatar file: multiple instances of skin_color" << LL_ENDL; + return false; + } + mTexSkinColorInfo = new LLTexGlobalColorInfo; + if( !mTexSkinColorInfo->parseXml( color_node ) ) + { + delete_and_clear(mTexSkinColorInfo); + LL_WARNS() << "avatar file: mTexSkinColor->parseXml() failed" << LL_ENDL; + return false; + } + } + else if( global_color_name == "hair_color" ) + { + if (mTexHairColorInfo) + { + LL_WARNS() << "avatar file: multiple instances of hair_color" << LL_ENDL; + return false; + } + mTexHairColorInfo = new LLTexGlobalColorInfo; + if( !mTexHairColorInfo->parseXml( color_node ) ) + { + delete_and_clear(mTexHairColorInfo); + LL_WARNS() << "avatar file: mTexHairColor->parseXml() failed" << LL_ENDL; + return false; + } + } + else if( global_color_name == "eye_color" ) + { + if (mTexEyeColorInfo) + { + LL_WARNS() << "avatar file: multiple instances of eye_color" << LL_ENDL; + return false; + } + mTexEyeColorInfo = new LLTexGlobalColorInfo; + if( !mTexEyeColorInfo->parseXml( color_node ) ) + { + LL_WARNS() << "avatar file: mTexEyeColor->parseXml() failed" << LL_ENDL; + return false; + } + } + } + } + return true; +} + +//----------------------------------------------------------------------------- +// parseXmlLayerNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +{ + for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); + layer_node; + layer_node = root->getNextNamedChild()) + { + LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo(); + if( layer_info->parseXml( layer_node ) ) + { + mLayerInfoList.push_back(layer_info); + } + else + { + delete layer_info; + LL_WARNS() << "avatar file: layer_set->parseXml() failed" << LL_ENDL; + return false; + } + } + return true; +} + +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +{ + LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); + if( driver ) + { + for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" ); + grand_child; + grand_child = driver->getNextNamedChild()) + { + if( grand_child->getChildByName( "param_driver" ) ) + { + LLDriverParamInfo* driver_info = new LLDriverParamInfo(); + if( driver_info->parseXml( grand_child ) ) + { + mDriverInfoList.push_back(driver_info); + } + else + { + delete driver_info; + LL_WARNS() << "avatar file: driver_param->parseXml() failed" << LL_ENDL; + return false; + } + } + } + } + return true; +} + +//----------------------------------------------------------------------------- +// parseXmlDriverNodes(): parses nodes from XML tree +//----------------------------------------------------------------------------- +bool LLAvatarAppearance::LLAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root) +{ + LLXmlTreeNode* masks = root->getChildByName( "morph_masks" ); + if( !masks ) + { + return false; + } + + for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" ); + grand_child; + grand_child = masks->getNextNamedChild()) + { + LLAvatarMorphInfo* info = new LLAvatarMorphInfo(); + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name"); + if (!grand_child->getFastAttributeString(name_string, info->mName)) + { + LL_WARNS() << "No name supplied for morph mask." << LL_ENDL; + delete info; + return false; + } + + static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region"); + if (!grand_child->getFastAttributeString(region_string, info->mRegion)) + { + LL_WARNS() << "No region supplied for morph mask." << LL_ENDL; + delete info; + return false; + } + + static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer"); + if (!grand_child->getFastAttributeString(layer_string, info->mLayer)) + { + LL_WARNS() << "No layer supplied for morph mask." << LL_ENDL; + delete info; + return false; + } + + // optional parameter. don't throw a warning if not present. + static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); + grand_child->getFastAttributeBOOL(invert_string, info->mInvert); + + mMorphMaskInfoList.push_back(info); + } + + return true; +} + +//virtual +LLAvatarAppearance::LLMaskedMorph::LLMaskedMorph(LLVisualParam *morph_target, bool invert, std::string layer) : + mMorphTarget(morph_target), + mInvert(invert), + mLayer(layer) +{ + LLPolyMorphTarget *target = dynamic_cast(morph_target); + if (target) + { + target->addPendingMorphMask(); + } +} diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 29221cde15..c2188d8ac9 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -1,471 +1,471 @@ -/** - * @file llavatarappearance.h - * @brief Declaration of LLAvatarAppearance class - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_AVATAR_APPEARANCE_H -#define LL_AVATAR_APPEARANCE_H - -#include "llcharacter.h" -#include "llavatarappearancedefines.h" -#include "llavatarjointmesh.h" -#include "lldriverparam.h" -#include "lltexlayer.h" -#include "llviewervisualparam.h" -#include "llxmltree.h" - -class LLTexLayerSet; -class LLTexGlobalColor; -class LLTexGlobalColorInfo; -class LLWearableData; -class LLAvatarBoneInfo; -class LLAvatarSkeletonInfo; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLAvatarAppearance -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLAvatarAppearance : public LLCharacter -{ - LOG_CLASS(LLAvatarAppearance); - -protected: - struct LLAvatarXmlInfo; - -/******************************************************************************** - ** ** - ** INITIALIZATION - **/ -private: - // Hide default constructor. - LLAvatarAppearance() {} - -public: - LLAvatarAppearance(LLWearableData* wearable_data); - virtual ~LLAvatarAppearance(); - - static void initClass(const std::string& avatar_file_name, const std::string& skeleton_file_name); // initializes static members - static void initClass(); - static void cleanupClass(); // Cleanup data that's only init'd once per class. - virtual void initInstance(); // Called after construction to initialize the instance. - S32 mInitFlags; - virtual bool loadSkeletonNode(); - bool loadMeshNodes(); - bool loadLayersets(); - - -/** Initialization - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** INHERITED - **/ - - //-------------------------------------------------------------------- - // LLCharacter interface and related - //-------------------------------------------------------------------- -public: - /*virtual*/ LLJoint* getCharacterJoint(U32 num); - - /*virtual*/ const char* getAnimationPrefix() { return "avatar"; } - /*virtual*/ LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); - /*virtual*/ LLJoint* findCollisionVolume(S32 volume_id); - /*virtual*/ S32 getCollisionVolumeID(std::string &name); - /*virtual*/ LLPolyMesh* getHeadMesh(); - /*virtual*/ LLPolyMesh* getUpperBodyMesh(); - -/** Inherited - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** STATE - **/ -public: - virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent - virtual bool isValid() const; - virtual bool isUsingLocalAppearance() const = 0; - virtual bool isEditingAppearance() const = 0; - - bool isBuilt() const { return mIsBuilt; } - - -/** State - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** SKELETON - **/ - -protected: - virtual LLAvatarJoint* createAvatarJoint() = 0; - virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0; - virtual LLAvatarJointMesh* createAvatarJointMesh() = 0; - void makeJointAliases(LLAvatarBoneInfo *bone_info); - - -public: - F32 getPelvisToFoot() const { return mPelvisToFoot; } - /*virtual*/ LLJoint* getRootJoint() { return mRoot; } - - LLVector3 mHeadOffset; // current head position - LLAvatarJoint *mRoot; - - typedef std::map joint_map_t; - joint_map_t mJointMap; - - typedef std::map joint_state_map_t; - joint_state_map_t mLastBodySizeState; - joint_state_map_t mCurrBodySizeState; - void compareJointStateMaps(joint_state_map_t& last_state, - joint_state_map_t& curr_state); - void computeBodySize(); - F32 computeBodyHeight(); - F32 computePelvisToFoot(); - -public: - typedef std::vector avatar_joint_list_t; - const avatar_joint_list_t& getSkeleton() { return mSkeleton; } - typedef std::map joint_alias_map_t; - const joint_alias_map_t& getJointAliases(); - - -protected: - static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); - virtual void buildCharacter(); - virtual bool loadAvatar(); - - bool setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); - bool allocateCharacterJoints(U32 num); - bool buildSkeleton(const LLAvatarSkeletonInfo *info); - - void clearSkeleton(); - bool mIsBuilt; // state of deferred character building - avatar_joint_list_t mSkeleton; - LLVector3OverrideMap mPelvisFixups; - joint_alias_map_t mJointAliasMap; - - //-------------------------------------------------------------------- - // Pelvis height adjustment members. - //-------------------------------------------------------------------- -public: - void addPelvisFixup( F32 fixup, const LLUUID& mesh_id ); - void removePelvisFixup( const LLUUID& mesh_id ); - bool hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const; - bool hasPelvisFixup( F32& fixup ) const; - - LLVector3 mBodySize; - LLVector3 mAvatarOffset; -protected: - F32 mPelvisToFoot; - - //-------------------------------------------------------------------- - // Cached pointers to well known joints - //-------------------------------------------------------------------- -public: - LLJoint* mPelvisp; - LLJoint* mTorsop; - LLJoint* mChestp; - LLJoint* mNeckp; - LLJoint* mHeadp; - LLJoint* mSkullp; - LLJoint* mEyeLeftp; - LLJoint* mEyeRightp; - LLJoint* mHipLeftp; - LLJoint* mHipRightp; - LLJoint* mKneeLeftp; - LLJoint* mKneeRightp; - LLJoint* mAnkleLeftp; - LLJoint* mAnkleRightp; - LLJoint* mFootLeftp; - LLJoint* mFootRightp; - LLJoint* mWristLeftp; - LLJoint* mWristRightp; - - //-------------------------------------------------------------------- - // XML parse tree - //-------------------------------------------------------------------- -protected: - static LLAvatarSkeletonInfo* sAvatarSkeletonInfo; - static LLAvatarXmlInfo* sAvatarXmlInfo; - - -/** Skeleton - ** ** - *******************************************************************************/ - - -/******************************************************************************** - ** ** - ** RENDERING - **/ -public: - bool mIsDummy; // for special views and animated object controllers; local to viewer - - //-------------------------------------------------------------------- - // Morph masks - //-------------------------------------------------------------------- -public: - void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, bool invert, std::string layer); - virtual void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; - -/** Rendering - ** ** - *******************************************************************************/ - - //-------------------------------------------------------------------- - // Composites - //-------------------------------------------------------------------- -public: - virtual void invalidateComposite(LLTexLayerSet* layerset) = 0; - -/******************************************************************************** - ** ** - ** MESHES - **/ - -public: - virtual void updateMeshTextures() = 0; - virtual void dirtyMesh() = 0; // Dirty the avatar mesh - static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } -protected: - virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority - -protected: - typedef std::multimap polymesh_map_t; - polymesh_map_t mPolyMeshes; - avatar_joint_list_t mMeshLOD; - - // mesh entries and backed textures - static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; - -/** Meshes - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** APPEARANCE - **/ - - //-------------------------------------------------------------------- - // Clothing colors (convenience functions to access visual parameters) - //-------------------------------------------------------------------- -public: - void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color); - LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); - static bool teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); - - //-------------------------------------------------------------------- - // Global colors - //-------------------------------------------------------------------- -public: - LLColor4 getGlobalColor(const std::string& color_name ) const; - virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0; -protected: - LLTexGlobalColor* mTexSkinColor; - LLTexGlobalColor* mTexHairColor; - LLTexGlobalColor* mTexEyeColor; - - //-------------------------------------------------------------------- - // Visibility - //-------------------------------------------------------------------- -public: - static LLColor4 getDummyColor(); -/** Appearance - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** WEARABLES - **/ - -public: - LLWearableData* getWearableData() { return mWearableData; } - const LLWearableData* getWearableData() const { return mWearableData; } - virtual bool isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0; - virtual bool isWearingWearableType(LLWearableType::EType type ) const; - -private: - LLWearableData* mWearableData; - -/******************************************************************************** - ** ** - ** BAKED TEXTURES - **/ -public: - LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; - -protected: - virtual LLTexLayerSet* createTexLayerSet() = 0; - -protected: - class LLMaskedMorph; - typedef std::deque morph_list_t; - struct BakedTextureData - { - LLUUID mLastTextureID; - LLTexLayerSet* mTexLayerSet; // Only exists for self - bool mIsLoaded; - bool mIsUsed; - LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; - U32 mMaskTexName; - // Stores pointers to the joint meshes that this baked texture deals with - avatar_joint_mesh_list_t mJointMeshes; - morph_list_t mMaskedMorphs; - }; - typedef std::vector bakedtexturedata_vec_t; - bakedtexturedata_vec_t mBakedTextureDatas; - -/******************************************************************************** - ** ** - ** PHYSICS - **/ - - //-------------------------------------------------------------------- - // Collision volumes - //-------------------------------------------------------------------- -public: - S32 mNumBones; - S32 mNumCollisionVolumes; - LLAvatarJointCollisionVolume* mCollisionVolumes; -protected: - bool allocateCollisionVolumes(U32 num); - -/** Physics - ** ** - *******************************************************************************/ - -/******************************************************************************** - ** ** - ** SUPPORT CLASSES - **/ - - struct LLAvatarXmlInfo - { - LLAvatarXmlInfo(); - ~LLAvatarXmlInfo(); - - bool parseXmlSkeletonNode(LLXmlTreeNode* root); - bool parseXmlMeshNodes(LLXmlTreeNode* root); - bool parseXmlColorNodes(LLXmlTreeNode* root); - bool parseXmlLayerNodes(LLXmlTreeNode* root); - bool parseXmlDriverNodes(LLXmlTreeNode* root); - bool parseXmlMorphNodes(LLXmlTreeNode* root); - - struct LLAvatarMeshInfo - { - typedef std::pair morph_info_pair_t; // LLPolyMorphTargetInfo stored here - typedef std::vector morph_info_list_t; - - LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} - ~LLAvatarMeshInfo() - { - for (morph_info_list_t::value_type& pair : mPolyMorphTargetInfoList) - { - delete pair.first; - } - mPolyMorphTargetInfoList.clear(); - } - - std::string mType; - S32 mLOD; - std::string mMeshFileName; - std::string mReferenceMeshName; - F32 mMinPixelArea; - morph_info_list_t mPolyMorphTargetInfoList; - }; - typedef std::vector mesh_info_list_t; - mesh_info_list_t mMeshInfoList; - - typedef std::vector skeletal_distortion_info_list_t; // LLPolySkeletalDistortionInfo stored here - skeletal_distortion_info_list_t mSkeletalDistortionInfoList; - - struct LLAvatarAttachmentInfo - { - LLAvatarAttachmentInfo() - : 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 attachment_info_list_t; - attachment_info_list_t mAttachmentInfoList; - - LLTexGlobalColorInfo *mTexSkinColorInfo; - LLTexGlobalColorInfo *mTexHairColorInfo; - LLTexGlobalColorInfo *mTexEyeColorInfo; - - typedef std::vector layer_info_list_t; - layer_info_list_t mLayerInfoList; - - typedef std::vector driver_info_list_t; - driver_info_list_t mDriverInfoList; - - struct LLAvatarMorphInfo - { - LLAvatarMorphInfo() - : mInvert(false) {} - std::string mName; - std::string mRegion; - std::string mLayer; - bool mInvert; - }; - - typedef std::vector morph_info_list_t; - morph_info_list_t mMorphMaskInfoList; - }; - - - class LLMaskedMorph - { - public: - LLMaskedMorph(LLVisualParam *morph_target, bool invert, std::string layer); - - LLVisualParam *mMorphTarget; - bool mInvert; - std::string mLayer; - }; -/** Support Classes - ** ** - *******************************************************************************/ -}; - -#endif // LL_AVATAR_APPEARANCE_H +/** + * @file llavatarappearance.h + * @brief Declaration of LLAvatarAppearance class + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_AVATAR_APPEARANCE_H +#define LL_AVATAR_APPEARANCE_H + +#include "llcharacter.h" +#include "llavatarappearancedefines.h" +#include "llavatarjointmesh.h" +#include "lldriverparam.h" +#include "lltexlayer.h" +#include "llviewervisualparam.h" +#include "llxmltree.h" + +class LLTexLayerSet; +class LLTexGlobalColor; +class LLTexGlobalColorInfo; +class LLWearableData; +class LLAvatarBoneInfo; +class LLAvatarSkeletonInfo; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLAvatarAppearance +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLAvatarAppearance : public LLCharacter +{ + LOG_CLASS(LLAvatarAppearance); + +protected: + struct LLAvatarXmlInfo; + +/******************************************************************************** + ** ** + ** INITIALIZATION + **/ +private: + // Hide default constructor. + LLAvatarAppearance() {} + +public: + LLAvatarAppearance(LLWearableData* wearable_data); + virtual ~LLAvatarAppearance(); + + static void initClass(const std::string& avatar_file_name, const std::string& skeleton_file_name); // initializes static members + static void initClass(); + static void cleanupClass(); // Cleanup data that's only init'd once per class. + virtual void initInstance(); // Called after construction to initialize the instance. + S32 mInitFlags; + virtual bool loadSkeletonNode(); + bool loadMeshNodes(); + bool loadLayersets(); + + +/** Initialization + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** INHERITED + **/ + + //-------------------------------------------------------------------- + // LLCharacter interface and related + //-------------------------------------------------------------------- +public: + /*virtual*/ LLJoint* getCharacterJoint(U32 num); + + /*virtual*/ const char* getAnimationPrefix() { return "avatar"; } + /*virtual*/ LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); + /*virtual*/ LLJoint* findCollisionVolume(S32 volume_id); + /*virtual*/ S32 getCollisionVolumeID(std::string &name); + /*virtual*/ LLPolyMesh* getHeadMesh(); + /*virtual*/ LLPolyMesh* getUpperBodyMesh(); + +/** Inherited + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** STATE + **/ +public: + virtual bool isSelf() const { return false; } // True if this avatar is for this viewer's agent + virtual bool isValid() const; + virtual bool isUsingLocalAppearance() const = 0; + virtual bool isEditingAppearance() const = 0; + + bool isBuilt() const { return mIsBuilt; } + + +/** State + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SKELETON + **/ + +protected: + virtual LLAvatarJoint* createAvatarJoint() = 0; + virtual LLAvatarJoint* createAvatarJoint(S32 joint_num) = 0; + virtual LLAvatarJointMesh* createAvatarJointMesh() = 0; + void makeJointAliases(LLAvatarBoneInfo *bone_info); + + +public: + F32 getPelvisToFoot() const { return mPelvisToFoot; } + /*virtual*/ LLJoint* getRootJoint() { return mRoot; } + + LLVector3 mHeadOffset; // current head position + LLAvatarJoint *mRoot; + + typedef std::map joint_map_t; + joint_map_t mJointMap; + + typedef std::map joint_state_map_t; + joint_state_map_t mLastBodySizeState; + joint_state_map_t mCurrBodySizeState; + void compareJointStateMaps(joint_state_map_t& last_state, + joint_state_map_t& curr_state); + void computeBodySize(); + F32 computeBodyHeight(); + F32 computePelvisToFoot(); + +public: + typedef std::vector avatar_joint_list_t; + const avatar_joint_list_t& getSkeleton() { return mSkeleton; } + typedef std::map joint_alias_map_t; + const joint_alias_map_t& getJointAliases(); + + +protected: + static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); + virtual void buildCharacter(); + virtual bool loadAvatar(); + + bool setupBone(const LLAvatarBoneInfo* info, LLJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + bool allocateCharacterJoints(U32 num); + bool buildSkeleton(const LLAvatarSkeletonInfo *info); + + void clearSkeleton(); + bool mIsBuilt; // state of deferred character building + avatar_joint_list_t mSkeleton; + LLVector3OverrideMap mPelvisFixups; + joint_alias_map_t mJointAliasMap; + + //-------------------------------------------------------------------- + // Pelvis height adjustment members. + //-------------------------------------------------------------------- +public: + void addPelvisFixup( F32 fixup, const LLUUID& mesh_id ); + void removePelvisFixup( const LLUUID& mesh_id ); + bool hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const; + bool hasPelvisFixup( F32& fixup ) const; + + LLVector3 mBodySize; + LLVector3 mAvatarOffset; +protected: + F32 mPelvisToFoot; + + //-------------------------------------------------------------------- + // Cached pointers to well known joints + //-------------------------------------------------------------------- +public: + LLJoint* mPelvisp; + LLJoint* mTorsop; + LLJoint* mChestp; + LLJoint* mNeckp; + LLJoint* mHeadp; + LLJoint* mSkullp; + LLJoint* mEyeLeftp; + LLJoint* mEyeRightp; + LLJoint* mHipLeftp; + LLJoint* mHipRightp; + LLJoint* mKneeLeftp; + LLJoint* mKneeRightp; + LLJoint* mAnkleLeftp; + LLJoint* mAnkleRightp; + LLJoint* mFootLeftp; + LLJoint* mFootRightp; + LLJoint* mWristLeftp; + LLJoint* mWristRightp; + + //-------------------------------------------------------------------- + // XML parse tree + //-------------------------------------------------------------------- +protected: + static LLAvatarSkeletonInfo* sAvatarSkeletonInfo; + static LLAvatarXmlInfo* sAvatarXmlInfo; + + +/** Skeleton + ** ** + *******************************************************************************/ + + +/******************************************************************************** + ** ** + ** RENDERING + **/ +public: + bool mIsDummy; // for special views and animated object controllers; local to viewer + + //-------------------------------------------------------------------- + // Morph masks + //-------------------------------------------------------------------- +public: + void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, bool invert, std::string layer); + virtual void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0; + +/** Rendering + ** ** + *******************************************************************************/ + + //-------------------------------------------------------------------- + // Composites + //-------------------------------------------------------------------- +public: + virtual void invalidateComposite(LLTexLayerSet* layerset) = 0; + +/******************************************************************************** + ** ** + ** MESHES + **/ + +public: + virtual void updateMeshTextures() = 0; + virtual void dirtyMesh() = 0; // Dirty the avatar mesh + static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; } +protected: + virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority + +protected: + typedef std::multimap polymesh_map_t; + polymesh_map_t mPolyMeshes; + avatar_joint_list_t mMeshLOD; + + // mesh entries and backed textures + static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary; + +/** Meshes + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** APPEARANCE + **/ + + //-------------------------------------------------------------------- + // Clothing colors (convenience functions to access visual parameters) + //-------------------------------------------------------------------- +public: + void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color); + LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); + static bool teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + LLColor4 getGlobalColor(const std::string& color_name ) const; + virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0; +protected: + LLTexGlobalColor* mTexSkinColor; + LLTexGlobalColor* mTexHairColor; + LLTexGlobalColor* mTexEyeColor; + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +public: + static LLColor4 getDummyColor(); +/** Appearance + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** WEARABLES + **/ + +public: + LLWearableData* getWearableData() { return mWearableData; } + const LLWearableData* getWearableData() const { return mWearableData; } + virtual bool isTextureDefined(LLAvatarAppearanceDefines::ETextureIndex te, U32 index = 0 ) const = 0; + virtual bool isWearingWearableType(LLWearableType::EType type ) const; + +private: + LLWearableData* mWearableData; + +/******************************************************************************** + ** ** + ** BAKED TEXTURES + **/ +public: + LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; + +protected: + virtual LLTexLayerSet* createTexLayerSet() = 0; + +protected: + class LLMaskedMorph; + typedef std::deque morph_list_t; + struct BakedTextureData + { + LLUUID mLastTextureID; + LLTexLayerSet* mTexLayerSet; // Only exists for self + bool mIsLoaded; + bool mIsUsed; + LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; + U32 mMaskTexName; + // Stores pointers to the joint meshes that this baked texture deals with + avatar_joint_mesh_list_t mJointMeshes; + morph_list_t mMaskedMorphs; + }; + typedef std::vector bakedtexturedata_vec_t; + bakedtexturedata_vec_t mBakedTextureDatas; + +/******************************************************************************** + ** ** + ** PHYSICS + **/ + + //-------------------------------------------------------------------- + // Collision volumes + //-------------------------------------------------------------------- +public: + S32 mNumBones; + S32 mNumCollisionVolumes; + LLAvatarJointCollisionVolume* mCollisionVolumes; +protected: + bool allocateCollisionVolumes(U32 num); + +/** Physics + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SUPPORT CLASSES + **/ + + struct LLAvatarXmlInfo + { + LLAvatarXmlInfo(); + ~LLAvatarXmlInfo(); + + bool parseXmlSkeletonNode(LLXmlTreeNode* root); + bool parseXmlMeshNodes(LLXmlTreeNode* root); + bool parseXmlColorNodes(LLXmlTreeNode* root); + bool parseXmlLayerNodes(LLXmlTreeNode* root); + bool parseXmlDriverNodes(LLXmlTreeNode* root); + bool parseXmlMorphNodes(LLXmlTreeNode* root); + + struct LLAvatarMeshInfo + { + typedef std::pair morph_info_pair_t; // LLPolyMorphTargetInfo stored here + typedef std::vector morph_info_list_t; + + LLAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} + ~LLAvatarMeshInfo() + { + for (morph_info_list_t::value_type& pair : mPolyMorphTargetInfoList) + { + delete pair.first; + } + mPolyMorphTargetInfoList.clear(); + } + + std::string mType; + S32 mLOD; + std::string mMeshFileName; + std::string mReferenceMeshName; + F32 mMinPixelArea; + morph_info_list_t mPolyMorphTargetInfoList; + }; + typedef std::vector mesh_info_list_t; + mesh_info_list_t mMeshInfoList; + + typedef std::vector skeletal_distortion_info_list_t; // LLPolySkeletalDistortionInfo stored here + skeletal_distortion_info_list_t mSkeletalDistortionInfoList; + + struct LLAvatarAttachmentInfo + { + LLAvatarAttachmentInfo() + : 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 attachment_info_list_t; + attachment_info_list_t mAttachmentInfoList; + + LLTexGlobalColorInfo *mTexSkinColorInfo; + LLTexGlobalColorInfo *mTexHairColorInfo; + LLTexGlobalColorInfo *mTexEyeColorInfo; + + typedef std::vector layer_info_list_t; + layer_info_list_t mLayerInfoList; + + typedef std::vector driver_info_list_t; + driver_info_list_t mDriverInfoList; + + struct LLAvatarMorphInfo + { + LLAvatarMorphInfo() + : mInvert(false) {} + std::string mName; + std::string mRegion; + std::string mLayer; + bool mInvert; + }; + + typedef std::vector morph_info_list_t; + morph_info_list_t mMorphMaskInfoList; + }; + + + class LLMaskedMorph + { + public: + LLMaskedMorph(LLVisualParam *morph_target, bool invert, std::string layer); + + LLVisualParam *mMorphTarget; + bool mInvert; + std::string mLayer; + }; +/** Support Classes + ** ** + *******************************************************************************/ +}; + +#endif // LL_AVATAR_APPEARANCE_H diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index 1fd30d023d..c69517cb22 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -1,413 +1,413 @@ -/** - * @file llavatarappearancedefines.cpp - * @brief Implementation of LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llavatarappearancedefines.h" -#include "indra_constants.h" - -const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 1024; -const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 1024; - -using namespace LLAvatarAppearanceDefines; - -/********************************************************************************* - * Edit this function to add/remove/change textures and mesh definitions for avatars. - */ - -LLAvatarAppearanceDictionary::Textures::Textures() -{ - addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", true, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); - addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", true, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); - addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", true, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); - addEntry(TEX_HAIR, new TextureEntry("hair_grain", true, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); - addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); - addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", true, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); - addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", true, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); - addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", true, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", true, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); - addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", true, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); - addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", true, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); - addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", true, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); - addEntry(TEX_SKIRT, new TextureEntry("skirt", true, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); - - addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); - - addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); - - addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new TextureEntry("head_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new TextureEntry("upper_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new TextureEntry("lower_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_SKIRT_TATTOO, new TextureEntry("skirt_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_HAIR_TATTOO, new TextureEntry("hair_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_EYES_TATTOO, new TextureEntry("eyes_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_LEFT_ARM_TATTOO, new TextureEntry("leftarm_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_LEFT_LEG_TATTOO, new TextureEntry("leftleg_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_AUX1_TATTOO, new TextureEntry("aux1_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_AUX2_TATTOO, new TextureEntry("aux2_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - addEntry(TEX_AUX3_TATTOO, new TextureEntry("aux3_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); - - - addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", false, BAKED_HEAD, "head")); - addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", false, BAKED_UPPER, "upper")); - addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", false, BAKED_LOWER, "lower")); - addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", false, BAKED_EYES, "eyes")); - addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", false, BAKED_HAIR, "hair")); - addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", false, BAKED_SKIRT, "skirt")); - addEntry(TEX_LEFT_ARM_BAKED, new TextureEntry("leftarm-baked", false, BAKED_LEFT_ARM, "leftarm")); - addEntry(TEX_LEFT_LEG_BAKED, new TextureEntry("leftleg-baked", false, BAKED_LEFT_LEG, "leftleg")); - addEntry(TEX_AUX1_BAKED, new TextureEntry("aux1-baked", false, BAKED_AUX1, "aux1")); - addEntry(TEX_AUX2_BAKED, new TextureEntry("aux2-baked", false, BAKED_AUX2, "aux2")); - addEntry(TEX_AUX3_BAKED, new TextureEntry("aux3-baked", false, BAKED_AUX3, "aux3")); -} - -LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() -{ - // Baked textures - addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, - "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", - 4, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, TEX_HEAD_UNIVERSAL_TATTOO, - 6, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, - "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", - 8, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, - TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, TEX_UPPER_UNIVERSAL_TATTOO, - 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, - "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", - 9, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, - TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, TEX_LOWER_UNIVERSAL_TATTOO, - 10, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, - "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", - 3, TEX_EYES_IRIS, TEX_EYES_TATTOO, TEX_EYES_ALPHA, - 3, LLWearableType::WT_EYES, LLWearableType::WT_UNIVERSAL, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, - "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", - 2, TEX_SKIRT, TEX_SKIRT_TATTOO, - 2, LLWearableType::WT_SKIRT, LLWearableType::WT_UNIVERSAL )); - - addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, - "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", - 3, TEX_HAIR, TEX_HAIR_TATTOO, TEX_HAIR_ALPHA, - 3, LLWearableType::WT_HAIR, LLWearableType::WT_UNIVERSAL, LLWearableType::WT_ALPHA)); - - addEntry(BAKED_LEFT_ARM, new BakedEntry(TEX_LEFT_ARM_BAKED, - "leftarm", "9f39febf-22d7-0087-79d1-e9e8c6c9ed19", - 1, TEX_LEFT_ARM_TATTOO, - 1, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_LEFT_LEG, new BakedEntry(TEX_LEFT_LEG_BAKED, - "leftleg", "054a7a58-8ed5-6386-0add-3b636fb28b78", - 1, TEX_LEFT_LEG_TATTOO, - 1, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_AUX1, new BakedEntry(TEX_AUX1_BAKED, - "aux1", "790c11be-b25c-c17e-b4d2-6a4ad786b752", - 1, TEX_AUX1_TATTOO, - 1, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_AUX2, new BakedEntry(TEX_AUX2_BAKED, - "aux2", "d78c478f-48c7-5928-5864-8d99fb1f521e", - 1, TEX_AUX2_TATTOO, - 1, LLWearableType::WT_UNIVERSAL)); - - addEntry(BAKED_AUX3, new BakedEntry(TEX_AUX3_BAKED, - "aux3", "6a95dd53-edd9-aac8-f6d3-27ed99f3c3eb", - 1, TEX_AUX3_TATTOO, - 1, LLWearableType::WT_UNIVERSAL)); -} - -LLAvatarAppearanceDictionary::MeshEntries::MeshEntries() -{ - // MeshEntries - addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); - addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); - addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently - addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1)); - addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2)); - addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3)); - addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3)); - addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5)); -} - -/* - * - *********************************************************************************/ - -LLAvatarAppearanceDictionary::LLAvatarAppearanceDictionary() -{ - createAssociations(); -} - -//virtual -LLAvatarAppearanceDictionary::~LLAvatarAppearanceDictionary() -{ -} - -// Baked textures are composites of textures; for each such composited texture, -// map it to the baked texture. -void LLAvatarAppearanceDictionary::createAssociations() -{ - for (BakedTextures::value_type& baked_pair : mBakedTextures) - { - const EBakedTextureIndex baked_index = baked_pair.first; - const BakedEntry *dict = baked_pair.second; - - // For each texture that this baked texture index affects, associate those textures - // with this baked texture index. - for (const ETextureIndex local_texture_index : dict->mLocalTextures) - { - mTextures[local_texture_index]->mIsUsedByBakedTexture = true; - mTextures[local_texture_index]->mBakedTextureIndex = baked_index; - } - } - -} - -LLAvatarAppearanceDictionary::TextureEntry::TextureEntry(const std::string &name, - bool is_local_texture, - EBakedTextureIndex baked_texture_index, - const std::string &default_image_name, - LLWearableType::EType wearable_type) : - LLDictionaryEntry(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) -{ -} - -LLAvatarAppearanceDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, - const std::string &name, - U8 level, - LLJointPickName pick) : - LLDictionaryEntry(name), - mBakedID(baked_index), - mLOD(level), - mPickName(pick) -{ -} -LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, - const std::string &name, - const std::string &hash_name, - U32 num_local_textures, - ... ) : - LLDictionaryEntry(name), - mWearablesHashID(LLUUID(hash_name)), - mTextureIndex(tex_index) -{ - va_list argp; - - va_start(argp, num_local_textures); - - // Read in local textures - for (U8 i=0; i < num_local_textures; i++) - { - ETextureIndex t = (ETextureIndex)va_arg(argp,int); - mLocalTextures.push_back(t); - } - - // Read in number of wearables - const U32 num_wearables = (U32)va_arg(argp,int); - // Read in wearables - for (U8 i=0; i < num_wearables; i++) - { - LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); - mWearables.push_back(t); - } -} - -ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) const -{ - return getBakedTexture(index)->mTextureIndex; -} - -EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) -{ - U8 index = 0; - while (index < BAKED_NUM_INDICES) - { - const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index); - if (be && be->mName.compare(name) == 0) - { - // baked texture found - return (EBakedTextureIndex) index; - } - index++; - } - // baked texture could not be found - return BAKED_NUM_INDICES; -} - -EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name) -{ - U8 index = 0; - while (index < BAKED_NUM_INDICES) - { - const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index); - if (be) - { - const TextureEntry *te = getTexture(be->mTextureIndex); - if (te && te->mDefaultImageName.compare(name) == 0) - { - // baked texture found - return (EBakedTextureIndex) index; - } - } - index++; - } - // baked texture could not be found - return BAKED_NUM_INDICES; -} - -LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) const -{ - return getTexture(index)->mWearableType; -} - -// static -bool LLAvatarAppearanceDictionary::isBakedImageId(const LLUUID& id) -{ - if ((id == IMG_USE_BAKED_EYES) || (id == IMG_USE_BAKED_HAIR) || (id == IMG_USE_BAKED_HEAD) || (id == IMG_USE_BAKED_LOWER) || (id == IMG_USE_BAKED_SKIRT) || (id == IMG_USE_BAKED_UPPER) - || (id == IMG_USE_BAKED_LEFTARM) || (id == IMG_USE_BAKED_LEFTLEG) || (id == IMG_USE_BAKED_AUX1) || (id == IMG_USE_BAKED_AUX2) || (id == IMG_USE_BAKED_AUX3) ) - { - return true; - } - - return false; -} - -// static -EBakedTextureIndex LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(const LLUUID& id) -{ - if (id == IMG_USE_BAKED_EYES) - { - return BAKED_EYES; - } - else if (id == IMG_USE_BAKED_HAIR) - { - return BAKED_HAIR; - } - else if (id == IMG_USE_BAKED_HEAD) - { - return BAKED_HEAD; - } - else if (id == IMG_USE_BAKED_LOWER) - { - return BAKED_LOWER; - } - else if (id == IMG_USE_BAKED_SKIRT) - { - return BAKED_SKIRT; - } - else if (id == IMG_USE_BAKED_UPPER) - { - return BAKED_UPPER; - } - else if (id == IMG_USE_BAKED_LEFTARM) - { - return BAKED_LEFT_ARM; - } - else if (id == IMG_USE_BAKED_LEFTLEG) - { - return BAKED_LEFT_LEG; - } - else if (id == IMG_USE_BAKED_AUX1) - { - return BAKED_AUX1; - } - else if (id == IMG_USE_BAKED_AUX2) - { - return BAKED_AUX2; - } - else if (id == IMG_USE_BAKED_AUX3) - { - return BAKED_AUX3; - } - - return BAKED_NUM_INDICES; -} - -//static -LLUUID LLAvatarAppearanceDictionary::localTextureIndexToMagicId(ETextureIndex t) -{ - LLUUID id = LLUUID::null; - - switch (t) - { - case LLAvatarAppearanceDefines::TEX_HEAD_BAKED: - id = IMG_USE_BAKED_HEAD; - break; - case LLAvatarAppearanceDefines::TEX_UPPER_BAKED: - id = IMG_USE_BAKED_UPPER; - break; - case LLAvatarAppearanceDefines::TEX_LOWER_BAKED: - id = IMG_USE_BAKED_LOWER; - break; - case LLAvatarAppearanceDefines::TEX_EYES_BAKED: - id = IMG_USE_BAKED_EYES; - break; - case LLAvatarAppearanceDefines::TEX_SKIRT_BAKED: - id = IMG_USE_BAKED_SKIRT; - break; - case LLAvatarAppearanceDefines::TEX_HAIR_BAKED: - id = IMG_USE_BAKED_HAIR; - break; - case LLAvatarAppearanceDefines::TEX_LEFT_ARM_BAKED: - id = IMG_USE_BAKED_LEFTARM; - break; - case LLAvatarAppearanceDefines::TEX_LEFT_LEG_BAKED: - id = IMG_USE_BAKED_LEFTLEG; - break; - case LLAvatarAppearanceDefines::TEX_AUX1_BAKED: - id = IMG_USE_BAKED_AUX1; - break; - case LLAvatarAppearanceDefines::TEX_AUX2_BAKED: - id = IMG_USE_BAKED_AUX2; - break; - case LLAvatarAppearanceDefines::TEX_AUX3_BAKED: - id = IMG_USE_BAKED_AUX3; - break; - default: - break; - } - - return id; -} +/** + * @file llavatarappearancedefines.cpp + * @brief Implementation of LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llavatarappearancedefines.h" +#include "indra_constants.h" + +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 1024; +const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 1024; + +using namespace LLAvatarAppearanceDefines; + +/********************************************************************************* + * Edit this function to add/remove/change textures and mesh definitions for avatars. + */ + +LLAvatarAppearanceDictionary::Textures::Textures() +{ + addEntry(TEX_HEAD_BODYPAINT, new TextureEntry("head_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_UPPER_SHIRT, new TextureEntry("upper_shirt", true, BAKED_NUM_INDICES, "UIImgDefaultShirtUUID", LLWearableType::WT_SHIRT)); + addEntry(TEX_LOWER_PANTS, new TextureEntry("lower_pants", true, BAKED_NUM_INDICES, "UIImgDefaultPantsUUID", LLWearableType::WT_PANTS)); + addEntry(TEX_EYES_IRIS, new TextureEntry("eyes_iris", true, BAKED_NUM_INDICES, "UIImgDefaultEyesUUID", LLWearableType::WT_EYES)); + addEntry(TEX_HAIR, new TextureEntry("hair_grain", true, BAKED_NUM_INDICES, "UIImgDefaultHairUUID", LLWearableType::WT_HAIR)); + addEntry(TEX_UPPER_BODYPAINT, new TextureEntry("upper_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_BODYPAINT, new TextureEntry("lower_bodypaint", true, BAKED_NUM_INDICES, "", LLWearableType::WT_SKIN)); + addEntry(TEX_LOWER_SHOES, new TextureEntry("lower_shoes", true, BAKED_NUM_INDICES, "UIImgDefaultShoesUUID", LLWearableType::WT_SHOES)); + addEntry(TEX_LOWER_SOCKS, new TextureEntry("lower_socks", true, BAKED_NUM_INDICES, "UIImgDefaultSocksUUID", LLWearableType::WT_SOCKS)); + addEntry(TEX_UPPER_JACKET, new TextureEntry("upper_jacket", true, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_LOWER_JACKET, new TextureEntry("lower_jacket", true, BAKED_NUM_INDICES, "UIImgDefaultJacketUUID", LLWearableType::WT_JACKET)); + addEntry(TEX_UPPER_GLOVES, new TextureEntry("upper_gloves", true, BAKED_NUM_INDICES, "UIImgDefaultGlovesUUID", LLWearableType::WT_GLOVES)); + addEntry(TEX_UPPER_UNDERSHIRT, new TextureEntry("upper_undershirt", true, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERSHIRT)); + addEntry(TEX_LOWER_UNDERPANTS, new TextureEntry("lower_underpants", true, BAKED_NUM_INDICES, "UIImgDefaultUnderwearUUID", LLWearableType::WT_UNDERPANTS)); + addEntry(TEX_SKIRT, new TextureEntry("skirt", true, BAKED_NUM_INDICES, "UIImgDefaultSkirtUUID", LLWearableType::WT_SKIRT)); + + addEntry(TEX_LOWER_ALPHA, new TextureEntry("lower_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_UPPER_ALPHA, new TextureEntry("upper_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HEAD_ALPHA, new TextureEntry("head_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_EYES_ALPHA, new TextureEntry("eyes_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + addEntry(TEX_HAIR_ALPHA, new TextureEntry("hair_alpha", true, BAKED_NUM_INDICES, "UIImgDefaultAlphaUUID", LLWearableType::WT_ALPHA)); + + addEntry(TEX_HEAD_TATTOO, new TextureEntry("head_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_TATTOO)); + + addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new TextureEntry("head_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new TextureEntry("upper_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new TextureEntry("lower_universal_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_SKIRT_TATTOO, new TextureEntry("skirt_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_HAIR_TATTOO, new TextureEntry("hair_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_EYES_TATTOO, new TextureEntry("eyes_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LEFT_ARM_TATTOO, new TextureEntry("leftarm_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_LEFT_LEG_TATTOO, new TextureEntry("leftleg_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX1_TATTOO, new TextureEntry("aux1_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX2_TATTOO, new TextureEntry("aux2_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + addEntry(TEX_AUX3_TATTOO, new TextureEntry("aux3_tattoo", true, BAKED_NUM_INDICES, "", LLWearableType::WT_UNIVERSAL)); + + + addEntry(TEX_HEAD_BAKED, new TextureEntry("head-baked", false, BAKED_HEAD, "head")); + addEntry(TEX_UPPER_BAKED, new TextureEntry("upper-baked", false, BAKED_UPPER, "upper")); + addEntry(TEX_LOWER_BAKED, new TextureEntry("lower-baked", false, BAKED_LOWER, "lower")); + addEntry(TEX_EYES_BAKED, new TextureEntry("eyes-baked", false, BAKED_EYES, "eyes")); + addEntry(TEX_HAIR_BAKED, new TextureEntry("hair-baked", false, BAKED_HAIR, "hair")); + addEntry(TEX_SKIRT_BAKED, new TextureEntry("skirt-baked", false, BAKED_SKIRT, "skirt")); + addEntry(TEX_LEFT_ARM_BAKED, new TextureEntry("leftarm-baked", false, BAKED_LEFT_ARM, "leftarm")); + addEntry(TEX_LEFT_LEG_BAKED, new TextureEntry("leftleg-baked", false, BAKED_LEFT_LEG, "leftleg")); + addEntry(TEX_AUX1_BAKED, new TextureEntry("aux1-baked", false, BAKED_AUX1, "aux1")); + addEntry(TEX_AUX2_BAKED, new TextureEntry("aux2-baked", false, BAKED_AUX2, "aux2")); + addEntry(TEX_AUX3_BAKED, new TextureEntry("aux3-baked", false, BAKED_AUX3, "aux3")); +} + +LLAvatarAppearanceDictionary::BakedTextures::BakedTextures() +{ + // Baked textures + addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED, + "head", "a4b9dc38-e13b-4df9-b284-751efb0566ff", + 4, TEX_HEAD_BODYPAINT, TEX_HEAD_TATTOO, TEX_HEAD_ALPHA, TEX_HEAD_UNIVERSAL_TATTOO, + 6, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_HAIR, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_UPPER, new BakedEntry(TEX_UPPER_BAKED, + "upper_body", "5943ff64-d26c-4a90-a8c0-d61f56bd98d4", + 8, TEX_UPPER_SHIRT,TEX_UPPER_BODYPAINT, TEX_UPPER_JACKET, + TEX_UPPER_GLOVES, TEX_UPPER_UNDERSHIRT, TEX_UPPER_TATTOO, TEX_UPPER_ALPHA, TEX_UPPER_UNIVERSAL_TATTOO, + 9, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_SHIRT, LLWearableType::WT_JACKET, LLWearableType::WT_GLOVES, LLWearableType::WT_UNDERSHIRT, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_LOWER, new BakedEntry(TEX_LOWER_BAKED, + "lower_body", "2944ee70-90a7-425d-a5fb-d749c782ed7d", + 9, TEX_LOWER_PANTS,TEX_LOWER_BODYPAINT,TEX_LOWER_SHOES, TEX_LOWER_SOCKS, + TEX_LOWER_JACKET, TEX_LOWER_UNDERPANTS, TEX_LOWER_TATTOO, TEX_LOWER_ALPHA, TEX_LOWER_UNIVERSAL_TATTOO, + 10, LLWearableType::WT_SHAPE, LLWearableType::WT_SKIN, LLWearableType::WT_PANTS, LLWearableType::WT_SHOES, LLWearableType::WT_SOCKS, LLWearableType::WT_JACKET, LLWearableType::WT_UNDERPANTS, LLWearableType::WT_TATTOO, LLWearableType::WT_ALPHA, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_EYES, new BakedEntry(TEX_EYES_BAKED, + "eyes", "27b1bc0f-979f-4b13-95fe-b981c2ba9788", + 3, TEX_EYES_IRIS, TEX_EYES_TATTOO, TEX_EYES_ALPHA, + 3, LLWearableType::WT_EYES, LLWearableType::WT_UNIVERSAL, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_SKIRT, new BakedEntry(TEX_SKIRT_BAKED, + "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63", + 2, TEX_SKIRT, TEX_SKIRT_TATTOO, + 2, LLWearableType::WT_SKIRT, LLWearableType::WT_UNIVERSAL )); + + addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED, + "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61", + 3, TEX_HAIR, TEX_HAIR_TATTOO, TEX_HAIR_ALPHA, + 3, LLWearableType::WT_HAIR, LLWearableType::WT_UNIVERSAL, LLWearableType::WT_ALPHA)); + + addEntry(BAKED_LEFT_ARM, new BakedEntry(TEX_LEFT_ARM_BAKED, + "leftarm", "9f39febf-22d7-0087-79d1-e9e8c6c9ed19", + 1, TEX_LEFT_ARM_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_LEFT_LEG, new BakedEntry(TEX_LEFT_LEG_BAKED, + "leftleg", "054a7a58-8ed5-6386-0add-3b636fb28b78", + 1, TEX_LEFT_LEG_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_AUX1, new BakedEntry(TEX_AUX1_BAKED, + "aux1", "790c11be-b25c-c17e-b4d2-6a4ad786b752", + 1, TEX_AUX1_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_AUX2, new BakedEntry(TEX_AUX2_BAKED, + "aux2", "d78c478f-48c7-5928-5864-8d99fb1f521e", + 1, TEX_AUX2_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); + + addEntry(BAKED_AUX3, new BakedEntry(TEX_AUX3_BAKED, + "aux3", "6a95dd53-edd9-aac8-f6d3-27ed99f3c3eb", + 1, TEX_AUX3_TATTOO, + 1, LLWearableType::WT_UNIVERSAL)); +} + +LLAvatarAppearanceDictionary::MeshEntries::MeshEntries() +{ + // MeshEntries + addEntry(MESH_ID_HAIR, new MeshEntry(BAKED_HAIR, "hairMesh", 6, PN_4)); + addEntry(MESH_ID_HEAD, new MeshEntry(BAKED_HEAD, "headMesh", 5, PN_5)); + addEntry(MESH_ID_EYELASH, new MeshEntry(BAKED_HEAD, "eyelashMesh", 1, PN_0)); // no baked mesh associated currently + addEntry(MESH_ID_UPPER_BODY, new MeshEntry(BAKED_UPPER, "upperBodyMesh", 5, PN_1)); + addEntry(MESH_ID_LOWER_BODY, new MeshEntry(BAKED_LOWER, "lowerBodyMesh", 5, PN_2)); + addEntry(MESH_ID_EYEBALL_LEFT, new MeshEntry(BAKED_EYES, "eyeBallLeftMesh", 2, PN_3)); + addEntry(MESH_ID_EYEBALL_RIGHT, new MeshEntry(BAKED_EYES, "eyeBallRightMesh", 2, PN_3)); + addEntry(MESH_ID_SKIRT, new MeshEntry(BAKED_SKIRT, "skirtMesh", 5, PN_5)); +} + +/* + * + *********************************************************************************/ + +LLAvatarAppearanceDictionary::LLAvatarAppearanceDictionary() +{ + createAssociations(); +} + +//virtual +LLAvatarAppearanceDictionary::~LLAvatarAppearanceDictionary() +{ +} + +// Baked textures are composites of textures; for each such composited texture, +// map it to the baked texture. +void LLAvatarAppearanceDictionary::createAssociations() +{ + for (BakedTextures::value_type& baked_pair : mBakedTextures) + { + const EBakedTextureIndex baked_index = baked_pair.first; + const BakedEntry *dict = baked_pair.second; + + // For each texture that this baked texture index affects, associate those textures + // with this baked texture index. + for (const ETextureIndex local_texture_index : dict->mLocalTextures) + { + mTextures[local_texture_index]->mIsUsedByBakedTexture = true; + mTextures[local_texture_index]->mBakedTextureIndex = baked_index; + } + } + +} + +LLAvatarAppearanceDictionary::TextureEntry::TextureEntry(const std::string &name, + bool is_local_texture, + EBakedTextureIndex baked_texture_index, + const std::string &default_image_name, + LLWearableType::EType wearable_type) : + LLDictionaryEntry(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) +{ +} + +LLAvatarAppearanceDictionary::MeshEntry::MeshEntry(EBakedTextureIndex baked_index, + const std::string &name, + U8 level, + LLJointPickName pick) : + LLDictionaryEntry(name), + mBakedID(baked_index), + mLOD(level), + mPickName(pick) +{ +} +LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index, + const std::string &name, + const std::string &hash_name, + U32 num_local_textures, + ... ) : + LLDictionaryEntry(name), + mWearablesHashID(LLUUID(hash_name)), + mTextureIndex(tex_index) +{ + va_list argp; + + va_start(argp, num_local_textures); + + // Read in local textures + for (U8 i=0; i < num_local_textures; i++) + { + ETextureIndex t = (ETextureIndex)va_arg(argp,int); + mLocalTextures.push_back(t); + } + + // Read in number of wearables + const U32 num_wearables = (U32)va_arg(argp,int); + // Read in wearables + for (U8 i=0; i < num_wearables; i++) + { + LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int); + mWearables.push_back(t); + } +} + +ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) const +{ + return getBakedTexture(index)->mTextureIndex; +} + +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) +{ + U8 index = 0; + while (index < BAKED_NUM_INDICES) + { + const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index); + if (be && be->mName.compare(name) == 0) + { + // baked texture found + return (EBakedTextureIndex) index; + } + index++; + } + // baked texture could not be found + return BAKED_NUM_INDICES; +} + +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name) +{ + U8 index = 0; + while (index < BAKED_NUM_INDICES) + { + const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index); + if (be) + { + const TextureEntry *te = getTexture(be->mTextureIndex); + if (te && te->mDefaultImageName.compare(name) == 0) + { + // baked texture found + return (EBakedTextureIndex) index; + } + } + index++; + } + // baked texture could not be found + return BAKED_NUM_INDICES; +} + +LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) const +{ + return getTexture(index)->mWearableType; +} + +// static +bool LLAvatarAppearanceDictionary::isBakedImageId(const LLUUID& id) +{ + if ((id == IMG_USE_BAKED_EYES) || (id == IMG_USE_BAKED_HAIR) || (id == IMG_USE_BAKED_HEAD) || (id == IMG_USE_BAKED_LOWER) || (id == IMG_USE_BAKED_SKIRT) || (id == IMG_USE_BAKED_UPPER) + || (id == IMG_USE_BAKED_LEFTARM) || (id == IMG_USE_BAKED_LEFTLEG) || (id == IMG_USE_BAKED_AUX1) || (id == IMG_USE_BAKED_AUX2) || (id == IMG_USE_BAKED_AUX3) ) + { + return true; + } + + return false; +} + +// static +EBakedTextureIndex LLAvatarAppearanceDictionary::assetIdToBakedTextureIndex(const LLUUID& id) +{ + if (id == IMG_USE_BAKED_EYES) + { + return BAKED_EYES; + } + else if (id == IMG_USE_BAKED_HAIR) + { + return BAKED_HAIR; + } + else if (id == IMG_USE_BAKED_HEAD) + { + return BAKED_HEAD; + } + else if (id == IMG_USE_BAKED_LOWER) + { + return BAKED_LOWER; + } + else if (id == IMG_USE_BAKED_SKIRT) + { + return BAKED_SKIRT; + } + else if (id == IMG_USE_BAKED_UPPER) + { + return BAKED_UPPER; + } + else if (id == IMG_USE_BAKED_LEFTARM) + { + return BAKED_LEFT_ARM; + } + else if (id == IMG_USE_BAKED_LEFTLEG) + { + return BAKED_LEFT_LEG; + } + else if (id == IMG_USE_BAKED_AUX1) + { + return BAKED_AUX1; + } + else if (id == IMG_USE_BAKED_AUX2) + { + return BAKED_AUX2; + } + else if (id == IMG_USE_BAKED_AUX3) + { + return BAKED_AUX3; + } + + return BAKED_NUM_INDICES; +} + +//static +LLUUID LLAvatarAppearanceDictionary::localTextureIndexToMagicId(ETextureIndex t) +{ + LLUUID id = LLUUID::null; + + switch (t) + { + case LLAvatarAppearanceDefines::TEX_HEAD_BAKED: + id = IMG_USE_BAKED_HEAD; + break; + case LLAvatarAppearanceDefines::TEX_UPPER_BAKED: + id = IMG_USE_BAKED_UPPER; + break; + case LLAvatarAppearanceDefines::TEX_LOWER_BAKED: + id = IMG_USE_BAKED_LOWER; + break; + case LLAvatarAppearanceDefines::TEX_EYES_BAKED: + id = IMG_USE_BAKED_EYES; + break; + case LLAvatarAppearanceDefines::TEX_SKIRT_BAKED: + id = IMG_USE_BAKED_SKIRT; + break; + case LLAvatarAppearanceDefines::TEX_HAIR_BAKED: + id = IMG_USE_BAKED_HAIR; + break; + case LLAvatarAppearanceDefines::TEX_LEFT_ARM_BAKED: + id = IMG_USE_BAKED_LEFTARM; + break; + case LLAvatarAppearanceDefines::TEX_LEFT_LEG_BAKED: + id = IMG_USE_BAKED_LEFTLEG; + break; + case LLAvatarAppearanceDefines::TEX_AUX1_BAKED: + id = IMG_USE_BAKED_AUX1; + break; + case LLAvatarAppearanceDefines::TEX_AUX2_BAKED: + id = IMG_USE_BAKED_AUX2; + break; + case LLAvatarAppearanceDefines::TEX_AUX3_BAKED: + id = IMG_USE_BAKED_AUX3; + break; + default: + break; + } + + return id; +} diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index d87b87a939..50a72a45a5 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -1,255 +1,255 @@ -/** - * @file llavatarappearancedefines.h - * @brief Various LLAvatarAppearance related definitions - * LLViewerObject - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_AVATARAPPEARANCE_DEFINES_H -#define LL_AVATARAPPEARANCE_DEFINES_H - -#include -#include "lljointpickname.h" -#include "lldictionary.h" -#include "llwearabletype.h" -#include "lluuid.h" - -namespace LLAvatarAppearanceDefines -{ - -extern const S32 SCRATCH_TEX_WIDTH; -extern const S32 SCRATCH_TEX_HEIGHT; - -static constexpr U32 AVATAR_HOVER = 11001; - -//-------------------------------------------------------------------- -// Enums -//-------------------------------------------------------------------- -enum ETextureIndex -{ - TEX_INVALID = -1, - 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_LOWER_ALPHA, - TEX_UPPER_ALPHA, - TEX_HEAD_ALPHA, - TEX_EYES_ALPHA, - TEX_HAIR_ALPHA, - TEX_HEAD_TATTOO, - TEX_UPPER_TATTOO, - TEX_LOWER_TATTOO, - TEX_HEAD_UNIVERSAL_TATTOO, - TEX_UPPER_UNIVERSAL_TATTOO, - TEX_LOWER_UNIVERSAL_TATTOO, - TEX_SKIRT_TATTOO, - TEX_HAIR_TATTOO, - TEX_EYES_TATTOO, - TEX_LEFT_ARM_TATTOO, - TEX_LEFT_LEG_TATTOO, - TEX_AUX1_TATTOO, - TEX_AUX2_TATTOO, - TEX_AUX3_TATTOO, - TEX_LEFT_ARM_BAKED, // Pre-composited - TEX_LEFT_LEG_BAKED, // Pre-composited - TEX_AUX1_BAKED, // Pre-composited - TEX_AUX2_BAKED, // Pre-composited - TEX_AUX3_BAKED, // Pre-composited - TEX_NUM_INDICES -}; - -enum EBakedTextureIndex -{ - BAKED_HEAD = 0, - BAKED_UPPER, - BAKED_LOWER, - BAKED_EYES, - BAKED_SKIRT, - BAKED_HAIR, - BAKED_LEFT_ARM, - BAKED_LEFT_LEG, - BAKED_AUX1, - BAKED_AUX2, - BAKED_AUX3, - BAKED_NUM_INDICES -}; - -// 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 -}; - -//-------------------------------------------------------------------- -// Vector Types -//-------------------------------------------------------------------- -typedef std::vector texture_vec_t; -typedef std::vector bakedtexture_vec_t; -typedef std::vector mesh_vec_t; -typedef std::vector wearables_vec_t; - -//------------------------------------------------------------------------ -// LLAvatarAppearanceDictionary -// -// 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 LLAvatarAppearanceDictionary -{ - //-------------------------------------------------------------------- - // Constructors and Destructors - //-------------------------------------------------------------------- -public: - LLAvatarAppearanceDictionary(); - ~LLAvatarAppearanceDictionary(); -private: - void createAssociations(); - - //-------------------------------------------------------------------- - // Local and baked textures - //-------------------------------------------------------------------- -public: - struct TextureEntry : public LLDictionaryEntry - { - TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml - bool is_local_texture, - EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, - const std::string& default_image_name = "", - LLWearableType::EType wearable_type = LLWearableType::WT_INVALID); - const std::string mDefaultImageName; - const LLWearableType::EType 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 Textures : public LLDictionary - { - Textures(); - } mTextures; - const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); } - const Textures& getTextures() const { return mTextures; } - - //-------------------------------------------------------------------- - // Meshes - //-------------------------------------------------------------------- -public: - struct MeshEntry : public LLDictionaryEntry - { - MeshEntry(EBakedTextureIndex baked_index, - const std::string &name, // names of mesh types as they are used in avatar_lad.xml - U8 level, - LLJointPickName pick); - // 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 LLJointPickName mPickName; - }; - - struct MeshEntries : public LLDictionary - { - MeshEntries(); - } mMeshEntries; - const MeshEntry* getMeshEntry(EMeshIndex index) const { return mMeshEntries.lookup(index); } - const MeshEntries& getMeshEntries() const { return mMeshEntries; } - - //-------------------------------------------------------------------- - // Baked Textures - //-------------------------------------------------------------------- -public: - struct BakedEntry : public LLDictionaryEntry - { - BakedEntry(ETextureIndex tex_index, - const std::string &name, // unused, but necessary for templating. - const std::string &hash_name, - U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list - // Local Textures - const ETextureIndex mTextureIndex; - texture_vec_t mLocalTextures; - // Wearables - const LLUUID mWearablesHashID; - wearables_vec_t mWearables; - }; - - struct BakedTextures: public LLDictionary - { - BakedTextures(); - } mBakedTextures; - const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); } - const BakedTextures& getBakedTextures() const { return mBakedTextures; } - - //-------------------------------------------------------------------- - // Convenience Functions - //-------------------------------------------------------------------- -public: - // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED - ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t) const; - - // find a baked texture index based on its name - EBakedTextureIndex findBakedByRegionName(std::string name); - EBakedTextureIndex findBakedByImageName(std::string name); - - // Given a texture entry, determine which wearable type owns it. - LLWearableType::EType getTEWearableType(ETextureIndex index) const; - - static bool isBakedImageId(const LLUUID& id); - static EBakedTextureIndex assetIdToBakedTextureIndex(const LLUUID& id); - static LLUUID localTextureIndexToMagicId(ETextureIndex t); - -}; // End LLAvatarAppearanceDictionary - -} // End namespace LLAvatarAppearanceDefines - -#endif //LL_AVATARAPPEARANCE_DEFINES_H +/** + * @file llavatarappearancedefines.h + * @brief Various LLAvatarAppearance related definitions + * LLViewerObject + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_AVATARAPPEARANCE_DEFINES_H +#define LL_AVATARAPPEARANCE_DEFINES_H + +#include +#include "lljointpickname.h" +#include "lldictionary.h" +#include "llwearabletype.h" +#include "lluuid.h" + +namespace LLAvatarAppearanceDefines +{ + +extern const S32 SCRATCH_TEX_WIDTH; +extern const S32 SCRATCH_TEX_HEIGHT; + +static constexpr U32 AVATAR_HOVER = 11001; + +//-------------------------------------------------------------------- +// Enums +//-------------------------------------------------------------------- +enum ETextureIndex +{ + TEX_INVALID = -1, + 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_LOWER_ALPHA, + TEX_UPPER_ALPHA, + TEX_HEAD_ALPHA, + TEX_EYES_ALPHA, + TEX_HAIR_ALPHA, + TEX_HEAD_TATTOO, + TEX_UPPER_TATTOO, + TEX_LOWER_TATTOO, + TEX_HEAD_UNIVERSAL_TATTOO, + TEX_UPPER_UNIVERSAL_TATTOO, + TEX_LOWER_UNIVERSAL_TATTOO, + TEX_SKIRT_TATTOO, + TEX_HAIR_TATTOO, + TEX_EYES_TATTOO, + TEX_LEFT_ARM_TATTOO, + TEX_LEFT_LEG_TATTOO, + TEX_AUX1_TATTOO, + TEX_AUX2_TATTOO, + TEX_AUX3_TATTOO, + TEX_LEFT_ARM_BAKED, // Pre-composited + TEX_LEFT_LEG_BAKED, // Pre-composited + TEX_AUX1_BAKED, // Pre-composited + TEX_AUX2_BAKED, // Pre-composited + TEX_AUX3_BAKED, // Pre-composited + TEX_NUM_INDICES +}; + +enum EBakedTextureIndex +{ + BAKED_HEAD = 0, + BAKED_UPPER, + BAKED_LOWER, + BAKED_EYES, + BAKED_SKIRT, + BAKED_HAIR, + BAKED_LEFT_ARM, + BAKED_LEFT_LEG, + BAKED_AUX1, + BAKED_AUX2, + BAKED_AUX3, + BAKED_NUM_INDICES +}; + +// 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 +}; + +//-------------------------------------------------------------------- +// Vector Types +//-------------------------------------------------------------------- +typedef std::vector texture_vec_t; +typedef std::vector bakedtexture_vec_t; +typedef std::vector mesh_vec_t; +typedef std::vector wearables_vec_t; + +//------------------------------------------------------------------------ +// LLAvatarAppearanceDictionary +// +// 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 LLAvatarAppearanceDictionary +{ + //-------------------------------------------------------------------- + // Constructors and Destructors + //-------------------------------------------------------------------- +public: + LLAvatarAppearanceDictionary(); + ~LLAvatarAppearanceDictionary(); +private: + void createAssociations(); + + //-------------------------------------------------------------------- + // Local and baked textures + //-------------------------------------------------------------------- +public: + struct TextureEntry : public LLDictionaryEntry + { + TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml + bool is_local_texture, + EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES, + const std::string& default_image_name = "", + LLWearableType::EType wearable_type = LLWearableType::WT_INVALID); + const std::string mDefaultImageName; + const LLWearableType::EType 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 Textures : public LLDictionary + { + Textures(); + } mTextures; + const TextureEntry* getTexture(ETextureIndex index) const { return mTextures.lookup(index); } + const Textures& getTextures() const { return mTextures; } + + //-------------------------------------------------------------------- + // Meshes + //-------------------------------------------------------------------- +public: + struct MeshEntry : public LLDictionaryEntry + { + MeshEntry(EBakedTextureIndex baked_index, + const std::string &name, // names of mesh types as they are used in avatar_lad.xml + U8 level, + LLJointPickName pick); + // 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 LLJointPickName mPickName; + }; + + struct MeshEntries : public LLDictionary + { + MeshEntries(); + } mMeshEntries; + const MeshEntry* getMeshEntry(EMeshIndex index) const { return mMeshEntries.lookup(index); } + const MeshEntries& getMeshEntries() const { return mMeshEntries; } + + //-------------------------------------------------------------------- + // Baked Textures + //-------------------------------------------------------------------- +public: + struct BakedEntry : public LLDictionaryEntry + { + BakedEntry(ETextureIndex tex_index, + const std::string &name, // unused, but necessary for templating. + const std::string &hash_name, + U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list + // Local Textures + const ETextureIndex mTextureIndex; + texture_vec_t mLocalTextures; + // Wearables + const LLUUID mWearablesHashID; + wearables_vec_t mWearables; + }; + + struct BakedTextures: public LLDictionary + { + BakedTextures(); + } mBakedTextures; + const BakedEntry* getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); } + const BakedTextures& getBakedTextures() const { return mBakedTextures; } + + //-------------------------------------------------------------------- + // Convenience Functions + //-------------------------------------------------------------------- +public: + // Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED + ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t) const; + + // find a baked texture index based on its name + EBakedTextureIndex findBakedByRegionName(std::string name); + EBakedTextureIndex findBakedByImageName(std::string name); + + // Given a texture entry, determine which wearable type owns it. + LLWearableType::EType getTEWearableType(ETextureIndex index) const; + + static bool isBakedImageId(const LLUUID& id); + static EBakedTextureIndex assetIdToBakedTextureIndex(const LLUUID& id); + static LLUUID localTextureIndexToMagicId(ETextureIndex t); + +}; // End LLAvatarAppearanceDictionary + +} // End namespace LLAvatarAppearanceDefines + +#endif //LL_AVATARAPPEARANCE_DEFINES_H diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp index a3bbcf1ad3..2aa6cb63e1 100644 --- a/indra/llappearance/llavatarjoint.cpp +++ b/indra/llappearance/llavatarjoint.cpp @@ -1,316 +1,316 @@ -/** - * @file llavatarjoint.cpp - * @brief Implementation of LLAvatarJoint class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "llavatarjoint.h" - -#include "llgl.h" -#include "llrender.h" -#include "llmath.h" -#include "llglheaders.h" -#include "llavatarappearance.h" - -const F32 DEFAULT_AVATAR_JOINT_LOD = 0.0f; - -//----------------------------------------------------------------------------- -// Static Data -//----------------------------------------------------------------------------- -bool LLAvatarJoint::sDisableLOD = false; - -//----------------------------------------------------------------------------- -// LLAvatarJoint() -// Class Constructors -//----------------------------------------------------------------------------- -LLAvatarJoint::LLAvatarJoint() : - LLJoint() -{ - init(); -} - -LLAvatarJoint::LLAvatarJoint(S32 joint_num) : - LLJoint(joint_num) -{ - init(); -} - -LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) : - LLJoint(name, parent) -{ - init(); -} - -void LLAvatarJoint::init() -{ - mValid = false; - mComponents = SC_JOINT | SC_BONE | SC_AXES; - mMinPixelArea = DEFAULT_AVATAR_JOINT_LOD; - mPickName = PN_DEFAULT; - mVisible = true; - mMeshID = 0; - mIsTransparent = false; -} - - -//----------------------------------------------------------------------------- -// ~LLAvatarJoint() -// Class Destructor -//----------------------------------------------------------------------------- -LLAvatarJoint::~LLAvatarJoint() -{ -} - - -//-------------------------------------------------------------------- -// setValid() -//-------------------------------------------------------------------- -void LLAvatarJoint::setValid( bool valid, bool recursive ) -{ - //---------------------------------------------------------------- - // set visibility for this joint - //---------------------------------------------------------------- - mValid = valid; - - //---------------------------------------------------------------- - // set visibility for children - //---------------------------------------------------------------- - if (recursive) - { - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->setValid(valid, true); - } - } - -} - -//-------------------------------------------------------------------- -// setSkeletonComponents() -//-------------------------------------------------------------------- -void LLAvatarJoint::setSkeletonComponents( U32 comp, bool recursive ) -{ - mComponents = comp; - if (recursive) - { - for (auto child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->setSkeletonComponents(comp, recursive); - } - } -} - -void LLAvatarJoint::setVisible(bool visible, bool recursive) -{ - mVisible = visible; - - if (recursive) - { - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->setVisible(visible, recursive); - } - } -} - -void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) -{ - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->updateFaceSizes(num_vertices, num_indices, pixel_area); - } -} - -void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, bool damp_wind, bool terse_update) -{ - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->updateFaceData(face, pixel_area, damp_wind, terse_update); - } -} - -void LLAvatarJoint::updateJointGeometry() -{ - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->updateJointGeometry(); - } -} - - -bool LLAvatarJoint::updateLOD(F32 pixel_area, bool activate) -{ - bool lod_changed = false; - bool found_lod = false; - - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - F32 jointLOD = joint->getLOD(); - - if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) - { - // we've already found a joint to enable, so enable the rest as alternatives - lod_changed |= joint->updateLOD(pixel_area, true); - } - else - { - if (pixel_area >= jointLOD || sDisableLOD) - { - lod_changed |= joint->updateLOD(pixel_area, true); - found_lod = true; - } - else - { - lod_changed |= joint->updateLOD(pixel_area, false); - } - } - } - return lod_changed; -} - -void LLAvatarJoint::dump() -{ - for (LLJoint* child : mChildren) - { - LLAvatarJoint* joint = static_cast(child); - joint->dump(); - } -} - - -void LLAvatarJoint::setMeshesToChildren() -{ - removeAllChildren(); - for (LLAvatarJointMesh* mesh : mMeshParts) - { - addChild(mesh); - } -} -//----------------------------------------------------------------------------- -// LLAvatarJointCollisionVolume() -//----------------------------------------------------------------------------- - -LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume() -{ - mUpdateXform = false; -} - -/*virtual*/ -U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, bool first_pass, bool is_dummy ) -{ - LL_ERRS() << "Cannot call render() on LLAvatarJointCollisionVolume" << LL_ENDL; - return 0; -} - -LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset) -{ - mUpdateXform = true; - - LLVector3 result = offset; - result.scaleVec(getScale()); - result.rotVec(getWorldRotation()); - result += getWorldPosition(); - - return result; -} - -void LLAvatarJointCollisionVolume::renderCollision() -{ - updateWorldMatrix(); - - gGL.pushMatrix(); - gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] ); - - gGL.diffuseColor3f( 0.f, 0.f, 1.f ); - - gGL.begin(LLRender::LINES); - - LLVector3 v[] = - { - LLVector3(1,0,0), - LLVector3(-1,0,0), - LLVector3(0,1,0), - LLVector3(0,-1,0), - - LLVector3(0,0,-1), - LLVector3(0,0,1), - }; - - //sides - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[2].mV); - - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[3].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[2].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[3].mV); - - - //top - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[4].mV); - - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[4].mV); - - - //bottom - gGL.vertex3fv(v[0].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[1].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[2].mV); - gGL.vertex3fv(v[5].mV); - - gGL.vertex3fv(v[3].mV); - gGL.vertex3fv(v[5].mV); - - gGL.end(); - - gGL.popMatrix(); -} - - -// End +/** + * @file llavatarjoint.cpp + * @brief Implementation of LLAvatarJoint class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llavatarjoint.h" + +#include "llgl.h" +#include "llrender.h" +#include "llmath.h" +#include "llglheaders.h" +#include "llavatarappearance.h" + +const F32 DEFAULT_AVATAR_JOINT_LOD = 0.0f; + +//----------------------------------------------------------------------------- +// Static Data +//----------------------------------------------------------------------------- +bool LLAvatarJoint::sDisableLOD = false; + +//----------------------------------------------------------------------------- +// LLAvatarJoint() +// Class Constructors +//----------------------------------------------------------------------------- +LLAvatarJoint::LLAvatarJoint() : + LLJoint() +{ + init(); +} + +LLAvatarJoint::LLAvatarJoint(S32 joint_num) : + LLJoint(joint_num) +{ + init(); +} + +LLAvatarJoint::LLAvatarJoint(const std::string &name, LLJoint *parent) : + LLJoint(name, parent) +{ + init(); +} + +void LLAvatarJoint::init() +{ + mValid = false; + mComponents = SC_JOINT | SC_BONE | SC_AXES; + mMinPixelArea = DEFAULT_AVATAR_JOINT_LOD; + mPickName = PN_DEFAULT; + mVisible = true; + mMeshID = 0; + mIsTransparent = false; +} + + +//----------------------------------------------------------------------------- +// ~LLAvatarJoint() +// Class Destructor +//----------------------------------------------------------------------------- +LLAvatarJoint::~LLAvatarJoint() +{ +} + + +//-------------------------------------------------------------------- +// setValid() +//-------------------------------------------------------------------- +void LLAvatarJoint::setValid( bool valid, bool recursive ) +{ + //---------------------------------------------------------------- + // set visibility for this joint + //---------------------------------------------------------------- + mValid = valid; + + //---------------------------------------------------------------- + // set visibility for children + //---------------------------------------------------------------- + if (recursive) + { + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->setValid(valid, true); + } + } + +} + +//-------------------------------------------------------------------- +// setSkeletonComponents() +//-------------------------------------------------------------------- +void LLAvatarJoint::setSkeletonComponents( U32 comp, bool recursive ) +{ + mComponents = comp; + if (recursive) + { + for (auto child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->setSkeletonComponents(comp, recursive); + } + } +} + +void LLAvatarJoint::setVisible(bool visible, bool recursive) +{ + mVisible = visible; + + if (recursive) + { + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->setVisible(visible, recursive); + } + } +} + +void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) +{ + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->updateFaceSizes(num_vertices, num_indices, pixel_area); + } +} + +void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, bool damp_wind, bool terse_update) +{ + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->updateFaceData(face, pixel_area, damp_wind, terse_update); + } +} + +void LLAvatarJoint::updateJointGeometry() +{ + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->updateJointGeometry(); + } +} + + +bool LLAvatarJoint::updateLOD(F32 pixel_area, bool activate) +{ + bool lod_changed = false; + bool found_lod = false; + + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + F32 jointLOD = joint->getLOD(); + + if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD) + { + // we've already found a joint to enable, so enable the rest as alternatives + lod_changed |= joint->updateLOD(pixel_area, true); + } + else + { + if (pixel_area >= jointLOD || sDisableLOD) + { + lod_changed |= joint->updateLOD(pixel_area, true); + found_lod = true; + } + else + { + lod_changed |= joint->updateLOD(pixel_area, false); + } + } + } + return lod_changed; +} + +void LLAvatarJoint::dump() +{ + for (LLJoint* child : mChildren) + { + LLAvatarJoint* joint = static_cast(child); + joint->dump(); + } +} + + +void LLAvatarJoint::setMeshesToChildren() +{ + removeAllChildren(); + for (LLAvatarJointMesh* mesh : mMeshParts) + { + addChild(mesh); + } +} +//----------------------------------------------------------------------------- +// LLAvatarJointCollisionVolume() +//----------------------------------------------------------------------------- + +LLAvatarJointCollisionVolume::LLAvatarJointCollisionVolume() +{ + mUpdateXform = false; +} + +/*virtual*/ +U32 LLAvatarJointCollisionVolume::render( F32 pixelArea, bool first_pass, bool is_dummy ) +{ + LL_ERRS() << "Cannot call render() on LLAvatarJointCollisionVolume" << LL_ENDL; + return 0; +} + +LLVector3 LLAvatarJointCollisionVolume::getVolumePos(LLVector3 &offset) +{ + mUpdateXform = true; + + LLVector3 result = offset; + result.scaleVec(getScale()); + result.rotVec(getWorldRotation()); + result += getWorldPosition(); + + return result; +} + +void LLAvatarJointCollisionVolume::renderCollision() +{ + updateWorldMatrix(); + + gGL.pushMatrix(); + gGL.multMatrix( &mXform.getWorldMatrix().mMatrix[0][0] ); + + gGL.diffuseColor3f( 0.f, 0.f, 1.f ); + + gGL.begin(LLRender::LINES); + + LLVector3 v[] = + { + LLVector3(1,0,0), + LLVector3(-1,0,0), + LLVector3(0,1,0), + LLVector3(0,-1,0), + + LLVector3(0,0,-1), + LLVector3(0,0,1), + }; + + //sides + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[2].mV); + + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[3].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[2].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[3].mV); + + + //top + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[4].mV); + + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[4].mV); + + + //bottom + gGL.vertex3fv(v[0].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[1].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[2].mV); + gGL.vertex3fv(v[5].mV); + + gGL.vertex3fv(v[3].mV); + gGL.vertex3fv(v[5].mV); + + gGL.end(); + + gGL.popMatrix(); +} + + +// End diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index c3f181e4f8..13f025fd5f 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -1,140 +1,140 @@ -/** - * @file llavatarjoint.h - * @brief Implementation of LLAvatarJoint class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLAVATARJOINT_H -#define LL_LLAVATARJOINT_H - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "lljoint.h" -#include "lljointpickname.h" - -class LLFace; -class LLAvatarJointMesh; - -extern const F32 DEFAULT_AVATAR_JOINT_LOD; - -//----------------------------------------------------------------------------- -// class LLViewerJoint -//----------------------------------------------------------------------------- -class LLAvatarJoint : - public LLJoint -{ -public: - LLAvatarJoint(); - LLAvatarJoint(S32 joint_num); - // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* - LLAvatarJoint(const std::string &name, LLJoint *parent = NULL); - virtual ~LLAvatarJoint(); - - // Gets the validity of this joint - bool getValid() { return mValid; } - - // Sets the validity of this joint - virtual void setValid( bool valid, bool recursive=false ); - - // Returns true if this object is transparent. - // This is used to determine in which order to draw objects. - virtual bool isTransparent() { return mIsTransparent; } - - // Returns true if this object should inherit scale modifiers from its immediate parent - virtual bool inheritScale() { return false; } - - enum Components - { - SC_BONE = 1, - SC_JOINT = 2, - SC_AXES = 4 - }; - - // Selects which skeleton components to draw - void setSkeletonComponents( U32 comp, bool recursive = true ); - - // Returns which skeleton components are enables for drawing - U32 getSkeletonComponents() { return mComponents; } - - // Sets the level of detail for this node as a minimum - // pixel area threshold. If the current pixel area for this - // object is less than the specified threshold, the node is - // not traversed. In addition, if a value is specified (not - // default of 0.0), and the pixel area is larger than the - // specified minimum, the node is rendered, but no other siblings - // of this node under the same parent will be. - F32 getLOD() { return mMinPixelArea; } - void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } - - void setPickName(LLJointPickName name) { mPickName = name; } - LLJointPickName getPickName() { return mPickName; } - - void setVisible( bool visible, bool recursive ); - - // Takes meshes in mMeshParts and sets each one as a child joint - void setMeshesToChildren(); - - // LLViewerJoint interface - virtual U32 render( F32 pixelArea, bool first_pass = true, bool is_dummy = false ) = 0; - virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); - virtual void updateFaceData(LLFace *face, F32 pixel_area, bool damp_wind = false, bool terse_update = false); - virtual bool updateLOD(F32 pixel_area, bool activate); - virtual void updateJointGeometry(); - virtual void dump(); - - -public: - static bool sDisableLOD; - avatar_joint_mesh_list_t mMeshParts; //LLViewerJointMesh* - void setMeshID( S32 id ) {mMeshID = id;} - -protected: - void init(); - - bool mValid; - bool mIsTransparent; - U32 mComponents; - F32 mMinPixelArea; - LLJointPickName mPickName; - bool mVisible; - S32 mMeshID; -}; - -class LLAvatarJointCollisionVolume : public LLAvatarJoint -{ -public: - LLAvatarJointCollisionVolume(); - virtual ~LLAvatarJointCollisionVolume() {}; - - /*virtual*/ bool inheritScale() { return true; } - /*virtual*/ U32 render( F32 pixelArea, bool first_pass = true, bool is_dummy = false ); - - void renderCollision(); - - LLVector3 getVolumePos(LLVector3 &offset); -}; - -#endif // LL_LLAVATARJOINT_H - - +/** + * @file llavatarjoint.h + * @brief Implementation of LLAvatarJoint class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAVATARJOINT_H +#define LL_LLAVATARJOINT_H + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "lljoint.h" +#include "lljointpickname.h" + +class LLFace; +class LLAvatarJointMesh; + +extern const F32 DEFAULT_AVATAR_JOINT_LOD; + +//----------------------------------------------------------------------------- +// class LLViewerJoint +//----------------------------------------------------------------------------- +class LLAvatarJoint : + public LLJoint +{ +public: + LLAvatarJoint(); + LLAvatarJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* + LLAvatarJoint(const std::string &name, LLJoint *parent = NULL); + virtual ~LLAvatarJoint(); + + // Gets the validity of this joint + bool getValid() { return mValid; } + + // Sets the validity of this joint + virtual void setValid( bool valid, bool recursive=false ); + + // Returns true if this object is transparent. + // This is used to determine in which order to draw objects. + virtual bool isTransparent() { return mIsTransparent; } + + // Returns true if this object should inherit scale modifiers from its immediate parent + virtual bool inheritScale() { return false; } + + enum Components + { + SC_BONE = 1, + SC_JOINT = 2, + SC_AXES = 4 + }; + + // Selects which skeleton components to draw + void setSkeletonComponents( U32 comp, bool recursive = true ); + + // Returns which skeleton components are enables for drawing + U32 getSkeletonComponents() { return mComponents; } + + // Sets the level of detail for this node as a minimum + // pixel area threshold. If the current pixel area for this + // object is less than the specified threshold, the node is + // not traversed. In addition, if a value is specified (not + // default of 0.0), and the pixel area is larger than the + // specified minimum, the node is rendered, but no other siblings + // of this node under the same parent will be. + F32 getLOD() { return mMinPixelArea; } + void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } + + void setPickName(LLJointPickName name) { mPickName = name; } + LLJointPickName getPickName() { return mPickName; } + + void setVisible( bool visible, bool recursive ); + + // Takes meshes in mMeshParts and sets each one as a child joint + void setMeshesToChildren(); + + // LLViewerJoint interface + virtual U32 render( F32 pixelArea, bool first_pass = true, bool is_dummy = false ) = 0; + virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); + virtual void updateFaceData(LLFace *face, F32 pixel_area, bool damp_wind = false, bool terse_update = false); + virtual bool updateLOD(F32 pixel_area, bool activate); + virtual void updateJointGeometry(); + virtual void dump(); + + +public: + static bool sDisableLOD; + avatar_joint_mesh_list_t mMeshParts; //LLViewerJointMesh* + void setMeshID( S32 id ) {mMeshID = id;} + +protected: + void init(); + + bool mValid; + bool mIsTransparent; + U32 mComponents; + F32 mMinPixelArea; + LLJointPickName mPickName; + bool mVisible; + S32 mMeshID; +}; + +class LLAvatarJointCollisionVolume : public LLAvatarJoint +{ +public: + LLAvatarJointCollisionVolume(); + virtual ~LLAvatarJointCollisionVolume() {}; + + /*virtual*/ bool inheritScale() { return true; } + /*virtual*/ U32 render( F32 pixelArea, bool first_pass = true, bool is_dummy = false ); + + void renderCollision(); + + LLVector3 getVolumePos(LLVector3 &offset); +}; + +#endif // LL_LLAVATARJOINT_H + + diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index ebdb14fd42..69a9023994 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -1,390 +1,390 @@ -/** - * @file LLAvatarJointMesh.cpp - * @brief Implementation of LLAvatarJointMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "linden_common.h" -#include "llfasttimer.h" -#include "llrender.h" - -#include "llavatarjointmesh.h" -#include "llavatarappearance.h" -#include "lltexlayer.h" -#include "llmath.h" -#include "v4math.h" -#include "m3math.h" -#include "m4math.h" -#include "llmatrix4a.h" - - -// Utility functions added with Bento to simplify handling of extra -// spine joints, or other new joints internal to the original -// skeleton, and unknown to the system avatar. - -//----------------------------------------------------------------------------- -// getBaseSkeletonAncestor() -//----------------------------------------------------------------------------- -LLAvatarJoint *getBaseSkeletonAncestor(LLAvatarJoint* joint) -{ - LLJoint *ancestor = joint->getParent(); - while (ancestor->getParent() && (ancestor->getSupport() != LLJoint::SUPPORT_BASE)) - { - LL_DEBUGS("Avatar") << "skipping non-base ancestor " << ancestor->getName() << LL_ENDL; - ancestor = ancestor->getParent(); - } - return (LLAvatarJoint*) ancestor; -} - -//----------------------------------------------------------------------------- -// totalSkinOffset() -//----------------------------------------------------------------------------- -LLVector3 totalSkinOffset(LLAvatarJoint *joint) -{ - LLVector3 totalOffset; - while (joint) - { - if (joint->getSupport() == LLJoint::SUPPORT_BASE) - { - totalOffset += joint->getSkinOffset(); - } - joint = (LLAvatarJoint*)joint->getParent(); - } - return totalOffset; -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// LLAvatarJointMesh::LLSkinJoint -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// LLSkinJoint -//----------------------------------------------------------------------------- -LLSkinJoint::LLSkinJoint() -{ - mJoint = NULL; -} - -//----------------------------------------------------------------------------- -// ~LLSkinJoint -//----------------------------------------------------------------------------- -LLSkinJoint::~LLSkinJoint() -{ - mJoint = NULL; -} - - -//----------------------------------------------------------------------------- -// LLSkinJoint::setupSkinJoint() -//----------------------------------------------------------------------------- -bool LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) -{ - // find the named joint - mJoint = joint; - if ( !mJoint ) - { - LL_INFOS() << "Can't find joint" << LL_ENDL; - } - - // compute the inverse root skin matrix - mRootToJointSkinOffset = totalSkinOffset(joint); - mRootToJointSkinOffset = -mRootToJointSkinOffset; - - //mRootToParentJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint->getParent()); - mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor(joint)); - mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset; - - return true; -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// LLAvatarJointMesh -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -bool LLAvatarJointMesh::sPipelineRender = false; -U32 LLAvatarJointMesh::sClothingMaskImageName = 0; -LLColor4 LLAvatarJointMesh::sClothingInnerColor; - -//----------------------------------------------------------------------------- -// LLAvatarJointMesh() -//----------------------------------------------------------------------------- -LLAvatarJointMesh::LLAvatarJointMesh() - : - mTexture( NULL ), - mLayerSet( NULL ), - mTestImageName( 0 ), - mFaceIndexCount(0) -{ - - mColor[0] = 1.0f; - mColor[1] = 1.0f; - mColor[2] = 1.0f; - mColor[3] = 1.0f; - mShiny = 0.0f; - mCullBackFaces = true; - - mMesh = NULL; - - mNumSkinJoints = 0; - mSkinJoints = NULL; - - mFace = NULL; - - mMeshID = 0; - mUpdateXform = false; - - mValid = false; - - mIsTransparent = false; -} - - -//----------------------------------------------------------------------------- -// ~LLAvatarJointMesh() -// Class Destructor -//----------------------------------------------------------------------------- -LLAvatarJointMesh::~LLAvatarJointMesh() -{ - mMesh = NULL; - mTexture = NULL; - freeSkinData(); -} - - -//----------------------------------------------------------------------------- -// LLAvatarJointMesh::allocateSkinData() -//----------------------------------------------------------------------------- -bool LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) -{ - mSkinJoints = new LLSkinJoint[ numSkinJoints ]; - mNumSkinJoints = numSkinJoints; - return true; -} - -//----------------------------------------------------------------------------- -// LLAvatarJointMesh::freeSkinData() -//----------------------------------------------------------------------------- -void LLAvatarJointMesh::freeSkinData() -{ - mNumSkinJoints = 0; - delete [] mSkinJoints; - mSkinJoints = NULL; -} - -//-------------------------------------------------------------------- -// LLAvatarJointMesh::getColor() -//-------------------------------------------------------------------- -void LLAvatarJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ) -{ - *red = mColor[0]; - *green = mColor[1]; - *blue = mColor[2]; - *alpha = mColor[3]; -} - -//-------------------------------------------------------------------- -// LLAvatarJointMesh::setColor() -//-------------------------------------------------------------------- -void LLAvatarJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) -{ - mColor[0] = red; - mColor[1] = green; - mColor[2] = blue; - mColor[3] = alpha; -} - -void LLAvatarJointMesh::setColor( const LLColor4& color ) -{ - mColor = color; -} - - -//-------------------------------------------------------------------- -// LLAvatarJointMesh::getTexture() -//-------------------------------------------------------------------- -//LLViewerTexture *LLAvatarJointMesh::getTexture() -//{ -// return mTexture; -//} - -//-------------------------------------------------------------------- -// LLAvatarJointMesh::setTexture() -//-------------------------------------------------------------------- -void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) -{ - mTexture = texture; - - // texture and dynamic_texture are mutually exclusive - if( texture ) - { - mLayerSet = NULL; - //texture->bindTexture(0); - //texture->setClamp(true, true); - } -} - - -bool LLAvatarJointMesh::hasGLTexture() const -{ - return mTexture.notNull() && mTexture->hasGLTexture(); -} - -//-------------------------------------------------------------------- -// LLAvatarJointMesh::setLayerSet() -// Sets the shape texture (takes precedence over normal texture) -//-------------------------------------------------------------------- -void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set ) -{ - mLayerSet = layer_set; - - // texture and dynamic_texture are mutually exclusive - if( layer_set ) - { - mTexture = NULL; - } -} - -bool LLAvatarJointMesh::hasComposite() const -{ - return (mLayerSet && mLayerSet->hasComposite()); -} - - -//-------------------------------------------------------------------- -// LLAvatarJointMesh::getMesh() -//-------------------------------------------------------------------- -LLPolyMesh *LLAvatarJointMesh::getMesh() -{ - return mMesh; -} - -//----------------------------------------------------------------------------- -// LLAvatarJointMesh::setMesh() -//----------------------------------------------------------------------------- -void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) -{ - // set the mesh pointer - mMesh = mesh; - - // release any existing skin joints - freeSkinData(); - - if ( mMesh == NULL ) - { - return; - } - - // acquire the transform from the mesh object - // SL-315 - setPosition( mMesh->getPosition() ); - setRotation( mMesh->getRotation() ); - setScale( mMesh->getScale() ); - - // create skin joints if necessary - if ( mMesh->hasWeights() && !mMesh->isLOD()) - { - U32 numJointNames = mMesh->getNumJointNames(); - - allocateSkinData( numJointNames ); - std::string *jointNames = mMesh->getJointNames(); - - U32 jn; - for (jn = 0; jn < numJointNames; jn++) - { - //LL_INFOS() << "Setting up joint " << jointNames[jn] << LL_ENDL; - LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) ); - mSkinJoints[jn].setupSkinJoint( joint ); - } - } - - // setup joint array - if (!mMesh->isLOD()) - { - setupJoint((LLAvatarJoint*)getRoot()); - LL_DEBUGS("Avatar") << getName() << " joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL; - } - -} - -//----------------------------------------------------------------------------- -// setupJoint() -//----------------------------------------------------------------------------- -void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) -{ - U32 sj; - - for (sj=0; sjgetName() << " matches skinjoint " << sj << LL_ENDL; - - // is the last joint in the array our parent? - - std::vector &jrd = mMesh->mJointRenderData; - - // SL-287 - need to update this so the results are the same if - // additional extended-skeleton joints lie between this joint - // and the original parent. - LLJoint *ancestor = getBaseSkeletonAncestor(current_joint); - if(jrd.size() && jrd.back()->mWorldMatrix == &ancestor->getWorldMatrix()) - { - // ...then just add ourselves - LLAvatarJoint* jointp = js.mJoint; - jrd.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); - LL_DEBUGS("Avatar") << "add joint[" << (jrd.size()-1) << "] = " << js.mJoint->getName() << LL_ENDL; - } - // otherwise add our ancestor and ourselves - else - { - jrd.push_back(new LLJointRenderData(&ancestor->getWorldMatrix(), NULL)); - LL_DEBUGS("Avatar") << "add2 ancestor joint[" << (jrd.size()-1) << "] = " << ancestor->getName() << LL_ENDL; - jrd.push_back(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); - LL_DEBUGS("Avatar") << "add2 joint[" << (jrd.size()-1) << "] = " << current_joint->getName() << LL_ENDL; - } - } - - // depth-first traversal - for (LLJoint* joint : current_joint->mChildren) - { - LLAvatarJoint* child_joint = (LLAvatarJoint*)joint; - setupJoint(child_joint); - } -} - - -// End +/** + * @file LLAvatarJointMesh.cpp + * @brief Implementation of LLAvatarJointMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" +#include "llfasttimer.h" +#include "llrender.h" + +#include "llavatarjointmesh.h" +#include "llavatarappearance.h" +#include "lltexlayer.h" +#include "llmath.h" +#include "v4math.h" +#include "m3math.h" +#include "m4math.h" +#include "llmatrix4a.h" + + +// Utility functions added with Bento to simplify handling of extra +// spine joints, or other new joints internal to the original +// skeleton, and unknown to the system avatar. + +//----------------------------------------------------------------------------- +// getBaseSkeletonAncestor() +//----------------------------------------------------------------------------- +LLAvatarJoint *getBaseSkeletonAncestor(LLAvatarJoint* joint) +{ + LLJoint *ancestor = joint->getParent(); + while (ancestor->getParent() && (ancestor->getSupport() != LLJoint::SUPPORT_BASE)) + { + LL_DEBUGS("Avatar") << "skipping non-base ancestor " << ancestor->getName() << LL_ENDL; + ancestor = ancestor->getParent(); + } + return (LLAvatarJoint*) ancestor; +} + +//----------------------------------------------------------------------------- +// totalSkinOffset() +//----------------------------------------------------------------------------- +LLVector3 totalSkinOffset(LLAvatarJoint *joint) +{ + LLVector3 totalOffset; + while (joint) + { + if (joint->getSupport() == LLJoint::SUPPORT_BASE) + { + totalOffset += joint->getSkinOffset(); + } + joint = (LLAvatarJoint*)joint->getParent(); + } + return totalOffset; +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::LLSkinJoint +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// LLSkinJoint +//----------------------------------------------------------------------------- +LLSkinJoint::LLSkinJoint() +{ + mJoint = NULL; +} + +//----------------------------------------------------------------------------- +// ~LLSkinJoint +//----------------------------------------------------------------------------- +LLSkinJoint::~LLSkinJoint() +{ + mJoint = NULL; +} + + +//----------------------------------------------------------------------------- +// LLSkinJoint::setupSkinJoint() +//----------------------------------------------------------------------------- +bool LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) +{ + // find the named joint + mJoint = joint; + if ( !mJoint ) + { + LL_INFOS() << "Can't find joint" << LL_ENDL; + } + + // compute the inverse root skin matrix + mRootToJointSkinOffset = totalSkinOffset(joint); + mRootToJointSkinOffset = -mRootToJointSkinOffset; + + //mRootToParentJointSkinOffset = totalSkinOffset((LLAvatarJoint*)joint->getParent()); + mRootToParentJointSkinOffset = totalSkinOffset(getBaseSkeletonAncestor(joint)); + mRootToParentJointSkinOffset = -mRootToParentJointSkinOffset; + + return true; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// LLAvatarJointMesh +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +bool LLAvatarJointMesh::sPipelineRender = false; +U32 LLAvatarJointMesh::sClothingMaskImageName = 0; +LLColor4 LLAvatarJointMesh::sClothingInnerColor; + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh() +//----------------------------------------------------------------------------- +LLAvatarJointMesh::LLAvatarJointMesh() + : + mTexture( NULL ), + mLayerSet( NULL ), + mTestImageName( 0 ), + mFaceIndexCount(0) +{ + + mColor[0] = 1.0f; + mColor[1] = 1.0f; + mColor[2] = 1.0f; + mColor[3] = 1.0f; + mShiny = 0.0f; + mCullBackFaces = true; + + mMesh = NULL; + + mNumSkinJoints = 0; + mSkinJoints = NULL; + + mFace = NULL; + + mMeshID = 0; + mUpdateXform = false; + + mValid = false; + + mIsTransparent = false; +} + + +//----------------------------------------------------------------------------- +// ~LLAvatarJointMesh() +// Class Destructor +//----------------------------------------------------------------------------- +LLAvatarJointMesh::~LLAvatarJointMesh() +{ + mMesh = NULL; + mTexture = NULL; + freeSkinData(); +} + + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::allocateSkinData() +//----------------------------------------------------------------------------- +bool LLAvatarJointMesh::allocateSkinData( U32 numSkinJoints ) +{ + mSkinJoints = new LLSkinJoint[ numSkinJoints ]; + mNumSkinJoints = numSkinJoints; + return true; +} + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::freeSkinData() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::freeSkinData() +{ + mNumSkinJoints = 0; + delete [] mSkinJoints; + mSkinJoints = NULL; +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getColor() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ) +{ + *red = mColor[0]; + *green = mColor[1]; + *blue = mColor[2]; + *alpha = mColor[3]; +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setColor() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setColor( F32 red, F32 green, F32 blue, F32 alpha ) +{ + mColor[0] = red; + mColor[1] = green; + mColor[2] = blue; + mColor[3] = alpha; +} + +void LLAvatarJointMesh::setColor( const LLColor4& color ) +{ + mColor = color; +} + + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getTexture() +//-------------------------------------------------------------------- +//LLViewerTexture *LLAvatarJointMesh::getTexture() +//{ +// return mTexture; +//} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setTexture() +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setTexture( LLGLTexture *texture ) +{ + mTexture = texture; + + // texture and dynamic_texture are mutually exclusive + if( texture ) + { + mLayerSet = NULL; + //texture->bindTexture(0); + //texture->setClamp(true, true); + } +} + + +bool LLAvatarJointMesh::hasGLTexture() const +{ + return mTexture.notNull() && mTexture->hasGLTexture(); +} + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::setLayerSet() +// Sets the shape texture (takes precedence over normal texture) +//-------------------------------------------------------------------- +void LLAvatarJointMesh::setLayerSet( LLTexLayerSet* layer_set ) +{ + mLayerSet = layer_set; + + // texture and dynamic_texture are mutually exclusive + if( layer_set ) + { + mTexture = NULL; + } +} + +bool LLAvatarJointMesh::hasComposite() const +{ + return (mLayerSet && mLayerSet->hasComposite()); +} + + +//-------------------------------------------------------------------- +// LLAvatarJointMesh::getMesh() +//-------------------------------------------------------------------- +LLPolyMesh *LLAvatarJointMesh::getMesh() +{ + return mMesh; +} + +//----------------------------------------------------------------------------- +// LLAvatarJointMesh::setMesh() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::setMesh( LLPolyMesh *mesh ) +{ + // set the mesh pointer + mMesh = mesh; + + // release any existing skin joints + freeSkinData(); + + if ( mMesh == NULL ) + { + return; + } + + // acquire the transform from the mesh object + // SL-315 + setPosition( mMesh->getPosition() ); + setRotation( mMesh->getRotation() ); + setScale( mMesh->getScale() ); + + // create skin joints if necessary + if ( mMesh->hasWeights() && !mMesh->isLOD()) + { + U32 numJointNames = mMesh->getNumJointNames(); + + allocateSkinData( numJointNames ); + std::string *jointNames = mMesh->getJointNames(); + + U32 jn; + for (jn = 0; jn < numJointNames; jn++) + { + //LL_INFOS() << "Setting up joint " << jointNames[jn] << LL_ENDL; + LLAvatarJoint* joint = (LLAvatarJoint*)(getRoot()->findJoint(jointNames[jn]) ); + mSkinJoints[jn].setupSkinJoint( joint ); + } + } + + // setup joint array + if (!mMesh->isLOD()) + { + setupJoint((LLAvatarJoint*)getRoot()); + LL_DEBUGS("Avatar") << getName() << " joint render entries: " << mMesh->mJointRenderData.size() << LL_ENDL; + } + +} + +//----------------------------------------------------------------------------- +// setupJoint() +//----------------------------------------------------------------------------- +void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint) +{ + U32 sj; + + for (sj=0; sjgetName() << " matches skinjoint " << sj << LL_ENDL; + + // is the last joint in the array our parent? + + std::vector &jrd = mMesh->mJointRenderData; + + // SL-287 - need to update this so the results are the same if + // additional extended-skeleton joints lie between this joint + // and the original parent. + LLJoint *ancestor = getBaseSkeletonAncestor(current_joint); + if(jrd.size() && jrd.back()->mWorldMatrix == &ancestor->getWorldMatrix()) + { + // ...then just add ourselves + LLAvatarJoint* jointp = js.mJoint; + jrd.push_back(new LLJointRenderData(&jointp->getWorldMatrix(), &js)); + LL_DEBUGS("Avatar") << "add joint[" << (jrd.size()-1) << "] = " << js.mJoint->getName() << LL_ENDL; + } + // otherwise add our ancestor and ourselves + else + { + jrd.push_back(new LLJointRenderData(&ancestor->getWorldMatrix(), NULL)); + LL_DEBUGS("Avatar") << "add2 ancestor joint[" << (jrd.size()-1) << "] = " << ancestor->getName() << LL_ENDL; + jrd.push_back(new LLJointRenderData(¤t_joint->getWorldMatrix(), &js)); + LL_DEBUGS("Avatar") << "add2 joint[" << (jrd.size()-1) << "] = " << current_joint->getName() << LL_ENDL; + } + } + + // depth-first traversal + for (LLJoint* joint : current_joint->mChildren) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)joint; + setupJoint(child_joint); + } +} + + +// End diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 273ca4d52c..33f50fce00 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -1,141 +1,141 @@ -/** - * @file llavatarjointmesh.h - * @brief Declaration of LLAvatarJointMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLAVATARJOINTMESH_H -#define LL_LLAVATARJOINTMESH_H - -#include "llavatarjoint.h" -#include "llgltexture.h" -#include "llpolymesh.h" -#include "v4color.h" - -class LLDrawable; -class LLFace; -class LLCharacter; -class LLTexLayerSet; - -typedef enum e_avatar_render_pass -{ - AVATAR_RENDER_PASS_SINGLE, - AVATAR_RENDER_PASS_CLOTHING_INNER, - AVATAR_RENDER_PASS_CLOTHING_OUTER -} EAvatarRenderPass; - -class LLSkinJoint -{ -public: - LLSkinJoint(); - ~LLSkinJoint(); - bool setupSkinJoint( LLAvatarJoint *joint); - - LLAvatarJoint *mJoint; - LLVector3 mRootToJointSkinOffset; - LLVector3 mRootToParentJointSkinOffset; -}; - -//----------------------------------------------------------------------------- -// class LLViewerJointMesh -//----------------------------------------------------------------------------- -class LLAvatarJointMesh : public virtual LLAvatarJoint -{ -protected: - LLColor4 mColor; // color value -// LLColor4 mSpecular; // specular color (always white for now) - F32 mShiny; // shiny value - LLPointer mTexture; // ptr to a global texture - LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar - U32 mTestImageName; // handle to a temporary texture for previewing uploads - LLPolyMesh* mMesh; // ptr to a global polymesh - bool mCullBackFaces; // true by default - LLFace* mFace; // ptr to a face w/ AGP copy of mesh - - U32 mFaceIndexCount; - - U32 mNumSkinJoints; - LLSkinJoint* mSkinJoints; - S32 mMeshID; - -public: - static bool sPipelineRender; - //RN: this is here for testing purposes - static U32 sClothingMaskImageName; - static LLColor4 sClothingInnerColor; - -public: - // Constructor - LLAvatarJointMesh(); - - // Destructor - virtual ~LLAvatarJointMesh(); - - // Gets the shape color - void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); - - // Sets the shape color - void setColor( F32 red, F32 green, F32 blue, F32 alpha ); - void setColor( const LLColor4& color ); - - // Sets the shininess - void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; - - // Sets the shape texture - void setTexture( LLGLTexture *texture ); - - bool hasGLTexture() const; - - void setTestTexture( U32 name ) { mTestImageName = name; } - - // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) - void setLayerSet( LLTexLayerSet* layer_set ); - - bool hasComposite() const; - - // Gets the poly mesh - LLPolyMesh *getMesh(); - - // Sets the poly mesh - void setMesh( LLPolyMesh *mesh ); - - // Sets up joint matrix data for rendering - void setupJoint(LLAvatarJoint* current_joint); - - // Sets ID for picking - void setMeshID( S32 id ) {mMeshID = id;} - - // Gets ID for picking - S32 getMeshID() { return mMeshID; } - - void setIsTransparent(bool is_transparent) { mIsTransparent = is_transparent; } - -private: - // Allocate skin data - bool allocateSkinData( U32 numSkinJoints ); - - // Free skin data - void freeSkinData(); -}; - -#endif // LL_LLAVATARJOINTMESH_H +/** + * @file llavatarjointmesh.h + * @brief Declaration of LLAvatarJointMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAVATARJOINTMESH_H +#define LL_LLAVATARJOINTMESH_H + +#include "llavatarjoint.h" +#include "llgltexture.h" +#include "llpolymesh.h" +#include "v4color.h" + +class LLDrawable; +class LLFace; +class LLCharacter; +class LLTexLayerSet; + +typedef enum e_avatar_render_pass +{ + AVATAR_RENDER_PASS_SINGLE, + AVATAR_RENDER_PASS_CLOTHING_INNER, + AVATAR_RENDER_PASS_CLOTHING_OUTER +} EAvatarRenderPass; + +class LLSkinJoint +{ +public: + LLSkinJoint(); + ~LLSkinJoint(); + bool setupSkinJoint( LLAvatarJoint *joint); + + LLAvatarJoint *mJoint; + LLVector3 mRootToJointSkinOffset; + LLVector3 mRootToParentJointSkinOffset; +}; + +//----------------------------------------------------------------------------- +// class LLViewerJointMesh +//----------------------------------------------------------------------------- +class LLAvatarJointMesh : public virtual LLAvatarJoint +{ +protected: + LLColor4 mColor; // color value +// LLColor4 mSpecular; // specular color (always white for now) + F32 mShiny; // shiny value + LLPointer mTexture; // ptr to a global texture + LLTexLayerSet* mLayerSet; // ptr to a layer set owned by the avatar + U32 mTestImageName; // handle to a temporary texture for previewing uploads + LLPolyMesh* mMesh; // ptr to a global polymesh + bool mCullBackFaces; // true by default + LLFace* mFace; // ptr to a face w/ AGP copy of mesh + + U32 mFaceIndexCount; + + U32 mNumSkinJoints; + LLSkinJoint* mSkinJoints; + S32 mMeshID; + +public: + static bool sPipelineRender; + //RN: this is here for testing purposes + static U32 sClothingMaskImageName; + static LLColor4 sClothingInnerColor; + +public: + // Constructor + LLAvatarJointMesh(); + + // Destructor + virtual ~LLAvatarJointMesh(); + + // Gets the shape color + void getColor( F32 *red, F32 *green, F32 *blue, F32 *alpha ); + + // Sets the shape color + void setColor( F32 red, F32 green, F32 blue, F32 alpha ); + void setColor( const LLColor4& color ); + + // Sets the shininess + void setSpecular( const LLColor4& color, F32 shiny ) { /*mSpecular = color;*/ mShiny = shiny; }; + + // Sets the shape texture + void setTexture( LLGLTexture *texture ); + + bool hasGLTexture() const; + + void setTestTexture( U32 name ) { mTestImageName = name; } + + // Sets layer set responsible for a dynamic shape texture (takes precedence over normal texture) + void setLayerSet( LLTexLayerSet* layer_set ); + + bool hasComposite() const; + + // Gets the poly mesh + LLPolyMesh *getMesh(); + + // Sets the poly mesh + void setMesh( LLPolyMesh *mesh ); + + // Sets up joint matrix data for rendering + void setupJoint(LLAvatarJoint* current_joint); + + // Sets ID for picking + void setMeshID( S32 id ) {mMeshID = id;} + + // Gets ID for picking + S32 getMeshID() { return mMeshID; } + + void setIsTransparent(bool is_transparent) { mIsTransparent = is_transparent; } + +private: + // Allocate skin data + bool allocateSkinData( U32 numSkinJoints ); + + // Free skin data + void freeSkinData(); +}; + +#endif // LL_LLAVATARJOINTMESH_H diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index c8c50b90a6..29815d22f7 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -1,622 +1,622 @@ -/** - * @file lldriverparam.cpp - * @brief A visual parameter that drives (controls) other visual parameters. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lldriverparam.h" - -#include "llavatarappearance.h" -#include "llwearable.h" -#include "llwearabledata.h" - -//----------------------------------------------------------------------------- -// LLDriverParamInfo -//----------------------------------------------------------------------------- - -LLDriverParamInfo::LLDriverParamInfo() : - mDriverParam(NULL) -{ -} - -bool LLDriverParamInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) ); - - if( !LLViewerVisualParamInfo::parseXml( node )) - return false; - - LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" ); - if( !param_driver_node ) - return false; - - for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" ); - child; - child = param_driver_node->getNextNamedChild()) - { - S32 driven_id; - static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); - if( child->getFastAttributeS32( id_string, driven_id ) ) - { - F32 min1 = mMinWeight; - F32 max1 = mMaxWeight; - F32 max2 = max1; - F32 min2 = max1; - - // driven ________ // - // ^ /| |\ // - // | / | | \ // - // | / | | \ // - // | / | | \ // - // | / | | \ // - //-------|----|-------|----|-------> driver // - // | min1 max1 max2 min2 - - static LLStdStringHandle min1_string = LLXmlTree::addAttributeString("min1"); - child->getFastAttributeF32( min1_string, min1 ); // optional - static LLStdStringHandle max1_string = LLXmlTree::addAttributeString("max1"); - child->getFastAttributeF32( max1_string, max1 ); // optional - static LLStdStringHandle max2_string = LLXmlTree::addAttributeString("max2"); - child->getFastAttributeF32( max2_string, max2 ); // optional - static LLStdStringHandle min2_string = LLXmlTree::addAttributeString("min2"); - child->getFastAttributeF32( min2_string, min2 ); // optional - - // Push these on the front of the deque, so that we can construct - // them in order later (faster) - mDrivenInfoList.push_front( LLDrivenEntryInfo( driven_id, min1, max1, max2, min2 ) ); - } - else - { - LL_ERRS() << " Unable to resolve driven parameter: " << driven_id << LL_ENDL; - return false; - } - } - return true; -} - -//virtual -void LLDriverParamInfo::toStream(std::ostream &out) -{ - LLViewerVisualParamInfo::toStream(out); - out << "driver" << "\t"; - out << mDrivenInfoList.size() << "\t"; - for (LLDrivenEntryInfo& driven : mDrivenInfoList) - { - out << driven.mDrivenID << "\t"; - } - - out << std::endl; - - // FIXME - this mDriverParam backlink makes no sense, because the - // LLDriverParamInfos are static objects - there's only one copy - // for each param type, so the backlink will just reference the - // corresponding param in the most recently created - // avatar. Apparently these toStream() methods are not currently - // used anywhere, so it's not an urgent problem. - LL_WARNS_ONCE() << "Invalid usage of mDriverParam." << LL_ENDL; - - if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() && - mDriverParam->getAvatarAppearance()->isValid()) - { - for (LLDrivenEntryInfo& driven : mDrivenInfoList) - { - LLViewerVisualParam *param = - (LLViewerVisualParam*)mDriverParam->getAvatarAppearance()->getVisualParam(driven.mDrivenID); - if (param) - { - param->getInfo()->toStream(out); - if (param->getWearableType() != mWearableType) - { - if(param->getCrossWearable()) - { - out << "cross-wearable" << "\t"; - } - else - { - out << "ERROR!" << "\t"; - } - } - else - { - out << "valid" << "\t"; - } - } - else - { - LL_WARNS() << "could not get parameter " << driven.mDrivenID << " from avatar " - << mDriverParam->getAvatarAppearance() - << " for driver parameter " << getID() << LL_ENDL; - } - out << std::endl; - } - } -} - -//----------------------------------------------------------------------------- -// LLDriverParam -//----------------------------------------------------------------------------- - -LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) - : LLViewerVisualParam(), - mDefaultVec(), - mDriven(), - mCurrentDistortionParam( NULL ), - mAvatarAppearance(appearance), - mWearablep(wearable) -{ - llassert(mAvatarAppearance); - llassert((mWearablep == NULL) || mAvatarAppearance->isSelf()); - mDefaultVec.clear(); -} - -LLDriverParam::LLDriverParam(const LLDriverParam& pOther) - : LLViewerVisualParam(pOther), - mDefaultVec(pOther.mDefaultVec), - mDriven(pOther.mDriven), - mCurrentDistortionParam(pOther.mCurrentDistortionParam), - mAvatarAppearance(pOther.mAvatarAppearance), - mWearablep(pOther.mWearablep) -{ - llassert(mAvatarAppearance); - llassert((mWearablep == NULL) || mAvatarAppearance->isSelf()); -} - -LLDriverParam::~LLDriverParam() -{ -} - -bool LLDriverParam::setInfo(LLDriverParamInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return false; - mInfo = info; - mID = info->mID; - info->mDriverParam = this; - - setWeight(getDefaultWeight()); - - return true; -} - -/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const -{ - llassert(wearable); - return new LLDriverParam(*this); -} - -void LLDriverParam::setWeight(F32 weight) -{ - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - if (mIsAnimating) - { - // allow overshoot when animating - mCurWeight = weight; - } - else - { - mCurWeight = llclamp(weight, min_weight, max_weight); - } - - // driven ________ - // ^ /| |\ ^ - // | / | | \ | - // | / | | \ | - // | / | | \ | - // | / | | \ | - //-------|----|-------|----|-------> driver - // | min1 max1 max2 min2 - - for(LLDrivenEntry& driven : mDriven) - { - LLDrivenEntry* drivenp = &driven; - LLDrivenEntryInfo* info = drivenp->mInfo; - - F32 driven_weight = 0.f; - F32 driven_min = drivenp->mParam->getMinWeight(); - F32 driven_max = drivenp->mParam->getMaxWeight(); - - if (mIsAnimating) - { - // driven param doesn't interpolate (textures, for example) - if (!drivenp->mParam->getAnimating()) - { - continue; - } - if( mCurWeight < info->mMin1 ) - { - if (info->mMin1 == min_weight) - { - if (info->mMin1 == info->mMax1) - { - driven_weight = driven_max; - } - else - { - //up slope extrapolation - F32 t = (mCurWeight - info->mMin1) / (info->mMax1 - info->mMin1 ); - driven_weight = driven_min + t * (driven_max - driven_min); - } - } - else - { - driven_weight = driven_min; - } - - setDrivenWeight(drivenp,driven_weight); - continue; - } - else - if ( mCurWeight > info->mMin2 ) - { - if (info->mMin2 == max_weight) - { - if (info->mMin2 == info->mMax2) - { - driven_weight = driven_max; - } - else - { - //down slope extrapolation - F32 t = (mCurWeight - info->mMax2) / (info->mMin2 - info->mMax2 ); - driven_weight = driven_max + t * (driven_min - driven_max); - } - } - else - { - driven_weight = driven_min; - } - - setDrivenWeight(drivenp,driven_weight); - continue; - } - } - - driven_weight = getDrivenWeight(drivenp, mCurWeight); - setDrivenWeight(drivenp,driven_weight); - } -} - -F32 LLDriverParam::getTotalDistortion() -{ - F32 sum = 0.f; - for(LLDrivenEntry& driven : mDriven) - { - sum += driven.mParam->getTotalDistortion(); - } - - return sum; -} - -const LLVector4a &LLDriverParam::getAvgDistortion() -{ - // It's not actually correct to take the average of averages, but it good enough here. - LLVector4a sum; - sum.clear(); - S32 count = 0; - for(LLDrivenEntry& driven : mDriven) - { - sum.add(driven.mParam->getAvgDistortion()); - count++; - } - sum.mul( 1.f/(F32)count); - - mDefaultVec = sum; - return mDefaultVec; -} - -F32 LLDriverParam::getMaxDistortion() -{ - F32 max = 0.f; - for(LLDrivenEntry& driven : mDriven) - { - F32 param_max = driven.mParam->getMaxDistortion(); - if( param_max > max ) - { - max = param_max; - } - } - - return max; -} - - -LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) -{ - LLVector4a sum; - sum.clear(); - for(LLDrivenEntry& driven : mDriven) - { - sum.add(driven.mParam->getVertexDistortion(index, poly_mesh)); - } - return sum; -} - -const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - mCurrentDistortionParam = NULL; - const LLVector4a* v = NULL; - for(LLDrivenEntry& driven : mDriven) - { - v = driven.mParam->getFirstDistortion(index, poly_mesh); - if( v ) - { - mCurrentDistortionParam = driven.mParam; - break; - } - } - - return v; -}; - -const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - llassert( mCurrentDistortionParam ); - if( !mCurrentDistortionParam ) - { - return NULL; - } - - LLDrivenEntry* driven = NULL; - entry_list_t::iterator iter; - - // Set mDriven iteration to the right point - for( iter = mDriven.begin(); iter != mDriven.end(); iter++ ) - { - driven = &(*iter); - if( driven->mParam == mCurrentDistortionParam ) - { - break; - } - } - - llassert(driven); - if (!driven) - { - return NULL; // shouldn't happen, but... - } - - // We're already in the middle of a param's distortions, so get the next one. - const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); - if( (!v) && (iter != mDriven.end()) ) - { - // This param is finished, so start the next param. It might not have any - // distortions, though, so we have to loop to find the next param that does. - for( iter++; iter != mDriven.end(); iter++ ) - { - driven = &(*iter); - v = driven->mParam->getFirstDistortion(index, poly_mesh); - if( v ) - { - mCurrentDistortionParam = driven->mParam; - break; - } - } - } - - return v; -}; - -S32 LLDriverParam::getDrivenParamsCount() const -{ - return mDriven.size(); -} - -const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const -{ - if (0 > index || index >= mDriven.size()) - { - return NULL; - } - return mDriven[index].mParam; -} - -//----------------------------------------------------------------------------- -// setAnimationTarget() -//----------------------------------------------------------------------------- -void LLDriverParam::setAnimationTarget( F32 target_value) -{ - LLVisualParam::setAnimationTarget(target_value); - - for(LLDrivenEntry& driven : mDriven) - { - LLDrivenEntry* drivenp = &driven; - F32 driven_weight = getDrivenWeight(drivenp, mTargetWeight); - - // this isn't normally necessary, as driver params handle interpolation of their driven params - // but texture params need to know to assume their final value at beginning of interpolation - drivenp->mParam->setAnimationTarget(driven_weight); - } -} - -//----------------------------------------------------------------------------- -// stopAnimating() -//----------------------------------------------------------------------------- -void LLDriverParam::stopAnimating() -{ - LLVisualParam::stopAnimating(); - - for(LLDrivenEntry& driven : mDriven) - { - driven.mParam->setAnimating(false); - } -} - -/*virtual*/ -bool LLDriverParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params) -{ - bool success = true; - for (LLDrivenEntryInfo& driven_info : getInfo()->mDrivenInfoList) - { - S32 driven_id = driven_info.mDrivenID; - - // check for already existing links. Do not overwrite. - bool found = false; - for (auto& driven : mDriven) - { - if (driven.mInfo->mDrivenID == driven_id) - { - found = true; - } - } - - if (!found) - { - LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id); - if (param) param->setParamLocation(this->getParamLocation()); - bool push = param && (!only_cross_params || param->getCrossWearable()); - if (push) - { - mDriven.push_back(LLDrivenEntry( param, &driven_info )); - } - else - { - success = false; - } - } - } - - return success; -} - -void LLDriverParam::resetDrivenParams() -{ - mDriven.clear(); - mDriven.reserve(getInfo()->mDrivenInfoList.size()); -} - -void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type) -{ - bool needs_update = (getWearableType()==driven_type); - - // if the driver has a driven entry for the passed-in wearable type, we need to refresh the value - for(LLDrivenEntry& driven : mDriven) - { - if (driven.mParam && driven.mParam->getCrossWearable() && driven.mParam->getWearableType() == driven_type) - { - needs_update = true; - } - } - - - if (needs_update) - { - LLWearableType::EType driver_type = (LLWearableType::EType)getWearableType(); - - // If we've gotten here, we've added a new wearable of type "type" - // Thus this wearable needs to get updates from the driver wearable. - // The call to setVisualParamWeight seems redundant, but is necessary - // as the number of driven wearables has changed since the last update. -Nyx - LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type); - if (wearable) - { - wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID)); - } - } -} - - -//----------------------------------------------------------------------------- -// getDrivenWeight() -//----------------------------------------------------------------------------- -F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight) -{ - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - const LLDrivenEntryInfo* info = driven->mInfo; - - F32 driven_weight = 0.f; - F32 driven_min = driven->mParam->getMinWeight(); - F32 driven_max = driven->mParam->getMaxWeight(); - - if( input_weight <= info->mMin1 ) - { - if( info->mMin1 == info->mMax1 && - info->mMin1 <= min_weight) - { - driven_weight = driven_max; - } - else - { - driven_weight = driven_min; - } - } - else - if( input_weight <= info->mMax1 ) - { - F32 t = (input_weight - info->mMin1) / (info->mMax1 - info->mMin1 ); - driven_weight = driven_min + t * (driven_max - driven_min); - } - else - if( input_weight <= info->mMax2 ) - { - driven_weight = driven_max; - } - else - if( input_weight <= info->mMin2 ) - { - F32 t = (input_weight - info->mMax2) / (info->mMin2 - info->mMax2 ); - driven_weight = driven_max + t * (driven_min - driven_max); - } - else - { - if (info->mMax2 >= max_weight) - { - driven_weight = driven_max; - } - else - { - driven_weight = driven_min; - } - } - - return driven_weight; -} - -void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight) -{ - bool use_self = false; - if(mWearablep && - mAvatarAppearance->isValid() && - driven->mParam->getCrossWearable()) - { - LLWearable* wearable = mWearablep; - if (mAvatarAppearance->getWearableData()->isOnTop(wearable)) - { - use_self = true; - } - } - - if (use_self) - { - // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values - mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight); - } - else - { - driven->mParam->setWeight( driven_weight); - } -} +/** + * @file lldriverparam.cpp + * @brief A visual parameter that drives (controls) other visual parameters. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lldriverparam.h" + +#include "llavatarappearance.h" +#include "llwearable.h" +#include "llwearabledata.h" + +//----------------------------------------------------------------------------- +// LLDriverParamInfo +//----------------------------------------------------------------------------- + +LLDriverParamInfo::LLDriverParamInfo() : + mDriverParam(NULL) +{ +} + +bool LLDriverParamInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) ); + + if( !LLViewerVisualParamInfo::parseXml( node )) + return false; + + LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" ); + if( !param_driver_node ) + return false; + + for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" ); + child; + child = param_driver_node->getNextNamedChild()) + { + S32 driven_id; + static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id"); + if( child->getFastAttributeS32( id_string, driven_id ) ) + { + F32 min1 = mMinWeight; + F32 max1 = mMaxWeight; + F32 max2 = max1; + F32 min2 = max1; + + // driven ________ // + // ^ /| |\ // + // | / | | \ // + // | / | | \ // + // | / | | \ // + // | / | | \ // + //-------|----|-------|----|-------> driver // + // | min1 max1 max2 min2 + + static LLStdStringHandle min1_string = LLXmlTree::addAttributeString("min1"); + child->getFastAttributeF32( min1_string, min1 ); // optional + static LLStdStringHandle max1_string = LLXmlTree::addAttributeString("max1"); + child->getFastAttributeF32( max1_string, max1 ); // optional + static LLStdStringHandle max2_string = LLXmlTree::addAttributeString("max2"); + child->getFastAttributeF32( max2_string, max2 ); // optional + static LLStdStringHandle min2_string = LLXmlTree::addAttributeString("min2"); + child->getFastAttributeF32( min2_string, min2 ); // optional + + // Push these on the front of the deque, so that we can construct + // them in order later (faster) + mDrivenInfoList.push_front( LLDrivenEntryInfo( driven_id, min1, max1, max2, min2 ) ); + } + else + { + LL_ERRS() << " Unable to resolve driven parameter: " << driven_id << LL_ENDL; + return false; + } + } + return true; +} + +//virtual +void LLDriverParamInfo::toStream(std::ostream &out) +{ + LLViewerVisualParamInfo::toStream(out); + out << "driver" << "\t"; + out << mDrivenInfoList.size() << "\t"; + for (LLDrivenEntryInfo& driven : mDrivenInfoList) + { + out << driven.mDrivenID << "\t"; + } + + out << std::endl; + + // FIXME - this mDriverParam backlink makes no sense, because the + // LLDriverParamInfos are static objects - there's only one copy + // for each param type, so the backlink will just reference the + // corresponding param in the most recently created + // avatar. Apparently these toStream() methods are not currently + // used anywhere, so it's not an urgent problem. + LL_WARNS_ONCE() << "Invalid usage of mDriverParam." << LL_ENDL; + + if(mDriverParam && mDriverParam->getAvatarAppearance()->isSelf() && + mDriverParam->getAvatarAppearance()->isValid()) + { + for (LLDrivenEntryInfo& driven : mDrivenInfoList) + { + LLViewerVisualParam *param = + (LLViewerVisualParam*)mDriverParam->getAvatarAppearance()->getVisualParam(driven.mDrivenID); + if (param) + { + param->getInfo()->toStream(out); + if (param->getWearableType() != mWearableType) + { + if(param->getCrossWearable()) + { + out << "cross-wearable" << "\t"; + } + else + { + out << "ERROR!" << "\t"; + } + } + else + { + out << "valid" << "\t"; + } + } + else + { + LL_WARNS() << "could not get parameter " << driven.mDrivenID << " from avatar " + << mDriverParam->getAvatarAppearance() + << " for driver parameter " << getID() << LL_ENDL; + } + out << std::endl; + } + } +} + +//----------------------------------------------------------------------------- +// LLDriverParam +//----------------------------------------------------------------------------- + +LLDriverParam::LLDriverParam(LLAvatarAppearance *appearance, LLWearable* wearable /* = NULL */) + : LLViewerVisualParam(), + mDefaultVec(), + mDriven(), + mCurrentDistortionParam( NULL ), + mAvatarAppearance(appearance), + mWearablep(wearable) +{ + llassert(mAvatarAppearance); + llassert((mWearablep == NULL) || mAvatarAppearance->isSelf()); + mDefaultVec.clear(); +} + +LLDriverParam::LLDriverParam(const LLDriverParam& pOther) + : LLViewerVisualParam(pOther), + mDefaultVec(pOther.mDefaultVec), + mDriven(pOther.mDriven), + mCurrentDistortionParam(pOther.mCurrentDistortionParam), + mAvatarAppearance(pOther.mAvatarAppearance), + mWearablep(pOther.mWearablep) +{ + llassert(mAvatarAppearance); + llassert((mWearablep == NULL) || mAvatarAppearance->isSelf()); +} + +LLDriverParam::~LLDriverParam() +{ +} + +bool LLDriverParam::setInfo(LLDriverParamInfo *info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return false; + mInfo = info; + mID = info->mID; + info->mDriverParam = this; + + setWeight(getDefaultWeight()); + + return true; +} + +/*virtual*/ LLViewerVisualParam* LLDriverParam::cloneParam(LLWearable* wearable) const +{ + llassert(wearable); + return new LLDriverParam(*this); +} + +void LLDriverParam::setWeight(F32 weight) +{ + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + if (mIsAnimating) + { + // allow overshoot when animating + mCurWeight = weight; + } + else + { + mCurWeight = llclamp(weight, min_weight, max_weight); + } + + // driven ________ + // ^ /| |\ ^ + // | / | | \ | + // | / | | \ | + // | / | | \ | + // | / | | \ | + //-------|----|-------|----|-------> driver + // | min1 max1 max2 min2 + + for(LLDrivenEntry& driven : mDriven) + { + LLDrivenEntry* drivenp = &driven; + LLDrivenEntryInfo* info = drivenp->mInfo; + + F32 driven_weight = 0.f; + F32 driven_min = drivenp->mParam->getMinWeight(); + F32 driven_max = drivenp->mParam->getMaxWeight(); + + if (mIsAnimating) + { + // driven param doesn't interpolate (textures, for example) + if (!drivenp->mParam->getAnimating()) + { + continue; + } + if( mCurWeight < info->mMin1 ) + { + if (info->mMin1 == min_weight) + { + if (info->mMin1 == info->mMax1) + { + driven_weight = driven_max; + } + else + { + //up slope extrapolation + F32 t = (mCurWeight - info->mMin1) / (info->mMax1 - info->mMin1 ); + driven_weight = driven_min + t * (driven_max - driven_min); + } + } + else + { + driven_weight = driven_min; + } + + setDrivenWeight(drivenp,driven_weight); + continue; + } + else + if ( mCurWeight > info->mMin2 ) + { + if (info->mMin2 == max_weight) + { + if (info->mMin2 == info->mMax2) + { + driven_weight = driven_max; + } + else + { + //down slope extrapolation + F32 t = (mCurWeight - info->mMax2) / (info->mMin2 - info->mMax2 ); + driven_weight = driven_max + t * (driven_min - driven_max); + } + } + else + { + driven_weight = driven_min; + } + + setDrivenWeight(drivenp,driven_weight); + continue; + } + } + + driven_weight = getDrivenWeight(drivenp, mCurWeight); + setDrivenWeight(drivenp,driven_weight); + } +} + +F32 LLDriverParam::getTotalDistortion() +{ + F32 sum = 0.f; + for(LLDrivenEntry& driven : mDriven) + { + sum += driven.mParam->getTotalDistortion(); + } + + return sum; +} + +const LLVector4a &LLDriverParam::getAvgDistortion() +{ + // It's not actually correct to take the average of averages, but it good enough here. + LLVector4a sum; + sum.clear(); + S32 count = 0; + for(LLDrivenEntry& driven : mDriven) + { + sum.add(driven.mParam->getAvgDistortion()); + count++; + } + sum.mul( 1.f/(F32)count); + + mDefaultVec = sum; + return mDefaultVec; +} + +F32 LLDriverParam::getMaxDistortion() +{ + F32 max = 0.f; + for(LLDrivenEntry& driven : mDriven) + { + F32 param_max = driven.mParam->getMaxDistortion(); + if( param_max > max ) + { + max = param_max; + } + } + + return max; +} + + +LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) +{ + LLVector4a sum; + sum.clear(); + for(LLDrivenEntry& driven : mDriven) + { + sum.add(driven.mParam->getVertexDistortion(index, poly_mesh)); + } + return sum; +} + +const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + mCurrentDistortionParam = NULL; + const LLVector4a* v = NULL; + for(LLDrivenEntry& driven : mDriven) + { + v = driven.mParam->getFirstDistortion(index, poly_mesh); + if( v ) + { + mCurrentDistortionParam = driven.mParam; + break; + } + } + + return v; +}; + +const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + llassert( mCurrentDistortionParam ); + if( !mCurrentDistortionParam ) + { + return NULL; + } + + LLDrivenEntry* driven = NULL; + entry_list_t::iterator iter; + + // Set mDriven iteration to the right point + for( iter = mDriven.begin(); iter != mDriven.end(); iter++ ) + { + driven = &(*iter); + if( driven->mParam == mCurrentDistortionParam ) + { + break; + } + } + + llassert(driven); + if (!driven) + { + return NULL; // shouldn't happen, but... + } + + // We're already in the middle of a param's distortions, so get the next one. + const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); + if( (!v) && (iter != mDriven.end()) ) + { + // This param is finished, so start the next param. It might not have any + // distortions, though, so we have to loop to find the next param that does. + for( iter++; iter != mDriven.end(); iter++ ) + { + driven = &(*iter); + v = driven->mParam->getFirstDistortion(index, poly_mesh); + if( v ) + { + mCurrentDistortionParam = driven->mParam; + break; + } + } + } + + return v; +}; + +S32 LLDriverParam::getDrivenParamsCount() const +{ + return mDriven.size(); +} + +const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const +{ + if (0 > index || index >= mDriven.size()) + { + return NULL; + } + return mDriven[index].mParam; +} + +//----------------------------------------------------------------------------- +// setAnimationTarget() +//----------------------------------------------------------------------------- +void LLDriverParam::setAnimationTarget( F32 target_value) +{ + LLVisualParam::setAnimationTarget(target_value); + + for(LLDrivenEntry& driven : mDriven) + { + LLDrivenEntry* drivenp = &driven; + F32 driven_weight = getDrivenWeight(drivenp, mTargetWeight); + + // this isn't normally necessary, as driver params handle interpolation of their driven params + // but texture params need to know to assume their final value at beginning of interpolation + drivenp->mParam->setAnimationTarget(driven_weight); + } +} + +//----------------------------------------------------------------------------- +// stopAnimating() +//----------------------------------------------------------------------------- +void LLDriverParam::stopAnimating() +{ + LLVisualParam::stopAnimating(); + + for(LLDrivenEntry& driven : mDriven) + { + driven.mParam->setAnimating(false); + } +} + +/*virtual*/ +bool LLDriverParam::linkDrivenParams(visual_param_mapper mapper, bool only_cross_params) +{ + bool success = true; + for (LLDrivenEntryInfo& driven_info : getInfo()->mDrivenInfoList) + { + S32 driven_id = driven_info.mDrivenID; + + // check for already existing links. Do not overwrite. + bool found = false; + for (auto& driven : mDriven) + { + if (driven.mInfo->mDrivenID == driven_id) + { + found = true; + } + } + + if (!found) + { + LLViewerVisualParam* param = (LLViewerVisualParam*)mapper(driven_id); + if (param) param->setParamLocation(this->getParamLocation()); + bool push = param && (!only_cross_params || param->getCrossWearable()); + if (push) + { + mDriven.push_back(LLDrivenEntry( param, &driven_info )); + } + else + { + success = false; + } + } + } + + return success; +} + +void LLDriverParam::resetDrivenParams() +{ + mDriven.clear(); + mDriven.reserve(getInfo()->mDrivenInfoList.size()); +} + +void LLDriverParam::updateCrossDrivenParams(LLWearableType::EType driven_type) +{ + bool needs_update = (getWearableType()==driven_type); + + // if the driver has a driven entry for the passed-in wearable type, we need to refresh the value + for(LLDrivenEntry& driven : mDriven) + { + if (driven.mParam && driven.mParam->getCrossWearable() && driven.mParam->getWearableType() == driven_type) + { + needs_update = true; + } + } + + + if (needs_update) + { + LLWearableType::EType driver_type = (LLWearableType::EType)getWearableType(); + + // If we've gotten here, we've added a new wearable of type "type" + // Thus this wearable needs to get updates from the driver wearable. + // The call to setVisualParamWeight seems redundant, but is necessary + // as the number of driven wearables has changed since the last update. -Nyx + LLWearable *wearable = mAvatarAppearance->getWearableData()->getTopWearable(driver_type); + if (wearable) + { + wearable->setVisualParamWeight(mID, wearable->getVisualParamWeight(mID)); + } + } +} + + +//----------------------------------------------------------------------------- +// getDrivenWeight() +//----------------------------------------------------------------------------- +F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight) +{ + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + const LLDrivenEntryInfo* info = driven->mInfo; + + F32 driven_weight = 0.f; + F32 driven_min = driven->mParam->getMinWeight(); + F32 driven_max = driven->mParam->getMaxWeight(); + + if( input_weight <= info->mMin1 ) + { + if( info->mMin1 == info->mMax1 && + info->mMin1 <= min_weight) + { + driven_weight = driven_max; + } + else + { + driven_weight = driven_min; + } + } + else + if( input_weight <= info->mMax1 ) + { + F32 t = (input_weight - info->mMin1) / (info->mMax1 - info->mMin1 ); + driven_weight = driven_min + t * (driven_max - driven_min); + } + else + if( input_weight <= info->mMax2 ) + { + driven_weight = driven_max; + } + else + if( input_weight <= info->mMin2 ) + { + F32 t = (input_weight - info->mMax2) / (info->mMin2 - info->mMax2 ); + driven_weight = driven_max + t * (driven_min - driven_max); + } + else + { + if (info->mMax2 >= max_weight) + { + driven_weight = driven_max; + } + else + { + driven_weight = driven_min; + } + } + + return driven_weight; +} + +void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight) +{ + bool use_self = false; + if(mWearablep && + mAvatarAppearance->isValid() && + driven->mParam->getCrossWearable()) + { + LLWearable* wearable = mWearablep; + if (mAvatarAppearance->getWearableData()->isOnTop(wearable)) + { + use_self = true; + } + } + + if (use_self) + { + // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values + mAvatarAppearance->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight); + } + else + { + driven->mParam->setWeight( driven_weight); + } +} diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index 52f088f2d2..b7eac80603 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -1,139 +1,139 @@ -/** - * @file lldriverparam.h - * @brief A visual parameter that drives (controls) other visual parameters. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLDRIVERPARAM_H -#define LL_LLDRIVERPARAM_H - -#include "llviewervisualparam.h" -#include "llwearabletype.h" -#include - -class LLAvatarAppearance; -class LLDriverParam; -class LLWearable; - -//----------------------------------------------------------------------------- - -struct LLDrivenEntryInfo -{ - LLDrivenEntryInfo( S32 id, F32 min1, F32 max1, F32 max2, F32 min2 ) - : mDrivenID( id ), mMin1( min1 ), mMax1( max1 ), mMax2( max2 ), mMin2( min2 ) {} - S32 mDrivenID; - F32 mMin1; - F32 mMax1; - F32 mMax2; - F32 mMin2; -}; - -struct LLDrivenEntry -{ - LLDrivenEntry( LLViewerVisualParam* param, LLDrivenEntryInfo *info ) - : mParam( param ), mInfo( info ) {} - LLViewerVisualParam* mParam; - LLDrivenEntryInfo* mInfo; -}; - -//----------------------------------------------------------------------------- - -class LLDriverParamInfo : public LLViewerVisualParamInfo -{ - friend class LLDriverParam; -public: - LLDriverParamInfo(); - /*virtual*/ ~LLDriverParamInfo() {}; - - /*virtual*/ bool parseXml(LLXmlTreeNode* node); - - /*virtual*/ void toStream(std::ostream &out); - -protected: - typedef std::deque entry_info_list_t; - entry_info_list_t mDrivenInfoList; - LLDriverParam* mDriverParam; // backpointer -}; - -//----------------------------------------------------------------------------- - -class alignas(16) LLDriverParam : public LLViewerVisualParam -{ - LL_ALIGN_NEW -private: - // Hide the default constructor. Force construction with LLAvatarAppearance. - LLDriverParam() {} -public: - LLDriverParam(LLAvatarAppearance* appearance, LLWearable* wearable = NULL); - ~LLDriverParam(); - - // Special: These functions are overridden by child classes - LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } - // This sets mInfo and calls initialization functions - bool setInfo(LLDriverParamInfo* info); - - LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } - const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } - - void updateCrossDrivenParams(LLWearableType::EType driven_type); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - /*virtual*/ void apply(ESex sex) {} // apply is called separately for each driven param. - /*virtual*/ void setWeight(F32 weight); - /*virtual*/ void setAnimationTarget(F32 target_value); - /*virtual*/ void stopAnimating(); - /*virtual*/ bool linkDrivenParams(visual_param_mapper mapper, bool only_cross_params); - /*virtual*/ void resetDrivenParams(); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector4a& getAvgDistortion(); - /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh* poly_mesh); - /*virtual*/ const LLVector4a* getFirstDistortion(U32* index, LLPolyMesh** poly_mesh); - /*virtual*/ const LLVector4a* getNextDistortion(U32* index, LLPolyMesh** poly_mesh); - - S32 getDrivenParamsCount() const; - const LLViewerVisualParam* getDrivenParam(S32 index) const; - - typedef std::vector entry_list_t; - entry_list_t& getDrivenList() { return mDriven; } - void setDrivenList(entry_list_t& driven_list) { mDriven = driven_list; } - -protected: - LLDriverParam(const LLDriverParam& pOther); - F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); - void setDrivenWeight(LLDrivenEntry* driven, F32 driven_weight); - - - LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder - entry_list_t mDriven; - LLViewerVisualParam* mCurrentDistortionParam; - // Backlink only; don't make this an LLPointer. - LLAvatarAppearance* mAvatarAppearance; - LLWearable* mWearablep; -}; - -#endif // LL_LLDRIVERPARAM_H +/** + * @file lldriverparam.h + * @brief A visual parameter that drives (controls) other visual parameters. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDRIVERPARAM_H +#define LL_LLDRIVERPARAM_H + +#include "llviewervisualparam.h" +#include "llwearabletype.h" +#include + +class LLAvatarAppearance; +class LLDriverParam; +class LLWearable; + +//----------------------------------------------------------------------------- + +struct LLDrivenEntryInfo +{ + LLDrivenEntryInfo( S32 id, F32 min1, F32 max1, F32 max2, F32 min2 ) + : mDrivenID( id ), mMin1( min1 ), mMax1( max1 ), mMax2( max2 ), mMin2( min2 ) {} + S32 mDrivenID; + F32 mMin1; + F32 mMax1; + F32 mMax2; + F32 mMin2; +}; + +struct LLDrivenEntry +{ + LLDrivenEntry( LLViewerVisualParam* param, LLDrivenEntryInfo *info ) + : mParam( param ), mInfo( info ) {} + LLViewerVisualParam* mParam; + LLDrivenEntryInfo* mInfo; +}; + +//----------------------------------------------------------------------------- + +class LLDriverParamInfo : public LLViewerVisualParamInfo +{ + friend class LLDriverParam; +public: + LLDriverParamInfo(); + /*virtual*/ ~LLDriverParamInfo() {}; + + /*virtual*/ bool parseXml(LLXmlTreeNode* node); + + /*virtual*/ void toStream(std::ostream &out); + +protected: + typedef std::deque entry_info_list_t; + entry_info_list_t mDrivenInfoList; + LLDriverParam* mDriverParam; // backpointer +}; + +//----------------------------------------------------------------------------- + +class alignas(16) LLDriverParam : public LLViewerVisualParam +{ + LL_ALIGN_NEW +private: + // Hide the default constructor. Force construction with LLAvatarAppearance. + LLDriverParam() {} +public: + LLDriverParam(LLAvatarAppearance* appearance, LLWearable* wearable = NULL); + ~LLDriverParam(); + + // Special: These functions are overridden by child classes + LLDriverParamInfo* getInfo() const { return (LLDriverParamInfo*)mInfo; } + // This sets mInfo and calls initialization functions + bool setInfo(LLDriverParamInfo* info); + + LLAvatarAppearance* getAvatarAppearance() { return mAvatarAppearance; } + const LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + + void updateCrossDrivenParams(LLWearableType::EType driven_type); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + /*virtual*/ void apply(ESex sex) {} // apply is called separately for each driven param. + /*virtual*/ void setWeight(F32 weight); + /*virtual*/ void setAnimationTarget(F32 target_value); + /*virtual*/ void stopAnimating(); + /*virtual*/ bool linkDrivenParams(visual_param_mapper mapper, bool only_cross_params); + /*virtual*/ void resetDrivenParams(); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); + /*virtual*/ F32 getMaxDistortion(); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh* poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32* index, LLPolyMesh** poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32* index, LLPolyMesh** poly_mesh); + + S32 getDrivenParamsCount() const; + const LLViewerVisualParam* getDrivenParam(S32 index) const; + + typedef std::vector entry_list_t; + entry_list_t& getDrivenList() { return mDriven; } + void setDrivenList(entry_list_t& driven_list) { mDriven = driven_list; } + +protected: + LLDriverParam(const LLDriverParam& pOther); + F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); + void setDrivenWeight(LLDrivenEntry* driven, F32 driven_weight); + + + LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder + entry_list_t mDriven; + LLViewerVisualParam* mCurrentDistortionParam; + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance* mAvatarAppearance; + LLWearable* mWearablep; +}; + +#endif // LL_LLDRIVERPARAM_H diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index 65464e7f65..9707f002ee 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -1,212 +1,212 @@ -/** - * @file lllocaltextureobject.cpp - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lllocaltextureobject.h" - -#include "llimage.h" -#include "llrender.h" -#include "lltexlayer.h" -#include "llgltexture.h" -#include "lluuid.h" -#include "llwearable.h" - - -LLLocalTextureObject::LLLocalTextureObject() : - mIsBakedReady(false), - mDiscard(MAX_DISCARD_LEVEL+1) -{ - mImage = NULL; -} - -LLLocalTextureObject::LLLocalTextureObject(LLGLTexture* image, const LLUUID& id) : - mIsBakedReady(false), - mDiscard(MAX_DISCARD_LEVEL+1) -{ - mImage = image; - gGL.getTexUnit(0)->bind(mImage); - mID = id; -} - -LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : - mImage(lto.mImage), - mID(lto.mID), - mIsBakedReady(lto.mIsBakedReady), - mDiscard(lto.mDiscard) -{ - U32 num_layers = lto.getNumTexLayers(); - mTexLayers.reserve(num_layers); - for (U32 index = 0; index < num_layers; index++) - { - LLTexLayer* original_layer = lto.getTexLayer(index); - if (!original_layer) - { - LL_ERRS() << "could not clone Local Texture Object: unable to extract texlayer!" << LL_ENDL; - continue; - } - - LLTexLayer* new_layer = new LLTexLayer(*original_layer); - new_layer->setLTO(this); - mTexLayers.push_back(new_layer); - } -} - -LLLocalTextureObject::~LLLocalTextureObject() -{ - delete_and_clear(mTexLayers); -} - -LLGLTexture* LLLocalTextureObject::getImage() const -{ - return mImage; -} - -LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const -{ - if (index >= getNumTexLayers()) - { - return NULL; - } - - return mTexLayers[index]; -} - -LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) -{ - for(LLTexLayer* layer : mTexLayers) - { - if (layer->getName().compare(name) == 0) - { - return layer; - } - } - - return NULL; -} - -U32 LLLocalTextureObject::getNumTexLayers() const -{ - return mTexLayers.size(); -} - -LLUUID LLLocalTextureObject::getID() const -{ - return mID; -} - -S32 LLLocalTextureObject::getDiscard() const -{ - return mDiscard; -} - -bool LLLocalTextureObject::getBakedReady() const -{ - return mIsBakedReady; -} - -void LLLocalTextureObject::setImage(LLGLTexture* new_image) -{ - mImage = new_image; -} - -bool LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) -{ - if (index >= getNumTexLayers() ) - { - return false; - } - - if (new_tex_layer == NULL) - { - return removeTexLayer(index); - } - - LLTexLayer *layer = new LLTexLayer(*new_tex_layer); - layer->setLTO(this); - - if (mTexLayers[index]) - { - delete mTexLayers[index]; - } - mTexLayers[index] = layer; - - return true; -} - -bool LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) -{ - if (new_tex_layer == NULL) - { - return false; - } - - LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable); - layer->setLTO(this); - mTexLayers.push_back(layer); - return true; -} - -bool LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) -{ - if (new_tex_layer == NULL) - { - return false; - } - - LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable); - layer->setLTO(this); - mTexLayers.push_back(layer); - return true; -} - -bool LLLocalTextureObject::removeTexLayer(U32 index) -{ - if (index >= getNumTexLayers()) - { - return false; - } - tex_layer_vec_t::iterator iter = mTexLayers.begin(); - iter += index; - - delete *iter; - mTexLayers.erase(iter); - return true; -} - -void LLLocalTextureObject::setID(LLUUID new_id) -{ - mID = new_id; -} - -void LLLocalTextureObject::setDiscard(S32 new_discard) -{ - mDiscard = new_discard; -} - -void LLLocalTextureObject::setBakedReady(bool ready) -{ - mIsBakedReady = ready; -} +/** + * @file lllocaltextureobject.cpp + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lllocaltextureobject.h" + +#include "llimage.h" +#include "llrender.h" +#include "lltexlayer.h" +#include "llgltexture.h" +#include "lluuid.h" +#include "llwearable.h" + + +LLLocalTextureObject::LLLocalTextureObject() : + mIsBakedReady(false), + mDiscard(MAX_DISCARD_LEVEL+1) +{ + mImage = NULL; +} + +LLLocalTextureObject::LLLocalTextureObject(LLGLTexture* image, const LLUUID& id) : + mIsBakedReady(false), + mDiscard(MAX_DISCARD_LEVEL+1) +{ + mImage = image; + gGL.getTexUnit(0)->bind(mImage); + mID = id; +} + +LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : + mImage(lto.mImage), + mID(lto.mID), + mIsBakedReady(lto.mIsBakedReady), + mDiscard(lto.mDiscard) +{ + U32 num_layers = lto.getNumTexLayers(); + mTexLayers.reserve(num_layers); + for (U32 index = 0; index < num_layers; index++) + { + LLTexLayer* original_layer = lto.getTexLayer(index); + if (!original_layer) + { + LL_ERRS() << "could not clone Local Texture Object: unable to extract texlayer!" << LL_ENDL; + continue; + } + + LLTexLayer* new_layer = new LLTexLayer(*original_layer); + new_layer->setLTO(this); + mTexLayers.push_back(new_layer); + } +} + +LLLocalTextureObject::~LLLocalTextureObject() +{ + delete_and_clear(mTexLayers); +} + +LLGLTexture* LLLocalTextureObject::getImage() const +{ + return mImage; +} + +LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const +{ + if (index >= getNumTexLayers()) + { + return NULL; + } + + return mTexLayers[index]; +} + +LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) +{ + for(LLTexLayer* layer : mTexLayers) + { + if (layer->getName().compare(name) == 0) + { + return layer; + } + } + + return NULL; +} + +U32 LLLocalTextureObject::getNumTexLayers() const +{ + return mTexLayers.size(); +} + +LLUUID LLLocalTextureObject::getID() const +{ + return mID; +} + +S32 LLLocalTextureObject::getDiscard() const +{ + return mDiscard; +} + +bool LLLocalTextureObject::getBakedReady() const +{ + return mIsBakedReady; +} + +void LLLocalTextureObject::setImage(LLGLTexture* new_image) +{ + mImage = new_image; +} + +bool LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index) +{ + if (index >= getNumTexLayers() ) + { + return false; + } + + if (new_tex_layer == NULL) + { + return removeTexLayer(index); + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer); + layer->setLTO(this); + + if (mTexLayers[index]) + { + delete mTexLayers[index]; + } + mTexLayers[index] = layer; + + return true; +} + +bool LLLocalTextureObject::addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable) +{ + if (new_tex_layer == NULL) + { + return false; + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer, wearable); + layer->setLTO(this); + mTexLayers.push_back(layer); + return true; +} + +bool LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable) +{ + if (new_tex_layer == NULL) + { + return false; + } + + LLTexLayer *layer = new LLTexLayer(*new_tex_layer, this, wearable); + layer->setLTO(this); + mTexLayers.push_back(layer); + return true; +} + +bool LLLocalTextureObject::removeTexLayer(U32 index) +{ + if (index >= getNumTexLayers()) + { + return false; + } + tex_layer_vec_t::iterator iter = mTexLayers.begin(); + iter += index; + + delete *iter; + mTexLayers.erase(iter); + return true; +} + +void LLLocalTextureObject::setID(LLUUID new_id) +{ + mID = new_id; +} + +void LLLocalTextureObject::setDiscard(S32 new_discard) +{ + mDiscard = new_discard; +} + +void LLLocalTextureObject::setBakedReady(bool ready) +{ + mIsBakedReady = ready; +} diff --git a/indra/llappearance/lllocaltextureobject.h b/indra/llappearance/lllocaltextureobject.h index 8922ec414f..5505ef205a 100644 --- a/indra/llappearance/lllocaltextureobject.h +++ b/indra/llappearance/lllocaltextureobject.h @@ -1,86 +1,86 @@ -/** - * @file lllocaltextureobject.h - * @brief LLLocalTextureObject class header file - * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LOCALTEXTUREOBJECT_H -#define LL_LOCALTEXTUREOBJECT_H - -#include - -#include "llpointer.h" -#include "llgltexture.h" - -class LLTexLayer; -class LLTexLayerTemplate; -class LLWearable; - -// Stores all relevant information for a single texture -// assumed to have ownership of all objects referred to - -// will delete objects when being replaced or if object is destroyed. -class LLLocalTextureObject -{ -public: - LLLocalTextureObject(); - LLLocalTextureObject(LLGLTexture* image, const LLUUID& id); - LLLocalTextureObject(const LLLocalTextureObject& lto); - ~LLLocalTextureObject(); - - LLGLTexture* getImage() const; - LLTexLayer* getTexLayer(U32 index) const; - LLTexLayer* getTexLayer(const std::string &name); - U32 getNumTexLayers() const; - LLUUID getID() const; - S32 getDiscard() const; - bool getBakedReady() const; - - void setImage(LLGLTexture* new_image); - bool setTexLayer(LLTexLayer *new_tex_layer, U32 index); - bool addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); - bool addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); - bool removeTexLayer(U32 index); - - void setID(LLUUID new_id); - void setDiscard(S32 new_discard); - void setBakedReady(bool ready); - -protected: - -private: - - LLPointer mImage; - // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer - // using shared pointers here only for smart assignment & cleanup - // do NOT create new shared pointers to these objects, or keep pointers to them around - typedef std::vector tex_layer_vec_t; - tex_layer_vec_t mTexLayers; - - LLUUID mID; - - bool mIsBakedReady; - S32 mDiscard; -}; - - #endif // LL_LOCALTEXTUREOBJECT_H - +/** + * @file lllocaltextureobject.h + * @brief LLLocalTextureObject class header file + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LOCALTEXTUREOBJECT_H +#define LL_LOCALTEXTUREOBJECT_H + +#include + +#include "llpointer.h" +#include "llgltexture.h" + +class LLTexLayer; +class LLTexLayerTemplate; +class LLWearable; + +// Stores all relevant information for a single texture +// assumed to have ownership of all objects referred to - +// will delete objects when being replaced or if object is destroyed. +class LLLocalTextureObject +{ +public: + LLLocalTextureObject(); + LLLocalTextureObject(LLGLTexture* image, const LLUUID& id); + LLLocalTextureObject(const LLLocalTextureObject& lto); + ~LLLocalTextureObject(); + + LLGLTexture* getImage() const; + LLTexLayer* getTexLayer(U32 index) const; + LLTexLayer* getTexLayer(const std::string &name); + U32 getNumTexLayers() const; + LLUUID getID() const; + S32 getDiscard() const; + bool getBakedReady() const; + + void setImage(LLGLTexture* new_image); + bool setTexLayer(LLTexLayer *new_tex_layer, U32 index); + bool addTexLayer(LLTexLayer *new_tex_layer, LLWearable *wearable); + bool addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable); + bool removeTexLayer(U32 index); + + void setID(LLUUID new_id); + void setDiscard(S32 new_discard); + void setBakedReady(bool ready); + +protected: + +private: + + LLPointer mImage; + // NOTE: LLLocalTextureObject should be the exclusive owner of mTexEntry and mTexLayer + // using shared pointers here only for smart assignment & cleanup + // do NOT create new shared pointers to these objects, or keep pointers to them around + typedef std::vector tex_layer_vec_t; + tex_layer_vec_t mTexLayers; + + LLUUID mID; + + bool mIsBakedReady; + S32 mDiscard; +}; + + #endif // LL_LOCALTEXTUREOBJECT_H + diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 6c56b192ed..b70e5af69f 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -1,1040 +1,1040 @@ -/** - * @file llpolymesh.cpp - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "linden_common.h" -#include "llpolymesh.h" -#include "llfasttimer.h" -#include "llmemory.h" - -//#include "llviewercontrol.h" -#include "llxmltree.h" -#include "llavatarappearance.h" -#include "llwearable.h" -#include "lldir.h" -#include "llvolume.h" -#include "llendianswizzle.h" - - -#define HEADER_ASCII "Linden Mesh 1.0" -#define HEADER_BINARY "Linden Binary Mesh 1.0" - -//extern LLControlGroup gSavedSettings; // read only - -LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, - const std::string &name); -LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, - const LLVector3 &direction, - const std::string &name); -LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, - F32 scale, - const std::string &name); - -//----------------------------------------------------------------------------- -// Global table of loaded LLPolyMeshes -//----------------------------------------------------------------------------- -LLPolyMesh::LLPolyMeshSharedDataTable LLPolyMesh::sGlobalSharedMeshList; - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData() -//----------------------------------------------------------------------------- -LLPolyMeshSharedData::LLPolyMeshSharedData() -{ - mNumVertices = 0; - mBaseCoords = NULL; - mBaseNormals = NULL; - mBaseBinormals = NULL; - mTexCoords = NULL; - mDetailTexCoords = NULL; - mWeights = NULL; - mHasWeights = false; - mHasDetailTexCoords = false; - - mNumFaces = 0; - mFaces = NULL; - - mNumJointNames = 0; - mJointNames = NULL; - - mTriangleIndices = NULL; - mNumTriangleIndices = 0; - - mReferenceData = NULL; - - mLastIndexOffset = -1; -} - -//----------------------------------------------------------------------------- -// ~LLPolyMeshSharedData() -//----------------------------------------------------------------------------- -LLPolyMeshSharedData::~LLPolyMeshSharedData() -{ - freeMeshData(); - for_each(mMorphData.begin(), mMorphData.end(), DeletePointer()); - mMorphData.clear(); -} - -//----------------------------------------------------------------------------- -// setupLOD() -//----------------------------------------------------------------------------- -void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data) -{ - mReferenceData = reference_data; - - if (reference_data) - { - mBaseCoords = reference_data->mBaseCoords; - mBaseNormals = reference_data->mBaseNormals; - mBaseBinormals = reference_data->mBaseBinormals; - mTexCoords = reference_data->mTexCoords; - mDetailTexCoords = reference_data->mDetailTexCoords; - mWeights = reference_data->mWeights; - mHasWeights = reference_data->mHasWeights; - mHasDetailTexCoords = reference_data->mHasDetailTexCoords; - } -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::freeMeshData() -//----------------------------------------------------------------------------- -void LLPolyMeshSharedData::freeMeshData() -{ - if (!mReferenceData) - { - mNumVertices = 0; - - ll_aligned_free_16(mBaseCoords); - mBaseCoords = NULL; - - ll_aligned_free_16(mBaseNormals); - mBaseNormals = NULL; - - ll_aligned_free_16(mBaseBinormals); - mBaseBinormals = NULL; - - ll_aligned_free_16(mTexCoords); - mTexCoords = NULL; - - ll_aligned_free_16(mDetailTexCoords); - mDetailTexCoords = NULL; - - ll_aligned_free_16(mWeights); - mWeights = NULL; - } - - mNumFaces = 0; - delete [] mFaces; - mFaces = NULL; - - mNumJointNames = 0; - delete [] mJointNames; - mJointNames = NULL; - - delete [] mTriangleIndices; - mTriangleIndices = NULL; - -// mVertFaceMap.deleteAllData(); -} - -// compare_int is used by the qsort function to sort the index array -S32 compare_int(const void *a, const void *b); - -//----------------------------------------------------------------------------- -// genIndices() -//----------------------------------------------------------------------------- -void LLPolyMeshSharedData::genIndices(S32 index_offset) -{ - if (index_offset == mLastIndexOffset) - { - return; - } - - delete []mTriangleIndices; - mTriangleIndices = new U32[mNumTriangleIndices]; - - S32 cur_index = 0; - for (S32 i = 0; i < mNumFaces; i++) - { - mTriangleIndices[cur_index] = mFaces[i][0] + index_offset; - cur_index++; - mTriangleIndices[cur_index] = mFaces[i][1] + index_offset; - cur_index++; - mTriangleIndices[cur_index] = mFaces[i][2] + index_offset; - cur_index++; - } - - mLastIndexOffset = index_offset; -} - -//-------------------------------------------------------------------- -// LLPolyMeshSharedData::getNumKB() -//-------------------------------------------------------------------- -U32 LLPolyMeshSharedData::getNumKB() -{ - U32 num_kb = sizeof(LLPolyMesh); - - if (!isLOD()) - { - num_kb += mNumVertices * - ( sizeof(LLVector3) + // coords - sizeof(LLVector3) + // normals - sizeof(LLVector2) ); // texCoords - } - - if (mHasDetailTexCoords && !isLOD()) - { - num_kb += mNumVertices * sizeof(LLVector2); // detailTexCoords - } - - if (mHasWeights && !isLOD()) - { - num_kb += mNumVertices * sizeof(float); // weights - } - - num_kb += mNumFaces * sizeof(LLPolyFace); // faces - - num_kb /= 1024; - return num_kb; -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::allocateVertexData() -//----------------------------------------------------------------------------- -bool LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) -{ - U32 i; - mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); - mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); - mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); - mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); - mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); - mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); - for (i = 0; i < numVertices; i++) - { - mBaseCoords[i].clear(); - mBaseNormals[i].clear(); - mBaseBinormals[i].clear(); - mTexCoords[i].clear(); - mWeights[i] = 0.f; - } - mNumVertices = numVertices; - return true; -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::allocateFaceData() -//----------------------------------------------------------------------------- -bool LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) -{ - mFaces = new LLPolyFace[ numFaces ]; - mNumFaces = numFaces; - mNumTriangleIndices = mNumFaces * 3; - return true; -} - -//----------------------------------------------------------------------------- -// LLPolyMeshSharedData::allocateJointNames() -//----------------------------------------------------------------------------- -bool LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) -{ - mJointNames = new std::string[ numJointNames ]; - mNumJointNames = numJointNames; - return true; -} - -//-------------------------------------------------------------------- -// LLPolyMeshSharedData::loadMesh() -//-------------------------------------------------------------------- -bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) -{ - //------------------------------------------------------------------------- - // Open the file - //------------------------------------------------------------------------- - if(fileName.empty()) - { - LL_ERRS() << "Filename is Empty!" << LL_ENDL; - return false; - } - LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ - if (!fp) - { - LL_ERRS() << "can't open: " << fileName << LL_ENDL; - return false; - } - - //------------------------------------------------------------------------- - // Read a chunk - //------------------------------------------------------------------------- - char header[128]; /*Flawfinder: ignore*/ - if (fread(header, sizeof(char), 128, fp) != 128) - { - LL_WARNS() << "Short read" << LL_ENDL; - } - - //------------------------------------------------------------------------- - // Check for proper binary header - //------------------------------------------------------------------------- - bool status = false; - if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ - { - LL_DEBUGS() << "Loading " << fileName << LL_ENDL; - - //---------------------------------------------------------------- - // File Header (seek past it) - //---------------------------------------------------------------- - fseek(fp, 24, SEEK_SET); - - //---------------------------------------------------------------- - // HasWeights - //---------------------------------------------------------------- - U8 hasWeights; - size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp); - if (numRead != 1) - { - LL_ERRS() << "can't read HasWeights flag from " << fileName << LL_ENDL; - return false; - } - if (!isLOD()) - { - mHasWeights = hasWeights > 0; - } - - //---------------------------------------------------------------- - // HasDetailTexCoords - //---------------------------------------------------------------- - U8 hasDetailTexCoords; - numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp); - if (numRead != 1) - { - LL_ERRS() << "can't read HasDetailTexCoords flag from " << fileName << LL_ENDL; - return false; - } - - //---------------------------------------------------------------- - // Position - //---------------------------------------------------------------- - LLVector3 position; - numRead = fread(position.mV, sizeof(float), 3, fp); - llendianswizzle(position.mV, sizeof(float), 3); - if (numRead != 3) - { - LL_ERRS() << "can't read Position from " << fileName << LL_ENDL; - return false; - } - setPosition( position ); - - //---------------------------------------------------------------- - // Rotation - //---------------------------------------------------------------- - LLVector3 rotationAngles; - numRead = fread(rotationAngles.mV, sizeof(float), 3, fp); - llendianswizzle(rotationAngles.mV, sizeof(float), 3); - if (numRead != 3) - { - LL_ERRS() << "can't read RotationAngles from " << fileName << LL_ENDL; - return false; - } - - U8 rotationOrder; - numRead = fread(&rotationOrder, sizeof(U8), 1, fp); - - if (numRead != 1) - { - LL_ERRS() << "can't read RotationOrder from " << fileName << LL_ENDL; - return false; - } - - rotationOrder = 0; - - setRotation( mayaQ( rotationAngles.mV[0], - rotationAngles.mV[1], - rotationAngles.mV[2], - (LLQuaternion::Order)rotationOrder ) ); - - //---------------------------------------------------------------- - // Scale - //---------------------------------------------------------------- - LLVector3 scale; - numRead = fread(scale.mV, sizeof(float), 3, fp); - llendianswizzle(scale.mV, sizeof(float), 3); - if (numRead != 3) - { - LL_ERRS() << "can't read Scale from " << fileName << LL_ENDL; - return false; - } - setScale( scale ); - - //------------------------------------------------------------------------- - // Release any existing mesh geometry - //------------------------------------------------------------------------- - freeMeshData(); - - U16 numVertices = 0; - - //---------------------------------------------------------------- - // NumVertices - //---------------------------------------------------------------- - if (!isLOD()) - { - numRead = fread(&numVertices, sizeof(U16), 1, fp); - llendianswizzle(&numVertices, sizeof(U16), 1); - if (numRead != 1) - { - LL_ERRS() << "can't read NumVertices from " << fileName << LL_ENDL; - return false; - } - - allocateVertexData( numVertices ); - - for (U16 i = 0; i < numVertices; ++i) - { - //---------------------------------------------------------------- - // Coords - //---------------------------------------------------------------- - numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); - llendianswizzle(&mBaseCoords[i], sizeof(float), 3); - if (numRead != 3) - { - LL_ERRS() << "can't read Coordinates from " << fileName << LL_ENDL; - return false; - } - } - - for (U16 i = 0; i < numVertices; ++i) - { - //---------------------------------------------------------------- - // Normals - //---------------------------------------------------------------- - numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); - llendianswizzle(&mBaseNormals[i], sizeof(float), 3); - if (numRead != 3) - { - LL_ERRS() << " can't read Normals from " << fileName << LL_ENDL; - return false; - } - } - - for (U16 i = 0; i < numVertices; ++i) - { - //---------------------------------------------------------------- - // Binormals - //---------------------------------------------------------------- - numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); - llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); - if (numRead != 3) - { - LL_ERRS() << " can't read Binormals from " << fileName << LL_ENDL; - return false; - } - } - - //---------------------------------------------------------------- - // TexCoords - //---------------------------------------------------------------- - numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp); - llendianswizzle(mTexCoords, sizeof(float), 2*numVertices); - if (numRead != numVertices) - { - LL_ERRS() << "can't read TexCoords from " << fileName << LL_ENDL; - return false; - } - - //---------------------------------------------------------------- - // DetailTexCoords - //---------------------------------------------------------------- - if (mHasDetailTexCoords) - { - numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp); - llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices); - if (numRead != numVertices) - { - LL_ERRS() << "can't read DetailTexCoords from " << fileName << LL_ENDL; - return false; - } - } - - //---------------------------------------------------------------- - // Weights - //---------------------------------------------------------------- - if (mHasWeights) - { - numRead = fread(mWeights, sizeof(float), numVertices, fp); - llendianswizzle(mWeights, sizeof(float), numVertices); - if (numRead != numVertices) - { - LL_ERRS() << "can't read Weights from " << fileName << LL_ENDL; - return false; - } - } - } - - //---------------------------------------------------------------- - // NumFaces - //---------------------------------------------------------------- - U16 numFaces; - numRead = fread(&numFaces, sizeof(U16), 1, fp); - llendianswizzle(&numFaces, sizeof(U16), 1); - if (numRead != 1) - { - LL_ERRS() << "can't read NumFaces from " << fileName << LL_ENDL; - return false; - } - allocateFaceData( numFaces ); - - - //---------------------------------------------------------------- - // Faces - //---------------------------------------------------------------- - U32 i; - U32 numTris = 0; - for (i = 0; i < numFaces; i++) - { - S16 face[3]; - numRead = fread(face, sizeof(U16), 3, fp); - llendianswizzle(face, sizeof(U16), 3); - if (numRead != 3) - { - LL_ERRS() << "can't read Face[" << i << "] from " << fileName << LL_ENDL; - return false; - } - if (mReferenceData) - { - llassert(face[0] < mReferenceData->mNumVertices); - llassert(face[1] < mReferenceData->mNumVertices); - llassert(face[2] < mReferenceData->mNumVertices); - } - - if (isLOD()) - { - // store largest index in case of LODs - for (S32 j = 0; j < 3; j++) - { - if (face[j] > mNumVertices - 1) - { - mNumVertices = face[j] + 1; - } - } - } - mFaces[i][0] = face[0]; - mFaces[i][1] = face[1]; - mFaces[i][2] = face[2]; - -// S32 j; -// for(j = 0; j < 3; j++) -// { -// std::vector *face_list = mVertFaceMap.getIfThere(face[j]); -// if (!face_list) -// { -// face_list = new std::vector; -// mVertFaceMap.addData(face[j], face_list); -// } -// face_list->put(i); -// } - - numTris++; - } - - LL_DEBUGS() << "verts: " << numVertices - << ", faces: " << numFaces - << ", tris: " << numTris - << LL_ENDL; - - //---------------------------------------------------------------- - // NumSkinJoints - //---------------------------------------------------------------- - if (!isLOD()) - { - U16 numSkinJoints = 0; - if ( mHasWeights ) - { - numRead = fread(&numSkinJoints, sizeof(U16), 1, fp); - llendianswizzle(&numSkinJoints, sizeof(U16), 1); - if (numRead != 1) - { - LL_ERRS() << "can't read NumSkinJoints from " << fileName << LL_ENDL; - return false; - } - allocateJointNames( numSkinJoints ); - } - - //---------------------------------------------------------------- - // SkinJoints - //---------------------------------------------------------------- - for (i=0; i < numSkinJoints; i++) - { - char jointName[64+1]; - numRead = fread(jointName, sizeof(jointName)-1, 1, fp); - jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination - if (numRead != 1) - { - LL_ERRS() << "can't read Skin[" << i << "].Name from " << fileName << LL_ENDL; - return false; - } - - std::string *jn = &mJointNames[i]; - *jn = jointName; - } - - //------------------------------------------------------------------------- - // look for morph section - //------------------------------------------------------------------------- - char morphName[64+1]; - morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination - while(fread(&morphName, sizeof(char), 64, fp) == 64) - { - if (!strcmp(morphName, "End Morphs")) - { - // we reached the end of the morphs - break; - } - std::string morph_name(morphName); - LLPolyMorphData* morph_data = new LLPolyMorphData(morph_name); - - bool result = morph_data->loadBinary(fp, this); - - if (!result) - { - LL_WARNS() << "Failure loading " << morph_name << " from " << fileName << LL_ENDL; - delete morph_data; - continue; - } - - mMorphData.insert(morph_data); - - if (!strcmp(morphName, "Breast_Female_Cleavage")) - { - mMorphData.insert(clone_morph_param_cleavage(morph_data, - .75f, - "Breast_Physics_LeftRight_Driven")); - } - - if (!strcmp(morphName, "Breast_Female_Cleavage")) - { - mMorphData.insert(clone_morph_param_duplicate(morph_data, - "Breast_Physics_InOut_Driven")); - } - if (!strcmp(morphName, "Breast_Gravity")) - { - mMorphData.insert(clone_morph_param_duplicate(morph_data, - "Breast_Physics_UpDown_Driven")); - } - - if (!strcmp(morphName, "Big_Belly_Torso")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Belly_Physics_Torso_UpDown_Driven")); - } - - if (!strcmp(morphName, "Big_Belly_Legs")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Belly_Physics_Legs_UpDown_Driven")); - } - - if (!strcmp(morphName, "skirt_belly")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Belly_Physics_Skirt_UpDown_Driven")); - } - - if (!strcmp(morphName, "Small_Butt")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0,0.05f), - "Butt_Physics_UpDown_Driven")); - } - if (!strcmp(morphName, "Small_Butt")) - { - mMorphData.insert(clone_morph_param_direction(morph_data, - LLVector3(0,0.03f,0), - "Butt_Physics_LeftRight_Driven")); - } - } - - S32 numRemaps; - if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) - { - llendianswizzle(&numRemaps, sizeof(S32), 1); - for (S32 i = 0; i < numRemaps; i++) - { - S32 remapSrc; - S32 remapDst; - if (fread(&remapSrc, sizeof(S32), 1, fp) != 1) - { - LL_ERRS() << "can't read source vertex in vertex remap data" << LL_ENDL; - break; - } - if (fread(&remapDst, sizeof(S32), 1, fp) != 1) - { - LL_ERRS() << "can't read destination vertex in vertex remap data" << LL_ENDL; - break; - } - llendianswizzle(&remapSrc, sizeof(S32), 1); - llendianswizzle(&remapDst, sizeof(S32), 1); - - mSharedVerts[remapSrc] = remapDst; - } - } - } - - status = true; - } - else - { - LL_ERRS() << "invalid mesh file header: " << fileName << LL_ENDL; - status = false; - } - - if (0 == mNumJointNames) - { - allocateJointNames(1); - } - - fclose( fp ); - - return status; -} - -//----------------------------------------------------------------------------- -// getSharedVert() -//----------------------------------------------------------------------------- -const S32 *LLPolyMeshSharedData::getSharedVert(S32 vert) -{ - if (mSharedVerts.count(vert) > 0) - { - return &mSharedVerts[vert]; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getUV() -//----------------------------------------------------------------------------- -const LLVector2 &LLPolyMeshSharedData::getUVs(U32 index) -{ - // TODO: convert all index variables to S32 - llassert((S32)index < mNumVertices); - - return mTexCoords[index]; -} - -//----------------------------------------------------------------------------- -// LLPolyMesh() -//----------------------------------------------------------------------------- -LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh) -{ - llassert(shared_data); - - mSharedData = shared_data; - mReferenceMesh = reference_mesh; - mAvatarp = NULL; - mVertexData = NULL; - - mCurVertexCount = 0; - mFaceIndexCount = 0; - mFaceIndexOffset = 0; - mFaceVertexCount = 0; - mFaceVertexOffset = 0; - - if (shared_data->isLOD() && reference_mesh) - { - mCoords = reference_mesh->mCoords; - mNormals = reference_mesh->mNormals; - mScaledNormals = reference_mesh->mScaledNormals; - mBinormals = reference_mesh->mBinormals; - mScaledBinormals = reference_mesh->mScaledBinormals; - mTexCoords = reference_mesh->mTexCoords; - mClothingWeights = reference_mesh->mClothingWeights; - } - else - { - // Allocate memory without initializing every vector - // NOTE: This makes asusmptions about the size of LLVector[234] - S32 nverts = mSharedData->mNumVertices; - //make sure it's an even number of verts for alignment - nverts += nverts%2; - S32 nfloats = nverts * ( - 4 + //coords - 4 + //normals - 4 + //weights - 2 + //coords - 4 + //scaled normals - 4 + //binormals - 4); //scaled binormals - - //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly - mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); - S32 offset = 0; - mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; - initializeForMorph(); - } -} - - -//----------------------------------------------------------------------------- -// ~LLPolyMesh() -//----------------------------------------------------------------------------- -LLPolyMesh::~LLPolyMesh() -{ - delete_and_clear(mJointRenderData); - ll_aligned_free_16(mVertexData); -} - - -//----------------------------------------------------------------------------- -// LLPolyMesh::getMesh() -//----------------------------------------------------------------------------- -LLPolyMesh *LLPolyMesh::getMesh(const std::string &name, LLPolyMesh* reference_mesh) -{ - //------------------------------------------------------------------------- - // search for an existing mesh by this name - //------------------------------------------------------------------------- - LLPolyMeshSharedData* meshSharedData = get_if_there(sGlobalSharedMeshList, name, (LLPolyMeshSharedData*)NULL); - if (meshSharedData) - { -// LL_INFOS() << "Polymesh " << name << " found in global mesh table." << LL_ENDL; - LLPolyMesh *poly_mesh = new LLPolyMesh(meshSharedData, reference_mesh); - return poly_mesh; - } - - //------------------------------------------------------------------------- - // if not found, create a new one, add it to the list - //------------------------------------------------------------------------- - std::string full_path; - full_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name); - - LLPolyMeshSharedData *mesh_data = new LLPolyMeshSharedData(); - if (reference_mesh) - { - mesh_data->setupLOD(reference_mesh->getSharedData()); - } - if ( ! mesh_data->loadMesh( full_path ) ) - { - delete mesh_data; - return NULL; - } - - LLPolyMesh *poly_mesh = new LLPolyMesh(mesh_data, reference_mesh); - -// LL_INFOS() << "Polymesh " << name << " added to global mesh table." << LL_ENDL; - sGlobalSharedMeshList[name] = poly_mesh->mSharedData; - - return poly_mesh; -} - -//----------------------------------------------------------------------------- -// LLPolyMesh::freeAllMeshes() -//----------------------------------------------------------------------------- -void LLPolyMesh::freeAllMeshes() -{ - // delete each item in the global lists - for_each(sGlobalSharedMeshList.begin(), sGlobalSharedMeshList.end(), DeletePairedPointer()); - sGlobalSharedMeshList.clear(); -} - -LLPolyMeshSharedData *LLPolyMesh::getSharedData() const -{ - return mSharedData; -} - - -//-------------------------------------------------------------------- -// LLPolyMesh::dumpDiagInfo() -//-------------------------------------------------------------------- -void LLPolyMesh::dumpDiagInfo() -{ - // keep track of totals - U32 total_verts = 0; - U32 total_faces = 0; - U32 total_kb = 0; - - std::string buf; - - LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; - LL_INFOS() << " Global PolyMesh Table (DEBUG only)" << LL_ENDL; - LL_INFOS() << " Verts Faces Mem(KB) Name" << LL_ENDL; - LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; - - // print each loaded mesh, and it's memory usage - for(const LLPolyMeshSharedDataTable::value_type& mesh_pair : sGlobalSharedMeshList) - { - const std::string& mesh_name = mesh_pair.first; - LLPolyMeshSharedData* mesh = mesh_pair.second; - - S32 num_verts = mesh->mNumVertices; - S32 num_faces = mesh->mNumFaces; - U32 num_kb = mesh->getNumKB(); - - buf = llformat("%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name.c_str()); - LL_INFOS() << buf << LL_ENDL; - - total_verts += num_verts; - total_faces += num_faces; - total_kb += num_kb; - } - - LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; - buf = llformat("%8d %8d %8d TOTAL", total_verts, total_faces, total_kb ); - LL_INFOS() << buf << LL_ENDL; - LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; -} - -//----------------------------------------------------------------------------- -// getWritableCoords() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableCoords() -{ - return mCoords; -} - -//----------------------------------------------------------------------------- -// getWritableNormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableNormals() -{ - return mNormals; -} - -//----------------------------------------------------------------------------- -// getWritableBinormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableBinormals() -{ - return mBinormals; -} - - -//----------------------------------------------------------------------------- -// getWritableClothingWeights() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getWritableClothingWeights() -{ - return mClothingWeights; -} - -//----------------------------------------------------------------------------- -// getWritableTexCoords() -//----------------------------------------------------------------------------- -LLVector2 *LLPolyMesh::getWritableTexCoords() -{ - return mTexCoords; -} - -//----------------------------------------------------------------------------- -// getScaledNormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getScaledNormals() -{ - return mScaledNormals; -} - -//----------------------------------------------------------------------------- -// getScaledBinormals() -//----------------------------------------------------------------------------- -LLVector4a *LLPolyMesh::getScaledBinormals() -{ - return mScaledBinormals; -} - - -//----------------------------------------------------------------------------- -// initializeForMorph() -//----------------------------------------------------------------------------- -void LLPolyMesh::initializeForMorph() -{ - LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); - - for (U32 i = 0; i < mSharedData->mNumVertices; ++i) - { - mClothingWeights[i].clear(); - } -} - -//----------------------------------------------------------------------------- -// getMorphData() -//----------------------------------------------------------------------------- -LLPolyMorphData* LLPolyMesh::getMorphData(const std::string& morph_name) -{ - if (!mSharedData) - return NULL; - for (LLPolyMorphData* morph_data : mSharedData->mMorphData) - { - if (morph_data->getName() == morph_name) - { - return morph_data; - } - } - return NULL; -} - -//----------------------------------------------------------------------------- -// removeMorphData() -//----------------------------------------------------------------------------- -// // erasing but not deleting seems bad, but fortunately we don't actually use this... -// void LLPolyMesh::removeMorphData(LLPolyMorphData *morph_target) -// { -// if (!mSharedData) -// return; -// mSharedData->mMorphData.erase(morph_target); -// } - -//----------------------------------------------------------------------------- -// deleteAllMorphData() -//----------------------------------------------------------------------------- -// void LLPolyMesh::deleteAllMorphData() -// { -// if (!mSharedData) -// return; - -// for_each(mSharedData->mMorphData.begin(), mSharedData->mMorphData.end(), DeletePointer()); -// mSharedData->mMorphData.clear(); -// } - -//----------------------------------------------------------------------------- -// getWritableWeights() -//----------------------------------------------------------------------------- -F32* LLPolyMesh::getWritableWeights() const -{ - return mSharedData->mWeights; -} - -// End +/** + * @file llpolymesh.cpp + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" +#include "llpolymesh.h" +#include "llfasttimer.h" +#include "llmemory.h" + +//#include "llviewercontrol.h" +#include "llxmltree.h" +#include "llavatarappearance.h" +#include "llwearable.h" +#include "lldir.h" +#include "llvolume.h" +#include "llendianswizzle.h" + + +#define HEADER_ASCII "Linden Mesh 1.0" +#define HEADER_BINARY "Linden Binary Mesh 1.0" + +//extern LLControlGroup gSavedSettings; // read only + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name); +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name); +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name); + +//----------------------------------------------------------------------------- +// Global table of loaded LLPolyMeshes +//----------------------------------------------------------------------------- +LLPolyMesh::LLPolyMeshSharedDataTable LLPolyMesh::sGlobalSharedMeshList; + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData() +//----------------------------------------------------------------------------- +LLPolyMeshSharedData::LLPolyMeshSharedData() +{ + mNumVertices = 0; + mBaseCoords = NULL; + mBaseNormals = NULL; + mBaseBinormals = NULL; + mTexCoords = NULL; + mDetailTexCoords = NULL; + mWeights = NULL; + mHasWeights = false; + mHasDetailTexCoords = false; + + mNumFaces = 0; + mFaces = NULL; + + mNumJointNames = 0; + mJointNames = NULL; + + mTriangleIndices = NULL; + mNumTriangleIndices = 0; + + mReferenceData = NULL; + + mLastIndexOffset = -1; +} + +//----------------------------------------------------------------------------- +// ~LLPolyMeshSharedData() +//----------------------------------------------------------------------------- +LLPolyMeshSharedData::~LLPolyMeshSharedData() +{ + freeMeshData(); + for_each(mMorphData.begin(), mMorphData.end(), DeletePointer()); + mMorphData.clear(); +} + +//----------------------------------------------------------------------------- +// setupLOD() +//----------------------------------------------------------------------------- +void LLPolyMeshSharedData::setupLOD(LLPolyMeshSharedData* reference_data) +{ + mReferenceData = reference_data; + + if (reference_data) + { + mBaseCoords = reference_data->mBaseCoords; + mBaseNormals = reference_data->mBaseNormals; + mBaseBinormals = reference_data->mBaseBinormals; + mTexCoords = reference_data->mTexCoords; + mDetailTexCoords = reference_data->mDetailTexCoords; + mWeights = reference_data->mWeights; + mHasWeights = reference_data->mHasWeights; + mHasDetailTexCoords = reference_data->mHasDetailTexCoords; + } +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::freeMeshData() +//----------------------------------------------------------------------------- +void LLPolyMeshSharedData::freeMeshData() +{ + if (!mReferenceData) + { + mNumVertices = 0; + + ll_aligned_free_16(mBaseCoords); + mBaseCoords = NULL; + + ll_aligned_free_16(mBaseNormals); + mBaseNormals = NULL; + + ll_aligned_free_16(mBaseBinormals); + mBaseBinormals = NULL; + + ll_aligned_free_16(mTexCoords); + mTexCoords = NULL; + + ll_aligned_free_16(mDetailTexCoords); + mDetailTexCoords = NULL; + + ll_aligned_free_16(mWeights); + mWeights = NULL; + } + + mNumFaces = 0; + delete [] mFaces; + mFaces = NULL; + + mNumJointNames = 0; + delete [] mJointNames; + mJointNames = NULL; + + delete [] mTriangleIndices; + mTriangleIndices = NULL; + +// mVertFaceMap.deleteAllData(); +} + +// compare_int is used by the qsort function to sort the index array +S32 compare_int(const void *a, const void *b); + +//----------------------------------------------------------------------------- +// genIndices() +//----------------------------------------------------------------------------- +void LLPolyMeshSharedData::genIndices(S32 index_offset) +{ + if (index_offset == mLastIndexOffset) + { + return; + } + + delete []mTriangleIndices; + mTriangleIndices = new U32[mNumTriangleIndices]; + + S32 cur_index = 0; + for (S32 i = 0; i < mNumFaces; i++) + { + mTriangleIndices[cur_index] = mFaces[i][0] + index_offset; + cur_index++; + mTriangleIndices[cur_index] = mFaces[i][1] + index_offset; + cur_index++; + mTriangleIndices[cur_index] = mFaces[i][2] + index_offset; + cur_index++; + } + + mLastIndexOffset = index_offset; +} + +//-------------------------------------------------------------------- +// LLPolyMeshSharedData::getNumKB() +//-------------------------------------------------------------------- +U32 LLPolyMeshSharedData::getNumKB() +{ + U32 num_kb = sizeof(LLPolyMesh); + + if (!isLOD()) + { + num_kb += mNumVertices * + ( sizeof(LLVector3) + // coords + sizeof(LLVector3) + // normals + sizeof(LLVector2) ); // texCoords + } + + if (mHasDetailTexCoords && !isLOD()) + { + num_kb += mNumVertices * sizeof(LLVector2); // detailTexCoords + } + + if (mHasWeights && !isLOD()) + { + num_kb += mNumVertices * sizeof(float); // weights + } + + num_kb += mNumFaces * sizeof(LLPolyFace); // faces + + num_kb /= 1024; + return num_kb; +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::allocateVertexData() +//----------------------------------------------------------------------------- +bool LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) +{ + U32 i; + mBaseCoords = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseNormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mBaseBinormals = (LLVector4a*) ll_aligned_malloc_16(numVertices*sizeof(LLVector4a)); + mTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mDetailTexCoords = (LLVector2*) ll_aligned_malloc_16(numVertices*sizeof(LLVector2)); + mWeights = (F32*) ll_aligned_malloc_16(numVertices*sizeof(F32)); + for (i = 0; i < numVertices; i++) + { + mBaseCoords[i].clear(); + mBaseNormals[i].clear(); + mBaseBinormals[i].clear(); + mTexCoords[i].clear(); + mWeights[i] = 0.f; + } + mNumVertices = numVertices; + return true; +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::allocateFaceData() +//----------------------------------------------------------------------------- +bool LLPolyMeshSharedData::allocateFaceData( U32 numFaces ) +{ + mFaces = new LLPolyFace[ numFaces ]; + mNumFaces = numFaces; + mNumTriangleIndices = mNumFaces * 3; + return true; +} + +//----------------------------------------------------------------------------- +// LLPolyMeshSharedData::allocateJointNames() +//----------------------------------------------------------------------------- +bool LLPolyMeshSharedData::allocateJointNames( U32 numJointNames ) +{ + mJointNames = new std::string[ numJointNames ]; + mNumJointNames = numJointNames; + return true; +} + +//-------------------------------------------------------------------- +// LLPolyMeshSharedData::loadMesh() +//-------------------------------------------------------------------- +bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) +{ + //------------------------------------------------------------------------- + // Open the file + //------------------------------------------------------------------------- + if(fileName.empty()) + { + LL_ERRS() << "Filename is Empty!" << LL_ENDL; + return false; + } + LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ + if (!fp) + { + LL_ERRS() << "can't open: " << fileName << LL_ENDL; + return false; + } + + //------------------------------------------------------------------------- + // Read a chunk + //------------------------------------------------------------------------- + char header[128]; /*Flawfinder: ignore*/ + if (fread(header, sizeof(char), 128, fp) != 128) + { + LL_WARNS() << "Short read" << LL_ENDL; + } + + //------------------------------------------------------------------------- + // Check for proper binary header + //------------------------------------------------------------------------- + bool status = false; + if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ + { + LL_DEBUGS() << "Loading " << fileName << LL_ENDL; + + //---------------------------------------------------------------- + // File Header (seek past it) + //---------------------------------------------------------------- + fseek(fp, 24, SEEK_SET); + + //---------------------------------------------------------------- + // HasWeights + //---------------------------------------------------------------- + U8 hasWeights; + size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp); + if (numRead != 1) + { + LL_ERRS() << "can't read HasWeights flag from " << fileName << LL_ENDL; + return false; + } + if (!isLOD()) + { + mHasWeights = hasWeights > 0; + } + + //---------------------------------------------------------------- + // HasDetailTexCoords + //---------------------------------------------------------------- + U8 hasDetailTexCoords; + numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp); + if (numRead != 1) + { + LL_ERRS() << "can't read HasDetailTexCoords flag from " << fileName << LL_ENDL; + return false; + } + + //---------------------------------------------------------------- + // Position + //---------------------------------------------------------------- + LLVector3 position; + numRead = fread(position.mV, sizeof(float), 3, fp); + llendianswizzle(position.mV, sizeof(float), 3); + if (numRead != 3) + { + LL_ERRS() << "can't read Position from " << fileName << LL_ENDL; + return false; + } + setPosition( position ); + + //---------------------------------------------------------------- + // Rotation + //---------------------------------------------------------------- + LLVector3 rotationAngles; + numRead = fread(rotationAngles.mV, sizeof(float), 3, fp); + llendianswizzle(rotationAngles.mV, sizeof(float), 3); + if (numRead != 3) + { + LL_ERRS() << "can't read RotationAngles from " << fileName << LL_ENDL; + return false; + } + + U8 rotationOrder; + numRead = fread(&rotationOrder, sizeof(U8), 1, fp); + + if (numRead != 1) + { + LL_ERRS() << "can't read RotationOrder from " << fileName << LL_ENDL; + return false; + } + + rotationOrder = 0; + + setRotation( mayaQ( rotationAngles.mV[0], + rotationAngles.mV[1], + rotationAngles.mV[2], + (LLQuaternion::Order)rotationOrder ) ); + + //---------------------------------------------------------------- + // Scale + //---------------------------------------------------------------- + LLVector3 scale; + numRead = fread(scale.mV, sizeof(float), 3, fp); + llendianswizzle(scale.mV, sizeof(float), 3); + if (numRead != 3) + { + LL_ERRS() << "can't read Scale from " << fileName << LL_ENDL; + return false; + } + setScale( scale ); + + //------------------------------------------------------------------------- + // Release any existing mesh geometry + //------------------------------------------------------------------------- + freeMeshData(); + + U16 numVertices = 0; + + //---------------------------------------------------------------- + // NumVertices + //---------------------------------------------------------------- + if (!isLOD()) + { + numRead = fread(&numVertices, sizeof(U16), 1, fp); + llendianswizzle(&numVertices, sizeof(U16), 1); + if (numRead != 1) + { + LL_ERRS() << "can't read NumVertices from " << fileName << LL_ENDL; + return false; + } + + allocateVertexData( numVertices ); + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Coords + //---------------------------------------------------------------- + numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseCoords[i], sizeof(float), 3); + if (numRead != 3) + { + LL_ERRS() << "can't read Coordinates from " << fileName << LL_ENDL; + return false; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Normals + //---------------------------------------------------------------- + numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseNormals[i], sizeof(float), 3); + if (numRead != 3) + { + LL_ERRS() << " can't read Normals from " << fileName << LL_ENDL; + return false; + } + } + + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Binormals + //---------------------------------------------------------------- + numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); + if (numRead != 3) + { + LL_ERRS() << " can't read Binormals from " << fileName << LL_ENDL; + return false; + } + } + + //---------------------------------------------------------------- + // TexCoords + //---------------------------------------------------------------- + numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp); + llendianswizzle(mTexCoords, sizeof(float), 2*numVertices); + if (numRead != numVertices) + { + LL_ERRS() << "can't read TexCoords from " << fileName << LL_ENDL; + return false; + } + + //---------------------------------------------------------------- + // DetailTexCoords + //---------------------------------------------------------------- + if (mHasDetailTexCoords) + { + numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp); + llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices); + if (numRead != numVertices) + { + LL_ERRS() << "can't read DetailTexCoords from " << fileName << LL_ENDL; + return false; + } + } + + //---------------------------------------------------------------- + // Weights + //---------------------------------------------------------------- + if (mHasWeights) + { + numRead = fread(mWeights, sizeof(float), numVertices, fp); + llendianswizzle(mWeights, sizeof(float), numVertices); + if (numRead != numVertices) + { + LL_ERRS() << "can't read Weights from " << fileName << LL_ENDL; + return false; + } + } + } + + //---------------------------------------------------------------- + // NumFaces + //---------------------------------------------------------------- + U16 numFaces; + numRead = fread(&numFaces, sizeof(U16), 1, fp); + llendianswizzle(&numFaces, sizeof(U16), 1); + if (numRead != 1) + { + LL_ERRS() << "can't read NumFaces from " << fileName << LL_ENDL; + return false; + } + allocateFaceData( numFaces ); + + + //---------------------------------------------------------------- + // Faces + //---------------------------------------------------------------- + U32 i; + U32 numTris = 0; + for (i = 0; i < numFaces; i++) + { + S16 face[3]; + numRead = fread(face, sizeof(U16), 3, fp); + llendianswizzle(face, sizeof(U16), 3); + if (numRead != 3) + { + LL_ERRS() << "can't read Face[" << i << "] from " << fileName << LL_ENDL; + return false; + } + if (mReferenceData) + { + llassert(face[0] < mReferenceData->mNumVertices); + llassert(face[1] < mReferenceData->mNumVertices); + llassert(face[2] < mReferenceData->mNumVertices); + } + + if (isLOD()) + { + // store largest index in case of LODs + for (S32 j = 0; j < 3; j++) + { + if (face[j] > mNumVertices - 1) + { + mNumVertices = face[j] + 1; + } + } + } + mFaces[i][0] = face[0]; + mFaces[i][1] = face[1]; + mFaces[i][2] = face[2]; + +// S32 j; +// for(j = 0; j < 3; j++) +// { +// std::vector *face_list = mVertFaceMap.getIfThere(face[j]); +// if (!face_list) +// { +// face_list = new std::vector; +// mVertFaceMap.addData(face[j], face_list); +// } +// face_list->put(i); +// } + + numTris++; + } + + LL_DEBUGS() << "verts: " << numVertices + << ", faces: " << numFaces + << ", tris: " << numTris + << LL_ENDL; + + //---------------------------------------------------------------- + // NumSkinJoints + //---------------------------------------------------------------- + if (!isLOD()) + { + U16 numSkinJoints = 0; + if ( mHasWeights ) + { + numRead = fread(&numSkinJoints, sizeof(U16), 1, fp); + llendianswizzle(&numSkinJoints, sizeof(U16), 1); + if (numRead != 1) + { + LL_ERRS() << "can't read NumSkinJoints from " << fileName << LL_ENDL; + return false; + } + allocateJointNames( numSkinJoints ); + } + + //---------------------------------------------------------------- + // SkinJoints + //---------------------------------------------------------------- + for (i=0; i < numSkinJoints; i++) + { + char jointName[64+1]; + numRead = fread(jointName, sizeof(jointName)-1, 1, fp); + jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination + if (numRead != 1) + { + LL_ERRS() << "can't read Skin[" << i << "].Name from " << fileName << LL_ENDL; + return false; + } + + std::string *jn = &mJointNames[i]; + *jn = jointName; + } + + //------------------------------------------------------------------------- + // look for morph section + //------------------------------------------------------------------------- + char morphName[64+1]; + morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination + while(fread(&morphName, sizeof(char), 64, fp) == 64) + { + if (!strcmp(morphName, "End Morphs")) + { + // we reached the end of the morphs + break; + } + std::string morph_name(morphName); + LLPolyMorphData* morph_data = new LLPolyMorphData(morph_name); + + bool result = morph_data->loadBinary(fp, this); + + if (!result) + { + LL_WARNS() << "Failure loading " << morph_name << " from " << fileName << LL_ENDL; + delete morph_data; + continue; + } + + mMorphData.insert(morph_data); + + if (!strcmp(morphName, "Breast_Female_Cleavage")) + { + mMorphData.insert(clone_morph_param_cleavage(morph_data, + .75f, + "Breast_Physics_LeftRight_Driven")); + } + + if (!strcmp(morphName, "Breast_Female_Cleavage")) + { + mMorphData.insert(clone_morph_param_duplicate(morph_data, + "Breast_Physics_InOut_Driven")); + } + if (!strcmp(morphName, "Breast_Gravity")) + { + mMorphData.insert(clone_morph_param_duplicate(morph_data, + "Breast_Physics_UpDown_Driven")); + } + + if (!strcmp(morphName, "Big_Belly_Torso")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Torso_UpDown_Driven")); + } + + if (!strcmp(morphName, "Big_Belly_Legs")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Legs_UpDown_Driven")); + } + + if (!strcmp(morphName, "skirt_belly")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Belly_Physics_Skirt_UpDown_Driven")); + } + + if (!strcmp(morphName, "Small_Butt")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0,0.05f), + "Butt_Physics_UpDown_Driven")); + } + if (!strcmp(morphName, "Small_Butt")) + { + mMorphData.insert(clone_morph_param_direction(morph_data, + LLVector3(0,0.03f,0), + "Butt_Physics_LeftRight_Driven")); + } + } + + S32 numRemaps; + if (fread(&numRemaps, sizeof(S32), 1, fp) == 1) + { + llendianswizzle(&numRemaps, sizeof(S32), 1); + for (S32 i = 0; i < numRemaps; i++) + { + S32 remapSrc; + S32 remapDst; + if (fread(&remapSrc, sizeof(S32), 1, fp) != 1) + { + LL_ERRS() << "can't read source vertex in vertex remap data" << LL_ENDL; + break; + } + if (fread(&remapDst, sizeof(S32), 1, fp) != 1) + { + LL_ERRS() << "can't read destination vertex in vertex remap data" << LL_ENDL; + break; + } + llendianswizzle(&remapSrc, sizeof(S32), 1); + llendianswizzle(&remapDst, sizeof(S32), 1); + + mSharedVerts[remapSrc] = remapDst; + } + } + } + + status = true; + } + else + { + LL_ERRS() << "invalid mesh file header: " << fileName << LL_ENDL; + status = false; + } + + if (0 == mNumJointNames) + { + allocateJointNames(1); + } + + fclose( fp ); + + return status; +} + +//----------------------------------------------------------------------------- +// getSharedVert() +//----------------------------------------------------------------------------- +const S32 *LLPolyMeshSharedData::getSharedVert(S32 vert) +{ + if (mSharedVerts.count(vert) > 0) + { + return &mSharedVerts[vert]; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getUV() +//----------------------------------------------------------------------------- +const LLVector2 &LLPolyMeshSharedData::getUVs(U32 index) +{ + // TODO: convert all index variables to S32 + llassert((S32)index < mNumVertices); + + return mTexCoords[index]; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh() +//----------------------------------------------------------------------------- +LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh) +{ + llassert(shared_data); + + mSharedData = shared_data; + mReferenceMesh = reference_mesh; + mAvatarp = NULL; + mVertexData = NULL; + + mCurVertexCount = 0; + mFaceIndexCount = 0; + mFaceIndexOffset = 0; + mFaceVertexCount = 0; + mFaceVertexOffset = 0; + + if (shared_data->isLOD() && reference_mesh) + { + mCoords = reference_mesh->mCoords; + mNormals = reference_mesh->mNormals; + mScaledNormals = reference_mesh->mScaledNormals; + mBinormals = reference_mesh->mBinormals; + mScaledBinormals = reference_mesh->mScaledBinormals; + mTexCoords = reference_mesh->mTexCoords; + mClothingWeights = reference_mesh->mClothingWeights; + } + else + { + // Allocate memory without initializing every vector + // NOTE: This makes asusmptions about the size of LLVector[234] + S32 nverts = mSharedData->mNumVertices; + //make sure it's an even number of verts for alignment + nverts += nverts%2; + S32 nfloats = nverts * ( + 4 + //coords + 4 + //normals + 4 + //weights + 2 + //coords + 4 + //scaled normals + 4 + //binormals + 4); //scaled binormals + + //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly + mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); + S32 offset = 0; + mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + initializeForMorph(); + } +} + + +//----------------------------------------------------------------------------- +// ~LLPolyMesh() +//----------------------------------------------------------------------------- +LLPolyMesh::~LLPolyMesh() +{ + delete_and_clear(mJointRenderData); + ll_aligned_free_16(mVertexData); +} + + +//----------------------------------------------------------------------------- +// LLPolyMesh::getMesh() +//----------------------------------------------------------------------------- +LLPolyMesh *LLPolyMesh::getMesh(const std::string &name, LLPolyMesh* reference_mesh) +{ + //------------------------------------------------------------------------- + // search for an existing mesh by this name + //------------------------------------------------------------------------- + LLPolyMeshSharedData* meshSharedData = get_if_there(sGlobalSharedMeshList, name, (LLPolyMeshSharedData*)NULL); + if (meshSharedData) + { +// LL_INFOS() << "Polymesh " << name << " found in global mesh table." << LL_ENDL; + LLPolyMesh *poly_mesh = new LLPolyMesh(meshSharedData, reference_mesh); + return poly_mesh; + } + + //------------------------------------------------------------------------- + // if not found, create a new one, add it to the list + //------------------------------------------------------------------------- + std::string full_path; + full_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name); + + LLPolyMeshSharedData *mesh_data = new LLPolyMeshSharedData(); + if (reference_mesh) + { + mesh_data->setupLOD(reference_mesh->getSharedData()); + } + if ( ! mesh_data->loadMesh( full_path ) ) + { + delete mesh_data; + return NULL; + } + + LLPolyMesh *poly_mesh = new LLPolyMesh(mesh_data, reference_mesh); + +// LL_INFOS() << "Polymesh " << name << " added to global mesh table." << LL_ENDL; + sGlobalSharedMeshList[name] = poly_mesh->mSharedData; + + return poly_mesh; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh::freeAllMeshes() +//----------------------------------------------------------------------------- +void LLPolyMesh::freeAllMeshes() +{ + // delete each item in the global lists + for_each(sGlobalSharedMeshList.begin(), sGlobalSharedMeshList.end(), DeletePairedPointer()); + sGlobalSharedMeshList.clear(); +} + +LLPolyMeshSharedData *LLPolyMesh::getSharedData() const +{ + return mSharedData; +} + + +//-------------------------------------------------------------------- +// LLPolyMesh::dumpDiagInfo() +//-------------------------------------------------------------------- +void LLPolyMesh::dumpDiagInfo() +{ + // keep track of totals + U32 total_verts = 0; + U32 total_faces = 0; + U32 total_kb = 0; + + std::string buf; + + LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; + LL_INFOS() << " Global PolyMesh Table (DEBUG only)" << LL_ENDL; + LL_INFOS() << " Verts Faces Mem(KB) Name" << LL_ENDL; + LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; + + // print each loaded mesh, and it's memory usage + for(const LLPolyMeshSharedDataTable::value_type& mesh_pair : sGlobalSharedMeshList) + { + const std::string& mesh_name = mesh_pair.first; + LLPolyMeshSharedData* mesh = mesh_pair.second; + + S32 num_verts = mesh->mNumVertices; + S32 num_faces = mesh->mNumFaces; + U32 num_kb = mesh->getNumKB(); + + buf = llformat("%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name.c_str()); + LL_INFOS() << buf << LL_ENDL; + + total_verts += num_verts; + total_faces += num_faces; + total_kb += num_kb; + } + + LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; + buf = llformat("%8d %8d %8d TOTAL", total_verts, total_faces, total_kb ); + LL_INFOS() << buf << LL_ENDL; + LL_INFOS() << "-----------------------------------------------------" << LL_ENDL; +} + +//----------------------------------------------------------------------------- +// getWritableCoords() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableCoords() +{ + return mCoords; +} + +//----------------------------------------------------------------------------- +// getWritableNormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableNormals() +{ + return mNormals; +} + +//----------------------------------------------------------------------------- +// getWritableBinormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableBinormals() +{ + return mBinormals; +} + + +//----------------------------------------------------------------------------- +// getWritableClothingWeights() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getWritableClothingWeights() +{ + return mClothingWeights; +} + +//----------------------------------------------------------------------------- +// getWritableTexCoords() +//----------------------------------------------------------------------------- +LLVector2 *LLPolyMesh::getWritableTexCoords() +{ + return mTexCoords; +} + +//----------------------------------------------------------------------------- +// getScaledNormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getScaledNormals() +{ + return mScaledNormals; +} + +//----------------------------------------------------------------------------- +// getScaledBinormals() +//----------------------------------------------------------------------------- +LLVector4a *LLPolyMesh::getScaledBinormals() +{ + return mScaledBinormals; +} + + +//----------------------------------------------------------------------------- +// initializeForMorph() +//----------------------------------------------------------------------------- +void LLPolyMesh::initializeForMorph() +{ + LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); + + for (U32 i = 0; i < mSharedData->mNumVertices; ++i) + { + mClothingWeights[i].clear(); + } +} + +//----------------------------------------------------------------------------- +// getMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData* LLPolyMesh::getMorphData(const std::string& morph_name) +{ + if (!mSharedData) + return NULL; + for (LLPolyMorphData* morph_data : mSharedData->mMorphData) + { + if (morph_data->getName() == morph_name) + { + return morph_data; + } + } + return NULL; +} + +//----------------------------------------------------------------------------- +// removeMorphData() +//----------------------------------------------------------------------------- +// // erasing but not deleting seems bad, but fortunately we don't actually use this... +// void LLPolyMesh::removeMorphData(LLPolyMorphData *morph_target) +// { +// if (!mSharedData) +// return; +// mSharedData->mMorphData.erase(morph_target); +// } + +//----------------------------------------------------------------------------- +// deleteAllMorphData() +//----------------------------------------------------------------------------- +// void LLPolyMesh::deleteAllMorphData() +// { +// if (!mSharedData) +// return; + +// for_each(mSharedData->mMorphData.begin(), mSharedData->mMorphData.end(), DeletePointer()); +// mSharedData->mMorphData.clear(); +// } + +//----------------------------------------------------------------------------- +// getWritableWeights() +//----------------------------------------------------------------------------- +F32* LLPolyMesh::getWritableWeights() const +{ + return mSharedData->mWeights; +} + +// End diff --git a/indra/llappearance/llpolymesh.h b/indra/llappearance/llpolymesh.h index d3b349c987..5f8b4eab02 100644 --- a/indra/llappearance/llpolymesh.h +++ b/indra/llappearance/llpolymesh.h @@ -1,368 +1,368 @@ -/** - * @file llpolymesh.h - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPOLYMESHINTERFACE_H -#define LL_LLPOLYMESHINTERFACE_H - -#include -#include -#include "llstl.h" - -#include "v3math.h" -#include "v2math.h" -#include "llquaternion.h" -#include "llpolymorph.h" -#include "lljoint.h" - -class LLSkinJoint; -class LLAvatarAppearance; -class LLWearable; - -//#define USE_STRIPS // Use tri-strips for rendering. - -//----------------------------------------------------------------------------- -// LLPolyFace -// A set of 4 vertex indices. -// An LLPolyFace can represent either a triangle or quad. -// If the last index is -1, it's a triangle. -//----------------------------------------------------------------------------- -typedef S32 LLPolyFace[3]; - -//struct PrimitiveGroup; - -//----------------------------------------------------------------------------- -// LLPolyMesh -// A polyhedra consisting of any number of triangles and quads. -// All instances contain a set of faces, and optionally may include -// faces grouped into named face sets. -//----------------------------------------------------------------------------- -class LLPolyMorphTarget; - -class LLPolyMeshSharedData -{ - friend class LLPolyMesh; -private: - // transform data - LLVector3 mPosition; - LLQuaternion mRotation; - LLVector3 mScale; - - // vertex data - S32 mNumVertices; - LLVector4a *mBaseCoords; - LLVector4a *mBaseNormals; - LLVector4a *mBaseBinormals; - LLVector2 *mTexCoords; - LLVector2 *mDetailTexCoords; - F32 *mWeights; - - bool mHasWeights; - bool mHasDetailTexCoords; - - // face data - S32 mNumFaces; - LLPolyFace *mFaces; - - // face set data - U32 mNumJointNames; - std::string* mJointNames; - - // morph targets - typedef std::set morphdata_list_t; - morphdata_list_t mMorphData; - - std::map mSharedVerts; - - LLPolyMeshSharedData* mReferenceData; - S32 mLastIndexOffset; - -public: - // Temporarily... - // Triangle indices - U32 mNumTriangleIndices; - U32 *mTriangleIndices; - -public: - LLPolyMeshSharedData(); - ~LLPolyMeshSharedData(); - -private: - void setupLOD(LLPolyMeshSharedData* reference_data); - - // Frees all mesh memory resources - void freeMeshData(); - - void setPosition( const LLVector3 &pos ) { mPosition = pos; } - void setRotation( const LLQuaternion &rot ) { mRotation = rot; } - void setScale( const LLVector3 &scale ) { mScale = scale; } - - bool allocateVertexData( U32 numVertices ); - - bool allocateFaceData( U32 numFaces ); - - bool allocateJointNames( U32 numJointNames ); - - // Retrieve the number of KB of memory used by this instance - U32 getNumKB(); - - // Load mesh data from file - bool loadMesh( const std::string& fileName ); - -public: - void genIndices(S32 offset); - - const LLVector2 &getUVs(U32 index); - - const S32 *getSharedVert(S32 vert); - - bool isLOD() { return (mReferenceData != NULL); } -}; - - -class LLJointRenderData -{ -public: - LLJointRenderData(const LLMatrix4* world_matrix, LLSkinJoint* skin_joint) : mWorldMatrix(world_matrix), mSkinJoint(skin_joint) {} - ~LLJointRenderData(){} - - const LLMatrix4* mWorldMatrix; - LLSkinJoint* mSkinJoint; -}; - - -class LLPolyMesh -{ -public: - - // Constructor - LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh); - - // Destructor - ~LLPolyMesh(); - - // Requests a mesh by name. - // If the mesh already exists in the global mesh table, it is returned, - // otherwise it is loaded from file, added to the table, and returned. - static LLPolyMesh *getMesh( const std::string &name, LLPolyMesh* reference_mesh = NULL); - - // Frees all loaded meshes. - // This should only be called once you know there are no outstanding - // references to these objects. Generally, upon exit of the application. - static void freeAllMeshes(); - - //-------------------------------------------------------------------- - // Transform Data Access - //-------------------------------------------------------------------- - // Get position - const LLVector3 &getPosition() { - llassert (mSharedData); - return mSharedData->mPosition; - } - - // Get rotation - const LLQuaternion &getRotation() { - llassert (mSharedData); - return mSharedData->mRotation; - } - - // Get scale - const LLVector3 &getScale() { - llassert (mSharedData); - return mSharedData->mScale; - } - - //-------------------------------------------------------------------- - // Vertex Data Access - //-------------------------------------------------------------------- - // Get number of vertices - U32 getNumVertices() { - llassert (mSharedData); - return mSharedData->mNumVertices; - } - - // Returns whether or not the mesh has detail texture coords - bool hasDetailTexCoords() { - llassert (mSharedData); - return mSharedData->mHasDetailTexCoords; - } - - // Returns whether or not the mesh has vertex weights - bool hasWeights() const{ - llassert (mSharedData); - return mSharedData->mHasWeights; - } - - // Get coords - const LLVector4a *getCoords() const{ - return mCoords; - } - - // non const version - LLVector4a *getWritableCoords(); - - // Get normals - const LLVector4a *getNormals() const{ - return mNormals; - } - - // Get normals - const LLVector4a *getBinormals() const{ - return mBinormals; - } - - // Get base mesh normals - const LLVector4a *getBaseNormals() const{ - llassert(mSharedData); - return mSharedData->mBaseNormals; - } - - // Get base mesh normals - const LLVector4a *getBaseBinormals() const{ - llassert(mSharedData); - return mSharedData->mBaseBinormals; - } - - // intermediate morphed normals and output normals - LLVector4a *getWritableNormals(); - LLVector4a *getScaledNormals(); - - LLVector4a *getWritableBinormals(); - LLVector4a *getScaledBinormals(); - - // Get texCoords - const LLVector2 *getTexCoords() const { - return mTexCoords; - } - - // non const version - LLVector2 *getWritableTexCoords(); - - // Get detailTexCoords - const LLVector2 *getDetailTexCoords() const { - llassert (mSharedData); - return mSharedData->mDetailTexCoords; - } - - // Get weights - const F32 *getWeights() const { - llassert (mSharedData); - return mSharedData->mWeights; - } - - F32 *getWritableWeights() const; - - LLVector4a *getWritableClothingWeights(); - - const LLVector4a *getClothingWeights() - { - return mClothingWeights; - } - - //-------------------------------------------------------------------- - // Face Data Access - //-------------------------------------------------------------------- - // Get number of faces - S32 getNumFaces() { - llassert (mSharedData); - return mSharedData->mNumFaces; - } - - // Get faces - LLPolyFace *getFaces() { - llassert (mSharedData); - return mSharedData->mFaces; - } - - U32 getNumJointNames() { - llassert (mSharedData); - return mSharedData->mNumJointNames; - } - - std::string *getJointNames() { - llassert (mSharedData); - return mSharedData->mJointNames; - } - - LLPolyMorphData* getMorphData(const std::string& morph_name); -// void removeMorphData(LLPolyMorphData *morph_target); -// void deleteAllMorphData(); - - LLPolyMeshSharedData *getSharedData() const; - LLPolyMesh *getReferenceMesh() { return mReferenceMesh ? mReferenceMesh : this; } - - // Get indices - U32* getIndices() { return mSharedData ? mSharedData->mTriangleIndices : NULL; } - - bool isLOD() { return mSharedData && mSharedData->isLOD(); } - - void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; } - LLAvatarAppearance* getAvatar() { return mAvatarp; } - - std::vector mJointRenderData; - - U32 mFaceVertexOffset; - U32 mFaceVertexCount; - U32 mFaceIndexOffset; - U32 mFaceIndexCount; - U32 mCurVertexCount; -private: - void initializeForMorph(); - - // Dumps diagnostic information about the global mesh table - static void dumpDiagInfo(); - -protected: - // mesh data shared across all instances of a given mesh - LLPolyMeshSharedData *mSharedData; - // Single array of floats for allocation / deletion - F32 *mVertexData; - // deformed vertices (resulting from application of morph targets) - LLVector4a *mCoords; - // deformed normals (resulting from application of morph targets) - LLVector4a *mScaledNormals; - // output normals (after normalization) - LLVector4a *mNormals; - // deformed binormals (resulting from application of morph targets) - LLVector4a *mScaledBinormals; - // output binormals (after normalization) - LLVector4a *mBinormals; - // weight values that mark verts as clothing/skin - LLVector4a *mClothingWeights; - // output texture coordinates - LLVector2 *mTexCoords; - - LLPolyMesh *mReferenceMesh; - - // global mesh list - typedef std::map LLPolyMeshSharedDataTable; - static LLPolyMeshSharedDataTable sGlobalSharedMeshList; - - // Backlink only; don't make this an LLPointer. - LLAvatarAppearance* mAvatarp; -}; - -#endif // LL_LLPOLYMESHINTERFACE_H - +/** + * @file llpolymesh.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYMESHINTERFACE_H +#define LL_LLPOLYMESHINTERFACE_H + +#include +#include +#include "llstl.h" + +#include "v3math.h" +#include "v2math.h" +#include "llquaternion.h" +#include "llpolymorph.h" +#include "lljoint.h" + +class LLSkinJoint; +class LLAvatarAppearance; +class LLWearable; + +//#define USE_STRIPS // Use tri-strips for rendering. + +//----------------------------------------------------------------------------- +// LLPolyFace +// A set of 4 vertex indices. +// An LLPolyFace can represent either a triangle or quad. +// If the last index is -1, it's a triangle. +//----------------------------------------------------------------------------- +typedef S32 LLPolyFace[3]; + +//struct PrimitiveGroup; + +//----------------------------------------------------------------------------- +// LLPolyMesh +// A polyhedra consisting of any number of triangles and quads. +// All instances contain a set of faces, and optionally may include +// faces grouped into named face sets. +//----------------------------------------------------------------------------- +class LLPolyMorphTarget; + +class LLPolyMeshSharedData +{ + friend class LLPolyMesh; +private: + // transform data + LLVector3 mPosition; + LLQuaternion mRotation; + LLVector3 mScale; + + // vertex data + S32 mNumVertices; + LLVector4a *mBaseCoords; + LLVector4a *mBaseNormals; + LLVector4a *mBaseBinormals; + LLVector2 *mTexCoords; + LLVector2 *mDetailTexCoords; + F32 *mWeights; + + bool mHasWeights; + bool mHasDetailTexCoords; + + // face data + S32 mNumFaces; + LLPolyFace *mFaces; + + // face set data + U32 mNumJointNames; + std::string* mJointNames; + + // morph targets + typedef std::set morphdata_list_t; + morphdata_list_t mMorphData; + + std::map mSharedVerts; + + LLPolyMeshSharedData* mReferenceData; + S32 mLastIndexOffset; + +public: + // Temporarily... + // Triangle indices + U32 mNumTriangleIndices; + U32 *mTriangleIndices; + +public: + LLPolyMeshSharedData(); + ~LLPolyMeshSharedData(); + +private: + void setupLOD(LLPolyMeshSharedData* reference_data); + + // Frees all mesh memory resources + void freeMeshData(); + + void setPosition( const LLVector3 &pos ) { mPosition = pos; } + void setRotation( const LLQuaternion &rot ) { mRotation = rot; } + void setScale( const LLVector3 &scale ) { mScale = scale; } + + bool allocateVertexData( U32 numVertices ); + + bool allocateFaceData( U32 numFaces ); + + bool allocateJointNames( U32 numJointNames ); + + // Retrieve the number of KB of memory used by this instance + U32 getNumKB(); + + // Load mesh data from file + bool loadMesh( const std::string& fileName ); + +public: + void genIndices(S32 offset); + + const LLVector2 &getUVs(U32 index); + + const S32 *getSharedVert(S32 vert); + + bool isLOD() { return (mReferenceData != NULL); } +}; + + +class LLJointRenderData +{ +public: + LLJointRenderData(const LLMatrix4* world_matrix, LLSkinJoint* skin_joint) : mWorldMatrix(world_matrix), mSkinJoint(skin_joint) {} + ~LLJointRenderData(){} + + const LLMatrix4* mWorldMatrix; + LLSkinJoint* mSkinJoint; +}; + + +class LLPolyMesh +{ +public: + + // Constructor + LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_mesh); + + // Destructor + ~LLPolyMesh(); + + // Requests a mesh by name. + // If the mesh already exists in the global mesh table, it is returned, + // otherwise it is loaded from file, added to the table, and returned. + static LLPolyMesh *getMesh( const std::string &name, LLPolyMesh* reference_mesh = NULL); + + // Frees all loaded meshes. + // This should only be called once you know there are no outstanding + // references to these objects. Generally, upon exit of the application. + static void freeAllMeshes(); + + //-------------------------------------------------------------------- + // Transform Data Access + //-------------------------------------------------------------------- + // Get position + const LLVector3 &getPosition() { + llassert (mSharedData); + return mSharedData->mPosition; + } + + // Get rotation + const LLQuaternion &getRotation() { + llassert (mSharedData); + return mSharedData->mRotation; + } + + // Get scale + const LLVector3 &getScale() { + llassert (mSharedData); + return mSharedData->mScale; + } + + //-------------------------------------------------------------------- + // Vertex Data Access + //-------------------------------------------------------------------- + // Get number of vertices + U32 getNumVertices() { + llassert (mSharedData); + return mSharedData->mNumVertices; + } + + // Returns whether or not the mesh has detail texture coords + bool hasDetailTexCoords() { + llassert (mSharedData); + return mSharedData->mHasDetailTexCoords; + } + + // Returns whether or not the mesh has vertex weights + bool hasWeights() const{ + llassert (mSharedData); + return mSharedData->mHasWeights; + } + + // Get coords + const LLVector4a *getCoords() const{ + return mCoords; + } + + // non const version + LLVector4a *getWritableCoords(); + + // Get normals + const LLVector4a *getNormals() const{ + return mNormals; + } + + // Get normals + const LLVector4a *getBinormals() const{ + return mBinormals; + } + + // Get base mesh normals + const LLVector4a *getBaseNormals() const{ + llassert(mSharedData); + return mSharedData->mBaseNormals; + } + + // Get base mesh normals + const LLVector4a *getBaseBinormals() const{ + llassert(mSharedData); + return mSharedData->mBaseBinormals; + } + + // intermediate morphed normals and output normals + LLVector4a *getWritableNormals(); + LLVector4a *getScaledNormals(); + + LLVector4a *getWritableBinormals(); + LLVector4a *getScaledBinormals(); + + // Get texCoords + const LLVector2 *getTexCoords() const { + return mTexCoords; + } + + // non const version + LLVector2 *getWritableTexCoords(); + + // Get detailTexCoords + const LLVector2 *getDetailTexCoords() const { + llassert (mSharedData); + return mSharedData->mDetailTexCoords; + } + + // Get weights + const F32 *getWeights() const { + llassert (mSharedData); + return mSharedData->mWeights; + } + + F32 *getWritableWeights() const; + + LLVector4a *getWritableClothingWeights(); + + const LLVector4a *getClothingWeights() + { + return mClothingWeights; + } + + //-------------------------------------------------------------------- + // Face Data Access + //-------------------------------------------------------------------- + // Get number of faces + S32 getNumFaces() { + llassert (mSharedData); + return mSharedData->mNumFaces; + } + + // Get faces + LLPolyFace *getFaces() { + llassert (mSharedData); + return mSharedData->mFaces; + } + + U32 getNumJointNames() { + llassert (mSharedData); + return mSharedData->mNumJointNames; + } + + std::string *getJointNames() { + llassert (mSharedData); + return mSharedData->mJointNames; + } + + LLPolyMorphData* getMorphData(const std::string& morph_name); +// void removeMorphData(LLPolyMorphData *morph_target); +// void deleteAllMorphData(); + + LLPolyMeshSharedData *getSharedData() const; + LLPolyMesh *getReferenceMesh() { return mReferenceMesh ? mReferenceMesh : this; } + + // Get indices + U32* getIndices() { return mSharedData ? mSharedData->mTriangleIndices : NULL; } + + bool isLOD() { return mSharedData && mSharedData->isLOD(); } + + void setAvatar(LLAvatarAppearance* avatarp) { mAvatarp = avatarp; } + LLAvatarAppearance* getAvatar() { return mAvatarp; } + + std::vector mJointRenderData; + + U32 mFaceVertexOffset; + U32 mFaceVertexCount; + U32 mFaceIndexOffset; + U32 mFaceIndexCount; + U32 mCurVertexCount; +private: + void initializeForMorph(); + + // Dumps diagnostic information about the global mesh table + static void dumpDiagInfo(); + +protected: + // mesh data shared across all instances of a given mesh + LLPolyMeshSharedData *mSharedData; + // Single array of floats for allocation / deletion + F32 *mVertexData; + // deformed vertices (resulting from application of morph targets) + LLVector4a *mCoords; + // deformed normals (resulting from application of morph targets) + LLVector4a *mScaledNormals; + // output normals (after normalization) + LLVector4a *mNormals; + // deformed binormals (resulting from application of morph targets) + LLVector4a *mScaledBinormals; + // output binormals (after normalization) + LLVector4a *mBinormals; + // weight values that mark verts as clothing/skin + LLVector4a *mClothingWeights; + // output texture coordinates + LLVector2 *mTexCoords; + + LLPolyMesh *mReferenceMesh; + + // global mesh list + typedef std::map LLPolyMeshSharedDataTable; + static LLPolyMeshSharedDataTable sGlobalSharedMeshList; + + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance* mAvatarp; +}; + +#endif // LL_LLPOLYMESHINTERFACE_H + diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 8665ac2433..d8109d79c2 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -1,844 +1,844 @@ -/** - * @file llpolymorph.cpp - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- - -#include "llpolymorph.h" -#include "llavatarappearance.h" -#include "llavatarjoint.h" -#include "llwearable.h" -#include "llxmltree.h" -#include "llendianswizzle.h" -#include "llpolymesh.h" -#include "llfasttimer.h" - -//#include "../tools/imdebug/imdebug.h" - -const F32 NORMAL_SOFTEN_FACTOR = 0.65f; - -//----------------------------------------------------------------------------- -// LLPolyMorphData() -//----------------------------------------------------------------------------- -LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) - : mName(morph_name) -{ - mNumIndices = 0; - mCurrentIndex = 0; - mTotalDistortion = 0.f; - mAvgDistortion.clear(); - mMaxDistortion = 0.f; - mVertexIndices = NULL; - mCoords = NULL; - mNormals = NULL; - mBinormals = NULL; - mTexCoords = NULL; - - mMesh = NULL; -} - -LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : - mName(rhs.mName), - mNumIndices(rhs.mNumIndices), - mTotalDistortion(rhs.mTotalDistortion), - mAvgDistortion(rhs.mAvgDistortion), - mMaxDistortion(rhs.mMaxDistortion), - mVertexIndices(NULL), - mCoords(NULL), - mNormals(NULL), - mBinormals(NULL), - mTexCoords(NULL) -{ - const S32 numVertices = mNumIndices; - - U32 size = sizeof(LLVector4a)*numVertices; - - mCoords = static_cast( ll_aligned_malloc_16(size) ); - mNormals = static_cast( ll_aligned_malloc_16(size) ); - mBinormals = static_cast( ll_aligned_malloc_16(size) ); - mTexCoords = new LLVector2[numVertices]; - mVertexIndices = new U32[numVertices]; - - for (S32 v=0; v < numVertices; v++) - { - mCoords[v] = rhs.mCoords[v]; - mNormals[v] = rhs.mNormals[v]; - mBinormals[v] = rhs.mBinormals[v]; - mTexCoords[v] = rhs.mTexCoords[v]; - mVertexIndices[v] = rhs.mVertexIndices[v]; - } -} - -//----------------------------------------------------------------------------- -// ~LLPolyMorphData() -//----------------------------------------------------------------------------- -LLPolyMorphData::~LLPolyMorphData() -{ - freeData(); -} - -//----------------------------------------------------------------------------- -// loadBinary() -//----------------------------------------------------------------------------- -bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) -{ - S32 numVertices; - S32 numRead; - - numRead = fread(&numVertices, sizeof(S32), 1, fp); - llendianswizzle(&numVertices, sizeof(S32), 1); - if (numRead != 1) - { - LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL; - return false; - } - - //------------------------------------------------------------------------- - // free any existing data - //------------------------------------------------------------------------- - freeData(); - - //------------------------------------------------------------------------- - // allocate vertices - //------------------------------------------------------------------------- - - U32 size = sizeof(LLVector4a)*numVertices; - - mCoords = static_cast(ll_aligned_malloc_16(size)); - mNormals = static_cast(ll_aligned_malloc_16(size)); - mBinormals = static_cast(ll_aligned_malloc_16(size)); - - mTexCoords = new LLVector2[numVertices]; - // Actually, we are allocating more space than we need for the skiplist - mVertexIndices = new U32[numVertices]; - mNumIndices = 0; - mTotalDistortion = 0.f; - mMaxDistortion = 0.f; - mAvgDistortion.clear(); - mMesh = mesh; - - //------------------------------------------------------------------------- - // read vertices - //------------------------------------------------------------------------- - for(S32 v = 0; v < numVertices; v++) - { - numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp); - llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); - if (numRead != 1) - { - LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL; - return false; - } - - if (mVertexIndices[v] > 10000) - { - // Bad install? These are usually .llm files from 'character' fodler - LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; - return false; - } - - - numRead = fread(&mCoords[v], sizeof(F32), 3, fp); - llendianswizzle(&mCoords[v], sizeof(F32), 3); - if (numRead != 3) - { - LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL; - return false; - } - - F32 magnitude = mCoords[v].getLength3().getF32(); - - mTotalDistortion += magnitude; - LLVector4a t; - t.setAbs(mCoords[v]); - mAvgDistortion.add(t); - - if (magnitude > mMaxDistortion) - { - mMaxDistortion = magnitude; - } - - numRead = fread(&mNormals[v], sizeof(F32), 3, fp); - llendianswizzle(&mNormals[v], sizeof(F32), 3); - if (numRead != 3) - { - LL_WARNS() << "Can't read morph target normal" << LL_ENDL; - return false; - } - - numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); - llendianswizzle(&mBinormals[v], sizeof(F32), 3); - if (numRead != 3) - { - LL_WARNS() << "Can't read morph target binormal" << LL_ENDL; - return false; - } - - - numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp); - llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); - if (numRead != 2) - { - LL_WARNS() << "Can't read morph target uv" << LL_ENDL; - return false; - } - - mNumIndices++; - } - - mAvgDistortion.mul(1.f/(F32)mNumIndices); - mAvgDistortion.normalize3fast(); - - return true; -} - -//----------------------------------------------------------------------------- -// freeData() -//----------------------------------------------------------------------------- -void LLPolyMorphData::freeData() -{ - if (mCoords != NULL) - { - ll_aligned_free_16(mCoords); - mCoords = NULL; - } - - if (mNormals != NULL) - { - ll_aligned_free_16(mNormals); - mNormals = NULL; - } - - if (mBinormals != NULL) - { - ll_aligned_free_16(mBinormals); - mBinormals = NULL; - } - - if (mTexCoords != NULL) - { - delete [] mTexCoords; - mTexCoords = NULL; - } - - if (mVertexIndices != NULL) - { - delete [] mVertexIndices; - mVertexIndices = NULL; - } -} - -//----------------------------------------------------------------------------- -// LLPolyMorphTargetInfo() -//----------------------------------------------------------------------------- -LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() - : mIsClothingMorph(false) -{ -} - -bool LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return false; - - // Get mixed-case name - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if( !node->getFastAttributeString( name_string, mMorphName ) ) - { - LL_WARNS() << "Avatar file: is missing name attribute" << LL_ENDL; - return false; // Continue, ignoring this tag - } - - static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); - node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph); - - LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); - - if (NULL == paramNode) - { - LL_WARNS() << "Failed to getChildByName(\"param_morph\")" - << LL_ENDL; - return false; - } - - for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); - child_node; - child_node = paramNode->getNextChild()) - { - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (child_node->hasName("volume_morph")) - { - std::string volume_name; - if (child_node->getFastAttributeString(name_string, volume_name)) - { - LLVector3 scale; - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - child_node->getFastAttributeVector3(scale_string, scale); - - LLVector3 pos; - static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); - child_node->getFastAttributeVector3(pos_string, pos); - - mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos)); - } - } - } - - return true; -} - -//----------------------------------------------------------------------------- -// LLPolyMorphTarget() -//----------------------------------------------------------------------------- -LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) - : LLViewerVisualParam(), - mMorphData(NULL), - mMesh(poly_mesh), - mVertMask(NULL), - mLastSex(SEX_FEMALE), - mNumMorphMasksPending(0), - mVolumeMorphs() -{ -} - -//----------------------------------------------------------------------------- -// LLPolyMorphTarget() -//----------------------------------------------------------------------------- -LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther) - : LLViewerVisualParam(pOther), - mMorphData(pOther.mMorphData), - mMesh(pOther.mMesh), - mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)), - mLastSex(pOther.mLastSex), - mNumMorphMasksPending(pOther.mNumMorphMasksPending), - mVolumeMorphs(pOther.mVolumeMorphs) -{ -} - -//----------------------------------------------------------------------------- -// ~LLPolyMorphTarget() -//----------------------------------------------------------------------------- -LLPolyMorphTarget::~LLPolyMorphTarget() -{ - delete mVertMask; - mVertMask = NULL; -} - -//----------------------------------------------------------------------------- -// setInfo() -//----------------------------------------------------------------------------- -bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return false; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight()); - - LLAvatarAppearance* avatarp = mMesh->getAvatar(); - for (LLPolyVolumeMorphInfo& volume_info : getInfo()->mVolumeInfoList) - { - for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++) - { - if (avatarp->mCollisionVolumes[i].getName() == volume_info.mName) - { - mVolumeMorphs.push_back( - LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], - volume_info.mScale, - volume_info.mPos)); - break; - } - } - } - - std::string morph_param_name = getInfo()->mMorphName; - - mMorphData = mMesh->getMorphData(morph_param_name); - if (!mMorphData) - { - const std::string driven_tag = "_Driven"; - U32 pos = morph_param_name.find(driven_tag); - if (pos > 0) - { - morph_param_name = morph_param_name.substr(0,pos); - mMorphData = mMesh->getMorphData(morph_param_name); - } - } - if (!mMorphData) - { - LL_WARNS() << "No morph target named " << morph_param_name << " found in mesh." << LL_ENDL; - return false; // Continue, ignoring this tag - } - return true; -} - -/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const -{ - return new LLPolyMorphTarget(*this); -} - -#if 0 // obsolete -//----------------------------------------------------------------------------- -// parseData() -//----------------------------------------------------------------------------- -bool LLPolyMorphTarget::parseData(LLXmlTreeNode* node) -{ - LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; - - info->parseXml(node); - if (!setInfo(info)) - { - delete info; - return false; - } - return true; -} -#endif - -//----------------------------------------------------------------------------- -// getVertexDistortion() -//----------------------------------------------------------------------------- -LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) -{ - if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); - - for(U32 index = 0; index < mMorphData->mNumIndices; index++) - { - if (mMorphData->mVertexIndices[index] == (U32)requested_index) - { - return mMorphData->mCoords[index]; - } - } - - return LLVector4a::getZero(); -} - -//----------------------------------------------------------------------------- -// getFirstDistortion() -//----------------------------------------------------------------------------- -const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - if (!mMorphData) return &LLVector4a::getZero(); - - LLVector4a* resultVec; - mMorphData->mCurrentIndex = 0; - if (mMorphData->mNumIndices) - { - resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; - if (index != NULL) - { - *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; - } - if (poly_mesh != NULL) - { - *poly_mesh = mMesh; - } - - return resultVec; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getNextDistortion() -//----------------------------------------------------------------------------- -const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) -{ - if (!mMorphData) return &LLVector4a::getZero(); - - LLVector4a* resultVec; - mMorphData->mCurrentIndex++; - if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) - { - resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; - if (index != NULL) - { - *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; - } - if (poly_mesh != NULL) - { - *poly_mesh = mMesh; - } - return resultVec; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// getTotalDistortion() -//----------------------------------------------------------------------------- -F32 LLPolyMorphTarget::getTotalDistortion() -{ - if (mMorphData) - { - return mMorphData->mTotalDistortion; - } - else - { - return 0.f; - } -} - -//----------------------------------------------------------------------------- -// getAvgDistortion() -//----------------------------------------------------------------------------- -const LLVector4a& LLPolyMorphTarget::getAvgDistortion() -{ - if (mMorphData) - { - return mMorphData->mAvgDistortion; - } - else - { - return LLVector4a::getZero(); - } -} - -//----------------------------------------------------------------------------- -// getMaxDistortion() -//----------------------------------------------------------------------------- -F32 LLPolyMorphTarget::getMaxDistortion() -{ - if (mMorphData) - { - return mMorphData->mMaxDistortion; - } - else - { - return 0.f; - } -} - -//----------------------------------------------------------------------------- -// apply() -//----------------------------------------------------------------------------- -void LLPolyMorphTarget::apply( ESex avatar_sex ) -{ - if (!mMorphData || mNumMorphMasksPending > 0) - { - return; - } - - LL_PROFILE_ZONE_SCOPED; - - mLastSex = avatar_sex; - - // Check for NaN condition (NaN is detected if a variable doesn't equal itself. - if (mCurWeight != mCurWeight) - { - mCurWeight = 0.0; - } - if (mLastWeight != mLastWeight) - { - mLastWeight = mCurWeight+.001; - } - - // perform differential update of morph - F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); - // store last weight - mLastWeight += delta_weight; - - if (delta_weight != 0.f) - { - llassert(!mMesh->isLOD()); - LLVector4a *coords = mMesh->getWritableCoords(); - - LLVector4a *scaled_normals = mMesh->getScaledNormals(); - LLVector4a *normals = mMesh->getWritableNormals(); - - LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); - LLVector4a *binormals = mMesh->getWritableBinormals(); - - LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); - LLVector2 *tex_coords = mMesh->getWritableTexCoords(); - - F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; - - for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++) - { - S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph]; - - F32 maskWeight = 1.f; - if (maskWeightArray) - { - maskWeight = maskWeightArray[vert_index_morph]; - } - - - LLVector4a pos = mMorphData->mCoords[vert_index_morph]; - pos.mul(delta_weight*maskWeight); - coords[vert_index_mesh].add(pos); - - if (getInfo()->mIsClothingMorph && clothing_weights) - { - LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; - clothing_offset.mul(delta_weight * maskWeight); - LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; - clothing_weight->add(clothing_offset); - clothing_weight->getF32ptr()[VW] = maskWeight; - } - - // calculate new normals based on half angles - LLVector4a norm = mMorphData->mNormals[vert_index_morph]; - norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); - scaled_normals[vert_index_mesh].add(norm); - norm = scaled_normals[vert_index_mesh]; - - // guard against degenerate input data before we create NaNs below! - // - norm.normalize3fast(); - normals[vert_index_mesh] = norm; - - // calculate new binormals - LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; - - // guard against degenerate input data before we create NaNs below! - // - if (!binorm.isFinite3() || (binorm.dot3(binorm).getF32() <= F_APPROXIMATELY_ZERO)) - { - binorm.set(1,0,0,1); - } - - binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); - scaled_binormals[vert_index_mesh].add(binorm); - LLVector4a tangent; - tangent.setCross3(scaled_binormals[vert_index_mesh], norm); - LLVector4a& normalized_binormal = binormals[vert_index_mesh]; - - normalized_binormal.setCross3(norm, tangent); - normalized_binormal.normalize3fast(); - - tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; - } - - // now apply volume changes - for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) - { - LLVector3 scale_delta = volume_morph.mScale * delta_weight; - LLVector3 pos_delta = volume_morph.mPos * delta_weight; - - volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); - // SL-315 - volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); - } - } - - if (mNext) - { - mNext->apply(avatar_sex); - } -} - -//----------------------------------------------------------------------------- -// applyMask() -//----------------------------------------------------------------------------- -void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert) -{ - LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; - - if (!mVertMask) - { - mVertMask = new LLPolyVertexMask(mMorphData); - mNumMorphMasksPending--; - } - else - { - // remove effect of previous mask - F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; - - if (maskWeights) - { - LLVector4a *coords = mMesh->getWritableCoords(); - LLVector4a *scaled_normals = mMesh->getScaledNormals(); - LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); - LLVector2 *tex_coords = mMesh->getWritableTexCoords(); - - LLVector4Logical clothing_mask; - clothing_mask.clear(); - clothing_mask.setElement<0>(); - clothing_mask.setElement<1>(); - clothing_mask.setElement<2>(); - - - for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) - { - F32 lastMaskWeight = mLastWeight * maskWeights[vert]; - S32 out_vert = mMorphData->mVertexIndices[vert]; - - // remove effect of existing masked morph - LLVector4a t; - t = mMorphData->mCoords[vert]; - t.mul(lastMaskWeight); - coords[out_vert].sub(t); - - t = mMorphData->mNormals[vert]; - t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); - scaled_normals[out_vert].sub(t); - - t = mMorphData->mBinormals[vert]; - t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); - scaled_binormals[out_vert].sub(t); - - tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; - - if (clothing_weights) - { - LLVector4a clothing_offset = mMorphData->mCoords[vert]; - clothing_offset.mul(lastMaskWeight); - LLVector4a* clothing_weight = &clothing_weights[out_vert]; - LLVector4a t; - t.setSub(*clothing_weight, clothing_offset); - clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); - } - } - } - } - - // set last weight to 0, since we've removed the effect of this morph - mLastWeight = 0.f; - - mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); - - apply(mLastSex); -} - -void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) -{ - // now apply volume changes - for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) - { - LLVector3 scale_delta = volume_morph.mScale * delta_weight; - LLVector3 pos_delta = volume_morph.mPos * delta_weight; - - volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); - // SL-315 - volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); - } -} - -//----------------------------------------------------------------------------- -// LLPolyVertexMask() -//----------------------------------------------------------------------------- -LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) - : mWeights(new F32[morph_data->mNumIndices]), - mMorphData(morph_data), - mWeightsGenerated(false) -{ - llassert(mMorphData != NULL); - llassert(mMorphData->mNumIndices > 0); -} - -//----------------------------------------------------------------------------- -// LLPolyVertexMask() -//----------------------------------------------------------------------------- -LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther) - : mWeights(new F32[pOther.mMorphData->mNumIndices]), - mMorphData(pOther.mMorphData), - mWeightsGenerated(pOther.mWeightsGenerated) -{ - llassert(mMorphData != NULL); - llassert(mMorphData->mNumIndices > 0); - memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices); -} - -//----------------------------------------------------------------------------- -// ~LLPolyVertexMask() -//----------------------------------------------------------------------------- -LLPolyVertexMask::~LLPolyVertexMask() -{ - delete [] mWeights; - mWeights = NULL; -} - -//----------------------------------------------------------------------------- -// generateMask() -//----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights) -{ -// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) -// bool debugImg = false; -// if (debugImg) -// { -// if (invert) -// { -// imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData); -// } -// else -// { -// imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData); -// } -// } - for (U32 index = 0; index < mMorphData->mNumIndices; index++) - { - S32 vertIndex = mMorphData->mVertexIndices[index]; - const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex); - LLVector2 uvCoords; - - if (sharedVertIndex) - { - uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex); - } - else - { - uvCoords = mMorphData->mMesh->getUVs(vertIndex); - } - U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1); - U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1); - - mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f; - - if (invert) - { - mWeights[index] = 1.f - mWeights[index]; - } - - // now apply step function - // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f; - - if (clothing_weights) - { - clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; - } - } - mWeightsGenerated = true; -} - -//----------------------------------------------------------------------------- -// getMaskForMorphIndex() -//----------------------------------------------------------------------------- -F32* LLPolyVertexMask::getMorphMaskWeights() -{ - if (!mWeightsGenerated) - { - return NULL; - } - - return mWeights; -} +/** + * @file llpolymorph.cpp + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- + +#include "llpolymorph.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" +#include "llwearable.h" +#include "llxmltree.h" +#include "llendianswizzle.h" +#include "llpolymesh.h" +#include "llfasttimer.h" + +//#include "../tools/imdebug/imdebug.h" + +const F32 NORMAL_SOFTEN_FACTOR = 0.65f; + +//----------------------------------------------------------------------------- +// LLPolyMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) + : mName(morph_name) +{ + mNumIndices = 0; + mCurrentIndex = 0; + mTotalDistortion = 0.f; + mAvgDistortion.clear(); + mMaxDistortion = 0.f; + mVertexIndices = NULL; + mCoords = NULL; + mNormals = NULL; + mBinormals = NULL; + mTexCoords = NULL; + + mMesh = NULL; +} + +LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : + mName(rhs.mName), + mNumIndices(rhs.mNumIndices), + mTotalDistortion(rhs.mTotalDistortion), + mAvgDistortion(rhs.mAvgDistortion), + mMaxDistortion(rhs.mMaxDistortion), + mVertexIndices(NULL), + mCoords(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL) +{ + const S32 numVertices = mNumIndices; + + U32 size = sizeof(LLVector4a)*numVertices; + + mCoords = static_cast( ll_aligned_malloc_16(size) ); + mNormals = static_cast( ll_aligned_malloc_16(size) ); + mBinormals = static_cast( ll_aligned_malloc_16(size) ); + mTexCoords = new LLVector2[numVertices]; + mVertexIndices = new U32[numVertices]; + + for (S32 v=0; v < numVertices; v++) + { + mCoords[v] = rhs.mCoords[v]; + mNormals[v] = rhs.mNormals[v]; + mBinormals[v] = rhs.mBinormals[v]; + mTexCoords[v] = rhs.mTexCoords[v]; + mVertexIndices[v] = rhs.mVertexIndices[v]; + } +} + +//----------------------------------------------------------------------------- +// ~LLPolyMorphData() +//----------------------------------------------------------------------------- +LLPolyMorphData::~LLPolyMorphData() +{ + freeData(); +} + +//----------------------------------------------------------------------------- +// loadBinary() +//----------------------------------------------------------------------------- +bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) +{ + S32 numVertices; + S32 numRead; + + numRead = fread(&numVertices, sizeof(S32), 1, fp); + llendianswizzle(&numVertices, sizeof(S32), 1); + if (numRead != 1) + { + LL_WARNS() << "Can't read number of morph target vertices" << LL_ENDL; + return false; + } + + //------------------------------------------------------------------------- + // free any existing data + //------------------------------------------------------------------------- + freeData(); + + //------------------------------------------------------------------------- + // allocate vertices + //------------------------------------------------------------------------- + + U32 size = sizeof(LLVector4a)*numVertices; + + mCoords = static_cast(ll_aligned_malloc_16(size)); + mNormals = static_cast(ll_aligned_malloc_16(size)); + mBinormals = static_cast(ll_aligned_malloc_16(size)); + + mTexCoords = new LLVector2[numVertices]; + // Actually, we are allocating more space than we need for the skiplist + mVertexIndices = new U32[numVertices]; + mNumIndices = 0; + mTotalDistortion = 0.f; + mMaxDistortion = 0.f; + mAvgDistortion.clear(); + mMesh = mesh; + + //------------------------------------------------------------------------- + // read vertices + //------------------------------------------------------------------------- + for(S32 v = 0; v < numVertices; v++) + { + numRead = fread(&mVertexIndices[v], sizeof(U32), 1, fp); + llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); + if (numRead != 1) + { + LL_WARNS() << "Can't read morph target vertex number" << LL_ENDL; + return false; + } + + if (mVertexIndices[v] > 10000) + { + // Bad install? These are usually .llm files from 'character' fodler + LL_WARNS() << "Bad morph index " << v << ": " << mVertexIndices[v] << LL_ENDL; + return false; + } + + + numRead = fread(&mCoords[v], sizeof(F32), 3, fp); + llendianswizzle(&mCoords[v], sizeof(F32), 3); + if (numRead != 3) + { + LL_WARNS() << "Can't read morph target vertex coordinates" << LL_ENDL; + return false; + } + + F32 magnitude = mCoords[v].getLength3().getF32(); + + mTotalDistortion += magnitude; + LLVector4a t; + t.setAbs(mCoords[v]); + mAvgDistortion.add(t); + + if (magnitude > mMaxDistortion) + { + mMaxDistortion = magnitude; + } + + numRead = fread(&mNormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mNormals[v], sizeof(F32), 3); + if (numRead != 3) + { + LL_WARNS() << "Can't read morph target normal" << LL_ENDL; + return false; + } + + numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mBinormals[v], sizeof(F32), 3); + if (numRead != 3) + { + LL_WARNS() << "Can't read morph target binormal" << LL_ENDL; + return false; + } + + + numRead = fread(&mTexCoords[v].mV, sizeof(F32), 2, fp); + llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); + if (numRead != 2) + { + LL_WARNS() << "Can't read morph target uv" << LL_ENDL; + return false; + } + + mNumIndices++; + } + + mAvgDistortion.mul(1.f/(F32)mNumIndices); + mAvgDistortion.normalize3fast(); + + return true; +} + +//----------------------------------------------------------------------------- +// freeData() +//----------------------------------------------------------------------------- +void LLPolyMorphData::freeData() +{ + if (mCoords != NULL) + { + ll_aligned_free_16(mCoords); + mCoords = NULL; + } + + if (mNormals != NULL) + { + ll_aligned_free_16(mNormals); + mNormals = NULL; + } + + if (mBinormals != NULL) + { + ll_aligned_free_16(mBinormals); + mBinormals = NULL; + } + + if (mTexCoords != NULL) + { + delete [] mTexCoords; + mTexCoords = NULL; + } + + if (mVertexIndices != NULL) + { + delete [] mVertexIndices; + mVertexIndices = NULL; + } +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTargetInfo() +//----------------------------------------------------------------------------- +LLPolyMorphTargetInfo::LLPolyMorphTargetInfo() + : mIsClothingMorph(false) +{ +} + +bool LLPolyMorphTargetInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_morph" ) ); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return false; + + // Get mixed-case name + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if( !node->getFastAttributeString( name_string, mMorphName ) ) + { + LL_WARNS() << "Avatar file: is missing name attribute" << LL_ENDL; + return false; // Continue, ignoring this tag + } + + static LLStdStringHandle clothing_morph_string = LLXmlTree::addAttributeString("clothing_morph"); + node->getFastAttributeBOOL(clothing_morph_string, mIsClothingMorph); + + LLXmlTreeNode *paramNode = node->getChildByName("param_morph"); + + if (NULL == paramNode) + { + LL_WARNS() << "Failed to getChildByName(\"param_morph\")" + << LL_ENDL; + return false; + } + + for (LLXmlTreeNode* child_node = paramNode->getFirstChild(); + child_node; + child_node = paramNode->getNextChild()) + { + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (child_node->hasName("volume_morph")) + { + std::string volume_name; + if (child_node->getFastAttributeString(name_string, volume_name)) + { + LLVector3 scale; + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + child_node->getFastAttributeVector3(scale_string, scale); + + LLVector3 pos; + static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); + child_node->getFastAttributeVector3(pos_string, pos); + + mVolumeInfoList.push_back(LLPolyVolumeMorphInfo(volume_name,scale,pos)); + } + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::LLPolyMorphTarget(LLPolyMesh *poly_mesh) + : LLViewerVisualParam(), + mMorphData(NULL), + mMesh(poly_mesh), + mVertMask(NULL), + mLastSex(SEX_FEMALE), + mNumMorphMasksPending(0), + mVolumeMorphs() +{ +} + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::LLPolyMorphTarget(const LLPolyMorphTarget& pOther) + : LLViewerVisualParam(pOther), + mMorphData(pOther.mMorphData), + mMesh(pOther.mMesh), + mVertMask(pOther.mVertMask == NULL ? NULL : new LLPolyVertexMask(*pOther.mVertMask)), + mLastSex(pOther.mLastSex), + mNumMorphMasksPending(pOther.mNumMorphMasksPending), + mVolumeMorphs(pOther.mVolumeMorphs) +{ +} + +//----------------------------------------------------------------------------- +// ~LLPolyMorphTarget() +//----------------------------------------------------------------------------- +LLPolyMorphTarget::~LLPolyMorphTarget() +{ + delete mVertMask; + mVertMask = NULL; +} + +//----------------------------------------------------------------------------- +// setInfo() +//----------------------------------------------------------------------------- +bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return false; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight()); + + LLAvatarAppearance* avatarp = mMesh->getAvatar(); + for (LLPolyVolumeMorphInfo& volume_info : getInfo()->mVolumeInfoList) + { + for (S32 i = 0; i < avatarp->mNumCollisionVolumes; i++) + { + if (avatarp->mCollisionVolumes[i].getName() == volume_info.mName) + { + mVolumeMorphs.push_back( + LLPolyVolumeMorph(&avatarp->mCollisionVolumes[i], + volume_info.mScale, + volume_info.mPos)); + break; + } + } + } + + std::string morph_param_name = getInfo()->mMorphName; + + mMorphData = mMesh->getMorphData(morph_param_name); + if (!mMorphData) + { + const std::string driven_tag = "_Driven"; + U32 pos = morph_param_name.find(driven_tag); + if (pos > 0) + { + morph_param_name = morph_param_name.substr(0,pos); + mMorphData = mMesh->getMorphData(morph_param_name); + } + } + if (!mMorphData) + { + LL_WARNS() << "No morph target named " << morph_param_name << " found in mesh." << LL_ENDL; + return false; // Continue, ignoring this tag + } + return true; +} + +/*virtual*/ LLViewerVisualParam* LLPolyMorphTarget::cloneParam(LLWearable* wearable) const +{ + return new LLPolyMorphTarget(*this); +} + +#if 0 // obsolete +//----------------------------------------------------------------------------- +// parseData() +//----------------------------------------------------------------------------- +bool LLPolyMorphTarget::parseData(LLXmlTreeNode* node) +{ + LLPolyMorphTargetInfo* info = new LLPolyMorphTargetInfo; + + info->parseXml(node); + if (!setInfo(info)) + { + delete info; + return false; + } + return true; +} +#endif + +//----------------------------------------------------------------------------- +// getVertexDistortion() +//----------------------------------------------------------------------------- +LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) +{ + if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); + + for(U32 index = 0; index < mMorphData->mNumIndices; index++) + { + if (mMorphData->mVertexIndices[index] == (U32)requested_index) + { + return mMorphData->mCoords[index]; + } + } + + return LLVector4a::getZero(); +} + +//----------------------------------------------------------------------------- +// getFirstDistortion() +//----------------------------------------------------------------------------- +const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + if (!mMorphData) return &LLVector4a::getZero(); + + LLVector4a* resultVec; + mMorphData->mCurrentIndex = 0; + if (mMorphData->mNumIndices) + { + resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; + if (index != NULL) + { + *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; + } + if (poly_mesh != NULL) + { + *poly_mesh = mMesh; + } + + return resultVec; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getNextDistortion() +//----------------------------------------------------------------------------- +const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +{ + if (!mMorphData) return &LLVector4a::getZero(); + + LLVector4a* resultVec; + mMorphData->mCurrentIndex++; + if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) + { + resultVec = &mMorphData->mCoords[mMorphData->mCurrentIndex]; + if (index != NULL) + { + *index = mMorphData->mVertexIndices[mMorphData->mCurrentIndex]; + } + if (poly_mesh != NULL) + { + *poly_mesh = mMesh; + } + return resultVec; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// getTotalDistortion() +//----------------------------------------------------------------------------- +F32 LLPolyMorphTarget::getTotalDistortion() +{ + if (mMorphData) + { + return mMorphData->mTotalDistortion; + } + else + { + return 0.f; + } +} + +//----------------------------------------------------------------------------- +// getAvgDistortion() +//----------------------------------------------------------------------------- +const LLVector4a& LLPolyMorphTarget::getAvgDistortion() +{ + if (mMorphData) + { + return mMorphData->mAvgDistortion; + } + else + { + return LLVector4a::getZero(); + } +} + +//----------------------------------------------------------------------------- +// getMaxDistortion() +//----------------------------------------------------------------------------- +F32 LLPolyMorphTarget::getMaxDistortion() +{ + if (mMorphData) + { + return mMorphData->mMaxDistortion; + } + else + { + return 0.f; + } +} + +//----------------------------------------------------------------------------- +// apply() +//----------------------------------------------------------------------------- +void LLPolyMorphTarget::apply( ESex avatar_sex ) +{ + if (!mMorphData || mNumMorphMasksPending > 0) + { + return; + } + + LL_PROFILE_ZONE_SCOPED; + + mLastSex = avatar_sex; + + // Check for NaN condition (NaN is detected if a variable doesn't equal itself. + if (mCurWeight != mCurWeight) + { + mCurWeight = 0.0; + } + if (mLastWeight != mLastWeight) + { + mLastWeight = mCurWeight+.001; + } + + // perform differential update of morph + F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight); + // store last weight + mLastWeight += delta_weight; + + if (delta_weight != 0.f) + { + llassert(!mMesh->isLOD()); + LLVector4a *coords = mMesh->getWritableCoords(); + + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *normals = mMesh->getWritableNormals(); + + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *binormals = mMesh->getWritableBinormals(); + + LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); + LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + + F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + + for(U32 vert_index_morph = 0; vert_index_morph < mMorphData->mNumIndices; vert_index_morph++) + { + S32 vert_index_mesh = mMorphData->mVertexIndices[vert_index_morph]; + + F32 maskWeight = 1.f; + if (maskWeightArray) + { + maskWeight = maskWeightArray[vert_index_morph]; + } + + + LLVector4a pos = mMorphData->mCoords[vert_index_morph]; + pos.mul(delta_weight*maskWeight); + coords[vert_index_mesh].add(pos); + + if (getInfo()->mIsClothingMorph && clothing_weights) + { + LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; + clothing_offset.mul(delta_weight * maskWeight); + LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; + clothing_weight->add(clothing_offset); + clothing_weight->getF32ptr()[VW] = maskWeight; + } + + // calculate new normals based on half angles + LLVector4a norm = mMorphData->mNormals[vert_index_morph]; + norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[vert_index_mesh].add(norm); + norm = scaled_normals[vert_index_mesh]; + + // guard against degenerate input data before we create NaNs below! + // + norm.normalize3fast(); + normals[vert_index_mesh] = norm; + + // calculate new binormals + LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; + + // guard against degenerate input data before we create NaNs below! + // + if (!binorm.isFinite3() || (binorm.dot3(binorm).getF32() <= F_APPROXIMATELY_ZERO)) + { + binorm.set(1,0,0,1); + } + + binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[vert_index_mesh].add(binorm); + LLVector4a tangent; + tangent.setCross3(scaled_binormals[vert_index_mesh], norm); + LLVector4a& normalized_binormal = binormals[vert_index_mesh]; + + normalized_binormal.setCross3(norm, tangent); + normalized_binormal.normalize3fast(); + + tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; + } + + // now apply volume changes + for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) + { + LLVector3 scale_delta = volume_morph.mScale * delta_weight; + LLVector3 pos_delta = volume_morph.mPos * delta_weight; + + volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); + // SL-315 + volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); + } + } + + if (mNext) + { + mNext->apply(avatar_sex); + } +} + +//----------------------------------------------------------------------------- +// applyMask() +//----------------------------------------------------------------------------- +void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert) +{ + LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + + if (!mVertMask) + { + mVertMask = new LLPolyVertexMask(mMorphData); + mNumMorphMasksPending--; + } + else + { + // remove effect of previous mask + F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + + if (maskWeights) + { + LLVector4a *coords = mMesh->getWritableCoords(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + + LLVector4Logical clothing_mask; + clothing_mask.clear(); + clothing_mask.setElement<0>(); + clothing_mask.setElement<1>(); + clothing_mask.setElement<2>(); + + + for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) + { + F32 lastMaskWeight = mLastWeight * maskWeights[vert]; + S32 out_vert = mMorphData->mVertexIndices[vert]; + + // remove effect of existing masked morph + LLVector4a t; + t = mMorphData->mCoords[vert]; + t.mul(lastMaskWeight); + coords[out_vert].sub(t); + + t = mMorphData->mNormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[out_vert].sub(t); + + t = mMorphData->mBinormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[out_vert].sub(t); + + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; + + if (clothing_weights) + { + LLVector4a clothing_offset = mMorphData->mCoords[vert]; + clothing_offset.mul(lastMaskWeight); + LLVector4a* clothing_weight = &clothing_weights[out_vert]; + LLVector4a t; + t.setSub(*clothing_weight, clothing_offset); + clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); + } + } + } + } + + // set last weight to 0, since we've removed the effect of this morph + mLastWeight = 0.f; + + mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); + + apply(mLastSex); +} + +void LLPolyMorphTarget::applyVolumeChanges(F32 delta_weight) +{ + // now apply volume changes + for(LLPolyVolumeMorph& volume_morph : mVolumeMorphs) + { + LLVector3 scale_delta = volume_morph.mScale * delta_weight; + LLVector3 pos_delta = volume_morph.mPos * delta_weight; + + volume_morph.mVolume->setScale(volume_morph.mVolume->getScale() + scale_delta); + // SL-315 + volume_morph.mVolume->setPosition(volume_morph.mVolume->getPosition() + pos_delta); + } +} + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::LLPolyVertexMask(LLPolyMorphData* morph_data) + : mWeights(new F32[morph_data->mNumIndices]), + mMorphData(morph_data), + mWeightsGenerated(false) +{ + llassert(mMorphData != NULL); + llassert(mMorphData->mNumIndices > 0); +} + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::LLPolyVertexMask(const LLPolyVertexMask& pOther) + : mWeights(new F32[pOther.mMorphData->mNumIndices]), + mMorphData(pOther.mMorphData), + mWeightsGenerated(pOther.mWeightsGenerated) +{ + llassert(mMorphData != NULL); + llassert(mMorphData->mNumIndices > 0); + memcpy(mWeights, pOther.mWeights, sizeof(F32) * mMorphData->mNumIndices); +} + +//----------------------------------------------------------------------------- +// ~LLPolyVertexMask() +//----------------------------------------------------------------------------- +LLPolyVertexMask::~LLPolyVertexMask() +{ + delete [] mWeights; + mWeights = NULL; +} + +//----------------------------------------------------------------------------- +// generateMask() +//----------------------------------------------------------------------------- +void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights) +{ +// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) +// bool debugImg = false; +// if (debugImg) +// { +// if (invert) +// { +// imdebug("lum rbga=rgba b=8 w=%d h=%d *-1 %p", width, height, maskTextureData); +// } +// else +// { +// imdebug("lum rbga=rgba b=8 w=%d h=%d %p", width, height, maskTextureData); +// } +// } + for (U32 index = 0; index < mMorphData->mNumIndices; index++) + { + S32 vertIndex = mMorphData->mVertexIndices[index]; + const S32 *sharedVertIndex = mMorphData->mMesh->getSharedVert(vertIndex); + LLVector2 uvCoords; + + if (sharedVertIndex) + { + uvCoords = mMorphData->mMesh->getUVs(*sharedVertIndex); + } + else + { + uvCoords = mMorphData->mMesh->getUVs(vertIndex); + } + U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1); + U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1); + + mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f; + + if (invert) + { + mWeights[index] = 1.f - mWeights[index]; + } + + // now apply step function + // mWeights[index] = mWeights[index] > 0.95f ? 1.f : 0.f; + + if (clothing_weights) + { + clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; + } + } + mWeightsGenerated = true; +} + +//----------------------------------------------------------------------------- +// getMaskForMorphIndex() +//----------------------------------------------------------------------------- +F32* LLPolyVertexMask::getMorphMaskWeights() +{ + if (!mWeightsGenerated) + { + return NULL; + } + + return mWeights; +} diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 3c7cf81c90..8c76689f2c 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -1,193 +1,193 @@ -/** - * @file llpolymorph.h - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPOLYMORPH_H -#define LL_LLPOLYMORPH_H - -#include -#include - -#include "llviewervisualparam.h" - -class LLAvatarJointCollisionVolume; -class LLPolyMeshSharedData; -class LLVector2; -class LLAvatarJointCollisionVolume; -class LLWearable; - -//----------------------------------------------------------------------------- -// LLPolyMorphData() -//----------------------------------------------------------------------------- -class alignas(16) LLPolyMorphData -{ - LL_ALIGN_NEW -public: - LLPolyMorphData(const std::string& morph_name); - ~LLPolyMorphData(); - LLPolyMorphData(const LLPolyMorphData &rhs); - - bool loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); - const std::string& getName() { return mName; } - -public: - std::string mName; - - // morphology - U32 mNumIndices; - U32* mVertexIndices; - U32 mCurrentIndex; - LLVector4a* mCoords; - LLVector4a* mNormals; - LLVector4a* mBinormals; - LLVector2* mTexCoords; - - F32 mTotalDistortion; // vertex distortion summed over entire morph - F32 mMaxDistortion; // maximum single vertex distortion in a given morph - LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph - LLPolyMeshSharedData* mMesh; - -private: - void freeData(); -} LL_ALIGN_POSTFIX(16); - - -//----------------------------------------------------------------------------- -// LLPolyVertexMask() -//----------------------------------------------------------------------------- -class LLPolyVertexMask -{ -public: - LLPolyVertexMask(LLPolyMorphData* morph_data); - LLPolyVertexMask(const LLPolyVertexMask& pOther); - ~LLPolyVertexMask(); - - void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights); - F32* getMorphMaskWeights(); - - -protected: - F32* mWeights; - LLPolyMorphData *mMorphData; - bool mWeightsGenerated; - -}; - -//----------------------------------------------------------------------------- -// LLPolyMorphTarget Data structs -//----------------------------------------------------------------------------- -struct LLPolyVolumeMorphInfo -{ - LLPolyVolumeMorphInfo(std::string &name, LLVector3 &scale, LLVector3 &pos) - : mName(name), mScale(scale), mPos(pos) {}; - - std::string mName; - LLVector3 mScale; - LLVector3 mPos; -}; - -struct LLPolyVolumeMorph -{ - LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) - : mVolume(volume), mScale(scale), mPos(pos) {}; - - LLAvatarJointCollisionVolume* mVolume; - LLVector3 mScale; - LLVector3 mPos; -}; - -//----------------------------------------------------------------------------- -// LLPolyMorphTargetInfo -// Shared information for LLPolyMorphTargets -//----------------------------------------------------------------------------- -class LLPolyMorphTargetInfo : public LLViewerVisualParamInfo -{ - friend class LLPolyMorphTarget; -public: - LLPolyMorphTargetInfo(); - /*virtual*/ ~LLPolyMorphTargetInfo() {}; - - /*virtual*/ bool parseXml(LLXmlTreeNode* node); - -protected: - std::string mMorphName; - bool mIsClothingMorph; - typedef std::vector volume_info_list_t; - volume_info_list_t mVolumeInfoList; -}; - -//----------------------------------------------------------------------------- -// LLPolyMorphTarget -// A set of vertex data associated with morph target. -// These morph targets must be topologically consistent with a given Polymesh -// (share face sets) -//----------------------------------------------------------------------------- -class alignas(16) LLPolyMorphTarget : public LLViewerVisualParam -{ - LL_ALIGN_NEW -public: - LLPolyMorphTarget(LLPolyMesh *poly_mesh); - ~LLPolyMorphTarget(); - - // Special: These functions are overridden by child classes - LLPolyMorphTargetInfo* getInfo() const { return (LLPolyMorphTargetInfo*)mInfo; } - // This sets mInfo and calls initialization functions - bool setInfo(LLPolyMorphTargetInfo *info); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - ///*virtual*/ bool parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex sex ); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector4a& getAvgDistortion(); - /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); - - void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, bool invert); - void addPendingMorphMask() { mNumMorphMasksPending++; } - - void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() - -protected: - LLPolyMorphTarget(const LLPolyMorphTarget& pOther); - - LLPolyMorphData* mMorphData; - LLPolyMesh* mMesh; - LLPolyVertexMask * mVertMask; - ESex mLastSex; - // number of morph masks that haven't been generated, must be 0 before this morph is applied - S32 mNumMorphMasksPending; - - typedef std::vector volume_list_t; - volume_list_t mVolumeMorphs; - -}; - -#endif // LL_LLPOLYMORPH_H +/** + * @file llpolymorph.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYMORPH_H +#define LL_LLPOLYMORPH_H + +#include +#include + +#include "llviewervisualparam.h" + +class LLAvatarJointCollisionVolume; +class LLPolyMeshSharedData; +class LLVector2; +class LLAvatarJointCollisionVolume; +class LLWearable; + +//----------------------------------------------------------------------------- +// LLPolyMorphData() +//----------------------------------------------------------------------------- +class alignas(16) LLPolyMorphData +{ + LL_ALIGN_NEW +public: + LLPolyMorphData(const std::string& morph_name); + ~LLPolyMorphData(); + LLPolyMorphData(const LLPolyMorphData &rhs); + + bool loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); + const std::string& getName() { return mName; } + +public: + std::string mName; + + // morphology + U32 mNumIndices; + U32* mVertexIndices; + U32 mCurrentIndex; + LLVector4a* mCoords; + LLVector4a* mNormals; + LLVector4a* mBinormals; + LLVector2* mTexCoords; + + F32 mTotalDistortion; // vertex distortion summed over entire morph + F32 mMaxDistortion; // maximum single vertex distortion in a given morph + LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph + LLPolyMeshSharedData* mMesh; + +private: + void freeData(); +} LL_ALIGN_POSTFIX(16); + + +//----------------------------------------------------------------------------- +// LLPolyVertexMask() +//----------------------------------------------------------------------------- +class LLPolyVertexMask +{ +public: + LLPolyVertexMask(LLPolyMorphData* morph_data); + LLPolyVertexMask(const LLPolyVertexMask& pOther); + ~LLPolyVertexMask(); + + void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, bool invert, LLVector4a *clothing_weights); + F32* getMorphMaskWeights(); + + +protected: + F32* mWeights; + LLPolyMorphData *mMorphData; + bool mWeightsGenerated; + +}; + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget Data structs +//----------------------------------------------------------------------------- +struct LLPolyVolumeMorphInfo +{ + LLPolyVolumeMorphInfo(std::string &name, LLVector3 &scale, LLVector3 &pos) + : mName(name), mScale(scale), mPos(pos) {}; + + std::string mName; + LLVector3 mScale; + LLVector3 mPos; +}; + +struct LLPolyVolumeMorph +{ + LLPolyVolumeMorph(LLAvatarJointCollisionVolume* volume, LLVector3 scale, LLVector3 pos) + : mVolume(volume), mScale(scale), mPos(pos) {}; + + LLAvatarJointCollisionVolume* mVolume; + LLVector3 mScale; + LLVector3 mPos; +}; + +//----------------------------------------------------------------------------- +// LLPolyMorphTargetInfo +// Shared information for LLPolyMorphTargets +//----------------------------------------------------------------------------- +class LLPolyMorphTargetInfo : public LLViewerVisualParamInfo +{ + friend class LLPolyMorphTarget; +public: + LLPolyMorphTargetInfo(); + /*virtual*/ ~LLPolyMorphTargetInfo() {}; + + /*virtual*/ bool parseXml(LLXmlTreeNode* node); + +protected: + std::string mMorphName; + bool mIsClothingMorph; + typedef std::vector volume_info_list_t; + volume_info_list_t mVolumeInfoList; +}; + +//----------------------------------------------------------------------------- +// LLPolyMorphTarget +// A set of vertex data associated with morph target. +// These morph targets must be topologically consistent with a given Polymesh +// (share face sets) +//----------------------------------------------------------------------------- +class alignas(16) LLPolyMorphTarget : public LLViewerVisualParam +{ + LL_ALIGN_NEW +public: + LLPolyMorphTarget(LLPolyMesh *poly_mesh); + ~LLPolyMorphTarget(); + + // Special: These functions are overridden by child classes + LLPolyMorphTargetInfo* getInfo() const { return (LLPolyMorphTargetInfo*)mInfo; } + // This sets mInfo and calls initialization functions + bool setInfo(LLPolyMorphTargetInfo *info); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + ///*virtual*/ bool parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex sex ); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); + /*virtual*/ F32 getMaxDistortion(); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + + void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, bool invert); + void addPendingMorphMask() { mNumMorphMasksPending++; } + + void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton() + +protected: + LLPolyMorphTarget(const LLPolyMorphTarget& pOther); + + LLPolyMorphData* mMorphData; + LLPolyMesh* mMesh; + LLPolyVertexMask * mVertMask; + ESex mLastSex; + // number of morph masks that haven't been generated, must be 0 before this morph is applied + S32 mNumMorphMasksPending; + + typedef std::vector volume_list_t; + volume_list_t mVolumeMorphs; + +}; + +#endif // LL_LLPOLYMORPH_H diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index ed6a71d8f3..18c64282f1 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -1,297 +1,297 @@ -/** - * @file llpolyskeletaldistortion.cpp - * @brief Implementation of LLPolySkeletalDistortion classes - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "llpreprocessor.h" -#include "llerror.h" -#include "llavatarappearance.h" -#include "llavatarjoint.h" -#include "llpolymorph.h" -#include "llwearable.h" -#include "llfasttimer.h" -#include "llcallstack.h" - -#include "llpolyskeletaldistortion.h" - -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortionInfo() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() -{ -} - -bool LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return false; - - LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); - - if (NULL == skeletalParam) - { - LL_WARNS() << "Failed to getChildByName(\"param_skeleton\")" - << LL_ENDL; - return false; - } - - for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) - { - if (bone->hasName("bone")) - { - std::string name; - LLVector3 scale; - LLVector3 pos; - bool haspos = false; - - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!bone->getFastAttributeString(name_string, name)) - { - LL_WARNS() << "No bone name specified for skeletal param." << LL_ENDL; - continue; - } - - static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); - if (!bone->getFastAttributeVector3(scale_string, scale)) - { - LL_WARNS() << "No scale specified for bone " << name << "." << LL_ENDL; - continue; - } - - // optional offset deformation (translation) - static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); - if (bone->getFastAttributeVector3(offset_string, pos)) - { - haspos = true; - } - mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); - } - else - { - LL_WARNS() << "Unrecognized element " << bone->getName() << " in skeletal distortion" << LL_ENDL; - continue; - } - } - return true; -} - -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp) - : LLViewerVisualParam(), - mDefaultVec(), - mJointScales(), - mJointOffsets(), - mAvatar(avatarp) -{ - mDefaultVec.splat(0.001f); -} - -//----------------------------------------------------------------------------- -// LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::LLPolySkeletalDistortion(const LLPolySkeletalDistortion &pOther) - : LLViewerVisualParam(pOther), - mDefaultVec(pOther.mDefaultVec), - mJointScales(pOther.mJointScales), - mJointOffsets(pOther.mJointOffsets), - mAvatar(pOther.mAvatar) -{ -} - -//----------------------------------------------------------------------------- -// ~LLPolySkeletalDistortion() -//----------------------------------------------------------------------------- -LLPolySkeletalDistortion::~LLPolySkeletalDistortion() -{ -} - -bool LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) -{ - if (info->mID < 0) - { - return false; - } - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight()); - - for (LLPolySkeletalBoneInfo& bone_info : getInfo()->mBoneInfoList) - { - LLJoint* joint = mAvatar->getJoint(bone_info.mBoneName); - if (!joint) - { - // There's no point continuing after this error - means - // that either the skeleton or lad file is broken. - LL_WARNS() << "Joint " << bone_info.mBoneName << " not found." << LL_ENDL; - return false; - } - - // store it - mJointScales[joint] = bone_info.mScaleDeformation; - - // apply to children that need to inherit it - for (LLJoint* joint : joint->mChildren) - { - LLAvatarJoint* child_joint = (LLAvatarJoint*)joint; - if (child_joint->inheritScale()) - { - LLVector3 childDeformation = LLVector3(child_joint->getScale()); - childDeformation.scaleVec(bone_info.mScaleDeformation); - mJointScales[child_joint] = childDeformation; - } - } - - if (bone_info.mHasPositionDeformation) - { - mJointOffsets[joint] = bone_info.mPositionDeformation; - } - } - return true; -} - -/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const -{ - return new LLPolySkeletalDistortion(*this); -} - -//----------------------------------------------------------------------------- -// apply() -//----------------------------------------------------------------------------- -void LLPolySkeletalDistortion::apply( ESex avatar_sex ) -{ - LL_PROFILE_ZONE_SCOPED; - - F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); - - LLJoint* joint; - - for (joint_vec_map_t::value_type& scale_pair : mJointScales) - { - joint = scale_pair.first; - LLVector3 newScale = joint->getScale(); - LLVector3 scaleDelta = scale_pair.second; - LLVector3 offset = (effective_weight - mLastWeight) * scaleDelta; - newScale = newScale + offset; - //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached - // needed? - // joint->storeScaleForReset( newScale ); - - // BENTO for detailed stack tracing of params. - std::stringstream ostr; - ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset; - LLScopedContextString str(ostr.str()); - - joint->setScale(newScale, true); - } - - for (joint_vec_map_t::value_type& offset_pair : mJointOffsets) - { - joint = offset_pair.first; - LLVector3 newPosition = joint->getPosition(); - LLVector3 positionDelta = offset_pair.second; - newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); - // SL-315 - bool allow_attachment_pos_overrides = true; - joint->setPosition(newPosition, allow_attachment_pos_overrides); - } - - if (mLastWeight != effective_weight && !mIsAnimating) - { - mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); - } - mLastWeight = effective_weight; -} - - -LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = src_data->mCoords[v]; - cloned_morph_data->mNormals[v] = src_data->mNormals[v]; - cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; - } - return cloned_morph_data; -} - -LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, - const LLVector3 &direction, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - LLVector4a dir; - dir.load3(direction.mV); - - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = dir; - cloned_morph_data->mNormals[v].clear(); - cloned_morph_data->mBinormals[v].clear(); - } - return cloned_morph_data; -} - -LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, - F32 scale, - const std::string &name) -{ - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - - LLVector4a sc; - sc.splat(scale); - - LLVector4a nsc; - nsc.set(scale, -scale, scale, scale); - - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - if (cloned_morph_data->mCoords[v][1] < 0) - { - cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); - cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); - cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); - } - else - { - cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); - cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); - cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); - } - } - return cloned_morph_data; -} - -// End +/** + * @file llpolyskeletaldistortion.cpp + * @brief Implementation of LLPolySkeletalDistortion classes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "llpreprocessor.h" +#include "llerror.h" +#include "llavatarappearance.h" +#include "llavatarjoint.h" +#include "llpolymorph.h" +#include "llwearable.h" +#include "llfasttimer.h" +#include "llcallstack.h" + +#include "llpolyskeletaldistortion.h" + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortionInfo() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortionInfo::LLPolySkeletalDistortionInfo() +{ +} + +bool LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "param" ) && node->getChildByName( "param_skeleton" ) ); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return false; + + LLXmlTreeNode* skeletalParam = node->getChildByName("param_skeleton"); + + if (NULL == skeletalParam) + { + LL_WARNS() << "Failed to getChildByName(\"param_skeleton\")" + << LL_ENDL; + return false; + } + + for( LLXmlTreeNode* bone = skeletalParam->getFirstChild(); bone; bone = skeletalParam->getNextChild() ) + { + if (bone->hasName("bone")) + { + std::string name; + LLVector3 scale; + LLVector3 pos; + bool haspos = false; + + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!bone->getFastAttributeString(name_string, name)) + { + LL_WARNS() << "No bone name specified for skeletal param." << LL_ENDL; + continue; + } + + static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); + if (!bone->getFastAttributeVector3(scale_string, scale)) + { + LL_WARNS() << "No scale specified for bone " << name << "." << LL_ENDL; + continue; + } + + // optional offset deformation (translation) + static LLStdStringHandle offset_string = LLXmlTree::addAttributeString("offset"); + if (bone->getFastAttributeVector3(offset_string, pos)) + { + haspos = true; + } + mBoneInfoList.push_back(LLPolySkeletalBoneInfo(name, scale, pos, haspos)); + } + else + { + LL_WARNS() << "Unrecognized element " << bone->getName() << " in skeletal distortion" << LL_ENDL; + continue; + } + } + return true; +} + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLAvatarAppearance *avatarp) + : LLViewerVisualParam(), + mDefaultVec(), + mJointScales(), + mJointOffsets(), + mAvatar(avatarp) +{ + mDefaultVec.splat(0.001f); +} + +//----------------------------------------------------------------------------- +// LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::LLPolySkeletalDistortion(const LLPolySkeletalDistortion &pOther) + : LLViewerVisualParam(pOther), + mDefaultVec(pOther.mDefaultVec), + mJointScales(pOther.mJointScales), + mJointOffsets(pOther.mJointOffsets), + mAvatar(pOther.mAvatar) +{ +} + +//----------------------------------------------------------------------------- +// ~LLPolySkeletalDistortion() +//----------------------------------------------------------------------------- +LLPolySkeletalDistortion::~LLPolySkeletalDistortion() +{ +} + +bool LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) +{ + if (info->mID < 0) + { + return false; + } + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight()); + + for (LLPolySkeletalBoneInfo& bone_info : getInfo()->mBoneInfoList) + { + LLJoint* joint = mAvatar->getJoint(bone_info.mBoneName); + if (!joint) + { + // There's no point continuing after this error - means + // that either the skeleton or lad file is broken. + LL_WARNS() << "Joint " << bone_info.mBoneName << " not found." << LL_ENDL; + return false; + } + + // store it + mJointScales[joint] = bone_info.mScaleDeformation; + + // apply to children that need to inherit it + for (LLJoint* joint : joint->mChildren) + { + LLAvatarJoint* child_joint = (LLAvatarJoint*)joint; + if (child_joint->inheritScale()) + { + LLVector3 childDeformation = LLVector3(child_joint->getScale()); + childDeformation.scaleVec(bone_info.mScaleDeformation); + mJointScales[child_joint] = childDeformation; + } + } + + if (bone_info.mHasPositionDeformation) + { + mJointOffsets[joint] = bone_info.mPositionDeformation; + } + } + return true; +} + +/*virtual*/ LLViewerVisualParam* LLPolySkeletalDistortion::cloneParam(LLWearable* wearable) const +{ + return new LLPolySkeletalDistortion(*this); +} + +//----------------------------------------------------------------------------- +// apply() +//----------------------------------------------------------------------------- +void LLPolySkeletalDistortion::apply( ESex avatar_sex ) +{ + LL_PROFILE_ZONE_SCOPED; + + F32 effective_weight = ( getSex() & avatar_sex ) ? mCurWeight : getDefaultWeight(); + + LLJoint* joint; + + for (joint_vec_map_t::value_type& scale_pair : mJointScales) + { + joint = scale_pair.first; + LLVector3 newScale = joint->getScale(); + LLVector3 scaleDelta = scale_pair.second; + LLVector3 offset = (effective_weight - mLastWeight) * scaleDelta; + newScale = newScale + offset; + //An aspect of attached mesh objects (which contain joint offsets) that need to be cleaned up when detached + // needed? + // joint->storeScaleForReset( newScale ); + + // BENTO for detailed stack tracing of params. + std::stringstream ostr; + ostr << "LLPolySkeletalDistortion::apply, id " << getID() << " " << getName() << " effective wt " << effective_weight << " last wt " << mLastWeight << " scaleDelta " << scaleDelta << " offset " << offset; + LLScopedContextString str(ostr.str()); + + joint->setScale(newScale, true); + } + + for (joint_vec_map_t::value_type& offset_pair : mJointOffsets) + { + joint = offset_pair.first; + LLVector3 newPosition = joint->getPosition(); + LLVector3 positionDelta = offset_pair.second; + newPosition = newPosition + (effective_weight * positionDelta) - (mLastWeight * positionDelta); + // SL-315 + bool allow_attachment_pos_overrides = true; + joint->setPosition(newPosition, allow_attachment_pos_overrides); + } + + if (mLastWeight != effective_weight && !mIsAnimating) + { + mAvatar->setSkeletonSerialNum(mAvatar->getSkeletonSerialNum() + 1); + } + mLastWeight = effective_weight; +} + + +LLPolyMorphData *clone_morph_param_duplicate(const LLPolyMorphData *src_data, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = src_data->mCoords[v]; + cloned_morph_data->mNormals[v] = src_data->mNormals[v]; + cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]; + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, + const LLVector3 &direction, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + LLVector4a dir; + dir.load3(direction.mV); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = dir; + cloned_morph_data->mNormals[v].clear(); + cloned_morph_data->mBinormals[v].clear(); + } + return cloned_morph_data; +} + +LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, + F32 scale, + const std::string &name) +{ + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + + LLVector4a sc; + sc.splat(scale); + + LLVector4a nsc; + nsc.set(scale, -scale, scale, scale); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); + } + else + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); + } + } + return cloned_morph_data; +} + +// End diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index 252ed70b7f..9ba4cf66e9 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -1,123 +1,123 @@ -/** - * @file llpolyskeletaldistortion.h - * @brief Implementation of LLPolyMesh class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLPOLYSKELETALDISTORTION_H -#define LL_LLPOLYSKELETALDISTORTION_H - -#include "llcommon.h" - -#include -#include -#include "llstl.h" - -#include "v3math.h" -#include "v2math.h" -#include "llquaternion.h" -//#include "llpolymorph.h" -#include "lljoint.h" -#include "llviewervisualparam.h" - -//class LLSkinJoint; -class LLAvatarAppearance; - -//#define USE_STRIPS // Use tri-strips for rendering. - -//----------------------------------------------------------------------------- -// LLPolySkeletalDeformationInfo -// Shared information for LLPolySkeletalDeformations -//----------------------------------------------------------------------------- -struct LLPolySkeletalBoneInfo -{ - LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, bool haspos) - : mBoneName(name), - mScaleDeformation(scale), - mPositionDeformation(pos), - mHasPositionDeformation(haspos) {} - std::string mBoneName; - LLVector3 mScaleDeformation; - LLVector3 mPositionDeformation; - bool mHasPositionDeformation; -}; - -class alignas(16) LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo -{ - LL_ALIGN_NEW - friend class LLPolySkeletalDistortion; -public: - - LLPolySkeletalDistortionInfo(); - /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; - - /*virtual*/ bool parseXml(LLXmlTreeNode* node); - -protected: - typedef std::vector bone_info_list_t; - bone_info_list_t mBoneInfoList; -}; - -//----------------------------------------------------------------------------- -// LLPolySkeletalDeformation -// A set of joint scale data for deforming the avatar mesh -//----------------------------------------------------------------------------- -class alignas(16) LLPolySkeletalDistortion : public LLViewerVisualParam -{ - LL_ALIGN_NEW -public: - LLPolySkeletalDistortion(LLAvatarAppearance *avatarp); - ~LLPolySkeletalDistortion(); - - // Special: These functions are overridden by child classes - LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } - // This sets mInfo and calls initialization functions - bool setInfo(LLPolySkeletalDistortionInfo *info); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; - - // LLVisualParam Virtual functions - ///*virtual*/ bool parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex sex ); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 0.1f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } - /*virtual*/ F32 getMaxDistortion() { return 0.1f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; - -protected: - LLPolySkeletalDistortion(const LLPolySkeletalDistortion& pOther); - - LL_ALIGN_16(LLVector4a mDefaultVec); - typedef std::map joint_vec_map_t; - joint_vec_map_t mJointScales; - joint_vec_map_t mJointOffsets; - // Backlink only; don't make this an LLPointer. - LLAvatarAppearance *mAvatar; -} LL_ALIGN_POSTFIX(16); - -#endif // LL_LLPOLYSKELETALDISTORTION_H - +/** + * @file llpolyskeletaldistortion.h + * @brief Implementation of LLPolyMesh class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLPOLYSKELETALDISTORTION_H +#define LL_LLPOLYSKELETALDISTORTION_H + +#include "llcommon.h" + +#include +#include +#include "llstl.h" + +#include "v3math.h" +#include "v2math.h" +#include "llquaternion.h" +//#include "llpolymorph.h" +#include "lljoint.h" +#include "llviewervisualparam.h" + +//class LLSkinJoint; +class LLAvatarAppearance; + +//#define USE_STRIPS // Use tri-strips for rendering. + +//----------------------------------------------------------------------------- +// LLPolySkeletalDeformationInfo +// Shared information for LLPolySkeletalDeformations +//----------------------------------------------------------------------------- +struct LLPolySkeletalBoneInfo +{ + LLPolySkeletalBoneInfo(std::string &name, LLVector3 &scale, LLVector3 &pos, bool haspos) + : mBoneName(name), + mScaleDeformation(scale), + mPositionDeformation(pos), + mHasPositionDeformation(haspos) {} + std::string mBoneName; + LLVector3 mScaleDeformation; + LLVector3 mPositionDeformation; + bool mHasPositionDeformation; +}; + +class alignas(16) LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo +{ + LL_ALIGN_NEW + friend class LLPolySkeletalDistortion; +public: + + LLPolySkeletalDistortionInfo(); + /*virtual*/ ~LLPolySkeletalDistortionInfo() {}; + + /*virtual*/ bool parseXml(LLXmlTreeNode* node); + +protected: + typedef std::vector bone_info_list_t; + bone_info_list_t mBoneInfoList; +}; + +//----------------------------------------------------------------------------- +// LLPolySkeletalDeformation +// A set of joint scale data for deforming the avatar mesh +//----------------------------------------------------------------------------- +class alignas(16) LLPolySkeletalDistortion : public LLViewerVisualParam +{ + LL_ALIGN_NEW +public: + LLPolySkeletalDistortion(LLAvatarAppearance *avatarp); + ~LLPolySkeletalDistortion(); + + // Special: These functions are overridden by child classes + LLPolySkeletalDistortionInfo* getInfo() const { return (LLPolySkeletalDistortionInfo*)mInfo; } + // This sets mInfo and calls initialization functions + bool setInfo(LLPolySkeletalDistortionInfo *info); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; + + // LLVisualParam Virtual functions + ///*virtual*/ bool parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex sex ); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 0.1f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } + /*virtual*/ F32 getMaxDistortion() { return 0.1f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; + +protected: + LLPolySkeletalDistortion(const LLPolySkeletalDistortion& pOther); + + LL_ALIGN_16(LLVector4a mDefaultVec); + typedef std::map joint_vec_map_t; + joint_vec_map_t mJointScales; + joint_vec_map_t mJointOffsets; + // Backlink only; don't make this an LLPointer. + LLAvatarAppearance *mAvatar; +} LL_ALIGN_POSTFIX(16); + +#endif // LL_LLPOLYSKELETALDISTORTION_H + diff --git a/indra/llappearance/lltexglobalcolor.cpp b/indra/llappearance/lltexglobalcolor.cpp index d01a7cb3d3..e39a856b78 100644 --- a/indra/llappearance/lltexglobalcolor.cpp +++ b/indra/llappearance/lltexglobalcolor.cpp @@ -1,165 +1,165 @@ -/** - * @file lltexlayerglobalcolor.cpp - * @brief Color for texture layers. - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llavatarappearance.h" -#include "lltexlayer.h" -#include "lltexglobalcolor.h" - -class LLWearable; - -//----------------------------------------------------------------------------- -// LLTexGlobalColor -//----------------------------------------------------------------------------- - -LLTexGlobalColor::LLTexGlobalColor(LLAvatarAppearance* appearance) - : - mAvatarAppearance(appearance), - mInfo(NULL) -{ -} - -LLTexGlobalColor::~LLTexGlobalColor() -{ - // mParamColorList are LLViewerVisualParam's and get deleted with ~LLCharacter() - //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); -} - -bool LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) -{ - llassert(mInfo == NULL); - mInfo = info; - //mID = info->mID; // No ID - - mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size()); - for (LLTexLayerParamColorInfo* color_info : mInfo->mParamColorInfoList) - { - LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); - if (!param_color->setInfo(color_info, true)) - { - mInfo = NULL; - return false; - } - mParamGlobalColorList.push_back(param_color); - } - - return true; -} - -LLColor4 LLTexGlobalColor::getColor() const -{ - // Sum of color params - if (mParamGlobalColorList.empty()) - return LLColor4(1.f, 1.f, 1.f, 1.f); - - LLColor4 net_color(0.f, 0.f, 0.f, 0.f); - LLTexLayer::calculateTexLayerColor(mParamGlobalColorList, net_color); - return net_color; -} - -const std::string& LLTexGlobalColor::getName() const -{ - return mInfo->mName; -} - -//----------------------------------------------------------------------------- -// LLTexParamGlobalColor -//----------------------------------------------------------------------------- -LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) - : LLTexLayerParamColor(tex_global_color->getAvatarAppearance()), - mTexGlobalColor(tex_global_color) -{ -} - -//----------------------------------------------------------------------------- -// LLTexParamGlobalColor -//----------------------------------------------------------------------------- -LLTexParamGlobalColor::LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther) - : LLTexLayerParamColor(pOther), - mTexGlobalColor(pOther.mTexGlobalColor) -{ -} - -//----------------------------------------------------------------------------- -// ~LLTexParamGlobalColor -//----------------------------------------------------------------------------- -LLTexParamGlobalColor::~LLTexParamGlobalColor() -{ -} - -/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const -{ - return new LLTexParamGlobalColor(*this); -} - -void LLTexParamGlobalColor::onGlobalColorChanged() -{ - mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor); -} - -//----------------------------------------------------------------------------- -// LLTexGlobalColorInfo -//----------------------------------------------------------------------------- - -LLTexGlobalColorInfo::LLTexGlobalColorInfo() -{ -} - - -LLTexGlobalColorInfo::~LLTexGlobalColorInfo() -{ - for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); - mParamColorInfoList.clear(); -} - -bool LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) -{ - // name attribute - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if (!node->getFastAttributeString(name_string, mName)) - { - LL_WARNS() << " element is missing name attribute." << LL_ENDL; - return false; - } - // sub-element - for (LLXmlTreeNode* child = node->getChildByName("param"); - child; - child = node->getNextNamedChild()) - { - if (child->getChildByName("param_color")) - { - // - LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); - if (!info->parseXml(child)) - { - delete info; - return false; - } - mParamColorInfoList.push_back(info); - } - } - return true; -} +/** + * @file lltexlayerglobalcolor.cpp + * @brief Color for texture layers. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llavatarappearance.h" +#include "lltexlayer.h" +#include "lltexglobalcolor.h" + +class LLWearable; + +//----------------------------------------------------------------------------- +// LLTexGlobalColor +//----------------------------------------------------------------------------- + +LLTexGlobalColor::LLTexGlobalColor(LLAvatarAppearance* appearance) + : + mAvatarAppearance(appearance), + mInfo(NULL) +{ +} + +LLTexGlobalColor::~LLTexGlobalColor() +{ + // mParamColorList are LLViewerVisualParam's and get deleted with ~LLCharacter() + //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); +} + +bool LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info) +{ + llassert(mInfo == NULL); + mInfo = info; + //mID = info->mID; // No ID + + mParamGlobalColorList.reserve(mInfo->mParamColorInfoList.size()); + for (LLTexLayerParamColorInfo* color_info : mInfo->mParamColorInfoList) + { + LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this); + if (!param_color->setInfo(color_info, true)) + { + mInfo = NULL; + return false; + } + mParamGlobalColorList.push_back(param_color); + } + + return true; +} + +LLColor4 LLTexGlobalColor::getColor() const +{ + // Sum of color params + if (mParamGlobalColorList.empty()) + return LLColor4(1.f, 1.f, 1.f, 1.f); + + LLColor4 net_color(0.f, 0.f, 0.f, 0.f); + LLTexLayer::calculateTexLayerColor(mParamGlobalColorList, net_color); + return net_color; +} + +const std::string& LLTexGlobalColor::getName() const +{ + return mInfo->mName; +} + +//----------------------------------------------------------------------------- +// LLTexParamGlobalColor +//----------------------------------------------------------------------------- +LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) + : LLTexLayerParamColor(tex_global_color->getAvatarAppearance()), + mTexGlobalColor(tex_global_color) +{ +} + +//----------------------------------------------------------------------------- +// LLTexParamGlobalColor +//----------------------------------------------------------------------------- +LLTexParamGlobalColor::LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther) + : LLTexLayerParamColor(pOther), + mTexGlobalColor(pOther.mTexGlobalColor) +{ +} + +//----------------------------------------------------------------------------- +// ~LLTexParamGlobalColor +//----------------------------------------------------------------------------- +LLTexParamGlobalColor::~LLTexParamGlobalColor() +{ +} + +/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const +{ + return new LLTexParamGlobalColor(*this); +} + +void LLTexParamGlobalColor::onGlobalColorChanged() +{ + mAvatarAppearance->onGlobalColorChanged(mTexGlobalColor); +} + +//----------------------------------------------------------------------------- +// LLTexGlobalColorInfo +//----------------------------------------------------------------------------- + +LLTexGlobalColorInfo::LLTexGlobalColorInfo() +{ +} + + +LLTexGlobalColorInfo::~LLTexGlobalColorInfo() +{ + for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); + mParamColorInfoList.clear(); +} + +bool LLTexGlobalColorInfo::parseXml(LLXmlTreeNode* node) +{ + // name attribute + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if (!node->getFastAttributeString(name_string, mName)) + { + LL_WARNS() << " element is missing name attribute." << LL_ENDL; + return false; + } + // sub-element + for (LLXmlTreeNode* child = node->getChildByName("param"); + child; + child = node->getNextNamedChild()) + { + if (child->getChildByName("param_color")) + { + // + LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); + if (!info->parseXml(child)) + { + delete info; + return false; + } + mParamColorInfoList.push_back(info); + } + } + return true; +} diff --git a/indra/llappearance/lltexglobalcolor.h b/indra/llappearance/lltexglobalcolor.h index 8fd0da79f6..7561ea7df9 100644 --- a/indra/llappearance/lltexglobalcolor.h +++ b/indra/llappearance/lltexglobalcolor.h @@ -1,85 +1,85 @@ -/** - * @file lltexglobalcolor.h - * @brief This is global texture color info used by llavatarappearance. - * - * $LicenseInfo:firstyear=2008&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTEXGLOBALCOLOR_H -#define LL_LLTEXGLOBALCOLOR_H - -#include "lltexlayer.h" -#include "lltexlayerparams.h" - -class LLAvatarAppearance; -class LLWearable; -class LLTexGlobalColorInfo; - -class LLTexGlobalColor -{ -public: - LLTexGlobalColor( LLAvatarAppearance* appearance ); - ~LLTexGlobalColor(); - - LLTexGlobalColorInfo* getInfo() const { return mInfo; } - // This sets mInfo and calls initialization functions - bool setInfo(LLTexGlobalColorInfo *info); - - LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } - LLColor4 getColor() const; - const std::string& getName() const; - -private: - param_color_list_t mParamGlobalColorList; - LLAvatarAppearance* mAvatarAppearance; // just backlink, don't LLPointer - LLTexGlobalColorInfo *mInfo; -}; - -// Used by llavatarappearance to determine skin/eye/hair color. -class LLTexGlobalColorInfo -{ - friend class LLTexGlobalColor; -public: - LLTexGlobalColorInfo(); - ~LLTexGlobalColorInfo(); - - bool parseXml(LLXmlTreeNode* node); - -private: - param_color_info_list_t mParamColorInfoList; - std::string mName; -}; - -class LLTexParamGlobalColor : public LLTexLayerParamColor -{ -public: - LLTexParamGlobalColor(LLTexGlobalColor *tex_color); - virtual ~LLTexParamGlobalColor(); - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; -protected: - LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther); - /*virtual*/ void onGlobalColorChanged(); -private: - LLTexGlobalColor* mTexGlobalColor; -}; - -#endif +/** + * @file lltexglobalcolor.h + * @brief This is global texture color info used by llavatarappearance. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXGLOBALCOLOR_H +#define LL_LLTEXGLOBALCOLOR_H + +#include "lltexlayer.h" +#include "lltexlayerparams.h" + +class LLAvatarAppearance; +class LLWearable; +class LLTexGlobalColorInfo; + +class LLTexGlobalColor +{ +public: + LLTexGlobalColor( LLAvatarAppearance* appearance ); + ~LLTexGlobalColor(); + + LLTexGlobalColorInfo* getInfo() const { return mInfo; } + // This sets mInfo and calls initialization functions + bool setInfo(LLTexGlobalColorInfo *info); + + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + LLColor4 getColor() const; + const std::string& getName() const; + +private: + param_color_list_t mParamGlobalColorList; + LLAvatarAppearance* mAvatarAppearance; // just backlink, don't LLPointer + LLTexGlobalColorInfo *mInfo; +}; + +// Used by llavatarappearance to determine skin/eye/hair color. +class LLTexGlobalColorInfo +{ + friend class LLTexGlobalColor; +public: + LLTexGlobalColorInfo(); + ~LLTexGlobalColorInfo(); + + bool parseXml(LLXmlTreeNode* node); + +private: + param_color_info_list_t mParamColorInfoList; + std::string mName; +}; + +class LLTexParamGlobalColor : public LLTexLayerParamColor +{ +public: + LLTexParamGlobalColor(LLTexGlobalColor *tex_color); + virtual ~LLTexParamGlobalColor(); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const; +protected: + LLTexParamGlobalColor(const LLTexParamGlobalColor& pOther); + /*virtual*/ void onGlobalColorChanged(); +private: + LLTexGlobalColor* mTexGlobalColor; +}; + +#endif diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index d1913134c4..60ff19f952 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1,1920 +1,1920 @@ -/** - * @file lltexlayer.cpp - * @brief A texture layer. Used for avatars. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lltexlayer.h" - -#include "llavatarappearance.h" -#include "llcrc.h" -#include "llimagej2c.h" -#include "llimagetga.h" -#include "lldir.h" -#include "lltexlayerparams.h" -#include "lltexturemanagerbridge.h" -#include "lllocaltextureobject.h" -#include "../llui/llui.h" -#include "llwearable.h" -#include "llwearabledata.h" -#include "llvertexbuffer.h" -#include "llviewervisualparam.h" -#include "llfasttimer.h" - -//#include "../tools/imdebug/imdebug.h" - -using namespace LLAvatarAppearanceDefines; - -// runway consolidate -extern std::string self_av_string(); - -class LLTexLayerInfo -{ - friend class LLTexLayer; - friend class LLTexLayerTemplate; - friend class LLTexLayerInterface; -public: - LLTexLayerInfo(); - ~LLTexLayerInfo(); - - bool parseXml(LLXmlTreeNode* node); - bool createVisualParams(LLAvatarAppearance *appearance); - bool isUserSettable() { return mLocalTexture != -1; } - S32 getLocalTexture() const { return mLocalTexture; } - bool getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } - std::string getName() const { return mName; } - -private: - std::string mName; - - bool mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, - LLTexLayerInterface::ERenderPass mRenderPass; - - std::string mGlobalColor; - LLColor4 mFixedColor; - - S32 mLocalTexture; - std::string mStaticImageFileName; - bool mStaticImageIsMask; - bool mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask - bool mIsVisibilityMask; - - typedef std::vector< std::pair< std::string,bool > > morph_name_list_t; - morph_name_list_t mMorphNameList; - param_color_info_list_t mParamColorInfoList; - param_alpha_info_list_t mParamAlphaInfoList; -}; - -//----------------------------------------------------------------------------- -// LLTexLayerSetBuffer -// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. -//----------------------------------------------------------------------------- - -LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner) : - mTexLayerSet(owner) -{ -} - -LLTexLayerSetBuffer::~LLTexLayerSetBuffer() -{ -} - -void LLTexLayerSetBuffer::pushProjection() const -{ - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.ortho(0.0f, getCompositeWidth(), 0.0f, getCompositeHeight(), -1.0f, 1.0f); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); -} - -void LLTexLayerSetBuffer::popProjection() const -{ - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); -} - -// virtual -void LLTexLayerSetBuffer::preRenderTexLayerSet() -{ - // Set up an ortho projection - pushProjection(); -} - -// virtual -void LLTexLayerSetBuffer::postRenderTexLayerSet(bool success) -{ - popProjection(); -} - -bool LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) -{ - // Default color mask for tex layer render - gGL.setColorMask(true, true); - - bool success = true; - - gAlphaMaskProgram.bind(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - - LLVertexBuffer::unbind(); - - // Composite the color data - LLGLSUIDefault gls_ui; - success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), - getCompositeWidth(), getCompositeHeight(), bound_target ); - gGL.flush(); - - midRenderTexLayerSet(success); - - gAlphaMaskProgram.unbind(); - - LLVertexBuffer::unbind(); - - // reset GL state - gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - return success; -} - -//----------------------------------------------------------------------------- -// LLTexLayerSetInfo -// An ordered set of texture layers that get composited into a single texture. -//----------------------------------------------------------------------------- - -LLTexLayerSetInfo::LLTexLayerSetInfo() : - mBodyRegion( "" ), - mWidth( 512 ), - mHeight( 512 ), - mClearAlpha( true ) -{ -} - -LLTexLayerSetInfo::~LLTexLayerSetInfo( ) -{ - std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); - mLayerInfoList.clear(); -} - -bool LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "layer_set" ) ); - if( !node->hasName( "layer_set" ) ) - { - return false; - } - - // body_region - static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region"); - if( !node->getFastAttributeString( body_region_string, mBodyRegion ) ) - { - LL_WARNS() << " is missing body_region attribute" << LL_ENDL; - return false; - } - - // width, height - static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width"); - if( !node->getFastAttributeS32( width_string, mWidth ) ) - { - return false; - } - - static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height"); - if( !node->getFastAttributeS32( height_string, mHeight ) ) - { - return false; - } - - // Optional alpha component to apply after all compositing is complete. - static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file"); - node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName ); - - static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha"); - node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha ); - - // - for (LLXmlTreeNode* child = node->getChildByName( "layer" ); - child; - child = node->getNextNamedChild()) - { - LLTexLayerInfo* info = new LLTexLayerInfo(); - if( !info->parseXml( child )) - { - delete info; - return false; - } - mLayerInfoList.push_back( info ); - } - return true; -} - -// creates visual params without generating layersets or layers -void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance) -{ - //layer_info_list_t mLayerInfoList; - for (LLTexLayerInfo* layer_info : mLayerInfoList) - { - layer_info->createVisualParams(appearance); - } -} - -//----------------------------------------------------------------------------- -// LLTexLayerSet -// An ordered set of texture layers that get composited into a single texture. -//----------------------------------------------------------------------------- - -bool LLTexLayerSet::sHasCaches = false; - -LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) : - mAvatarAppearance( appearance ), - mIsVisible( true ), - mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD), - mInfo( NULL ) -{ -} - -// virtual -LLTexLayerSet::~LLTexLayerSet() -{ - deleteCaches(); - std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer()); - mLayerList.clear(); - - std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer()); - mMaskLayerList.clear(); -} - -//----------------------------------------------------------------------------- -// setInfo -//----------------------------------------------------------------------------- - -bool LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) -{ - llassert(mInfo == NULL); - mInfo = info; - //mID = info->mID; // No ID - - mLayerList.reserve(info->mLayerInfoList.size()); - for (LLTexLayerInfo* layer_info : info->mLayerInfoList) - { - LLTexLayerInterface *layer = NULL; - if (layer_info->isUserSettable()) - { - layer = new LLTexLayerTemplate( this, getAvatarAppearance() ); - } - else - { - layer = new LLTexLayer(this); - } - // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar appearance - if (!layer->setInfo(layer_info, NULL)) - { - mInfo = NULL; - return false; - } - if (!layer->isVisibilityMask()) - { - mLayerList.push_back( layer ); - } - else - { - mMaskLayerList.push_back(layer); - } - } - - requestUpdate(); - - stop_glerror(); - - return true; -} - -#if 0 // obsolete -//----------------------------------------------------------------------------- -// parseData -//----------------------------------------------------------------------------- - -bool LLTexLayerSet::parseData(LLXmlTreeNode* node) -{ - LLTexLayerSetInfo *info = new LLTexLayerSetInfo; - - if (!info->parseXml(node)) - { - delete info; - return false; - } - if (!setInfo(info)) - { - delete info; - return false; - } - return true; -} -#endif - -void LLTexLayerSet::deleteCaches() -{ - for(LLTexLayerInterface* layer : mLayerList) - { - layer->deleteCaches(); - } - for (LLTexLayerInterface* layer : mMaskLayerList) - { - layer->deleteCaches(); - } -} - - -bool LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) -{ - bool success = true; - mIsVisible = true; - - if (mMaskLayerList.size() > 0) - { - for (LLTexLayerInterface* layer : mMaskLayerList) - { - if (layer->isInvisibleAlphaMask()) - { - mIsVisible = false; - } - } - } - - LLGLSUIDefault gls_ui; - LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); - gGL.setColorMask(true, true); - - // clear buffer area to ensure we don't pick up UI elements - { - gGL.flush(); - gAlphaMaskProgram.setMinimumAlpha(0.0f); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 1.f ); - - gl_rect_2d_simple( width, height ); - - gGL.flush(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - if (mIsVisible) - { - // composite color layers - for(LLTexLayerInterface* layer : mLayerList) - { - if (layer->getRenderPass() == LLTexLayer::RP_COLOR) - { - gGL.flush(); - success &= layer->render(x, y, width, height, bound_target); - gGL.flush(); - } - } - - renderAlphaMaskTextures(x, y, width, height, bound_target, false); - - stop_glerror(); - } - else - { - gGL.flush(); - - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gAlphaMaskProgram.setMinimumAlpha(0.f); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 0.f ); - - gl_rect_2d_simple( width, height ); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - gGL.flush(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - return success; -} - - -bool LLTexLayerSet::isBodyRegion(const std::string& region) const -{ - return mInfo->mBodyRegion == region; -} - -const std::string LLTexLayerSet::getBodyRegionName() const -{ - return mInfo->mBodyRegion; -} - -void LLTexLayerSet::destroyComposite() -{ - if( mComposite ) - { - mComposite = NULL; - } -} - -LLTexLayerSetBuffer* LLTexLayerSet::getComposite() -{ - if (!mComposite) - { - createComposite(); - } - return mComposite; -} - -const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const -{ - return mComposite; -} - -void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target) -{ - LL_PROFILE_ZONE_SCOPED; - memset(data, 255, width * height); - - for(LLTexLayerInterface* layer : mLayerList) - { - layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target); - } - - // Set alpha back to that of our alpha masks. - renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true); -} - -void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear) -{ - LL_PROFILE_ZONE_SCOPED; - const LLTexLayerSetInfo *info = getInfo(); - - gGL.setColorMask(false, true); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - - // (Optionally) replace alpha with a single component image from a tga file. - if (!info->mStaticAlphaFileName.empty()) - { - gGL.flush(); - { - LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, true); - if( tex ) - { - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->bind(tex); - gl_rect_2d_simple_tex( width, height ); - } - } - gGL.flush(); - } - else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0)) - { - // Set the alpha channel to one (clean up after previous blending) - gGL.flush(); - gAlphaMaskProgram.setMinimumAlpha(0.f); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f( 0.f, 0.f, 0.f, 1.f ); - - gl_rect_2d_simple( width, height ); - - gGL.flush(); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - // (Optional) Mask out part of the baked texture with alpha masks - // will still have an effect even if mClearAlpha is set or the alpha component was replaced - if (mMaskLayerList.size() > 0) - { - gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); - for (LLTexLayerInterface* layer : mMaskLayerList) - { - gGL.flush(); - layer->blendAlphaTexture(x,y,width, height); - gGL.flush(); - } - - } - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.setColorMask(true, true); - gGL.setSceneBlendType(LLRender::BT_ALPHA); -} - -void LLTexLayerSet::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components) -{ - mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); -} - -bool LLTexLayerSet::isMorphValid() const -{ - for(const LLTexLayerInterface* layer : mLayerList) - { - if (layer && !layer->isMorphValid()) - { - return false; - } - } - return true; -} - -void LLTexLayerSet::invalidateMorphMasks() -{ - for(LLTexLayerInterface* layer : mLayerList) - { - if (layer) - { - layer->invalidateMorphMasks(); - } - } -} - - -//----------------------------------------------------------------------------- -// LLTexLayerInfo -//----------------------------------------------------------------------------- -LLTexLayerInfo::LLTexLayerInfo() : - mWriteAllChannels( false ), - mRenderPass(LLTexLayer::RP_COLOR), - mFixedColor( 0.f, 0.f, 0.f, 0.f ), - mLocalTexture( -1 ), - mStaticImageIsMask( false ), - mUseLocalTextureAlphaOnly(false), - mIsVisibilityMask(false) -{ -} - -LLTexLayerInfo::~LLTexLayerInfo( ) -{ - std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); - mParamColorInfoList.clear(); - std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer()); - mParamAlphaInfoList.clear(); -} - -bool LLTexLayerInfo::parseXml(LLXmlTreeNode* node) -{ - llassert( node->hasName( "layer" ) ); - - // name attribute - static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); - if( !node->getFastAttributeString( name_string, mName ) ) - { - return false; - } - - static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels"); - node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels ); - - std::string render_pass_name; - static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass"); - if( node->getFastAttributeString( render_pass_string, render_pass_name ) ) - { - if( render_pass_name == "bump" ) - { - mRenderPass = LLTexLayer::RP_BUMP; - } - } - - // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a child. - // global color attribute (optional) - static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color"); - node->getFastAttributeString( global_color_string, mGlobalColor ); - - // Visibility mask (optional) - bool is_visibility; - static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask"); - if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility)) - { - mIsVisibilityMask = is_visibility; - } - - // color attribute (optional) - LLColor4U color4u; - static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color"); - if( node->getFastAttributeColor4U( fixed_color_string, color4u ) ) - { - mFixedColor.setVec( color4u ); - } - - // optional sub-element - for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" ); - texture_node; - texture_node = node->getNextNamedChild()) - { - std::string local_texture_name; - static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); - static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture"); - static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask"); - static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only"); - if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) - { - texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask ); - } - else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name)) - { - texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly ); - - /* if ("upper_shirt" == local_texture_name) - mLocalTexture = TEX_UPPER_SHIRT; */ - mLocalTexture = TEX_NUM_INDICES; - for (const LLAvatarAppearanceDictionary::Textures::value_type& dict_pair : LLAvatarAppearance::getDictionary()->getTextures()) - { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = dict_pair.second; - if (local_texture_name == texture_dict->mName) - { - mLocalTexture = dict_pair.first; - break; - } - } - if (mLocalTexture == TEX_NUM_INDICES) - { - LL_WARNS() << " element has invalid local_texture attribute: " << mName << " " << local_texture_name << LL_ENDL; - return false; - } - } - else - { - LL_WARNS() << " element is missing a required attribute. " << mName << LL_ENDL; - return false; - } - } - - for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" ); - maskNode; - maskNode = node->getNextNamedChild()) - { - std::string morph_name; - static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name"); - if (maskNode->getFastAttributeString(morph_name_string, morph_name)) - { - bool invert = false; - static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); - maskNode->getFastAttributeBOOL(invert_string, invert); - mMorphNameList.push_back(std::pair(morph_name,invert)); - } - } - - // optional sub-element (color or alpha params) - for (LLXmlTreeNode* child = node->getChildByName( "param" ); - child; - child = node->getNextNamedChild()) - { - if( child->getChildByName( "param_color" ) ) - { - // - LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); - if (!info->parseXml(child)) - { - delete info; - return false; - } - mParamColorInfoList.push_back(info); - } - else if( child->getChildByName( "param_alpha" ) ) - { - // - LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( ); - if (!info->parseXml(child)) - { - delete info; - return false; - } - mParamAlphaInfoList.push_back(info); - } - } - - return true; -} - -bool LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) -{ - bool success = true; - for (LLTexLayerParamColorInfo* color_info : mParamColorInfoList) - { - LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); - if (!param_color->setInfo(color_info, true)) - { - LL_WARNS() << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << LL_ENDL; - delete param_color; - success = false; - } - } - - for (LLTexLayerParamAlphaInfo* alpha_info : mParamAlphaInfoList) - { - LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance); - if (!param_alpha->setInfo(alpha_info, true)) - { - LL_WARNS() << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << LL_ENDL; - delete param_alpha; - success = false; - } - } - - return success; -} - -LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): - mTexLayerSet( layer_set ), - mMorphMasksValid( false ), - mInfo(NULL), - mHasMorph(false) -{ -} - -LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable): - mTexLayerSet( layer.mTexLayerSet ), - mInfo(NULL) -{ - // don't add visual params for cloned layers - setInfo(layer.getInfo(), wearable); - - mHasMorph = layer.mHasMorph; -} - -bool LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions -{ - // setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer. - // Not a critical warning, but could be useful for debugging later issues. -Nyx - if (mInfo != NULL) - { - LL_WARNS() << "mInfo != NULL" << LL_ENDL; - } - mInfo = info; - //mID = info->mID; // No ID - - mParamColorList.reserve(mInfo->mParamColorInfoList.size()); - for (LLTexLayerParamColorInfo* color_info : mInfo->mParamColorInfoList) - { - LLTexLayerParamColor* param_color; - if (!wearable) - { - param_color = new LLTexLayerParamColor(this); - if (!param_color->setInfo(color_info, true)) - { - mInfo = NULL; - return false; - } - } - else - { - param_color = (LLTexLayerParamColor*)wearable->getVisualParam(color_info->getID()); - if (!param_color) - { - mInfo = NULL; - return false; - } - } - mParamColorList.push_back( param_color ); - } - - mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); - for (LLTexLayerParamAlphaInfo* alpha_info : mInfo->mParamAlphaInfoList) - { - LLTexLayerParamAlpha* param_alpha; - if (!wearable) - { - param_alpha = new LLTexLayerParamAlpha( this ); - if (!param_alpha->setInfo(alpha_info, true)) - { - mInfo = NULL; - return false; - } - } - else - { - param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam(alpha_info->getID()); - if (!param_alpha) - { - mInfo = NULL; - return false; - } - } - mParamAlphaList.push_back( param_alpha ); - } - - return true; -} - -/*virtual*/ void LLTexLayerInterface::requestUpdate() -{ - mTexLayerSet->requestUpdate(); -} - -const std::string& LLTexLayerInterface::getName() const -{ - return mInfo->mName; -} - -ETextureIndex LLTexLayerInterface::getLocalTextureIndex() const -{ - return (ETextureIndex) mInfo->mLocalTexture; -} - -LLWearableType::EType LLTexLayerInterface::getWearableType() const -{ - ETextureIndex te = getLocalTextureIndex(); - if (TEX_INVALID == te) - { - LLWearableType::EType type = LLWearableType::WT_INVALID; - - for (LLTexLayerParamColor* param : mParamColorList) - { - if (param) - { - LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType(); - if (new_type != LLWearableType::WT_INVALID && new_type != type) - { - if (type != LLWearableType::WT_INVALID) - { - return LLWearableType::WT_INVALID; - } - type = new_type; - } - } - } - - for (LLTexLayerParamAlpha* param : mParamAlphaList) - { - if (param) - { - LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType(); - if (new_type != LLWearableType::WT_INVALID && new_type != type) - { - if (type != LLWearableType::WT_INVALID) - { - return LLWearableType::WT_INVALID; - } - type = new_type; - } - } - } - - return type; - } - return LLAvatarAppearance::getDictionary()->getTEWearableType(te); -} - -LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const -{ - return mInfo->mRenderPass; -} - -const std::string& LLTexLayerInterface::getGlobalColor() const -{ - return mInfo->mGlobalColor; -} - -bool LLTexLayerInterface::isVisibilityMask() const -{ - return mInfo->mIsVisibilityMask; -} - -void LLTexLayerInterface::invalidateMorphMasks() -{ - mMorphMasksValid = false; -} - -LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const -{ - LLViewerVisualParam *result = NULL; - for (LLTexLayerParamColor* param : mParamColorList) - { - if (param->getID() == index) - { - result = param; - } - } - for (LLTexLayerParamAlpha* param : mParamAlphaList) - { - if (param->getID() == index) - { - result = param; - } - } - - return result; -} - -//----------------------------------------------------------------------------- -// LLTexLayer -// A single texture layer, consisting of: -// * color, consisting of either -// * one or more color parameters (weighted colors) -// * a reference to a global color -// * a fixed color with non-zero alpha -// * opaque white (the default) -// * (optional) a texture defined by either -// * a GUID -// * a texture entry index (TE) -// * (optional) one or more alpha parameters (weighted alpha textures) -//----------------------------------------------------------------------------- -LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) : - LLTexLayerInterface( layer_set ), - mLocalTextureObject(NULL) -{ -} - -LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) : - LLTexLayerInterface( layer, wearable ), - mLocalTextureObject(NULL) -{ -} - -LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) : - LLTexLayerInterface( layer_template, wearable ), - mLocalTextureObject(lto) -{ -} - -LLTexLayer::~LLTexLayer() -{ - // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get - // deleted with ~LLCharacter() - //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer()); - //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); - - for (alpha_cache_t::value_type& alpha_pair : mAlphaCache) - { - U8* alpha_data = alpha_pair.second; - ll_aligned_free_32(alpha_data); - } - -} - -void LLTexLayer::asLLSD(LLSD& sd) const -{ - // *TODO: Finish - sd["id"] = getUUID(); -} - -//----------------------------------------------------------------------------- -// setInfo -//----------------------------------------------------------------------------- - -bool LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) -{ - return LLTexLayerInterface::setInfo(info, wearable); -} - -//static -void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color) -{ - for (const LLTexLayerParamColor* param : param_list) - { - LLColor4 param_net = param->getNetColor(); - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); - switch(info->getOperation()) - { - case LLTexLayerParamColor::OP_ADD: - net_color += param_net; - break; - case LLTexLayerParamColor::OP_MULTIPLY: - net_color = net_color * param_net; - break; - case LLTexLayerParamColor::OP_BLEND: - net_color = lerp(net_color, param_net, param->getWeight()); - break; - default: - llassert(0); - break; - } - } - net_color.clamp(); -} - -/*virtual*/ void LLTexLayer::deleteCaches() -{ - // Only need to delete caches for alpha params. Color params don't hold extra memory - for (LLTexLayerParamAlpha* param : mParamAlphaList) - { - param->deleteCaches(); - } -} - -bool LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) -{ - // *TODO: Is this correct? - //gPipeline.disableLights(); - stop_glerror(); - - LLColor4 net_color; - bool color_specified = findNetColor(&net_color); - - if (mTexLayerSet->getAvatarAppearance()->mIsDummy) - { - color_specified = true; - net_color = LLAvatarAppearance::getDummyColor(); - } - - bool success = true; - - // If you can't see the layer, don't render it. - if( is_approx_zero( net_color.mV[VW] ) ) - { - return success; - } - - bool alpha_mask_specified = false; - param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); - if( iter != mParamAlphaList.end() ) - { - // If we have alpha masks, but we're skipping all of them, skip the whole layer. - // However, we can't do this optimization if we have morph masks that need updating. -/* if (!mHasMorph) - { - bool skip_layer = true; - - while( iter != mParamAlphaList.end() ) - { - const LLTexLayerParamAlpha* param = *iter; - - if( !param->getSkip() ) - { - skip_layer = false; - break; - } - - iter++; - } - - if( skip_layer ) - { - return success; - } - }//*/ - - const bool force_render = true; - renderMorphMasks(x, y, width, height, net_color, bound_target, force_render); - alpha_mask_specified = true; - gGL.flush(); - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); - } - - gGL.color4fv( net_color.mV); - - if( getInfo()->mWriteAllChannels ) - { - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - } - - if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) - { - { - LLGLTexture* tex = NULL; - if (mLocalTextureObject && mLocalTextureObject->getImage()) - { - tex = mLocalTextureObject->getImage(); - if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR) - { - tex = NULL; - } - } - else - { - LL_INFOS() << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << LL_ENDL; - } -// if( mTexLayerSet->getAvatarAppearance()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) - { - if( tex ) - { - bool no_alpha_test = getInfo()->mWriteAllChannels; - if (no_alpha_test) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - } - - LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - - gGL.getTexUnit(0)->bind(tex, true); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - - gl_rect_2d_simple_tex( width, height ); - - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (no_alpha_test) - { - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - } -// else -// { -// success = false; -// } - } - } - - if( !getInfo()->mStaticImageFileName.empty() ) - { - { - LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - gGL.getTexUnit(0)->bind(tex, true); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - else - { - success = false; - } - } - } - - if(((-1 == getInfo()->mLocalTexture) || - getInfo()->mUseLocalTextureAlphaOnly) && - getInfo()->mStaticImageFileName.empty() && - color_specified ) - { - gAlphaMaskProgram.setMinimumAlpha(0.000f); - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv( net_color.mV ); - gl_rect_2d_simple( width, height ); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - - if( alpha_mask_specified || getInfo()->mWriteAllChannels ) - { - // Restore standard blend func value - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - stop_glerror(); - } - - if( !success ) - { - LL_INFOS() << "LLTexLayer::render() partial: " << getInfo()->mName << LL_ENDL; - } - return success; -} - -const U8* LLTexLayer::getAlphaData() const -{ - LLCRC alpha_mask_crc; - const LLUUID& uuid = getUUID(); - alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - - for (const LLTexLayerParamAlpha* param : mParamAlphaList) - { - // MULTI-WEARABLE: verify visual parameters used here - F32 param_weight = param->getWeight(); - alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); - } - - U32 cache_index = alpha_mask_crc.getCRC(); - - alpha_cache_t::const_iterator iter2 = mAlphaCache.find(cache_index); - return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; -} - -bool LLTexLayer::findNetColor(LLColor4* net_color) const -{ - // Color is either: - // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) - // * a reference to a global color - // * a fixed color with non-zero alpha - // * opaque white (the default) - - if( !mParamColorList.empty() ) - { - if( !getGlobalColor().empty() ) - { - net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getInfo()->mGlobalColor ) ); - } - else if (getInfo()->mFixedColor.mV[VW]) - { - net_color->setVec( getInfo()->mFixedColor ); - } - else - { - net_color->setVec( 0.f, 0.f, 0.f, 0.f ); - } - - calculateTexLayerColor(mParamColorList, *net_color); - return true; - } - - if( !getGlobalColor().empty() ) - { - net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getGlobalColor() ) ); - return true; - } - - if( getInfo()->mFixedColor.mV[VW] ) - { - net_color->setVec( getInfo()->mFixedColor ); - return true; - } - - net_color->setToWhite(); - - return false; // No need to draw a separate colored polygon -} - -bool LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) -{ - bool success = true; - - gGL.flush(); - - if( !getInfo()->mStaticImageFileName.empty() ) - { - LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); - if( tex ) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - gGL.getTexUnit(0)->bind(tex, true); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - else - { - success = false; - } - } - else - { - if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) - { - LLGLTexture* tex = mLocalTextureObject->getImage(); - if (tex) - { - gAlphaMaskProgram.setMinimumAlpha(0.f); - gGL.getTexUnit(0)->bind(tex); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gAlphaMaskProgram.setMinimumAlpha(0.004f); - } - } - } - - return success; -} - -/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) -{ - addAlphaMask(data, originX, originY, width, height, bound_target); -} - -void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render) -{ - if (!force_render && !hasMorph()) - { - LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; - return; - } - LL_PROFILE_ZONE_SCOPED; - bool success = true; - - llassert( !mParamAlphaList.empty() ); - - gAlphaMaskProgram.setMinimumAlpha(0.f); - gGL.setColorMask(false, true); - - LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin(); - // Note: if the first param is a mulitply, multiply against the current buffer's alpha - if( !first_param || !first_param->getMultiplyBlend() ) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // Clear the alpha - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - - gGL.color4f( 0.f, 0.f, 0.f, 0.f ); - gl_rect_2d_simple( width, height ); - } - - // Accumulate alphas - gGL.color4f( 1.f, 1.f, 1.f, 1.f ); - for (LLTexLayerParamAlpha* param : mParamAlphaList) - { - success &= param->render( x, y, width, height ); - if (!success && !force_render) - { - LL_DEBUGS() << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL; - return; - } - } - - // Approximates a min() function - gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); - - // Accumulate the alpha component of the texture - if( getInfo()->mLocalTexture != -1 ) - { - LLGLTexture* tex = mLocalTextureObject->getImage(); - if( tex && (tex->getComponents() == 4) ) - { - LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); - - gGL.getTexUnit(0)->bind(tex, true); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - - gl_rect_2d_simple_tex( width, height ); - - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - } - - if( !getInfo()->mStaticImageFileName.empty() && getInfo()->mStaticImageIsMask ) - { - LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - if( (tex->getComponents() == 4) || (tex->getComponents() == 1) ) - { - gGL.getTexUnit(0)->bind(tex, true); - gl_rect_2d_simple_tex( width, height ); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - else - { - LL_WARNS() << "Skipping rendering of " << getInfo()->mStaticImageFileName - << "; expected 1 or 4 components." << LL_ENDL; - } - } - } - - // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. - // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); - if ( !is_approx_equal(layer_color.mV[VW], 1.f) ) - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4fv(layer_color.mV); - gl_rect_2d_simple( width, height ); - } - - gAlphaMaskProgram.setMinimumAlpha(0.004f); - - LLGLSUIDefault gls_ui; - - gGL.setColorMask(true, true); - - if (hasMorph() && success) - { - LLCRC alpha_mask_crc; - const LLUUID& uuid = getUUID(); - alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); - - for (const LLTexLayerParamAlpha* param : mParamAlphaList) - { - F32 param_weight = param->getWeight(); - alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); - } - - U32 cache_index = alpha_mask_crc.getCRC(); - U8* alpha_data = NULL; - // We believe we need to generate morph masks, do not assume that the cached version is accurate. - // We can get bad morph masks during login, on minimize, and occasional gl errors. - // We should only be doing this when we believe something has changed with respect to the user's appearance. - { - LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; - // clear out a slot if we have filled our cache - S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; - while ((S32)mAlphaCache.size() >= max_cache_entries) - { - alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry - alpha_data = iter2->second; - ll_aligned_free_32(alpha_data); - mAlphaCache.erase(iter2); - } - - // GPUs tend to be very uptight about memory alignment as the DMA used to convey - // said data to the card works better when well-aligned so plain old default-aligned heap mem is a no-no - //new U8[width * height]; - size_t bytes_per_pixel = 1; // unsigned byte alpha channel only... - size_t row_size = (width + 3) & ~0x3; // OpenGL 4-byte row align (even for things < 4 bpp...) - size_t pixels = (row_size * height); - size_t mem_size = pixels * bytes_per_pixel; - - alpha_data = (U8*)ll_aligned_malloc_32(mem_size); - - bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels - - if (!skip_readback) - { - if (gGLManager.mIsIntel) - { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO - // returning only the alpha portion without locking up downstream - U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA - - if (bound_target) - { - gGL.getTexUnit(0)->bind(bound_target); - } - else - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0); - } - - glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); - - U8* alpha_cursor = alpha_data; - U8* pixel = temp; - for (int i = 0; i < pixels; i++) - { - *alpha_cursor++ = pixel[3]; - pixel += 4; - } - - gGL.getTexUnit(0)->disable(); - - ll_aligned_free_32(temp); - } - else - { // platforms with working drivers... - // We just want GL_ALPHA, but that isn't supported in OGL core profile 4. - static const size_t TEMP_BYTES_PER_PIXEL = 4; - U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL); - glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data); - for (size_t pixel = 0; pixel < pixels; pixel++) { - alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3]; - } - ll_aligned_free_32(temp_data); - } - } - else - { - ll_aligned_free_32(alpha_data); - alpha_data = nullptr; - } - - mAlphaCache[cache_index] = alpha_data; - } - - getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); - - mMorphMasksValid = true; - getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); - } -} - -void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) -{ - LL_PROFILE_ZONE_SCOPED; - S32 size = width * height; - const U8* alphaData = getAlphaData(); - if (!alphaData && hasAlphaParams()) - { - LLColor4 net_color; - findNetColor( &net_color ); - // TODO: eliminate need for layer morph mask valid flag - invalidateMorphMasks(); - const bool force_render = false; - renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render); - alphaData = getAlphaData(); - } - if (alphaData) - { - for( S32 i = 0; i < size; i++ ) - { - U8 curAlpha = data[i]; - U16 resultAlpha = curAlpha; - resultAlpha *= ( ((U16)alphaData[i]) + 1); - resultAlpha = resultAlpha >> 8; - data[i] = (U8)resultAlpha; - } - } -} - -/*virtual*/ bool LLTexLayer::isInvisibleAlphaMask() const -{ - if (mLocalTextureObject) - { - if (mLocalTextureObject->getID() == IMG_INVISIBLE) - { - return true; - } - } - - return false; -} - -LLUUID LLTexLayer::getUUID() const -{ - LLUUID uuid; - if( getInfo()->mLocalTexture != -1 ) - { - LLGLTexture* tex = mLocalTextureObject->getImage(); - if (tex) - { - uuid = mLocalTextureObject->getID(); - } - } - if( !getInfo()->mStaticImageFileName.empty() ) - { - LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); - if( tex ) - { - uuid = tex->getID(); - } - } - return uuid; -} - - -//----------------------------------------------------------------------------- -// LLTexLayerTemplate -// A single texture layer, consisting of: -// * color, consisting of either -// * one or more color parameters (weighted colors) -// * a reference to a global color -// * a fixed color with non-zero alpha -// * opaque white (the default) -// * (optional) a texture defined by either -// * a GUID -// * a texture entry index (TE) -// * (optional) one or more alpha parameters (weighted alpha textures) -//----------------------------------------------------------------------------- -LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set, LLAvatarAppearance* const appearance) : - LLTexLayerInterface(layer_set), - mAvatarAppearance( appearance ) -{ -} - -LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) : - LLTexLayerInterface(layer), - mAvatarAppearance(layer.getAvatarAppearance()) -{ -} - -LLTexLayerTemplate::~LLTexLayerTemplate() -{ -} - -//----------------------------------------------------------------------------- -// setInfo -//----------------------------------------------------------------------------- - -/*virtual*/ bool LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) -{ - return LLTexLayerInterface::setInfo(info, wearable); -} - -U32 LLTexLayerTemplate::updateWearableCache() const -{ - mWearableCache.clear(); - - LLWearableType::EType wearable_type = getWearableType(); - if (LLWearableType::WT_INVALID == wearable_type) - { - //this isn't a cloneable layer - return 0; - } - U32 num_wearables = getAvatarAppearance()->getWearableData()->getWearableCount(wearable_type); - U32 added = 0; - for (U32 i = 0; i < num_wearables; i++) - { - LLWearable* wearable = getAvatarAppearance()->getWearableData()->getWearable(wearable_type, i); - if (!wearable) - { - continue; - } - mWearableCache.push_back(wearable); - added++; - } - return added; -} -LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const -{ - if (mWearableCache.size() <= i) - { - return NULL; - } - LLWearable *wearable = mWearableCache[i]; - LLLocalTextureObject *lto = NULL; - LLTexLayer *layer = NULL; - if (wearable) - { - lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); - } - if (lto) - { - layer = lto->getTexLayer(getName()); - } - return layer; -} - -/*virtual*/ bool LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) -{ - if(!mInfo) - { - return false ; - } - - bool success = true; - updateWearableCache(); - for (LLWearable* wearable : mWearableCache) - { - LLLocalTextureObject *lto = NULL; - LLTexLayer *layer = NULL; - if (wearable) - { - lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); - } - if (lto) - { - layer = lto->getTexLayer(getName()); - } - if (layer) - { - wearable->writeToAvatar(mAvatarAppearance); - layer->setLTO(lto); - success &= layer->render(x, y, width, height, bound_target); - } - } - - return success; -} - -/*virtual*/ bool LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer -{ - bool success = true; - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - success &= layer->blendAlphaTexture(x,y,width,height); - } - } - return success; -} - -/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) -{ - U32 num_wearables = updateWearableCache(); - U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->addAlphaMask(data, originX, originY, width, height, bound_target); - } -} - -/*virtual*/ void LLTexLayerTemplate::setHasMorph(bool newval) -{ - mHasMorph = newval; - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->setHasMorph(newval); - } - } -} - -/*virtual*/ void LLTexLayerTemplate::deleteCaches() -{ - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - layer->deleteCaches(); - } - } -} - -/*virtual*/ bool LLTexLayerTemplate::isInvisibleAlphaMask() const -{ - U32 num_wearables = updateWearableCache(); - for (U32 i = 0; i < num_wearables; i++) - { - LLTexLayer *layer = getLayer(i); - if (layer) - { - if (layer->isInvisibleAlphaMask()) - { - return true; - } - } - } - - return false; -} - - -//----------------------------------------------------------------------------- -// finds a specific layer based on a passed in name -//----------------------------------------------------------------------------- -LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) -{ - for (LLTexLayerInterface* layer : mLayerList) - { - if (layer->getName() == name) - { - return layer; - } - } - for (LLTexLayerInterface* layer : mMaskLayerList) - { - if (layer->getName() == name) - { - return layer; - } - } - return NULL; -} - -void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable *wearable) -{ - // initialize all texlayers with this texture type for this LTO - for(LLTexLayerInterface* layer : mLayerList) - { - LLTexLayerTemplate* layer_template = (LLTexLayerTemplate*)layer; - if (layer_template->getInfo()->getLocalTexture() == (S32)tex_index) - { - lto->addTexLayer(layer_template, wearable); - } - } - for(LLTexLayerInterface* layer : mMaskLayerList) - { - LLTexLayerTemplate* layer_template = (LLTexLayerTemplate*)layer; - if (layer_template->getInfo()->getLocalTexture() == (S32)tex_index) - { - lto->addTexLayer(layer_template, wearable); - } - } -} -//----------------------------------------------------------------------------- -// LLTexLayerStaticImageList -//----------------------------------------------------------------------------- - -LLTexLayerStaticImageList::LLTexLayerStaticImageList() : - mGLBytes(0), - mTGABytes(0), - mImageNames(16384) -{ -} - -LLTexLayerStaticImageList::~LLTexLayerStaticImageList() -{ - deleteCachedImages(); -} - -void LLTexLayerStaticImageList::dumpByteCount() const -{ - LL_INFOS() << "Avatar Static Textures " << - "KB GL:" << (mGLBytes / 1024) << - "KB TGA:" << (mTGABytes / 1024) << "KB" << LL_ENDL; -} - -void LLTexLayerStaticImageList::deleteCachedImages() -{ - if( mGLBytes || mTGABytes ) - { - LL_INFOS() << "Clearing Static Textures " << - "KB GL:" << (mGLBytes / 1024) << - "KB TGA:" << (mTGABytes / 1024) << "KB" << LL_ENDL; - - //mStaticImageLists uses LLPointers, clear() will cause deletion - - mStaticImageListTGA.clear(); - mStaticImageList.clear(); - - mGLBytes = 0; - mTGABytes = 0; - } -} - -// Note: in general, for a given image image we'll call either getImageTga() or getTexture(). -// We call getImageTga() if the image is used as an alpha gradient. -// Otherwise, we call getTexture() - -// Returns an LLImageTGA that contains the encoded data from a tga file named file_name. -// Caches the result to speed identical subsequent requests. -LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) -{ - LL_PROFILE_ZONE_SCOPED; - const char *namekey = mImageNames.addString(file_name); - image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); - if( iter != mStaticImageListTGA.end() ) - { - return iter->second; - } - else - { - std::string path; - path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); - LLPointer image_tga = new LLImageTGA( path ); - if( image_tga->getDataSize() > 0 ) - { - mStaticImageListTGA[ namekey ] = image_tga; - mTGABytes += image_tga->getDataSize(); - return image_tga; - } - else - { - return NULL; - } - } -} - -// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. -// Caches the result to speed identical subsequent requests. -LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, bool is_mask) -{ - LL_PROFILE_ZONE_SCOPED; - LLPointer tex; - const char *namekey = mImageNames.addString(file_name); - - texture_map_t::const_iterator iter = mStaticImageList.find(namekey); - if( iter != mStaticImageList.end() ) - { - tex = iter->second; - } - else - { - llassert(gTextureManagerBridgep); - tex = gTextureManagerBridgep->getLocalTexture( false ); - LLPointer image_raw = new LLImageRaw; - if( loadImageRaw( file_name, image_raw ) ) - { - if( (image_raw->getComponents() == 1) && is_mask ) - { - // Convert grayscale alpha masks from single channel into RGBA. - // Fill RGB with black to allow fixed function gl calls - // to match shader implementation. - LLPointer alpha_image_raw = image_raw; - image_raw = new LLImageRaw(image_raw->getWidth(), - image_raw->getHeight(), - 4); - - image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); - } - tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL); - - gGL.getTexUnit(0)->bind(tex); - tex->setAddressMode(LLTexUnit::TAM_CLAMP); - - mStaticImageList [ namekey ] = tex; - mGLBytes += (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); - } - else - { - tex = NULL; - } - } - - return tex; -} - -// Reads a .tga file, decodes it, and puts the decoded data in image_raw. -// Returns true if successful. -bool LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) -{ - LL_PROFILE_ZONE_SCOPED; - bool success = false; - std::string path; - path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); - LLPointer image_tga = new LLImageTGA( path ); - if( image_tga->getDataSize() > 0 ) - { - // Copy data from tga to raw. - success = image_tga->decode( image_raw ); - } - - return success; -} - +/** + * @file lltexlayer.cpp + * @brief A texture layer. Used for avatars. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lltexlayer.h" + +#include "llavatarappearance.h" +#include "llcrc.h" +#include "llimagej2c.h" +#include "llimagetga.h" +#include "lldir.h" +#include "lltexlayerparams.h" +#include "lltexturemanagerbridge.h" +#include "lllocaltextureobject.h" +#include "../llui/llui.h" +#include "llwearable.h" +#include "llwearabledata.h" +#include "llvertexbuffer.h" +#include "llviewervisualparam.h" +#include "llfasttimer.h" + +//#include "../tools/imdebug/imdebug.h" + +using namespace LLAvatarAppearanceDefines; + +// runway consolidate +extern std::string self_av_string(); + +class LLTexLayerInfo +{ + friend class LLTexLayer; + friend class LLTexLayerTemplate; + friend class LLTexLayerInterface; +public: + LLTexLayerInfo(); + ~LLTexLayerInfo(); + + bool parseXml(LLXmlTreeNode* node); + bool createVisualParams(LLAvatarAppearance *appearance); + bool isUserSettable() { return mLocalTexture != -1; } + S32 getLocalTexture() const { return mLocalTexture; } + bool getOnlyAlpha() const { return mUseLocalTextureAlphaOnly; } + std::string getName() const { return mName; } + +private: + std::string mName; + + bool mWriteAllChannels; // Don't use masking. Just write RGBA into buffer, + LLTexLayerInterface::ERenderPass mRenderPass; + + std::string mGlobalColor; + LLColor4 mFixedColor; + + S32 mLocalTexture; + std::string mStaticImageFileName; + bool mStaticImageIsMask; + bool mUseLocalTextureAlphaOnly; // Ignore RGB channels from the input texture. Use alpha as a mask + bool mIsVisibilityMask; + + typedef std::vector< std::pair< std::string,bool > > morph_name_list_t; + morph_name_list_t mMorphNameList; + param_color_info_list_t mParamColorInfoList; + param_alpha_info_list_t mParamAlphaInfoList; +}; + +//----------------------------------------------------------------------------- +// LLTexLayerSetBuffer +// The composite image that a LLViewerTexLayerSet writes to. Each LLViewerTexLayerSet has one. +//----------------------------------------------------------------------------- + +LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner) : + mTexLayerSet(owner) +{ +} + +LLTexLayerSetBuffer::~LLTexLayerSetBuffer() +{ +} + +void LLTexLayerSetBuffer::pushProjection() const +{ + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.ortho(0.0f, getCompositeWidth(), 0.0f, getCompositeHeight(), -1.0f, 1.0f); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); +} + +void LLTexLayerSetBuffer::popProjection() const +{ + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); +} + +// virtual +void LLTexLayerSetBuffer::preRenderTexLayerSet() +{ + // Set up an ortho projection + pushProjection(); +} + +// virtual +void LLTexLayerSetBuffer::postRenderTexLayerSet(bool success) +{ + popProjection(); +} + +bool LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target) +{ + // Default color mask for tex layer render + gGL.setColorMask(true, true); + + bool success = true; + + gAlphaMaskProgram.bind(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + + LLVertexBuffer::unbind(); + + // Composite the color data + LLGLSUIDefault gls_ui; + success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), + getCompositeWidth(), getCompositeHeight(), bound_target ); + gGL.flush(); + + midRenderTexLayerSet(success); + + gAlphaMaskProgram.unbind(); + + LLVertexBuffer::unbind(); + + // reset GL state + gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + return success; +} + +//----------------------------------------------------------------------------- +// LLTexLayerSetInfo +// An ordered set of texture layers that get composited into a single texture. +//----------------------------------------------------------------------------- + +LLTexLayerSetInfo::LLTexLayerSetInfo() : + mBodyRegion( "" ), + mWidth( 512 ), + mHeight( 512 ), + mClearAlpha( true ) +{ +} + +LLTexLayerSetInfo::~LLTexLayerSetInfo( ) +{ + std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer()); + mLayerInfoList.clear(); +} + +bool LLTexLayerSetInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "layer_set" ) ); + if( !node->hasName( "layer_set" ) ) + { + return false; + } + + // body_region + static LLStdStringHandle body_region_string = LLXmlTree::addAttributeString("body_region"); + if( !node->getFastAttributeString( body_region_string, mBodyRegion ) ) + { + LL_WARNS() << " is missing body_region attribute" << LL_ENDL; + return false; + } + + // width, height + static LLStdStringHandle width_string = LLXmlTree::addAttributeString("width"); + if( !node->getFastAttributeS32( width_string, mWidth ) ) + { + return false; + } + + static LLStdStringHandle height_string = LLXmlTree::addAttributeString("height"); + if( !node->getFastAttributeS32( height_string, mHeight ) ) + { + return false; + } + + // Optional alpha component to apply after all compositing is complete. + static LLStdStringHandle alpha_tga_file_string = LLXmlTree::addAttributeString("alpha_tga_file"); + node->getFastAttributeString( alpha_tga_file_string, mStaticAlphaFileName ); + + static LLStdStringHandle clear_alpha_string = LLXmlTree::addAttributeString("clear_alpha"); + node->getFastAttributeBOOL( clear_alpha_string, mClearAlpha ); + + // + for (LLXmlTreeNode* child = node->getChildByName( "layer" ); + child; + child = node->getNextNamedChild()) + { + LLTexLayerInfo* info = new LLTexLayerInfo(); + if( !info->parseXml( child )) + { + delete info; + return false; + } + mLayerInfoList.push_back( info ); + } + return true; +} + +// creates visual params without generating layersets or layers +void LLTexLayerSetInfo::createVisualParams(LLAvatarAppearance *appearance) +{ + //layer_info_list_t mLayerInfoList; + for (LLTexLayerInfo* layer_info : mLayerInfoList) + { + layer_info->createVisualParams(appearance); + } +} + +//----------------------------------------------------------------------------- +// LLTexLayerSet +// An ordered set of texture layers that get composited into a single texture. +//----------------------------------------------------------------------------- + +bool LLTexLayerSet::sHasCaches = false; + +LLTexLayerSet::LLTexLayerSet(LLAvatarAppearance* const appearance) : + mAvatarAppearance( appearance ), + mIsVisible( true ), + mBakedTexIndex(LLAvatarAppearanceDefines::BAKED_HEAD), + mInfo( NULL ) +{ +} + +// virtual +LLTexLayerSet::~LLTexLayerSet() +{ + deleteCaches(); + std::for_each(mLayerList.begin(), mLayerList.end(), DeletePointer()); + mLayerList.clear(); + + std::for_each(mMaskLayerList.begin(), mMaskLayerList.end(), DeletePointer()); + mMaskLayerList.clear(); +} + +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- + +bool LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info) +{ + llassert(mInfo == NULL); + mInfo = info; + //mID = info->mID; // No ID + + mLayerList.reserve(info->mLayerInfoList.size()); + for (LLTexLayerInfo* layer_info : info->mLayerInfoList) + { + LLTexLayerInterface *layer = NULL; + if (layer_info->isUserSettable()) + { + layer = new LLTexLayerTemplate( this, getAvatarAppearance() ); + } + else + { + layer = new LLTexLayer(this); + } + // this is the first time this layer (of either type) is being created - make sure you add the parameters to the avatar appearance + if (!layer->setInfo(layer_info, NULL)) + { + mInfo = NULL; + return false; + } + if (!layer->isVisibilityMask()) + { + mLayerList.push_back( layer ); + } + else + { + mMaskLayerList.push_back(layer); + } + } + + requestUpdate(); + + stop_glerror(); + + return true; +} + +#if 0 // obsolete +//----------------------------------------------------------------------------- +// parseData +//----------------------------------------------------------------------------- + +bool LLTexLayerSet::parseData(LLXmlTreeNode* node) +{ + LLTexLayerSetInfo *info = new LLTexLayerSetInfo; + + if (!info->parseXml(node)) + { + delete info; + return false; + } + if (!setInfo(info)) + { + delete info; + return false; + } + return true; +} +#endif + +void LLTexLayerSet::deleteCaches() +{ + for(LLTexLayerInterface* layer : mLayerList) + { + layer->deleteCaches(); + } + for (LLTexLayerInterface* layer : mMaskLayerList) + { + layer->deleteCaches(); + } +} + + +bool LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target ) +{ + bool success = true; + mIsVisible = true; + + if (mMaskLayerList.size() > 0) + { + for (LLTexLayerInterface* layer : mMaskLayerList) + { + if (layer->isInvisibleAlphaMask()) + { + mIsVisible = false; + } + } + } + + LLGLSUIDefault gls_ui; + LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); + gGL.setColorMask(true, true); + + // clear buffer area to ensure we don't pick up UI elements + { + gGL.flush(); + gAlphaMaskProgram.setMinimumAlpha(0.0f); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 1.f ); + + gl_rect_2d_simple( width, height ); + + gGL.flush(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + if (mIsVisible) + { + // composite color layers + for(LLTexLayerInterface* layer : mLayerList) + { + if (layer->getRenderPass() == LLTexLayer::RP_COLOR) + { + gGL.flush(); + success &= layer->render(x, y, width, height, bound_target); + gGL.flush(); + } + } + + renderAlphaMaskTextures(x, y, width, height, bound_target, false); + + stop_glerror(); + } + else + { + gGL.flush(); + + gGL.setSceneBlendType(LLRender::BT_REPLACE); + gAlphaMaskProgram.setMinimumAlpha(0.f); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 0.f ); + + gl_rect_2d_simple( width, height ); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + gGL.flush(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + return success; +} + + +bool LLTexLayerSet::isBodyRegion(const std::string& region) const +{ + return mInfo->mBodyRegion == region; +} + +const std::string LLTexLayerSet::getBodyRegionName() const +{ + return mInfo->mBodyRegion; +} + +void LLTexLayerSet::destroyComposite() +{ + if( mComposite ) + { + mComposite = NULL; + } +} + +LLTexLayerSetBuffer* LLTexLayerSet::getComposite() +{ + if (!mComposite) + { + createComposite(); + } + return mComposite; +} + +const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const +{ + return mComposite; +} + +void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target) +{ + LL_PROFILE_ZONE_SCOPED; + memset(data, 255, width * height); + + for(LLTexLayerInterface* layer : mLayerList) + { + layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target); + } + + // Set alpha back to that of our alpha masks. + renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true); +} + +void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear) +{ + LL_PROFILE_ZONE_SCOPED; + const LLTexLayerSetInfo *info = getInfo(); + + gGL.setColorMask(false, true); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + + // (Optionally) replace alpha with a single component image from a tga file. + if (!info->mStaticAlphaFileName.empty()) + { + gGL.flush(); + { + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(info->mStaticAlphaFileName, true); + if( tex ) + { + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->bind(tex); + gl_rect_2d_simple_tex( width, height ); + } + } + gGL.flush(); + } + else if (forceClear || info->mClearAlpha || (mMaskLayerList.size() > 0)) + { + // Set the alpha channel to one (clean up after previous blending) + gGL.flush(); + gAlphaMaskProgram.setMinimumAlpha(0.f); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f( 0.f, 0.f, 0.f, 1.f ); + + gl_rect_2d_simple( width, height ); + + gGL.flush(); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + // (Optional) Mask out part of the baked texture with alpha masks + // will still have an effect even if mClearAlpha is set or the alpha component was replaced + if (mMaskLayerList.size() > 0) + { + gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); + for (LLTexLayerInterface* layer : mMaskLayerList) + { + gGL.flush(); + layer->blendAlphaTexture(x,y,width, height); + gGL.flush(); + } + + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gGL.setColorMask(true, true); + gGL.setSceneBlendType(LLRender::BT_ALPHA); +} + +void LLTexLayerSet::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components) +{ + mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex); +} + +bool LLTexLayerSet::isMorphValid() const +{ + for(const LLTexLayerInterface* layer : mLayerList) + { + if (layer && !layer->isMorphValid()) + { + return false; + } + } + return true; +} + +void LLTexLayerSet::invalidateMorphMasks() +{ + for(LLTexLayerInterface* layer : mLayerList) + { + if (layer) + { + layer->invalidateMorphMasks(); + } + } +} + + +//----------------------------------------------------------------------------- +// LLTexLayerInfo +//----------------------------------------------------------------------------- +LLTexLayerInfo::LLTexLayerInfo() : + mWriteAllChannels( false ), + mRenderPass(LLTexLayer::RP_COLOR), + mFixedColor( 0.f, 0.f, 0.f, 0.f ), + mLocalTexture( -1 ), + mStaticImageIsMask( false ), + mUseLocalTextureAlphaOnly(false), + mIsVisibilityMask(false) +{ +} + +LLTexLayerInfo::~LLTexLayerInfo( ) +{ + std::for_each(mParamColorInfoList.begin(), mParamColorInfoList.end(), DeletePointer()); + mParamColorInfoList.clear(); + std::for_each(mParamAlphaInfoList.begin(), mParamAlphaInfoList.end(), DeletePointer()); + mParamAlphaInfoList.clear(); +} + +bool LLTexLayerInfo::parseXml(LLXmlTreeNode* node) +{ + llassert( node->hasName( "layer" ) ); + + // name attribute + static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); + if( !node->getFastAttributeString( name_string, mName ) ) + { + return false; + } + + static LLStdStringHandle write_all_channels_string = LLXmlTree::addAttributeString("write_all_channels"); + node->getFastAttributeBOOL( write_all_channels_string, mWriteAllChannels ); + + std::string render_pass_name; + static LLStdStringHandle render_pass_string = LLXmlTree::addAttributeString("render_pass"); + if( node->getFastAttributeString( render_pass_string, render_pass_name ) ) + { + if( render_pass_name == "bump" ) + { + mRenderPass = LLTexLayer::RP_BUMP; + } + } + + // Note: layers can have either a "global_color" attrib, a "fixed_color" attrib, or a child. + // global color attribute (optional) + static LLStdStringHandle global_color_string = LLXmlTree::addAttributeString("global_color"); + node->getFastAttributeString( global_color_string, mGlobalColor ); + + // Visibility mask (optional) + bool is_visibility; + static LLStdStringHandle visibility_mask_string = LLXmlTree::addAttributeString("visibility_mask"); + if (node->getFastAttributeBOOL(visibility_mask_string, is_visibility)) + { + mIsVisibilityMask = is_visibility; + } + + // color attribute (optional) + LLColor4U color4u; + static LLStdStringHandle fixed_color_string = LLXmlTree::addAttributeString("fixed_color"); + if( node->getFastAttributeColor4U( fixed_color_string, color4u ) ) + { + mFixedColor.setVec( color4u ); + } + + // optional sub-element + for (LLXmlTreeNode* texture_node = node->getChildByName( "texture" ); + texture_node; + texture_node = node->getNextNamedChild()) + { + std::string local_texture_name; + static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); + static LLStdStringHandle local_texture_string = LLXmlTree::addAttributeString("local_texture"); + static LLStdStringHandle file_is_mask_string = LLXmlTree::addAttributeString("file_is_mask"); + static LLStdStringHandle local_texture_alpha_only_string = LLXmlTree::addAttributeString("local_texture_alpha_only"); + if( texture_node->getFastAttributeString( tga_file_string, mStaticImageFileName ) ) + { + texture_node->getFastAttributeBOOL( file_is_mask_string, mStaticImageIsMask ); + } + else if (texture_node->getFastAttributeString(local_texture_string, local_texture_name)) + { + texture_node->getFastAttributeBOOL( local_texture_alpha_only_string, mUseLocalTextureAlphaOnly ); + + /* if ("upper_shirt" == local_texture_name) + mLocalTexture = TEX_UPPER_SHIRT; */ + mLocalTexture = TEX_NUM_INDICES; + for (const LLAvatarAppearanceDictionary::Textures::value_type& dict_pair : LLAvatarAppearance::getDictionary()->getTextures()) + { + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = dict_pair.second; + if (local_texture_name == texture_dict->mName) + { + mLocalTexture = dict_pair.first; + break; + } + } + if (mLocalTexture == TEX_NUM_INDICES) + { + LL_WARNS() << " element has invalid local_texture attribute: " << mName << " " << local_texture_name << LL_ENDL; + return false; + } + } + else + { + LL_WARNS() << " element is missing a required attribute. " << mName << LL_ENDL; + return false; + } + } + + for (LLXmlTreeNode* maskNode = node->getChildByName( "morph_mask" ); + maskNode; + maskNode = node->getNextNamedChild()) + { + std::string morph_name; + static LLStdStringHandle morph_name_string = LLXmlTree::addAttributeString("morph_name"); + if (maskNode->getFastAttributeString(morph_name_string, morph_name)) + { + bool invert = false; + static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert"); + maskNode->getFastAttributeBOOL(invert_string, invert); + mMorphNameList.push_back(std::pair(morph_name,invert)); + } + } + + // optional sub-element (color or alpha params) + for (LLXmlTreeNode* child = node->getChildByName( "param" ); + child; + child = node->getNextNamedChild()) + { + if( child->getChildByName( "param_color" ) ) + { + // + LLTexLayerParamColorInfo* info = new LLTexLayerParamColorInfo(); + if (!info->parseXml(child)) + { + delete info; + return false; + } + mParamColorInfoList.push_back(info); + } + else if( child->getChildByName( "param_alpha" ) ) + { + // + LLTexLayerParamAlphaInfo* info = new LLTexLayerParamAlphaInfo( ); + if (!info->parseXml(child)) + { + delete info; + return false; + } + mParamAlphaInfoList.push_back(info); + } + } + + return true; +} + +bool LLTexLayerInfo::createVisualParams(LLAvatarAppearance *appearance) +{ + bool success = true; + for (LLTexLayerParamColorInfo* color_info : mParamColorInfoList) + { + LLTexLayerParamColor* param_color = new LLTexLayerParamColor(appearance); + if (!param_color->setInfo(color_info, true)) + { + LL_WARNS() << "NULL TexLayer Color Param could not be added to visual param list. Deleting." << LL_ENDL; + delete param_color; + success = false; + } + } + + for (LLTexLayerParamAlphaInfo* alpha_info : mParamAlphaInfoList) + { + LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(appearance); + if (!param_alpha->setInfo(alpha_info, true)) + { + LL_WARNS() << "NULL TexLayer Alpha Param could not be added to visual param list. Deleting." << LL_ENDL; + delete param_alpha; + success = false; + } + } + + return success; +} + +LLTexLayerInterface::LLTexLayerInterface(LLTexLayerSet* const layer_set): + mTexLayerSet( layer_set ), + mMorphMasksValid( false ), + mInfo(NULL), + mHasMorph(false) +{ +} + +LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable): + mTexLayerSet( layer.mTexLayerSet ), + mInfo(NULL) +{ + // don't add visual params for cloned layers + setInfo(layer.getInfo(), wearable); + + mHasMorph = layer.mHasMorph; +} + +bool LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions +{ + // setInfo should only be called once. Code is not robust enough to handle redefinition of a texlayer. + // Not a critical warning, but could be useful for debugging later issues. -Nyx + if (mInfo != NULL) + { + LL_WARNS() << "mInfo != NULL" << LL_ENDL; + } + mInfo = info; + //mID = info->mID; // No ID + + mParamColorList.reserve(mInfo->mParamColorInfoList.size()); + for (LLTexLayerParamColorInfo* color_info : mInfo->mParamColorInfoList) + { + LLTexLayerParamColor* param_color; + if (!wearable) + { + param_color = new LLTexLayerParamColor(this); + if (!param_color->setInfo(color_info, true)) + { + mInfo = NULL; + return false; + } + } + else + { + param_color = (LLTexLayerParamColor*)wearable->getVisualParam(color_info->getID()); + if (!param_color) + { + mInfo = NULL; + return false; + } + } + mParamColorList.push_back( param_color ); + } + + mParamAlphaList.reserve(mInfo->mParamAlphaInfoList.size()); + for (LLTexLayerParamAlphaInfo* alpha_info : mInfo->mParamAlphaInfoList) + { + LLTexLayerParamAlpha* param_alpha; + if (!wearable) + { + param_alpha = new LLTexLayerParamAlpha( this ); + if (!param_alpha->setInfo(alpha_info, true)) + { + mInfo = NULL; + return false; + } + } + else + { + param_alpha = (LLTexLayerParamAlpha*) wearable->getVisualParam(alpha_info->getID()); + if (!param_alpha) + { + mInfo = NULL; + return false; + } + } + mParamAlphaList.push_back( param_alpha ); + } + + return true; +} + +/*virtual*/ void LLTexLayerInterface::requestUpdate() +{ + mTexLayerSet->requestUpdate(); +} + +const std::string& LLTexLayerInterface::getName() const +{ + return mInfo->mName; +} + +ETextureIndex LLTexLayerInterface::getLocalTextureIndex() const +{ + return (ETextureIndex) mInfo->mLocalTexture; +} + +LLWearableType::EType LLTexLayerInterface::getWearableType() const +{ + ETextureIndex te = getLocalTextureIndex(); + if (TEX_INVALID == te) + { + LLWearableType::EType type = LLWearableType::WT_INVALID; + + for (LLTexLayerParamColor* param : mParamColorList) + { + if (param) + { + LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType(); + if (new_type != LLWearableType::WT_INVALID && new_type != type) + { + if (type != LLWearableType::WT_INVALID) + { + return LLWearableType::WT_INVALID; + } + type = new_type; + } + } + } + + for (LLTexLayerParamAlpha* param : mParamAlphaList) + { + if (param) + { + LLWearableType::EType new_type = (LLWearableType::EType)param->getWearableType(); + if (new_type != LLWearableType::WT_INVALID && new_type != type) + { + if (type != LLWearableType::WT_INVALID) + { + return LLWearableType::WT_INVALID; + } + type = new_type; + } + } + } + + return type; + } + return LLAvatarAppearance::getDictionary()->getTEWearableType(te); +} + +LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const +{ + return mInfo->mRenderPass; +} + +const std::string& LLTexLayerInterface::getGlobalColor() const +{ + return mInfo->mGlobalColor; +} + +bool LLTexLayerInterface::isVisibilityMask() const +{ + return mInfo->mIsVisibilityMask; +} + +void LLTexLayerInterface::invalidateMorphMasks() +{ + mMorphMasksValid = false; +} + +LLViewerVisualParam* LLTexLayerInterface::getVisualParamPtr(S32 index) const +{ + LLViewerVisualParam *result = NULL; + for (LLTexLayerParamColor* param : mParamColorList) + { + if (param->getID() == index) + { + result = param; + } + } + for (LLTexLayerParamAlpha* param : mParamAlphaList) + { + if (param->getID() == index) + { + result = param; + } + } + + return result; +} + +//----------------------------------------------------------------------------- +// LLTexLayer +// A single texture layer, consisting of: +// * color, consisting of either +// * one or more color parameters (weighted colors) +// * a reference to a global color +// * a fixed color with non-zero alpha +// * opaque white (the default) +// * (optional) a texture defined by either +// * a GUID +// * a texture entry index (TE) +// * (optional) one or more alpha parameters (weighted alpha textures) +//----------------------------------------------------------------------------- +LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) : + LLTexLayerInterface( layer_set ), + mLocalTextureObject(NULL) +{ +} + +LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) : + LLTexLayerInterface( layer, wearable ), + mLocalTextureObject(NULL) +{ +} + +LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) : + LLTexLayerInterface( layer_template, wearable ), + mLocalTextureObject(lto) +{ +} + +LLTexLayer::~LLTexLayer() +{ + // mParamAlphaList and mParamColorList are LLViewerVisualParam's and get + // deleted with ~LLCharacter() + //std::for_each(mParamAlphaList.begin(), mParamAlphaList.end(), DeletePointer()); + //std::for_each(mParamColorList.begin(), mParamColorList.end(), DeletePointer()); + + for (alpha_cache_t::value_type& alpha_pair : mAlphaCache) + { + U8* alpha_data = alpha_pair.second; + ll_aligned_free_32(alpha_data); + } + +} + +void LLTexLayer::asLLSD(LLSD& sd) const +{ + // *TODO: Finish + sd["id"] = getUUID(); +} + +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- + +bool LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +{ + return LLTexLayerInterface::setInfo(info, wearable); +} + +//static +void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color) +{ + for (const LLTexLayerParamColor* param : param_list) + { + LLColor4 param_net = param->getNetColor(); + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)param->getInfo(); + switch(info->getOperation()) + { + case LLTexLayerParamColor::OP_ADD: + net_color += param_net; + break; + case LLTexLayerParamColor::OP_MULTIPLY: + net_color = net_color * param_net; + break; + case LLTexLayerParamColor::OP_BLEND: + net_color = lerp(net_color, param_net, param->getWeight()); + break; + default: + llassert(0); + break; + } + } + net_color.clamp(); +} + +/*virtual*/ void LLTexLayer::deleteCaches() +{ + // Only need to delete caches for alpha params. Color params don't hold extra memory + for (LLTexLayerParamAlpha* param : mParamAlphaList) + { + param->deleteCaches(); + } +} + +bool LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) +{ + // *TODO: Is this correct? + //gPipeline.disableLights(); + stop_glerror(); + + LLColor4 net_color; + bool color_specified = findNetColor(&net_color); + + if (mTexLayerSet->getAvatarAppearance()->mIsDummy) + { + color_specified = true; + net_color = LLAvatarAppearance::getDummyColor(); + } + + bool success = true; + + // If you can't see the layer, don't render it. + if( is_approx_zero( net_color.mV[VW] ) ) + { + return success; + } + + bool alpha_mask_specified = false; + param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); + if( iter != mParamAlphaList.end() ) + { + // If we have alpha masks, but we're skipping all of them, skip the whole layer. + // However, we can't do this optimization if we have morph masks that need updating. +/* if (!mHasMorph) + { + bool skip_layer = true; + + while( iter != mParamAlphaList.end() ) + { + const LLTexLayerParamAlpha* param = *iter; + + if( !param->getSkip() ) + { + skip_layer = false; + break; + } + + iter++; + } + + if( skip_layer ) + { + return success; + } + }//*/ + + const bool force_render = true; + renderMorphMasks(x, y, width, height, net_color, bound_target, force_render); + alpha_mask_specified = true; + gGL.flush(); + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA); + } + + gGL.color4fv( net_color.mV); + + if( getInfo()->mWriteAllChannels ) + { + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + } + + if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) + { + { + LLGLTexture* tex = NULL; + if (mLocalTextureObject && mLocalTextureObject->getImage()) + { + tex = mLocalTextureObject->getImage(); + if (mLocalTextureObject->getID() == IMG_DEFAULT_AVATAR) + { + tex = NULL; + } + } + else + { + LL_INFOS() << "lto not defined or image not defined: " << getInfo()->getLocalTexture() << " lto: " << mLocalTextureObject << LL_ENDL; + } +// if( mTexLayerSet->getAvatarAppearance()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &image_gl ) ) + { + if( tex ) + { + bool no_alpha_test = getInfo()->mWriteAllChannels; + if (no_alpha_test) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + } + + LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); + + gGL.getTexUnit(0)->bind(tex, true); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + gl_rect_2d_simple_tex( width, height ); + + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + if (no_alpha_test) + { + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + } +// else +// { +// success = false; +// } + } + } + + if( !getInfo()->mStaticImageFileName.empty() ) + { + { + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + gGL.getTexUnit(0)->bind(tex, true); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else + { + success = false; + } + } + } + + if(((-1 == getInfo()->mLocalTexture) || + getInfo()->mUseLocalTextureAlphaOnly) && + getInfo()->mStaticImageFileName.empty() && + color_specified ) + { + gAlphaMaskProgram.setMinimumAlpha(0.000f); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4fv( net_color.mV ); + gl_rect_2d_simple( width, height ); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + + if( alpha_mask_specified || getInfo()->mWriteAllChannels ) + { + // Restore standard blend func value + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + stop_glerror(); + } + + if( !success ) + { + LL_INFOS() << "LLTexLayer::render() partial: " << getInfo()->mName << LL_ENDL; + } + return success; +} + +const U8* LLTexLayer::getAlphaData() const +{ + LLCRC alpha_mask_crc; + const LLUUID& uuid = getUUID(); + alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); + + for (const LLTexLayerParamAlpha* param : mParamAlphaList) + { + // MULTI-WEARABLE: verify visual parameters used here + F32 param_weight = param->getWeight(); + alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); + } + + U32 cache_index = alpha_mask_crc.getCRC(); + + alpha_cache_t::const_iterator iter2 = mAlphaCache.find(cache_index); + return (iter2 == mAlphaCache.end()) ? 0 : iter2->second; +} + +bool LLTexLayer::findNetColor(LLColor4* net_color) const +{ + // Color is either: + // * one or more color parameters (weighted colors) (which may make use of a global color or fixed color) + // * a reference to a global color + // * a fixed color with non-zero alpha + // * opaque white (the default) + + if( !mParamColorList.empty() ) + { + if( !getGlobalColor().empty() ) + { + net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getInfo()->mGlobalColor ) ); + } + else if (getInfo()->mFixedColor.mV[VW]) + { + net_color->setVec( getInfo()->mFixedColor ); + } + else + { + net_color->setVec( 0.f, 0.f, 0.f, 0.f ); + } + + calculateTexLayerColor(mParamColorList, *net_color); + return true; + } + + if( !getGlobalColor().empty() ) + { + net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getGlobalColor() ) ); + return true; + } + + if( getInfo()->mFixedColor.mV[VW] ) + { + net_color->setVec( getInfo()->mFixedColor ); + return true; + } + + net_color->setToWhite(); + + return false; // No need to draw a separate colored polygon +} + +bool LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) +{ + bool success = true; + + gGL.flush(); + + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); + if( tex ) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + gGL.getTexUnit(0)->bind(tex, true); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + else + { + success = false; + } + } + else + { + if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES) + { + LLGLTexture* tex = mLocalTextureObject->getImage(); + if (tex) + { + gAlphaMaskProgram.setMinimumAlpha(0.f); + gGL.getTexUnit(0)->bind(tex); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gAlphaMaskProgram.setMinimumAlpha(0.004f); + } + } + } + + return success; +} + +/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) +{ + addAlphaMask(data, originX, originY, width, height, bound_target); +} + +void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render) +{ + if (!force_render && !hasMorph()) + { + LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; + return; + } + LL_PROFILE_ZONE_SCOPED; + bool success = true; + + llassert( !mParamAlphaList.empty() ); + + gAlphaMaskProgram.setMinimumAlpha(0.f); + gGL.setColorMask(false, true); + + LLTexLayerParamAlpha* first_param = *mParamAlphaList.begin(); + // Note: if the first param is a mulitply, multiply against the current buffer's alpha + if( !first_param || !first_param->getMultiplyBlend() ) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + // Clear the alpha + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_REPLACE); + + gGL.color4f( 0.f, 0.f, 0.f, 0.f ); + gl_rect_2d_simple( width, height ); + } + + // Accumulate alphas + gGL.color4f( 1.f, 1.f, 1.f, 1.f ); + for (LLTexLayerParamAlpha* param : mParamAlphaList) + { + success &= param->render( x, y, width, height ); + if (!success && !force_render) + { + LL_DEBUGS() << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL; + return; + } + } + + // Approximates a min() function + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_MULT_ALPHA); + + // Accumulate the alpha component of the texture + if( getInfo()->mLocalTexture != -1 ) + { + LLGLTexture* tex = mLocalTextureObject->getImage(); + if( tex && (tex->getComponents() == 4) ) + { + LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode(); + + gGL.getTexUnit(0)->bind(tex, true); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + gl_rect_2d_simple_tex( width, height ); + + gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + } + + if( !getInfo()->mStaticImageFileName.empty() && getInfo()->mStaticImageIsMask ) + { + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + if( (tex->getComponents() == 4) || (tex->getComponents() == 1) ) + { + gGL.getTexUnit(0)->bind(tex, true); + gl_rect_2d_simple_tex( width, height ); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else + { + LL_WARNS() << "Skipping rendering of " << getInfo()->mStaticImageFileName + << "; expected 1 or 4 components." << LL_ENDL; + } + } + } + + // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. + // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); + if ( !is_approx_equal(layer_color.mV[VW], 1.f) ) + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4fv(layer_color.mV); + gl_rect_2d_simple( width, height ); + } + + gAlphaMaskProgram.setMinimumAlpha(0.004f); + + LLGLSUIDefault gls_ui; + + gGL.setColorMask(true, true); + + if (hasMorph() && success) + { + LLCRC alpha_mask_crc; + const LLUUID& uuid = getUUID(); + alpha_mask_crc.update((U8*)(&uuid.mData), UUID_BYTES); + + for (const LLTexLayerParamAlpha* param : mParamAlphaList) + { + F32 param_weight = param->getWeight(); + alpha_mask_crc.update((U8*)¶m_weight, sizeof(F32)); + } + + U32 cache_index = alpha_mask_crc.getCRC(); + U8* alpha_data = NULL; + // We believe we need to generate morph masks, do not assume that the cached version is accurate. + // We can get bad morph masks during login, on minimize, and occasional gl errors. + // We should only be doing this when we believe something has changed with respect to the user's appearance. + { + LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; + // clear out a slot if we have filled our cache + S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; + while ((S32)mAlphaCache.size() >= max_cache_entries) + { + alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry + alpha_data = iter2->second; + ll_aligned_free_32(alpha_data); + mAlphaCache.erase(iter2); + } + + // GPUs tend to be very uptight about memory alignment as the DMA used to convey + // said data to the card works better when well-aligned so plain old default-aligned heap mem is a no-no + //new U8[width * height]; + size_t bytes_per_pixel = 1; // unsigned byte alpha channel only... + size_t row_size = (width + 3) & ~0x3; // OpenGL 4-byte row align (even for things < 4 bpp...) + size_t pixels = (row_size * height); + size_t mem_size = pixels * bytes_per_pixel; + + alpha_data = (U8*)ll_aligned_malloc_32(mem_size); + + bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels + + if (!skip_readback) + { + if (gGLManager.mIsIntel) + { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO + // returning only the alpha portion without locking up downstream + U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA + + if (bound_target) + { + gGL.getTexUnit(0)->bind(bound_target); + } + else + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0); + } + + glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); + + U8* alpha_cursor = alpha_data; + U8* pixel = temp; + for (int i = 0; i < pixels; i++) + { + *alpha_cursor++ = pixel[3]; + pixel += 4; + } + + gGL.getTexUnit(0)->disable(); + + ll_aligned_free_32(temp); + } + else + { // platforms with working drivers... + // We just want GL_ALPHA, but that isn't supported in OGL core profile 4. + static const size_t TEMP_BYTES_PER_PIXEL = 4; + U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL); + glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data); + for (size_t pixel = 0; pixel < pixels; pixel++) { + alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3]; + } + ll_aligned_free_32(temp_data); + } + } + else + { + ll_aligned_free_32(alpha_data); + alpha_data = nullptr; + } + + mAlphaCache[cache_index] = alpha_data; + } + + getTexLayerSet()->getAvatarAppearance()->dirtyMesh(); + + mMorphMasksValid = true; + getTexLayerSet()->applyMorphMask(alpha_data, width, height, 1); + } +} + +void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) +{ + LL_PROFILE_ZONE_SCOPED; + S32 size = width * height; + const U8* alphaData = getAlphaData(); + if (!alphaData && hasAlphaParams()) + { + LLColor4 net_color; + findNetColor( &net_color ); + // TODO: eliminate need for layer morph mask valid flag + invalidateMorphMasks(); + const bool force_render = false; + renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render); + alphaData = getAlphaData(); + } + if (alphaData) + { + for( S32 i = 0; i < size; i++ ) + { + U8 curAlpha = data[i]; + U16 resultAlpha = curAlpha; + resultAlpha *= ( ((U16)alphaData[i]) + 1); + resultAlpha = resultAlpha >> 8; + data[i] = (U8)resultAlpha; + } + } +} + +/*virtual*/ bool LLTexLayer::isInvisibleAlphaMask() const +{ + if (mLocalTextureObject) + { + if (mLocalTextureObject->getID() == IMG_INVISIBLE) + { + return true; + } + } + + return false; +} + +LLUUID LLTexLayer::getUUID() const +{ + LLUUID uuid; + if( getInfo()->mLocalTexture != -1 ) + { + LLGLTexture* tex = mLocalTextureObject->getImage(); + if (tex) + { + uuid = mLocalTextureObject->getID(); + } + } + if( !getInfo()->mStaticImageFileName.empty() ) + { + LLGLTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask); + if( tex ) + { + uuid = tex->getID(); + } + } + return uuid; +} + + +//----------------------------------------------------------------------------- +// LLTexLayerTemplate +// A single texture layer, consisting of: +// * color, consisting of either +// * one or more color parameters (weighted colors) +// * a reference to a global color +// * a fixed color with non-zero alpha +// * opaque white (the default) +// * (optional) a texture defined by either +// * a GUID +// * a texture entry index (TE) +// * (optional) one or more alpha parameters (weighted alpha textures) +//----------------------------------------------------------------------------- +LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set, LLAvatarAppearance* const appearance) : + LLTexLayerInterface(layer_set), + mAvatarAppearance( appearance ) +{ +} + +LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) : + LLTexLayerInterface(layer), + mAvatarAppearance(layer.getAvatarAppearance()) +{ +} + +LLTexLayerTemplate::~LLTexLayerTemplate() +{ +} + +//----------------------------------------------------------------------------- +// setInfo +//----------------------------------------------------------------------------- + +/*virtual*/ bool LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable ) +{ + return LLTexLayerInterface::setInfo(info, wearable); +} + +U32 LLTexLayerTemplate::updateWearableCache() const +{ + mWearableCache.clear(); + + LLWearableType::EType wearable_type = getWearableType(); + if (LLWearableType::WT_INVALID == wearable_type) + { + //this isn't a cloneable layer + return 0; + } + U32 num_wearables = getAvatarAppearance()->getWearableData()->getWearableCount(wearable_type); + U32 added = 0; + for (U32 i = 0; i < num_wearables; i++) + { + LLWearable* wearable = getAvatarAppearance()->getWearableData()->getWearable(wearable_type, i); + if (!wearable) + { + continue; + } + mWearableCache.push_back(wearable); + added++; + } + return added; +} +LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const +{ + if (mWearableCache.size() <= i) + { + return NULL; + } + LLWearable *wearable = mWearableCache[i]; + LLLocalTextureObject *lto = NULL; + LLTexLayer *layer = NULL; + if (wearable) + { + lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); + } + if (lto) + { + layer = lto->getTexLayer(getName()); + } + return layer; +} + +/*virtual*/ bool LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) +{ + if(!mInfo) + { + return false ; + } + + bool success = true; + updateWearableCache(); + for (LLWearable* wearable : mWearableCache) + { + LLLocalTextureObject *lto = NULL; + LLTexLayer *layer = NULL; + if (wearable) + { + lto = wearable->getLocalTextureObject(mInfo->mLocalTexture); + } + if (lto) + { + layer = lto->getTexLayer(getName()); + } + if (layer) + { + wearable->writeToAvatar(mAvatarAppearance); + layer->setLTO(lto); + success &= layer->render(x, y, width, height, bound_target); + } + } + + return success; +} + +/*virtual*/ bool LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer +{ + bool success = true; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + success &= layer->blendAlphaTexture(x,y,width,height); + } + } + return success; +} + +/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) +{ + U32 num_wearables = updateWearableCache(); + U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->addAlphaMask(data, originX, originY, width, height, bound_target); + } +} + +/*virtual*/ void LLTexLayerTemplate::setHasMorph(bool newval) +{ + mHasMorph = newval; + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->setHasMorph(newval); + } + } +} + +/*virtual*/ void LLTexLayerTemplate::deleteCaches() +{ + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + layer->deleteCaches(); + } + } +} + +/*virtual*/ bool LLTexLayerTemplate::isInvisibleAlphaMask() const +{ + U32 num_wearables = updateWearableCache(); + for (U32 i = 0; i < num_wearables; i++) + { + LLTexLayer *layer = getLayer(i); + if (layer) + { + if (layer->isInvisibleAlphaMask()) + { + return true; + } + } + } + + return false; +} + + +//----------------------------------------------------------------------------- +// finds a specific layer based on a passed in name +//----------------------------------------------------------------------------- +LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name) +{ + for (LLTexLayerInterface* layer : mLayerList) + { + if (layer->getName() == name) + { + return layer; + } + } + for (LLTexLayerInterface* layer : mMaskLayerList) + { + if (layer->getName() == name) + { + return layer; + } + } + return NULL; +} + +void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable *wearable) +{ + // initialize all texlayers with this texture type for this LTO + for(LLTexLayerInterface* layer : mLayerList) + { + LLTexLayerTemplate* layer_template = (LLTexLayerTemplate*)layer; + if (layer_template->getInfo()->getLocalTexture() == (S32)tex_index) + { + lto->addTexLayer(layer_template, wearable); + } + } + for(LLTexLayerInterface* layer : mMaskLayerList) + { + LLTexLayerTemplate* layer_template = (LLTexLayerTemplate*)layer; + if (layer_template->getInfo()->getLocalTexture() == (S32)tex_index) + { + lto->addTexLayer(layer_template, wearable); + } + } +} +//----------------------------------------------------------------------------- +// LLTexLayerStaticImageList +//----------------------------------------------------------------------------- + +LLTexLayerStaticImageList::LLTexLayerStaticImageList() : + mGLBytes(0), + mTGABytes(0), + mImageNames(16384) +{ +} + +LLTexLayerStaticImageList::~LLTexLayerStaticImageList() +{ + deleteCachedImages(); +} + +void LLTexLayerStaticImageList::dumpByteCount() const +{ + LL_INFOS() << "Avatar Static Textures " << + "KB GL:" << (mGLBytes / 1024) << + "KB TGA:" << (mTGABytes / 1024) << "KB" << LL_ENDL; +} + +void LLTexLayerStaticImageList::deleteCachedImages() +{ + if( mGLBytes || mTGABytes ) + { + LL_INFOS() << "Clearing Static Textures " << + "KB GL:" << (mGLBytes / 1024) << + "KB TGA:" << (mTGABytes / 1024) << "KB" << LL_ENDL; + + //mStaticImageLists uses LLPointers, clear() will cause deletion + + mStaticImageListTGA.clear(); + mStaticImageList.clear(); + + mGLBytes = 0; + mTGABytes = 0; + } +} + +// Note: in general, for a given image image we'll call either getImageTga() or getTexture(). +// We call getImageTga() if the image is used as an alpha gradient. +// Otherwise, we call getTexture() + +// Returns an LLImageTGA that contains the encoded data from a tga file named file_name. +// Caches the result to speed identical subsequent requests. +LLImageTGA* LLTexLayerStaticImageList::getImageTGA(const std::string& file_name) +{ + LL_PROFILE_ZONE_SCOPED; + const char *namekey = mImageNames.addString(file_name); + image_tga_map_t::const_iterator iter = mStaticImageListTGA.find(namekey); + if( iter != mStaticImageListTGA.end() ) + { + return iter->second; + } + else + { + std::string path; + path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); + LLPointer image_tga = new LLImageTGA( path ); + if( image_tga->getDataSize() > 0 ) + { + mStaticImageListTGA[ namekey ] = image_tga; + mTGABytes += image_tga->getDataSize(); + return image_tga; + } + else + { + return NULL; + } + } +} + +// Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. +// Caches the result to speed identical subsequent requests. +LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, bool is_mask) +{ + LL_PROFILE_ZONE_SCOPED; + LLPointer tex; + const char *namekey = mImageNames.addString(file_name); + + texture_map_t::const_iterator iter = mStaticImageList.find(namekey); + if( iter != mStaticImageList.end() ) + { + tex = iter->second; + } + else + { + llassert(gTextureManagerBridgep); + tex = gTextureManagerBridgep->getLocalTexture( false ); + LLPointer image_raw = new LLImageRaw; + if( loadImageRaw( file_name, image_raw ) ) + { + if( (image_raw->getComponents() == 1) && is_mask ) + { + // Convert grayscale alpha masks from single channel into RGBA. + // Fill RGB with black to allow fixed function gl calls + // to match shader implementation. + LLPointer alpha_image_raw = image_raw; + image_raw = new LLImageRaw(image_raw->getWidth(), + image_raw->getHeight(), + 4); + + image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); + } + tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL); + + gGL.getTexUnit(0)->bind(tex); + tex->setAddressMode(LLTexUnit::TAM_CLAMP); + + mStaticImageList [ namekey ] = tex; + mGLBytes += (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); + } + else + { + tex = NULL; + } + } + + return tex; +} + +// Reads a .tga file, decodes it, and puts the decoded data in image_raw. +// Returns true if successful. +bool LLTexLayerStaticImageList::loadImageRaw(const std::string& file_name, LLImageRaw* image_raw) +{ + LL_PROFILE_ZONE_SCOPED; + bool success = false; + std::string path; + path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,file_name); + LLPointer image_tga = new LLImageTGA( path ); + if( image_tga->getDataSize() > 0 ) + { + // Copy data from tga to raw. + success = image_tga->decode( image_raw ); + } + + return success; +} + diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index ea43135310..876ea6f600 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -1,313 +1,313 @@ -/** - * @file lltexlayer.h - * @brief Texture layer classes. Used for avatars. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTEXLAYER_H -#define LL_LLTEXLAYER_H - -#include -#include "llglslshader.h" -#include "llgltexture.h" -#include "llavatarappearancedefines.h" -#include "lltexlayerparams.h" - -class LLAvatarAppearance; -class LLImageTGA; -class LLImageRaw; -class LLLocalTextureObject; -class LLXmlTreeNode; -class LLTexLayerSet; -class LLTexLayerSetInfo; -class LLTexLayerInfo; -class LLTexLayerSetBuffer; -class LLWearable; -class LLViewerVisualParam; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerInterface -// -// Interface class to generalize functionality shared by LLTexLayer -// and LLTexLayerTemplate. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerInterface -{ -public: - enum ERenderPass - { - RP_COLOR, - RP_BUMP, - RP_SHINE - }; - - LLTexLayerInterface(LLTexLayerSet* const layer_set); - LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); - virtual ~LLTexLayerInterface() {} - - virtual bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; - virtual void deleteCaches() = 0; - virtual bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; - virtual bool isInvisibleAlphaMask() const = 0; - - const LLTexLayerInfo* getInfo() const { return mInfo; } - virtual bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions - LLWearableType::EType getWearableType() const; - LLAvatarAppearanceDefines::ETextureIndex getLocalTextureIndex() const; - - const std::string& getName() const; - const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } - LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; } - - void invalidateMorphMasks(); - virtual void setHasMorph(bool newval) { mHasMorph = newval; } - bool hasMorph() const { return mHasMorph; } - bool isMorphValid() const { return mMorphMasksValid; } - - void requestUpdate(); - virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0; - bool hasAlphaParams() const { return !mParamAlphaList.empty(); } - - ERenderPass getRenderPass() const; - bool isVisibilityMask() const; - - virtual void asLLSD(LLSD& sd) const {} - -protected: - const std::string& getGlobalColor() const; - LLViewerVisualParam* getVisualParamPtr(S32 index) const; - -protected: - LLTexLayerSet* const mTexLayerSet; - const LLTexLayerInfo* mInfo; - bool mMorphMasksValid; - bool mHasMorph; - - // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. - param_color_list_t mParamColorList; - param_alpha_list_t mParamAlphaList; - // mGlobalColor name stored in mInfo - // mFixedColor value stored in mInfo -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerTemplate -// -// Only exists for llvoavatarself. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerTemplate : public LLTexLayerInterface -{ -public: - LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); - LLTexLayerTemplate(const LLTexLayerTemplate &layer); - /*virtual*/ ~LLTexLayerTemplate(); - /*virtual*/ bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); - /*virtual*/ bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); - /*virtual*/ void setHasMorph(bool newval); - /*virtual*/ void deleteCaches(); - /*virtual*/ bool isInvisibleAlphaMask() const; -protected: - U32 updateWearableCache() const; - LLTexLayer* getLayer(U32 i) const; - LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } -private: - LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. - typedef std::vector wearable_cache_t; - mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayer -// -// A single texture layer. Only exists for llvoavatarself. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayer : public LLTexLayerInterface -{ -public: - LLTexLayer(LLTexLayerSet* const layer_set); - LLTexLayer(const LLTexLayer &layer, LLWearable *wearable); - LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable); - /*virtual*/ ~LLTexLayer(); - - /*virtual*/ bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions - /*virtual*/ bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); - - /*virtual*/ void deleteCaches(); - const U8* getAlphaData() const; - - bool findNetColor(LLColor4* color) const; - /*virtual*/ bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer - /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); - void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render); - void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); - /*virtual*/ bool isInvisibleAlphaMask() const; - - void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } - LLLocalTextureObject* getLTO() { return mLocalTextureObject; } - - /*virtual*/ void asLLSD(LLSD& sd) const; - - static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color); -protected: - LLUUID getUUID() const; - typedef std::map alpha_cache_t; - alpha_cache_t mAlphaCache; - LLLocalTextureObject* mLocalTextureObject; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSet -// -// An ordered set of texture layers that gets composited into a single texture. -// Only exists for llvoavatarself. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSet -{ - friend class LLTexLayerSetBuffer; -public: - LLTexLayerSet(LLAvatarAppearance* const appearance); - virtual ~LLTexLayerSet(); - - LLTexLayerSetBuffer* getComposite(); - const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. - virtual void createComposite() = 0; - void destroyComposite(); - void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target); - - const LLTexLayerSetInfo* getInfo() const { return mInfo; } - bool setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions - - bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); - void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); - - bool isBodyRegion(const std::string& region) const; - void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components); - bool isMorphValid() const; - virtual void requestUpdate() = 0; - void invalidateMorphMasks(); - void deleteCaches(); - LLTexLayerInterface* findLayerByName(const std::string& name); - void cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable* wearable); - - LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } - const std::string getBodyRegionName() const; - bool hasComposite() const { return (mComposite.notNull()); } - LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() const { return mBakedTexIndex; } - void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } - bool isVisible() const { return mIsVisible; } - - static bool sHasCaches; - -protected: - typedef std::vector layer_list_t; - layer_list_t mLayerList; - layer_list_t mMaskLayerList; - LLPointer mComposite; - LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. - bool mIsVisible; - - LLAvatarAppearanceDefines::EBakedTextureIndex mBakedTexIndex; - const LLTexLayerSetInfo* mInfo; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSetInfo -// -// Contains shared layer set data. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSetInfo -{ - friend class LLTexLayerSet; -public: - LLTexLayerSetInfo(); - ~LLTexLayerSetInfo(); - bool parseXml(LLXmlTreeNode* node); - void createVisualParams(LLAvatarAppearance *appearance); - S32 getWidth() const { return mWidth; } - S32 getHeight() const { return mHeight; } -protected: - std::string mBodyRegion; - S32 mWidth; - S32 mHeight; - std::string mStaticAlphaFileName; - bool mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) - typedef std::vector layer_info_list_t; - layer_info_list_t mLayerInfoList; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerSetBuffer -// -// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerSetBuffer : public virtual LLRefCount -{ - LOG_CLASS(LLTexLayerSetBuffer); - -public: - LLTexLayerSetBuffer(LLTexLayerSet* const owner); - virtual ~LLTexLayerSetBuffer(); - -protected: - void pushProjection() const; - void popProjection() const; - virtual void preRenderTexLayerSet(); - virtual void midRenderTexLayerSet(bool success) {} - virtual void postRenderTexLayerSet(bool success); - virtual S32 getCompositeOriginX() const = 0; - virtual S32 getCompositeOriginY() const = 0; - virtual S32 getCompositeWidth() const = 0; - virtual S32 getCompositeHeight() const = 0; - bool renderTexLayerSet(LLRenderTarget* bound_target); - - LLTexLayerSet* const mTexLayerSet; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerStaticImageList -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerStaticImageList : public LLSingleton -{ - LLSINGLETON(LLTexLayerStaticImageList); - ~LLTexLayerStaticImageList(); -public: - LLGLTexture* getTexture(const std::string& file_name, bool is_mask); - LLImageTGA* getImageTGA(const std::string& file_name); - void deleteCachedImages(); - void dumpByteCount() const; -protected: - bool loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); -private: - LLStringTable mImageNames; - typedef std::map > texture_map_t; - texture_map_t mStaticImageList; - typedef std::map > image_tga_map_t; - image_tga_map_t mStaticImageListTGA; - S32 mGLBytes; - S32 mTGABytes; -}; - -#endif // LL_LLTEXLAYER_H +/** + * @file lltexlayer.h + * @brief Texture layer classes. Used for avatars. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXLAYER_H +#define LL_LLTEXLAYER_H + +#include +#include "llglslshader.h" +#include "llgltexture.h" +#include "llavatarappearancedefines.h" +#include "lltexlayerparams.h" + +class LLAvatarAppearance; +class LLImageTGA; +class LLImageRaw; +class LLLocalTextureObject; +class LLXmlTreeNode; +class LLTexLayerSet; +class LLTexLayerSetInfo; +class LLTexLayerInfo; +class LLTexLayerSetBuffer; +class LLWearable; +class LLViewerVisualParam; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerInterface +// +// Interface class to generalize functionality shared by LLTexLayer +// and LLTexLayerTemplate. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerInterface +{ +public: + enum ERenderPass + { + RP_COLOR, + RP_BUMP, + RP_SHINE + }; + + LLTexLayerInterface(LLTexLayerSet* const layer_set); + LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable); + virtual ~LLTexLayerInterface() {} + + virtual bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0; + virtual void deleteCaches() = 0; + virtual bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0; + virtual bool isInvisibleAlphaMask() const = 0; + + const LLTexLayerInfo* getInfo() const { return mInfo; } + virtual bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // sets mInfo, calls initialization functions + LLWearableType::EType getWearableType() const; + LLAvatarAppearanceDefines::ETextureIndex getLocalTextureIndex() const; + + const std::string& getName() const; + const LLTexLayerSet* const getTexLayerSet() const { return mTexLayerSet; } + LLTexLayerSet* const getTexLayerSet() { return mTexLayerSet; } + + void invalidateMorphMasks(); + virtual void setHasMorph(bool newval) { mHasMorph = newval; } + bool hasMorph() const { return mHasMorph; } + bool isMorphValid() const { return mMorphMasksValid; } + + void requestUpdate(); + virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0; + bool hasAlphaParams() const { return !mParamAlphaList.empty(); } + + ERenderPass getRenderPass() const; + bool isVisibilityMask() const; + + virtual void asLLSD(LLSD& sd) const {} + +protected: + const std::string& getGlobalColor() const; + LLViewerVisualParam* getVisualParamPtr(S32 index) const; + +protected: + LLTexLayerSet* const mTexLayerSet; + const LLTexLayerInfo* mInfo; + bool mMorphMasksValid; + bool mHasMorph; + + // Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order. + param_color_list_t mParamColorList; + param_alpha_list_t mParamAlphaList; + // mGlobalColor name stored in mInfo + // mFixedColor value stored in mInfo +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerTemplate +// +// Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerTemplate : public LLTexLayerInterface +{ +public: + LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance); + LLTexLayerTemplate(const LLTexLayerTemplate &layer); + /*virtual*/ ~LLTexLayerTemplate(); + /*virtual*/ bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions + /*virtual*/ bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ void setHasMorph(bool newval); + /*virtual*/ void deleteCaches(); + /*virtual*/ bool isInvisibleAlphaMask() const; +protected: + U32 updateWearableCache() const; + LLTexLayer* getLayer(U32 i) const; + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } +private: + LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. + typedef std::vector wearable_cache_t; + mutable wearable_cache_t mWearableCache; // mutable b/c most get- require updating this cache +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayer +// +// A single texture layer. Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayer : public LLTexLayerInterface +{ +public: + LLTexLayer(LLTexLayerSet* const layer_set); + LLTexLayer(const LLTexLayer &layer, LLWearable *wearable); + LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable); + /*virtual*/ ~LLTexLayer(); + + /*virtual*/ bool setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions + /*virtual*/ bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target); + + /*virtual*/ void deleteCaches(); + const U8* getAlphaData() const; + + bool findNetColor(LLColor4* color) const; + /*virtual*/ bool blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer + /*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render); + void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target); + /*virtual*/ bool isInvisibleAlphaMask() const; + + void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; } + LLLocalTextureObject* getLTO() { return mLocalTextureObject; } + + /*virtual*/ void asLLSD(LLSD& sd) const; + + static void calculateTexLayerColor(const param_color_list_t ¶m_list, LLColor4 &net_color); +protected: + LLUUID getUUID() const; + typedef std::map alpha_cache_t; + alpha_cache_t mAlphaCache; + LLLocalTextureObject* mLocalTextureObject; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSet +// +// An ordered set of texture layers that gets composited into a single texture. +// Only exists for llvoavatarself. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSet +{ + friend class LLTexLayerSetBuffer; +public: + LLTexLayerSet(LLAvatarAppearance* const appearance); + virtual ~LLTexLayerSet(); + + LLTexLayerSetBuffer* getComposite(); + const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist. + virtual void createComposite() = 0; + void destroyComposite(); + void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target); + + const LLTexLayerSetInfo* getInfo() const { return mInfo; } + bool setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions + + bool render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr); + void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false); + + bool isBodyRegion(const std::string& region) const; + void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components); + bool isMorphValid() const; + virtual void requestUpdate() = 0; + void invalidateMorphMasks(); + void deleteCaches(); + LLTexLayerInterface* findLayerByName(const std::string& name); + void cloneTemplates(LLLocalTextureObject *lto, LLAvatarAppearanceDefines::ETextureIndex tex_index, LLWearable* wearable); + + LLAvatarAppearance* getAvatarAppearance() const { return mAvatarAppearance; } + const std::string getBodyRegionName() const; + bool hasComposite() const { return (mComposite.notNull()); } + LLAvatarAppearanceDefines::EBakedTextureIndex getBakedTexIndex() const { return mBakedTexIndex; } + void setBakedTexIndex(LLAvatarAppearanceDefines::EBakedTextureIndex index) { mBakedTexIndex = index; } + bool isVisible() const { return mIsVisible; } + + static bool sHasCaches; + +protected: + typedef std::vector layer_list_t; + layer_list_t mLayerList; + layer_list_t mMaskLayerList; + LLPointer mComposite; + LLAvatarAppearance* const mAvatarAppearance; // note: backlink only; don't make this an LLPointer. + bool mIsVisible; + + LLAvatarAppearanceDefines::EBakedTextureIndex mBakedTexIndex; + const LLTexLayerSetInfo* mInfo; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSetInfo +// +// Contains shared layer set data. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSetInfo +{ + friend class LLTexLayerSet; +public: + LLTexLayerSetInfo(); + ~LLTexLayerSetInfo(); + bool parseXml(LLXmlTreeNode* node); + void createVisualParams(LLAvatarAppearance *appearance); + S32 getWidth() const { return mWidth; } + S32 getHeight() const { return mHeight; } +protected: + std::string mBodyRegion; + S32 mWidth; + S32 mHeight; + std::string mStaticAlphaFileName; + bool mClearAlpha; // Set alpha to 1 for this layerset (if there is no mStaticAlphaFileName) + typedef std::vector layer_info_list_t; + layer_info_list_t mLayerInfoList; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerSetBuffer +// +// The composite image that a LLTexLayerSet writes to. Each LLTexLayerSet has one. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerSetBuffer : public virtual LLRefCount +{ + LOG_CLASS(LLTexLayerSetBuffer); + +public: + LLTexLayerSetBuffer(LLTexLayerSet* const owner); + virtual ~LLTexLayerSetBuffer(); + +protected: + void pushProjection() const; + void popProjection() const; + virtual void preRenderTexLayerSet(); + virtual void midRenderTexLayerSet(bool success) {} + virtual void postRenderTexLayerSet(bool success); + virtual S32 getCompositeOriginX() const = 0; + virtual S32 getCompositeOriginY() const = 0; + virtual S32 getCompositeWidth() const = 0; + virtual S32 getCompositeHeight() const = 0; + bool renderTexLayerSet(LLRenderTarget* bound_target); + + LLTexLayerSet* const mTexLayerSet; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerStaticImageList +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerStaticImageList : public LLSingleton +{ + LLSINGLETON(LLTexLayerStaticImageList); + ~LLTexLayerStaticImageList(); +public: + LLGLTexture* getTexture(const std::string& file_name, bool is_mask); + LLImageTGA* getImageTGA(const std::string& file_name); + void deleteCachedImages(); + void dumpByteCount() const; +protected: + bool loadImageRaw(const std::string& file_name, LLImageRaw* image_raw); +private: + LLStringTable mImageNames; + typedef std::map > texture_map_t; + texture_map_t mStaticImageList; + typedef std::map > image_tga_map_t; + image_tga_map_t mStaticImageListTGA; + S32 mGLBytes; + S32 mTGABytes; +}; + +#endif // LL_LLTEXLAYER_H diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index b55df16185..7beffbcd19 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -1,594 +1,594 @@ -/** - * @file lltexlayerparams.cpp - * @brief Texture layer parameters - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "lltexlayerparams.h" - -#include "llavatarappearance.h" -#include "llimagetga.h" -#include "llquantize.h" -#include "lltexlayer.h" -#include "lltexturemanagerbridge.h" -#include "../llui/llui.h" -#include "llwearable.h" -#include "llfasttimer.h" - -//----------------------------------------------------------------------------- -// LLTexLayerParam -//----------------------------------------------------------------------------- -LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) - : LLViewerVisualParam(), - mTexLayer(layer), - mAvatarAppearance(NULL) -{ - if (mTexLayer != NULL) - { - mAvatarAppearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); - } - else - { - LL_ERRS() << "LLTexLayerParam constructor passed with NULL reference for layer!" << LL_ENDL; - } -} - -LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) - : LLViewerVisualParam(), - mTexLayer(NULL), - mAvatarAppearance(appearance) -{ -} - -LLTexLayerParam::LLTexLayerParam(const LLTexLayerParam& pOther) - : LLViewerVisualParam(pOther), - mTexLayer(pOther.mTexLayer), - mAvatarAppearance(pOther.mAvatarAppearance) -{ -} - -bool LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, bool add_to_appearance) -{ - LLViewerVisualParam::setInfo(info); - - if (add_to_appearance) - { - mAvatarAppearance->addVisualParam( this); - this->setParamLocation(mAvatarAppearance->isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); - } - - return true; -} - - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlpha -//----------------------------------------------------------------------------- - -// static -LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; - -// static -void LLTexLayerParamAlpha::dumpCacheByteCount() -{ - S32 gl_bytes = 0; - getCacheByteCount( &gl_bytes); - LL_INFOS() << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << LL_ENDL; -} - -// static -void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) -{ - *gl_bytes = 0; - - for (LLTexLayerParamAlpha* instance : sInstances) - { - LLGLTexture* tex = instance->mCachedProcessedTexture; - if (tex) - { - S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); - - if (tex->hasGLTexture()) - { - *gl_bytes += bytes; - } - } - } -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) - : LLTexLayerParam(layer), - mCachedProcessedTexture(NULL), - mStaticImageTGA(), - mStaticImageRaw(), - mNeedsCreateTexture(false), - mStaticImageInvalid(false), - mAvgDistortionVec(1.f, 1.f, 1.f), - mCachedEffectiveWeight(0.f) -{ - sInstances.push_front(this); -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) - : LLTexLayerParam(appearance), - mCachedProcessedTexture(NULL), - mStaticImageTGA(), - mStaticImageRaw(), - mNeedsCreateTexture(false), - mStaticImageInvalid(false), - mAvgDistortionVec(1.f, 1.f, 1.f), - mCachedEffectiveWeight(0.f) -{ - sInstances.push_front(this); -} - -LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther) - : LLTexLayerParam(pOther), - mCachedProcessedTexture(pOther.mCachedProcessedTexture), - mStaticImageTGA(pOther.mStaticImageTGA), - mStaticImageRaw(pOther.mStaticImageRaw), - mNeedsCreateTexture(pOther.mNeedsCreateTexture.load()), - mStaticImageInvalid(pOther.mStaticImageInvalid), - mAvgDistortionVec(pOther.mAvgDistortionVec), - mCachedEffectiveWeight(pOther.mCachedEffectiveWeight) -{ - sInstances.push_front(this); -} - -LLTexLayerParamAlpha::~LLTexLayerParamAlpha() -{ - deleteCaches(); - sInstances.remove(this); -} - -/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const -{ - return new LLTexLayerParamAlpha(*this); -} - -void LLTexLayerParamAlpha::deleteCaches() -{ - mStaticImageTGA = NULL; // deletes image - mCachedProcessedTexture = NULL; - mStaticImageRaw = NULL; - mNeedsCreateTexture = false; -} - -bool LLTexLayerParamAlpha::getMultiplyBlend() const -{ - return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; -} - -void LLTexLayerParamAlpha::setWeight(F32 weight) -{ - if (mIsAnimating || mTexLayer == NULL) - { - return; - } - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - F32 new_weight = llclamp(weight, min_weight, max_weight); - U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); - U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); - if (cur_u8 != new_u8) - { - mCurWeight = new_weight; - - if ((mAvatarAppearance->getSex() & getSex()) && - (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. - { - mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet()); - mTexLayer->invalidateMorphMasks(); - } - } -} - -void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value) -{ - // do not animate dummy parameters - if (mIsDummy) - { - setWeight(target_value); - return; - } - - mTargetWeight = target_value; - setWeight(target_value); - mIsAnimating = true; - if (mNext) - { - mNext->setAnimationTarget(target_value); - } -} - -void LLTexLayerParamAlpha::animate(F32 delta) -{ - if (mNext) - { - mNext->animate(delta); - } -} - -bool LLTexLayerParamAlpha::getSkip() const -{ - if (!mTexLayer) - { - return true; - } - - const LLAvatarAppearance *appearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); - - if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight) - { - F32 effective_weight = (appearance->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); - if (is_approx_zero(effective_weight)) - { - return true; - } - } - - LLWearableType::EType type = (LLWearableType::EType)getWearableType(); - if ((type != LLWearableType::WT_INVALID) && !appearance->isWearingWearableType(type)) - { - return true; - } - - return false; -} - - -bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) -{ - LL_PROFILE_ZONE_SCOPED; - bool success = true; - - if (!mTexLayer) - { - return success; - } - - F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatarAppearance()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); - bool weight_changed = effective_weight != mCachedEffectiveWeight; - if (getSkip()) - { - return success; - } - - LLTexLayerParamAlphaInfo *info = (LLTexLayerParamAlphaInfo *)getInfo(); - gGL.flush(); - if (info->mMultiplyBlend) - { - gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function - } - else - { - gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function - } - - if (!info->mStaticImageFileName.empty() && !mStaticImageInvalid) - { - if (mStaticImageTGA.isNull()) - { - // Don't load the image file until we actually need it the first time. Like now. - mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName); - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull(); - - if (mStaticImageTGA.isNull()) - { - LL_WARNS() << "Unable to load static file: " << info->mStaticImageFileName << LL_ENDL; - mStaticImageInvalid = true; // don't try again. - return false; - } - } - - const S32 image_tga_width = mStaticImageTGA->getWidth(); - const S32 image_tga_height = mStaticImageTGA->getHeight(); - if (!mCachedProcessedTexture || - (mCachedProcessedTexture->getWidth() != image_tga_width) || - (mCachedProcessedTexture->getHeight() != image_tga_height) || - (weight_changed)) - { - mCachedEffectiveWeight = effective_weight; - - if (!mCachedProcessedTexture) - { - llassert(gTextureManagerBridgep); - mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, false); - - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mCachedProcessedTexture.notNull(); - - mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - } - - // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed. - mStaticImageRaw = NULL; - mStaticImageRaw = new LLImageRaw; - mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight); - mNeedsCreateTexture = true; - LL_DEBUGS() << "Built Cached Alpha: " << info->mStaticImageFileName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << "Domain: " << info->mDomain << " Weight: " << effective_weight << LL_ENDL; - } - - if (mCachedProcessedTexture) - { - { - // Create the GL texture, and then hang onto it for future use. - if (mNeedsCreateTexture) - { - mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); - mNeedsCreateTexture = false; - gGL.getTexUnit(0)->bind(mCachedProcessedTexture); - mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); - } - - gGL.getTexUnit(0)->bind(mCachedProcessedTexture); - gl_rect_2d_simple_tex(width, height); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - stop_glerror(); - } - } - - // 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 (!mAvatarAppearance->isSelf()) - { - mCachedProcessedTexture = NULL; - } - } - else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f(0.f, 0.f, 0.f, effective_weight); - gl_rect_2d_simple(width, height); - } - - return success; -} - -//----------------------------------------------------------------------------- -// LLTexLayerParamAlphaInfo -//----------------------------------------------------------------------------- -LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() : - mMultiplyBlend(false), - mSkipIfZeroWeight(false), - mDomain(0.f) -{ -} - -bool LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) -{ - llassert(node->hasName("param") && node->getChildByName("param_alpha")); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return false; - - LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha"); - if (!param_alpha_node) - { - return false; - } - - static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); - if (param_alpha_node->getFastAttributeString(tga_file_string, mStaticImageFileName)) - { - // Don't load the image file until it's actually needed. - } -// else -// { -// LL_WARNS() << " element is missing tga_file attribute." << LL_ENDL; -// } - - static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend"); - param_alpha_node->getFastAttributeBOOL(multiply_blend_string, mMultiplyBlend); - - static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero"); - param_alpha_node->getFastAttributeBOOL(skip_if_zero_string, mSkipIfZeroWeight); - - static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); - param_alpha_node->getFastAttributeF32(domain_string, mDomain); - - return true; -} - - - - -LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) - : LLTexLayerParam(layer), - mAvgDistortionVec(1.f, 1.f, 1.f) -{ -} - -LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) - : LLTexLayerParam(appearance), - mAvgDistortionVec(1.f, 1.f, 1.f) -{ -} - -LLTexLayerParamColor::LLTexLayerParamColor(const LLTexLayerParamColor& pOther) - : LLTexLayerParam(pOther), - mAvgDistortionVec(pOther.mAvgDistortionVec) -{ -} - -LLTexLayerParamColor::~LLTexLayerParamColor() -{ -} - -/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const -{ - return new LLTexLayerParamColor(*this); -} - -LLColor4 LLTexLayerParamColor::getNetColor() const -{ - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); - - llassert(info->mNumColors >= 1); - - F32 effective_weight = (mAvatarAppearance && (mAvatarAppearance->getSex() & getSex())) ? mCurWeight : getDefaultWeight(); - - S32 index_last = info->mNumColors - 1; - F32 scaled_weight = effective_weight * index_last; - S32 index_start = (S32) scaled_weight; - S32 index_end = index_start + 1; - if (index_start == index_last) - { - return info->mColors[index_last]; - } - else - { - F32 weight = scaled_weight - index_start; - const LLColor4 *start = &info->mColors[ index_start ]; - const LLColor4 *end = &info->mColors[ index_end ]; - return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX], - (1.f - weight) * start->mV[VY] + weight * end->mV[VY], - (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], - (1.f - weight) * start->mV[VW] + weight * end->mV[VW]); - } -} - - -void LLTexLayerParamColor::setWeight(F32 weight) -{ - if (mIsAnimating) - { - return; - } - - F32 min_weight = getMinWeight(); - F32 max_weight = getMaxWeight(); - F32 new_weight = llclamp(weight, min_weight, max_weight); - U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); - U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); - if (cur_u8 != new_u8) - { - mCurWeight = new_weight; - - const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); - - if (info->mNumColors <= 0) - { - // This will happen when we set the default weight the first time. - return; - } - - if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. - { - onGlobalColorChanged(); - if (mTexLayer) - { - mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet()); - } - } - -// LL_INFOS() << "param " << mName << " = " << new_weight << LL_ENDL; - } -} - -void LLTexLayerParamColor::setAnimationTarget(F32 target_value) -{ - // set value first then set interpolating flag to ignore further updates - mTargetWeight = target_value; - setWeight(target_value); - mIsAnimating = true; - if (mNext) - { - mNext->setAnimationTarget(target_value); - } -} - -void LLTexLayerParamColor::animate(F32 delta) -{ - if (mNext) - { - mNext->animate(delta); - } -} - -//----------------------------------------------------------------------------- -// LLTexLayerParamColorInfo -//----------------------------------------------------------------------------- -LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() : - mOperation(LLTexLayerParamColor::OP_ADD), - mNumColors(0) -{ -} - -bool LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) -{ - llassert(node->hasName("param") && node->getChildByName("param_color")); - - if (!LLViewerVisualParamInfo::parseXml(node)) - return false; - - LLXmlTreeNode* param_color_node = node->getChildByName("param_color"); - if (!param_color_node) - { - return false; - } - - std::string op_string; - static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation"); - if (param_color_node->getFastAttributeString(operation_string, op_string)) - { - LLStringUtil::toLower(op_string); - if (op_string == "add") mOperation = LLTexLayerParamColor::OP_ADD; - else if (op_string == "multiply") mOperation = LLTexLayerParamColor::OP_MULTIPLY; - else if (op_string == "blend") mOperation = LLTexLayerParamColor::OP_BLEND; - } - - mNumColors = 0; - - LLColor4U color4u; - for (LLXmlTreeNode* child = param_color_node->getChildByName("value"); - child; - child = param_color_node->getNextNamedChild()) - { - if ((mNumColors < MAX_COLOR_VALUES)) - { - static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color"); - if (child->getFastAttributeColor4U(color_string, color4u)) - { - mColors[ mNumColors ].setVec(color4u); - mNumColors++; - } - } - } - if (!mNumColors) - { - LL_WARNS() << " is missing sub-elements" << LL_ENDL; - return false; - } - - if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1)) - { - LL_WARNS() << " with operation\"blend\" must have exactly one " << LL_ENDL; - return false; - } - - return true; -} +/** + * @file lltexlayerparams.cpp + * @brief Texture layer parameters + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "lltexlayerparams.h" + +#include "llavatarappearance.h" +#include "llimagetga.h" +#include "llquantize.h" +#include "lltexlayer.h" +#include "lltexturemanagerbridge.h" +#include "../llui/llui.h" +#include "llwearable.h" +#include "llfasttimer.h" + +//----------------------------------------------------------------------------- +// LLTexLayerParam +//----------------------------------------------------------------------------- +LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) + : LLViewerVisualParam(), + mTexLayer(layer), + mAvatarAppearance(NULL) +{ + if (mTexLayer != NULL) + { + mAvatarAppearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); + } + else + { + LL_ERRS() << "LLTexLayerParam constructor passed with NULL reference for layer!" << LL_ENDL; + } +} + +LLTexLayerParam::LLTexLayerParam(LLAvatarAppearance *appearance) + : LLViewerVisualParam(), + mTexLayer(NULL), + mAvatarAppearance(appearance) +{ +} + +LLTexLayerParam::LLTexLayerParam(const LLTexLayerParam& pOther) + : LLViewerVisualParam(pOther), + mTexLayer(pOther.mTexLayer), + mAvatarAppearance(pOther.mAvatarAppearance) +{ +} + +bool LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, bool add_to_appearance) +{ + LLViewerVisualParam::setInfo(info); + + if (add_to_appearance) + { + mAvatarAppearance->addVisualParam( this); + this->setParamLocation(mAvatarAppearance->isSelf() ? LOC_AV_SELF : LOC_AV_OTHER); + } + + return true; +} + + +//----------------------------------------------------------------------------- +// LLTexLayerParamAlpha +//----------------------------------------------------------------------------- + +// static +LLTexLayerParamAlpha::param_alpha_ptr_list_t LLTexLayerParamAlpha::sInstances; + +// static +void LLTexLayerParamAlpha::dumpCacheByteCount() +{ + S32 gl_bytes = 0; + getCacheByteCount( &gl_bytes); + LL_INFOS() << "Processed Alpha Texture Cache GL:" << (gl_bytes/1024) << "KB" << LL_ENDL; +} + +// static +void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes) +{ + *gl_bytes = 0; + + for (LLTexLayerParamAlpha* instance : sInstances) + { + LLGLTexture* tex = instance->mCachedProcessedTexture; + if (tex) + { + S32 bytes = (S32)tex->getWidth() * tex->getHeight() * tex->getComponents(); + + if (tex->hasGLTexture()) + { + *gl_bytes += bytes; + } + } + } +} + +LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) + : LLTexLayerParam(layer), + mCachedProcessedTexture(NULL), + mStaticImageTGA(), + mStaticImageRaw(), + mNeedsCreateTexture(false), + mStaticImageInvalid(false), + mAvgDistortionVec(1.f, 1.f, 1.f), + mCachedEffectiveWeight(0.f) +{ + sInstances.push_front(this); +} + +LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLAvatarAppearance* appearance) + : LLTexLayerParam(appearance), + mCachedProcessedTexture(NULL), + mStaticImageTGA(), + mStaticImageRaw(), + mNeedsCreateTexture(false), + mStaticImageInvalid(false), + mAvgDistortionVec(1.f, 1.f, 1.f), + mCachedEffectiveWeight(0.f) +{ + sInstances.push_front(this); +} + +LLTexLayerParamAlpha::LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther) + : LLTexLayerParam(pOther), + mCachedProcessedTexture(pOther.mCachedProcessedTexture), + mStaticImageTGA(pOther.mStaticImageTGA), + mStaticImageRaw(pOther.mStaticImageRaw), + mNeedsCreateTexture(pOther.mNeedsCreateTexture.load()), + mStaticImageInvalid(pOther.mStaticImageInvalid), + mAvgDistortionVec(pOther.mAvgDistortionVec), + mCachedEffectiveWeight(pOther.mCachedEffectiveWeight) +{ + sInstances.push_front(this); +} + +LLTexLayerParamAlpha::~LLTexLayerParamAlpha() +{ + deleteCaches(); + sInstances.remove(this); +} + +/*virtual*/ LLViewerVisualParam* LLTexLayerParamAlpha::cloneParam(LLWearable* wearable) const +{ + return new LLTexLayerParamAlpha(*this); +} + +void LLTexLayerParamAlpha::deleteCaches() +{ + mStaticImageTGA = NULL; // deletes image + mCachedProcessedTexture = NULL; + mStaticImageRaw = NULL; + mNeedsCreateTexture = false; +} + +bool LLTexLayerParamAlpha::getMultiplyBlend() const +{ + return ((LLTexLayerParamAlphaInfo *)getInfo())->mMultiplyBlend; +} + +void LLTexLayerParamAlpha::setWeight(F32 weight) +{ + if (mIsAnimating || mTexLayer == NULL) + { + return; + } + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + F32 new_weight = llclamp(weight, min_weight, max_weight); + U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); + U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); + if (cur_u8 != new_u8) + { + mCurWeight = new_weight; + + if ((mAvatarAppearance->getSex() & getSex()) && + (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. + { + mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet()); + mTexLayer->invalidateMorphMasks(); + } + } +} + +void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value) +{ + // do not animate dummy parameters + if (mIsDummy) + { + setWeight(target_value); + return; + } + + mTargetWeight = target_value; + setWeight(target_value); + mIsAnimating = true; + if (mNext) + { + mNext->setAnimationTarget(target_value); + } +} + +void LLTexLayerParamAlpha::animate(F32 delta) +{ + if (mNext) + { + mNext->animate(delta); + } +} + +bool LLTexLayerParamAlpha::getSkip() const +{ + if (!mTexLayer) + { + return true; + } + + const LLAvatarAppearance *appearance = mTexLayer->getTexLayerSet()->getAvatarAppearance(); + + if (((LLTexLayerParamAlphaInfo *)getInfo())->mSkipIfZeroWeight) + { + F32 effective_weight = (appearance->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); + if (is_approx_zero(effective_weight)) + { + return true; + } + } + + LLWearableType::EType type = (LLWearableType::EType)getWearableType(); + if ((type != LLWearableType::WT_INVALID) && !appearance->isWearingWearableType(type)) + { + return true; + } + + return false; +} + + +bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) +{ + LL_PROFILE_ZONE_SCOPED; + bool success = true; + + if (!mTexLayer) + { + return success; + } + + F32 effective_weight = (mTexLayer->getTexLayerSet()->getAvatarAppearance()->getSex() & getSex()) ? mCurWeight : getDefaultWeight(); + bool weight_changed = effective_weight != mCachedEffectiveWeight; + if (getSkip()) + { + return success; + } + + LLTexLayerParamAlphaInfo *info = (LLTexLayerParamAlphaInfo *)getInfo(); + gGL.flush(); + if (info->mMultiplyBlend) + { + gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ZERO); // Multiplication: approximates a min() function + } + else + { + gGL.setSceneBlendType(LLRender::BT_ADD); // Addition: approximates a max() function + } + + if (!info->mStaticImageFileName.empty() && !mStaticImageInvalid) + { + if (mStaticImageTGA.isNull()) + { + // Don't load the image file until we actually need it the first time. Like now. + mStaticImageTGA = LLTexLayerStaticImageList::getInstance()->getImageTGA(info->mStaticImageFileName); + // We now have something in one of our caches + LLTexLayerSet::sHasCaches |= mStaticImageTGA.notNull(); + + if (mStaticImageTGA.isNull()) + { + LL_WARNS() << "Unable to load static file: " << info->mStaticImageFileName << LL_ENDL; + mStaticImageInvalid = true; // don't try again. + return false; + } + } + + const S32 image_tga_width = mStaticImageTGA->getWidth(); + const S32 image_tga_height = mStaticImageTGA->getHeight(); + if (!mCachedProcessedTexture || + (mCachedProcessedTexture->getWidth() != image_tga_width) || + (mCachedProcessedTexture->getHeight() != image_tga_height) || + (weight_changed)) + { + mCachedEffectiveWeight = effective_weight; + + if (!mCachedProcessedTexture) + { + llassert(gTextureManagerBridgep); + mCachedProcessedTexture = gTextureManagerBridgep->getLocalTexture(image_tga_width, image_tga_height, 1, false); + + // We now have something in one of our caches + LLTexLayerSet::sHasCaches |= mCachedProcessedTexture.notNull(); + + mCachedProcessedTexture->setExplicitFormat(GL_ALPHA8, GL_ALPHA); + } + + // Applies domain and effective weight to data as it is decoded. Also resizes the raw image if needed. + mStaticImageRaw = NULL; + mStaticImageRaw = new LLImageRaw; + mStaticImageTGA->decodeAndProcess(mStaticImageRaw, info->mDomain, effective_weight); + mNeedsCreateTexture = true; + LL_DEBUGS() << "Built Cached Alpha: " << info->mStaticImageFileName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << "Domain: " << info->mDomain << " Weight: " << effective_weight << LL_ENDL; + } + + if (mCachedProcessedTexture) + { + { + // Create the GL texture, and then hang onto it for future use. + if (mNeedsCreateTexture) + { + mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); + mNeedsCreateTexture = false; + gGL.getTexUnit(0)->bind(mCachedProcessedTexture); + mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); + } + + gGL.getTexUnit(0)->bind(mCachedProcessedTexture); + gl_rect_2d_simple_tex(width, height); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + stop_glerror(); + } + } + + // 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 (!mAvatarAppearance->isSelf()) + { + mCachedProcessedTexture = NULL; + } + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.color4f(0.f, 0.f, 0.f, effective_weight); + gl_rect_2d_simple(width, height); + } + + return success; +} + +//----------------------------------------------------------------------------- +// LLTexLayerParamAlphaInfo +//----------------------------------------------------------------------------- +LLTexLayerParamAlphaInfo::LLTexLayerParamAlphaInfo() : + mMultiplyBlend(false), + mSkipIfZeroWeight(false), + mDomain(0.f) +{ +} + +bool LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node) +{ + llassert(node->hasName("param") && node->getChildByName("param_alpha")); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return false; + + LLXmlTreeNode* param_alpha_node = node->getChildByName("param_alpha"); + if (!param_alpha_node) + { + return false; + } + + static LLStdStringHandle tga_file_string = LLXmlTree::addAttributeString("tga_file"); + if (param_alpha_node->getFastAttributeString(tga_file_string, mStaticImageFileName)) + { + // Don't load the image file until it's actually needed. + } +// else +// { +// LL_WARNS() << " element is missing tga_file attribute." << LL_ENDL; +// } + + static LLStdStringHandle multiply_blend_string = LLXmlTree::addAttributeString("multiply_blend"); + param_alpha_node->getFastAttributeBOOL(multiply_blend_string, mMultiplyBlend); + + static LLStdStringHandle skip_if_zero_string = LLXmlTree::addAttributeString("skip_if_zero"); + param_alpha_node->getFastAttributeBOOL(skip_if_zero_string, mSkipIfZeroWeight); + + static LLStdStringHandle domain_string = LLXmlTree::addAttributeString("domain"); + param_alpha_node->getFastAttributeF32(domain_string, mDomain); + + return true; +} + + + + +LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) + : LLTexLayerParam(layer), + mAvgDistortionVec(1.f, 1.f, 1.f) +{ +} + +LLTexLayerParamColor::LLTexLayerParamColor(LLAvatarAppearance *appearance) + : LLTexLayerParam(appearance), + mAvgDistortionVec(1.f, 1.f, 1.f) +{ +} + +LLTexLayerParamColor::LLTexLayerParamColor(const LLTexLayerParamColor& pOther) + : LLTexLayerParam(pOther), + mAvgDistortionVec(pOther.mAvgDistortionVec) +{ +} + +LLTexLayerParamColor::~LLTexLayerParamColor() +{ +} + +/*virtual*/ LLViewerVisualParam* LLTexLayerParamColor::cloneParam(LLWearable* wearable) const +{ + return new LLTexLayerParamColor(*this); +} + +LLColor4 LLTexLayerParamColor::getNetColor() const +{ + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); + + llassert(info->mNumColors >= 1); + + F32 effective_weight = (mAvatarAppearance && (mAvatarAppearance->getSex() & getSex())) ? mCurWeight : getDefaultWeight(); + + S32 index_last = info->mNumColors - 1; + F32 scaled_weight = effective_weight * index_last; + S32 index_start = (S32) scaled_weight; + S32 index_end = index_start + 1; + if (index_start == index_last) + { + return info->mColors[index_last]; + } + else + { + F32 weight = scaled_weight - index_start; + const LLColor4 *start = &info->mColors[ index_start ]; + const LLColor4 *end = &info->mColors[ index_end ]; + return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX], + (1.f - weight) * start->mV[VY] + weight * end->mV[VY], + (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], + (1.f - weight) * start->mV[VW] + weight * end->mV[VW]); + } +} + + +void LLTexLayerParamColor::setWeight(F32 weight) +{ + if (mIsAnimating) + { + return; + } + + F32 min_weight = getMinWeight(); + F32 max_weight = getMaxWeight(); + F32 new_weight = llclamp(weight, min_weight, max_weight); + U8 cur_u8 = F32_to_U8(mCurWeight, min_weight, max_weight); + U8 new_u8 = F32_to_U8(new_weight, min_weight, max_weight); + if (cur_u8 != new_u8) + { + mCurWeight = new_weight; + + const LLTexLayerParamColorInfo *info = (LLTexLayerParamColorInfo *)getInfo(); + + if (info->mNumColors <= 0) + { + // This will happen when we set the default weight the first time. + return; + } + + if ((mAvatarAppearance->getSex() & getSex()) && (mAvatarAppearance->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param. + { + onGlobalColorChanged(); + if (mTexLayer) + { + mAvatarAppearance->invalidateComposite(mTexLayer->getTexLayerSet()); + } + } + +// LL_INFOS() << "param " << mName << " = " << new_weight << LL_ENDL; + } +} + +void LLTexLayerParamColor::setAnimationTarget(F32 target_value) +{ + // set value first then set interpolating flag to ignore further updates + mTargetWeight = target_value; + setWeight(target_value); + mIsAnimating = true; + if (mNext) + { + mNext->setAnimationTarget(target_value); + } +} + +void LLTexLayerParamColor::animate(F32 delta) +{ + if (mNext) + { + mNext->animate(delta); + } +} + +//----------------------------------------------------------------------------- +// LLTexLayerParamColorInfo +//----------------------------------------------------------------------------- +LLTexLayerParamColorInfo::LLTexLayerParamColorInfo() : + mOperation(LLTexLayerParamColor::OP_ADD), + mNumColors(0) +{ +} + +bool LLTexLayerParamColorInfo::parseXml(LLXmlTreeNode *node) +{ + llassert(node->hasName("param") && node->getChildByName("param_color")); + + if (!LLViewerVisualParamInfo::parseXml(node)) + return false; + + LLXmlTreeNode* param_color_node = node->getChildByName("param_color"); + if (!param_color_node) + { + return false; + } + + std::string op_string; + static LLStdStringHandle operation_string = LLXmlTree::addAttributeString("operation"); + if (param_color_node->getFastAttributeString(operation_string, op_string)) + { + LLStringUtil::toLower(op_string); + if (op_string == "add") mOperation = LLTexLayerParamColor::OP_ADD; + else if (op_string == "multiply") mOperation = LLTexLayerParamColor::OP_MULTIPLY; + else if (op_string == "blend") mOperation = LLTexLayerParamColor::OP_BLEND; + } + + mNumColors = 0; + + LLColor4U color4u; + for (LLXmlTreeNode* child = param_color_node->getChildByName("value"); + child; + child = param_color_node->getNextNamedChild()) + { + if ((mNumColors < MAX_COLOR_VALUES)) + { + static LLStdStringHandle color_string = LLXmlTree::addAttributeString("color"); + if (child->getFastAttributeColor4U(color_string, color4u)) + { + mColors[ mNumColors ].setVec(color4u); + mNumColors++; + } + } + } + if (!mNumColors) + { + LL_WARNS() << " is missing sub-elements" << LL_ENDL; + return false; + } + + if ((mOperation == LLTexLayerParamColor::OP_BLEND) && (mNumColors != 1)) + { + LL_WARNS() << " with operation\"blend\" must have exactly one " << LL_ENDL; + return false; + } + + return true; +} diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index 90c8c92557..5e785e4f3e 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -1,206 +1,206 @@ -/** - * @file lltexlayerparams.h - * @brief Texture layer parameters, used by lltexlayer. - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLTEXLAYERPARAMS_H -#define LL_LLTEXLAYERPARAMS_H - -#include "llpointer.h" -#include "v4color.h" -#include "llviewervisualparam.h" - -class LLAvatarAppearance; -class LLImageRaw; -class LLImageTGA; -class LLTexLayer; -class LLTexLayerInterface; -class LLGLTexture; -class LLWearable; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerParam -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLTexLayerParam : public LLViewerVisualParam -{ -public: - LLTexLayerParam(LLTexLayerInterface *layer); - LLTexLayerParam(LLAvatarAppearance *appearance); - /*virtual*/ bool setInfo(LLViewerVisualParamInfo *info, bool add_to_appearance); - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; - -protected: - LLTexLayerParam(const LLTexLayerParam& pOther); - - LLTexLayerInterface* mTexLayer; - LLAvatarAppearance* mAvatarAppearance; -}; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerParamAlpha -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL_ALIGN_PREFIX(16) -class alignas(16) LLTexLayerParamAlpha : public LLTexLayerParam -{ - LL_ALIGN_NEW -public: - LLTexLayerParamAlpha( LLTexLayerInterface* layer ); - LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); - /*virtual*/ ~LLTexLayerParamAlpha(); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; - - // LLVisualParam Virtual functions - ///*virtual*/ bool parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight); - /*virtual*/ void setAnimationTarget(F32 target_value); - /*virtual*/ void animate(F32 delta); - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } - /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; - - // New functions - bool render( S32 x, S32 y, S32 width, S32 height ); - bool getSkip() const; - void deleteCaches(); - bool getMultiplyBlend() const; - -private: - LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther); - - LLPointer mCachedProcessedTexture; - LLPointer mStaticImageTGA; - LLPointer mStaticImageRaw; - std::atomic mNeedsCreateTexture; - bool mStaticImageInvalid; - LL_ALIGN_16(LLVector4a mAvgDistortionVec); - F32 mCachedEffectiveWeight; - -public: - // Global list of instances for gathering statistics - static void dumpCacheByteCount(); - static void getCacheByteCount( S32* gl_bytes ); - - typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; - static param_alpha_ptr_list_t sInstances; -} LL_ALIGN_POSTFIX(16); -class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo -{ - friend class LLTexLayerParamAlpha; -public: - LLTexLayerParamAlphaInfo(); - /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; - - /*virtual*/ bool parseXml(LLXmlTreeNode* node); - -private: - std::string mStaticImageFileName; - bool mMultiplyBlend; - bool mSkipIfZeroWeight; - F32 mDomain; -}; -// -// LLTexLayerParamAlpha -//----------------------------------------------------------------------------- - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// LLTexLayerParamColor -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class alignas(16) LLTexLayerParamColor : public LLTexLayerParam -{ - LL_ALIGN_NEW -public: - enum EColorOperation - { - OP_ADD = 0, - OP_MULTIPLY = 1, - OP_BLEND = 2, - OP_COUNT = 3 // Number of operations - }; - - LLTexLayerParamColor( LLTexLayerInterface* layer ); - LLTexLayerParamColor( LLAvatarAppearance* appearance ); - - /* virtual */ ~LLTexLayerParamColor(); - - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; - - // LLVisualParam Virtual functions - ///*virtual*/ bool parseData(LLXmlTreeNode* node); - /*virtual*/ void apply( ESex avatar_sex ) {} - /*virtual*/ void setWeight(F32 weight); - /*virtual*/ void setAnimationTarget(F32 target_value); - /*virtual*/ void animate(F32 delta); - - - // LLViewerVisualParam Virtual functions - /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } - /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } - /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; - - // New functions - LLColor4 getNetColor() const; -protected: - LLTexLayerParamColor(const LLTexLayerParamColor& pOther); - - virtual void onGlobalColorChanged() {} -private: - LLVector4a mAvgDistortionVec; -}; - -class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo -{ - friend class LLTexLayerParamColor; - -public: - LLTexLayerParamColorInfo(); - virtual ~LLTexLayerParamColorInfo() {}; - bool parseXml( LLXmlTreeNode* node ); - LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; } -private: - enum { MAX_COLOR_VALUES = 20 }; - LLTexLayerParamColor::EColorOperation mOperation; - LLColor4 mColors[MAX_COLOR_VALUES]; - S32 mNumColors; -}; - -typedef std::vector param_color_list_t; -typedef std::vector param_alpha_list_t; -typedef std::vector param_color_info_list_t; -typedef std::vector param_alpha_info_list_t; - -#endif +/** + * @file lltexlayerparams.h + * @brief Texture layer parameters, used by lltexlayer. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXLAYERPARAMS_H +#define LL_LLTEXLAYERPARAMS_H + +#include "llpointer.h" +#include "v4color.h" +#include "llviewervisualparam.h" + +class LLAvatarAppearance; +class LLImageRaw; +class LLImageTGA; +class LLTexLayer; +class LLTexLayerInterface; +class LLGLTexture; +class LLWearable; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParam +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLTexLayerParam : public LLViewerVisualParam +{ +public: + LLTexLayerParam(LLTexLayerInterface *layer); + LLTexLayerParam(LLAvatarAppearance *appearance); + /*virtual*/ bool setInfo(LLViewerVisualParamInfo *info, bool add_to_appearance); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; + +protected: + LLTexLayerParam(const LLTexLayerParam& pOther); + + LLTexLayerInterface* mTexLayer; + LLAvatarAppearance* mAvatarAppearance; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParamAlpha +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL_ALIGN_PREFIX(16) +class alignas(16) LLTexLayerParamAlpha : public LLTexLayerParam +{ + LL_ALIGN_NEW +public: + LLTexLayerParamAlpha( LLTexLayerInterface* layer ); + LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); + /*virtual*/ ~LLTexLayerParamAlpha(); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; + + // LLVisualParam Virtual functions + ///*virtual*/ bool parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex avatar_sex ) {} + /*virtual*/ void setWeight(F32 weight); + /*virtual*/ void setAnimationTarget(F32 target_value); + /*virtual*/ void animate(F32 delta); + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 1.f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ F32 getMaxDistortion() { return 3.f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + + // New functions + bool render( S32 x, S32 y, S32 width, S32 height ); + bool getSkip() const; + void deleteCaches(); + bool getMultiplyBlend() const; + +private: + LLTexLayerParamAlpha(const LLTexLayerParamAlpha& pOther); + + LLPointer mCachedProcessedTexture; + LLPointer mStaticImageTGA; + LLPointer mStaticImageRaw; + std::atomic mNeedsCreateTexture; + bool mStaticImageInvalid; + LL_ALIGN_16(LLVector4a mAvgDistortionVec); + F32 mCachedEffectiveWeight; + +public: + // Global list of instances for gathering statistics + static void dumpCacheByteCount(); + static void getCacheByteCount( S32* gl_bytes ); + + typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; + static param_alpha_ptr_list_t sInstances; +} LL_ALIGN_POSTFIX(16); +class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo +{ + friend class LLTexLayerParamAlpha; +public: + LLTexLayerParamAlphaInfo(); + /*virtual*/ ~LLTexLayerParamAlphaInfo() {}; + + /*virtual*/ bool parseXml(LLXmlTreeNode* node); + +private: + std::string mStaticImageFileName; + bool mMultiplyBlend; + bool mSkipIfZeroWeight; + F32 mDomain; +}; +// +// LLTexLayerParamAlpha +//----------------------------------------------------------------------------- + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LLTexLayerParamColor +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class alignas(16) LLTexLayerParamColor : public LLTexLayerParam +{ + LL_ALIGN_NEW +public: + enum EColorOperation + { + OP_ADD = 0, + OP_MULTIPLY = 1, + OP_BLEND = 2, + OP_COUNT = 3 // Number of operations + }; + + LLTexLayerParamColor( LLTexLayerInterface* layer ); + LLTexLayerParamColor( LLAvatarAppearance* appearance ); + + /* virtual */ ~LLTexLayerParamColor(); + + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; + + // LLVisualParam Virtual functions + ///*virtual*/ bool parseData(LLXmlTreeNode* node); + /*virtual*/ void apply( ESex avatar_sex ) {} + /*virtual*/ void setWeight(F32 weight); + /*virtual*/ void setAnimationTarget(F32 target_value); + /*virtual*/ void animate(F32 delta); + + + // LLViewerVisualParam Virtual functions + /*virtual*/ F32 getTotalDistortion() { return 1.f; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ F32 getMaxDistortion() { return 3.f; } + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + + // New functions + LLColor4 getNetColor() const; +protected: + LLTexLayerParamColor(const LLTexLayerParamColor& pOther); + + virtual void onGlobalColorChanged() {} +private: + LLVector4a mAvgDistortionVec; +}; + +class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo +{ + friend class LLTexLayerParamColor; + +public: + LLTexLayerParamColorInfo(); + virtual ~LLTexLayerParamColorInfo() {}; + bool parseXml( LLXmlTreeNode* node ); + LLTexLayerParamColor::EColorOperation getOperation() const { return mOperation; } +private: + enum { MAX_COLOR_VALUES = 20 }; + LLTexLayerParamColor::EColorOperation mOperation; + LLColor4 mColors[MAX_COLOR_VALUES]; + S32 mNumColors; +}; + +typedef std::vector param_color_list_t; +typedef std::vector param_alpha_list_t; +typedef std::vector param_color_info_list_t; +typedef std::vector param_alpha_info_list_t; + +#endif diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index 1b4916cce9..00d6383ad0 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -1,179 +1,179 @@ -/** - * @file llviewervisualparam.cpp - * @brief Implementation of LLViewerVisualParam class - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "linden_common.h" - -#include "llviewervisualparam.h" -#include "llxmltree.h" -#include "llwearable.h" - -//----------------------------------------------------------------------------- -// LLViewerVisualParamInfo() -//----------------------------------------------------------------------------- -LLViewerVisualParamInfo::LLViewerVisualParamInfo() - : - mWearableType( LLWearableType::WT_INVALID ), - mCrossWearable(false), - mCamDist( 0.5f ), - mCamAngle( 0.f ), - mCamElevation( 0.f ), - mEditGroupDisplayOrder( 0 ), - mShowSimple(false), - mSimpleMin(0.f), - mSimpleMax(100.f) -{ -} - -LLViewerVisualParamInfo::~LLViewerVisualParamInfo() -{ -} - -//----------------------------------------------------------------------------- -// parseXml() -//----------------------------------------------------------------------------- -bool LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) -{ - llassert( node->hasName( "param" ) ); - - if (!LLVisualParamInfo::parseXml(node)) - return false; - - // VIEWER SPECIFIC PARAMS - - std::string wearable; - static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable"); - if( node->getFastAttributeString( wearable_string, wearable) ) - { - mWearableType = LLWearableType::getInstance()->typeNameToType( wearable ); - } - - static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); - if (!node->getFastAttributeString( edit_group_string, mEditGroup)) - { - mEditGroup = ""; - } - - static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable"); - if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable)) - { - mCrossWearable = false; - } - - // Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails). - static LLStdStringHandle camera_distance_string = LLXmlTree::addAttributeString("camera_distance"); - node->getFastAttributeF32( camera_distance_string, mCamDist ); - static LLStdStringHandle camera_angle_string = LLXmlTree::addAttributeString("camera_angle"); - node->getFastAttributeF32( camera_angle_string, mCamAngle ); // in degrees - static LLStdStringHandle camera_elevation_string = LLXmlTree::addAttributeString("camera_elevation"); - node->getFastAttributeF32( camera_elevation_string, mCamElevation ); - - mCamAngle += 180; - - static S32 params_loaded = 0; - - // By default, parameters are displayed in the order in which they appear in the xml file. - // "edit_group_order" overriddes. - static LLStdStringHandle edit_group_order_string = LLXmlTree::addAttributeString("edit_group_order"); - if( !node->getFastAttributeF32( edit_group_order_string, mEditGroupDisplayOrder ) ) - { - mEditGroupDisplayOrder = (F32)params_loaded; - } - - params_loaded++; - - return true; -} - -/*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out) -{ - LLVisualParamInfo::toStream(out); - - out << mWearableType << "\t"; - out << mEditGroup << "\t"; - out << mEditGroupDisplayOrder << "\t"; -} - -//----------------------------------------------------------------------------- -// LLViewerVisualParam() -//----------------------------------------------------------------------------- -LLViewerVisualParam::LLViewerVisualParam() - : LLVisualParam() -{ -} - -//----------------------------------------------------------------------------- -// LLViewerVisualParam() -//----------------------------------------------------------------------------- -LLViewerVisualParam::LLViewerVisualParam(const LLViewerVisualParam& pOther) - : LLVisualParam(pOther) -{ -} - -//----------------------------------------------------------------------------- -// ~LLViewerVisualParam() -//----------------------------------------------------------------------------- -LLViewerVisualParam::~LLViewerVisualParam() -{ -} - -//----------------------------------------------------------------------------- -// setInfo() -//----------------------------------------------------------------------------- - -bool LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) -{ - llassert(mInfo == NULL); - if (info->mID < 0) - return false; - mInfo = info; - mID = info->mID; - setWeight(getDefaultWeight()); - return true; -} - -/* -//============================================================================= -// These virtual functions should always be overridden, -// but are included here for use as templates -//============================================================================= - -//----------------------------------------------------------------------------- -// parseData() -//----------------------------------------------------------------------------- -bool LLViewerVisualParam::parseData(LLXmlTreeNode *node) -{ - LLViewerVisualParamInfo* info = new LLViewerVisualParamInfo; - - info->parseXml(node); - if (!setInfo(info)) - return false; - - return true; -} -*/ +/** + * @file llviewervisualparam.cpp + * @brief Implementation of LLViewerVisualParam class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +//----------------------------------------------------------------------------- +// Header Files +//----------------------------------------------------------------------------- +#include "linden_common.h" + +#include "llviewervisualparam.h" +#include "llxmltree.h" +#include "llwearable.h" + +//----------------------------------------------------------------------------- +// LLViewerVisualParamInfo() +//----------------------------------------------------------------------------- +LLViewerVisualParamInfo::LLViewerVisualParamInfo() + : + mWearableType( LLWearableType::WT_INVALID ), + mCrossWearable(false), + mCamDist( 0.5f ), + mCamAngle( 0.f ), + mCamElevation( 0.f ), + mEditGroupDisplayOrder( 0 ), + mShowSimple(false), + mSimpleMin(0.f), + mSimpleMax(100.f) +{ +} + +LLViewerVisualParamInfo::~LLViewerVisualParamInfo() +{ +} + +//----------------------------------------------------------------------------- +// parseXml() +//----------------------------------------------------------------------------- +bool LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node) +{ + llassert( node->hasName( "param" ) ); + + if (!LLVisualParamInfo::parseXml(node)) + return false; + + // VIEWER SPECIFIC PARAMS + + std::string wearable; + static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable"); + if( node->getFastAttributeString( wearable_string, wearable) ) + { + mWearableType = LLWearableType::getInstance()->typeNameToType( wearable ); + } + + static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group"); + if (!node->getFastAttributeString( edit_group_string, mEditGroup)) + { + mEditGroup = ""; + } + + static LLStdStringHandle cross_wearable_string = LLXmlTree::addAttributeString("cross_wearable"); + if (!node->getFastAttributeBOOL(cross_wearable_string, mCrossWearable)) + { + mCrossWearable = false; + } + + // Optional camera offsets from the current joint center. Used for generating "hints" (thumbnails). + static LLStdStringHandle camera_distance_string = LLXmlTree::addAttributeString("camera_distance"); + node->getFastAttributeF32( camera_distance_string, mCamDist ); + static LLStdStringHandle camera_angle_string = LLXmlTree::addAttributeString("camera_angle"); + node->getFastAttributeF32( camera_angle_string, mCamAngle ); // in degrees + static LLStdStringHandle camera_elevation_string = LLXmlTree::addAttributeString("camera_elevation"); + node->getFastAttributeF32( camera_elevation_string, mCamElevation ); + + mCamAngle += 180; + + static S32 params_loaded = 0; + + // By default, parameters are displayed in the order in which they appear in the xml file. + // "edit_group_order" overriddes. + static LLStdStringHandle edit_group_order_string = LLXmlTree::addAttributeString("edit_group_order"); + if( !node->getFastAttributeF32( edit_group_order_string, mEditGroupDisplayOrder ) ) + { + mEditGroupDisplayOrder = (F32)params_loaded; + } + + params_loaded++; + + return true; +} + +/*virtual*/ void LLViewerVisualParamInfo::toStream(std::ostream &out) +{ + LLVisualParamInfo::toStream(out); + + out << mWearableType << "\t"; + out << mEditGroup << "\t"; + out << mEditGroupDisplayOrder << "\t"; +} + +//----------------------------------------------------------------------------- +// LLViewerVisualParam() +//----------------------------------------------------------------------------- +LLViewerVisualParam::LLViewerVisualParam() + : LLVisualParam() +{ +} + +//----------------------------------------------------------------------------- +// LLViewerVisualParam() +//----------------------------------------------------------------------------- +LLViewerVisualParam::LLViewerVisualParam(const LLViewerVisualParam& pOther) + : LLVisualParam(pOther) +{ +} + +//----------------------------------------------------------------------------- +// ~LLViewerVisualParam() +//----------------------------------------------------------------------------- +LLViewerVisualParam::~LLViewerVisualParam() +{ +} + +//----------------------------------------------------------------------------- +// setInfo() +//----------------------------------------------------------------------------- + +bool LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) +{ + llassert(mInfo == NULL); + if (info->mID < 0) + return false; + mInfo = info; + mID = info->mID; + setWeight(getDefaultWeight()); + return true; +} + +/* +//============================================================================= +// These virtual functions should always be overridden, +// but are included here for use as templates +//============================================================================= + +//----------------------------------------------------------------------------- +// parseData() +//----------------------------------------------------------------------------- +bool LLViewerVisualParam::parseData(LLXmlTreeNode *node) +{ + LLViewerVisualParamInfo* info = new LLViewerVisualParamInfo; + + info->parseXml(node); + if (!setInfo(info)) + return false; + + return true; +} +*/ diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index e384dce3ac..b79983df8e 100644 --- a/indra/llappearance/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h @@ -1,112 +1,112 @@ -/** - * @file llviewervisualparam.h - * @brief viewer side visual params (with data file parsing) - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLViewerVisualParam_H -#define LL_LLViewerVisualParam_H - -#include "v3math.h" -#include "llstring.h" -#include "llvisualparam.h" - -class LLWearable; - -//----------------------------------------------------------------------------- -// LLViewerVisualParamInfo -//----------------------------------------------------------------------------- -class LLViewerVisualParamInfo : public LLVisualParamInfo -{ - friend class LLViewerVisualParam; -public: - LLViewerVisualParamInfo(); - /*virtual*/ ~LLViewerVisualParamInfo(); - - /*virtual*/ bool parseXml(LLXmlTreeNode* node); - - /*virtual*/ void toStream(std::ostream &out); - -protected: - S32 mWearableType; - bool mCrossWearable; - std::string mEditGroup; - F32 mCamDist; - F32 mCamAngle; // degrees - F32 mCamElevation; - F32 mEditGroupDisplayOrder; - bool mShowSimple; // show edit controls when in "simple ui" mode? - F32 mSimpleMin; // when in simple UI, apply this minimum, range 0.f to 100.f - F32 mSimpleMax; // when in simple UI, apply this maximum, range 0.f to 100.f -}; - -//----------------------------------------------------------------------------- -// LLViewerVisualParam -// VIRTUAL CLASS -// a viewer side interface class for a generalized parametric modification of the avatar mesh -//----------------------------------------------------------------------------- -LL_ALIGN_PREFIX(16) -class LLViewerVisualParam : public LLVisualParam -{ -public: - LLViewerVisualParam(); - virtual ~LLViewerVisualParam(); - - // Special: These functions are overridden by child classes - LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; }; - // This sets mInfo and calls initialization functions - bool setInfo(LLViewerVisualParamInfo *info); - - virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; - - // LLVisualParam Virtual functions - ///*virtual*/ bool parseData(LLXmlTreeNode* node); - - // New Virtual functions - virtual F32 getTotalDistortion() = 0; - virtual const LLVector4a& getAvgDistortion() = 0; - virtual F32 getMaxDistortion() = 0; - virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; - virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; - virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; - - // interface methods - F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } - S32 getWearableType() const { return getInfo()->mWearableType; } - const std::string& getEditGroup() const { return getInfo()->mEditGroup; } - - F32 getCameraDistance() const { return getInfo()->mCamDist; } - F32 getCameraAngle() const { return getInfo()->mCamAngle; } // degrees - F32 getCameraElevation() const { return getInfo()->mCamElevation; } - - bool getShowSimple() const { return getInfo()->mShowSimple; } - F32 getSimpleMin() const { return getInfo()->mSimpleMin; } - F32 getSimpleMax() const { return getInfo()->mSimpleMax; } - - bool getCrossWearable() const { return getInfo()->mCrossWearable; } - -protected: - LLViewerVisualParam(const LLViewerVisualParam& pOther); -} LL_ALIGN_POSTFIX(16); - -#endif // LL_LLViewerVisualParam_H +/** + * @file llviewervisualparam.h + * @brief viewer side visual params (with data file parsing) + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLViewerVisualParam_H +#define LL_LLViewerVisualParam_H + +#include "v3math.h" +#include "llstring.h" +#include "llvisualparam.h" + +class LLWearable; + +//----------------------------------------------------------------------------- +// LLViewerVisualParamInfo +//----------------------------------------------------------------------------- +class LLViewerVisualParamInfo : public LLVisualParamInfo +{ + friend class LLViewerVisualParam; +public: + LLViewerVisualParamInfo(); + /*virtual*/ ~LLViewerVisualParamInfo(); + + /*virtual*/ bool parseXml(LLXmlTreeNode* node); + + /*virtual*/ void toStream(std::ostream &out); + +protected: + S32 mWearableType; + bool mCrossWearable; + std::string mEditGroup; + F32 mCamDist; + F32 mCamAngle; // degrees + F32 mCamElevation; + F32 mEditGroupDisplayOrder; + bool mShowSimple; // show edit controls when in "simple ui" mode? + F32 mSimpleMin; // when in simple UI, apply this minimum, range 0.f to 100.f + F32 mSimpleMax; // when in simple UI, apply this maximum, range 0.f to 100.f +}; + +//----------------------------------------------------------------------------- +// LLViewerVisualParam +// VIRTUAL CLASS +// a viewer side interface class for a generalized parametric modification of the avatar mesh +//----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) +class LLViewerVisualParam : public LLVisualParam +{ +public: + LLViewerVisualParam(); + virtual ~LLViewerVisualParam(); + + // Special: These functions are overridden by child classes + LLViewerVisualParamInfo *getInfo() const { return (LLViewerVisualParamInfo*)mInfo; }; + // This sets mInfo and calls initialization functions + bool setInfo(LLViewerVisualParamInfo *info); + + virtual LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0; + + // LLVisualParam Virtual functions + ///*virtual*/ bool parseData(LLXmlTreeNode* node); + + // New Virtual functions + virtual F32 getTotalDistortion() = 0; + virtual const LLVector4a& getAvgDistortion() = 0; + virtual F32 getMaxDistortion() = 0; + virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; + virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; + + // interface methods + F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } + S32 getWearableType() const { return getInfo()->mWearableType; } + const std::string& getEditGroup() const { return getInfo()->mEditGroup; } + + F32 getCameraDistance() const { return getInfo()->mCamDist; } + F32 getCameraAngle() const { return getInfo()->mCamAngle; } // degrees + F32 getCameraElevation() const { return getInfo()->mCamElevation; } + + bool getShowSimple() const { return getInfo()->mShowSimple; } + F32 getSimpleMin() const { return getInfo()->mSimpleMin; } + F32 getSimpleMax() const { return getInfo()->mSimpleMax; } + + bool getCrossWearable() const { return getInfo()->mCrossWearable; } + +protected: + LLViewerVisualParam(const LLViewerVisualParam& pOther); +} LL_ALIGN_POSTFIX(16); + +#endif // LL_LLViewerVisualParam_H diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 7f57d1c9c5..9c41e3c256 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -1,773 +1,773 @@ -/** - * @file llwearable.cpp - * @brief LLWearable class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llavatarappearance.h" -#include "lllocaltextureobject.h" -#include "lltexlayer.h" -#include "lltexturemanagerbridge.h" -#include "llvisualparam.h" -#include "llavatarappearancedefines.h" -#include "llwearable.h" -#include "boost/bind.hpp" - -using namespace LLAvatarAppearanceDefines; - -// static -S32 LLWearable::sCurrentDefinitionVersion = 1; - -// Private local functions -static std::string terse_F32_to_string(F32 f); - -LLWearable::LLWearable() - : mDefinitionVersion(-1), - mName(), - mDescription(), - mPermissions(), - mSaleInfo(), - mType(LLWearableType::WT_NONE), - mSavedVisualParamMap(), - mVisualParamIndexMap(), - mTEMap(), - mSavedTEMap() -{ -} - -// virtual -LLWearable::~LLWearable() -{ - for (visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) - { - LLVisualParam* vp = vp_pair.second; - vp->clearNextParam(); - delete vp; - vp_pair.second = NULL; - } - - destroyTextures(); -} - -const std::string& LLWearable::getTypeLabel() const -{ - return LLWearableType::getInstance()->getTypeLabel(mType); -} - -const std::string& LLWearable::getTypeName() const -{ - return LLWearableType::getInstance()->getTypeName(mType); -} - -LLAssetType::EType LLWearable::getAssetType() const -{ - return LLWearableType::getInstance()->getAssetType(mType); -} - -bool LLWearable::exportFile(const std::string& filename) const -{ - llofstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); - return ofs.is_open() && exportStream(ofs); -} - -// virtual -bool LLWearable::exportStream( std::ostream& output_stream ) const -{ - if (!output_stream.good()) return false; - - // header and version - output_stream << "LLWearable version " << mDefinitionVersion << "\n"; - // name - output_stream << mName << "\n"; - // description - output_stream << mDescription << "\n"; - - // permissions - if( !mPermissions.exportLegacyStream( output_stream ) ) - { - return false; - } - - // sale info - if( !mSaleInfo.exportLegacyStream( output_stream ) ) - { - return false; - } - - // wearable type - output_stream << "type " << (S32) getType() << "\n"; - - // parameters - output_stream << "parameters " << mVisualParamIndexMap.size() << "\n"; - - for (const visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) - { - S32 param_id = vp_pair.first; - const LLVisualParam* param = vp_pair.second; - F32 param_weight = param->getWeight(); - output_stream << param_id << " " << terse_F32_to_string( param_weight ) << "\n"; - } - - // texture entries - output_stream << "textures " << mTEMap.size() << "\n"; - - for (const te_map_t::value_type& te_pair : mTEMap) - { - S32 te = te_pair.first; - const LLUUID& image_id = te_pair.second->getID(); - output_stream << te << " " << image_id << "\n"; - } - return true; -} - -void LLWearable::createVisualParams(LLAvatarAppearance *avatarp) -{ - for (LLViewerVisualParam* param = (LLViewerVisualParam*) avatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) avatarp->getNextVisualParam()) - { - if (param->getWearableType() == mType) - { - LLVisualParam *clone_param = param->cloneParam(this); - clone_param->setParamLocation(LOC_UNKNOWN); - clone_param->setParamLocation(LOC_WEARABLE); - addVisualParam(clone_param); - } - } - - // resync driver parameters to point to the newly cloned driven parameters - for (visual_param_index_map_t::value_type& param_pair : mVisualParamIndexMap) - { - LLVisualParam* param = param_pair.second; - LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; - // need this line to disambiguate between versions of LLCharacter::getVisualParam() - LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; - param->resetDrivenParams(); - if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) - { - if( !param->linkDrivenParams(boost::bind(param_function,avatarp,_1 ), true)) - { - LL_DEBUGS("Avatar") << "could not link driven params for wearable " << getName() << " id: " << param->getID() << LL_ENDL; - continue; - } - } - } -} - -void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) -{ - LLTexLayerSet *layer_set = NULL; - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); - if (texture_dict && texture_dict->mIsUsedByBakedTexture) - { - const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - - layer_set = avatarp->getAvatarLayerSet(baked_index); - } - - if (layer_set) - { - layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); - } - else - { - LL_WARNS() << "could not find layerset for LTO in wearable!" << LL_ENDL; - } -} - -LLWearable::EImportResult LLWearable::importFile(const std::string& filename, - LLAvatarAppearance* avatarp ) -{ - llifstream ifs(filename.c_str(), std::ios_base::in | std::ios_base::binary); - return (! ifs.is_open())? FAILURE : importStream(ifs, avatarp); -} - -// virtual -LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) -{ - // *NOTE: changing the type or size of this buffer will require - // changes in the fscanf() code below. - // We are using a local max buffer size here to avoid issues - // if MAX_STRING size changes. - const U32 PARSE_BUFFER_SIZE = 2048; - char buffer[PARSE_BUFFER_SIZE]; /* Flawfinder: ignore */ - char uuid_buffer[37]; /* Flawfinder: ignore */ - - // This data is being generated on the viewer. - // Impose some sane limits on parameter and texture counts. - const S32 MAX_WEARABLE_ASSET_TEXTURES = 100; - const S32 MAX_WEARABLE_ASSET_PARAMETERS = 1000; - - if(!avatarp) - { - return LLWearable::FAILURE; - } - - // read header and version - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Failed to read wearable asset input stream." << LL_ENDL; - return LLWearable::FAILURE; - } - if ( 1 != sscanf( /* Flawfinder: ignore */ - buffer, - "LLWearable version %d\n", - &mDefinitionVersion ) ) - { - return LLWearable::BAD_HEADER; - } - - // Hack to allow wearables with definition version 24 to still load. - // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 - // the extra check for version == 24 can be removed before release, once internal testers - // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that - // these wearables get re-saved with version definition 22. - if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) - { - LL_WARNS() << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << LL_ENDL; - return LLWearable::FAILURE; - } - - // name may be empty - if (!input_stream.good()) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading name" << LL_ENDL; - return LLWearable::FAILURE; - } - input_stream.getline(buffer, PARSE_BUFFER_SIZE); - mName = buffer; - - // description may be empty - if (!input_stream.good()) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading description" << LL_ENDL; - return LLWearable::FAILURE; - } - input_stream.getline(buffer, PARSE_BUFFER_SIZE); - mDescription = buffer; - - // permissions may have extra empty lines before the correct line - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading permissions" << LL_ENDL; - return LLWearable::FAILURE; - } - S32 perm_version = -1; - if ( 1 != sscanf( buffer, " permissions %d\n", &perm_version ) || - perm_version != 0 ) - { - LL_WARNS() << "Bad Wearable asset: missing valid permissions" << LL_ENDL; - return LLWearable::FAILURE; - } - if( !mPermissions.importLegacyStream( input_stream ) ) - { - return LLWearable::FAILURE; - } - - // sale info - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading sale info" << LL_ENDL; - return LLWearable::FAILURE; - } - S32 sale_info_version = -1; - if ( 1 != sscanf( buffer, " sale_info %d\n", &sale_info_version ) || - sale_info_version != 0 ) - { - LL_WARNS() << "Bad Wearable asset: missing valid sale_info" << LL_ENDL; - return LLWearable::FAILURE; - } - // Sale info used to contain next owner perm. It is now in the - // permissions. Thus, we read that out, and fix legacy - // objects. It's possible this op would fail, but it should pick - // up the vast majority of the tasks. - bool has_perm_mask = false; - U32 perm_mask = 0; - if( !mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask) ) - { - return LLWearable::FAILURE; - } - if(has_perm_mask) - { - // fair use fix. - if(!(perm_mask & PERM_COPY)) - { - perm_mask |= PERM_TRANSFER; - } - mPermissions.setMaskNext(perm_mask); - } - - // wearable type - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading type" << LL_ENDL; - return LLWearable::FAILURE; - } - S32 type = -1; - if ( 1 != sscanf( buffer, "type %d\n", &type ) ) - { - LL_WARNS() << "Bad Wearable asset: bad type" << LL_ENDL; - return LLWearable::FAILURE; - } - if( 0 <= type && type < LLWearableType::WT_COUNT ) - { - setType((LLWearableType::EType)type, avatarp); - } - else - { - mType = LLWearableType::WT_COUNT; - LL_WARNS() << "Bad Wearable asset: bad type #" << type << LL_ENDL; - return LLWearable::FAILURE; - } - - // parameters header - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading parameters header" << LL_ENDL; - return LLWearable::FAILURE; - } - S32 num_parameters = -1; - if ( 1 != sscanf( buffer, "parameters %d\n", &num_parameters ) ) - { - LL_WARNS() << "Bad Wearable asset: missing parameters block" << LL_ENDL; - return LLWearable::FAILURE; - } - if ( num_parameters > MAX_WEARABLE_ASSET_PARAMETERS ) - { - LL_WARNS() << "Bad Wearable asset: too many parameters, " - << num_parameters << LL_ENDL; - return LLWearable::FAILURE; - } - if( num_parameters != mVisualParamIndexMap.size() ) - { - LL_WARNS() << "Wearable parameter mismatch. Reading in " - << num_parameters << " from file, but created " - << mVisualParamIndexMap.size() - << " from avatar parameters. type: " - << getType() << LL_ENDL; - } - - // parameters - S32 i; - for( i = 0; i < num_parameters; i++ ) - { - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading parameter #" << i << LL_ENDL; - return LLWearable::FAILURE; - } - S32 param_id = 0; - F32 param_weight = 0.f; - if ( 2 != sscanf( buffer, "%d %f\n", ¶m_id, ¶m_weight ) ) - { - LL_WARNS() << "Bad Wearable asset: bad parameter, #" << i << LL_ENDL; - return LLWearable::FAILURE; - } - mSavedVisualParamMap[param_id] = param_weight; - } - - // textures header - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading textures header" << i << LL_ENDL; - return LLWearable::FAILURE; - } - S32 num_textures = -1; - if ( 1 != sscanf( buffer, "textures %d\n", &num_textures) ) - { - LL_WARNS() << "Bad Wearable asset: missing textures block" << LL_ENDL; - return LLWearable::FAILURE; - } - if ( num_textures > MAX_WEARABLE_ASSET_TEXTURES ) - { - LL_WARNS() << "Bad Wearable asset: too many textures, " - << num_textures << LL_ENDL; - return LLWearable::FAILURE; - } - - // textures - for( i = 0; i < num_textures; i++ ) - { - if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) - { - LL_WARNS() << "Bad Wearable asset: early end of input stream " - << "while reading textures #" << i << LL_ENDL; - return LLWearable::FAILURE; - } - S32 te = 0; - if ( 2 != sscanf( /* Flawfinder: ignore */ - buffer, - "%d %36s\n", - &te, uuid_buffer) ) - { - LL_WARNS() << "Bad Wearable asset: bad texture, #" << i << LL_ENDL; - return LLWearable::FAILURE; - } - - if (te >= ETextureIndex::TEX_NUM_INDICES) //createLayers() converts to ETextureIndex - { - LL_WARNS() << "Bad Wearable asset: bad texture index: " << te << LL_ENDL; - return LLWearable::FAILURE; - } - - if( !LLUUID::validate( uuid_buffer ) ) - { - LL_WARNS() << "Bad Wearable asset: bad texture uuid: " - << uuid_buffer << LL_ENDL; - return LLWearable::FAILURE; - } - LLUUID id = LLUUID(uuid_buffer); - LLGLTexture* image = gTextureManagerBridgep->getFetchedTexture( id ); - if( mTEMap.find(te) != mTEMap.end() ) - { - delete mTEMap[te]; - } - if( mSavedTEMap.find(te) != mSavedTEMap.end() ) - { - delete mSavedTEMap[te]; - } - - LLUUID textureid(uuid_buffer); - mTEMap[te] = new LLLocalTextureObject(image, textureid); - mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); - createLayers(te, avatarp); - } - - // copy all saved param values to working params - revertValues(); - - return LLWearable::SUCCESS; -} - -bool LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size) -{ - if (!input_stream.good()) - { - return false; - } - - do - { - input_stream.getline(buffer, buffer_size); - } - while (input_stream.good() && buffer[0]=='\0'); - - return (buffer[0] != '\0'); -} - - -void LLWearable::setType(LLWearableType::EType type, LLAvatarAppearance *avatarp) -{ - mType = type; - createVisualParams(avatarp); -} - - -LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) -{ - te_map_t::iterator iter = mTEMap.find(index); - if( iter != mTEMap.end() ) - { - LLLocalTextureObject* lto = iter->second; - return lto; - } - return NULL; -} - -const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const -{ - te_map_t::const_iterator iter = mTEMap.find(index); - if( iter != mTEMap.end() ) - { - const LLLocalTextureObject* lto = iter->second; - return lto; - } - return NULL; -} - -std::vector LLWearable::getLocalTextureListSeq() -{ - std::vector result; - - for(te_map_t::value_type& te_pair : mTEMap) - { - LLLocalTextureObject* lto = te_pair.second; - result.push_back(lto); - } - - return result; -} - -void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) -{ - if( mTEMap.find(index) != mTEMap.end() ) - { - mTEMap.erase(index); - } - mTEMap[index] = new LLLocalTextureObject(lto); -} - -void LLWearable::revertValues() -{ - // FIXME DRANO - this triggers changes to driven params on avatar, potentially clobbering baked appearance. - - //update saved settings so wearable is no longer dirty - // One loop should be necessary here - for (param_map_t::value_type& vp_pair : mSavedVisualParamMap) - { - S32 id = vp_pair.first; - LLVisualParam *param = getVisualParam(id); - if(param) - { - F32 value = vp_pair.second; - param->setWeight(value); - mSavedVisualParamMap[id] = param->getWeight(); - } - } - - syncImages(mSavedTEMap, mTEMap); -} - -void LLWearable::saveValues() -{ - //update saved settings so wearable is no longer dirty - mSavedVisualParamMap.clear(); - for (const visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) - { - S32 id = vp_pair.first; - LLVisualParam *wearable_param = vp_pair.second; - F32 value = wearable_param->getWeight(); - mSavedVisualParamMap[id] = value; - } - - // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) - syncImages(mTEMap, mSavedTEMap); -} - -void LLWearable::syncImages(te_map_t &src, te_map_t &dst) -{ - // Deep copy of src (copies only those tes that are current, filling in defaults where needed) - for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) - { - if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex) te) == mType) - { - te_map_t::const_iterator iter = src.find(te); - LLUUID image_id; - LLGLTexture *image = NULL; - LLLocalTextureObject *lto = NULL; - if(iter != src.end()) - { - // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. - lto = iter->second; - image = lto->getImage(); - image_id = lto->getID(); - } - else - { - // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. - image_id = getDefaultTextureImageID((ETextureIndex) te); - image = gTextureManagerBridgep->getFetchedTexture( image_id ); - } - - if( dst.find(te) != dst.end() ) - { - // there's already an entry in the destination map for the texture. Just update its values. - dst[te]->setImage(image); - dst[te]->setID(image_id); - } - else - { - // no entry found in the destination map, we need to create a new Local Texture Object - dst[te] = new LLLocalTextureObject(image, image_id); - } - - if( lto ) - { - // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. - dst[te]->setBakedReady(lto->getBakedReady()); - dst[te]->setDiscard(lto->getDiscard()); - } - } - } -} - -void LLWearable::destroyTextures() -{ - std::for_each(mTEMap.begin(), mTEMap.end(), DeletePairedPointer()); - mTEMap.clear(); - - std::for_each(mSavedTEMap.begin(), mSavedTEMap.end(), DeletePairedPointer()); - mSavedTEMap.clear(); -} - -void LLWearable::addVisualParam(LLVisualParam *param) -{ - if( mVisualParamIndexMap[param->getID()] ) - { - delete mVisualParamIndexMap[param->getID()]; - } - param->setIsDummy(false); - param->setParamLocation(LOC_WEARABLE); - mVisualParamIndexMap[param->getID()] = param; - mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); -} - - -void LLWearable::setVisualParamWeight(S32 param_index, F32 value) -{ - if( is_in_map(mVisualParamIndexMap, param_index ) ) - { - LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; - wearable_param->setWeight(value); - } - else - { - LL_ERRS() << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; - } -} - -F32 LLWearable::getVisualParamWeight(S32 param_index) const -{ - if( is_in_map(mVisualParamIndexMap, param_index ) ) - { - const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; - return wearable_param->getWeight(); - } - else - { - LL_WARNS() << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; - } - return (F32)-1.0; -} - -LLVisualParam* LLWearable::getVisualParam(S32 index) const -{ - visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); - return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; -} - - -void LLWearable::getVisualParams(visual_param_vec_t &list) -{ - // add all visual params to the passed-in vector - for(visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) - { - list.push_back(vp_pair.second); - } -} - -void LLWearable::animateParams(F32 delta) -{ - for(visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) - { - LLVisualParam *param = (LLVisualParam*)vp_pair.second; - param->animate(delta); - } -} - -LLColor4 LLWearable::getClothesColor(S32 te) const -{ - LLColor4 color; - U32 param_name[3]; - if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) - { - for( U8 index = 0; index < 3; index++ ) - { - color.mV[index] = getVisualParamWeight(param_name[index]); - } - } - return color; -} - -void LLWearable::setClothesColor( S32 te, const LLColor4& new_color) -{ - U32 param_name[3]; - if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) - { - for( U8 index = 0; index < 3; index++ ) - { - setVisualParamWeight(param_name[index], new_color.mV[index]); - } - } -} - -void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) -{ - if (!avatarp) return; - - // Pull params - for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) - { - // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the - // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. - if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) - { - S32 param_id = param->getID(); - F32 weight = getVisualParamWeight(param_id); - - avatarp->setVisualParamWeight( param_id, weight); - } - } -} - - -std::string terse_F32_to_string(F32 f) -{ - std::string r = llformat("%.2f", f); - S32 len = r.length(); - - // "1.20" -> "1.2" - // "24.00" -> "24." - while (len > 0 && ('0' == r[len - 1])) - { - r.erase(len-1, 1); - len--; - } - if ('.' == r[len - 1]) - { - // "24." -> "24" - r.erase(len-1, 1); - } - else if (('-' == r[0]) && ('0' == r[1])) - { - // "-0.59" -> "-.59" - r.erase(1, 1); - } - else if ('0' == r[0]) - { - // "0.59" -> ".59" - r.erase(0, 1); - } - return r; -} - +/** + * @file llwearable.cpp + * @brief LLWearable class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "lllocaltextureobject.h" +#include "lltexlayer.h" +#include "lltexturemanagerbridge.h" +#include "llvisualparam.h" +#include "llavatarappearancedefines.h" +#include "llwearable.h" +#include "boost/bind.hpp" + +using namespace LLAvatarAppearanceDefines; + +// static +S32 LLWearable::sCurrentDefinitionVersion = 1; + +// Private local functions +static std::string terse_F32_to_string(F32 f); + +LLWearable::LLWearable() + : mDefinitionVersion(-1), + mName(), + mDescription(), + mPermissions(), + mSaleInfo(), + mType(LLWearableType::WT_NONE), + mSavedVisualParamMap(), + mVisualParamIndexMap(), + mTEMap(), + mSavedTEMap() +{ +} + +// virtual +LLWearable::~LLWearable() +{ + for (visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) + { + LLVisualParam* vp = vp_pair.second; + vp->clearNextParam(); + delete vp; + vp_pair.second = NULL; + } + + destroyTextures(); +} + +const std::string& LLWearable::getTypeLabel() const +{ + return LLWearableType::getInstance()->getTypeLabel(mType); +} + +const std::string& LLWearable::getTypeName() const +{ + return LLWearableType::getInstance()->getTypeName(mType); +} + +LLAssetType::EType LLWearable::getAssetType() const +{ + return LLWearableType::getInstance()->getAssetType(mType); +} + +bool LLWearable::exportFile(const std::string& filename) const +{ + llofstream ofs(filename.c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary); + return ofs.is_open() && exportStream(ofs); +} + +// virtual +bool LLWearable::exportStream( std::ostream& output_stream ) const +{ + if (!output_stream.good()) return false; + + // header and version + output_stream << "LLWearable version " << mDefinitionVersion << "\n"; + // name + output_stream << mName << "\n"; + // description + output_stream << mDescription << "\n"; + + // permissions + if( !mPermissions.exportLegacyStream( output_stream ) ) + { + return false; + } + + // sale info + if( !mSaleInfo.exportLegacyStream( output_stream ) ) + { + return false; + } + + // wearable type + output_stream << "type " << (S32) getType() << "\n"; + + // parameters + output_stream << "parameters " << mVisualParamIndexMap.size() << "\n"; + + for (const visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) + { + S32 param_id = vp_pair.first; + const LLVisualParam* param = vp_pair.second; + F32 param_weight = param->getWeight(); + output_stream << param_id << " " << terse_F32_to_string( param_weight ) << "\n"; + } + + // texture entries + output_stream << "textures " << mTEMap.size() << "\n"; + + for (const te_map_t::value_type& te_pair : mTEMap) + { + S32 te = te_pair.first; + const LLUUID& image_id = te_pair.second->getID(); + output_stream << te << " " << image_id << "\n"; + } + return true; +} + +void LLWearable::createVisualParams(LLAvatarAppearance *avatarp) +{ + for (LLViewerVisualParam* param = (LLViewerVisualParam*) avatarp->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) avatarp->getNextVisualParam()) + { + if (param->getWearableType() == mType) + { + LLVisualParam *clone_param = param->cloneParam(this); + clone_param->setParamLocation(LOC_UNKNOWN); + clone_param->setParamLocation(LOC_WEARABLE); + addVisualParam(clone_param); + } + } + + // resync driver parameters to point to the newly cloned driven parameters + for (visual_param_index_map_t::value_type& param_pair : mVisualParamIndexMap) + { + LLVisualParam* param = param_pair.second; + LLVisualParam*(LLWearable::*wearable_function)(S32)const = &LLWearable::getVisualParam; + // need this line to disambiguate between versions of LLCharacter::getVisualParam() + LLVisualParam*(LLAvatarAppearance::*param_function)(S32)const = &LLAvatarAppearance::getVisualParam; + param->resetDrivenParams(); + if(!param->linkDrivenParams(boost::bind(wearable_function,(LLWearable*)this, _1), false)) + { + if( !param->linkDrivenParams(boost::bind(param_function,avatarp,_1 ), true)) + { + LL_DEBUGS("Avatar") << "could not link driven params for wearable " << getName() << " id: " << param->getID() << LL_ENDL; + continue; + } + } + } +} + +void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) +{ + LLTexLayerSet *layer_set = NULL; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); + if (texture_dict && texture_dict->mIsUsedByBakedTexture) + { + const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; + + layer_set = avatarp->getAvatarLayerSet(baked_index); + } + + if (layer_set) + { + layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); + } + else + { + LL_WARNS() << "could not find layerset for LTO in wearable!" << LL_ENDL; + } +} + +LLWearable::EImportResult LLWearable::importFile(const std::string& filename, + LLAvatarAppearance* avatarp ) +{ + llifstream ifs(filename.c_str(), std::ios_base::in | std::ios_base::binary); + return (! ifs.is_open())? FAILURE : importStream(ifs, avatarp); +} + +// virtual +LLWearable::EImportResult LLWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) +{ + // *NOTE: changing the type or size of this buffer will require + // changes in the fscanf() code below. + // We are using a local max buffer size here to avoid issues + // if MAX_STRING size changes. + const U32 PARSE_BUFFER_SIZE = 2048; + char buffer[PARSE_BUFFER_SIZE]; /* Flawfinder: ignore */ + char uuid_buffer[37]; /* Flawfinder: ignore */ + + // This data is being generated on the viewer. + // Impose some sane limits on parameter and texture counts. + const S32 MAX_WEARABLE_ASSET_TEXTURES = 100; + const S32 MAX_WEARABLE_ASSET_PARAMETERS = 1000; + + if(!avatarp) + { + return LLWearable::FAILURE; + } + + // read header and version + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Failed to read wearable asset input stream." << LL_ENDL; + return LLWearable::FAILURE; + } + if ( 1 != sscanf( /* Flawfinder: ignore */ + buffer, + "LLWearable version %d\n", + &mDefinitionVersion ) ) + { + return LLWearable::BAD_HEADER; + } + + // Hack to allow wearables with definition version 24 to still load. + // This should only affect lindens and NDA'd testers who have saved wearables in 2.0 + // the extra check for version == 24 can be removed before release, once internal testers + // have loaded these wearables again. See hack pt 2 at bottom of function to ensure that + // these wearables get re-saved with version definition 22. + if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) + { + LL_WARNS() << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << LL_ENDL; + return LLWearable::FAILURE; + } + + // name may be empty + if (!input_stream.good()) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading name" << LL_ENDL; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + mName = buffer; + + // description may be empty + if (!input_stream.good()) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading description" << LL_ENDL; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + mDescription = buffer; + + // permissions may have extra empty lines before the correct line + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading permissions" << LL_ENDL; + return LLWearable::FAILURE; + } + S32 perm_version = -1; + if ( 1 != sscanf( buffer, " permissions %d\n", &perm_version ) || + perm_version != 0 ) + { + LL_WARNS() << "Bad Wearable asset: missing valid permissions" << LL_ENDL; + return LLWearable::FAILURE; + } + if( !mPermissions.importLegacyStream( input_stream ) ) + { + return LLWearable::FAILURE; + } + + // sale info + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading sale info" << LL_ENDL; + return LLWearable::FAILURE; + } + S32 sale_info_version = -1; + if ( 1 != sscanf( buffer, " sale_info %d\n", &sale_info_version ) || + sale_info_version != 0 ) + { + LL_WARNS() << "Bad Wearable asset: missing valid sale_info" << LL_ENDL; + return LLWearable::FAILURE; + } + // Sale info used to contain next owner perm. It is now in the + // permissions. Thus, we read that out, and fix legacy + // objects. It's possible this op would fail, but it should pick + // up the vast majority of the tasks. + bool has_perm_mask = false; + U32 perm_mask = 0; + if( !mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask) ) + { + return LLWearable::FAILURE; + } + if(has_perm_mask) + { + // fair use fix. + if(!(perm_mask & PERM_COPY)) + { + perm_mask |= PERM_TRANSFER; + } + mPermissions.setMaskNext(perm_mask); + } + + // wearable type + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading type" << LL_ENDL; + return LLWearable::FAILURE; + } + S32 type = -1; + if ( 1 != sscanf( buffer, "type %d\n", &type ) ) + { + LL_WARNS() << "Bad Wearable asset: bad type" << LL_ENDL; + return LLWearable::FAILURE; + } + if( 0 <= type && type < LLWearableType::WT_COUNT ) + { + setType((LLWearableType::EType)type, avatarp); + } + else + { + mType = LLWearableType::WT_COUNT; + LL_WARNS() << "Bad Wearable asset: bad type #" << type << LL_ENDL; + return LLWearable::FAILURE; + } + + // parameters header + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading parameters header" << LL_ENDL; + return LLWearable::FAILURE; + } + S32 num_parameters = -1; + if ( 1 != sscanf( buffer, "parameters %d\n", &num_parameters ) ) + { + LL_WARNS() << "Bad Wearable asset: missing parameters block" << LL_ENDL; + return LLWearable::FAILURE; + } + if ( num_parameters > MAX_WEARABLE_ASSET_PARAMETERS ) + { + LL_WARNS() << "Bad Wearable asset: too many parameters, " + << num_parameters << LL_ENDL; + return LLWearable::FAILURE; + } + if( num_parameters != mVisualParamIndexMap.size() ) + { + LL_WARNS() << "Wearable parameter mismatch. Reading in " + << num_parameters << " from file, but created " + << mVisualParamIndexMap.size() + << " from avatar parameters. type: " + << getType() << LL_ENDL; + } + + // parameters + S32 i; + for( i = 0; i < num_parameters; i++ ) + { + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading parameter #" << i << LL_ENDL; + return LLWearable::FAILURE; + } + S32 param_id = 0; + F32 param_weight = 0.f; + if ( 2 != sscanf( buffer, "%d %f\n", ¶m_id, ¶m_weight ) ) + { + LL_WARNS() << "Bad Wearable asset: bad parameter, #" << i << LL_ENDL; + return LLWearable::FAILURE; + } + mSavedVisualParamMap[param_id] = param_weight; + } + + // textures header + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading textures header" << i << LL_ENDL; + return LLWearable::FAILURE; + } + S32 num_textures = -1; + if ( 1 != sscanf( buffer, "textures %d\n", &num_textures) ) + { + LL_WARNS() << "Bad Wearable asset: missing textures block" << LL_ENDL; + return LLWearable::FAILURE; + } + if ( num_textures > MAX_WEARABLE_ASSET_TEXTURES ) + { + LL_WARNS() << "Bad Wearable asset: too many textures, " + << num_textures << LL_ENDL; + return LLWearable::FAILURE; + } + + // textures + for( i = 0; i < num_textures; i++ ) + { + if (!getNextPopulatedLine(input_stream, buffer, PARSE_BUFFER_SIZE)) + { + LL_WARNS() << "Bad Wearable asset: early end of input stream " + << "while reading textures #" << i << LL_ENDL; + return LLWearable::FAILURE; + } + S32 te = 0; + if ( 2 != sscanf( /* Flawfinder: ignore */ + buffer, + "%d %36s\n", + &te, uuid_buffer) ) + { + LL_WARNS() << "Bad Wearable asset: bad texture, #" << i << LL_ENDL; + return LLWearable::FAILURE; + } + + if (te >= ETextureIndex::TEX_NUM_INDICES) //createLayers() converts to ETextureIndex + { + LL_WARNS() << "Bad Wearable asset: bad texture index: " << te << LL_ENDL; + return LLWearable::FAILURE; + } + + if( !LLUUID::validate( uuid_buffer ) ) + { + LL_WARNS() << "Bad Wearable asset: bad texture uuid: " + << uuid_buffer << LL_ENDL; + return LLWearable::FAILURE; + } + LLUUID id = LLUUID(uuid_buffer); + LLGLTexture* image = gTextureManagerBridgep->getFetchedTexture( id ); + if( mTEMap.find(te) != mTEMap.end() ) + { + delete mTEMap[te]; + } + if( mSavedTEMap.find(te) != mSavedTEMap.end() ) + { + delete mSavedTEMap[te]; + } + + LLUUID textureid(uuid_buffer); + mTEMap[te] = new LLLocalTextureObject(image, textureid); + mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); + createLayers(te, avatarp); + } + + // copy all saved param values to working params + revertValues(); + + return LLWearable::SUCCESS; +} + +bool LLWearable::getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size) +{ + if (!input_stream.good()) + { + return false; + } + + do + { + input_stream.getline(buffer, buffer_size); + } + while (input_stream.good() && buffer[0]=='\0'); + + return (buffer[0] != '\0'); +} + + +void LLWearable::setType(LLWearableType::EType type, LLAvatarAppearance *avatarp) +{ + mType = type; + createVisualParams(avatarp); +} + + +LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) +{ + te_map_t::iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +const LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const +{ + te_map_t::const_iterator iter = mTEMap.find(index); + if( iter != mTEMap.end() ) + { + const LLLocalTextureObject* lto = iter->second; + return lto; + } + return NULL; +} + +std::vector LLWearable::getLocalTextureListSeq() +{ + std::vector result; + + for(te_map_t::value_type& te_pair : mTEMap) + { + LLLocalTextureObject* lto = te_pair.second; + result.push_back(lto); + } + + return result; +} + +void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) +{ + if( mTEMap.find(index) != mTEMap.end() ) + { + mTEMap.erase(index); + } + mTEMap[index] = new LLLocalTextureObject(lto); +} + +void LLWearable::revertValues() +{ + // FIXME DRANO - this triggers changes to driven params on avatar, potentially clobbering baked appearance. + + //update saved settings so wearable is no longer dirty + // One loop should be necessary here + for (param_map_t::value_type& vp_pair : mSavedVisualParamMap) + { + S32 id = vp_pair.first; + LLVisualParam *param = getVisualParam(id); + if(param) + { + F32 value = vp_pair.second; + param->setWeight(value); + mSavedVisualParamMap[id] = param->getWeight(); + } + } + + syncImages(mSavedTEMap, mTEMap); +} + +void LLWearable::saveValues() +{ + //update saved settings so wearable is no longer dirty + mSavedVisualParamMap.clear(); + for (const visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) + { + S32 id = vp_pair.first; + LLVisualParam *wearable_param = vp_pair.second; + F32 value = wearable_param->getWeight(); + mSavedVisualParamMap[id] = value; + } + + // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed) + syncImages(mTEMap, mSavedTEMap); +} + +void LLWearable::syncImages(te_map_t &src, te_map_t &dst) +{ + // Deep copy of src (copies only those tes that are current, filling in defaults where needed) + for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) + { + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex) te) == mType) + { + te_map_t::const_iterator iter = src.find(te); + LLUUID image_id; + LLGLTexture *image = NULL; + LLLocalTextureObject *lto = NULL; + if(iter != src.end()) + { + // there's a Local Texture Object in the source image map. Use this to populate the values to store in the destination image map. + lto = iter->second; + image = lto->getImage(); + image_id = lto->getID(); + } + else + { + // there is no Local Texture Object in the source image map. Get defaults values for populating the destination image map. + image_id = getDefaultTextureImageID((ETextureIndex) te); + image = gTextureManagerBridgep->getFetchedTexture( image_id ); + } + + if( dst.find(te) != dst.end() ) + { + // there's already an entry in the destination map for the texture. Just update its values. + dst[te]->setImage(image); + dst[te]->setID(image_id); + } + else + { + // no entry found in the destination map, we need to create a new Local Texture Object + dst[te] = new LLLocalTextureObject(image, image_id); + } + + if( lto ) + { + // If we pulled values from a Local Texture Object in the source map, make sure the proper flags are set in the new (or updated) entry in the destination map. + dst[te]->setBakedReady(lto->getBakedReady()); + dst[te]->setDiscard(lto->getDiscard()); + } + } + } +} + +void LLWearable::destroyTextures() +{ + std::for_each(mTEMap.begin(), mTEMap.end(), DeletePairedPointer()); + mTEMap.clear(); + + std::for_each(mSavedTEMap.begin(), mSavedTEMap.end(), DeletePairedPointer()); + mSavedTEMap.clear(); +} + +void LLWearable::addVisualParam(LLVisualParam *param) +{ + if( mVisualParamIndexMap[param->getID()] ) + { + delete mVisualParamIndexMap[param->getID()]; + } + param->setIsDummy(false); + param->setParamLocation(LOC_WEARABLE); + mVisualParamIndexMap[param->getID()] = param; + mSavedVisualParamMap[param->getID()] = param->getDefaultWeight(); +} + + +void LLWearable::setVisualParamWeight(S32 param_index, F32 value) +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + wearable_param->setWeight(value); + } + else + { + LL_ERRS() << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; + } +} + +F32 LLWearable::getVisualParamWeight(S32 param_index) const +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; + return wearable_param->getWeight(); + } + else + { + LL_WARNS() << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; + } + return (F32)-1.0; +} + +LLVisualParam* LLWearable::getVisualParam(S32 index) const +{ + visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); + return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; +} + + +void LLWearable::getVisualParams(visual_param_vec_t &list) +{ + // add all visual params to the passed-in vector + for(visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) + { + list.push_back(vp_pair.second); + } +} + +void LLWearable::animateParams(F32 delta) +{ + for(visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) + { + LLVisualParam *param = (LLVisualParam*)vp_pair.second; + param->animate(delta); + } +} + +LLColor4 LLWearable::getClothesColor(S32 te) const +{ + LLColor4 color; + U32 param_name[3]; + if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) + { + for( U8 index = 0; index < 3; index++ ) + { + color.mV[index] = getVisualParamWeight(param_name[index]); + } + } + return color; +} + +void LLWearable::setClothesColor( S32 te, const LLColor4& new_color) +{ + U32 param_name[3]; + if( LLAvatarAppearance::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) + { + for( U8 index = 0; index < 3; index++ ) + { + setVisualParamWeight(param_name[index], new_color.mV[index]); + } + } +} + +void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) +{ + if (!avatarp) return; + + // Pull params + for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + { + // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the + // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. + if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) + { + S32 param_id = param->getID(); + F32 weight = getVisualParamWeight(param_id); + + avatarp->setVisualParamWeight( param_id, weight); + } + } +} + + +std::string terse_F32_to_string(F32 f) +{ + std::string r = llformat("%.2f", f); + S32 len = r.length(); + + // "1.20" -> "1.2" + // "24.00" -> "24." + while (len > 0 && ('0' == r[len - 1])) + { + r.erase(len-1, 1); + len--; + } + if ('.' == r[len - 1]) + { + // "24." -> "24" + r.erase(len-1, 1); + } + else if (('-' == r[0]) && ('0' == r[1])) + { + // "-0.59" -> "-.59" + r.erase(1, 1); + } + else if ('0' == r[0]) + { + // "0.59" -> ".59" + r.erase(0, 1); + } + return r; +} + diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index 831b4bc07e..c76e836a46 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -1,138 +1,138 @@ -/** - * @file llwearable.h - * @brief LLWearable class header file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLWEARABLE_H -#define LL_LLWEARABLE_H - -#include "llavatarappearancedefines.h" -#include "llpermissions.h" -#include "llsaleinfo.h" -#include "llwearabletype.h" - -class LLVisualParam; -class LLTexGlobalColorInfo; -class LLTexGlobalColor; -class LLLocalTextureObject; -class LLAvatarAppearance; - -// Abstract class. -class LLWearable -{ - //-------------------------------------------------------------------- - // Constructors and destructors - //-------------------------------------------------------------------- -public: - LLWearable(); - virtual ~LLWearable(); - - //-------------------------------------------------------------------- - // Accessors - //-------------------------------------------------------------------- -public: - LLWearableType::EType getType() const { return mType; } - void setType(LLWearableType::EType type, LLAvatarAppearance *avatarp); - const std::string& getName() const { return mName; } - void setName(const std::string& name) { mName = name; } - const std::string& getDescription() const { return mDescription; } - void setDescription(const std::string& desc) { mDescription = desc; } - const LLPermissions& getPermissions() const { return mPermissions; } - void setPermissions(const LLPermissions& p) { mPermissions = p; } - const LLSaleInfo& getSaleInfo() const { return mSaleInfo; } - void setSaleInfo(const LLSaleInfo& info) { mSaleInfo = info; } - const std::string& getTypeLabel() const; - const std::string& getTypeName() const; - LLAssetType::EType getAssetType() const; - S32 getDefinitionVersion() const { return mDefinitionVersion; } - void setDefinitionVersion( S32 new_version ) { mDefinitionVersion = new_version; } - static S32 getCurrentDefinitionVersion() { return LLWearable::sCurrentDefinitionVersion; } - -public: - typedef std::vector visual_param_vec_t; - - virtual void writeToAvatar(LLAvatarAppearance* avatarp); - - enum EImportResult - { - FAILURE = 0, - SUCCESS, - BAD_HEADER - }; - bool exportFile(const std::string& filename) const; - EImportResult importFile(const std::string& filename, LLAvatarAppearance* avatarp ); - virtual bool exportStream( std::ostream& output_stream ) const; - virtual EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); - - static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } - virtual LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const = 0; - - LLLocalTextureObject* getLocalTextureObject(S32 index); - const LLLocalTextureObject* getLocalTextureObject(S32 index) const; - std::vector getLocalTextureListSeq(); - - void setLocalTextureObject(S32 index, LLLocalTextureObject <o); - void addVisualParam(LLVisualParam *param); - void setVisualParamWeight(S32 index, F32 value); - F32 getVisualParamWeight(S32 index) const; - LLVisualParam* getVisualParam(S32 index) const; - void getVisualParams(visual_param_vec_t &list); - void animateParams(F32 delta); - - LLColor4 getClothesColor(S32 te) const; - void setClothesColor( S32 te, const LLColor4& new_color); - - virtual void revertValues(); - virtual void saveValues(); - - // Something happened that requires the wearable to be updated (e.g. worn/unworn). - virtual void setUpdated() const = 0; - - typedef std::map visual_param_index_map_t; - visual_param_index_map_t mVisualParamIndexMap; - -protected: - typedef std::map te_map_t; - void syncImages(te_map_t &src, te_map_t &dst); - void destroyTextures(); - void createVisualParams(LLAvatarAppearance *avatarp); - void createLayers(S32 te, LLAvatarAppearance *avatarp); - bool getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size); - - static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. - S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created. - std::string mName; - std::string mDescription; - LLPermissions mPermissions; - LLSaleInfo mSaleInfo; - LLWearableType::EType mType; - - typedef std::map param_map_t; - param_map_t mSavedVisualParamMap; // last saved version of visual params - - te_map_t mTEMap; // maps TE to LocalTextureObject - te_map_t mSavedTEMap; // last saved version of TEMap -}; - -#endif // LL_LLWEARABLE_H +/** + * @file llwearable.h + * @brief LLWearable class header file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLWEARABLE_H +#define LL_LLWEARABLE_H + +#include "llavatarappearancedefines.h" +#include "llpermissions.h" +#include "llsaleinfo.h" +#include "llwearabletype.h" + +class LLVisualParam; +class LLTexGlobalColorInfo; +class LLTexGlobalColor; +class LLLocalTextureObject; +class LLAvatarAppearance; + +// Abstract class. +class LLWearable +{ + //-------------------------------------------------------------------- + // Constructors and destructors + //-------------------------------------------------------------------- +public: + LLWearable(); + virtual ~LLWearable(); + + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + LLWearableType::EType getType() const { return mType; } + void setType(LLWearableType::EType type, LLAvatarAppearance *avatarp); + const std::string& getName() const { return mName; } + void setName(const std::string& name) { mName = name; } + const std::string& getDescription() const { return mDescription; } + void setDescription(const std::string& desc) { mDescription = desc; } + const LLPermissions& getPermissions() const { return mPermissions; } + void setPermissions(const LLPermissions& p) { mPermissions = p; } + const LLSaleInfo& getSaleInfo() const { return mSaleInfo; } + void setSaleInfo(const LLSaleInfo& info) { mSaleInfo = info; } + const std::string& getTypeLabel() const; + const std::string& getTypeName() const; + LLAssetType::EType getAssetType() const; + S32 getDefinitionVersion() const { return mDefinitionVersion; } + void setDefinitionVersion( S32 new_version ) { mDefinitionVersion = new_version; } + static S32 getCurrentDefinitionVersion() { return LLWearable::sCurrentDefinitionVersion; } + +public: + typedef std::vector visual_param_vec_t; + + virtual void writeToAvatar(LLAvatarAppearance* avatarp); + + enum EImportResult + { + FAILURE = 0, + SUCCESS, + BAD_HEADER + }; + bool exportFile(const std::string& filename) const; + EImportResult importFile(const std::string& filename, LLAvatarAppearance* avatarp ); + virtual bool exportStream( std::ostream& output_stream ) const; + virtual EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); + + static void setCurrentDefinitionVersion( S32 version ) { LLWearable::sCurrentDefinitionVersion = version; } + virtual LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const = 0; + + LLLocalTextureObject* getLocalTextureObject(S32 index); + const LLLocalTextureObject* getLocalTextureObject(S32 index) const; + std::vector getLocalTextureListSeq(); + + void setLocalTextureObject(S32 index, LLLocalTextureObject <o); + void addVisualParam(LLVisualParam *param); + void setVisualParamWeight(S32 index, F32 value); + F32 getVisualParamWeight(S32 index) const; + LLVisualParam* getVisualParam(S32 index) const; + void getVisualParams(visual_param_vec_t &list); + void animateParams(F32 delta); + + LLColor4 getClothesColor(S32 te) const; + void setClothesColor( S32 te, const LLColor4& new_color); + + virtual void revertValues(); + virtual void saveValues(); + + // Something happened that requires the wearable to be updated (e.g. worn/unworn). + virtual void setUpdated() const = 0; + + typedef std::map visual_param_index_map_t; + visual_param_index_map_t mVisualParamIndexMap; + +protected: + typedef std::map te_map_t; + void syncImages(te_map_t &src, te_map_t &dst); + void destroyTextures(); + void createVisualParams(LLAvatarAppearance *avatarp); + void createLayers(S32 te, LLAvatarAppearance *avatarp); + bool getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size); + + static S32 sCurrentDefinitionVersion; // Depends on the current state of the avatar_lad.xml. + S32 mDefinitionVersion; // Depends on the state of the avatar_lad.xml when this asset was created. + std::string mName; + std::string mDescription; + LLPermissions mPermissions; + LLSaleInfo mSaleInfo; + LLWearableType::EType mType; + + typedef std::map param_map_t; + param_map_t mSavedVisualParamMap; // last saved version of visual params + + te_map_t mTEMap; // maps TE to LocalTextureObject + te_map_t mSavedTEMap; // last saved version of TEMap +}; + +#endif // LL_LLWEARABLE_H diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 04f29ecf27..a58138c434 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -1,344 +1,344 @@ -/** - * @file llwearabledata.cpp - * @brief LLWearableData class implementation - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llwearabledata.h" - -#include "llavatarappearance.h" -#include "llavatarappearancedefines.h" -#include "lldriverparam.h" - -LLWearableData::LLWearableData() : - mAvatarAppearance(NULL) -{ -} - -// virtual -LLWearableData::~LLWearableData() -{ -} - -using namespace LLAvatarAppearanceDefines; - -LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) -{ - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return NULL; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - return NULL; - } - else - { - return wearable_vec[index]; - } -} - -void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) -{ - LLWearable *old_wearable = getWearable(type,index); - if (!old_wearable) - { - pushWearable(type,wearable); - return; - } - - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - LL_WARNS() << "invalid type, type " << type << " index " << index << LL_ENDL; - return; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - LL_WARNS() << "invalid index, type " << type << " index " << index << LL_ENDL; - } - else - { - wearable_vec[index] = wearable; - old_wearable->setUpdated(); - const bool removed = false; - wearableUpdated(wearable, removed); - } -} - -void LLWearableData::pushWearable(const LLWearableType::EType type, - LLWearable *wearable, - bool trigger_updated /* = true */) -{ - if (wearable == NULL) - { - // no null wearables please! - LL_WARNS() << "Null wearable sent for type " << type << LL_ENDL; - } - if (canAddWearable(type)) - { - mWearableDatas[type].push_back(wearable); - if (trigger_updated) - { - const bool removed = false; - wearableUpdated(wearable, removed); - } - } -} - -// virtual -void LLWearableData::wearableUpdated(LLWearable *wearable, bool removed) -{ - wearable->setUpdated(); - if (!removed) - { - pullCrossWearableValues(wearable->getType()); - } -} - -void LLWearableData::eraseWearable(LLWearable *wearable) -{ - if (wearable == NULL) - { - // nothing to do here. move along. - return; - } - - const LLWearableType::EType type = wearable->getType(); - - U32 index; - if (getWearableIndex(wearable,index)) - { - eraseWearable(type, index); - } -} - -void LLWearableData::eraseWearable(const LLWearableType::EType type, U32 index) -{ - LLWearable *wearable = getWearable(type, index); - if (wearable) - { - mWearableDatas[type].erase(mWearableDatas[type].begin() + index); - const bool removed = true; - wearableUpdated(wearable, removed); - } -} - -void LLWearableData::clearWearableType(const LLWearableType::EType type) -{ - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return; - } - wearableentry_vec_t& wearable_vec = wearable_iter->second; - wearable_vec.clear(); -} - -bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b) -{ - wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return false; - } - - wearableentry_vec_t& wearable_vec = wearable_iter->second; - // removed 0 > index_a and index_b comparisions - can never be true - if (index_a >= wearable_vec.size()) return false; - if (index_b >= wearable_vec.size()) return false; - - LLWearable* wearable = wearable_vec[index_a]; - wearable_vec[index_a] = wearable_vec[index_b]; - wearable_vec[index_b] = wearable; - return true; -} - -void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type) -{ - llassert(mAvatarAppearance); - // scan through all of the avatar's visual parameters - for (LLViewerVisualParam* param = (LLViewerVisualParam*) mAvatarAppearance->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) mAvatarAppearance->getNextVisualParam()) - { - if( param ) - { - LLDriverParam *driver_param = dynamic_cast(param); - if(driver_param) - { - // parameter is a driver parameter, have it update its cross-driven params - driver_param->updateCrossDrivenParams(type); - } - } - } -} - - -bool LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const -{ - if (wearable == NULL) - { - return false; - } - - const LLWearableType::EType type = wearable->getType(); - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - LL_WARNS() << "tried to get wearable index with an invalid type!" << LL_ENDL; - return false; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - for(U32 index = 0; index < wearable_vec.size(); index++) - { - if (wearable_vec[index] == wearable) - { - index_found = index; - return true; - } - } - - return false; -} - -U32 LLWearableData::getClothingLayerCount() const -{ - U32 count = 0; - LLWearableType *wr_inst = LLWearableType::getInstance(); - for (S32 i = 0; i < LLWearableType::WT_COUNT; i++) - { - LLWearableType::EType type = (LLWearableType::EType)i; - if (wr_inst->getAssetType(type)==LLAssetType::AT_CLOTHING) - { - count += getWearableCount(type); - } - } - return count; -} - -bool LLWearableData::canAddWearable(const LLWearableType::EType type) const -{ - LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type); - if (a_type==LLAssetType::AT_CLOTHING) - { - return (getClothingLayerCount() < MAX_CLOTHING_LAYERS); - } - else if (a_type==LLAssetType::AT_BODYPART) - { - return (getWearableCount(type) < 1); - } - else - { - return false; - } -} - -bool LLWearableData::isOnTop(LLWearable* wearable) const -{ - if (!wearable) return false; - const LLWearableType::EType type = wearable->getType(); - return ( getTopWearable(type) == wearable ); -} - -const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) const -{ - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return NULL; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - if (index>=wearable_vec.size()) - { - return NULL; - } - else - { - return wearable_vec[index]; - } -} - -LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) -{ - U32 count = getWearableCount(type); - if ( count == 0) - { - return NULL; - } - - return getWearable(type, count-1); -} - -const LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) const -{ - U32 count = getWearableCount(type); - if ( count == 0) - { - return NULL; - } - - return getWearable(type, count-1); -} - -LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) -{ - if (getWearableCount(type) == 0) - { - return NULL; - } - - return getWearable(type, 0); -} - -const LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) const -{ - if (getWearableCount(type) == 0) - { - return NULL; - } - - return getWearable(type, 0); -} - -U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const -{ - wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); - if (wearable_iter == mWearableDatas.end()) - { - return 0; - } - const wearableentry_vec_t& wearable_vec = wearable_iter->second; - return wearable_vec.size(); -} - -U32 LLWearableData::getWearableCount(const U32 tex_index) const -{ - const LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); - return getWearableCount(wearable_type); -} +/** + * @file llwearabledata.cpp + * @brief LLWearableData class implementation + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llwearabledata.h" + +#include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "lldriverparam.h" + +LLWearableData::LLWearableData() : + mAvatarAppearance(NULL) +{ +} + +// virtual +LLWearableData::~LLWearableData() +{ +} + +using namespace LLAvatarAppearanceDefines; + +LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } +} + +void LLWearableData::setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable) +{ + LLWearable *old_wearable = getWearable(type,index); + if (!old_wearable) + { + pushWearable(type,wearable); + return; + } + + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + LL_WARNS() << "invalid type, type " << type << " index " << index << LL_ENDL; + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + LL_WARNS() << "invalid index, type " << type << " index " << index << LL_ENDL; + } + else + { + wearable_vec[index] = wearable; + old_wearable->setUpdated(); + const bool removed = false; + wearableUpdated(wearable, removed); + } +} + +void LLWearableData::pushWearable(const LLWearableType::EType type, + LLWearable *wearable, + bool trigger_updated /* = true */) +{ + if (wearable == NULL) + { + // no null wearables please! + LL_WARNS() << "Null wearable sent for type " << type << LL_ENDL; + } + if (canAddWearable(type)) + { + mWearableDatas[type].push_back(wearable); + if (trigger_updated) + { + const bool removed = false; + wearableUpdated(wearable, removed); + } + } +} + +// virtual +void LLWearableData::wearableUpdated(LLWearable *wearable, bool removed) +{ + wearable->setUpdated(); + if (!removed) + { + pullCrossWearableValues(wearable->getType()); + } +} + +void LLWearableData::eraseWearable(LLWearable *wearable) +{ + if (wearable == NULL) + { + // nothing to do here. move along. + return; + } + + const LLWearableType::EType type = wearable->getType(); + + U32 index; + if (getWearableIndex(wearable,index)) + { + eraseWearable(type, index); + } +} + +void LLWearableData::eraseWearable(const LLWearableType::EType type, U32 index) +{ + LLWearable *wearable = getWearable(type, index); + if (wearable) + { + mWearableDatas[type].erase(mWearableDatas[type].begin() + index); + const bool removed = true; + wearableUpdated(wearable, removed); + } +} + +void LLWearableData::clearWearableType(const LLWearableType::EType type) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return; + } + wearableentry_vec_t& wearable_vec = wearable_iter->second; + wearable_vec.clear(); +} + +bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b) +{ + wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return false; + } + + wearableentry_vec_t& wearable_vec = wearable_iter->second; + // removed 0 > index_a and index_b comparisions - can never be true + if (index_a >= wearable_vec.size()) return false; + if (index_b >= wearable_vec.size()) return false; + + LLWearable* wearable = wearable_vec[index_a]; + wearable_vec[index_a] = wearable_vec[index_b]; + wearable_vec[index_b] = wearable; + return true; +} + +void LLWearableData::pullCrossWearableValues(const LLWearableType::EType type) +{ + llassert(mAvatarAppearance); + // scan through all of the avatar's visual parameters + for (LLViewerVisualParam* param = (LLViewerVisualParam*) mAvatarAppearance->getFirstVisualParam(); + param; + param = (LLViewerVisualParam*) mAvatarAppearance->getNextVisualParam()) + { + if( param ) + { + LLDriverParam *driver_param = dynamic_cast(param); + if(driver_param) + { + // parameter is a driver parameter, have it update its cross-driven params + driver_param->updateCrossDrivenParams(type); + } + } + } +} + + +bool LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_found) const +{ + if (wearable == NULL) + { + return false; + } + + const LLWearableType::EType type = wearable->getType(); + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + LL_WARNS() << "tried to get wearable index with an invalid type!" << LL_ENDL; + return false; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + for(U32 index = 0; index < wearable_vec.size(); index++) + { + if (wearable_vec[index] == wearable) + { + index_found = index; + return true; + } + } + + return false; +} + +U32 LLWearableData::getClothingLayerCount() const +{ + U32 count = 0; + LLWearableType *wr_inst = LLWearableType::getInstance(); + for (S32 i = 0; i < LLWearableType::WT_COUNT; i++) + { + LLWearableType::EType type = (LLWearableType::EType)i; + if (wr_inst->getAssetType(type)==LLAssetType::AT_CLOTHING) + { + count += getWearableCount(type); + } + } + return count; +} + +bool LLWearableData::canAddWearable(const LLWearableType::EType type) const +{ + LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type); + if (a_type==LLAssetType::AT_CLOTHING) + { + return (getClothingLayerCount() < MAX_CLOTHING_LAYERS); + } + else if (a_type==LLAssetType::AT_BODYPART) + { + return (getWearableCount(type) < 1); + } + else + { + return false; + } +} + +bool LLWearableData::isOnTop(LLWearable* wearable) const +{ + if (!wearable) return false; + const LLWearableType::EType type = wearable->getType(); + return ( getTopWearable(type) == wearable ); +} + +const LLWearable* LLWearableData::getWearable(const LLWearableType::EType type, U32 index) const +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return NULL; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + if (index>=wearable_vec.size()) + { + return NULL; + } + else + { + return wearable_vec[index]; + } +} + +LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + +const LLWearable* LLWearableData::getTopWearable(const LLWearableType::EType type) const +{ + U32 count = getWearableCount(type); + if ( count == 0) + { + return NULL; + } + + return getWearable(type, count-1); +} + +LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) +{ + if (getWearableCount(type) == 0) + { + return NULL; + } + + return getWearable(type, 0); +} + +const LLWearable* LLWearableData::getBottomWearable(const LLWearableType::EType type) const +{ + if (getWearableCount(type) == 0) + { + return NULL; + } + + return getWearable(type, 0); +} + +U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const +{ + wearableentry_map_t::const_iterator wearable_iter = mWearableDatas.find(type); + if (wearable_iter == mWearableDatas.end()) + { + return 0; + } + const wearableentry_vec_t& wearable_vec = wearable_iter->second; + return wearable_vec.size(); +} + +U32 LLWearableData::getWearableCount(const U32 tex_index) const +{ + const LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index); + return getWearableCount(wearable_type); +} diff --git a/indra/llappearance/llwearabledata.h b/indra/llappearance/llwearabledata.h index 1396dda52c..1266aed008 100644 --- a/indra/llappearance/llwearabledata.h +++ b/indra/llappearance/llwearabledata.h @@ -1,102 +1,102 @@ -/** - * @file llwearabledata.h - * @brief LLWearableData class header file - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_WEARABLEDATA_H -#define LL_WEARABLEDATA_H - -#include "llavatarappearancedefines.h" -#include "llwearable.h" -#include "llerror.h" - -class LLAvatarAppearance; - -class LLWearableData -{ - // *TODO: Figure out why this is causing compile error. - //LOG_CLASS(LLWearableData); - - //-------------------------------------------------------------------- - // Constructors / destructors / Initializers - //-------------------------------------------------------------------- -public: - LLWearableData(); - virtual ~LLWearableData(); - - void setAvatarAppearance(LLAvatarAppearance* appearance) { mAvatarAppearance = appearance; } - -protected: - //-------------------------------------------------------------------- - // Accessors - //-------------------------------------------------------------------- -public: - LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); - const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; - LLWearable* getTopWearable(const LLWearableType::EType type); - const LLWearable* getTopWearable(const LLWearableType::EType type) const; - LLWearable* getBottomWearable(const LLWearableType::EType type); - const LLWearable* getBottomWearable(const LLWearableType::EType type) const; - U32 getWearableCount(const LLWearableType::EType type) const; - U32 getWearableCount(const U32 tex_index) const; - bool getWearableIndex(const LLWearable *wearable, U32& index) const; - U32 getClothingLayerCount() const; - bool canAddWearable(const LLWearableType::EType type) const; - - bool isOnTop(LLWearable* wearable) const; - - static const U32 MAX_CLOTHING_LAYERS = 60; - - //-------------------------------------------------------------------- - // Setters - //-------------------------------------------------------------------- -protected: - // Low-level data structure setter - public access is via setWearableItem, etc. - void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); - void pushWearable(const LLWearableType::EType type, LLWearable *wearable, - bool trigger_updated = true); - virtual void wearableUpdated(LLWearable *wearable, bool removed); - void eraseWearable(LLWearable *wearable); - void eraseWearable(const LLWearableType::EType type, U32 index); - void clearWearableType(const LLWearableType::EType type); - bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b); - -private: - void pullCrossWearableValues(const LLWearableType::EType type); - - //-------------------------------------------------------------------- - // Member variables - //-------------------------------------------------------------------- -protected: - LLAvatarAppearance* mAvatarAppearance; - typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) - typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type - wearableentry_map_t mWearableDatas; - -}; - - - -#endif // LL_WEARABLEDATA_H - +/** + * @file llwearabledata.h + * @brief LLWearableData class header file + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_WEARABLEDATA_H +#define LL_WEARABLEDATA_H + +#include "llavatarappearancedefines.h" +#include "llwearable.h" +#include "llerror.h" + +class LLAvatarAppearance; + +class LLWearableData +{ + // *TODO: Figure out why this is causing compile error. + //LOG_CLASS(LLWearableData); + + //-------------------------------------------------------------------- + // Constructors / destructors / Initializers + //-------------------------------------------------------------------- +public: + LLWearableData(); + virtual ~LLWearableData(); + + void setAvatarAppearance(LLAvatarAppearance* appearance) { mAvatarAppearance = appearance; } + +protected: + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- +public: + LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/); + const LLWearable* getWearable(const LLWearableType::EType type, U32 index /*= 0*/) const; + LLWearable* getTopWearable(const LLWearableType::EType type); + const LLWearable* getTopWearable(const LLWearableType::EType type) const; + LLWearable* getBottomWearable(const LLWearableType::EType type); + const LLWearable* getBottomWearable(const LLWearableType::EType type) const; + U32 getWearableCount(const LLWearableType::EType type) const; + U32 getWearableCount(const U32 tex_index) const; + bool getWearableIndex(const LLWearable *wearable, U32& index) const; + U32 getClothingLayerCount() const; + bool canAddWearable(const LLWearableType::EType type) const; + + bool isOnTop(LLWearable* wearable) const; + + static const U32 MAX_CLOTHING_LAYERS = 60; + + //-------------------------------------------------------------------- + // Setters + //-------------------------------------------------------------------- +protected: + // Low-level data structure setter - public access is via setWearableItem, etc. + void setWearable(const LLWearableType::EType type, U32 index, LLWearable *wearable); + void pushWearable(const LLWearableType::EType type, LLWearable *wearable, + bool trigger_updated = true); + virtual void wearableUpdated(LLWearable *wearable, bool removed); + void eraseWearable(LLWearable *wearable); + void eraseWearable(const LLWearableType::EType type, U32 index); + void clearWearableType(const LLWearableType::EType type); + bool swapWearables(const LLWearableType::EType type, U32 index_a, U32 index_b); + +private: + void pullCrossWearableValues(const LLWearableType::EType type); + + //-------------------------------------------------------------------- + // Member variables + //-------------------------------------------------------------------- +protected: + LLAvatarAppearance* mAvatarAppearance; + typedef std::vector wearableentry_vec_t; // all wearables of a certain type (EG all shirts) + typedef std::map wearableentry_map_t; // wearable "categories" arranged by wearable type + wearableentry_map_t mWearableDatas; + +}; + + + +#endif // LL_WEARABLEDATA_H + diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 0e870232e8..988304cbac 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -1,134 +1,134 @@ -/** - * @file llwearabletype.cpp - * @brief LLWearableType class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llwearabletype.h" -#include "llinventorytype.h" -#include "llinventorydefines.h" - - -LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans) -{ - addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, false, false)); - addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, false, false)); - addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, false, false)); - addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, false, false)); - addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, false, true)); - addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, false, true)); - addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, false, true)); - addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, false, true)); - addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, false, true)); - addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, false, true)); - addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, false, true)); - addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, false, true)); - addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, false, true)); - addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, false, true)); - addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, false, true)); - addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, false, true)); - - addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, true, true)); - - addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, false, false)); - addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, false, false)); -} - - -// class LLWearableType - -LLWearableType::LLWearableType(LLTranslationBridge::ptr_t &trans) -: mDictionary(trans) -{ -} - -LLWearableType::~LLWearableType() -{ -} - -void LLWearableType::initSingleton() -{ -} - -LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name) -{ - const LLWearableType::EType wearable = mDictionary.lookup(type_name); - return wearable; -} - -const std::string& LLWearableType::getTypeName(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return getTypeName(WT_INVALID); - return entry->mName; -} - -const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return getTypeDefaultNewName(WT_INVALID); - return entry->mDefaultNewName; -} - -const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return getTypeLabel(WT_INVALID); - return entry->mLabel; -} - -LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return getAssetType(WT_INVALID); - return entry->mAssetType; -} - -LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return getIconName(WT_INVALID); - return entry->mIconName; -} - -bool LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return false; - return entry->mDisableCameraSwitch; -} - -bool LLWearableType::getAllowMultiwear(LLWearableType::EType type) -{ - const WearableEntry *entry = mDictionary.lookup(type); - if (!entry) return false; - return entry->mAllowMultiwear; -} - -// static -LLWearableType::EType LLWearableType::inventoryFlagsToWearableType(U32 flags) -{ - return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK); -} - +/** + * @file llwearabletype.cpp + * @brief LLWearableType class implementation + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llwearabletype.h" +#include "llinventorytype.h" +#include "llinventorydefines.h" + + +LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans) +{ + addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, false, false)); + addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, false, false)); + addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, false, false)); + addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, false, false)); + addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, false, true)); + addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, false, true)); + addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, false, true)); + addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, false, true)); + addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, false, true)); + addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, false, true)); + addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, false, true)); + addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, false, true)); + addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, false, true)); + addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, false, true)); + addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, false, true)); + addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, false, true)); + + addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, true, true)); + + addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, false, false)); + addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, false, false)); +} + + +// class LLWearableType + +LLWearableType::LLWearableType(LLTranslationBridge::ptr_t &trans) +: mDictionary(trans) +{ +} + +LLWearableType::~LLWearableType() +{ +} + +void LLWearableType::initSingleton() +{ +} + +LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name) +{ + const LLWearableType::EType wearable = mDictionary.lookup(type_name); + return wearable; +} + +const std::string& LLWearableType::getTypeName(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return getTypeName(WT_INVALID); + return entry->mName; +} + +const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return getTypeDefaultNewName(WT_INVALID); + return entry->mDefaultNewName; +} + +const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return getTypeLabel(WT_INVALID); + return entry->mLabel; +} + +LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return getAssetType(WT_INVALID); + return entry->mAssetType; +} + +LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return getIconName(WT_INVALID); + return entry->mIconName; +} + +bool LLWearableType::getDisableCameraSwitch(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return false; + return entry->mDisableCameraSwitch; +} + +bool LLWearableType::getAllowMultiwear(LLWearableType::EType type) +{ + const WearableEntry *entry = mDictionary.lookup(type); + if (!entry) return false; + return entry->mAllowMultiwear; +} + +// static +LLWearableType::EType LLWearableType::inventoryFlagsToWearableType(U32 flags) +{ + return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK); +} + diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h index 10238994ba..206a344134 100644 --- a/indra/llappearance/llwearabletype.h +++ b/indra/llappearance/llwearabletype.h @@ -1,118 +1,118 @@ -/** - * @file llwearabletype.h - * @brief LLWearableType class header file - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLWEARABLETYPE_H -#define LL_LLWEARABLETYPE_H - -#include "llassettype.h" -#include "lldictionary.h" -#include "llinventorytype.h" -#include "llsingleton.h" -#include "llinvtranslationbrdg.h" - -class LLWearableType : public LLParamSingleton -{ - LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans); - ~LLWearableType(); - void initSingleton() override; -public: - enum EType - { - WT_SHAPE = 0, - WT_SKIN = 1, - WT_HAIR = 2, - WT_EYES = 3, - WT_SHIRT = 4, - WT_PANTS = 5, - WT_SHOES = 6, - WT_SOCKS = 7, - WT_JACKET = 8, - WT_GLOVES = 9, - WT_UNDERSHIRT = 10, - WT_UNDERPANTS = 11, - WT_SKIRT = 12, - WT_ALPHA = 13, - WT_TATTOO = 14, - WT_PHYSICS = 15, - WT_UNIVERSAL = 16, - WT_COUNT = 17, - - WT_INVALID = 255, - WT_NONE = -1, - }; - - // Most methods are wrappers for dictionary, but if LLWearableType is not initialized, - // they will crash. Whole LLWearableType is just wrapper for convinient calls. - const std::string& getTypeName(EType type); - const std::string& getTypeDefaultNewName(EType type); - const std::string& getTypeLabel(EType type); - LLAssetType::EType getAssetType(EType type); - EType typeNameToType(const std::string& type_name); - LLInventoryType::EIconName getIconName(EType type); - bool getDisableCameraSwitch(EType type); - bool getAllowMultiwear(EType type); - - static EType inventoryFlagsToWearableType(U32 flags); - -private: - struct WearableEntry : public LLDictionaryEntry - { - WearableEntry(LLTranslationBridge::ptr_t& trans, - const std::string &name, - const std::string& default_new_name, - LLAssetType::EType assetType, - LLInventoryType::EIconName iconName, - bool disable_camera_switch = false, - bool allow_multiwear = true) : - LLDictionaryEntry(name), - mAssetType(assetType), - mDefaultNewName(default_new_name), - mLabel(trans->getString(name)), - mIconName(iconName), - mDisableCameraSwitch(disable_camera_switch), - mAllowMultiwear(allow_multiwear) - { - - } - const LLAssetType::EType mAssetType; - const std::string mLabel; - const std::string mDefaultNewName; - LLInventoryType::EIconName mIconName; - bool mDisableCameraSwitch; - bool mAllowMultiwear; - }; - - class LLWearableDictionary : public LLDictionary - { - public: - LLWearableDictionary(LLTranslationBridge::ptr_t& trans); - ~LLWearableDictionary() {} - }; - - LLWearableDictionary mDictionary; -}; - -#endif // LL_LLWEARABLETYPE_H +/** + * @file llwearabletype.h + * @brief LLWearableType class header file + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLWEARABLETYPE_H +#define LL_LLWEARABLETYPE_H + +#include "llassettype.h" +#include "lldictionary.h" +#include "llinventorytype.h" +#include "llsingleton.h" +#include "llinvtranslationbrdg.h" + +class LLWearableType : public LLParamSingleton +{ + LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans); + ~LLWearableType(); + void initSingleton() override; +public: + enum EType + { + WT_SHAPE = 0, + WT_SKIN = 1, + WT_HAIR = 2, + WT_EYES = 3, + WT_SHIRT = 4, + WT_PANTS = 5, + WT_SHOES = 6, + WT_SOCKS = 7, + WT_JACKET = 8, + WT_GLOVES = 9, + WT_UNDERSHIRT = 10, + WT_UNDERPANTS = 11, + WT_SKIRT = 12, + WT_ALPHA = 13, + WT_TATTOO = 14, + WT_PHYSICS = 15, + WT_UNIVERSAL = 16, + WT_COUNT = 17, + + WT_INVALID = 255, + WT_NONE = -1, + }; + + // Most methods are wrappers for dictionary, but if LLWearableType is not initialized, + // they will crash. Whole LLWearableType is just wrapper for convinient calls. + const std::string& getTypeName(EType type); + const std::string& getTypeDefaultNewName(EType type); + const std::string& getTypeLabel(EType type); + LLAssetType::EType getAssetType(EType type); + EType typeNameToType(const std::string& type_name); + LLInventoryType::EIconName getIconName(EType type); + bool getDisableCameraSwitch(EType type); + bool getAllowMultiwear(EType type); + + static EType inventoryFlagsToWearableType(U32 flags); + +private: + struct WearableEntry : public LLDictionaryEntry + { + WearableEntry(LLTranslationBridge::ptr_t& trans, + const std::string &name, + const std::string& default_new_name, + LLAssetType::EType assetType, + LLInventoryType::EIconName iconName, + bool disable_camera_switch = false, + bool allow_multiwear = true) : + LLDictionaryEntry(name), + mAssetType(assetType), + mDefaultNewName(default_new_name), + mLabel(trans->getString(name)), + mIconName(iconName), + mDisableCameraSwitch(disable_camera_switch), + mAllowMultiwear(allow_multiwear) + { + + } + const LLAssetType::EType mAssetType; + const std::string mLabel; + const std::string mDefaultNewName; + LLInventoryType::EIconName mIconName; + bool mDisableCameraSwitch; + bool mAllowMultiwear; + }; + + class LLWearableDictionary : public LLDictionary + { + public: + LLWearableDictionary(LLTranslationBridge::ptr_t& trans); + ~LLWearableDictionary() {} + }; + + LLWearableDictionary mDictionary; +}; + +#endif // LL_LLWEARABLETYPE_H -- cgit v1.2.3 From cb3bd8865aa0f9fb8a247ea595cf1973057ba91f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 30 May 2024 15:41:36 +0200 Subject: Fix a bunch of uninitialized variable warnings that showed up in Visual Studio --- indra/llappearance/llavatarappearance.cpp | 14 +----- indra/llappearance/llavatarappearance.h | 72 +++++++++++++++---------------- indra/llappearance/lldriverparam.h | 6 +-- 3 files changed, 40 insertions(+), 52 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index f06845f084..743c1745d0 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -164,19 +164,7 @@ LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* LLAvatarAppearance::sAv LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) : LLCharacter(), - mIsDummy(false), - mTexSkinColor( NULL ), - mTexHairColor( NULL ), - mTexEyeColor( NULL ), - mPelvisToFoot(0.f), - mHeadOffset(), - mRoot(NULL), - mWearableData(wearable_data), - mNumBones(0), - mNumCollisionVolumes(0), - mCollisionVolumes(NULL), - mIsBuilt(false), - mInitFlags(0) + mWearableData(wearable_data) { llassert_always(mWearableData); mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES); diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index c2188d8ac9..1f33ae290e 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -70,7 +70,7 @@ public: static void initClass(); static void cleanupClass(); // Cleanup data that's only init'd once per class. virtual void initInstance(); // Called after construction to initialize the instance. - S32 mInitFlags; + S32 mInitFlags{ 0 }; virtual bool loadSkeletonNode(); bool loadMeshNodes(); bool loadLayersets(); @@ -135,8 +135,8 @@ public: F32 getPelvisToFoot() const { return mPelvisToFoot; } /*virtual*/ LLJoint* getRootJoint() { return mRoot; } - LLVector3 mHeadOffset; // current head position - LLAvatarJoint *mRoot; + LLVector3 mHeadOffset{}; // current head position + LLAvatarJoint* mRoot{ nullptr }; typedef std::map joint_map_t; joint_map_t mJointMap; @@ -167,7 +167,7 @@ protected: bool buildSkeleton(const LLAvatarSkeletonInfo *info); void clearSkeleton(); - bool mIsBuilt; // state of deferred character building + bool mIsBuilt{ false }; // state of deferred character building avatar_joint_list_t mSkeleton; LLVector3OverrideMap mPelvisFixups; joint_alias_map_t mJointAliasMap; @@ -184,30 +184,30 @@ public: LLVector3 mBodySize; LLVector3 mAvatarOffset; protected: - F32 mPelvisToFoot; + F32 mPelvisToFoot{ 0.f }; //-------------------------------------------------------------------- // Cached pointers to well known joints //-------------------------------------------------------------------- public: - LLJoint* mPelvisp; - LLJoint* mTorsop; - LLJoint* mChestp; - LLJoint* mNeckp; - LLJoint* mHeadp; - LLJoint* mSkullp; - LLJoint* mEyeLeftp; - LLJoint* mEyeRightp; - LLJoint* mHipLeftp; - LLJoint* mHipRightp; - LLJoint* mKneeLeftp; - LLJoint* mKneeRightp; - LLJoint* mAnkleLeftp; - LLJoint* mAnkleRightp; - LLJoint* mFootLeftp; - LLJoint* mFootRightp; - LLJoint* mWristLeftp; - LLJoint* mWristRightp; + LLJoint* mPelvisp{nullptr}; + LLJoint* mTorsop{ nullptr }; + LLJoint* mChestp{ nullptr }; + LLJoint* mNeckp{ nullptr }; + LLJoint* mHeadp{ nullptr }; + LLJoint* mSkullp{ nullptr }; + LLJoint* mEyeLeftp{ nullptr }; + LLJoint* mEyeRightp{ nullptr }; + LLJoint* mHipLeftp{ nullptr }; + LLJoint* mHipRightp{ nullptr }; + LLJoint* mKneeLeftp{ nullptr }; + LLJoint* mKneeRightp{ nullptr }; + LLJoint* mAnkleLeftp{ nullptr }; + LLJoint* mAnkleRightp{ nullptr }; + LLJoint* mFootLeftp{ nullptr }; + LLJoint* mFootRightp{ nullptr }; + LLJoint* mWristLeftp{ nullptr }; + LLJoint* mWristRightp{ nullptr }; //-------------------------------------------------------------------- // XML parse tree @@ -227,7 +227,7 @@ protected: ** RENDERING **/ public: - bool mIsDummy; // for special views and animated object controllers; local to viewer + bool mIsDummy{ false }; // for special views and animated object controllers; local to viewer //-------------------------------------------------------------------- // Morph masks @@ -290,9 +290,9 @@ public: LLColor4 getGlobalColor(const std::string& color_name ) const; virtual void onGlobalColorChanged(const LLTexGlobalColor* global_color) = 0; protected: - LLTexGlobalColor* mTexSkinColor; - LLTexGlobalColor* mTexHairColor; - LLTexGlobalColor* mTexEyeColor; + LLTexGlobalColor* mTexSkinColor{ nullptr }; + LLTexGlobalColor* mTexHairColor{ nullptr }; + LLTexGlobalColor* mTexEyeColor{ nullptr }; //-------------------------------------------------------------------- // Visibility @@ -315,7 +315,7 @@ public: virtual bool isWearingWearableType(LLWearableType::EType type ) const; private: - LLWearableData* mWearableData; + LLWearableData* mWearableData{ nullptr }; /******************************************************************************** ** ** @@ -333,11 +333,11 @@ protected: struct BakedTextureData { LLUUID mLastTextureID; - LLTexLayerSet* mTexLayerSet; // Only exists for self - bool mIsLoaded; - bool mIsUsed; - LLAvatarAppearanceDefines::ETextureIndex mTextureIndex; - U32 mMaskTexName; + LLTexLayerSet* mTexLayerSet{ nullptr }; // Only exists for self + bool mIsLoaded{ false }; + bool mIsUsed{ false }; + LLAvatarAppearanceDefines::ETextureIndex mTextureIndex{ LLAvatarAppearanceDefines::ETextureIndex::TEX_INVALID }; + U32 mMaskTexName{ 0 }; // Stores pointers to the joint meshes that this baked texture deals with avatar_joint_mesh_list_t mJointMeshes; morph_list_t mMaskedMorphs; @@ -354,9 +354,9 @@ protected: // Collision volumes //-------------------------------------------------------------------- public: - S32 mNumBones; - S32 mNumCollisionVolumes; - LLAvatarJointCollisionVolume* mCollisionVolumes; + S32 mNumBones{ 0 }; + S32 mNumCollisionVolumes{ 0 }; + LLAvatarJointCollisionVolume* mCollisionVolumes{ nullptr }; protected: bool allocateCollisionVolumes(U32 num); diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index b7eac80603..59092988dd 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -130,10 +130,10 @@ protected: LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder entry_list_t mDriven; - LLViewerVisualParam* mCurrentDistortionParam; + LLViewerVisualParam* mCurrentDistortionParam{ nullptr }; // Backlink only; don't make this an LLPointer. - LLAvatarAppearance* mAvatarAppearance; - LLWearable* mWearablep; + LLAvatarAppearance* mAvatarAppearance{ nullptr }; + LLWearable* mWearablep{ nullptr }; }; #endif // LL_LLDRIVERPARAM_H -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/llappearance/lldriverparam.cpp | 2 +- indra/llappearance/lllocaltextureobject.cpp | 2 +- indra/llappearance/llpolymorph.cpp | 4 ++-- indra/llappearance/llwearable.cpp | 2 +- indra/llappearance/llwearabledata.cpp | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp index 29815d22f7..2e933f9357 100644 --- a/indra/llappearance/lldriverparam.cpp +++ b/indra/llappearance/lldriverparam.cpp @@ -422,7 +422,7 @@ const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **po S32 LLDriverParam::getDrivenParamsCount() const { - return mDriven.size(); + return static_cast(mDriven.size()); } const LLViewerVisualParam* LLDriverParam::getDrivenParam(S32 index) const diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index 9707f002ee..f743f7b517 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -109,7 +109,7 @@ LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name) U32 LLLocalTextureObject::getNumTexLayers() const { - return mTexLayers.size(); + return static_cast(mTexLayers.size()); } LLUUID LLLocalTextureObject::getID() const diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index d8109d79c2..068be84441 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -107,7 +107,7 @@ LLPolyMorphData::~LLPolyMorphData() bool LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) { S32 numVertices; - S32 numRead; + size_t numRead; numRead = fread(&numVertices, sizeof(S32), 1, fp); llendianswizzle(&numVertices, sizeof(S32), 1); @@ -384,7 +384,7 @@ bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) if (!mMorphData) { const std::string driven_tag = "_Driven"; - U32 pos = morph_param_name.find(driven_tag); + auto pos = morph_param_name.find(driven_tag); if (pos > 0) { morph_param_name = morph_param_name.substr(0,pos); diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 9c41e3c256..a7e5292fed 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -744,7 +744,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) std::string terse_F32_to_string(F32 f) { std::string r = llformat("%.2f", f); - S32 len = r.length(); + auto len = r.length(); // "1.20" -> "1.2" // "24.00" -> "24." diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index a58138c434..7598ed67f3 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -334,7 +334,7 @@ U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const return 0; } const wearableentry_vec_t& wearable_vec = wearable_iter->second; - return wearable_vec.size(); + return static_cast(wearable_vec.size()); } U32 LLWearableData::getWearableCount(const U32 tex_index) const -- cgit v1.2.3 From 9e45c1e506e0cdf8ade6136da9bbf867c93d16e6 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 9 Jun 2024 16:17:03 +0200 Subject: Fix issues resulting from b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 --- indra/llappearance/llpolymorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 068be84441..7deb943a9b 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -385,7 +385,7 @@ bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { const std::string driven_tag = "_Driven"; auto pos = morph_param_name.find(driven_tag); - if (pos > 0) + if (pos != std::string::npos) { morph_param_name = morph_param_name.substr(0,pos); mMorphData = mMesh->getMorphData(morph_param_name); -- cgit v1.2.3 From 8703d5b0f91d303a33624edb26ebed16c1c6d941 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 9 Jun 2024 16:21:28 +0200 Subject: Found string should not be directly at the start --- indra/llappearance/llpolymorph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 7deb943a9b..7ae760d312 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -385,7 +385,7 @@ bool LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info) { const std::string driven_tag = "_Driven"; auto pos = morph_param_name.find(driven_tag); - if (pos != std::string::npos) + if (pos != std::string::npos && pos > 0) { morph_param_name = morph_param_name.substr(0,pos); mMorphData = mMesh->getMorphData(morph_param_name); -- cgit v1.2.3 From c0fad3028fd55c2067ce6a0ae4382cffe1014284 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 10 Jun 2024 16:42:43 +0200 Subject: Re-enable compiler warnings C4018, C4100, C4231 and C4506 --- indra/llappearance/llpolymesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index b70e5af69f..97f9ca68b6 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -983,7 +983,7 @@ void LLPolyMesh::initializeForMorph() LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); - for (U32 i = 0; i < mSharedData->mNumVertices; ++i) + for (S32 i = 0; i < mSharedData->mNumVertices; ++i) { mClothingWeights[i].clear(); } -- cgit v1.2.3 From 4b52dd754b41948efca0087ccac6d813f1fcce3f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Mon, 10 Jun 2024 18:16:13 +0200 Subject: Fix incorrect use of VX/VY/VZ/VW indices when color components are accessed --- indra/llappearance/llavatarappearance.cpp | 12 ++++++------ indra/llappearance/lltexlayer.cpp | 8 ++++---- indra/llappearance/lltexlayerparams.cpp | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'indra/llappearance') diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 743c1745d0..de18fce0f8 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -1422,9 +1422,9 @@ void LLAvatarAppearance::setClothesColor( ETextureIndex te, const LLColor4& new_ U32 param_name[3]; if( teToColorParams( te, param_name ) ) { - setVisualParamWeight( param_name[0], new_color.mV[VX]); - setVisualParamWeight( param_name[1], new_color.mV[VY]); - setVisualParamWeight( param_name[2], new_color.mV[VZ]); + setVisualParamWeight( param_name[0], new_color.mV[VRED]); + setVisualParamWeight( param_name[1], new_color.mV[VGREEN]); + setVisualParamWeight( param_name[2], new_color.mV[VBLUE]); } } @@ -1434,9 +1434,9 @@ LLColor4 LLAvatarAppearance::getClothesColor( ETextureIndex te ) U32 param_name[3]; if( teToColorParams( te, param_name ) ) { - color.mV[VX] = getVisualParamWeight( param_name[0] ); - color.mV[VY] = getVisualParamWeight( param_name[1] ); - color.mV[VZ] = getVisualParamWeight( param_name[2] ); + color.mV[VRED] = getVisualParamWeight( param_name[0] ); + color.mV[VGREEN] = getVisualParamWeight( param_name[1] ); + color.mV[VBLUE] = getVisualParamWeight( param_name[2] ); } return color; } diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 60ff19f952..d376c68c7f 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1038,7 +1038,7 @@ bool LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bou bool success = true; // If you can't see the layer, don't render it. - if( is_approx_zero( net_color.mV[VW] ) ) + if( is_approx_zero( net_color.mV[VALPHA] ) ) { return success; } @@ -1213,7 +1213,7 @@ bool LLTexLayer::findNetColor(LLColor4* net_color) const { net_color->setVec( mTexLayerSet->getAvatarAppearance()->getGlobalColor( getInfo()->mGlobalColor ) ); } - else if (getInfo()->mFixedColor.mV[VW]) + else if (getInfo()->mFixedColor.mV[VALPHA]) { net_color->setVec( getInfo()->mFixedColor ); } @@ -1232,7 +1232,7 @@ bool LLTexLayer::findNetColor(LLColor4* net_color) const return true; } - if( getInfo()->mFixedColor.mV[VW] ) + if( getInfo()->mFixedColor.mV[VALPHA] ) { net_color->setVec( getInfo()->mFixedColor ); return true; @@ -1373,7 +1373,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. // Note: we're still using gGL.blendFunc( GL_DST_ALPHA, GL_ZERO ); - if ( !is_approx_equal(layer_color.mV[VW], 1.f) ) + if ( !is_approx_equal(layer_color.mV[VALPHA], 1.f) ) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.color4fv(layer_color.mV); diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 7beffbcd19..30551c115d 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -464,10 +464,10 @@ LLColor4 LLTexLayerParamColor::getNetColor() const F32 weight = scaled_weight - index_start; const LLColor4 *start = &info->mColors[ index_start ]; const LLColor4 *end = &info->mColors[ index_end ]; - return LLColor4((1.f - weight) * start->mV[VX] + weight * end->mV[VX], - (1.f - weight) * start->mV[VY] + weight * end->mV[VY], - (1.f - weight) * start->mV[VZ] + weight * end->mV[VZ], - (1.f - weight) * start->mV[VW] + weight * end->mV[VW]); + return LLColor4((1.f - weight) * start->mV[VRED] + weight * end->mV[VRED], + (1.f - weight) * start->mV[VGREEN] + weight * end->mV[VGREEN], + (1.f - weight) * start->mV[VBLUE] + weight * end->mV[VBLUE], + (1.f - weight) * start->mV[VALPHA] + weight * end->mV[VALPHA]); } } -- cgit v1.2.3