From 146919fa764bed09bfa5e27bc30d02ce2afb6188 Mon Sep 17 00:00:00 2001
From: Aura Linden <aura@lindenlab.com>
Date: Wed, 11 Nov 2015 13:44:51 -0800
Subject: [PATCH] animations and meshes will recognize all joint names in
 joint_aliases.xml

---
 indra/llcharacter/llbvhloader.cpp            | 589 +++----------------
 indra/llcharacter/llbvhloader.h              |  11 +-
 indra/llprimitive/lldaeloader.cpp            |   4 +-
 indra/llprimitive/lldaeloader.h              |   1 +
 indra/llprimitive/llmodelloader.cpp          |  71 +--
 indra/llprimitive/llmodelloader.h            |   3 +-
 indra/newview/CMakeLists.txt                 |   2 +-
 indra/newview/app_settings/anim.ini          |  87 ---
 indra/newview/app_settings/joint_aliases.xml |  97 +++
 indra/newview/llfloaterbvhpreview.cpp        |  18 +-
 indra/newview/llfloaterbvhpreview.h          |   3 +-
 indra/newview/llfloatermodelpreview.cpp      |   7 +
 indra/newview/llstartup.cpp                  |   2 +-
 indra/newview/llvoavatar.cpp                 |  23 +
 indra/newview/llvoavatar.h                   |   3 +
 15 files changed, 257 insertions(+), 664 deletions(-)
 delete mode 100755 indra/newview/app_settings/anim.ini
 create mode 100755 indra/newview/app_settings/joint_aliases.xml

diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index 4dedeeab527..cc2505a5ab4 100755
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -37,6 +37,7 @@
 #include "llquantize.h"
 #include "llstl.h"
 #include "llapr.h"
+#include "llsdserialize.h"
 
 
 using namespace std;
@@ -122,47 +123,21 @@ LLQuaternion::Order bvhStringToOrder( char *str )
 // LLBVHLoader()
 //-----------------------------------------------------------------------------
 
-/*
- LLBVHLoader::LLBVHLoader(const char* buffer)
+LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::deque<std::string>& legal_joint_names)
 {
 	reset();
+	errorLine = 0;
+    
+    // Recognize all names we've been told are legal.
+    for (std::deque<std::string>::iterator joint_name_it = legal_joint_names.begin();
+         joint_name_it != legal_joint_names.end(); ++joint_name_it)
+    {
+        const std::string& name = *joint_name_it;
 
-	mStatus = loadTranslationTable("anim.ini");
-
-	if (mStatus == LLBVHLoader::ST_NO_XLT_FILE)
-	{
-		LL_WARNS() << "NOTE: No translation table found." << LL_ENDL;
-		return;
-	}
-	else
-	{
-		if (mStatus != LLBVHLoader::ST_OK)
-		{
-			LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
-			return;
-		}
-	}
-
-	char error_text[128];		// Flawfinder: ignore 
-	S32 error_line;
-	mStatus = loadBVHFile(buffer, error_text, error_line);
-	if (mStatus != LLBVHLoader::ST_OK)
-	{
-		LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL;
-		return;
-	}
-
-	applyTranslations();
-	optimize();
+        makeTranslation(name, name);
+    }
 
-	mInitialized = TRUE;
-}
-*/
-LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine)
-{
-	reset();
-	errorLine = 0;
-	mStatus = loadTranslationTable("anim.ini");
+	mStatus = loadAliases("joint_aliases.xml"); //Load joint name aliases
 	loadStatus = mStatus;
 	LL_INFOS("BVH") << "Load Status 00 : " << loadStatus << LL_ENDL;
 	if (mStatus == E_ST_NO_XLT_FILE)
@@ -184,7 +159,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error
 	
 	char error_text[128];		/* Flawfinder: ignore */
 	S32 error_line;
-	mStatus = loadBVHFile(buffer, error_text, error_line);
+	mStatus = loadBVHFile(buffer, error_text, error_line); //Reads all joints in BVH file.
 
 	LL_DEBUGS("BVH") << "============================================================" << LL_ENDL;
 	LL_DEBUGS("BVH") << "Raw data from file" << LL_ENDL;
@@ -198,7 +173,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error
 		return;
 	}
 	
-	applyTranslations();
+	applyTranslations();  //Maps between joints found in file and the aliased names.
 	optimize();
 	
 	LL_DEBUGS("BVH") << "============================================================" << LL_ENDL;
@@ -215,464 +190,64 @@ LLBVHLoader::~LLBVHLoader()
 	mJoints.clear();
 }
 
-//------------------------------------------------------------------------
-// LLBVHLoader::loadTranslationTable()
-//------------------------------------------------------------------------
-ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
+void LLBVHLoader::makeTranslation(std::string alias_name, std::string joint_name)
 {
-	mLineNumber = 0;
-	mTranslations.clear();
-	mConstraints.clear();
-
-	//--------------------------------------------------------------------
-	// open file
-	//--------------------------------------------------------------------
-	std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName);
-
-	LLAPRFile infile ;
-	infile.open(path, LL_APR_R);
-	apr_file_t *fp = infile.getFileHandle();
-	if (!fp)
-		return E_ST_NO_XLT_FILE;
-
-	LL_INFOS("BVH") << "NOTE: Loading translation table: " << fileName << LL_ENDL;
-
-	//--------------------------------------------------------------------
-	// register file to be closed on function exit
-	//--------------------------------------------------------------------
-	
-	//--------------------------------------------------------------------
-	// load header
-	//--------------------------------------------------------------------
-	if ( ! getLine(fp) )
-		return E_ST_EOF;
-	if ( strncmp(mLine, "Translations 1.0", 16) )
-		return E_ST_NO_XLT_HEADER;
-
-	//--------------------------------------------------------------------
-	// load data one line at a time
-	//--------------------------------------------------------------------
-	BOOL loadingGlobals = FALSE;
-	Translation *trans = NULL;
-	while ( getLine(fp) )
-	{
-		//----------------------------------------------------------------
-		// check the 1st token on the line to determine if it's empty or a comment
-		//----------------------------------------------------------------
-		char token[128]; /* Flawfinder: ignore */
-		if ( sscanf(mLine, " %127s", token) != 1 )	/* Flawfinder: ignore */
-			continue;
-
-		if (token[0] == '#')
-			continue;
-
-		//----------------------------------------------------------------
-		// check if a [jointName] or [GLOBALS] was specified.
-		//----------------------------------------------------------------
-		if (token[0] == '[')
-		{
-			char name[128]; /* Flawfinder: ignore */
-			if ( sscanf(mLine, " [%127[^]]", name) != 1 )
-				return E_ST_NO_XLT_NAME;
-
-			if (strcmp(name, "GLOBALS")==0)
-			{
-				loadingGlobals = TRUE;
-				continue;
-			}
-			else
-			{
-				loadingGlobals = FALSE;
-				Translation &newTrans = mTranslations[ name ];
-				trans = &newTrans;
-				continue;
-			}
-		}
-
-		//----------------------------------------------------------------
-		// check for optional emote 
-		//----------------------------------------------------------------
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "emote")==0)
-		{
-			char emote_str[1024];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_EMOTE;
-
-			mEmoteName.assign( emote_str );
-//			LL_INFOS() << "NOTE: Emote: " << mEmoteName.c_str() << LL_ENDL;
-			continue;
-		}
-
-
-		//----------------------------------------------------------------
-		// check for global priority setting
-		//----------------------------------------------------------------
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "priority")==0)
-		{
-			S32 priority;
-			if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
-				return E_ST_NO_XLT_PRIORITY;
-
-			mPriority = priority;
-//			LL_INFOS() << "NOTE: Priority: " << mPriority << LL_ENDL;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for global loop setting
-		//----------------------------------------------------------------
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "loop")==0)
-		{
-			char trueFalse[128];		/* Flawfinder: ignore */
-			trueFalse[0] = '\0';
-			
-			F32 loop_in = 0.f;
-			F32 loop_out = 1.f;
-
-			if ( sscanf(mLine, " %*s = %f %f", &loop_in, &loop_out) == 2 )
-			{
-				mLoop = TRUE;
-			}
-			else if ( sscanf(mLine, " %*s = %127s", trueFalse) == 1 )	/* Flawfinder: ignore */	
-			{
-				mLoop = (LLStringUtil::compareInsensitive(trueFalse, "true")==0);
-			}
-			else
-			{
-				return E_ST_NO_XLT_LOOP;
-			}
-
-			mLoopInPoint = loop_in * mDuration;
-			mLoopOutPoint = loop_out * mDuration;
-
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for global easeIn setting
-		//----------------------------------------------------------------
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "easein")==0)
-		{
-			F32 duration;
-			char type[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_EASEIN;
-
-			mEaseIn = duration;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for global easeOut setting
-		//----------------------------------------------------------------
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "easeout")==0)
-		{
-			F32 duration;
-			char type[128];		/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_EASEOUT;
-
-			mEaseOut = duration;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for global handMorph setting
-		//----------------------------------------------------------------
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "hand")==0)
-		{
-			S32 handMorph;
-			if (sscanf(mLine, " %*s = %d", &handMorph) != 1)
-				return E_ST_NO_XLT_HAND;
-
-			mHand = handMorph;
-			continue;
-		}
-
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "constraint")==0)
-		{
-			Constraint constraint;
-
-			// try reading optional target direction
-			if(sscanf( /* Flawfinder: ignore */
-				mLine,
-				" %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f", 
-				&constraint.mChainLength,
-				&constraint.mEaseInStart,
-				&constraint.mEaseInStop,
-				&constraint.mEaseOutStart,
-				&constraint.mEaseOutStop,
-				constraint.mSourceJointName,
-				&constraint.mSourceOffset.mV[VX],
-				&constraint.mSourceOffset.mV[VY],
-				&constraint.mSourceOffset.mV[VZ],
-				constraint.mTargetJointName,
-				&constraint.mTargetOffset.mV[VX],
-				&constraint.mTargetOffset.mV[VY],
-				&constraint.mTargetOffset.mV[VZ],
-				&constraint.mTargetDir.mV[VX],
-				&constraint.mTargetDir.mV[VY],
-				&constraint.mTargetDir.mV[VZ]) != 16)
-			{
-				if(sscanf( /* Flawfinder: ignore */
-					mLine,
-					" %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f", 
-					&constraint.mChainLength,
-					&constraint.mEaseInStart,
-					&constraint.mEaseInStop,
-					&constraint.mEaseOutStart,
-					&constraint.mEaseOutStop,
-					constraint.mSourceJointName,
-					&constraint.mSourceOffset.mV[VX],
-					&constraint.mSourceOffset.mV[VY],
-					&constraint.mSourceOffset.mV[VZ],
-					constraint.mTargetJointName,
-					&constraint.mTargetOffset.mV[VX],
-					&constraint.mTargetOffset.mV[VY],
-					&constraint.mTargetOffset.mV[VZ]) != 13)
-				{
-					return E_ST_NO_CONSTRAINT;
-				}
-			}
-			else
-			{
-				// normalize direction
-				if (!constraint.mTargetDir.isExactlyZero())
-				{
-					constraint.mTargetDir.normVec();
-				}
-
-			}
-			
-			constraint.mConstraintType = CONSTRAINT_TYPE_POINT;
-			mConstraints.push_back(constraint);
-			continue;
-		}
-
-		if (loadingGlobals && LLStringUtil::compareInsensitive(token, "planar_constraint")==0)
-		{
-			Constraint constraint;
-
-			// try reading optional target direction
-			if(sscanf( /* Flawfinder: ignore */
-				mLine,
-				" %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f", 
-				&constraint.mChainLength,
-				&constraint.mEaseInStart,
-				&constraint.mEaseInStop,
-				&constraint.mEaseOutStart,
-				&constraint.mEaseOutStop,
-				constraint.mSourceJointName,
-				&constraint.mSourceOffset.mV[VX],
-				&constraint.mSourceOffset.mV[VY],
-				&constraint.mSourceOffset.mV[VZ],
-				constraint.mTargetJointName,
-				&constraint.mTargetOffset.mV[VX],
-				&constraint.mTargetOffset.mV[VY],
-				&constraint.mTargetOffset.mV[VZ],
-				&constraint.mTargetDir.mV[VX],
-				&constraint.mTargetDir.mV[VY],
-				&constraint.mTargetDir.mV[VZ]) != 16)
-			{
-				if(sscanf( /* Flawfinder: ignore */
-					mLine,
-					" %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f", 
-					&constraint.mChainLength,
-					&constraint.mEaseInStart,
-					&constraint.mEaseInStop,
-					&constraint.mEaseOutStart,
-					&constraint.mEaseOutStop,
-					constraint.mSourceJointName,
-					&constraint.mSourceOffset.mV[VX],
-					&constraint.mSourceOffset.mV[VY],
-					&constraint.mSourceOffset.mV[VZ],
-					constraint.mTargetJointName,
-					&constraint.mTargetOffset.mV[VX],
-					&constraint.mTargetOffset.mV[VY],
-					&constraint.mTargetOffset.mV[VZ]) != 13)
-				{
-					return E_ST_NO_CONSTRAINT;
-				}
-			}
-			else
-			{
-				// normalize direction
-				if (!constraint.mTargetDir.isExactlyZero())
-				{
-					constraint.mTargetDir.normVec();
-				}
-
-			}
-			
-			constraint.mConstraintType = CONSTRAINT_TYPE_PLANE;
-			mConstraints.push_back(constraint);
-			continue;
-		}
-
-
-		//----------------------------------------------------------------
-		// at this point there must be a valid trans pointer
-		//----------------------------------------------------------------
-		if ( ! trans )
-			return E_ST_NO_XLT_NAME;
-
-		//----------------------------------------------------------------
-		// check for ignore flag
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "ignore")==0 )
-		{
-			char trueFalse[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_IGNORE;
-
-			trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0);
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for relativepos flag
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "relativepos")==0 )
-		{
-			F32 x, y, z;
-			char relpos[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %f %f %f", &x, &y, &z) == 3 )
-			{
-				trans->mRelativePosition.setVec( x, y, z );
-			}
-			else if ( sscanf(mLine, " %*s = %127s", relpos) == 1 )	/* Flawfinder: ignore */
-			{
-				if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 )
-				{
-					trans->mRelativePositionKey = TRUE;
-				}
-				else
-				{
-					return E_ST_NO_XLT_RELATIVE;
-				}
-			}
-			else
-			{
-				return E_ST_NO_XLT_RELATIVE;
-			}
-
-			continue;
-		}
+    //Translation &newTrans = (foomap.insert(value_type(alias_name, Translation()))).first();
+    Translation &newTrans = mTranslations[ alias_name ];  //Uses []'s implicit call to ctor.
+    
+    newTrans.mOutName = joint_name;
+    LLMatrix3 fm;
+    LLVector3 vect1(0, 1, 0);
+    LLVector3 vect2(0, 0, 1);
+    LLVector3 vect3(1, 0, 0);
+    fm.setRows(vect1, vect2, vect3);
+    
+    newTrans.mFrameMatrix = fm;
+    
+    if (joint_name == "mPelvis")
+    {
+        newTrans.mRelativePositionKey = TRUE;
+        newTrans.mRelativeRotationKey = TRUE;
+    }
 
-		//----------------------------------------------------------------
-		// check for relativerot flag
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "relativerot")==0 )
-		{
-			//F32 x, y, z;
-			char relpos[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %127s", relpos) == 1 )	/* Flawfinder: ignore */
-			{
-				if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 )
-				{
-					trans->mRelativeRotationKey = TRUE;
-				}
-				else
-				{
-					return E_ST_NO_XLT_RELATIVE;
-				}
-			}
-			else
-			{
-				return E_ST_NO_XLT_RELATIVE;
-			}
-
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for outname value
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "outname")==0 )
-		{
-			char outName[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %127s", outName) != 1 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_OUTNAME;
-
-			trans->mOutName = outName;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for frame matrix value
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "frame")==0 )
-		{
-			LLMatrix3 fm;
-			if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f",
-					&fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2],
-					&fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2],
-					&fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2]	) != 9 )
-				return E_ST_NO_XLT_MATRIX;
-
-			trans->mFrameMatrix = fm;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for offset matrix value
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "offset")==0 )
-		{
-			LLMatrix3 om;
-			if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f",
-					&om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2],
-					&om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2],
-					&om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2]	) != 9 )
-				return E_ST_NO_XLT_MATRIX;
-
-			trans->mOffsetMatrix = om;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for mergeparent value
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "mergeparent")==0 )
-		{
-			char mergeParentName[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_MERGEPARENT;
-
-			trans->mMergeParentName = mergeParentName;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for mergechild value
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "mergechild")==0 )
-		{
-			char mergeChildName[128];	/* Flawfinder: ignore */
-			if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 )	/* Flawfinder: ignore */
-				return E_ST_NO_XLT_MERGECHILD;
-
-			trans->mMergeChildName = mergeChildName;
-			continue;
-		}
-
-		//----------------------------------------------------------------
-		// check for per-joint priority
-		//----------------------------------------------------------------
-		if ( LLStringUtil::compareInsensitive(token, "priority")==0 )
-		{
-			S32 priority;
-			if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
-				return E_ST_NO_XLT_PRIORITY;
-
-			trans->mPriorityModifier = priority;
-			continue;
-		}
-
-	}
+}
 
-	infile.close() ;
-	return E_ST_OK;
+ELoadStatus LLBVHLoader::loadAliases(const char * filename)
+{
+    LLSD aliases_sd;
+ 
+    std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,filename);
+    
+    llifstream input_stream;
+    input_stream.open(fullpath.c_str(), std::ios::in | std::ios::binary);
+    
+    if(input_stream.is_open())
+    {
+        if ( LLSDSerialize::fromXML(aliases_sd, input_stream) )
+        {
+            for(LLSD::map_iterator alias_iter = aliases_sd.beginMap();
+                alias_iter != aliases_sd.endMap();
+                ++alias_iter)
+            {
+                LLSD::String alias_name = alias_iter->first;
+                LLSD::String joint_name = alias_iter->second;
+                makeTranslation(alias_name, joint_name);
+                
+            }
+        }
+        else
+        {
+            return E_ST_NO_XLT_HEADER;
+        }
+        input_stream.close();
+    }
+    else
+    {
+        LL_WARNS("BVH") << "Can't open joint alias file " << fullpath << LL_ENDL;
+        return E_ST_NO_XLT_FILE;
+    }
+
+    return E_ST_OK;
 }
 
 void LLBVHLoader::dumpBVHInfo()
@@ -1374,6 +949,7 @@ void LLBVHLoader::reset()
 	mInitialized = FALSE;
 
 	mEmoteName = "";
+    mTranslations.clear();
 }
 
 //------------------------------------------------------------------------
@@ -1603,28 +1179,7 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)
 		}
 	}
 
-	S32 num_constraints = (S32)mConstraints.size();
-	dp.packS32(num_constraints, "num_constraints");
-
-	for (ConstraintVector::iterator constraint_it = mConstraints.begin();
-		constraint_it != mConstraints.end();
-		constraint_it++)
-		{
-			U8 byte = constraint_it->mChainLength;
-			dp.packU8(byte, "chain_length");
-			
-			byte = constraint_it->mConstraintType;
-			dp.packU8(byte, "constraint_type");
-			dp.packBinaryDataFixed((U8*)constraint_it->mSourceJointName, 16, "source_volume");
-			dp.packVector3(constraint_it->mSourceOffset, "source_offset");
-			dp.packBinaryDataFixed((U8*)constraint_it->mTargetJointName, 16, "target_volume");
-			dp.packVector3(constraint_it->mTargetOffset, "target_offset");
-			dp.packVector3(constraint_it->mTargetDir, "target_dir");
-			dp.packF32(constraint_it->mEaseInStart,	"ease_in_start");
-			dp.packF32(constraint_it->mEaseInStop,	"ease_in_stop");
-			dp.packF32(constraint_it->mEaseOutStart,	"ease_out_start");
-			dp.packF32(constraint_it->mEaseOutStop,	"ease_out_stop");
-		}
-
+	dp.packS32(0, "num_constraints");
+	
 	return TRUE;
 }
diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h
index 033d8714a9b..a0207750ed9 100755
--- a/indra/llcharacter/llbvhloader.h
+++ b/indra/llcharacter/llbvhloader.h
@@ -32,6 +32,7 @@
 #include "llmath.h"
 #include "llapr.h"
 #include "llbvhconsts.h"
+#include <deque>
 
 const S32 BVH_PARSER_LINE_SIZE = 2048;
 class LLDataPacker;
@@ -228,7 +229,8 @@ class LLBVHLoader
 public:
 	// Constructor
 //	LLBVHLoader(const char* buffer);
-	LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine);
+    LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine);
+	LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::deque<std::string>& legal_joint_names);
 	~LLBVHLoader();
 
 /*	
@@ -267,9 +269,16 @@ class LLBVHLoader
 	static const char *ST_NO_XLT_EMOTE;
 	static const char *ST_BAD_ROOT;
 */
+
 	// Loads the specified translation table.
 	ELoadStatus loadTranslationTable(const char *fileName);
 
+    //Create a new joint alias
+    void makeTranslation(std::string key, std::string value);
+    
+    // Loads joint aliases from XML file.
+    ELoadStatus loadAliases(const char * filename);
+
 	// Load the specified BVH file.
 	// Returns status code.
 	ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line);
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index c50db824af6..63457512ffd 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -811,6 +811,7 @@ LLDAELoader::LLDAELoader(
 	JointTransformMap&	jointTransformMap,
 	JointNameSet&		jointsFromNodes,
     JointNameSet&		legalJointNames,
+    std::string         jointAliasesFilename,
 	U32					modelLimit)
 : LLModelLoader(
 		filename,
@@ -822,7 +823,8 @@ LLDAELoader::LLDAELoader(
 		opaque_userdata,
 		jointTransformMap,
 		jointsFromNodes,
-        legalJointNames),
+        legalJointNames,
+        jointAliasesFilename),
 mGeneratedModelLimit(modelLimit)
 {
 }
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 79856741db6..52ad9d47055 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -57,6 +57,7 @@ class LLDAELoader : public LLModelLoader
 		JointTransformMap&					jointTransformMap,
 		JointNameSet&						jointsFromNodes,
         JointNameSet&						legalJointNames,
+        std::string                         jointAliasesFilename,
 		U32									modelLimit);
 	virtual ~LLDAELoader() ;
 
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index 9cf0f10a7e4..b4bd467c64e 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -111,7 +111,8 @@ LLModelLoader::LLModelLoader(
 	void*				opaque_userdata,
 	JointTransformMap&	jointTransformMap,
 	JointNameSet&		jointsFromNodes,
-    JointNameSet&		legalJointNames)
+    JointNameSet&		legalJointNames,
+    std::string         jointAliasFilename)
 : mJointList( jointTransformMap )
 , mJointsFromNode( jointsFromNodes )
 , LLThread("Model Loader")
@@ -135,57 +136,27 @@ LLModelLoader::LLModelLoader(
         const std::string& name = *joint_name_it;
         mJointMap[name] = name;
     }
+    
 
     // Also support various legacy aliases for commonly used joints
-	mJointMap["avatar_mPelvis"] = "mPelvis";
-	mJointMap["avatar_mTorso"] = "mTorso";
-	mJointMap["avatar_mChest"] = "mChest";
-	mJointMap["avatar_mNeck"] = "mNeck";
-	mJointMap["avatar_mHead"] = "mHead";
-	mJointMap["avatar_mSkull"] = "mSkull";
-	mJointMap["avatar_mEyeRight"] = "mEyeRight";
-	mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
-	mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
-	mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
-	mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
-	mJointMap["avatar_mWristLeft"] = "mWristLeft";
-	mJointMap["avatar_mCollarRight"] = "mCollarRight";
-	mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
-	mJointMap["avatar_mElbowRight"] = "mElbowRight";
-	mJointMap["avatar_mWristRight"] = "mWristRight";
-	mJointMap["avatar_mHipRight"] = "mHipRight";
-	mJointMap["avatar_mKneeRight"] = "mKneeRight";
-	mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
-	mJointMap["avatar_mFootRight"] = "mFootRight";
-	mJointMap["avatar_mToeRight"] = "mToeRight";
-	mJointMap["avatar_mHipLeft"] = "mHipLeft";
-	mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
-	mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
-	mJointMap["avatar_mFootLeft"] = "mFootLeft";
-	mJointMap["avatar_mToeLeft"] = "mToeLeft";
-
-
-	mJointMap["hip"] = "mPelvis";
-	mJointMap["abdomen"] = "mTorso";
-	mJointMap["chest"] = "mChest";
-	mJointMap["neck"] = "mNeck";
-	mJointMap["head"] = "mHead";
-	mJointMap["figureHair"] = "mSkull";
-	mJointMap["lCollar"] = "mCollarLeft";
-	mJointMap["lShldr"] = "mShoulderLeft";
-	mJointMap["lForeArm"] = "mElbowLeft";
-	mJointMap["lHand"] = "mWristLeft";
-	mJointMap["rCollar"] = "mCollarRight";
-	mJointMap["rShldr"] = "mShoulderRight";
-	mJointMap["rForeArm"] = "mElbowRight";
-	mJointMap["rHand"] = "mWristRight";
-	mJointMap["rThigh"] = "mHipRight";
-	mJointMap["rShin"] = "mKneeRight";
-	mJointMap["rFoot"] = "mFootRight";
-	mJointMap["lThigh"] = "mHipLeft";
-	mJointMap["lShin"] = "mKneeLeft";
-	mJointMap["lFoot"] = "mFootLeft";
-
+    LLSD aliases_sd;
+    llifstream input_stream;
+    input_stream.open(jointAliasFilename.c_str(), std::ios::in | std::ios::binary);
+    
+    if(input_stream.is_open())
+    {
+        LLSDSerialize::fromXML(aliases_sd, input_stream);
+        for(LLSD::map_iterator alias_iter = aliases_sd.beginMap();
+            alias_iter != aliases_sd.endMap();
+            ++alias_iter)
+        {
+            LLSD::String alias_name = alias_iter->first;
+            LLSD::String joint_name = alias_iter->second;
+            mJointMap[ alias_name ] = joint_name;
+        }
+        input_stream.close();
+    }
+    
 	//move into joint mapper class
 	//1. joints for joint offset verification
 	mMasterJointList.push_front("mPelvis");
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
index 894de2c76fb..20c3aee649e 100644
--- a/indra/llprimitive/llmodelloader.h
+++ b/indra/llprimitive/llmodelloader.h
@@ -128,7 +128,8 @@ class LLModelLoader : public LLThread
 		void*								opaque_userdata,
 		JointTransformMap&					jointTransformMap,
 		JointNameSet&						jointsFromNodes,
-        JointNameSet&						legalJointNames);
+        JointNameSet&						legalJointNames,
+        std::string                         jointAliasFilename);
 	virtual ~LLModelLoader() ;
 
 	virtual void setNoNormalize() { mNoNormalize = true; }
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a006611a45d..b371939fb5f 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1600,12 +1600,12 @@ set_source_files_properties(${viewer_XUI_FILES}
 list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES})
 
 set(viewer_APPSETTINGS_FILES
-    app_settings/anim.ini
     app_settings/cmd_line.xml
     app_settings/commands.xml
     app_settings/grass.xml
     app_settings/high_graphics.xml
     app_settings/ignorable_dialogs.xml
+    app_settings/joint_aliases.xml
     app_settings/keys.xml
     app_settings/keywords_lsl_default.xml
     app_settings/logcontrol.xml
diff --git a/indra/newview/app_settings/anim.ini b/indra/newview/app_settings/anim.ini
deleted file mode 100755
index 63c84e544db..00000000000
--- a/indra/newview/app_settings/anim.ini
+++ /dev/null
@@ -1,87 +0,0 @@
-Translations 1.0
-
-[hip]
-	relativepos = firstkey
-	relativerot = firstkey
-	outname = mPelvis
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[abdomen]
-	outname = mTorso
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[chest]
-	outname = mChest
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[neckDummy]
-	ignore = true
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[neck]
-	outname = mNeck
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[head]
-	outname = mHead
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[figureHair]
-	ignore = true
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lCollar]
-	outname = mCollarLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lShldr]
-	outname = mShoulderLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lForeArm]
-	outname = mElbowLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lHand]
-	outname = mWristLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rCollar]
-	outname = mCollarRight
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rShldr]
-	outname = mShoulderRight
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rForeArm]
-	outname = mElbowRight
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rHand]
-	outname = mWristRight
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lThigh]
-	outname = mHipLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lShin]
-	outname = mKneeLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[lFoot]
-	outname = mAnkleLeft
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rThigh]
-	outname = mHipRight
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rShin]
-	outname = mKneeRight
-	frame = 0 1 0, 0 0 1, 1 0 0
-
-[rFoot]
-	outname = mAnkleRight
-	frame = 0 1 0, 0 0 1, 1 0 0
\ No newline at end of file
diff --git a/indra/newview/app_settings/joint_aliases.xml b/indra/newview/app_settings/joint_aliases.xml
new file mode 100755
index 00000000000..1e4a233837c
--- /dev/null
+++ b/indra/newview/app_settings/joint_aliases.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
+<llsd>
+<map>
+    <key>avatar_mPelvis</key>
+    <string>mPelvis</string>
+    <key>avatar_mTorso</key>
+    <string>mTorso</string>
+    <key>avatar_mChest</key>
+    <string>mChest</string>
+    <key>avatar_mNeck</key>
+    <string>mNeck</string>
+    <key>avatar_mHead</key>
+    <string>mHead</string>
+    <key>avatar_mSkull</key>
+    <string>mSkull</string>
+    <key>avatar_mEyeRight</key>
+    <string>mEyeRight</string>
+    <key>avatar_mEyeLeft</key>
+    <string>mEyeLeft</string>
+    <key>avatar_mCollarLeft</key>
+    <string>mCollarLeft</string>
+    <key>avatar_mShoulderLeft</key>
+    <string>mShoulderLeft</string>
+    <key>avatar_mElbowLeft</key>
+    <string>mElbowLeft</string>
+    <key>avatar_mWristLeft</key>
+    <string>mWristLeft</string>
+    <key>avatar_mCollarRight</key>
+    <string>mCollarRight</string>
+    <key>avatar_mShoulderRight</key>
+    <string>mShoulderRight</string>
+    <key>avatar_mElbowRight</key>
+    <string>mElbowRight</string>
+    <key>avatar_mWristRight</key>
+    <string>mWristRight</string>
+    <key>avatar_mHipRight</key>
+    <string>mHipRight</string>
+    <key>avatar_mKneeRight</key>
+    <string>mKneeRight</string>
+    <key>avatar_mAnkleRight</key>
+    <string>mAnkleRight</string>
+    <key>avatar_mFootRight</key>
+    <string>mFootRight</string>
+    <key>avatar_mToeRight</key>
+    <string>mToeRight</string>
+    <key>avatar_mHipLeft</key>
+    <string>mHipLeft</string>
+    <key>avatar_mKneeLeft</key>
+    <string>mKneeLeft</string>
+    <key>avatar_mAnkleLeft</key>
+    <string>mAnkleLeft</string>
+    <key>avatar_mFootLeft</key>
+    <string>mFootLeft</string>
+    <key>avatar_mToeLeft</key>
+    <string>mToeLeft</string>
+    <key>hip</key>
+    <string>mPelvis</string>
+    <key>abdomen</key>
+    <string>mTorso</string>
+    <key>chest</key>
+    <string>mChest</string>
+    <key>neck</key>
+    <string>mNeck</string>
+    <key>head</key>
+    <string>mHead</string>
+    <key>figureHair</key>
+    <string>mSkull</string>
+    <key>lCollar</key>
+    <string>mCollarLeft</string>
+    <key>lShldr</key>
+    <string>mShoulderLeft</string>
+    <key>lForeArm</key>
+    <string>mElbowLeft</string>
+    <key>lHand</key>
+    <string>mWristLeft</string>
+    <key>rCollar</key>
+    <string>mCollarRight</string>
+    <key>rShldr</key>
+    <string>mShoulderRight</string>
+    <key>rForeArm</key>
+    <string>mElbowRight</string>
+    <key>rHand</key>
+    <string>mWristRight</string>
+    <key>rThigh</key>
+    <string>mHipRight</string>
+    <key>rShin</key>
+    <string>mKneeRight</string>
+    <key>rFoot</key>
+    <string>mFootRight</string>
+    <key>lThigh</key>
+    <string>mHipLeft</string>
+    <key>lShin</key>
+    <string>mKneeLeft</string>
+    <key>lFoot</key>
+    <string>mFootLeft</string>
+</map>
+</llsd>
diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index a800a3ca142..97769838e8e 100755
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -178,6 +178,14 @@ void LLFloaterBvhPreview::setAnimCallbacks()
 	getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1));
 }
 
+void LLFloaterBvhPreview::getLegalJointNames(std::deque<std::string>& legal_joint_names)
+{
+    // Get all standard skeleton joints from the preview avatar.
+    LLPointer<LLVOAvatar> av = (LLVOAvatar*)mAnimPreview->getDummyAvatar();
+    av->getLegalJointNames(legal_joint_names, false);
+}
+
+
 //-----------------------------------------------------------------------------
 // postBuild()
 //-----------------------------------------------------------------------------
@@ -215,6 +223,8 @@ BOOL LLFloaterBvhPreview::postBuild()
 
 	getChildView("bad_animation_text")->setVisible(FALSE);
 
+    mAnimPreview = new LLPreviewAnimation(256, 256);
+    
 	std::string exten = gDirUtilp->getExtension(mFilename);
 	if (exten == "bvh")
 	{
@@ -241,8 +251,10 @@ BOOL LLFloaterBvhPreview::postBuild()
 				file_buffer[file_size] = '\0';
 				LL_INFOS() << "Loading BVH file " << mFilename << LL_ENDL;
 				ELoadStatus load_status = E_ST_OK;
-				S32 line_number = 0; 
-				loaderp = new LLBVHLoader(file_buffer, load_status, line_number);
+				S32 line_number = 0;
+                std::deque<std::string> legal_joint_names;
+                getLegalJointNames(legal_joint_names);
+				loaderp = new LLBVHLoader(file_buffer, load_status, line_number, legal_joint_names);
 				std::string status = getString(STATUS[load_status]);
 				
 				if(load_status == E_ST_NO_XLT_FILE)
@@ -266,8 +278,6 @@ BOOL LLFloaterBvhPreview::postBuild()
 		mTransactionID.generate();
 		mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
 
-		mAnimPreview = new LLPreviewAnimation(256, 256);
-
 		// motion will be returned, but it will be in a load-pending state, as this is a new motion
 		// this motion will not request an asset transfer until next update, so we have a chance to 
 		// load the keyframe data locally
diff --git a/indra/newview/llfloaterbvhpreview.h b/indra/newview/llfloaterbvhpreview.h
index b81cc6e3a51..74d77d00045 100755
--- a/indra/newview/llfloaterbvhpreview.h
+++ b/indra/newview/llfloaterbvhpreview.h
@@ -109,7 +109,8 @@ class LLFloaterBvhPreview : public LLFloaterNameDesc
 									   S32 status, LLExtStat ext_status);
 private:
 	void setAnimCallbacks() ;
-	
+    void getLegalJointNames(std::deque<std::string>& legal_joint_names);
+
 protected:
 	void			draw();
 	void			resetMotion();
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 9c72238d87b..30051a79f11 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1712,6 +1712,8 @@ void LLModelPreview::getLegalJointNames(JointNameSet& legal_joint_names)
 {
     // Get all standard skeleton joints from the preview avatar.
     LLVOAvatar *av = getPreviewAvatar();
+ 
+    av->getLegalJointNames(legal_joint_names, true);
     const LLVOAvatar::avatar_joint_list_t &skel = av->getSkeleton();
     for (S32 i=0; i<skel.size(); i++)
     {
@@ -1775,6 +1777,10 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
     JointNameSet legal_joint_names;
     getLegalJointNames(legal_joint_names);
     
+    std::string joint_aliases_filename =
+                    gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"joint_aliases.xml");
+
+
 	mModelLoader = new LLDAELoader(
 		filename,
 		lod, 
@@ -1786,6 +1792,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
 		mJointTransformMap,
 		mJointsFromNode,
         legal_joint_names,
+        joint_aliases_filename,
 		gSavedSettings.getU32("ImporterModelLimit"));
 
 	if (force_disable_slm)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 54ecc76867c..6610330a56c 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1258,7 +1258,7 @@ bool idle_startup()
 		LLPostProcess::initClass();
 		display_startup();
 
-		LLAvatarAppearance::initClass(gSavedSettings.getString("AvatarFileName"),gSavedSettings.getString("SkeletonFileName"));
+        LLAvatarAppearance::initClass(gSavedSettings.getString("AvatarFileName"),gSavedSettings.getString("SkeletonFileName"));
 		display_startup();
 
 		LLViewerObject::initVOClasses();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 3b482e1bc0e..d14ec7e55be 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -937,6 +937,29 @@ std::string LLVOAvatar::rezStatusToString(S32 rez_status)
 	return "unknown";
 }
 
+void LLVOAvatar::getLegalJointNames(std::deque<std::string>& legal_joint_names,
+                                    bool include_collision_volumes)
+{
+    // Get all standard skeleton joints from the preview avatar.
+    const LLVOAvatar::avatar_joint_list_t &skel = getSkeleton();
+    for (S32 i=0; i<skel.size(); i++)
+    {
+        LLAvatarJoint *joint = skel[i];
+        if (joint)
+        {
+            legal_joint_names.push_back(joint->getName());
+        }
+    }
+    
+    if (include_collision_volumes)
+    {
+        for (S32 i = 0; i < mNumCollisionVolumes; i++)
+        {
+            legal_joint_names.push_back(mCollisionVolumes[i].getName());
+        }
+    }
+}
+
 // static
 void LLVOAvatar::dumpBakedStatus()
 {
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 7a2355b4473..29f70fca185 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -72,6 +72,7 @@ class LLTexGlobalColor;
 struct LLAppearanceMessageContents;
 class LLViewerJointMesh;
 
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // LLVOAvatar
 // 
@@ -146,6 +147,8 @@ class LLVOAvatar :
 	void 						collectBakedTextureUUIDs(std::set<LLUUID>& ids) const;
 	void 						collectTextureUUIDs(std::set<LLUUID>& ids);
 	void						releaseOldTextures();
+    void                        getLegalJointNames(std::deque<std::string>& legal_joint_names,
+                                                   bool include_collision_volumes);
 	/*virtual*/ void   	 	 	updateTextures();
 	LLViewerFetchedTexture*		getBakedTextureImage(const U8 te, const LLUUID& uuid);
 	/*virtual*/ S32    	 	 	setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim.
-- 
GitLab