diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index 6d3b19822..51db4c927 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -40,7 +40,7 @@ set(llappearance_SOURCE_FILES lltexlayer.cpp lltexlayerparams.cpp lltexturemanagerbridge.cpp - #llwearable.cpp + llwearable.cpp llwearabledata.cpp llwearabletype.cpp llviewervisualparam.cpp diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 254c2f8a9..fd7ddcc9c 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -1,7 +1,135 @@ -#include "linden_common.h" -#include "llavatarappearance.h" +/** + * @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$ + */ +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif + +#include "linden_common.h" + +#include "llavatarappearance.h" +#include "llavatarappearancedefines.h" +#include "llavatarjointmesh.h" +#include "imageids.h" +#include "lldir.h" +#include "lldeleteutils.h" +#include "llpolymorph.h" +#include "llpolymesh.h" +#include "llpolyskeletaldistortion.h" +#include "llstl.h" +#include "lltexglobalcolor.h" +#include "llwearabledata.h" + + +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + +#include + +using namespace LLAvatarAppearanceDefines; const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); +//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; + + default: + llassert(0); + return FALSE; + } + + return TRUE; +} // static LLColor4 LLAvatarAppearance::getDummyColor() { diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index ef44ffe63..4ed87c9da 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -260,7 +260,7 @@ protected: public: virtual void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake) = 0; virtual LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te) = 0; - //static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); + static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); //-------------------------------------------------------------------- // Global colors @@ -305,7 +305,7 @@ private: ** BAKED TEXTURES **/ public: - //LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; + virtual LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const = 0; protected: //virtual LLTexLayerSet* createTexLayerSet() = 0; diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp new file mode 100644 index 000000000..bacd4e5fb --- /dev/null +++ b/indra/llappearance/llwearable.cpp @@ -0,0 +1,820 @@ +/** + * @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" + +using namespace LLAvatarAppearanceDefines; + +// static +S32 LLWearable::sCurrentDefinitionVersion = 1; + +// Private local functions +static std::string terse_F32_to_string(F32 f); + +LLWearable::LLWearable() : + mDefinitionVersion(0), + mType(LLWearableType::WT_INVALID) +{ +} + +// virtual +LLWearable::~LLWearable() +{ +} + +const std::string& LLWearable::getTypeLabel() const +{ + return LLWearableType::getTypeLabel(mType); +} + +const std::string& LLWearable::getTypeName() const +{ + return LLWearableType::getTypeName(mType); +} + +LLAssetType::EType LLWearable::getAssetType() const +{ + return LLWearableType::getAssetType(mType); +} + +// reX: new function +BOOL LLWearable::FileExportParams( FILE* file ) const +{ + // wearable type + S32 type = (S32)mType; + fprintf( file, "type %d\n", type ); + + // parameters + S32 num_parameters = mVisualParamIndexMap.size(); + fprintf( file, "parameters %d\n", num_parameters ); + + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); ++iter) + { + S32 param_id = iter->first; + F32 param_weight = iter->second->getWeight(); + fprintf( file, "%d %s\n", param_id, terse_F32_to_string(param_weight).c_str() ); + } + + return TRUE; +} + +// reX: new function +BOOL LLWearable::FileExportTextures( FILE* file ) const +{ + // wearable type + S32 type = (S32)mType; + fprintf( file, "type %d\n", type ); + + // texture entries + S32 num_textures = mTEMap.size(); + fprintf( file, "textures %d\n", num_textures ); + + for (te_map_t::const_iterator iter = mTEMap.begin(); + iter != mTEMap.end(); ++iter) + { + S32 te = iter->first; + fprintf( file, "%d %s\n", te, iter->second->getID().asString().c_str() ); + } + + return TRUE; +} + +BOOL LLWearable::exportFile(LLFILE* fp) const +{ + llofstream ofs(fp); + return 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.exportStream( output_stream ) ) + { + return FALSE; + } + + // sale info + if( !mSaleInfo.exportStream( output_stream ) ) + { + return FALSE; + } + + // wearable type + output_stream << "type " << (S32) getType() << "\n"; + + // parameters + output_stream << "parameters " << mVisualParamIndexMap.size() << "\n"; + + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) + { + S32 param_id = iter->first; + const LLVisualParam* param = iter->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 (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) + { + S32 te = iter->first; + const LLUUID& image_id = iter->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::iterator param_iter = mVisualParamIndexMap.begin(); + param_iter != mVisualParamIndexMap.end(); + ++param_iter) + { + LLVisualParam* param = param_iter->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)) + { + llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; + continue; + } + } + } +} + +void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp) +{ + LLTexLayerSet *layer_set = NULL; + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); + if (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 + { + llerrs << "could not find layerset for LTO in wearable!" << llendl; + } +} + +LLWearable::EImportResult LLWearable::importFile(LLFILE* fp, LLAvatarAppearance* avatarp ) +{ + llifstream ifs(fp); + return 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[2048]; /* 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 (!input_stream.good()) + { + llwarns << "Failed to read wearable asset input stream." << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + 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 ) + { + llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; + return LLWearable::FAILURE; + } + + // name + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading name" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + mName = buffer; + + // description + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading description" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + mDescription = buffer; + + // permissions + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading permissions" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 perm_version = -1; + if ( 1 != sscanf( buffer, " permissions %d\n", &perm_version ) || + perm_version != 0 ) + { + llwarns << "Bad Wearable asset: missing valid permissions" << llendl; + return LLWearable::FAILURE; + } + if( !mPermissions.importStream( input_stream ) ) + { + return LLWearable::FAILURE; + } + + // sale info + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading sale info" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 sale_info_version = -1; + if ( 1 != sscanf( buffer, " sale_info %d\n", &sale_info_version ) || + sale_info_version != 0 ) + { + llwarns << "Bad Wearable asset: missing valid sale_info" << llendl; + 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.importStream(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 (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading type" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 type = -1; + if ( 1 != sscanf( buffer, "type %d\n", &type ) ) + { + llwarns << "Bad Wearable asset: bad type" << llendl; + return LLWearable::FAILURE; + } + if( 0 <= type && type < LLWearableType::WT_COUNT ) + { + setType((LLWearableType::EType)type, avatarp); + } + else + { + mType = LLWearableType::WT_COUNT; + llwarns << "Bad Wearable asset: bad type #" << type << llendl; + return LLWearable::FAILURE; + } + + // parameters header + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading parameters header" << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 num_parameters = -1; + if ( 1 != sscanf( buffer, "parameters %d\n", &num_parameters ) ) + { + llwarns << "Bad Wearable asset: missing parameters block" << llendl; + return LLWearable::FAILURE; + } + if ( num_parameters > MAX_WEARABLE_ASSET_PARAMETERS ) + { + llwarns << "Bad Wearable asset: too many parameters, " + << num_parameters << llendl; + return LLWearable::FAILURE; + } + if( num_parameters != mVisualParamIndexMap.size() ) + { + llwarns << "Wearable parameter mismatch. Reading in " + << num_parameters << " from file, but created " + << mVisualParamIndexMap.size() + << " from avatar parameters. type: " + << getType() << llendl; + } + + // parameters + S32 i; + for( i = 0; i < num_parameters; i++ ) + { + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading parameter #" << i << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 param_id = 0; + F32 param_weight = 0.f; + if ( 2 != sscanf( buffer, "%d %f\n", ¶m_id, ¶m_weight ) ) + { + llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl; + return LLWearable::FAILURE; + } + mSavedVisualParamMap[param_id] = param_weight; + } + + // textures header + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading textures header" << i << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 num_textures = -1; + if ( 1 != sscanf( buffer, "textures %d\n", &num_textures) ) + { + llwarns << "Bad Wearable asset: missing textures block" << llendl; + return LLWearable::FAILURE; + } + if ( num_textures > MAX_WEARABLE_ASSET_TEXTURES ) + { + llwarns << "Bad Wearable asset: too many textures, " + << num_textures << llendl; + return LLWearable::FAILURE; + } + + // textures + for( i = 0; i < num_textures; i++ ) + { + if (!input_stream.good()) + { + llwarns << "Bad Wearable asset: early end of input stream " + << "while reading textures #" << i << llendl; + return LLWearable::FAILURE; + } + input_stream.getline(buffer, PARSE_BUFFER_SIZE); + S32 te = 0; + if ( 2 != sscanf( /* Flawfinder: ignore */ + buffer, + "%d %36s\n", + &te, uuid_buffer) ) + { + llwarns << "Bad Wearable asset: bad texture, #" << i << llendl; + return LLWearable::FAILURE; + } + + if( !LLUUID::validate( uuid_buffer ) ) + { + llwarns << "Bad Wearable asset: bad texture uuid: " + << uuid_buffer << llendl; + 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; +} + +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::const_iterator iter = mTEMap.begin(); + iter != mTEMap.end(); iter++) + { + LLLocalTextureObject* lto = iter->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 + // non-driver params first + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && !dynamic_cast(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + //then driver params + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + F32 value = iter->second; + LLVisualParam *param = getVisualParam(id); + if(param && dynamic_cast(param) ) + { + setVisualParamWeight(id, value, TRUE); + } + } + + // make sure that saved values are sane + for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) + { + S32 id = iter->first; + LLVisualParam *param = getVisualParam(id); + if( param ) + { + mSavedVisualParamMap[id] = param->getWeight(); + } + } + + syncImages(mSavedTEMap, mTEMap); +} + +void LLWearable::saveValues() +{ + //update saved settings so wearable is no longer dirty + mSavedVisualParamMap.clear(); + for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) + { + S32 id = iter->first; + LLVisualParam *wearable_param = iter->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 (LLAvatarAppearanceDictionary::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() +{ + for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + mTEMap.clear(); + for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) + { + LLLocalTextureObject *lto = iter->second; + delete lto; + } + 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, BOOL upload_bake) +{ + if( is_in_map(mVisualParamIndexMap, param_index ) ) + { + LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + wearable_param->setWeight(value, upload_bake); + } + else + { + llerrs << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; + } +} + +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 + { + llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; + } + 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) +{ + visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); + + // add all visual params to the passed-in vector + for( ; iter != end; ++iter ) + { + list.push_back(iter->second); + } +} + +void LLWearable::animateParams(F32 delta, BOOL upload_bake) +{ + for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); + iter != mVisualParamIndexMap.end(); + ++iter) + { + LLVisualParam *param = (LLVisualParam*) iter->second; + param->animate(delta, upload_bake); + } +} + +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, BOOL upload_bake ) +{ + 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], upload_bake); + } + } +} + +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, FALSE ); + } + } +} + + +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; +} \ No newline at end of file diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index ccd4c2057..8faf383aa 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -47,25 +47,99 @@ class LLWearable // Constructors and destructors //-------------------------------------------------------------------- public: - virtual ~LLWearable() {}; + LLWearable(); + virtual ~LLWearable(); //-------------------------------------------------------------------- // Accessors //-------------------------------------------------------------------- public: - virtual LLWearableType::EType getType() const = 0; - virtual void writeToAvatar(LLAvatarAppearance* avatarp) = 0; - virtual LLLocalTextureObject* getLocalTextureObject(S32 index) = 0; - virtual const LLLocalTextureObject* getLocalTextureObject(S32 index) const = 0; - virtual void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake) = 0; - virtual F32 getVisualParamWeight(S32 index) const = 0; - virtual LLVisualParam* getVisualParam(S32 index) const = 0; + 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); + + BOOL FileExportParams(FILE* file) const; + BOOL FileExportTextures(FILE* file) const; + + enum EImportResult + { + FAILURE = 0, + SUCCESS, + BAD_HEADER + }; + BOOL exportFile(LLFILE* file) const; + EImportResult importFile(LLFILE* file, 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 const 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, BOOL upload_bake); + F32 getVisualParamWeight(S32 index) const; + LLVisualParam* getVisualParam(S32 index) const; + void getVisualParams(visual_param_vec_t &list); + void animateParams(F32 delta, BOOL upload_bake); + + LLColor4 getClothesColor(S32 te) const; + void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ); + + virtual void revertValues(); + virtual void saveValues(); // Something happened that requires the wearable to be updated (e.g. worn/unworn). virtual void setUpdated() const = 0; // Update the baked texture hash. virtual void addToBakedTextureHash(LLMD5& hash) const = 0; + +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); + + 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 + + typedef std::map visual_param_index_map_t; + visual_param_index_map_t mVisualParamIndexMap; + + 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/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 1f1f4ce38..31cca09fd 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -2,31 +2,25 @@ * @file llinventory.cpp * @brief Implementation of the inventory system. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -845,7 +839,7 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) } else if(0 == strcmp("permissions", keyword)) { - success = mPermissions.importLegacyStream(input_stream); + success = mPermissions.importStream(input_stream); } else if(0 == strcmp("sale_info", keyword)) { @@ -855,7 +849,7 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) // should pick up the vast majority of the tasks. BOOL has_perm_mask = FALSE; U32 perm_mask = 0; - success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask); + success = mSaleInfo.importStream(input_stream, has_perm_mask, perm_mask); if(has_perm_mask) { if(perm_mask == PERM_NONE) @@ -971,7 +965,7 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu output_stream << "\t\titem_id\t" << uuid_str << "\n"; mParentUUID.toString(uuid_str); output_stream << "\t\tparent_id\t" << uuid_str << "\n"; - mPermissions.exportLegacyStream(output_stream); + mPermissions.exportStream(output_stream); // Check for permissions to see the asset id, and if so write it // out as an asset id. Otherwise, apply our cheesy encryption. @@ -1005,7 +999,7 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu std::string buffer; buffer = llformat( "\t\tflags\t%08x\n", mFlags); output_stream << buffer; - mSaleInfo.exportLegacyStream(output_stream); + mSaleInfo.exportStream(output_stream); output_stream << "\t\tname\t" << mName.c_str() << "|\n"; output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n"; output_stream << "\t\tcreation_date\t" << mCreationDate << "\n"; @@ -1123,7 +1117,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd) { if (sd[w].isString()) { - mType = LLAssetType::lookup(sd[w].asString()); + mType = LLAssetType::lookup(sd[w].asString().c_str()); } else if (sd[w].isInteger()) { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 14c04a0d1..b03cb6fdf 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -2,31 +2,25 @@ * @file llinventory.h * @brief LLInventoryItem and LLInventoryCategory class declaration. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 9683252dc..34354e3e8 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -3,31 +3,25 @@ * @author Phoenix * @brief Permissions for objects and inventory. * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -578,143 +572,17 @@ void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 b BOOL LLPermissions::importFile(LLFILE* fp) { - init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); - const S32 BUFSIZE = 16384; - - // *NOTE: Changing the buffer size will require changing the scanf - // calls below. - char buffer[BUFSIZE]; /* Flawfinder: ignore */ - char keyword[256]; /* Flawfinder: ignore */ - char valuestr[256]; /* Flawfinder: ignore */ - char uuid_str[256]; /* Flawfinder: ignore */ - U32 mask; - - keyword[0] = '\0'; - valuestr[0] = '\0'; - - while (!feof(fp)) - { - if (fgets(buffer, BUFSIZE, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %255s %255s", - keyword, valuestr); - if (!strcmp("{", keyword)) - { - continue; - } - if (!strcmp("}",keyword)) - { - break; - } - else if (!strcmp("creator_mask", keyword)) - { - // legacy support for "creator" masks - sscanf(valuestr, "%x", &mask); - mMaskBase = mask; - fixFairUse(); - } - else if (!strcmp("base_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskBase = mask; - //fixFairUse(); - } - else if (!strcmp("owner_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskOwner = mask; - } - else if (!strcmp("group_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskGroup = mask; - } - else if (!strcmp("everyone_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskEveryone = mask; - } - else if (!strcmp("next_owner_mask", keyword)) - { - sscanf(valuestr, "%x", &mask); - mMaskNextOwner = mask; - } - else if (!strcmp("creator_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mCreator.set(uuid_str); - } - else if (!strcmp("owner_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mOwner.set(uuid_str); - } - else if (!strcmp("last_owner_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mLastOwner.set(uuid_str); - } - else if (!strcmp("group_id", keyword)) - { - sscanf(valuestr, "%255s", uuid_str); /* Flawfinder: ignore */ - mGroup.set(uuid_str); - } - else if (!strcmp("group_owned", keyword)) - { - sscanf(valuestr, "%d", &mask); - if(mask) mIsGroupOwned = true; - else mIsGroupOwned = false; - } - else - { - llinfos << "unknown keyword " << keyword << " in permissions import" << llendl; - } - } - fix(); - return TRUE; + llifstream ifs(fp); + return importStream(ifs); } - BOOL LLPermissions::exportFile(LLFILE* fp) const { - std::string uuid_str; - - fprintf(fp, "\tpermissions 0\n"); - fprintf(fp, "\t{\n"); - - fprintf(fp, "\t\tbase_mask\t%08x\n", mMaskBase); - fprintf(fp, "\t\towner_mask\t%08x\n", mMaskOwner); - fprintf(fp, "\t\tgroup_mask\t%08x\n", mMaskGroup); - fprintf(fp, "\t\teveryone_mask\t%08x\n", mMaskEveryone); - fprintf(fp, "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); - - mCreator.toString(uuid_str); - fprintf(fp, "\t\tcreator_id\t%s\n", uuid_str.c_str()); - - mOwner.toString(uuid_str); - fprintf(fp, "\t\towner_id\t%s\n", uuid_str.c_str()); - - mLastOwner.toString(uuid_str); - fprintf(fp, "\t\tlast_owner_id\t%s\n", uuid_str.c_str()); - - mGroup.toString(uuid_str); - fprintf(fp, "\t\tgroup_id\t%s\n", uuid_str.c_str()); - - if(mIsGroupOwned) - { - fprintf(fp, "\t\tgroup_owned\t1\n"); - } - fprintf(fp,"\t}\n"); - return TRUE; + llofstream ofs(fp); + return exportStream(ofs); } - -BOOL LLPermissions::importLegacyStream(std::istream& input_stream) +BOOL LLPermissions::importStream(std::istream& input_stream) { init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); const S32 BUFSIZE = 16384; @@ -733,6 +601,18 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream) while (input_stream.good()) { input_stream.getline(buffer, BUFSIZE); + if (input_stream.eof()) + { + llwarns << "Bad permissions: early end of input stream" + << llendl; + return FALSE; + } + if (input_stream.fail()) + { + llwarns << "Bad permissions: failed to read from input stream" + << llendl; + return FALSE; + } sscanf( /* Flawfinder: ignore */ buffer, " %255s %255s", @@ -806,7 +686,8 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream) } else { - llinfos << "unknown keyword " << keyword << " in permissions import" << llendl; + llwarns << "unknown keyword " << keyword + << " in permissions import" << llendl; } } fix(); @@ -814,36 +695,26 @@ BOOL LLPermissions::importLegacyStream(std::istream& input_stream) } -BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const +BOOL LLPermissions::exportStream(std::ostream& output_stream) const { - std::string uuid_str; - + if (!output_stream.good()) return FALSE; output_stream << "\tpermissions 0\n"; output_stream << "\t{\n"; - std::string buffer; - buffer = llformat( "\t\tbase_mask\t%08x\n", mMaskBase); - output_stream << buffer; - buffer = llformat( "\t\towner_mask\t%08x\n", mMaskOwner); - output_stream << buffer; - buffer = llformat( "\t\tgroup_mask\t%08x\n", mMaskGroup); - output_stream << buffer; - buffer = llformat( "\t\teveryone_mask\t%08x\n", mMaskEveryone); - output_stream << buffer; - buffer = llformat( "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); - output_stream << buffer; + char prev_fill = output_stream.fill('0'); + output_stream << std::hex; + output_stream << "\t\tbase_mask\t" << std::setw(8) << mMaskBase << "\n"; + output_stream << "\t\towner_mask\t" << std::setw(8) << mMaskOwner << "\n"; + output_stream << "\t\tgroup_mask\t" << std::setw(8) << mMaskGroup << "\n"; + output_stream << "\t\teveryone_mask\t" << std::setw(8) << mMaskEveryone << "\n"; + output_stream << "\t\tnext_owner_mask\t" << std::setw(8) << mMaskNextOwner << "\n"; + output_stream << std::dec; + output_stream.fill(prev_fill); - mCreator.toString(uuid_str); - output_stream << "\t\tcreator_id\t" << uuid_str << "\n"; - - mOwner.toString(uuid_str); - output_stream << "\t\towner_id\t" << uuid_str << "\n"; - - mLastOwner.toString(uuid_str); - output_stream << "\t\tlast_owner_id\t" << uuid_str << "\n"; - - mGroup.toString(uuid_str); - output_stream << "\t\tgroup_id\t" << uuid_str << "\n"; + output_stream << "\t\tcreator_id\t" << mCreator << "\n"; + output_stream << "\t\towner_id\t" << mOwner << "\n"; + output_stream << "\t\tlast_owner_id\t" << mLastOwner << "\n"; + output_stream << "\t\tgroup_id\t" << mGroup << "\n"; if(mIsGroupOwned) { diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index fa20d5c21..7d3a68d35 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -2,31 +2,25 @@ * @file llpermissions.h * @brief Permissions structures for objects. * - * $LicenseInfo:firstyear=2002&license=viewergpl$ - * - * Copyright (c) 2002-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -322,8 +316,8 @@ public: BOOL importFile(LLFILE* fp); BOOL exportFile(LLFILE* fp) const; - BOOL importLegacyStream(std::istream& input_stream); - BOOL exportLegacyStream(std::ostream& output_stream) const; + BOOL importStream(std::istream& input_stream); + BOOL exportStream(std::ostream& output_stream) const; bool operator==(const LLPermissions &rhs) const; bool operator!=(const LLPermissions &rhs) const; diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index 88e7da7ac..b39f02f6a 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -87,15 +87,13 @@ U32 LLSaleInfo::getCRC32() const BOOL LLSaleInfo::exportFile(LLFILE* fp) const { - fprintf(fp, "\tsale_info\t0\n\t{\n"); - fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType)); - fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice); - fprintf(fp,"\t}\n"); - return TRUE; + llofstream ofs(fp); + return exportStream(ofs); } -BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const +BOOL LLSaleInfo::exportStream(std::ostream& output_stream) const { + if (!output_stream.good()) return FALSE; output_stream << "\tsale_info\t0\n\t{\n"; output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n"; output_stream << "\t\tsale_price\t" << mSalePrice << "\n"; @@ -140,80 +138,39 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask) { - has_perm_mask = FALSE; - - // *NOTE: Changing the buffer size will require changing the scanf - // calls below. - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - char valuestr[MAX_STRING]; /* Flawfinder: ignore */ - BOOL success = TRUE; - - keyword[0] = '\0'; - valuestr[0] = '\0'; - while(success && (!feof(fp))) - { - if (fgets(buffer, MAX_STRING, fp) == NULL) - { - buffer[0] = '\0'; - } - - sscanf( /* Flawfinder: ignore */ - buffer, - " %254s %254s", - keyword, valuestr); - if(!keyword[0]) - { - continue; - } - if(0 == strcmp("{",keyword)) - { - continue; - } - if(0 == strcmp("}", keyword)) - { - break; - } - else if(0 == strcmp("sale_type", keyword)) - { - mSaleType = lookup(valuestr); - } - else if(0 == strcmp("sale_price", keyword)) - { - sscanf(valuestr, "%d", &mSalePrice); - mSalePrice = llclamp(mSalePrice, 0, S32_MAX); - } - else if (!strcmp("perm_mask", keyword)) - { - //llinfos << "found deprecated keyword perm_mask" << llendl; - has_perm_mask = TRUE; - sscanf(valuestr, "%x", &perm_mask); - } - else - { - llwarns << "unknown keyword '" << keyword - << "' in sale info import" << llendl; - } - } - return success; + llifstream ifs(fp); + return importStream(ifs, has_perm_mask, perm_mask); } -BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask) +BOOL LLSaleInfo::importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask) { has_perm_mask = FALSE; + const S32 BUFSIZE = 16384; + // *NOTE: Changing the buffer size will require changing the scanf // calls below. - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - char valuestr[MAX_STRING]; /* Flawfinder: ignore */ - BOOL success = TRUE; + char buffer[BUFSIZE]; /* Flawfinder: ignore */ + char keyword[255]; /* Flawfinder: ignore */ + char valuestr[255]; /* Flawfinder: ignore */ keyword[0] = '\0'; valuestr[0] = '\0'; - while(success && input_stream.good()) + while(input_stream.good()) { input_stream.getline(buffer, MAX_STRING); + if (input_stream.eof()) + { + llwarns << "Bad sale info: early end of input stream" + << llendl; + return FALSE; + } + if (input_stream.fail()) + { + llwarns << "Bad sale info: failed to read from input stream" + << llendl; + return FALSE; + } sscanf( /* Flawfinder: ignore */ buffer, " %254s %254s", @@ -251,7 +208,7 @@ BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_m << "' in sale info import" << llendl; } } - return success; + return TRUE; } void LLSaleInfo::setSalePrice(S32 price) diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index 3461a128b..026e042bc 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -95,11 +95,11 @@ public: BOOL exportFile(LLFILE* fp) const; BOOL importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask); - BOOL exportLegacyStream(std::ostream& output_stream) const; + BOOL exportStream(std::ostream& output_stream) const; LLSD asLLSD() const; operator LLSD() const { return asLLSD(); } bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask); - BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); + BOOL importStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); LLSD packMessage() const; void unpackMessage(LLSD sales); diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index c0d10b8ee..a621ae985 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -29,30 +29,19 @@ #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" -#include "lldictionary.h" #include "llfloatercustomize.h" -#include "lllocaltextureobject.h" #include "llnotificationsutil.h" -#include "llviewertexturelist.h" -#include "llinventorymodel.h" -#include "llinventoryobserver.h" -#include "lltexlayer.h" -#include "lltexglobalcolor.h" -#include "lltrans.h" -#include "llviewerregion.h" -#include "llvisualparam.h" -#include "llvoavatar.h" +#include "lltextureentry.h" +#include "llviewertexlayer.h" #include "llvoavatarself.h" #include "llavatarappearancedefines.h" #include "llviewerwearable.h" #include "llviewercontrol.h" -#include "llviewertexlayer.h" +#include "llviewerregion.h" +#include "llinventoryobserver.h" using namespace LLAvatarAppearanceDefines; -// static -S32 LLViewerWearable::sCurrentDefinitionVersion = 1; - // support class - remove for 2.1 (hackity hack hack) class LLOverrideBakedTextureUpdate { @@ -80,22 +69,17 @@ private: }; // Private local functions -static std::string terse_F32_to_string(F32 f); static std::string asset_id_to_filename(const LLUUID &asset_id); LLViewerWearable::LLViewerWearable(const LLTransactionID& transaction_id) : - LLWearable(), - mDefinitionVersion(LLViewerWearable::sCurrentDefinitionVersion), - mType(LLWearableType::WT_INVALID) + LLWearable() { mTransactionID = transaction_id; mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); } LLViewerWearable::LLViewerWearable(const LLAssetID& asset_id) : - LLWearable(), - mDefinitionVersion( LLViewerWearable::sCurrentDefinitionVersion ), - mType(LLWearableType::WT_INVALID) + LLWearable() { mAssetID = asset_id; mTransactionID.setNull(); @@ -106,416 +90,47 @@ LLViewerWearable::~LLViewerWearable() { } -const std::string& LLViewerWearable::getTypeLabel() const +// virtual +LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) { - return LLWearableType::getTypeLabel(mType); -} - -const std::string& LLViewerWearable::getTypeName() const -{ - return LLWearableType::getTypeName(mType); -} - -LLAssetType::EType LLViewerWearable::getAssetType() const -{ - return LLWearableType::getAssetType(mType); -} - -const LLUUID LLViewerWearable::getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) -{ - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); - const std::string &default_image_name = texture_dict->mDefaultImageName; - if (default_image_name == "") - { - return IMG_DEFAULT_AVATAR; - } - else - { - return LLUUID(gSavedSettings.getString(default_image_name)); - } -} - -// reX: new function -BOOL LLViewerWearable::FileExportParams( FILE* file ) -{ - // wearable type - S32 type = (S32)mType; - fprintf( file, "type %d\n", type ); - - // parameters - S32 num_parameters = mVisualParamIndexMap.size(); - fprintf( file, "parameters %d\n", num_parameters ); - - for (visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); ++iter) - { - S32 param_id = iter->first; - F32 param_weight = iter->second->getWeight(); - fprintf( file, "%d %s\n", param_id, terse_F32_to_string(param_weight).c_str() ); - } - - return TRUE; -} - -// reX: new function -BOOL LLViewerWearable::FileExportTextures( FILE* file ) -{ - // wearable type - S32 type = (S32)mType; - fprintf( file, "type %d\n", type ); - - // texture entries - S32 num_textures = mTEMap.size(); - fprintf( file, "textures %d\n", num_textures ); - - for (te_map_t::iterator iter = mTEMap.begin(); - iter != mTEMap.end(); ++iter) - { - S32 te = iter->first; - fprintf( file, "%d %s\n", te, iter->second->getID().asString().c_str() ); - } - - return TRUE; -} - -BOOL LLViewerWearable::exportFile(LLFILE* file) const -{ - // header and version - if( fprintf( file, "LLWearable version %d\n", mDefinitionVersion ) < 0 ) - { - return FALSE; - } - - // name - if( fprintf( file, "%s\n", mName.c_str() ) < 0 ) - { - return FALSE; - } - - // description - if( fprintf( file, "%s\n", mDescription.c_str() ) < 0 ) - { - return FALSE; - } - - // permissions - if( !mPermissions.exportFile( file ) ) - { - return FALSE; - } - - // sale info - if( !mSaleInfo.exportFile( file ) ) - { - return FALSE; - } - - // wearable type - S32 type = (S32)mType; - if( fprintf( file, "type %d\n", type ) < 0 ) - { - return FALSE; - } - - // parameters - S32 num_parameters = mVisualParamIndexMap.size(); - if( fprintf( file, "parameters %d\n", num_parameters ) < 0 ) - { - return FALSE; - } - - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); - ++iter) - { - S32 param_id = iter->first; - const LLVisualParam* param = iter->second; - F32 param_weight = param->getWeight(); - if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( param_weight ).c_str() ) < 0 ) - { - return FALSE; - } - } - - // texture entries - S32 num_textures = mTEMap.size(); - if( fprintf( file, "textures %d\n", num_textures ) < 0 ) - { - return FALSE; - } - - for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) - { - S32 te = iter->first; - const LLUUID& image_id = iter->second->getID(); - if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 ) - { - return FALSE; - } - } - return TRUE; -} - - -void LLViewerWearable::createVisualParams() -{ - for (LLViewerVisualParam* param = (LLViewerVisualParam*) gAgentAvatarp->getFirstVisualParam(); - param; - param = (LLViewerVisualParam*) gAgentAvatarp->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::iterator param_iter = mVisualParamIndexMap.begin(); - param_iter != mVisualParamIndexMap.end(); - ++param_iter) - { - LLVisualParam* param = param_iter->second; - LLVisualParam*(LLViewerWearable::*wearable_function)(S32)const = &LLViewerWearable::getVisualParam; - // need this line to disambiguate between versions of LLCharacter::getVisualParam() - LLVisualParam*(LLVOAvatarSelf::*avatar_function)(S32)const = &LLVOAvatarSelf::getVisualParam; - param->resetDrivenParams(); - if(!param->linkDrivenParams(boost::bind(wearable_function,(LLViewerWearable*)this, _1), false)) - { - if( !param->linkDrivenParams(boost::bind(avatar_function,gAgentAvatarp.get(),_1 ), true)) - { - llwarns << "could not link driven params for wearable " << getName() << " id: " << param->getID() << llendl; - continue; - } - } - } -} - -BOOL LLViewerWearable::importFile( LLFILE* file ) -{ - // *NOTE: changing the type or size of this buffer will require - // changes in the fscanf() code below. You would be better off - // rewriting this to use streams and not require an open FILE. - char text_buffer[2048]; /* Flawfinder: ignore */ - S32 fields_read = 0; - // suppress texlayerset updates while wearables are being imported. Layersets will be updated // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. LLOverrideBakedTextureUpdate stop_bakes(false); - // read header and version - fields_read = fscanf( file, "LLWearable version %d\n", &mDefinitionVersion ); - if( fields_read != 1 ) + LLWearable::EImportResult result = LLWearable::importStream(input_stream, avatarp); + if (LLWearable::FAILURE == result) return result; + if (LLWearable::BAD_HEADER == result) { // Shouldn't really log the asset id for security reasons, but // we need it in this case. llwarns << "Bad Wearable asset header: " << mAssetID << llendl; //gVFS->dumpMap(); - return FALSE; + return result; } + LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN ); + LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN ); - // Temoprary 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 > LLViewerWearable::sCurrentDefinitionVersion && mDefinitionVersion != 24 ) + te_map_t::const_iterator iter = mTEMap.begin(); + te_map_t::const_iterator end = mTEMap.end(); + for (; iter != end; ++iter) { - llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLViewerWearable::sCurrentDefinitionVersion << ")" << llendl; - return FALSE; - } - - // name - int next_char = fgetc( file ); /* Flawfinder: ignore */ - if( '\n' == next_char ) - { - // no name - mName = ""; - } - else - { - ungetc( next_char, file ); - fields_read = fscanf( /* Flawfinder: ignore */ - file, - "%2047[^\n]", - text_buffer); - if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ + S32 te = iter->first; + LLLocalTextureObject* lto = iter->second; + LLUUID textureid = LLUUID::null; + if (lto) { - llwarns << "Bad Wearable asset: early end of file" << llendl; - return FALSE; - } - mName = text_buffer; - LLStringUtil::truncate(mName, DB_INV_ITEM_NAME_STR_LEN ); - } - - // description - next_char = fgetc( file ); /* Flawfinder: ignore */ - if( '\n' == next_char ) - { - // no description - mDescription = ""; - } - else - { - ungetc( next_char, file ); - fields_read = fscanf( /* Flawfinder: ignore */ - file, - "%2047[^\n]", - text_buffer ); - if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ - { - llwarns << "Bad Wearable asset: early end of file" << llendl; - return FALSE; - } - mDescription = text_buffer; - LLStringUtil::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN ); - } - - // permissions - S32 perm_version; - fields_read = fscanf( file, " permissions %d\n", &perm_version ); - if( (fields_read != 1) || (perm_version != 0) ) - { - llwarns << "Bad Wearable asset: missing permissions" << llendl; - return FALSE; - } - if( !mPermissions.importFile( file ) ) - { - return FALSE; - } - - // sale info - S32 sale_info_version; - fields_read = fscanf( file, " sale_info %d\n", &sale_info_version ); - if( (fields_read != 1) || (sale_info_version != 0) ) - { - llwarns << "Bad Wearable asset: missing sale_info" << llendl; - return FALSE; - } - // 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.importFile(file, has_perm_mask, perm_mask) ) - { - return FALSE; - } - if(has_perm_mask) - { - // fair use fix. - if(!(perm_mask & PERM_COPY)) - { - perm_mask |= PERM_TRANSFER; - } - mPermissions.setMaskNext(perm_mask); - } - - // wearable type - S32 type = -1; - fields_read = fscanf( file, "type %d\n", &type ); - if( fields_read != 1 ) - { - llwarns << "Bad Wearable asset: bad type" << llendl; - return FALSE; - } - if( 0 <= type && type < LLWearableType::WT_COUNT ) - { - setType((LLWearableType::EType)type); - } - else - { - mType = LLWearableType::WT_COUNT; - llwarns << "Bad Wearable asset: bad type #" << type << llendl; - return FALSE; - } - - // parameters header - S32 num_parameters = 0; - fields_read = fscanf( file, "parameters %d\n", &num_parameters ); - if( fields_read != 1 ) - { - llwarns << "Bad Wearable asset: missing parameters block" << llendl; - return FALSE; - } - - if( num_parameters != mVisualParamIndexMap.size() ) - { - llwarns << "Wearable parameter mismatch. Reading in " << num_parameters << " from file, but created " << mVisualParamIndexMap.size() << " from avatar parameters. type: " << mType << llendl; - } - - // parameters - S32 i; - for( i = 0; i < num_parameters; i++ ) - { - S32 param_id = 0; - F32 param_weight = 0.f; - fields_read = fscanf( file, "%d %f\n", ¶m_id, ¶m_weight ); - if( fields_read != 2 ) - { - llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl; - return FALSE; - } - mSavedVisualParamMap[param_id] = param_weight; - } - - // textures header - S32 num_textures = 0; - fields_read = fscanf( file, "textures %d\n", &num_textures); - if( fields_read != 1 ) - { - llwarns << "Bad Wearable asset: missing textures block" << llendl; - return FALSE; - } - - // textures - for( i = 0; i < num_textures; i++ ) - { - S32 te = 0; - fields_read = fscanf( /* Flawfinder: ignore */ - file, - "%d %2047s\n", - &te, text_buffer); - if( fields_read != 2 ) - { - llwarns << "Bad Wearable asset: bad texture, #" << i << llendl; - return FALSE; - } - - if( !LLUUID::validate( text_buffer ) ) - { - llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl; - return FALSE; - } - LLUUID id = LLUUID(text_buffer); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( id ); - if( mTEMap.find(te) != mTEMap.end() ) - { - delete mTEMap[te]; - } - if( mSavedTEMap.find(te) != mSavedTEMap.end() ) - { - delete mSavedTEMap[te]; + textureid = lto->getID(); } + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( textureid ); if(gSavedSettings.getBOOL("DebugAvatarLocalTexLoadedTime")) { - image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(id, (LLAvatarAppearanceDefines::ETextureIndex)te), NULL); + image->setLoadedCallback(LLVOAvatarSelf::debugOnTimingLocalTexLoaded,0,TRUE,FALSE, new LLVOAvatarSelf::LLAvatarTexData(textureid, (LLAvatarAppearanceDefines::ETextureIndex)te), NULL); } - LLUUID textureid(text_buffer); - mTEMap[te] = new LLLocalTextureObject(image, textureid); - mSavedTEMap[te] = new LLLocalTextureObject(image, textureid); - createLayers(te); } - // copy all saved param values to working params - revertValues(); - - return TRUE; + return result; } @@ -526,13 +141,13 @@ BOOL LLViewerWearable::isOldVersion() const { if (!isAgentAvatarValid()) return FALSE; - if( LLViewerWearable::sCurrentDefinitionVersion < mDefinitionVersion ) + if( LLWearable::sCurrentDefinitionVersion < mDefinitionVersion ) { - llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLViewerWearable::sCurrentDefinitionVersion << ")" << llendl; + llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl; llassert(0); } - if( LLViewerWearable::sCurrentDefinitionVersion != mDefinitionVersion ) + if( LLWearable::sCurrentDefinitionVersion != mDefinitionVersion ) { return TRUE; } @@ -667,7 +282,7 @@ void LLViewerWearable::setTexturesToDefaults() if( mTEMap.find(te) == mTEMap.end() ) { mTEMap[te] = new LLLocalTextureObject(image, id); - createLayers(te); + createLayers(te, gAgentAvatarp); } else { @@ -680,6 +295,23 @@ void LLViewerWearable::setTexturesToDefaults() } } + +// virtual +const LLUUID LLViewerWearable::getDefaultTextureImageID(ETextureIndex index) const +{ + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture(index); + const std::string &default_image_name = texture_dict->mDefaultImageName; + if (default_image_name == "") + { + return IMG_DEFAULT_AVATAR; + } + else + { + return LLUUID(gSavedSettings.getString(default_image_name)); + } +} + + // Updates the user's avatar's appearance //virtual void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) @@ -692,19 +324,8 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) ESex old_sex = avatarp->getSex(); - // Pull params - for( LLVisualParam* param = gAgentAvatarp->getFirstVisualParam(); param; param = gAgentAvatarp->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); + LLWearable::writeToAvatar(avatarp); - gAgentAvatarp->setVisualParamWeight( param_id, weight, FALSE ); - } - } // Pull texture entries for( S32 te = 0; te < TEX_NUM_INDICES; te++ ) @@ -780,14 +401,14 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) { if (!isAgentAvatarValid()) return; - mDefinitionVersion = LLViewerWearable::sCurrentDefinitionVersion; + mDefinitionVersion = LLWearable::sCurrentDefinitionVersion; mName = src->mName; mDescription = src->mDescription; mPermissions = src->mPermissions; mSaleInfo = src->mSaleInfo; - setType(src->mType); + setType(src->mType, gAgentAvatarp); mSavedVisualParamMap.clear(); // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed) @@ -828,7 +449,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) mTEMap[te] = new LLLocalTextureObject(image, image_id); mSavedTEMap[te] = new LLLocalTextureObject(image, image_id); } - createLayers(te); + createLayers(te, gAgentAvatarp); } } @@ -842,195 +463,9 @@ void LLViewerWearable::setItemID(const LLUUID& item_id) mItemID = item_id; } -const LLUUID& LLViewerWearable::getItemID() const -{ - return mItemID; -} - -void LLViewerWearable::setType(LLWearableType::EType type) -{ - mType = type; - createVisualParams(); -} - -LLLocalTextureObject* LLViewerWearable::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* LLViewerWearable::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; -} - -void LLViewerWearable::setLocalTextureObject(S32 index, LLLocalTextureObject <o) -{ - if( mTEMap.find(index) != mTEMap.end() ) - { - mTEMap.erase(index); - } - mTEMap[index] = new LLLocalTextureObject(lto); -} - - -void LLViewerWearable::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 LLViewerWearable::setVisualParams() -{ - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->second; - F32 value = wearable_param->getWeight(); - gAgentAvatarp->setVisualParamWeight(id, value, FALSE); - } -} - - -void LLViewerWearable::setVisualParamWeight(S32 param_index, F32 value, BOOL upload_bake) -{ - if( is_in_map(mVisualParamIndexMap, param_index ) ) - { - LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; - wearable_param->setWeight(value, upload_bake); - } - else - { - llerrs << "LLViewerWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; - } -} - -F32 LLViewerWearable::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 - { - llwarns << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << llendl; - } - return (F32)-1.0; -} - -LLVisualParam* LLViewerWearable::getVisualParam(S32 index) const -{ - visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.find(index); - return (iter == mVisualParamIndexMap.end()) ? NULL : iter->second; -} - - -void LLViewerWearable::getVisualParams(visual_param_vec_t &list) -{ - visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); - visual_param_index_map_t::iterator end = mVisualParamIndexMap.end(); - - // add all visual params to the passed-in vector - for( ; iter != end; ++iter ) - { - list.push_back(iter->second); - } -} - -void LLViewerWearable::animateParams(F32 delta, BOOL upload_bake) -{ - for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin(); - iter != mVisualParamIndexMap.end(); - ++iter) - { - LLVisualParam *param = (LLVisualParam*) iter->second; - param->animate(delta, upload_bake); - } -} - -LLColor4 LLViewerWearable::getClothesColor(S32 te) const -{ - LLColor4 color; - U32 param_name[3]; - if( LLVOAvatar::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) - { - for( U8 index = 0; index < 3; index++ ) - { - color.mV[index] = getVisualParamWeight(param_name[index]); - } - } - return color; -} - -void LLViewerWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ) -{ - U32 param_name[3]; - if( LLVOAvatar::teToColorParams( (LLAvatarAppearanceDefines::ETextureIndex)te, param_name ) ) - { - for( U8 index = 0; index < 3; index++ ) - { - setVisualParamWeight(param_name[index], new_color.mV[index], upload_bake); - } - } -} - void LLViewerWearable::revertValues() { - //update saved settings so wearable is no longer dirty - // non-driver params first - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - F32 value = iter->second; - LLVisualParam *param = getVisualParam(id); - if(param && !dynamic_cast(param) ) - { - setVisualParamWeight(id, value, TRUE); - } - } - - //then driver params - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - F32 value = iter->second; - LLVisualParam *param = getVisualParam(id); - if(param && dynamic_cast(param) ) - { - setVisualParamWeight(id, value, TRUE); - } - } - - // make sure that saved values are sane - for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++) - { - S32 id = iter->first; - LLVisualParam *param = getVisualParam(id); - if( param ) - { - mSavedVisualParamMap[id] = param->getWeight(); - } - } - - syncImages(mSavedTEMap, mTEMap); + LLWearable::revertValues(); /*LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); @@ -1043,39 +478,9 @@ void LLViewerWearable::revertValues() } -BOOL LLViewerWearable::isOnTop() const -{ - return (this == gAgentWearables.getTopWearable(mType)); -} - -void LLViewerWearable::createLayers(S32 te) -{ - LLViewerTexLayerSet *layer_set = dynamic_cast(gAgentAvatarp->getLayerSet((ETextureIndex)te)); - if (layer_set) - { - layer_set->cloneTemplates(mTEMap[te], (ETextureIndex)te, this); - } - else - { - llerrs << "could not find layerset for LTO in wearable!" << llendl; - } -} - void LLViewerWearable::saveValues() { - //update saved settings so wearable is no longer dirty - mSavedVisualParamMap.clear(); - for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) - { - S32 id = iter->first; - LLVisualParam *wearable_param = iter->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); - + LLWearable::saveValues(); /*LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); if( panel ) @@ -1087,69 +492,6 @@ void LLViewerWearable::saveValues() gFloaterCustomize->updateScrollingPanelList(); } -void LLViewerWearable::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 (LLAvatarAppearanceDictionary::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 = LLViewerTextureManager::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 LLViewerWearable::destroyTextures() -{ - for( te_map_t::iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter ) - { - LLLocalTextureObject *lto = iter->second; - delete lto; - } - mTEMap.clear(); - for( te_map_t::iterator iter = mSavedTEMap.begin(); iter != mSavedTEMap.end(); ++iter ) - { - LLLocalTextureObject *lto = iter->second; - delete lto; - } - mSavedTEMap.clear(); -} - /*void LLViewerWearable::readFromAvatar() { LLVOAvatar* avatar = gAgentAvatarp; @@ -1189,7 +531,7 @@ void LLViewerWearable::destroyTextures() //} }*/ - +// virtual void LLViewerWearable::setUpdated() const { gInventory.addChangedMask(LLInventoryObserver::LABEL, getItemID()); @@ -1310,7 +652,7 @@ std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) //w.mSaleInfo s << " Params:" << "\n"; - for (LLViewerWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); + for (LLWearable::visual_param_index_map_t::const_iterator iter = w.mVisualParamIndexMap.begin(); iter != w.mVisualParamIndexMap.end(); ++iter) { S32 param_id = iter->first; @@ -1330,37 +672,6 @@ std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w) return s; } - -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; -} - std::string asset_id_to_filename(const LLUUID &asset_id) { std::string asset_id_string; diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index cf3f054b6..85d4faaf6 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -27,21 +27,10 @@ #ifndef LL_VIEWER_WEARABLE_H #define LL_VIEWER_WEARABLE_H -#include "lluuid.h" -#include "llstring.h" -#include "llpermissions.h" -#include "llsaleinfo.h" -#include "llassetstorage.h" -#include "llwearabletype.h" -#include "llfile.h" -#include "lllocaltextureobject.h" #include "llwearable.h" #include "llavatarappearancedefines.h" -class LLViewerInventoryItem; -class LLVisualParam; -class LLTexGlobalColorInfo; -class LLTexGlobalColor; +class LLVOAvatar; class LLViewerWearable : public LLWearable { @@ -61,76 +50,37 @@ public: // Accessors //-------------------------------------------------------------------- public: - const LLUUID& getItemID() const; + const LLUUID& getItemID() const { return mItemID; } const LLAssetID& getAssetID() const { return mAssetID; } const LLTransactionID& getTransactionID() const { return mTransactionID; } - - BOOL FileExportParams(FILE* file); - BOOL FileExportTextures(FILE* file); - - - LLWearableType::EType getType() const { return mType; } - void setType( LLWearableType::EType type ); - 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; } - virtual const LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index); + void setItemID(const LLUUID& item_id); public: - typedef std::vector visual_param_vec_t; BOOL isDirty() const; BOOL isOldVersion() const; - /*virtual*/ void writeToAvatar(LLAvatarAppearance* avatarp); + /*virtual*/ void writeToAvatar(LLAvatarAppearance *avatarp); void removeFromAvatar( BOOL upload_bake ) { LLViewerWearable::removeFromAvatar( mType, upload_bake ); } static void removeFromAvatar( LLWearableType::EType type, BOOL upload_bake ); - BOOL exportFile(LLFILE* file) const; - BOOL importFile(LLFILE* file); - + /*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); + void setParamsToDefaults(); void setTexturesToDefaults(); + /*virtual*/ const LLUUID getDefaultTextureImageID(LLAvatarAppearanceDefines::ETextureIndex index) const; + + void saveNewAsset() const; static void onSaveNewAssetComplete( const LLUUID& asset_uuid, void* user_data, S32 status, LLExtStat ext_status ); void copyDataFrom(const LLViewerWearable* src); - static void setCurrentDefinitionVersion( S32 version ) { LLViewerWearable::sCurrentDefinitionVersion = version; } - friend std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w); - void setItemID(const LLUUID& item_id); - LLLocalTextureObject* getLocalTextureObject(S32 index); - const LLLocalTextureObject* getLocalTextureObject(S32 index) const; - - void setLocalTextureObject(S32 index, LLLocalTextureObject <o); - void addVisualParam(LLVisualParam *param); - void setVisualParams(); - void setVisualParamWeight(S32 index, F32 value, BOOL upload_bake); - F32 getVisualParamWeight(S32 index) const; - LLVisualParam* getVisualParam(S32 index) const; - void getVisualParams(visual_param_vec_t &list); - void animateParams(F32 delta, BOOL upload_bake); - - LLColor4 getClothesColor(S32 te) const; - void setClothesColor( S32 te, const LLColor4& new_color, BOOL upload_bake ); - - void revertValues(); - void saveValues(); - - BOOL isOnTop() const; + /*virtual*/ void revertValues(); + /*virtual*/ void saveValues(); // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). void setUpdated() const; @@ -141,32 +91,11 @@ public: // Update the baked texture hash. /*virtual*/void addToBakedTextureHash(LLMD5& hash) const; -private: - typedef std::map te_map_t; - typedef std::map visual_param_index_map_t; - void createLayers(S32 te); - void createVisualParams(); - void syncImages(te_map_t &src, te_map_t &dst); - void destroyTextures(); - - 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; - LLAssetID mAssetID; +protected: + LLAssetID mAssetID; LLTransactionID mTransactionID; - LLWearableType::EType mType; - typedef std::map param_map_t; - param_map_t mSavedVisualParamMap; // last saved version of visual params - - visual_param_index_map_t mVisualParamIndexMap; - - te_map_t mTEMap; // maps TE to LocalTextureObject - te_map_t mSavedTEMap; // last saved version of TEMap LLUUID mItemID; // ID of the inventory item in the agent's inventory }; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 30f9e9267..62e9fe7a2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8073,82 +8073,6 @@ void LLVOAvatar::releaseComponentTextures() } } -//static -BOOL LLVOAvatar::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; - - default: - llassert(0); - return FALSE; - } - - return TRUE; -} - void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake ) { U32 param_name[3]; @@ -8252,6 +8176,16 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const return FALSE; } +LLTexLayerSet* LLVOAvatar::getAvatarLayerSet(EBakedTextureIndex baked_index) const +{ + /* switch(index) + case TEX_HEAD_BAKED: + case TEX_HEAD_BODYPAINT: + return mHeadLayerSet; */ + return mBakedTextureDatas[baked_index].mTexLayerSet; +} + + //----------------------------------------------------------------------------- // clampAttachmentPositions() //----------------------------------------------------------------------------- diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index c98ab0276..f9124f8bb 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -756,7 +756,6 @@ public: public: virtual void setClothesColor(LLAvatarAppearanceDefines::ETextureIndex te, const LLColor4& new_color, BOOL upload_bake); virtual LLColor4 getClothesColor(LLAvatarAppearanceDefines::ETextureIndex te); - static BOOL teToColorParams(LLAvatarAppearanceDefines::ETextureIndex te, U32 *param_name); //-------------------------------------------------------------------- // Global colors @@ -798,6 +797,7 @@ public: void cleanupAttachedMesh( LLViewerObject* pVO ); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; + virtual LLTexLayerSet* getAvatarLayerSet(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; protected: LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); void lazyAttach(); diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index a813bf04d..507ce57e7 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -112,16 +112,17 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID else if (status >= 0) { // read the file - LLFILE* fp = LLFile::fopen(std::string(filename), "rb"); /*Flawfinder: ignore*/ - if( !fp ) + llifstream ifs(filename, llifstream::binary); + if( !ifs.is_open() ) { LL_WARNS("Wearable") << "Bad Wearable Asset: unable to open file: '" << filename << "'" << LL_ENDL; } else { wearable = new LLViewerWearable(uuid); - bool res = wearable->importFile( fp ); - if (!res) + LLWearable::EImportResult result = wearable->importStream( + ifs, avatarp ); + if (LLWearable::SUCCESS != result) { if (wearable->getType() == LLWearableType::WT_COUNT) { @@ -131,9 +132,12 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID wearable = NULL; } - fclose( fp ); if(filename) { + if (ifs.is_open()) + { + ifs.close(); + } LLFile::remove(std::string(filename)); } } @@ -235,7 +239,7 @@ LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type, lldebugs << "LLWearableList::createNewWearable()" << llendl; LLViewerWearable *wearable = generateNewWearable(); - wearable->setType( type ); + wearable->setType( type, avatarp ); std::string name = LLTrans::getString( LLWearableType::getTypeDefaultNewName(wearable->getType()) ); wearable->setName( name );