Add AIXMLLindenGenepool - redo of archetype export/import using AIXML*.
In order to remove code duplication, and as prove of concept,
I redid the linden_genepool archetype export and import (from the Edit
Appearance Floater), using AIXML and AIAlert.
The import/export code did shrink significantly, and became a lot
simpler. Although a new file pair (aixmllindengenepool.{cpp,h}) is
added to define the (de)serialization of the linden_genepool XML format,
that code is now centralized in one place, and still a lot simpler.
As a bonus however, every possible error is now semi-automatically
reported to the user with all details that might help to overcome
the problem, like file names and system errors.
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -41,6 +41,7 @@ class LLVisualParam;
|
||||
class LLTexGlobalColorInfo;
|
||||
class LLTexGlobalColor;
|
||||
class LLAvatarAppearance;
|
||||
class AIArchetype;
|
||||
|
||||
// Abstract class.
|
||||
class LLWearable
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
205
indra/newview/aixmllindengenepool.cpp
Normal file
205
indra/newview/aixmllindengenepool.cpp
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <linden_genepool>:
|
||||
//
|
||||
// <meta gridnick="secondlife" date="2013-07-16T16:49:00.40Z" />
|
||||
//
|
||||
// Optionally, as child of <archetype>, the following node may appear:
|
||||
//
|
||||
// <meta path="clothing/jackets" name="Purple jacket" description="A jacket with mainly the color purple" />
|
||||
//
|
||||
// Furthermore, metaversion 1.0 and higher allow the occurance of one or more <archetype> blocks.
|
||||
// If this is used then it is strongly advised to use one <archetype> per wearable, so that
|
||||
// the the <meta> node makes sense (it then refers to the wearable of that <archetype>).
|
||||
//
|
||||
// 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 <archetype> 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);
|
||||
}
|
||||
|
||||
150
indra/newview/aixmllindengenepool.h
Normal file
150
indra/newview/aixmllindengenepool.h
Normal file
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <vector>
|
||||
|
||||
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<AIVisualParamIDValuePair> params_type;
|
||||
typedef std::vector<AITextureIDUUIDPair> 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); // <archetype name="???">
|
||||
AIArchetype(LLWearableType::EType type); // <archetype name="shirt">
|
||||
AIArchetype(LLViewerWearable const* wearable); // <archetype name="shirt"> <meta path="myclothes" name="blue shirt" description="Awesome blue shirt">
|
||||
|
||||
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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// <linden_genepool version="1.0" [metaversion="?"]> (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;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// <meta gridnick="secondlife" date="2013-07-20T15:27:55.80Z">
|
||||
//-------------------------------------------------------------------------
|
||||
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");
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// <archetype 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;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// <meta path="Clothing" name="New Shirt27" description="Some description"/>
|
||||
//-------------------------------------------------------------------------
|
||||
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"))
|
||||
//-------------------------------------------------------------------------
|
||||
// <linden_genepool version="1.0" [metaversion="?"]> (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 <param id=... value=... /> 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"))
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// <meta gridnick="secondlife" date="2013-07-20T15:27:55.80Z">
|
||||
//-------------------------------------------------------------------------
|
||||
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<AIArchetype> 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<AIArchetype>::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 <texture te=... uuid=... /> 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()
|
||||
|
||||
@@ -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, " <meta path=\"%s\" name=\"%s\" description=\"%s\"/>\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, " <texture te=\"%i\" uuid=\"%s\"/>\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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<LLTexLayerParamAlpha const*>(viewer_param))
|
||||
type_string = "param_alpha";
|
||||
if (dynamic_cast<LLTexLayerParamColor const*>(viewer_param))
|
||||
type_string = "param_color";
|
||||
if (dynamic_cast<LLDriverParam const*>(viewer_param))
|
||||
type_string = "param_driver";
|
||||
if (dynamic_cast<LLPolyMorphTarget const*>(viewer_param))
|
||||
type_string = "param_morph";
|
||||
if (dynamic_cast<LLPolySkeletalDistortion const*>(viewer_param))
|
||||
type_string = "param_skeleton";
|
||||
S32 wtype = -1;
|
||||
LLViewerVisualParam const* vparam = dynamic_cast<LLViewerVisualParam const*>(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(), " <param id=\"%d\" name=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\"/>\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 <linden_genepool>:
|
||||
//
|
||||
// <meta gridnick="secondlife" date="2013-07-16T16:49:00.40Z"/>
|
||||
//
|
||||
// Optionally, as child of <archetype>, the following node may appear:
|
||||
//
|
||||
// <meta path="clothing/jackets" name="Purple jacket" description="A jacket with mainly the color purple">
|
||||
//
|
||||
// Furthermore, metaversion 1.0 and higher allow the occurance of one or more <archetype> blocks.
|
||||
// If this is used then it is strongly advised to use one <archetype> per wearable, so that
|
||||
// the the <meta> node makes sense (it then refers to the wearable of that <archetype>).
|
||||
//
|
||||
// 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, "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>\n");
|
||||
apr_file_printf(fp, "<linden_genepool version=\"1.0\" metaversion=\"1.0\">\n");
|
||||
apr_file_printf(fp, " <meta gridnick=\"%s\" date=\"%s\"/>\n",
|
||||
LLXMLNode::escapeXML(gHippoGridManager->getConnectedGrid()->getGridNick()).c_str(),
|
||||
LLDate::now().asString().c_str());
|
||||
apr_file_printf(fp, " <archetype name=\"%s\">\n", archetype_name.c_str());
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVOAvatar::dumpArchetypeXML_footer(LLAPRFile& file)
|
||||
{
|
||||
apr_file_t* fp = file.getFileHandle();
|
||||
apr_file_printf(fp, " </archetype>\n");
|
||||
apr_file_printf(fp, "</linden_genepool>\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 <archetype name="???">.
|
||||
|
||||
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<!-- wearable: %s -->\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<texture te=\"%i\" uuid=\"%s\"/>\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<texture te=\"%i\" uuid=\"%s\"/>\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)
|
||||
|
||||
@@ -69,18 +69,8 @@
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<notification name="AIXMLExportWriteError">Export Failure: could not open file "[FILE]" for writing.</notification>
|
||||
|
||||
<notification name="AIXMLImportGridMismatch">Import Warning: could not apply textures: [FILE] was exported on grid "[GRIDNAME]" while the currentgrid is "[CURGRID]".</notification>
|
||||
|
||||
<notification name="AIXMLImportParseError">Import Failure: could not read or parse wearable import file "[FILE]".</notification>
|
||||
|
||||
<notification name="AIXMLImportRootTypeError">Import Failure: the file "[FILE]" is not a linden_genepool XML file.</notification>
|
||||
|
||||
<notification name="AIXMLImportRootVersionError">Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required.</notification>
|
||||
|
||||
<notification name="AIXMLImportInvalidError">Import Failure: the file "[FILE]" contains invalid data.</notification>
|
||||
|
||||
<notification name="AIXMLImportDifferentGrid">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!</notification>
|
||||
|
||||
<notification name="AIXMLImportMixedGrid">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!</notification>
|
||||
|
||||
@@ -149,30 +149,9 @@
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AIXMLExportWriteError"
|
||||
name="AIXMLExportSuccess"
|
||||
type="alertmodal">
|
||||
Export Failure: could not open file "[FILE]" for writing.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alert.tga"
|
||||
name="AIXMLImportGridMismatch"
|
||||
type="alert">
|
||||
Import Warning: could not apply textures: [FILE] was exported on grid "[GRIDNAME]" while the currentgrid is "[CURGRID]".
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AIXMLImportParseError"
|
||||
type="alertmodal">
|
||||
Import Failure: could not read or parse wearable import file "[FILE]".
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AIXMLImportRootTypeError"
|
||||
type="alertmodal">
|
||||
Import Failure: the file "[FILE]" is not a linden_genepool XML file.
|
||||
Successfully exported wearable to "[FILE]".
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
@@ -182,13 +161,6 @@ 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.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AIXMLImportInvalidError"
|
||||
type="alertmodal">
|
||||
Import Failure: the file "[FILE]" contains invalid data.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AIXMLImportDifferentGrid"
|
||||
@@ -203,11 +175,19 @@ Import was successful but note that the wearable was exported on grid [EXPORTGRI
|
||||
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!
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alert.tga"
|
||||
name="AIXMLImportEmptyArchetype"
|
||||
type="alert">
|
||||
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.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alert.tga"
|
||||
name="AIXMLImportWearableTypeMismatch"
|
||||
type="alert">
|
||||
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.
|
||||
</notification>
|
||||
|
||||
|
||||
@@ -4400,4 +4400,13 @@ Try enclosing path to the editor with double quotes.
|
||||
<string name="AIXMLElementParser_read_child_Invalid_uuid_in_FILEDESC_FILENAME">Invalid UUID in [FILEDESC] "[FILENAME]".</string>
|
||||
<string name="AIXMLElementParser_read_child_Invalid_date_DATE_in_FILEDESC_FILENAME">Invalid DATE ([DATE]) in [FILEDESC] "[FILENAME]".</string>
|
||||
|
||||
<!-- AIArchetype exception alerts -->
|
||||
<string name="AIArchetype_archetype_has_no_meta">archetype has no <meta> element.</string>
|
||||
<string name="AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE">archetype <meta> element has no '[ATTRIBUTE]' attribute.</string>
|
||||
|
||||
<string name="AIXMLdumpArchetypeXMLError">Failure dumping archetype to "[FILENAME]":</string>
|
||||
<string name="AIXMLExportWriteError">The export to file "[FILE]" failed:</string>
|
||||
<string name="AIXMLImportError">Failed to import the [TYPE] wearable:</string>
|
||||
<string name="AIXMLImportNoArchetypeError">No archetype found in wearable import file "[FILE]".</string>
|
||||
|
||||
</strings>
|
||||
|
||||
@@ -73,30 +73,10 @@
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<notification name="AIXMLExportWriteError">
|
||||
Fallo de Exportación: no se puede abrir el archivo "[FILE]" para escritura.
|
||||
</notification>
|
||||
|
||||
<notification name="AIXMLImportGridMismatch">
|
||||
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]".
|
||||
</notification>
|
||||
|
||||
<notification name="AIXMLImportParseError">
|
||||
Fallo de Importación: no se puede leer o analizar el archivo de vestimenta para importar "[FILE]".
|
||||
</notification>
|
||||
|
||||
<notification name="AIXMLImportRootTypeError">
|
||||
Fallo de Importación: el archivo "[FILE]" no es un archivo linden_genepool XML.
|
||||
</notification>
|
||||
|
||||
<notification name="AIXMLImportRootVersionError">
|
||||
Fallo de Importación: el archivo "[FILE]" contiene datos linden_genepool XML con [TAG] erróneo. Se requiere Versión "[VERSIONMAJOR].0" o inferior.
|
||||
</notification>
|
||||
|
||||
<notification name="AIXMLImportInvalidError">
|
||||
Fallo de Importación: el archivo "[FILE]" contiene datos inválidos.
|
||||
</notification>
|
||||
|
||||
<notification name="AIXMLImportDifferentGrid">
|
||||
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!
|
||||
</notification>
|
||||
|
||||
Reference in New Issue
Block a user