diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index 65dd3cdde..47d14d2a1 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -117,7 +117,8 @@ public: /*virtual*/ void stopAnimating(BOOL upload_bake); /*virtual*/ BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params); /*virtual*/ void resetDrivenParams(); - + /*virtual*/ char const* getTypeString(void) const { return "param_driver"; } + // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); /*virtual*/ const LLVector4a& getAvgDistortion(); diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 03915d3da..f1ecef881 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -173,6 +173,7 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ); + /*virtual*/ char const* getTypeString(void) const { return "param_morph"; } // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index 774bc7dfa..a9b843af6 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -109,7 +109,8 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ); - + /*virtual*/ char const* getTypeString(void) const { return "param_skeleton"; } + // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 0.1f; } /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index b38d28d3e..64a465a59 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -86,6 +86,7 @@ public: /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); /*virtual*/ void animate(F32 delta, BOOL upload_bake); + /*virtual*/ char const* getTypeString(void) const { return "param_alpha"; } // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } @@ -177,7 +178,7 @@ public: /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); /*virtual*/ void setAnimationTarget(F32 target_value, BOOL upload_bake); /*virtual*/ void animate(F32 delta, BOOL upload_bake); - + /*virtual*/ char const* getTypeString(void) const { return "param_color"; } // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp index dd5331207..4a4f69c56 100644 --- a/indra/llappearance/llviewervisualparam.cpp +++ b/indra/llappearance/llviewervisualparam.cpp @@ -143,6 +143,12 @@ BOOL LLViewerVisualParam::setInfo(LLViewerVisualParamInfo *info) return TRUE; } +//virtual +std::string LLViewerVisualParam::getDumpWearableTypeName(void) const +{ + return LLWearableType::getTypeName(LLWearableType::EType(getInfo()->mWearableType)); +} + /* //============================================================================= // These virtual functions should always be overridden, diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index 64364c881..39d29fccb 100644 --- a/indra/llappearance/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h @@ -82,6 +82,7 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); + /*virtual*/ std::string getDumpWearableTypeName(void) const; // New Virtual functions virtual F32 getTotalDistortion() = 0; diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index b6049eb21..a944a16fd 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -41,6 +41,7 @@ class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; class LLAvatarAppearance; +class AIArchetype; // Abstract class. class LLWearable diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index a5864c15c..6cb1fcaa6 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -162,6 +162,10 @@ public: void setParamLocation(EParamLocation loc); EParamLocation getParamLocation() const { return mParamLocation; } + // Singu extensions. Used for dumping the archtype. + virtual char const* getTypeString(void) const = 0; + virtual std::string getDumpWearableTypeName(void) const = 0; + protected: F32 mCurWeight; // current weight F32 mLastWeight; // last weight diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0ebcc899f..c9ccca66f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -82,6 +82,7 @@ include_directories( set(viewer_SOURCE_FILES NACLantispam.cpp aihttpview.cpp + aixmllindengenepool.cpp aoremotectrl.cpp ascentfloatercontactgroups.cpp ascentkeyword.cpp @@ -598,6 +599,7 @@ set(viewer_HEADER_FILES NACLantispam.h aihttpview.h + aixmllindengenepool.h aoremotectrl.h ascentfloatercontactgroups.h ascentkeyword.h diff --git a/indra/newview/aixmllindengenepool.cpp b/indra/newview/aixmllindengenepool.cpp new file mode 100644 index 000000000..c2c9160f2 --- /dev/null +++ b/indra/newview/aixmllindengenepool.cpp @@ -0,0 +1,205 @@ +/** + * @file aixmllindengenepool.cpp + * @brief XML linden_genepool serialization support. + * + * Copyright (c) 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 01/11/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +// metaversion 1.0 +// =============== +// +// Added as child of : +// +// +// +// Optionally, as child of , the following node may appear: +// +// +// +// Furthermore, metaversion 1.0 and higher allow the occurance of one or more blocks. +// If this is used then it is strongly advised to use one per wearable, so that +// the the node makes sense (it then refers to the wearable of that ). +// +// The reason for this clumsy way to link wearable to extra meta data is to stay +// compatible with the older format (no metaversion). + +#include "sys.h" +#include "aixmllindengenepool.h" +#include "hippogridmanager.h" +#include "llvisualparam.h" +#include "llviewerwearable.h" +#include "llquantize.h" + +extern void append_path_short(LLUUID const& id, std::string& path); + +void AIXMLLindenGenepool::MetaData::toXML(std::ostream& os, int indentation) const +{ + AIXMLElement tag(os, "meta", indentation); + tag.attribute("gridnick", mGridNick); + tag.attribute(DEFAULT_LLDATE_NAME, mDate); +} + +AIXMLLindenGenepool::MetaData::MetaData(AIXMLElementParser const& parser) +{ + parser.attribute("gridnick", mGridNick); + parser.attribute(DEFAULT_LLDATE_NAME, mDate); +} + +AIXMLLindenGenepool::AIXMLLindenGenepool(LLFILE* fp) : AIXMLRootElement(fp, "linden_genepool") +{ + attribute("version", "1.0"); + attribute("metaversion", "1.0"); + child(MetaData(gHippoGridManager->getConnectedGrid()->getGridNick(), LLDate::now())); +} + +void AIVisualParamIDValuePair::toXML(std::ostream& os, int indentation) const +{ + LLVisualParam const* visual_param = mVisualParam; + if (!visual_param && mWearable) + { + visual_param = mWearable->getVisualParam(mID); + } + if (visual_param) + { + AIXMLElement tag(os, "param", indentation); + tag.attribute("id", mID); + tag.attribute("name", visual_param->getName()); + tag.attribute("value", mValue); + tag.attribute("u8", (U32)F32_to_U8(mValue, visual_param->getMinWeight(), visual_param->getMaxWeight())); + tag.attribute("type", visual_param->getTypeString()); + tag.attribute("wearable", visual_param->getDumpWearableTypeName()); + } +} + +AIVisualParamIDValuePair::AIVisualParamIDValuePair(AIXMLElementParser const& parser) +{ + // Only id and value are relevant. Ignore all other attributes. + parser.attribute("id", mID); + parser.attribute("value", mValue); +} + +void AITextureIDUUIDPair::toXML(std::ostream& os, int indentation) const +{ + AIXMLElement tag(os, "texture", indentation); + tag.attribute("te", mID); + tag.attribute(DEFAULT_LLUUID_NAME, mUUID); +} + +AITextureIDUUIDPair::AITextureIDUUIDPair(AIXMLElementParser const& parser) +{ + parser.attribute("te", mID); + parser.attribute(DEFAULT_LLUUID_NAME, mUUID); +} + +void AIArchetype::MetaData::toXML(std::ostream& os, int indentation) const +{ + AIXMLElement tag(os, "meta", indentation); + tag.attribute("path", mPath); + tag.attribute("name", mName); + tag.attribute("description", mDescription); +} + +AIArchetype::MetaData::MetaData(AIXMLElementParser const& parser) +{ + char const* missing = NULL; + if (!parser.attribute("path", mPath)) + { + missing = "path"; + } + if (!parser.attribute("name", mName)) + { + missing = "name"; + } + if (!parser.attribute("description", mDescription)) + { + missing = "description"; + } + if (missing) + { + THROW_ALERT("AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE", AIArgs("[ATTRIBUTE]", missing)); + } +} + +AIArchetype::MetaData::MetaData(LLViewerWearable const* wearable) : mName(wearable->getName()), mDescription(wearable->getDescription()) +{ + append_path_short(wearable->getItemID(), mPath); +} + +AIArchetype::AIArchetype(void) : mType(LLWearableType::WT_NONE) +{ +} + +AIArchetype::AIArchetype(LLWearableType::EType type) : mType(type) +{ +} + +AIArchetype::AIArchetype(LLViewerWearable const* wearable) : mType(wearable->getType()), mMetaData(wearable) +{ +} + +void AIArchetype::toXML(std::ostream& os, int indentation) const +{ + AIXMLElement tag(os, "archetype", indentation); + if (mType == LLWearableType::WT_NONE) + { + tag.attribute("name", "???"); + } + else + { + tag.attribute("name", LLWearableType::getTypeName(mType)); + } + if (!mMetaData.mPath.empty()) + { + tag.child(mMetaData); + } + tag.child(mParams.begin(), mParams.end()); + tag.child(mTextures.begin(), mTextures.end()); +} + +AIArchetype::AIArchetype(AIXMLElementParser const& parser) +{ + std::string name; + mType = LLWearableType::WT_NONE; + + if (!parser.attribute("name", name)) + { + llwarns << "The tag in file \"" << parser.filename() << "\" is missing the 'name' parameter." << llendl; + } + else if (name != "???") + { + mType = LLWearableType::typeNameToType(name); + } + if (parser.version() >= 1) + { + if (!parser.child("meta", mMetaData)) + { + THROW_ALERT("AIArchetype_archetype_has_no_meta"); + } + } + parser.push_back_children("param", mParams); + parser.push_back_children("texture", mTextures); +} + diff --git a/indra/newview/aixmllindengenepool.h b/indra/newview/aixmllindengenepool.h new file mode 100644 index 000000000..c3a5a65d6 --- /dev/null +++ b/indra/newview/aixmllindengenepool.h @@ -0,0 +1,150 @@ +/** + * @file aixmllindengenepool.h + * @brief XML linden_genepool serialization support. + * + * Copyright (c) 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * 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. + * + * CHANGELOG + * and additional copyright holders. + * + * 01/11/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AIXMLLINDENGENEPOOL_H +#define AIXMLLINDENGENEPOOL_H + +#include "aixml.h" +#include "llwearabletype.h" +#include "llviewervisualparam.h" +#include + +class LLViewerWearable; + +class AIXMLLindenGenepool : public AIXMLRootElement +{ + public: + struct MetaData + { + std::string mGridNick; + LLDate mDate; + + MetaData(void) { } + MetaData(std::string const& grid_nick, LLDate const& date) : mGridNick(grid_nick), mDate(date) { } + + void toXML(std::ostream& os, int indentation) const; + MetaData(AIXMLElementParser const& parser); + }; + + AIXMLLindenGenepool(LLFILE* fp); +}; + +class AIVisualParamIDValuePair +{ + private: + // A wearable + ID define the LLVisualParam, but it also possible to specify the LLVisualParam directly. + LLVisualParam const* mVisualParam; // Specific LLVisualParam, given at construction, or ... + LLViewerWearable const* mWearable; // Underlaying wearable, if any. + + U32 mID; // The visual parameter id. + F32 mValue; // The value of the visual parameter. + + public: + AIVisualParamIDValuePair(LLVisualParam const* visual_param) : + mVisualParam(visual_param), mWearable(NULL), mID(visual_param->getID()), mValue(visual_param->getWeight()) { } + + AIVisualParamIDValuePair(LLVisualParam const* visual_param, F32 value) : + mVisualParam(visual_param), mWearable(NULL), mID(visual_param->getID()), mValue(value) { } + + AIVisualParamIDValuePair(LLViewerWearable const* wearable, U32 id, F32 value) : + mVisualParam(NULL), mWearable(wearable), mID(id), mValue(value) { } + + void toXML(std::ostream& os, int indentation) const; + AIVisualParamIDValuePair(AIXMLElementParser const& parser); + + // Accessors. + U32 getID(void) const { return mID; } + F32 getValue(void) const { return mValue; } +}; + +class AITextureIDUUIDPair +{ + private: + U32 mID; + LLUUID mUUID; + + public: + AITextureIDUUIDPair(U32 id, LLUUID const& uuid) : mID(id), mUUID(uuid) { } + + void toXML(std::ostream& os, int indentation) const; + AITextureIDUUIDPair(AIXMLElementParser const& parser); + + // Accessors. + U32 getID(void) const { return mID; } + LLUUID const& getUUID(void) const { return mUUID; } +}; + +class AIArchetype +{ + public: + struct MetaData + { + std::string mPath; // The wearable location in the inventory. + std::string mName; // The wearable name. + std::string mDescription; // The wearable description. + + MetaData(void) { } + MetaData(LLViewerWearable const* wearable); + + void toXML(std::ostream& os, int indentation) const; + MetaData(AIXMLElementParser const& parser); + }; + + typedef std::vector params_type; + typedef std::vector textures_type; + + private: + LLWearableType::EType mType; // The type of the wearable. + MetaData mMetaData; + params_type mParams; + textures_type mTextures; + + public: + // Accessors. + LLWearableType::EType getType(void) const { return mType; } + MetaData const& getMetaData(void) const { return mMetaData; } + params_type const& getParams(void) const { return mParams; } + textures_type const& getTextures(void) const { return mTextures; } + + public: + // An archtype without wearable has no (known) metadata. This is recognized because mPath will be empty. + // An archtype without type with get the attribute name="???". + AIArchetype(void); // + AIArchetype(LLWearableType::EType type); // + AIArchetype(LLViewerWearable const* wearable); // + + void add(AIVisualParamIDValuePair const& visual_param_id_value_pair) { mParams.push_back(visual_param_id_value_pair); } + void add(AITextureIDUUIDPair const& texture_id_uuid_pair) { mTextures.push_back(texture_id_uuid_pair); } + + void toXML(std::ostream& os, int indentation) const; + AIArchetype(AIXMLElementParser const& parser); +}; + +#endif // AIXMLLINDENGENEPOOL_H diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 3a9e9f397..00890eb78 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -53,8 +53,9 @@ #include "llvoavatarself.h" #include "statemachine/aifilepicker.h" -#include "llxmltree.h" #include "hippogridmanager.h" +#include "aixmllindengenepool.h" +#include "aifile.h" using namespace LLAvatarAppearanceDefines; @@ -330,215 +331,117 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) LLPanelEditWearable* panel_edit_wearable = getCurrentWearablePanel(); LLViewerWearable* edit_wearable = panel_edit_wearable->getWearable(); + LLWearableType::EType panel_wearable_type = panel_edit_wearable->getType(); + std::string label = utf8str_tolower(panel_edit_wearable->getLabel()); + std::string const filename = filepicker->getFilename(); + LLSD args(LLSD::emptyMap()); args["FILE"] = gDirUtilp->getBaseFileName(filename); - LLXmlTree xml; - BOOL success = xml.parseFile(filename, FALSE); - if (!success) - { - LLNotificationsUtil::add("AIXMLImportParseError", args); - return; - } - LLXmlTreeNode* root = xml.getRoot(); - if (!root) - { - llwarns << "No root node found in wearable import file: " << filename << llendl; - LLNotificationsUtil::add("AIXMLImportParseError", args); - return; - } - - //------------------------------------------------------------------------- - // (root) - //------------------------------------------------------------------------- - if (!root->hasName("linden_genepool")) - { - llwarns << "Invalid wearable import file (missing linden_genepool header): " << filename << llendl; - LLNotificationsUtil::add("AIXMLImportRootTypeError", args); - return; - } - static LLStdStringHandle const version_string = LLXmlTree::addAttributeString("version"); - std::string version; - if (!root->getFastAttributeString(version_string, version) || (version != "1.0")) - { - llwarns << "Invalid or incompatible linden_genepool version: " << version << " in file: " << filename << llendl; - args["TAG"] = "version"; - args["VERSIONMAJOR"] = "1"; - LLNotificationsUtil::add("AIXMLImportRootVersionError", args); - return; - } - static LLStdStringHandle const metaversion_string = LLXmlTree::addAttributeString("metaversion"); - std::string metaversion; - U32 metaversion_major; - if (!root->getFastAttributeString(metaversion_string, metaversion)) - { - llwarns << "Invalid linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl; - metaversion_major = 0; - } - else if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1) - { - llwarns << "Invalid or incompatible linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl; - args["TAG"] = "metaversion"; - args["VERSIONMAJOR"] = "1"; - LLNotificationsUtil::add("AIXMLImportRootVersionError", args); - return; - } - - //------------------------------------------------------------------------- - // - //------------------------------------------------------------------------- - std::string gridnick; - LLDate date; - bool different_grid = false; // By default assume it was exported on the same grid as we're on now. - bool mixed_grids = false; // Set to true if two different grids (might) share UUIDs. Currently only "secondlife" and "secondlife_beta". - if (metaversion_major >= 1) - { - static LLStdStringHandle const gridnick_string = LLXmlTree::addAttributeString("gridnick"); - static LLStdStringHandle const date_string = LLXmlTree::addAttributeString("date"); - std::string date_s; - bool invalid = true; - LLXmlTreeNode* meta_node = root->getChildByName("meta"); - if (!meta_node) - { - llwarns << "No meta (1) in wearable import file: " << filename << llendl; - } - else if (!meta_node->getFastAttributeString(gridnick_string, gridnick)) - { - llwarns << "meta tag in file: " << filename << " is missing the 'gridnick' parameter." << llendl; - } - else if (!meta_node->getFastAttributeString(date_string, date_s) || !date.fromString(date_s)) - { - llwarns << "meta tag in file: " << filename << " is missing or invalid 'date' parameter." << llendl; - } - else - { - invalid = false; - std::string current_gridnick = gHippoGridManager->getConnectedGrid()->getGridNick(); - different_grid = gridnick != current_gridnick; - mixed_grids = (gridnick == "secondlife" && current_gridnick == "secondlife_beta") || - (gridnick == "secondlife_beta" && current_gridnick == "secondlife"); - } - if (invalid) - { - LLNotificationsUtil::add("AIXMLImportInvalidError", args); - return; - } - } - - static LLStdStringHandle const name_string = LLXmlTree::addAttributeString("name"); - - //------------------------------------------------------------------------- - // - //------------------------------------------------------------------------- - LLXmlTreeNode* archetype_node = root->getChildByName("archetype"); - if (!archetype_node) - { - llwarns << "No archetype in wearable import file: " << filename << llendl; - LLNotificationsUtil::add("AIXMLImportInvalidError", args); - return; - } - // Legacy that name="" exists. Using it as human (only) readable type label of contents. Don't use it for anything else because it might not be set. - std::string label = "???"; - if (metaversion_major >= 1) - { - if (!archetype_node->getFastAttributeString(name_string, label)) - { - llwarns << "archetype tag in file: " << filename << " is missing the 'name' parameter." << llendl; - } - } - - //------------------------------------------------------------------------- - // - //------------------------------------------------------------------------- - std::string path; - std::string wearable_name; - std::string wearable_description; - if (metaversion_major >= 1) - { - static LLStdStringHandle const path_string = LLXmlTree::addAttributeString("path"); - static LLStdStringHandle const description_string = LLXmlTree::addAttributeString("description"); - bool invalid = true; - LLXmlTreeNode* meta_node = archetype_node->getChildByName("meta"); - if (!meta_node) - { - llwarns << "No meta (2) in wearable import file: " << filename << llendl; - } - else if (!meta_node->getFastAttributeString(path_string, path)) - { - llwarns << "meta tag in file: " << filename << " is missing the 'path' parameter." << llendl; - } - else if (!meta_node->getFastAttributeString(name_string, wearable_name)) - { - llwarns << "meta tag in file: " << filename << " is missing the 'name' parameter." << llendl; - } - else if (!meta_node->getFastAttributeString(description_string, wearable_description)) - { - llwarns << "meta tag in file: " << filename << " is missing the 'description' parameter." << llendl; - } - else - { - invalid = false; - } - if (invalid) - { - LLNotificationsUtil::add("AIXMLImportInvalidError", args); - return; - } - } - - // Parse the XML content. - static LLStdStringHandle const id_string = LLXmlTree::addAttributeString("id"); - static LLStdStringHandle const value_string = LLXmlTree::addAttributeString("value"); - static LLStdStringHandle const te_string = LLXmlTree::addAttributeString("te"); - static LLStdStringHandle const uuid_string = LLXmlTree::addAttributeString("uuid"); bool found_param = false; bool found_texture = false; - for(LLXmlTreeNode* child = archetype_node->getFirstChild(); child; child = archetype_node->getNextChild()) + bool found_type = false; + + bool different_grid = false; // By default assume it was exported on the same grid as we're on now. + bool mixed_grids = false; // Set to true if two different grids (might) share UUIDs. Currently only "secondlife" and "secondlife_beta". + std::string gridnick; + std::string wearable_types; + + try { - if (child->hasName("param")) + //------------------------------------------------------------------------- + // (root) + //------------------------------------------------------------------------- + std::string metaversion; + U32 metaversion_major; + + AIXMLParser linden_genepool(filename, "wearable import file", "linden_genepool", 1); + linden_genepool.attribute("version", "1.0"); + linden_genepool.attribute("metaversion", metaversion); + + if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1) { - std::string id_s; - U32 id; - std::string value_s; - F32 value; - if (!child->getFastAttributeString(id_string, id_s) || !LLStringUtil::convertToU32(id_s, id) || - !child->getFastAttributeString(value_string, value_s) || !LLStringUtil::convertToF32(value_s, value)) - { - llwarns << "Possible syntax error or corruption for node in " << filename << llendl; - continue; - } - LLVisualParam* visual_param = edit_wearable->getVisualParam(id); - if (visual_param) - { - found_param = true; - visual_param->setWeight(value, FALSE); - } + llwarns << "Invalid or incompatible linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl; + args["TAG"] = "metaversion"; + args["VERSIONMAJOR"] = "1"; + LLNotificationsUtil::add("AIXMLImportRootVersionError", args); + return; } - else if (child->hasName("texture")) + + //------------------------------------------------------------------------- + // + //------------------------------------------------------------------------- + AIXMLLindenGenepool::MetaData meta_data; + + if (metaversion_major >= 1) { - std::string te_s; - S32 te; - std::string uuid_s; - LLUUID uuid; - if (!child->getFastAttributeString(te_string, te_s) || !LLStringUtil::convertToS32(te_s, te) || te < 0 || te >= TEX_NUM_INDICES || - !child->getFastAttributeString(uuid_string, uuid_s) || !uuid.set(uuid_s, TRUE)) + linden_genepool.child("meta", meta_data); + std::string current_gridnick = gHippoGridManager->getConnectedGrid()->getGridNick(); + gridnick = meta_data.mGridNick; + different_grid = gridnick != current_gridnick; + mixed_grids = (gridnick == "secondlife" && current_gridnick == "secondlife_beta") || + (gridnick == "secondlife_beta" && current_gridnick == "secondlife"); + } + + std::vector archetypes; + linden_genepool.setVersion(metaversion_major); + linden_genepool.push_back_children("archetype", archetypes); + + if (archetypes.empty()) + { + THROW_ALERT("AIXMLImportNoArchetypeError", AIArgs("[FILE]", filename)); + } + + for (std::vector::iterator archetype = archetypes.begin(); archetype != archetypes.end(); ++archetype) + { + LLWearableType::EType type = archetype->getType(); + if (type != LLWearableType::WT_NONE) { - llwarns << "Possible syntax error or corruption for node in " << filename << llendl; - continue; - } - ETextureIndex te_index = (ETextureIndex)te; - LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index); - if (te_wearable_type == edit_wearable->getType()) - { - found_texture = true; - if (!different_grid || mixed_grids) + if (!wearable_types.empty()) { - panel_edit_wearable->setNewImageID(te_index, uuid); + wearable_types += "/"; + } + wearable_types += LLWearableType::getTypeName(type); + if (panel_wearable_type == type) + { + found_type = true; + } + } + for (AIArchetype::params_type::const_iterator param = archetype->getParams().begin(); param != archetype->getParams().end(); ++param) + { + LLVisualParam* visual_param = edit_wearable->getVisualParam(param->getID()); + if (visual_param) + { + found_param = true; + visual_param->setWeight(param->getValue(), FALSE); + } + } + for (AIArchetype::textures_type::const_iterator texture = archetype->getTextures().begin(); texture != archetype->getTextures().end(); ++texture) + { + U32 te = texture->getID(); + if (te >= TEX_NUM_INDICES) + { + } + ETextureIndex te_index = (ETextureIndex)te; + LLWearableType::EType te_wearable_type = LLAvatarAppearanceDictionary::getTEWearableType(te_index); + if (te_wearable_type == edit_wearable->getType()) + { + found_texture = true; + if (!different_grid || mixed_grids) + { + panel_edit_wearable->setNewImageID(te_index, texture->getUUID()); + } } } } } + catch (AIAlert const& alert) + { + LLNotificationsUtil::add(AIAlert(AIAlertPrefix(), AIAlert::modal, "AIXMLImportError", AIArgs("[TYPE]", label), alert)); + return; + } + if (found_param || found_texture) { edit_wearable->writeToAvatar(gAgentAvatarp); @@ -558,10 +461,15 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) } } } - else + else if (found_type) { - args["TYPE"] = panel_edit_wearable->LLPanel::getLabel(); - args["ARCHETYPENAME"] = label; + args["TYPE"] = label; + LLNotificationsUtil::add("AIXMLImportEmptyArchetype", args); + } + else if (!wearable_types.empty()) + { + args["TYPE"] = label; + args["ARCHETYPENAME"] = wearable_types; LLNotificationsUtil::add("AIXMLImportWearableTypeMismatch", args); } } @@ -615,21 +523,29 @@ void LLFloaterCustomize::onBtnExport_continued(LLViewerWearable* edit_wearable, } std::string filename = filepicker->getFilename(); - LLSD args(LLSD::emptyMap()); - args["FILE"] = filename; - LLAPRFile outfile; - outfile.open(filename, LL_APR_WB); - if (!outfile.getFileHandle()) + bool success = false; + try { - llwarns << "Could not open \"" << filename << "\" for writing." << llendl; - LLNotificationsUtil::add("AIXMLExportWriteError", args); - return; + LLFILE* outfile = AIFile::fopen(filename, "wb"); + + AIXMLLindenGenepool linden_genepool(outfile); + linden_genepool.child(edit_wearable->getArchetype()); + + AIFile::close(outfile); + success = true; + } + catch (AIAlert const& alert) + { + LLNotificationsUtil::add(AIAlert(AIAlertPrefix(), AIAlert::modal, "AIXMLExportWriteError", AIArgs("[FILE]", filename), alert)); } - LLVOAvatar::dumpArchetypeXML_header(outfile, edit_wearable->getTypeName()); - edit_wearable->archetypeExport(outfile); - LLVOAvatar::dumpArchetypeXML_footer(outfile); + if (success) + { + LLSD args(LLSD::emptyMap()); + args["FILE"] = filename; + LLNotificationsUtil::add("AIXMLExportSuccess", args); + } } void LLFloaterCustomize::onBtnOk() diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index bdd03c0eb..7a8ea7338 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -40,6 +40,7 @@ #include "llviewerregion.h" #include "llinventoryobserver.h" #include "llinventoryfunctions.h" +#include "aixmllindengenepool.h" using namespace LLAvatarAppearanceDefines; @@ -134,32 +135,18 @@ LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_st return result; } -extern void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value); - -void LLViewerWearable::archetypeExport(LLAPRFile& file) const +AIArchetype LLViewerWearable::getArchetype(void) const { - apr_file_t* fp = file.getFileHandle(); - - std::string path; - append_path_short(mItemID, path); - apr_file_printf(fp, " \n", - LLXMLNode::escapeXML(path).c_str(), - LLXMLNode::escapeXML(mName).c_str(), - LLXMLNode::escapeXML(mDescription).c_str()); - + AIArchetype archetype(this); for (visual_param_index_map_t::const_iterator iter = mVisualParamIndexMap.begin(); iter != mVisualParamIndexMap.end(); ++iter) { - LLVisualParam const* param = iter->second; - dump_visual_param(file, param, param->getWeight()); + archetype.add(AIVisualParamIDValuePair(iter->second)); } for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter) { - S32 te = iter->first; - LLUUID const& image_id = iter->second->getID(); - apr_file_printf(fp, " \n", te, image_id.asString().c_str()); + archetype.add(AITextureIDUUIDPair(iter->first, iter->second->getID())); } - - apr_file_printf(fp, "\n"); + return archetype; } // Avatar parameter and texture definitions can change over time. diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 660594d26..fbf4c87a0 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -29,6 +29,7 @@ #include "llwearable.h" #include "llavatarappearancedefines.h" +#include "aixmllindengenepool.h" class LLVOAvatar; class LLAPRFile; @@ -67,8 +68,9 @@ public: /*virtual*/ EImportResult importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ); - void archetypeExport(LLAPRFile& file) const; - + // Singu extension. + AIArchetype getArchetype(void) const; + void setParamsToDefaults(); void setTexturesToDefaults(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index ed242be4e..f45787f25 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -112,6 +112,8 @@ #include "llfloaterexploreanimations.h" #include "aihttptimeoutpolicy.h" +#include "aixmllindengenepool.h" +#include "aifile.h" #include "llavatarname.h" @@ -7676,29 +7678,10 @@ bool LLVOAvatar::visualParamWeightsAreDefault() void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value) { - std::string type_string = "unknown"; - if (dynamic_cast(viewer_param)) - type_string = "param_alpha"; - if (dynamic_cast(viewer_param)) - type_string = "param_color"; - if (dynamic_cast(viewer_param)) - type_string = "param_driver"; - if (dynamic_cast(viewer_param)) - type_string = "param_morph"; - if (dynamic_cast(viewer_param)) - type_string = "param_skeleton"; - S32 wtype = -1; - LLViewerVisualParam const* vparam = dynamic_cast(viewer_param); - if (vparam) - { - wtype = vparam->getWearableType(); - } S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight()); apr_file_printf(file.getFileHandle(), " \n", - viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, type_string.c_str(), - LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str() -// param_location_name(vparam->getParamLocation()).c_str() - ); + viewer_param->getID(), viewer_param->getName().c_str(), value, u8_value, viewer_param->getTypeString(), + viewer_param->getDumpWearableTypeName().c_str()); } void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, @@ -8356,127 +8339,83 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara dumpArchetypeXML_cont(fullpath, group_by_wearables); } -// metaversion 1.0 -// =============== -// -// Added as child of : -// -// -// -// Optionally, as child of , the following node may appear: -// -// -// -// Furthermore, metaversion 1.0 and higher allow the occurance of one or more blocks. -// If this is used then it is strongly advised to use one per wearable, so that -// the the node makes sense (it then refers to the wearable of that ). -// -// The reason for this clumsy way to link wearable to extra meta data is to stay -// compatible with the older format (no metaversion). -// -//static -void LLVOAvatar::dumpArchetypeXML_header(LLAPRFile& file, std::string const& archetype_name) -{ - apr_file_t* fp = file.getFileHandle(); - apr_file_printf(fp, "\n"); - apr_file_printf(fp, "\n"); - apr_file_printf(fp, " \n", - LLXMLNode::escapeXML(gHippoGridManager->getConnectedGrid()->getGridNick()).c_str(), - LLDate::now().asString().c_str()); - apr_file_printf(fp, " \n", archetype_name.c_str()); -} - -//static -void LLVOAvatar::dumpArchetypeXML_footer(LLAPRFile& file) -{ - apr_file_t* fp = file.getFileHandle(); - apr_file_printf(fp, " \n"); - apr_file_printf(fp, "\n"); -} - void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_by_wearables) { - LLAPRFile outfile; - outfile.open(fullpath, LL_APR_WB ); - apr_file_t* file = outfile.getFileHandle(); - if (!file) + try { - return; + AIFile outfile(fullpath, "wb"); + AIXMLLindenGenepool linden_genepool(outfile); + + if (group_by_wearables) + { + for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) + { + AIArchetype archetype((LLWearableType::EType)type); + + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; + if( (viewer_param->getWearableType() == type) && + (viewer_param->isTweakable() ) ) + { + archetype.add(AIVisualParamIDValuePair(param)); + } + } + + for (U8 te = 0; te < TEX_NUM_INDICES; te++) + { + if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) + { + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + if( te_image ) + { + archetype.add(AITextureIDUUIDPair(te, te_image->getID())); + } + } + } + + linden_genepool.child(archetype); + } + } + else + { + // Just dump all params sequentially. + AIArchetype archetype; // Legacy: Type is set to WT_NONE and will result in . + + for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) + { + archetype.add(AIVisualParamIDValuePair(param)); + } + + for (U8 te = 0; te < TEX_NUM_INDICES; te++) + { + { + // MULTIPLE_WEARABLES: extend to multiple wearables? + LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); + if( te_image ) + { + archetype.add(AITextureIDUUIDPair(te, te_image->getID())); + } + } + } + + linden_genepool.child(archetype); + } + +#if 0 // Wasn't used anyway. + bool ultra_verbose = false; + if (isSelf() && ultra_verbose) + { + // show the cloned params inside the wearables as well. + gAgentAvatarp->dumpWearableInfo(outfile); + } +#endif } - else + catch(AIAlert const& alert) { - llinfos << "xmlfile write handle obtained : " << fullpath << llendl; + LLNotificationsUtil::add(AIAlert(AIAlertPrefix(), AIAlert::modal, "AIXMLdumpArchetypeXMLError", AIArgs("[FILENAME]", fullpath), alert)); } - - LLVOAvatar::dumpArchetypeXML_header(outfile); - - if (group_by_wearables) - { - for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++) - { - const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type); - apr_file_printf( file, "\n\t\t\n", wearable_name.c_str() ); - - for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) - { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - if( (viewer_param->getWearableType() == type) && - (viewer_param->isTweakable() ) ) - { - dump_visual_param(outfile, viewer_param, viewer_param->getWeight()); - } - } - - for (U8 te = 0; te < TEX_NUM_INDICES; te++) - { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) - { - // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); - if( te_image ) - { - std::string uuid_str; - te_image->getID().toString( uuid_str ); - apr_file_printf( file, "\t\t\n", te, uuid_str.c_str()); - } - } - } - } - } - else - { - // Just dump all params sequentially. - for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam()) - { - LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param; - dump_visual_param(outfile, viewer_param, viewer_param->getWeight()); - } - - for (U8 te = 0; te < TEX_NUM_INDICES; te++) - { - { - // MULTIPLE_WEARABLES: extend to multiple wearables? - LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); - if( te_image ) - { - std::string uuid_str; - te_image->getID().toString( uuid_str ); - apr_file_printf( file, "\t\t\n", te, uuid_str.c_str()); - } - } - } - - } - - LLVOAvatar::dumpArchetypeXML_footer(outfile); - - bool ultra_verbose = false; - if (isSelf() && ultra_verbose) - { - // show the cloned params inside the wearables as well. - gAgentAvatarp->dumpWearableInfo(outfile); - } - // File will close when handle goes out of scope } void LLVOAvatar::setVisibilityRank(U32 rank) diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index d8587485f..45fbc535a 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -69,18 +69,8 @@ - Export Failure: could not open file "[FILE]" for writing. - - Import Warning: could not apply textures: [FILE] was exported on grid "[GRIDNAME]" while the currentgrid is "[CURGRID]". - - Import Failure: could not read or parse wearable import file "[FILE]". - - Import Failure: the file "[FILE]" is not a linden_genepool XML file. - Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required. - Import Failure: the file "[FILE]" contains invalid data. - Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied! Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here! diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 919e2595a..62f3cf1e2 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -149,30 +149,9 @@ -Export Failure: could not open file "[FILE]" for writing. - - - -Import Warning: could not apply textures: [FILE] was exported on grid "[GRIDNAME]" while the currentgrid is "[CURGRID]". - - - -Import Failure: could not read or parse wearable import file "[FILE]". - - - -Import Failure: the file "[FILE]" is not a linden_genepool XML file. +Successfully exported wearable to "[FILE]". - -Import Failure: the file "[FILE]" contains invalid data. - - + +Import warning: the file "[FILE]" contains a wearable of the selected type ([TYPE]), +but contains no parameters or textures for that type. Nothing was imported. + + -Import Warning: the file "[FILE]" does not contain a wearable of type [TYPE]. +Import warning: the file "[FILE]" does not contain a wearable of type [TYPE]. It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing. diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index 8ed04b942..c384090a3 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -4400,4 +4400,13 @@ Try enclosing path to the editor with double quotes. Invalid UUID in [FILEDESC] "[FILENAME]". Invalid DATE ([DATE]) in [FILEDESC] "[FILENAME]". + + archetype has no <meta> element. + archetype <meta> element has no '[ATTRIBUTE]' attribute. + + Failure dumping archetype to "[FILENAME]": + The export to file "[FILE]" failed: + Failed to import the [TYPE] wearable: + No archetype found in wearable import file "[FILE]". + diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 97f3dff5b..423b2c941 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -73,30 +73,10 @@ - - Fallo de Exportación: no se puede abrir el archivo "[FILE]" para escritura. - - - - Aviso de Importación: No se pueden aplicar las texturas: El [FILE] fue exportado en el grid "[GRIDNAME]" mientras que el grid actual es "[CURGRID]". - - - - Fallo de Importación: no se puede leer o analizar el archivo de vestimenta para importar "[FILE]". - - - - Fallo de Importación: el archivo "[FILE]" no es un archivo linden_genepool XML. - - Fallo de Importación: el archivo "[FILE]" contiene datos linden_genepool XML con [TAG] erróneo. Se requiere Versión "[VERSIONMAJOR].0" o inferior. - - Fallo de Importación: el archivo "[FILE]" contiene datos inválidos. - - La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]). ¡No se aplicaron las UUIDs de las Texturas!