From 74cdfe898ff3c23c8de045eb4d0005f4c4fd75bd Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Mon, 20 Dec 2021 00:24:29 -0500
Subject: [PATCH] Initial port of BD Poser

---
 indra/llappearance/llavatarappearance.cpp     |   24 +-
 indra/llappearance/llavatarappearance.h       |    5 +
 indra/llcharacter/lljoint.h                   |   31 +
 indra/llcharacter/llmotion.cpp                |   25 +
 indra/llcharacter/llmotion.h                  |   36 +-
 indra/llfilesystem/lldir.cpp                  |   33 +
 indra/llfilesystem/lldir.h                    |    2 +
 indra/llui/llscrolllistctrl.cpp               |   43 +-
 indra/llui/llscrolllistctrl.h                 |    3 +
 indra/llui/llscrolllistitem.cpp               |    8 +-
 indra/llui/llscrolllistitem.h                 |   31 +-
 indra/newview/CMakeLists.txt                  |    6 +
 indra/newview/bdanimator.cpp                  |  376 +++
 indra/newview/bdanimator.h                    |   81 +
 indra/newview/bdfloaterposer.cpp              | 2618 +++++++++++++++++
 indra/newview/bdfloaterposer.h                |  254 ++
 indra/newview/bdposingmotion.cpp              |  261 ++
 indra/newview/bdposingmotion.h                |  111 +
 indra/newview/character/avatar_skeleton.xml   |  188 +-
 indra/newview/llagent.h                       |   10 +
 indra/newview/llappviewer.cpp                 |    3 +
 indra/newview/llviewerfloaterreg.cpp          |    2 +
 indra/newview/llviewershadermgr.cpp           |    3 +
 indra/newview/llvoavatar.cpp                  |   38 +-
 indra/newview/llvoavatar.h                    |   26 +
 .../default/textures/icons/Inv_Shape.png      |  Bin 0 -> 693 bytes
 .../skins/default/textures/textures.xml       |    3 +
 .../default/textures/toolbar_icons/poser.png  |  Bin 0 -> 254 bytes
 .../skins/default/textures/transparent.tga    |  Bin 0 -> 49 bytes
 .../skins/default/xui/en/floater_poser.xml    | 1390 +++++++++
 .../skins/default/xui/en/menu_poser_poses.xml |   51 +
 .../skins/default/xui/en/menu_viewer.xml      |   11 +
 32 files changed, 5562 insertions(+), 111 deletions(-)
 create mode 100644 indra/newview/bdanimator.cpp
 create mode 100644 indra/newview/bdanimator.h
 create mode 100644 indra/newview/bdfloaterposer.cpp
 create mode 100644 indra/newview/bdfloaterposer.h
 create mode 100644 indra/newview/bdposingmotion.cpp
 create mode 100644 indra/newview/bdposingmotion.h
 create mode 100644 indra/newview/skins/default/textures/icons/Inv_Shape.png
 create mode 100644 indra/newview/skins/default/textures/toolbar_icons/poser.png
 create mode 100644 indra/newview/skins/default/textures/transparent.tga
 create mode 100644 indra/newview/skins/default/xui/en/floater_poser.xml
 create mode 100644 indra/newview/skins/default/xui/en/menu_poser_poses.xml

diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index cdee35d9f65..79f71d39390 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -84,6 +84,8 @@ class LLAvatarBoneInfo
 	LLVector3 mPivot;
 	typedef std::vector<LLAvatarBoneInfo*> bones_t;
 	bones_t mChildren;
+	//BD - Poser
+	BOOL mHasPosition;
 };
 
 //------------------------------------------------------------------------
@@ -656,6 +658,9 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
     joint->setSupport(info->mSupport);
 	joint->setEnd(info->mEnd);
 
+	//BD - Poser
+	joint->setCanReposition(info->mHasPosition);
+
 	if (info->mIsJoint)
 	{
 		joint->setSkinOffset( info->mPivot );
@@ -863,6 +868,11 @@ void LLAvatarAppearance::buildCharacter()
 	mWristRightp	= mRoot->findJoint("mWristRight");
 	mEyeLeftp		= mRoot->findJoint("mEyeLeft");
 	mEyeRightp		= mRoot->findJoint("mEyeRight");
+	//BD
+	mShoulderRightp = mRoot->findJoint("mShoulderRight");
+	mShoulderLeftp	= mRoot->findJoint("mShoulderLeft");
+	mElbowRightp	= mRoot->findJoint("mElbowRight");
+	mElbowLeftp		= mRoot->findJoint("mElbowLeft");
 
 	//-------------------------------------------------------------------------
 	// Make sure "well known" pointers exist
@@ -884,7 +894,12 @@ void LLAvatarAppearance::buildCharacter()
 		  mWristLeftp &&
 		  mWristRightp &&
 		  mEyeLeftp &&
-		  mEyeRightp))
+		  mEyeRightp &&
+		  //BD
+		  mShoulderRightp &&
+		  mShoulderLeftp &&
+		  mElbowRightp &&
+		  mElbowLeftp))
 	{
 		LL_ERRS() << "Failed to create avatar." << LL_ENDL;
 		return;
@@ -1661,6 +1676,13 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
 		}
 	}
 
+	//BD
+	static LLStdStringHandle reposition_string = LLXmlTree::addAttributeString("reposition");
+	if (!node->getFastAttributeBOOL(reposition_string, mHasPosition))
+	{
+		mHasPosition = FALSE;
+	}
+
 	// parse children
 	LLXmlTreeNode* child;
 	for( child = node->getFirstChild(); child; child = node->getNextChild() )
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index c721c86dd8e..91ca4db3d06 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -207,6 +207,11 @@ class LLAvatarAppearance : public LLCharacter
 	LLJoint* 		mFootRightp;
 	LLJoint* 		mWristLeftp;
 	LLJoint* 		mWristRightp;
+	//BD
+	LLJoint* 		mShoulderRightp;
+	LLJoint* 		mShoulderLeftp;
+	LLJoint* 		mElbowRightp;
+	LLJoint* 		mElbowLeftp;
 
 	//--------------------------------------------------------------------
 	// XML parse tree
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 6de398ac7d1..af412e6ad38 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -144,6 +144,15 @@ class LLJoint
 
 	S32				mJointNum;
 
+	//BD - Poser
+	LLQuaternion	mNextRotation;
+	LLQuaternion	mTargetRotation;
+	LLQuaternion	mLastRotation;
+	LLVector3		mNextPosition;
+	LLVector3		mTargetPosition;
+	LLVector3		mLastPosition;
+	bool			mHasPosition;
+
 	// child joints
 	typedef std::vector<LLJoint*> joints_t;
 	joints_t mChildren;
@@ -249,6 +258,28 @@ class LLJoint
 	LLVector3 getLastWorldPosition();
 	void setWorldPosition( const LLVector3& pos );
 
+	//BD - Poser
+	void setTargetPosition(const LLVector3& pos) { mTargetPosition = pos; }
+	LLVector3 getTargetPosition() const { return mTargetPosition; }
+
+	void setTargetRotation(const LLQuaternion& rot) { mTargetRotation = rot; }
+	LLQuaternion getTargetRotation() const { return mTargetRotation; }
+
+	void setLastPosition(const LLVector3& pos) { mLastPosition = pos; }
+	LLVector3 getLastPosition() const { return mLastPosition; }
+
+	void setLastRotation(const LLQuaternion& rot) { mLastRotation = rot; }
+	LLQuaternion getLastRotation() const { return mLastRotation; }
+
+	void setCanReposition(const bool can_reposition) { mHasPosition = can_reposition; }
+	bool canReposition() const { return mHasPosition; }
+
+	void setNextPosition(const LLVector3& pos) { mNextPosition = pos; }
+	LLVector3 getNextPosition() const { return mNextPosition; }
+
+	void setNextRotation(const LLQuaternion& rot) { mNextRotation = rot; }
+	LLQuaternion getNextRotation() const { return mNextRotation; }
+
 	// get/set local rotation
 	const LLQuaternion& getRotation();
 	void setRotation( const LLQuaternion& rot );
diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp
index 7c0e2d43435..f7eb26c7c59 100644
--- a/indra/llcharacter/llmotion.cpp
+++ b/indra/llcharacter/llmotion.cpp
@@ -114,6 +114,31 @@ void LLMotion::addJointState(const LLPointer<LLJointState>& jointState)
 	mJointSignature[2][joint_num] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0;
 }
 
+//BD
+//-----------------------------------------------------------------------------
+// removeJointState()
+//-----------------------------------------------------------------------------
+void LLMotion::removeJointState(const LLPointer<LLJointState>& jointState)
+{
+	mPose.removeJointState(jointState);
+}
+
+//BD
+//-----------------------------------------------------------------------------
+// findJointState()
+//-----------------------------------------------------------------------------
+const LLPointer<LLJointState> LLMotion::findJointState(const std::string jointName)
+{
+	const LLPointer<LLJointState> joint_state = mPose.findJointState(jointName);
+	return joint_state;
+}
+
+const LLPointer<LLJointState> LLMotion::findJointState(LLJoint *joint)
+{
+	const LLPointer<LLJointState> joint_state = mPose.findJointState(joint);
+	return joint_state;
+}
+
 void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata )
 {
 	mDeactivateCallback = cb;
diff --git a/indra/llcharacter/llmotion.h b/indra/llcharacter/llmotion.h
index efa44bbcc5a..234b1e8eec5 100644
--- a/indra/llcharacter/llmotion.h
+++ b/indra/llcharacter/llmotion.h
@@ -33,6 +33,7 @@
 #include <string>
 
 #include "llerror.h"
+#include "llframetimer.h"
 #include "llpose.h"
 #include "lluuid.h"
 
@@ -81,6 +82,8 @@ class LLMotion
 	// returns the pose associated with the current state of this motion
 	virtual LLPose* getPose() { return &mPose;}
 
+	void setPose(LLPose pose) { mPose = pose; }
+
 	void fadeOut();
 
 	void fadeIn();
@@ -156,13 +159,35 @@ class LLMotion
 	// optional callback routine called when animation deactivated.
 	void	setDeactivateCallback( void (*cb)(void *), void* userdata );
 
+	F32 getInterpolationTime() const					{ return mInterpolationTime; }
+	virtual void setInterpolationTime(F32 time)			{ mInterpolationTime = time; }
+
+	//BD - functions to set/get our interpolation type
+	//     0 = None, 
+	// 	   1 = Linear Interpolatioon, 
+	//     2 = Spherical Linear Interpolation,
+	//     3 = Curve
+	S32 getInterpolationType() const					{ return mInterpolationType; }
+	virtual void setInterpolationType(S32 type)			{ mInterpolationType = type; }
+
+	void pauseInterpolationTimer() { mInterpolationTimer.pause(); }
+	void startInterpolationTimer() { mInterpolationTimer.start(); }
+	void stopInterpolationTimer() { mInterpolationTimer.stop(); }
+
+	//BD
+	void addJointState(const LLPointer<LLJointState>& jointState);
+	void removeJointState(const LLPointer<LLJointState>& jointState);
+	const LLPointer<LLJointState> findJointState(const std::string jointName);
+	const LLPointer<LLJointState> findJointState(LLJoint *joint);
+
 protected:
 	// called when a motion is activated
 	// must return TRUE to indicate success, or else
 	// it will be deactivated
 	virtual BOOL onActivate() = 0;
 
-	void addJointState(const LLPointer<LLJointState>& jointState);
+// BD
+//	void addJointState(const LLPointer<LLJointState>& jointState);
 
 protected:
 	LLPose		mPose;
@@ -175,6 +200,15 @@ class LLMotion
 	//-------------------------------------------------------------------------
 	std::string		mName;			// instance name assigned by motion controller
 	LLUUID			mID;
+
+	//BD - functions to set/get our interpolation type
+	//     0 = None, 
+	// 	   1 = Linear Interpolatioon, 
+	//     2 = Spherical Linear Interpolation,
+	//     3 = Curve
+	S32					mInterpolationType;
+	F32					mInterpolationTime;
+	LLFrameTimer		mInterpolationTimer;
 	
 	F32 mActivationTimestamp;	// time when motion was activated
 	F32 mStopTimestamp;			// time when motion was told to stop
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index d26eb115421..c8f0546bee0 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -1086,6 +1086,39 @@ void LLDir::append(std::string& destpath, const std::string& name) const
 	destpath += name.substr(sepoff.second);
 }
 
+// static 
+std::string LLDir::escapePathString(std::string_view str)
+{
+	//BD - Don't use LLURI::escape() because it doesn't encode '-' characters
+	//     which may break handling of some poses.
+	//     From Singularity Viewer.
+	static const char hex[] = "0123456789ABCDEF";
+	std::stringstream escaped_str;
+	for (auto cha : str)
+	{
+		switch (cha) {
+		case '0': case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+		case 'a': case 'b': case 'c': case 'd': case 'e':
+		case 'f': case 'g': case 'h': case 'i': case 'j':
+		case 'k': case 'l': case 'm': case 'n': case 'o':
+		case 'p': case 'q': case 'r': case 's': case 't':
+		case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+		case 'A': case 'B': case 'C': case 'D': case 'E':
+		case 'F': case 'G': case 'H': case 'I': case 'J':
+		case 'K': case 'L': case 'M': case 'N': case 'O':
+		case 'P': case 'Q': case 'R': case 'S': case 'T':
+		case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+			escaped_str << (cha);
+			break;
+		default:
+			unsigned char c = (unsigned char)(cha);
+			escaped_str << '%' << hex[c >> 4] << hex[c & 0xF];
+		}
+	}
+	return escaped_str.str();
+}
+
 LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const
 {
 	if (path.empty() || name.empty())
diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h
index 99e6ffb8baf..6611203a4d6 100644
--- a/indra/llfilesystem/lldir.h
+++ b/indra/llfilesystem/lldir.h
@@ -223,6 +223,8 @@ class LLDir
 		return destpath;
 	}
 
+	static std::string escapePathString(std::string_view str);
+
 protected:
 	// Does an add() or append() call need a directory delimiter?
 	typedef std::pair<bool, unsigned short> SepOff;
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 547c46fbb63..f4ff34c54c7 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -265,17 +265,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
 		mBorder->reshape(getRect().getWidth(), getRect().getHeight());
 	}
 
-	LLTextBox::Params text_p;
-	text_p.name("comment_text");
-	text_p.border_visible(false);
-	text_p.rect(mItemListRect);
-	text_p.follows.flags(FOLLOWS_ALL);
-	// word wrap was added accroding to the EXT-6841
-	text_p.wrap(true);
-	addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
-
-
-	
 	for (LLInitParam::ParamIterator<LLScrollListColumn::Params>::const_iterator row_it = p.contents.columns.begin();
 		row_it != p.contents.columns.end();
 		++row_it)
@@ -295,6 +284,14 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
 		addRow(*row_it);
 	}
 
+	LLTextBox::Params text_p;
+	text_p.name("comment_text");
+	text_p.border_visible(false);
+	text_p.rect(mItemListRect);
+	text_p.follows.flags(FOLLOWS_ALL);
+	// word wrap was added accroding to the EXT-6841
+	text_p.wrap(true);
+	addChild(LLUICtrlFactory::create<LLTextBox>(text_p));
 }
 
 S32 LLScrollListCtrl::getSearchColumn()
@@ -1043,6 +1040,30 @@ void LLScrollListCtrl::deleteSelectedItems()
 	dirtyColumns();
 }
 
+//BD
+void LLScrollListCtrl::deleteFlaggedItems()
+{
+	item_list::iterator iter;
+	for (iter = mItemList.begin(); iter < mItemList.end();)
+	{
+		LLScrollListItem* itemp = *iter;
+		if (itemp && itemp->getFlagged())
+		{
+			if (itemp == mLastSelected)
+			{
+				mLastSelected = NULL;
+			}
+			delete itemp;
+			iter = mItemList.erase(iter);
+		}
+		else
+		{
+			iter++;
+		}
+	}
+	dirtyColumns();
+}
+
 void LLScrollListCtrl::clearHighlightedItems()
 {	
 	for (item_list::iterator iter = mItemList.begin(); iter != mItemList.end(); ++iter)
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index a1b017b535a..c344f9a0507 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -230,6 +230,9 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
 	void			deleteSingleItem( S32 index );
 	void			deleteItems(const LLSD& sd);
 	void 			deleteSelectedItems();
+	//BD
+	void 			deleteFlaggedItems();
+
 	void			deselectAllItems(BOOL no_commit_on_change = FALSE);	// by default, go ahead and commit on selection change
 
 	void			clearHighlightedItems();
diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp
index 42f0e8a4b02..5d769d158fe 100644
--- a/indra/llui/llscrolllistitem.cpp
+++ b/indra/llui/llscrolllistitem.cpp
@@ -44,8 +44,14 @@ LLScrollListItem::LLScrollListItem( const Params& p )
 	mSelectedIndex(-1),
 	mEnabled(p.enabled),
 	mUserdata(p.userdata),
-	mItemValue(p.value)
+	mItemValue(p.value),
+	mToolTip(p.tool_tip)
 {
+	//BD - Cells ~ Thanks to Liru
+	for (const auto& cell : p.contents.columns)
+	{
+		addColumn(cell);
+	}
 }
 
 
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index d2c3dd7721b..fe711bd3fd6 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -50,6 +50,18 @@ class LLScrollListItem
 {
 	friend class LLScrollListCtrl;
 public:
+	//BD - Cells ~ Thanks to Liru
+	struct Contents : public LLInitParam::Block<Contents>
+	{
+		Multiple<LLScrollListCell::Params>	columns;
+		Contents()
+		:	columns("columns")
+		{
+			addSynonym(columns, "columns");
+			addSynonym(columns, "cell");
+		}
+	};
+
 	struct Params : public LLInitParam::Block<Params>
 	{
 		Optional<bool>		enabled;
@@ -61,6 +73,9 @@ class LLScrollListItem
 		Ignored				length; 
 
 		Multiple<LLScrollListCell::Params> columns;
+		Optional<std::string> tool_tip;
+		//BD - Cells ~ Thanks to Liru
+		Optional<Contents> contents;
 
 		Params()
 		:	enabled("enabled", true),
@@ -68,7 +83,11 @@ class LLScrollListItem
 			name("name"),
 			type("type"),
 			length("length"),
-			columns("columns")
+			columns("columns"),
+			//BD
+			tool_tip("tool_tip"),
+			//BD - Cells ~ Thanks to Liru
+			contents("contents")
 		{
 			addSynonym(columns, "column");
 			addSynonym(value, "id");
@@ -92,6 +111,13 @@ class LLScrollListItem
 	void	setHoverCell( S32 cell );
 	S32		getHoverCell() const			{ return mHoverIndex; }
 
+	void		setToolTip(std::string str)	{ mToolTip = str; }
+	std::string	getToolTip() const			{ return mToolTip; }
+
+	//BD
+	void	setFlagged(bool b)				{ mFlaggedDead = b; }
+	bool	getFlagged() const				{ return mFlaggedDead; }
+
 	void	setUserdata( void* userdata )	{ mUserdata = userdata; }
 	void*	getUserdata() const 			{ return mUserdata; }
 
@@ -129,8 +155,11 @@ class LLScrollListItem
     S32		mHoverIndex;
 	S32		mSelectedIndex;
 	BOOL	mEnabled;
+
+	bool	mFlaggedDead = false;
 	void*	mUserdata;
 	LLSD	mItemValue;
+	std::string	mToolTip;
 	std::vector<LLScrollListCell *> mColumns;
 	LLRect  mRectangle;
 };
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 9181b2d1745..7b1ba438bfb 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -135,6 +135,9 @@ set(viewer_SOURCE_FILES
     altoolalign.cpp
     alunzip.cpp
     alviewermenu.cpp
+    bdanimator.cpp
+    bdfloaterposer.cpp
+    bdposingmotion.cpp
     groupchatlistener.cpp
     llaccountingcostmanager.cpp
     llaisapi.cpp
@@ -807,6 +810,9 @@ set(viewer_HEADER_FILES
     altoolalign.h
     alunzip.h
     alviewermenu.h
+    bdanimator.h
+    bdfloaterposer.h
+    bdposingmotion.h
     groupchatlistener.h
     llaccountingcost.h
     llaccountingcostmanager.h
diff --git a/indra/newview/bdanimator.cpp b/indra/newview/bdanimator.cpp
new file mode 100644
index 00000000000..cb96480f3a0
--- /dev/null
+++ b/indra/newview/bdanimator.cpp
@@ -0,0 +1,376 @@
+/**
+*
+* Copyright (C) 2018, NiranV Dean
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lluictrlfactory.h"
+#include "llagent.h"
+#include "lldiriterator.h"
+#include "llkeyframemotion.h"
+#include "llsdserialize.h"
+#include "llsdutil.h"
+#include "llviewerjointattachment.h"
+#include "llviewerjoint.h"
+#include "llvoavatarself.h"
+
+#include "bdfloaterposer.h"
+#include "bdanimator.h"
+#include "bdposingmotion.h"
+
+BDAnimator gDragonAnimator;
+
+void BDAnimator::update()
+{
+	//BD - Don't do anything if the animator is not activated.
+	if (!mPlaying) return;
+
+	//BD - Don't even bother when our list is empty.
+	if (mAvatarsList.empty()) return;
+
+	for (LLVOAvatar* avatar : mAvatarsList)
+	{
+		if (!avatar || avatar->isDead()) continue;
+
+		//BD - This should never happen since avatars are only in this list if they have at
+		//     least one action saved, better be safe than sorry though.
+		if (avatar->mAnimatorActions.empty())
+		{
+			avatar->mAnimPlayTimer.stop();
+			continue;
+		}
+
+		if (avatar->mAnimPlayTimer.getStarted() &&
+			avatar->mAnimPlayTimer.getElapsedTimeF32() > avatar->mExpiryTime)
+		{
+			Action action = avatar->mAnimatorActions[avatar->mCurrentAction];
+			//BD - Stop the timer, we're going to reconfigure and restart it when we're done.
+			avatar->mAnimPlayTimer.stop();
+
+			BD_EActionType type = action.mType;
+			std::string name = action.mPoseName;
+
+			//BD - We can't use Wait or Restart as label, need to fix this.
+			if (type == WAIT)
+			{
+				//BD - Do nothing?
+				avatar->mExpiryTime = action.mTime;
+				++avatar->mCurrentAction;
+			}
+			else if (type == REPEAT)
+			{
+				avatar->mCurrentAction = 0;
+				avatar->mExpiryTime = 0.0f;
+			}
+			else
+			{
+				avatar->mExpiryTime = 0.0f;
+				mTargetAvatar = avatar;
+				loadPose(name);
+				++avatar->mCurrentAction;
+			}
+
+			//BD - As long as we are not at the end, start the timer again, automatically
+			//     resetting the counter in the process.
+			if (avatar->mAnimatorActions.size() != avatar->mCurrentAction)
+			{
+				avatar->mAnimPlayTimer.start();
+			}
+		}
+	}
+}
+
+void BDAnimator::onAddAction(LLVOAvatar* avatar, LLScrollListItem* item, S32 location)
+{
+	if (!avatar || avatar->isDead()) return;
+
+	if (item)
+	{
+		Action action;
+		S32 type = item->getColumn(2)->getValue().asInteger();
+		if (type == 0)
+		{
+			action.mType = WAIT;
+		}
+		else if (type == 1)
+		{
+			action.mType = REPEAT;
+		}
+		else
+		{
+			action.mType = POSE;
+		}
+		action.mPoseName = item->getColumn(0)->getValue().asString();
+		action.mTime = item->getColumn(1)->getValue().asReal();
+		avatar->mAnimatorActions.push_back(action);
+
+		//BD - Lookup whether we already added this avatar, do it if we didn't this is
+		//     important.
+		for (LLVOAvatar* list_avatar : mAvatarsList)
+		{
+			if (list_avatar == avatar) return;
+		}
+		mAvatarsList.push_back(avatar);
+	}
+}
+
+void BDAnimator::onAddAction(LLVOAvatar* avatar, std::string name, BD_EActionType type, F32 time, S32 location)
+{
+	if (!avatar || avatar->isDead()) return;
+
+	Action action;
+	action.mType = type;
+	action.mPoseName = name;
+	action.mTime = time;
+	if (avatar->mAnimatorActions.size() == 0)
+	{
+		avatar->mAnimatorActions.push_back(action);
+	}
+	else
+	{
+		if (location <= avatar->mAnimatorActions.size())
+		{
+			avatar->mAnimatorActions.insert(avatar->mAnimatorActions.begin() + location, action);
+		}
+	}
+
+	//BD - Lookup whether we already added this avatar, do it if we didn't this is
+	//     important.
+	for (LLVOAvatar* list_avatar : mAvatarsList)
+	{
+		if (list_avatar == avatar) return;
+	}
+	mAvatarsList.push_back(avatar);
+}
+
+void BDAnimator::onAddAction(LLVOAvatar* avatar, Action action, S32 location)
+{
+	if (!avatar || avatar->isDead()) return;
+
+	avatar->mAnimatorActions.insert(avatar->mAnimatorActions.begin() + location, action);
+
+	//BD - Lookup whether we already added this avatar, do it if we didn't this is
+	//     important.
+	for (LLVOAvatar* list_avatar : mAvatarsList)
+	{
+		if (list_avatar == avatar) return;
+	}
+	mAvatarsList.push_back(avatar);
+}
+
+
+void BDAnimator::onDeleteAction(LLVOAvatar* avatar, S32 location)
+{
+	if (!mPlaying)
+	{
+		avatar->mAnimatorActions.erase(avatar->mAnimatorActions.begin() + location);
+
+		//BD - If this avatar has no more actions, delete it from our list.
+		if (avatar->mAnimatorActions.empty())
+		{
+			S32 i = 0;
+			for (LLVOAvatar* list_avatar : mAvatarsList)
+			{
+				if (list_avatar == avatar)
+				{
+					mAvatarsList.erase(mAvatarsList.begin() + i);
+				}
+				++i;
+			}
+		}
+	}
+}
+
+void BDAnimator::startPlayback()
+{
+	//BD - Don't even bother when our list is empty.
+	if (mAvatarsList.empty()) return;
+
+	for (LLVOAvatar* avatar : mAvatarsList)
+	{
+		if (!avatar || avatar->isDead()) continue;
+
+		avatar->mAnimPlayTimer.start();
+		avatar->mExpiryTime = 0.0f;
+		avatar->mCurrentAction = 0;
+	}
+	mPlaying = true;
+}
+
+void BDAnimator::stopPlayback()
+{
+	//BD - Don't even bother when our list is empty.
+	if (mAvatarsList.empty()) return;
+
+	for (LLVOAvatar* avatar : mAvatarsList)
+	{
+		if (!avatar || avatar->isDead()) continue;
+
+		avatar->mAnimPlayTimer.stop();
+	}
+	mPlaying = false;
+}
+
+//BD - We allow loading rotations, positions and scales seperately
+//     by giving the load an integer which determines what to load.
+//     1 is default and loads rotations only, 2 = positions only,
+//     4 = scales only, thus 3 = rotations and positions and so on.
+BOOL BDAnimator::loadPose(const LLSD& name, S32 load_type)
+{
+	if (!mTargetAvatar || mTargetAvatar->isDead())
+	{
+		LL_WARNS("Posing") << "Couldn't find avatar, dead?" << LL_ENDL;
+		return FALSE;
+	}
+
+	std::string filename;
+	if (!name.asString().empty())
+	{
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", LLDir::escapePathString(name.asString()) + ".xml");
+	}
+
+	LLSD pose;
+	llifstream infile;
+	infile.open(filename);
+	if (!infile.is_open())
+	{
+		LL_WARNS("Posing") << "Cannot find file in: " << filename << LL_ENDL;
+		return FALSE;
+	}
+
+	while (!infile.eof())
+	{
+		S32 count = LLSDSerialize::fromXML(pose, infile);
+		if (count == LLSDParser::PARSE_FAILURE)
+		{
+			LL_WARNS("Posing") << "Failed to parse file: " << filename << LL_ENDL;
+			return FALSE;
+		}
+
+		//BD - Not sure how to read the exact line out of a XML file, so we're just going
+		//     by the amount of tags here, since the header has only 3 it's a good indicator
+		//     if it's the correct line we're in.
+		BDPosingMotion* motion = (BDPosingMotion*)mTargetAvatar->findMotion(ANIM_BD_POSING_MOTION);
+		if (count == 3)
+		{
+			if (motion)
+			{
+				F32 time = pose["time"].asReal();
+				S32 type = pose["type"].asInteger();
+				motion->setInterpolationType(type);
+				motion->setInterpolationTime(time);
+				motion->startInterpolationTimer();
+			}
+		}
+
+		LLJoint* joint = mTargetAvatar->getJoint(pose["bone"].asString());
+		if (joint)
+		{
+			//BD - Don't try to add/remove joint states for anything but our default bones.
+			if (motion && joint->getJointNum() < 134)
+			{
+				LLPose* mpose = motion->getPose();
+				if (mpose)
+				{
+					//BD - Fail safe, assume that a bone is always enabled in case we
+					//     load a pose that was created prior to including the enabled
+					//     state or for whatever reason end up not having an enabled state
+					//     written into the file.
+					bool state_enabled = true;
+
+					//BD - Check whether the joint state of the current joint has any enabled
+					//     status saved into the pose file or not.
+					if (pose["enabled"].isDefined())
+					{
+						state_enabled = pose["enabled"].asBoolean();
+					}
+
+					//BD - Add the joint state but only if it's not active yet.
+					//     Same goes for removing it, don't remove it if it doesn't exist.
+					LLPointer<LLJointState> joint_state = mpose->findJointState(joint);
+					if (!joint_state && state_enabled)
+					{
+						motion->addJointToState(joint);
+					}
+					else if (joint_state && !state_enabled)
+					{
+						motion->removeJointState(joint_state);
+					}
+				}
+			}
+
+			LLVector3 vec3;
+			if (load_type & ROTATIONS && pose["rotation"].isDefined())
+			{
+				LLQuaternion quat;
+				LLQuaternion new_quat = joint->getRotation();
+
+				joint->setLastRotation(new_quat);
+				vec3.setValue(pose["rotation"]);
+				quat.setEulerAngles(vec3.mV[VX], vec3.mV[VZ], vec3.mV[VY]);
+				joint->setTargetRotation(quat);
+			}
+
+			//BD - Position information is only ever written when it is actually safe to do.
+			//     It's safe to assume that IF information is available it's safe to apply.
+			if (load_type & POSITIONS && pose["position"].isDefined())
+			{
+				vec3.setValue(pose["position"]);
+				joint->setLastPosition(joint->getPosition());
+				joint->setTargetPosition(vec3);
+			}
+
+			//BD - Bone Scales
+			if (load_type & SCALES && pose["scale"].isDefined())
+			{
+				vec3.setValue(pose["scale"]);
+				joint->setScale(vec3);
+			}
+		}
+	}
+	infile.close();
+	return TRUE;
+}
+
+LLSD BDAnimator::returnPose(const LLSD& name)
+{
+	std::string filename;
+	if (!name.asString().empty())
+	{
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", LLDir::escapePathString(name.asString()) + ".xml");
+	}
+
+	LLSD pose;
+	llifstream infile;
+	infile.open(filename);
+	if (!infile.is_open())
+	{
+		LL_WARNS("Posing") << "Cannot find file in: " << filename << LL_ENDL;
+		//return;
+	}
+
+	for (S32 i = 0; !infile.eof(); ++i)
+	//while (!infile.eof())
+	{
+		S32 count = LLSDSerialize::fromXML(pose[i], infile);
+		if (count == LLSDParser::PARSE_FAILURE)
+		{
+			LL_WARNS("Posing") << "Failed to parse file: " << filename << LL_ENDL;
+			//return;
+		}
+	}
+	infile.close();
+	return pose;
+}
\ No newline at end of file
diff --git a/indra/newview/bdanimator.h b/indra/newview/bdanimator.h
new file mode 100644
index 00000000000..4b6ce5fa24b
--- /dev/null
+++ b/indra/newview/bdanimator.h
@@ -0,0 +1,81 @@
+/**
+*
+* Copyright (C) 2018, NiranV Dean
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+*/
+
+
+#ifndef BD_ANIMATOR_H
+#define BD_ANIMATOR_H
+
+#include "llfloater.h"
+#include "llscrolllistctrl.h"
+#include "llsliderctrl.h"
+#include "llmultisliderctrl.h"
+#include "lltimectrl.h"
+#include "llkeyframemotion.h"
+
+enum BD_EActionType
+{
+	WAIT = 0,
+	REPEAT = 1,
+	POSE = 2
+};
+
+enum BD_ELoadType
+{
+	NOTHING = 0,
+	ROTATIONS = 0x1,			// Load rotations
+	POSITIONS = 0x1 << 1,		// Load positions
+	SCALES = 0x1 << 2,			// Load scales
+};
+
+class Action
+{
+public:
+	std::string		mPoseName;
+	BD_EActionType	mType = BD_EActionType::WAIT;
+	F32				mTime = 1.f;
+};
+
+class BDAnimator
+{
+public:
+
+	BDAnimator() = default;
+	~BDAnimator() = default;
+
+	void			onAddAction(LLVOAvatar* avatar, LLScrollListItem* item, S32 location);
+	void			onAddAction(LLVOAvatar* avatar, std::string name, BD_EActionType type, F32 time, S32 location);
+	void			onAddAction(LLVOAvatar* avatar, Action action, S32 location);
+	void			onDeleteAction(LLVOAvatar* avatar, S32 i);
+
+	BOOL			loadPose(const LLSD& name, S32 load_type = 3);
+	LLSD			returnPose(const LLSD& name);
+
+	void			update();
+	void			startPlayback();
+	void			stopPlayback();
+
+	//BD - Animesh Support
+	LLVOAvatar*						mTargetAvatar = nullptr;
+
+	std::vector<LLVOAvatar*>		mAvatarsList;
+
+	bool			getIsPlaying() { return mPlaying; }
+	bool			mPlaying = false;
+};
+
+extern BDAnimator gDragonAnimator;
+
+#endif
diff --git a/indra/newview/bdfloaterposer.cpp b/indra/newview/bdfloaterposer.cpp
new file mode 100644
index 00000000000..510036a67e0
--- /dev/null
+++ b/indra/newview/bdfloaterposer.cpp
@@ -0,0 +1,2618 @@
+/**
+*
+* Copyright (C) 2018, NiranV Dean
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "bdfloaterposer.h"
+#include "lluictrlfactory.h"
+#include "llagent.h"
+#include "llavatarname.h"
+#include "llavatarnamecache.h"
+#include "lldiriterator.h"
+#include "llkeyframemotion.h"
+#include "llmenugl.h"
+#include "llmenubutton.h"
+#include "lltoggleablemenu.h"
+#include "llviewermenu.h"
+#include "llsdserialize.h"
+#include "llsdutil.h"
+#include "llviewerjointattachment.h"
+#include "llviewerjoint.h"
+#include "llvoavatarself.h"
+
+//BD - Animesh Support
+#include "llcontrolavatar.h"
+
+//BD - Black Dragon specifics
+#include "bdanimator.h"
+#include "bdposingmotion.h"
+
+
+BDFloaterPoser::BDFloaterPoser(const LLSD& key)
+	:	LLFloater(key)
+{
+	//BD - Save our current pose into a XML file to import it later or use it for creating an animation.
+	mCommitCallbackRegistrar.add("Pose.Save", boost::bind(&BDFloaterPoser::onClickPoseSave, this));
+	//BD - Start our custom pose.
+	mCommitCallbackRegistrar.add("Pose.Start", boost::bind(&BDFloaterPoser::onPoseStart, this));
+	//BD - Load the current pose and export all its values into the UI so we can alter them.
+	mCommitCallbackRegistrar.add("Pose.Load", boost::bind(&BDFloaterPoser::onPoseLoad, this));
+	//BD - Delete the currently selected Pose.
+	mCommitCallbackRegistrar.add("Pose.Delete", boost::bind(&BDFloaterPoser::onPoseDelete, this));
+	//BD - Change a pose's blend type and time.
+	mCommitCallbackRegistrar.add("Pose.Set", boost::bind(&BDFloaterPoser::onPoseSet, this, _1, _2));
+	//BD - Extend or collapse the floater's pose list.
+	mCommitCallbackRegistrar.add("Pose.Layout", boost::bind(&BDFloaterPoser::onUpdateLayout, this));
+	//BD - Set the desired pose interpolation type.
+	mCommitCallbackRegistrar.add("Pose.Interpolation", boost::bind(&BDFloaterPoser::onJointControlsRefresh, this));
+	//BD - Include some menu interactions. Sadly necessary.
+	mCommitCallbackRegistrar.add("Pose.Menu", boost::bind(&BDFloaterPoser::onPoseMenuAction, this, _2));
+
+	//BD - Change a bone's rotation.
+	mCommitCallbackRegistrar.add("Joint.Set", boost::bind(&BDFloaterPoser::onJointSet, this, _1, _2));
+	//BD - Change a bone's position.
+	mCommitCallbackRegistrar.add("Joint.PosSet", boost::bind(&BDFloaterPoser::onJointPosSet, this, _1, _2));
+	//BD - Change a bone's scale.
+	mCommitCallbackRegistrar.add("Joint.SetScale", boost::bind(&BDFloaterPoser::onJointScaleSet, this, _1, _2));
+	//BD - Add or remove a joint state to or from the pose (enable/disable our overrides).
+	mCommitCallbackRegistrar.add("Joint.ChangeState", boost::bind(&BDFloaterPoser::onJointChangeState, this));
+	//BD - Reset all selected bone rotations and positions.
+	mCommitCallbackRegistrar.add("Joint.ResetJointFull", boost::bind(&BDFloaterPoser::onJointRotPosScaleReset, this));
+	//BD - Reset all selected bone rotations back to 0,0,0.
+	mCommitCallbackRegistrar.add("Joint.ResetJointRotation", boost::bind(&BDFloaterPoser::onJointRotationReset, this));
+	//BD - Reset all selected bones positions back to their default.
+	mCommitCallbackRegistrar.add("Joint.ResetJointPosition", boost::bind(&BDFloaterPoser::onJointPositionReset, this));
+	//BD - Reset all selected bones scales back to their default.
+	mCommitCallbackRegistrar.add("Joint.ResetJointScale", boost::bind(&BDFloaterPoser::onJointScaleReset, this));
+
+	//BD - Toggle Mirror Mode on/off.
+	mCommitCallbackRegistrar.add("Joint.ToggleMirror", boost::bind(&BDFloaterPoser::toggleMirrorMode, this, _1));
+	//BD - Toggle Easy Rotation on/off.
+	mCommitCallbackRegistrar.add("Joint.EasyRotations", boost::bind(&BDFloaterPoser::toggleEasyRotations, this, _1));
+	//BD - Flip pose (mirror).
+	mCommitCallbackRegistrar.add("Joint.FlipPose", boost::bind(&BDFloaterPoser::onFlipPose, this));
+
+	//BD - Refresh the avatar list.
+	mCommitCallbackRegistrar.add("Poser.RefreshAvatars", boost::bind(&BDFloaterPoser::onAvatarsRefresh, this));
+
+	//BD - Add a new entry to the animation creator.
+	mCommitCallbackRegistrar.add("Anim.Add", boost::bind(&BDFloaterPoser::onAnimAdd, this, _2));
+	//BD - Move the selected entry one row up.
+	mCommitCallbackRegistrar.add("Anim.Move", boost::bind(&BDFloaterPoser::onAnimMove, this, _2));
+	//BD - Remove an entry in the animation creator.
+	mCommitCallbackRegistrar.add("Anim.Delete", boost::bind(&BDFloaterPoser::onAnimDelete, this));
+	//BD - Save the currently build list as animation.
+	mCommitCallbackRegistrar.add("Anim.Save", boost::bind(&BDFloaterPoser::onAnimSave, this));
+	//BD - Play the current animator queue.
+	mCommitCallbackRegistrar.add("Anim.Play", boost::bind(&BDFloaterPoser::onAnimPlay, this));
+	//BD - Stop the current animator queue.
+	mCommitCallbackRegistrar.add("Anim.Stop", boost::bind(&BDFloaterPoser::onAnimStop, this));
+	//BD - Change the value for a wait entry.
+	mCommitCallbackRegistrar.add("Anim.Set", boost::bind(&BDFloaterPoser::onAnimSet, this));
+
+	//BD - Test.
+	//mCommitCallbackRegistrar.add("Anim.Edit", boost::bind(&BDFloaterPoser::onAnimEdit, this, _1, _2));
+	//mCommitCallbackRegistrar.add("Anim.SetValue", boost::bind(&BDFloaterPoser::onAnimSetValue, this, _1, _2));
+}
+
+BDFloaterPoser::~BDFloaterPoser()
+{
+}
+
+BOOL BDFloaterPoser::postBuild()
+{
+	//BD - Posing
+	mJointScrolls = { { this->getChild<LLScrollListCtrl>("joints_scroll", true),
+						this->getChild<LLScrollListCtrl>("cv_scroll", true),
+						this->getChild<LLScrollListCtrl>("attach_scroll", true) } };
+
+	mJointScrolls[JOINTS]->setCommitOnSelectionChange(TRUE);
+	mJointScrolls[JOINTS]->setCommitCallback(boost::bind(&BDFloaterPoser::onJointControlsRefresh, this));
+	mJointScrolls[JOINTS]->setDoubleClickCallback(boost::bind(&BDFloaterPoser::onJointChangeState, this));
+
+	//BD - Collision Volumes
+	mJointScrolls[COLLISION_VOLUMES]->setCommitOnSelectionChange(TRUE);
+	mJointScrolls[COLLISION_VOLUMES]->setCommitCallback(boost::bind(&BDFloaterPoser::onJointControlsRefresh, this));
+
+	//BD - Attachment Bones
+	mJointScrolls[ATTACHMENT_BONES]->setCommitOnSelectionChange(TRUE);
+	mJointScrolls[ATTACHMENT_BONES]->setCommitCallback(boost::bind(&BDFloaterPoser::onJointControlsRefresh, this));
+
+	mPoseScroll = this->getChild<LLScrollListCtrl>("poses_scroll", true);
+	mPoseScroll->setCommitOnSelectionChange(TRUE);
+	mPoseScroll->setCommitCallback(boost::bind(&BDFloaterPoser::onPoseControlsRefresh, this));
+	mPoseScroll->setDoubleClickCallback(boost::bind(&BDFloaterPoser::onPoseLoad, this));
+	mPoseScroll->setRightMouseDownCallback(boost::bind(&BDFloaterPoser::onPoseScrollRightMouse, this, _1, _2, _3));
+
+	mRotationSliders = { { getChild<LLUICtrl>("Rotation_X"), getChild<LLUICtrl>("Rotation_Y"), getChild<LLUICtrl>("Rotation_Z") } };
+	mPositionSliders = { { getChild<LLSliderCtrl>("Position_X"), getChild<LLSliderCtrl>("Position_Y"), getChild<LLSliderCtrl>("Position_Z") } };
+	mScaleSliders = { { getChild<LLSliderCtrl>("Scale_X"), getChild<LLSliderCtrl>("Scale_Y"), getChild<LLSliderCtrl>("Scale_Z") } };
+
+	mJointTabs = getChild<LLTabContainer>("joints_tabs");
+	mJointTabs->setCommitCallback(boost::bind(&BDFloaterPoser::onJointControlsRefresh, this));
+
+	//BD - Animesh
+	mAvatarScroll = this->getChild<LLScrollListCtrl>("avatar_scroll", true);
+	mAvatarScroll->setCommitCallback(boost::bind(&BDFloaterPoser::onAvatarsSelect, this));
+
+	//BD - Animations
+	mAnimEditorScroll = this->getChild<LLScrollListCtrl>("anim_editor_scroll", true);
+	mAnimEditorScroll->setCommitCallback(boost::bind(&BDFloaterPoser::onAnimControlsRefresh, this));
+
+	//BD - Misc
+	mDelayRefresh = false;
+
+	mMirrorMode = false;
+	mEasyRotations = true;
+
+	mStartPosingBtn = getChild<LLButton>("activate");
+	mLoadPosesBtn = getChild<LLMenuButton>("load_poses");
+
+	//BD - Poser Menu
+	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Pose.Menu", boost::bind(&BDFloaterPoser::onPoseLoadSelective, this, _2));
+	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_poser_poses.xml",
+		gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	if (context_menu)
+	{
+		mPosesMenuHandle = context_menu->getHandle();
+		mLoadPosesBtn->setMenu(context_menu, LLMenuButton::MP_BOTTOM_LEFT);
+	}
+
+	//BD - Experimental
+	/*mTimeSlider = getChild<LLMultiSliderCtrl>("time_slider");
+	mKeySlider = getChild<LLMultiSliderCtrl>("key_slider");
+
+	mTimeSlider->addSlider();
+	addSliderKey(0.f, BDPoseKey(std::string("Default")));
+	mTimeSlider->setCommitCallback(boost::bind(&BDFloaterPoser::onTimeSliderMoved, this));
+	mKeySlider->setCommitCallback(boost::bind(&BDFloaterPoser::onKeyTimeMoved, this));
+	getChild<LLButton>("add_key")->setClickedCallback(boost::bind(&BDFloaterPoser::onAddKey, this));
+	getChild<LLButton>("delete_key")->setClickedCallback(boost::bind(&BDFloaterPoser::onDeleteKey, this));*/
+
+	return TRUE;
+}
+
+void BDFloaterPoser::draw()
+{
+	if (gDragonAnimator.getIsPlaying())
+	{
+		LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+		if (item)
+		{
+			LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+			if (avatar || !avatar->isDead())
+			{
+				S32 current_index = avatar->getCurrentActionIndex();
+				if (mAnimEditorScroll->getItemCount() != 0)
+				{
+					mAnimEditorScroll->selectNthItem(current_index);
+				}
+			}
+		}
+	}
+
+	LLFloater::draw();
+}
+
+void BDFloaterPoser::onOpen(const LLSD& key)
+{
+	//BD - Check whether we should delay the default value collection or fire it immediately.
+	mDelayRefresh = !gAgentAvatarp->isFullyLoaded();
+	if (!mDelayRefresh)
+	{
+		onCollectDefaults();
+	}
+
+	onAvatarsRefresh();
+	onJointRefresh();
+	onPoseRefresh();
+	onUpdateLayout();
+}
+
+void BDFloaterPoser::onClose(bool app_quitting)
+{
+	//BD - Doesn't matter because we destroy the window and rebuild it every time we open it anyway.
+	mJointScrolls[JOINTS]->clearRows();
+	mJointScrolls[COLLISION_VOLUMES]->clearRows();
+	mJointScrolls[ATTACHMENT_BONES]->clearRows();
+	mAvatarScroll->clearRows();
+}
+
+////////////////////////////////
+//BD - Poses
+////////////////////////////////
+void BDFloaterPoser::onPoseRefresh()
+{
+	mPoseScroll->clearRows();
+	std::string dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", "");
+	std::string file;
+	LLDirIterator dir_iter(dir, "*.xml");
+	while (dir_iter.next(file))
+	{
+		std::string path = gDirUtilp->add(dir, file);
+		std::string name = gDirUtilp->getBaseFileName(LLURI::unescape(path), true);
+
+		LLSD row;
+		row["columns"][0]["column"] = "name";
+		row["columns"][0]["value"] = name;
+
+		llifstream infile;
+		infile.open(path);
+		if (!infile.is_open())
+		{
+			LL_WARNS("Posing") << "Skipping: Cannot read file in: " << path << LL_ENDL;
+			continue;
+		}
+
+		LLSD data;
+		if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(data, infile))
+		{
+			LL_WARNS("Posing") << "Skipping: Failed to parse pose file: " << path << LL_ENDL;
+			continue;
+		}
+
+		if (!infile.eof())
+		{
+			row["columns"][1]["column"] = "time";
+			row["columns"][1]["value"] = data["time"];
+			row["columns"][2]["column"] = "type";
+			row["columns"][2]["value"] = data["type"];
+		}
+		mPoseScroll->addElement(row);
+	}
+	onJointControlsRefresh();
+}
+
+void BDFloaterPoser::onClickPoseSave()
+{
+	//BD - Values don't matter when not editing.
+	onPoseSave(2, 0.1f, false);
+}
+
+void BDFloaterPoser::onPoseSave(S32 type, F32 time, bool editing)
+{
+	LLScrollListItem* av_item = mAvatarScroll->getFirstSelected();
+	if (!av_item)
+	{
+		LL_WARNS("Posing") << "No avatar selected." << LL_ENDL;
+		return;
+	}
+
+	LLVOAvatar* avatar = (LLVOAvatar*)av_item->getUserdata();
+	if (!avatar || avatar->isDead())
+	{
+		LL_WARNS("Posing") << "Couldn't find avatar, dead?" << LL_ENDL;
+		return;
+	}
+
+	//BD - First and foremost before we do anything, check if the folder exists.
+	std::string pathname = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses");
+	if (!gDirUtilp->fileExists(pathname))
+	{
+		LL_WARNS("Posing") << "Couldn't find folder: " << pathname << " - creating one." << LL_ENDL;
+		LLFile::mkdir(pathname);
+	}
+
+	std::string filename;
+	if (editing)
+	{
+		LLScrollListItem* item = mPoseScroll->getFirstSelected();
+		if (item)
+		{
+			filename = item->getColumn(0)->getValue().asString();
+		}
+	}
+	else
+	{
+		filename = getChild<LLUICtrl>("pose_name")->getValue().asString();
+	}
+
+	if (filename.empty())
+	{
+		return;
+	}
+
+	std::string full_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", LLDir::escapePathString(filename) + ".xml");
+	LLSD record;
+	S32 line = 0;
+
+	if (editing)
+	{
+		llifstream infile;
+
+		infile.open(full_path);
+		if (!infile.is_open())
+		{
+			LL_WARNS("Posing") << "Cannot find file in: " << filename << LL_ENDL;
+			return;
+		}
+
+		LLSD old_record;
+		//BD - Read the pose and save it into an LLSD so we can rewrite it later.
+		while (!infile.eof())
+		{
+			if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXML(old_record, infile))
+			{
+				LL_WARNS("Posing") << "Failed to parse while rewrtiting file: " << filename << LL_ENDL;
+				return;
+			}
+
+			if (line != 0)
+			{
+				record[line] = old_record;
+			}
+			++line;
+		}
+
+		//BD - Change the header here.
+		record[0]["type"] = type;
+		//BD - If we are using spherical linear interpolation we need to clamp the values 
+		//     between 0.001f and 1.f otherwise unexpected things might happen.
+		if (type == 2)
+		{
+			time = llclamp(time, 0.001f, 1.0f);
+		}
+		record[0]["time"] = time;
+
+		infile.close();
+
+		LLScrollListItem* item = mPoseScroll->getFirstSelected();
+		if (item)
+		{
+			item->getColumn(1)->setValue(time);
+			item->getColumn(2)->setValue(type);
+		}
+	}
+	else
+	{
+		//BD - Create the header first.
+		S32 type = getChild<LLUICtrl>("interpolation_type")->getValue();
+		F32 time = getChild<LLUICtrl>("interpolation_time")->getValue().asReal();
+		//BD - If we are using spherical linear interpolation we need to clamp the values 
+		//     between 0.001f and 1.f otherwise unexpected things might happen.
+		if (type == 2)
+		{
+			time = llclamp(time, 0.001f, 1.0f);
+		}
+		record[line]["time"] = time;
+		record[line]["type"] = type;
+		++line;
+
+		//BD - Now create the rest.
+		for (S32 it = 0; it < 3; ++it)
+		{
+			for (auto element : mJointScrolls[it]->getAllData())
+			{
+				LLVector3 vec3;
+				LLJoint* joint = (LLJoint*)element->getUserdata();
+				if (joint)
+				{
+					record[line]["bone"] = joint->getName();
+					joint->getTargetRotation().getEulerAngles(&vec3.mV[VX], &vec3.mV[VZ], &vec3.mV[VY]);
+					record[line]["rotation"] = vec3.getValue();
+
+					//BD - We could just check whether position information is available since only joints
+					//     which can have their position changed will have position information but we
+					//     want this to be a minefield for crashes.
+					//     Bones that can support position
+					//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+					//     as well as all attachment bones and collision volumes.
+					if (joint->mHasPosition || it > JOINTS)
+					{
+						vec3 = joint->getTargetPosition();
+						record[line]["position"] = vec3.getValue();
+					}
+
+					vec3 = joint->getScale();
+					record[line]["scale"] = vec3.getValue();
+
+					if (it == JOINTS)
+					{
+						//BD - Save the enabled state per preset so we can switch bones on and off
+						//     on demand inbetween poses additionally to globally.
+						BDPosingMotion* motion = (BDPosingMotion*)gAgentAvatarp->findMotion(ANIM_BD_POSING_MOTION);
+						if (motion)
+						{
+							LLPose* pose = motion->getPose();
+							if (pose)
+							{
+								if (pose->findJointState(joint))
+								{
+									record[line]["enabled"] = true;
+								}
+								else
+								{
+									record[line]["enabled"] = false;
+								}
+							}
+						}
+					}
+					++line;
+				}
+			}
+		}
+	}
+	
+	llofstream file;
+	file.open(full_path.c_str());
+	//BD - Now lets actually write the file, whether it is writing a new one
+	//     or just rewriting the previous one with a new header.
+	for (LLSD cur_line : llsd::inArray(record))
+	{
+		LLSDSerialize::toXML(cur_line, file);
+	}
+	file.close();
+
+	if (!editing)
+	{
+		onPoseRefresh();
+	}
+}
+
+void BDFloaterPoser::onPoseLoad()
+{
+	LLScrollListItem* item = mPoseScroll->getFirstSelected();
+	if (!item) return;
+
+	std::string pose_name = item->getColumn(0)->getValue().asString();
+
+	gDragonAnimator.loadPose(pose_name);
+	onJointRefresh();
+}
+
+void BDFloaterPoser::onPoseLoadSelective(const LLSD& param)
+{
+	LLScrollListItem* item = mPoseScroll->getFirstSelected();
+	if (!item) return;
+
+	std::string pose_name = item->getColumn(0)->getValue().asString();
+
+	S32 load_type = 0;
+	if (param.asString() == "rotation")
+		load_type |= ROTATIONS;
+	else if (param.asString() == "position")
+		load_type |= POSITIONS;
+	else if (param.asString() == "scale")
+		load_type |= SCALES;
+	else if (param.asString() == "rot_pos")
+		load_type |= ROTATIONS | POSITIONS;
+	else if (param.asString() == "rot_scale")
+		load_type |= ROTATIONS | SCALES;
+	else if (param.asString() == "pos_scale")
+		load_type |= POSITIONS | SCALES;
+	else if (param.asString() == "all")
+		load_type |= ROTATIONS | POSITIONS | SCALES;
+
+	gDragonAnimator.loadPose(pose_name, load_type);
+	onJointRefresh();
+}
+
+void BDFloaterPoser::onPoseStart()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	BDPosingMotion* motion = (BDPosingMotion*)avatar->findMotion(ANIM_BD_POSING_MOTION);
+	if (!motion || motion->isStopped())
+	{
+		avatar->setPosing();
+		if (avatar->isSelf())
+		{
+			//BD - Grab our current defaults to revert to them when stopping the Poser.
+			if(gAgentAvatarp->isFullyLoaded())
+				onCollectDefaults();
+
+			gAgent.stopFidget();
+			//gDragonStatus->setPosing(true);
+		}
+		avatar->startMotion(ANIM_BD_POSING_MOTION);
+	}
+	else
+	{
+		//BD - Reset everything, all rotations, positions and scales of all bones.
+		onJointRotPosScaleReset();
+
+		//BD - Clear posing when we're done now that we've safely endangered getting spaghetified.
+		avatar->clearPosing();
+		avatar->stopMotion(ANIM_BD_POSING_MOTION);
+
+		if (avatar->isSelf())
+		{
+			//gDragonStatus->setPosing(false);
+		}
+	}
+	//BD - Wipe the joint list.
+	onJointRefresh();
+
+	onPoseControlsRefresh();
+}
+
+void BDFloaterPoser::onPoseDelete()
+{
+	for (auto item : mPoseScroll->getAllSelected())
+	{
+		std::string filename = item->getColumn(0)->getValue().asString();
+		std::string dirname = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses");
+
+		if (gDirUtilp->deleteFilesInDir(dirname, LLDir::escapePathString(filename) + ".xml") < 1)
+		{
+			LL_WARNS("Posing") << "Cannot remove file: " << filename << LL_ENDL;
+		}
+	}
+	onPoseRefresh();
+}
+
+//BD - We use this function to edit an already saved pose's interpolation time or type.
+//     Both are combined into one function.
+void BDFloaterPoser::onPoseSet(LLUICtrl* ctrl, const LLSD& param)
+{
+	LLScrollListItem* item = mPoseScroll->getFirstSelected();
+	if (item)
+	{
+		S32 type;
+		F32 time;
+		//BD - We either edit the interpolation time here or if we don't we automatically assume 
+		//     we are trying to edit the interpolation type.
+		if (param.asString() == "time")
+		{
+			//BD - Get the new interpolation time from the time widget and read the type from
+			//     the list as we are not going to change it anyway.
+			time = getChild<LLUICtrl>("interp_time")->getValue().asReal();
+			type = item->getColumn(2)->getValue().asInteger();
+		}
+		else
+		{
+			//BD - Do the opposite here.
+			time = item->getColumn(1)->getValue().asReal();
+			type = getChild<LLUICtrl>("interp_type")->getValue().asInteger();
+		}
+		onPoseSave(type, time, true);
+	}
+}
+
+void BDFloaterPoser::onPoseControlsRefresh()
+{
+	bool is_playing = gDragonAnimator.getIsPlaying();
+	LLScrollListItem* item = mPoseScroll->getFirstSelected();
+	if (item)
+	{
+		getChild<LLUICtrl>("interp_time")->setValue(item->getColumn(1)->getValue());
+		getChild<LLUICtrl>("interp_type")->setValue(item->getColumn(2)->getValue());
+	}
+	getChild<LLUICtrl>("interp_time")->setEnabled(bool(item));
+	getChild<LLUICtrl>("interp_type")->setEnabled(bool(item));
+	getChild<LLUICtrl>("delete_poses")->setEnabled(bool(item));
+	getChild<LLUICtrl>("add_entry")->setEnabled(!is_playing && item);
+	getChild<LLUICtrl>("load_poses")->setEnabled(bool(item));
+}
+
+void BDFloaterPoser::onPoseMenuAction(const LLSD& param)
+{
+	onPoseLoadSelective(param);
+}
+
+void BDFloaterPoser::onPoseScrollRightMouse(LLUICtrl* ctrl, S32 x, S32 y)
+{
+	mPoseScroll->selectItemAt(x, y, MASK_NONE);
+	if (mPoseScroll->getFirstSelected())
+	{
+		LLToggleableMenu* poses_menu = mPosesMenuHandle.get();
+		if (poses_menu)
+		{
+			poses_menu->buildDrawLabels();
+			poses_menu->updateParent(LLMenuGL::sMenuContainer);
+			LLMenuGL::showPopup(mPoseScroll, poses_menu, x, y);
+		}
+	}
+}
+
+////////////////////////////////
+//BD - Joints
+////////////////////////////////
+void BDFloaterPoser::onJointRefresh()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	if (!(avatar->getRegion() == gAgent.getRegion())) return;
+
+	//BD - Getting collision volumes and attachment points.
+	std::vector<std::string> cv_names, attach_names;
+	avatar->getSortedJointNames(1, cv_names);
+	avatar->getSortedJointNames(2, attach_names);
+
+	bool is_posing = avatar->getPosing();
+	mJointScrolls[JOINTS]->clearRows();
+	mJointScrolls[COLLISION_VOLUMES]->clearRows();
+	mJointScrolls[ATTACHMENT_BONES]->clearRows();
+
+	LLVector3 rot;
+	LLVector3 pos;
+	LLVector3 scale;
+	LLJoint* joint;
+	for (S32 i = 0; (joint = avatar->getCharacterJoint(i)); ++i)
+	{
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint)	continue;
+
+		LLSD row;
+		const std::string joint_name = joint->getName();
+		//BD - Show some categories to make it a bit easier finding out which
+		//     bone belongs where and what they might be for those who can't use
+		//     bone names.
+		if (joint->mJointNum == 0 ||	//mPelvis
+			joint->mJointNum == 8 ||	//mHead
+			joint->mJointNum == 58 ||	//mCollarLeft
+			joint->mJointNum == 77 ||	//mCollarRight
+			joint->mJointNum == 96 ||	//mWingsRoot
+			joint->mJointNum == 107 ||	//mHipRight
+			joint->mJointNum == 112 ||	//mHipLeft
+			joint->mJointNum == 117 ||	//mTail1
+			joint->mJointNum == 123)	//mGroin
+		{
+			row["columns"][COL_ICON]["column"] = "icon";
+			row["columns"][COL_ICON]["type"] = "icon";
+			row["columns"][COL_ICON]["value"] = getString("icon_category");
+			row["columns"][COL_NAME]["column"] = "joint";
+			row["columns"][COL_NAME]["value"] = getString("title_" + joint_name);
+			LLScrollListItem* element = mJointScrolls[JOINTS]->addElement(row);
+			element->setEnabled(FALSE);
+		}
+
+		row["columns"][COL_ICON]["column"] = "icon";
+		row["columns"][COL_ICON]["type"] = "icon";
+		row["columns"][COL_ICON]["value"] = getString("icon_bone");
+		row["columns"][COL_NAME]["column"] = "joint";
+		row["columns"][COL_NAME]["value"] = joint_name;
+
+		if (is_posing)
+		{
+			//BD - Bone Rotations
+			joint->getTargetRotation().getEulerAngles(&rot.mV[VX], &rot.mV[VY], &rot.mV[VZ]);
+			row["columns"][COL_ROT_X]["column"] = "x";
+			row["columns"][COL_ROT_X]["value"] = ll_round(rot.mV[VX], 0.001f);
+			row["columns"][COL_ROT_Y]["column"] = "y";
+			row["columns"][COL_ROT_Y]["value"] = ll_round(rot.mV[VY], 0.001f);
+			row["columns"][COL_ROT_Z]["column"] = "z";
+			row["columns"][COL_ROT_Z]["value"] = ll_round(rot.mV[VZ], 0.001f);
+
+			//BD - Bone Scales
+			scale = joint->getScale();
+			row["columns"][COL_SCALE_X]["column"] = "scale_x";
+			row["columns"][COL_SCALE_X]["value"] = ll_round(scale.mV[VX], 0.001f);
+			row["columns"][COL_SCALE_Y]["column"] = "scale_y";
+			row["columns"][COL_SCALE_Y]["value"] = ll_round(scale.mV[VY], 0.001f);
+			row["columns"][COL_SCALE_Z]["column"] = "scale_z";
+			row["columns"][COL_SCALE_Z]["value"] = ll_round(scale.mV[VZ], 0.001f);
+		}
+
+		//BD - We could just check whether position information is available since only joints
+		//     which can have their position changed will have position information but we
+		//     want this to be a minefield for crashes.
+		//     Bones that can support position
+		//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+		if (joint->mHasPosition)
+		{
+			if (is_posing)
+			{
+				pos = joint->getTargetPosition();
+				row["columns"][COL_POS_X]["column"] = "pos_x";
+				row["columns"][COL_POS_X]["value"] = ll_round(pos.mV[VX], 0.001f);
+				row["columns"][COL_POS_Y]["column"] = "pos_y";
+				row["columns"][COL_POS_Y]["value"] = ll_round(pos.mV[VY], 0.001f);
+				row["columns"][COL_POS_Z]["column"] = "pos_z";
+				row["columns"][COL_POS_Z]["value"] = ll_round(pos.mV[VZ], 0.001f);
+			}
+		}
+
+		LLScrollListItem* item = mJointScrolls[JOINTS]->addElement(row);
+		item->setUserdata(joint);
+
+		//BD - We need to check if we are posing or not, simply set all bones to deactivated
+		//     when we are not posed otherwise they will remain on "enabled" state. This behavior
+		//     could be confusing to the user, this is due to how animations work.
+		if (is_posing)
+		{
+			BDPosingMotion* motion = (BDPosingMotion*)avatar->findMotion(ANIM_BD_POSING_MOTION);
+			if (motion)
+			{
+				LLPose* pose = motion->getPose();
+				if (pose)
+				{
+					// BD - We do check here for the joint_state because otherwise we end up with the toggle
+					//      state not appearing properly toggled/untoggled when we first refresh after firing
+					//      up the poser. At the same time this is used to refresh all bone states when we
+					//      load a pose.
+					LLPointer<LLJointState> joint_state = pose->findJointState(joint);
+					if (joint_state)
+					{
+						((LLScrollListText*)item->getColumn(COL_NAME))->setFontStyle(LLFontGL::BOLD);
+					}
+				}
+			}
+		}
+		else
+		{
+			((LLScrollListText*)item->getColumn(COL_NAME))->setFontStyle(LLFontGL::NORMAL);
+		}
+	}
+
+	//BD - We add an empty line into both lists and include an icon to automatically resize
+	//     the list row heights to sync up with the height in our joint list. We remove it
+	//     immediately after anyway.
+	LLSD test_row;
+	test_row["columns"][COL_ICON]["column"] = "icon";
+	test_row["columns"][COL_ICON]["type"] = "icon";
+	test_row["columns"][COL_ICON]["value"] = getString("icon_category");
+	mJointScrolls[COLLISION_VOLUMES]->addElement(test_row);
+	mJointScrolls[COLLISION_VOLUMES]->deleteSingleItem(0);
+	mJointScrolls[ATTACHMENT_BONES]->addElement(test_row);
+	mJointScrolls[ATTACHMENT_BONES]->deleteSingleItem(0);
+
+	//BD - Collision Volumes
+	for (auto name : cv_names)
+	{
+		joint = avatar->getJoint(name);
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint) continue;
+
+		LLSD row;
+		row["columns"][COL_ICON]["column"] = "icon";
+		row["columns"][COL_ICON]["type"] = "icon";
+		row["columns"][COL_ICON]["value"] = getString("icon_bone");
+		row["columns"][COL_NAME]["column"] = "joint";
+		row["columns"][COL_NAME]["value"] = name;
+
+		if (is_posing)
+		{
+			//BD - Bone Positions
+			pos = joint->getPosition();
+			row["columns"][COL_POS_X]["column"] = "pos_x";
+			row["columns"][COL_POS_X]["value"] = ll_round(pos.mV[VX], 0.001f);
+			row["columns"][COL_POS_Y]["column"] = "pos_y";
+			row["columns"][COL_POS_Y]["value"] = ll_round(pos.mV[VY], 0.001f);
+			row["columns"][COL_POS_Z]["column"] = "pos_z";
+			row["columns"][COL_POS_Z]["value"] = ll_round(pos.mV[VZ], 0.001f);
+
+			//BD - Bone Scales
+			scale = joint->getScale();
+			row["columns"][COL_SCALE_X]["column"] = "scale_x";
+			row["columns"][COL_SCALE_X]["value"] = ll_round(scale.mV[VX], 0.001f);
+			row["columns"][COL_SCALE_Y]["column"] = "scale_y";
+			row["columns"][COL_SCALE_Y]["value"] = ll_round(scale.mV[VY], 0.001f);
+			row["columns"][COL_SCALE_Z]["column"] = "scale_z";
+			row["columns"][COL_SCALE_Z]["value"] = ll_round(scale.mV[VZ], 0.001f);
+		}
+
+		LLScrollListItem* item = mJointScrolls[COLLISION_VOLUMES]->addElement(row);
+		item->setUserdata(joint);
+	}
+
+	//BD - Attachment Bones
+	for (auto name : attach_names)
+	{
+		joint = avatar->getJoint(name);
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint) continue;
+
+		LLSD row;
+		row["columns"][COL_ICON]["column"] = "icon";
+		row["columns"][COL_ICON]["type"] = "icon";
+		row["columns"][COL_ICON]["value"] = getString("icon_bone");
+		row["columns"][COL_NAME]["column"] = "joint";
+		row["columns"][COL_NAME]["value"] = name;
+
+		if (is_posing)
+		{
+			//BD - Bone Positions
+			pos = joint->getPosition();
+			row["columns"][COL_POS_X]["column"] = "pos_x";
+			row["columns"][COL_POS_X]["value"] = ll_round(pos.mV[VX], 0.001f);
+			row["columns"][COL_POS_Y]["column"] = "pos_y";
+			row["columns"][COL_POS_Y]["value"] = ll_round(pos.mV[VY], 0.001f);
+			row["columns"][COL_POS_Z]["column"] = "pos_z";
+			row["columns"][COL_POS_Z]["value"] = ll_round(pos.mV[VZ], 0.001f);
+
+			//BD - Bone Scales
+			scale = joint->getScale();
+			row["columns"][COL_SCALE_X]["column"] = "scale_x";
+			row["columns"][COL_SCALE_X]["value"] = ll_round(scale.mV[VX], 0.001f);
+			row["columns"][COL_SCALE_Y]["column"] = "scale_y";
+			row["columns"][COL_SCALE_Y]["value"] = ll_round(scale.mV[VY], 0.001f);
+			row["columns"][COL_SCALE_Z]["column"] = "scale_z";
+			row["columns"][COL_SCALE_Z]["value"] = ll_round(scale.mV[VZ], 0.001f);
+		}
+
+		LLScrollListItem* item = mJointScrolls[ATTACHMENT_BONES]->addElement(row);
+		item->setUserdata(joint);
+	}
+
+	onJointControlsRefresh();
+}
+
+void BDFloaterPoser::onJointControlsRefresh()
+{
+	LLScrollListItem* av_item = mAvatarScroll->getFirstSelected();
+	if (!av_item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)av_item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	bool can_position = false;
+	bool is_pelvis = false;
+	bool is_posing = (avatar->isFullyLoaded() && avatar->getPosing());
+	S32 index = mJointTabs->getCurrentPanelIndex();
+	LLScrollListItem* item = mJointScrolls[index]->getFirstSelected();
+
+	if (item)
+	{
+		LLJoint* joint = (LLJoint*)item->getUserdata();
+		if (joint)
+		{
+			if (index == 0)
+			{
+				mRotationSliders[VX]->setValue(item->getColumn(COL_ROT_X)->getValue());
+				mRotationSliders[VY]->setValue(item->getColumn(COL_ROT_Y)->getValue());
+				mRotationSliders[VZ]->setValue(item->getColumn(COL_ROT_Z)->getValue());
+			}
+
+			//BD - We could just check whether position information is available since only joints
+			//     which can have their position changed will have position information but we
+			//     want this to be a minefield for crashes.
+			//     Bones that can support position
+			//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+			//     as well as all attachment bones and collision volumes.
+			if (joint->mHasPosition || index > JOINTS)
+			{
+				can_position = true;
+				is_pelvis = (joint->mJointNum == 0);
+
+				mPositionSliders[VX]->setValue(item->getColumn(COL_POS_X)->getValue());
+				mPositionSliders[VY]->setValue(item->getColumn(COL_POS_Y)->getValue());
+				mPositionSliders[VZ]->setValue(item->getColumn(COL_POS_Z)->getValue());
+			}
+			else
+			{
+				//BD - If we didn't select a positionable bone kill all values. We might
+				//     end up with numbers that are too big for the min/max values when
+				//     changed below.
+				mPositionSliders[VX]->setValue(0.000f);
+				mPositionSliders[VY]->setValue(0.000f);
+				mPositionSliders[VZ]->setValue(0.000f);
+			}
+
+			//BD - Bone Scales
+			mScaleSliders[VX]->setValue(item->getColumn(COL_SCALE_X)->getValue());
+			mScaleSliders[VY]->setValue(item->getColumn(COL_SCALE_Y)->getValue());
+			mScaleSliders[VZ]->setValue(item->getColumn(COL_SCALE_Z)->getValue());
+
+			BDPosingMotion* motion = (BDPosingMotion*)gAgentAvatarp->findMotion(ANIM_BD_POSING_MOTION);
+			if (motion)
+			{
+				//BD - If we don't use our default spherical interpolation, set it once.
+				motion->setInterpolationTime(0.25f);
+				motion->setInterpolationType(2);
+
+				LLPose* pose = motion->getPose();
+				if (pose)
+				{
+					LLPointer<LLJointState> joint_state = pose->findJointState(joint);
+					getChild<LLButton>("toggle_bone")->setValue(joint_state.notNull());
+				}
+			}
+		}
+	}
+
+	getChild<LLButton>("toggle_bone")->setEnabled(item && is_posing && index == JOINTS);
+	getChild<LLButton>("activate")->setValue(is_posing);
+	getChild<LLUICtrl>("pose_name")->setEnabled(is_posing);
+	getChild<LLUICtrl>("save_poses")->setEnabled(is_posing);
+	getChild<LLUICtrl>("joints_tabs")->setEnabled(is_posing);
+
+	//BD - Depending on which interpolation type the user selects we want the time editor to show
+	//     a different label, since spherical and linear both have different min/max numbers and
+	//     work differently with them.
+	//     Spherical: 0.001 - 1.0.
+	//     Linear: 0.0 - infinite.
+	getChild<LLUICtrl>("interpolation_type")->setEnabled(is_posing);
+	S32 interp_type = getChild<LLUICtrl>("interpolation_type")->getValue();
+	getChild<LLUICtrl>("interpolation_time")->setEnabled(is_posing && interp_type != 0);
+	const std::string label_time = interp_type == 1 ? "linear_time" : "spherical_time";
+	getChild<LLLineEditor>("interpolation_time")->setLabel(getString(label_time));
+
+	//BD - Enable position tabs whenever positions are available, scales are always enabled
+	//     unless we are editing attachment bones, rotations on the other hand are only
+	//     enabled when editing joints.
+	LLTabContainer* modifier_tabs = getChild<LLTabContainer>("modifier_tabs");
+	modifier_tabs->setEnabled(item && is_posing);
+	modifier_tabs->enableTabButton(0, (item && is_posing && index == JOINTS));
+	modifier_tabs->enableTabButton(1, (item && is_posing && can_position));
+	modifier_tabs->enableTabButton(2, (item && is_posing && index != ATTACHMENT_BONES));
+
+	F32 max_val = is_pelvis ? 20.f : 1.0f;
+	mPositionSliders[VX]->setMaxValue(max_val);
+	mPositionSliders[VY]->setMaxValue(max_val);
+	mPositionSliders[VZ]->setMaxValue(max_val);
+	mPositionSliders[VX]->setMinValue(-max_val);
+	mPositionSliders[VY]->setMinValue(-max_val);
+	mPositionSliders[VZ]->setMinValue(-max_val);
+
+	//BD - Change our animator's target, make sure it is always up-to-date.
+	gDragonAnimator.mTargetAvatar = avatar;
+}
+
+void BDFloaterPoser::onJointSet(LLUICtrl* ctrl, const LLSD& param)
+{
+	//BD - Rotations are only supported by joints so far, everything
+	//     else snaps back instantly.
+	LLScrollListItem* item = mJointScrolls[JOINTS]->getFirstSelected();
+	if (!item)
+		return;
+
+	LLJoint* joint = (LLJoint*)item->getUserdata();
+	if (!joint)
+		return;
+
+	//BD - Neat yet quick and direct way of rotating our bones.
+	//     No more need to include bone rotation orders.
+	F32 val = ctrl->getValue().asReal();
+	S32 axis = param.asInteger();
+	LLScrollListCell* cell[3] = { item->getColumn(COL_ROT_X), item->getColumn(COL_ROT_Y), item->getColumn(COL_ROT_Z) };
+	LLQuaternion rot_quat = joint->getTargetRotation();
+	LLMatrix3 rot_mat;
+	F32 old_value;
+	F32 new_value;
+	LLVector3 vec3;
+
+	old_value = cell[axis]->getValue().asReal();
+	cell[axis]->setValue(ll_round(val, 0.001f));
+	new_value = val - old_value;
+	vec3.mV[axis] = new_value;
+	rot_mat = LLMatrix3(vec3.mV[VX], vec3.mV[VY], vec3.mV[VZ]);
+	rot_quat = LLQuaternion(rot_mat)*rot_quat;
+	joint->setTargetRotation(rot_quat);
+	if (!mEasyRotations)
+	{
+		rot_quat.getEulerAngles(&vec3.mV[VX], &vec3.mV[VY], &vec3.mV[VZ]);
+		S32 i = 0;
+		while (i < 3)
+		{
+			if (i != axis)
+			{
+				cell[i]->setValue(ll_round(vec3.mV[i], 0.001f));
+				mRotationSliders[i]->setValue(item->getColumn(i + 2)->getValue());
+			}
+			++i;
+		}
+	}
+	
+	//BD - If we are in Mirror mode, try to find the opposite bone of our currently
+	//     selected one, for now this simply means we take the name and replace "Left"
+	//     with "Right" and vise versa since all bones are conveniently that way.
+	//     TODO: Do this when creating the joint list so we don't try to find the joint
+	//     over and over again.
+	if (mMirrorMode)
+	{
+		LLJoint* mirror_joint = nullptr;
+		std::string mirror_joint_name = joint->getName();
+		S32 idx = joint->getName().find("Left");
+		if (idx != -1)
+			mirror_joint_name.replace(idx, mirror_joint_name.length(), "Right");
+
+		idx = joint->getName().find("Right");
+		if (idx != -1)
+			mirror_joint_name.replace(idx, mirror_joint_name.length(), "Left");
+
+		if (mirror_joint_name != joint->getName())
+		{
+			mirror_joint = gDragonAnimator.mTargetAvatar->mRoot->findJoint(mirror_joint_name);
+		}
+
+		if (mirror_joint)
+		{
+			//BD - For the opposite joint we invert X and Z axis, everything else is directly applied
+			//     exactly like we do it in our currently selected joint.
+			if (axis != 1)
+				val = -val;
+
+			LLQuaternion inv_quat = LLQuaternion(-rot_quat.mQ[VX], rot_quat.mQ[VY], -rot_quat.mQ[VZ], rot_quat.mQ[VW]);
+			mirror_joint->setTargetRotation(inv_quat);
+
+			//BD - We also need to find the opposite joint's list entry and change its values to reflect
+			//     the new ones, doing this here is still better than causing a complete refresh.
+			LLScrollListItem* item2 = mJointScrolls[JOINTS]->getItemByLabel(mirror_joint_name, FALSE, COL_NAME);
+			if (item2)
+			{
+				LLScrollListCell* cell2[3] = { item2->getColumn(COL_ROT_X), item2->getColumn(COL_ROT_Y), item2->getColumn(COL_ROT_Z) };
+				S32 i = 0;
+				while (i < 3)
+				{
+					cell2[i]->setValue(ll_round(item->getColumn(i + 2)->getValue(), 0.001f));
+					++i;
+				}
+			}
+		}
+	}
+}
+
+void BDFloaterPoser::onJointPosSet(LLUICtrl* ctrl, const LLSD& param)
+{
+	S32 index = mJointTabs->getCurrentPanelIndex();
+	LLScrollListItem* item = mJointScrolls[index]->getFirstSelected();
+
+	if (item)
+	{
+		LLJoint* joint = (LLJoint*)item->getUserdata();
+		if (joint)
+		{
+			//BD - We could just check whether position information is available since only joints
+			//     which can have their position changed will have position information but we
+			//     want this to be a minefield for crashes.
+			//     Bones that can support position
+			//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+			//     as well as all attachment bones and collision volumes.
+			if (joint->mHasPosition || index > JOINTS)
+			{
+				F32 val = ctrl->getValue().asReal();
+				LLScrollListCell* cell[3] = { item->getColumn(COL_POS_X), item->getColumn(COL_POS_Y), item->getColumn(COL_POS_Z) };
+				LLVector3 vec3 = { F32(cell[VX]->getValue().asReal()),
+								   F32(cell[VY]->getValue().asReal()),
+								   F32(cell[VZ]->getValue().asReal()) };
+
+				S32 dir = param.asInteger();
+				vec3.mV[dir] = val;
+				cell[dir]->setValue(ll_round(vec3.mV[dir], 0.001f));
+				joint->setTargetPosition(vec3);
+			}
+		}
+	}
+}
+
+void BDFloaterPoser::onJointScaleSet(LLUICtrl* ctrl, const LLSD& param)
+{
+	S32 index = mJointTabs->getCurrentPanelIndex();
+	LLScrollListItem* item = mJointScrolls[index]->getFirstSelected();
+
+	if (item)
+	{
+		LLJoint* joint = (LLJoint*)item->getUserdata();
+		if (joint)
+		{
+			F32 val = ctrl->getValue().asReal();
+			LLScrollListCell* cell[3] = { item->getColumn(COL_SCALE_X), item->getColumn(COL_SCALE_Y), item->getColumn(COL_SCALE_Z) };
+			LLVector3 vec3 = { F32(cell[VX]->getValue().asReal()),
+							   F32(cell[VY]->getValue().asReal()),
+							   F32(cell[VZ]->getValue().asReal()) };
+
+			S32 dir = param.asInteger();
+			vec3.mV[dir] = val;
+			cell[dir]->setValue(ll_round(vec3.mV[dir], 0.001f));
+			joint->setScale(vec3);
+		}
+	}
+}
+
+void BDFloaterPoser::onJointChangeState()
+{
+	BDPosingMotion* motion = (BDPosingMotion*)gAgentAvatarp->findMotion(ANIM_BD_POSING_MOTION);
+	if (motion)
+	{
+		for (auto item : mJointScrolls[JOINTS]->getAllSelected())
+		{
+			LLJoint* joint = (LLJoint*)item->getUserdata();
+			if (joint)
+			{
+				LLPose* pose = motion->getPose();
+				if (pose)
+				{
+					LLPointer<LLJointState> joint_state = pose->findJointState(joint);
+					if (joint_state)
+					{
+						motion->removeJointState(joint_state);
+						((LLScrollListText*)item->getColumn(COL_NAME))->setFontStyle(LLFontGL::NORMAL);
+					}
+					else
+					{
+						motion->addJointToState(joint);
+						((LLScrollListText*)item->getColumn(COL_NAME))->setFontStyle(LLFontGL::BOLD);
+					}
+				}
+			}
+		}
+	}
+	onJointControlsRefresh();
+}
+
+//BD - We use this to reset everything at once.
+void BDFloaterPoser::onJointRotPosScaleReset()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	//BD - We don't support resetting bones for anyone else yet.
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead() || !avatar->isSelf()) return;
+
+	//BD - While editing rotations, make sure we use a bit of spherical linear interpolation 
+	//     to make movements smoother.
+	BDPosingMotion* motion = (BDPosingMotion*)avatar->findMotion(ANIM_BD_POSING_MOTION);
+	if (motion)
+	{
+		//BD - If we don't use our default spherical interpolation, set it once.
+		motion->setInterpolationTime(0.25f);
+		motion->setInterpolationType(2);
+	}
+
+	for (S32 it = 0; it < 3; ++it)
+	{
+		//BD - We use this bool to determine whether or not we'll be in need for a full skeleton
+		//     reset and to prevent checking for it every single time.
+		for (auto item : mJointScrolls[it]->getAllData())
+		{
+			if (item)
+			{
+				LLJoint* joint = (LLJoint*)item->getUserdata();
+				if (joint)
+				{
+					//BD - Resetting rotations first if there are any.
+					if (it == JOINTS)
+					{
+						LLQuaternion quat;
+						LLScrollListCell* col_rot_x = item->getColumn(COL_ROT_X);
+						LLScrollListCell* col_rot_y = item->getColumn(COL_ROT_X);
+						LLScrollListCell* col_rot_z = item->getColumn(COL_ROT_X);
+
+						col_rot_x->setValue(0.000f);
+						col_rot_y->setValue(0.000f);
+						col_rot_z->setValue(0.000f);
+
+						quat.setEulerAngles(0, 0, 0);
+						joint->setTargetRotation(quat);
+
+						//BD - If we are in Mirror mode, try to find the opposite bone of our currently
+						//     selected one, for now this simply means we take the name and replace "Left"
+						//     with "Right" and vise versa since all bones are conveniently that way.
+						//     TODO: Do this when creating the joint list so we don't try to find the joint
+						//     over and over again.
+						if (mMirrorMode)
+						{
+							LLJoint* mirror_joint = nullptr;
+							std::string mirror_joint_name = joint->getName();
+							S32 idx = joint->getName().find("Left");
+							if (idx != -1)
+								mirror_joint_name.replace(idx, mirror_joint_name.length(), "Right");
+
+							idx = joint->getName().find("Right");
+							if (idx != -1)
+								mirror_joint_name.replace(idx, mirror_joint_name.length(), "Left");
+
+							if (mirror_joint_name != joint->getName())
+							{
+								mirror_joint = gDragonAnimator.mTargetAvatar->mRoot->findJoint(mirror_joint_name);
+							}
+
+							if (mirror_joint)
+							{
+								//BD - We also need to find the opposite joint's list entry and change its values to reflect
+								//     the new ones, doing this here is still better than causing a complete refresh.
+								LLScrollListItem* item2 = mJointScrolls[JOINTS]->getItemByLabel(mirror_joint_name, FALSE, COL_NAME);
+								if (item2)
+								{
+									col_rot_x = item2->getColumn(COL_ROT_X);
+									col_rot_y = item2->getColumn(COL_ROT_Y);
+									col_rot_z = item2->getColumn(COL_ROT_Z);
+
+									col_rot_x->setValue(0.000f);
+									col_rot_y->setValue(0.000f);
+									col_rot_z->setValue(0.000f);
+
+									mirror_joint->setTargetRotation(quat);
+								}
+							}
+						}
+					}
+
+					//BD - Resetting positions next.
+					//BD - We could just check whether position information is available since only joints
+					//     which can have their position changed will have position information but we
+					//     want this to be a minefield for crashes.
+					//     Bones that can support position
+					//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+					//     as well as all attachment bones and collision volumes.
+					if (joint->mHasPosition || it > JOINTS)
+					{
+						LLScrollListCell* col_pos_x = item->getColumn(COL_POS_X);
+						LLScrollListCell* col_pos_y = item->getColumn(COL_POS_Y);
+						LLScrollListCell* col_pos_z = item->getColumn(COL_POS_Z);
+						LLVector3 pos = mDefaultPositions[joint->getName()];
+
+						col_pos_x->setValue(ll_round(pos.mV[VX], 0.001f));
+						col_pos_y->setValue(ll_round(pos.mV[VY], 0.001f));
+						col_pos_z->setValue(ll_round(pos.mV[VZ], 0.001f));
+						joint->setTargetPosition(pos);
+					}
+
+					//BD - Resetting scales last.
+					LLScrollListCell* col_scale_x = item->getColumn(COL_SCALE_X);
+					LLScrollListCell* col_scale_y = item->getColumn(COL_SCALE_Y);
+					LLScrollListCell* col_scale_z = item->getColumn(COL_SCALE_Z);
+					LLVector3 scale = mDefaultScales[joint->getName()];
+
+					col_scale_x->setValue(ll_round(scale.mV[VX], 0.001f));
+					col_scale_y->setValue(ll_round(scale.mV[VY], 0.001f));
+					col_scale_z->setValue(ll_round(scale.mV[VZ], 0.001f));
+					joint->setScale(scale);
+				}
+			}
+		}
+	}
+
+	onJointControlsRefresh();
+}
+
+//BD - Used to reset rotations only.
+void BDFloaterPoser::onJointRotationReset()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	//BD - We do support resetting bone rotations for everyone however.
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	//BD - While editing rotations, make sure we use a bit of spherical linear interpolation 
+	//     to make movements smoother.
+	BDPosingMotion* motion = (BDPosingMotion*)avatar->findMotion(ANIM_BD_POSING_MOTION);
+	if (motion)
+	{
+		//BD - If we don't use our default spherical interpolation, set it once.
+		motion->setInterpolationTime(0.25f);
+		motion->setInterpolationType(2);
+	}
+
+	for (auto item : mJointScrolls[JOINTS]->getAllSelected())
+	{
+		if (item)
+		{
+			LLJoint* joint = (LLJoint*)item->getUserdata();
+			if (joint)
+			{
+				LLQuaternion quat;
+				LLScrollListCell* col_x = item->getColumn(COL_ROT_X);
+				LLScrollListCell* col_y = item->getColumn(COL_ROT_Y);
+				LLScrollListCell* col_z = item->getColumn(COL_ROT_Z);
+
+				col_x->setValue(0.000f);
+				col_y->setValue(0.000f);
+				col_z->setValue(0.000f);
+
+				quat.setEulerAngles(0, 0, 0);
+				joint->setTargetRotation(quat);
+
+				//BD - If we are in Mirror mode, try to find the opposite bone of our currently
+				//     selected one, for now this simply means we take the name and replace "Left"
+				//     with "Right" and vise versa since all bones are conveniently that way.
+				//     TODO: Do this when creating the joint list so we don't try to find the joint
+				//     over and over again.
+				if (mMirrorMode)
+				{
+					LLJoint* mirror_joint = nullptr;
+					std::string mirror_joint_name = joint->getName();
+					S32 idx = joint->getName().find("Left");
+					if (idx != -1)
+						mirror_joint_name.replace(idx, mirror_joint_name.length(), "Right");
+
+					idx = joint->getName().find("Right");
+					if (idx != -1)
+						mirror_joint_name.replace(idx, mirror_joint_name.length(), "Left");
+
+					if (mirror_joint_name != joint->getName())
+					{
+						mirror_joint = gDragonAnimator.mTargetAvatar->mRoot->findJoint(mirror_joint_name);
+					}
+
+					if (mirror_joint)
+					{
+						//BD - We also need to find the opposite joint's list entry and change its values to reflect
+						//     the new ones, doing this here is still better than causing a complete refresh.
+						LLScrollListItem* item2 = mJointScrolls[JOINTS]->getItemByLabel(mirror_joint_name, FALSE, COL_NAME);
+						if (item2)
+						{
+							col_x = item2->getColumn(COL_ROT_X);
+							col_y = item2->getColumn(COL_ROT_Y);
+							col_z = item2->getColumn(COL_ROT_Z);
+
+							col_x->setValue(0.000f);
+							col_y->setValue(0.000f);
+							col_z->setValue(0.000f);
+
+							mirror_joint->setTargetRotation(quat);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	onJointControlsRefresh();
+}
+
+//BD - Used to reset positions, this is very tricky hence why it was separated.
+//     It causes the avatar to flinch for a second which doesn't look as nice as resetting
+//     rotations does.
+void BDFloaterPoser::onJointPositionReset()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	//BD - We don't support resetting bones positions for anyone else yet.
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead() || !avatar->isSelf()) return;
+
+	S32 index = mJointTabs->getCurrentPanelIndex();
+
+	//BD - When resetting positions, we don't use interpolation for now, it looks stupid.
+	BDPosingMotion* motion = (BDPosingMotion*)avatar->findMotion(ANIM_BD_POSING_MOTION);
+	if (motion)
+	{
+		motion->setInterpolationTime(0.25f);
+		motion->setInterpolationType(2);
+	}
+
+	//BD - We use this bool to prevent going through attachment override reset every single time.
+	//bool has_reset = false;
+	for (auto item : mJointScrolls[index]->getAllSelected())
+	{
+		if (item)
+		{
+			LLJoint* joint = (LLJoint*)item->getUserdata();
+			if (joint)
+			{
+				//BD - We could just check whether position information is available since only joints
+				//     which can have their position changed will have position information but we
+				//     want this to be a minefield for crashes.
+				//     Bones that can support position
+				//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+				//     as well as all attachment bones and collision volumes.
+				if (joint->mHasPosition || index > JOINTS)
+				{
+					LLScrollListCell* col_pos_x = item->getColumn(COL_POS_X);
+					LLScrollListCell* col_pos_y = item->getColumn(COL_POS_Y);
+					LLScrollListCell* col_pos_z = item->getColumn(COL_POS_Z);
+					LLVector3 pos = mDefaultPositions[joint->getName()];
+
+					col_pos_x->setValue(ll_round(pos.mV[VX], 0.001f));
+					col_pos_y->setValue(ll_round(pos.mV[VY], 0.001f));
+					col_pos_z->setValue(ll_round(pos.mV[VZ], 0.001f));
+					joint->setTargetPosition(pos);
+				}
+			}
+		}
+	}
+
+	onJointControlsRefresh();
+}
+
+//BD - Used to reset scales only.
+void BDFloaterPoser::onJointScaleReset()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	//BD - We don't support resetting bones scales for anyone else yet.
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead() || !avatar->isSelf()) return;
+
+	S32 index = mJointTabs->getCurrentPanelIndex();
+
+	//BD - Clear all attachment bone scale changes we've done, they are not automatically
+	//     reverted.
+	for (auto item : mJointScrolls[index]->getAllSelected())
+	{
+		if (item)
+		{
+			LLJoint* joint = (LLJoint*)item->getUserdata();
+			if (joint)
+			{
+				LLScrollListCell* col_scale_x = item->getColumn(COL_SCALE_X);
+				LLScrollListCell* col_scale_y = item->getColumn(COL_SCALE_Y);
+				LLScrollListCell* col_scale_z = item->getColumn(COL_SCALE_Z);
+				LLVector3 scale = mDefaultScales[joint->getName()];
+
+				col_scale_x->setValue(ll_round(scale.mV[VX], 0.001f));
+				col_scale_y->setValue(ll_round(scale.mV[VY], 0.001f));
+				col_scale_z->setValue(ll_round(scale.mV[VZ], 0.001f));
+				joint->setScale(scale);
+			}
+		}
+	}
+	onJointControlsRefresh();
+}
+
+//BD - Flip our pose (mirror it)
+void BDFloaterPoser::onFlipPose()
+{
+	LLVOAvatar* avatar = gDragonAnimator.mTargetAvatar;
+	if (!avatar || avatar->isDead()) return;
+
+	if (!(avatar->getRegion() == gAgent.getRegion())) return;
+
+	LLJoint* joint = nullptr;
+	bool flipped[134] = { false };
+
+	for (S32 i = 0; (joint = avatar->getCharacterJoint(i)); ++i)
+	{
+		//BD - Skip if we already flipped this bone.
+		if (flipped[i]) continue;
+
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint)	continue;
+
+		LLVector3 rot, mirror_rot;
+		LLQuaternion rot_quat, mirror_rot_quat;
+		std::string joint_name = joint->getName();
+		std::string mirror_joint_name = joint->getName();
+		//BD - Attempt to find the "right" version of this bone first, we assume we always
+		//     end up with the "left" version of a bone first.
+		S32 idx = joint->getName().find("Left");
+		if (idx != -1)
+			mirror_joint_name.replace(idx, mirror_joint_name.length(), "Right");
+		//BD - Attempt to find the "right" version of this bone first, this is necessary
+		//     because there are a couple bones starting with the "right" bone.
+		idx = joint->getName().find("Right");
+		if (idx != -1)
+			mirror_joint_name.replace(idx, mirror_joint_name.length(), "Left");
+
+		LLJoint* mirror_joint = nullptr;
+		if (mirror_joint_name != joint->getName())
+			mirror_joint = gDragonAnimator.mTargetAvatar->mRoot->findJoint(mirror_joint_name);
+
+		//BD - Collect the joint and mirror joint entries and their cells, we need them later.
+		LLScrollListItem* item1 = mJointScrolls[JOINTS]->getItemByLabel(joint_name, FALSE, COL_NAME);
+		LLScrollListItem* item2 = nullptr;
+
+		//BD - Get the rotation of our current bone and that of the mirror bone (if available).
+		//     Flip our current bone's rotation and apply it to the mirror bone (if available).
+		//     Flip the mirror bone's rotation (if available) and apply it to our current bone.
+		//     If the mirror bone does not exist, flip the current bone rotation and use that.
+		rot_quat = joint->getTargetRotation();
+		LLQuaternion inv_rot_quat = LLQuaternion(-rot_quat.mQ[VX], rot_quat.mQ[VY], -rot_quat.mQ[VZ], rot_quat.mQ[VW]);
+		inv_rot_quat.getEulerAngles(&rot[VX], &rot[VY], &rot[VZ]);
+
+		if (mirror_joint)
+		{
+			mirror_rot_quat = mirror_joint->getTargetRotation();
+			LLQuaternion inv_mirror_rot_quat = LLQuaternion(-mirror_rot_quat.mQ[VX], mirror_rot_quat.mQ[VY], -mirror_rot_quat.mQ[VZ], mirror_rot_quat.mQ[VW]);
+			inv_mirror_rot_quat.getEulerAngles(&mirror_rot[VX], &mirror_rot[VY], &mirror_rot[VZ]);
+			mirror_joint->setTargetRotation(inv_rot_quat);
+			joint->setTargetRotation(inv_mirror_rot_quat);
+
+			item2 = mJointScrolls[JOINTS]->getItemByLabel(mirror_joint_name, FALSE, COL_NAME);
+
+			//BD - Make sure we flag this bone as flipped so we skip it next time we iterate over it.
+			flipped[mirror_joint->getJointNum()] = true;
+		}
+		else
+		{
+			joint->setTargetRotation(inv_rot_quat);
+		}
+
+		S32 axis = 0;
+		while (axis <= 2)
+		{
+			//BD - Now flip the list entry values.
+			if (item1)
+			{
+				if (mirror_joint)
+					item1->getColumn(axis + 2)->setValue(ll_round(mirror_rot[axis], 0.001f));
+				else
+					item1->getColumn(axis + 2)->setValue(ll_round(rot[axis], 0.001f));
+			}
+
+			//BD - Now flip the mirror joint list entry values.
+			if (item2)
+				item2->getColumn(axis + 2)->setValue(ll_round(rot[axis], 0.001f));
+
+			++axis;
+		}
+		flipped[i] = true;
+	}
+}
+
+//BD - This is used to collect all default values at the beginning to revert to later on.
+void BDFloaterPoser::onCollectDefaults()
+{
+	LLVector3 rot;
+	LLVector3 pos;
+	LLVector3 scale;
+	LLJoint* joint;
+
+	//BD - Getting collision volumes and attachment points.
+	std::vector<std::string> joint_names, cv_names, attach_names;
+	gAgentAvatarp->getSortedJointNames(0, joint_names);
+	gAgentAvatarp->getSortedJointNames(1, cv_names);
+	gAgentAvatarp->getSortedJointNames(2, attach_names);
+
+	mDefaultScales.clear();
+	mDefaultPositions.clear();
+
+	for (auto name : joint_names)
+	{
+		joint = gAgentAvatarp->getJoint(name);
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint)	continue;
+
+		LLSD row;
+
+		//BD - We always get the values but we don't write them out as they are not relevant for the
+		//     user yet but we need them to establish default values we revert to later on.
+		scale = joint->getScale();
+		mDefaultScales.insert(std::pair<std::string, LLVector3>(name, scale));
+
+		//BD - We could just check whether position information is available since only joints
+		//     which can have their position changed will have position information but we
+		//     want this to be a minefield for crashes.
+		//     Bones that can support position
+		//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+		if (joint->mHasPosition)
+		{
+			//BD - We always get the values but we don't write them out as they are not relevant for the
+			//     user yet but we need them to establish default values we revert to later on.
+			pos = joint->getPosition();
+			mDefaultPositions.insert(std::pair<std::string, LLVector3>(name, pos));
+		}
+	}
+
+	//BD - Collision Volumes
+	for (auto name : cv_names)
+	{
+		LLJoint* joint = gAgentAvatarp->getJoint(name);
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint)	continue;
+
+		//BD - We always get the values but we don't write them out as they are not relevant for the
+		//     user yet but we need them to establish default values we revert to later on.
+		pos = joint->getPosition();
+		scale = joint->getScale();
+		mDefaultPositions.insert(std::pair<std::string, LLVector3>(name, pos));
+		mDefaultScales.insert(std::pair<std::string, LLVector3>(name, scale));
+	}
+
+	//BD - Attachment Bones
+	for (auto name : attach_names)
+	{
+		LLJoint* joint = gAgentAvatarp->getJoint(name);
+		//BD - Nothing? Invalid? Skip, when we hit the end we'll break out anyway.
+		if (!joint)	continue;
+
+		//BD - We always get the values but we don't write them out as they are not relevant for the
+		//     user yet but we need them to establish default values we revert to later on.
+		pos = joint->getPosition();
+		scale = joint->getScale();
+
+		mDefaultPositions.insert(std::pair<std::string, LLVector3>(name, pos));
+		mDefaultScales.insert(std::pair<std::string, LLVector3>(name, scale));
+	}
+}
+
+////////////////////////////////
+//BD - Animations
+////////////////////////////////
+void BDFloaterPoser::onAnimAdd(const LLSD& param)
+{
+	//BD - Don't allow changing the list while it's currently playing, this might
+	//     cause a crash when the animator is past the null check and we delete an
+	//     entry between null checking and trying to read its values. 
+	if (gDragonAnimator.getIsPlaying()) return;
+
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	LLScrollListItem* pose = mPoseScroll->getFirstSelected();
+	std::string name = param.asString();
+	S32 location = mAnimEditorScroll->getFirstSelectedIndex() + 1;
+	F32 time = 0.f;
+	BD_EActionType type;
+	if (param.asString() == "Repeat")
+	{
+		type = BD_EActionType::REPEAT;
+	}
+	else if (param.asString() == "Wait")
+	{
+		type = BD_EActionType::WAIT;
+		time = 1.f;
+	}
+	else
+	{
+		name = pose->getColumn(0)->getValue().asString();
+		type = BD_EActionType::POSE;
+	}
+	//BD - We'll be adding the avatar into a list in here to keep track of all
+	//     avatars we've added actions for.
+	gDragonAnimator.onAddAction(avatar, name, type, time, location);
+	onAnimListWrite();
+
+	//BD - Select added entry and make it appear as nothing happened.
+	//     In case of nothing being selected yet, select the first entry.
+	mAnimEditorScroll->selectNthItem(location);
+
+	//BD - Update our controls when we add items, the move and delete buttons
+	//     should enable now that we selected something.
+	onAnimControlsRefresh();
+}
+
+void BDFloaterPoser::onAnimListWrite()
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	mAnimEditorScroll->clearRows();
+	//BD - Now go through the new list we created, read them out and add them
+	//     to our list in the new desired order.
+	for (auto action : avatar->mAnimatorActions)
+	{
+		LLSD row;
+		row["columns"][0]["column"] = "name";
+		row["columns"][0]["value"] = action.mPoseName;
+		if (action.mType == BD_EActionType::WAIT)
+		{
+			row["columns"][1]["column"] = "time";
+			row["columns"][1]["value"] = action.mTime;
+			row["columns"][2]["column"] = "type";
+			row["columns"][2]["value"] = action.mType;
+		}
+		mAnimEditorScroll->addElement(row);
+	}
+
+	//BD - Make sure we don't have a scrollbar unless we need it.
+	mAnimEditorScroll->updateLayout();
+}
+
+void BDFloaterPoser::onAnimMove(const LLSD& param)
+{
+	//BD - Don't allow changing the list while it's currently playing, this might
+	//     cause a crash when the animator is past the null check and we delete an
+	//     entry between null checking and trying to read its values. 
+	if (gDragonAnimator.getIsPlaying())	return;
+
+	//BD - Don't allow moving if we don't have anything selected either. (Crashfix)
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	S32 item_count = mAnimEditorScroll->getItemCount();
+	S32 new_index = mAnimEditorScroll->getFirstSelectedIndex();
+	S32 old_index = new_index;
+
+	//BD - Don't allow moving down when we are already at the bottom, this would
+	//     create another entry.
+	//     Don't allow going up when we are on the first entry already either, this
+	//     would select everything in the list.
+	//     Don't allow moving if there's nothing to move. (Crashfix)
+	if (((new_index + 1) >= item_count && param.asString() == "Down")
+		|| (new_index == 0 && param.asString() == "Up")
+		|| item_count == 0)
+	{
+		return;
+	}
+
+	//BD - Move up, otherwise move the entry down. No other option.
+	if (param.asString() == "Up")
+	{
+		--new_index;
+	}
+	else
+	{
+		++new_index;
+	}
+
+	Action action = avatar->mAnimatorActions[old_index];
+	gDragonAnimator.onDeleteAction(avatar, old_index);
+	gDragonAnimator.onAddAction(avatar, action, new_index);
+	onAnimListWrite();
+
+	//BD - Select added entry and make it appear as nothing happened.
+	//     In case of nothing being selected yet, select the first entry.
+	mAnimEditorScroll->selectNthItem(new_index);
+
+	//BD - Update our controls when we move items, the move and delete buttons
+	//     should enable now that we might have selected something.
+	onAnimControlsRefresh();
+}
+
+void BDFloaterPoser::onAnimDelete()
+{
+	//BD - Don't allow changing the list while it's currently playing, this might
+	//     cause a crash when the animator is past the null check and we delete an
+	//     entry between null checking and trying to read its values. 
+	if (gDragonAnimator.getIsPlaying())	return;
+
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	std::vector<LLScrollListItem*> items = mAnimEditorScroll->getAllSelected();
+	while (!items.empty())
+	{
+		//BD - We'll delete the avatar from our list if necessary when no more actions
+		//     are saved in a given avatar.
+		gDragonAnimator.onDeleteAction(avatar, mAnimEditorScroll->getFirstSelectedIndex());
+		items.erase(items.begin());
+	}
+	onAnimListWrite();
+
+	//BD - Make sure we don't have a scrollbar unless we need it.
+	mAnimEditorScroll->updateLayout();
+
+	//BD - Update our controls when we delete items. Most of them should
+	//     disable now that nothing is selected anymore.
+	onAnimControlsRefresh();
+}
+
+void BDFloaterPoser::loadPoseRotations(std::string name, LLVector3 *rotations)
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	std::string filename;
+	if (!name.empty())
+	{
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", LLDir::escapePathString(name) + ".xml");
+	}
+
+	LLSD pose;
+	llifstream infile;
+	infile.open(filename);
+	if (!infile.is_open())
+	{
+		LL_WARNS("Posing") << "Cannot find file in: " << filename << LL_ENDL;
+		return;
+	}
+
+	while (!infile.eof())
+	{
+		S32 count = LLSDSerialize::fromXML(pose, infile);
+		if (count == LLSDParser::PARSE_FAILURE)
+		{
+			LL_WARNS("Posing") << "Failed to parse file: " << filename << LL_ENDL;
+			return;
+		}
+
+		LLJoint* joint = avatar->getJoint(pose["bone"].asString());
+		if (joint)
+		{
+			S32 joint_num = joint->getJointNum();
+			if (pose["rotation"].isDefined())
+			{
+				rotations[joint_num].setValue(pose["rotation"]);
+			}
+		}
+	}
+	infile.close();
+	return;
+}
+
+void BDFloaterPoser::loadPosePositions(std::string name, LLVector3 *positions)
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	std::string filename;
+	if (!name.empty())
+	{
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", LLDir::escapePathString(name) + ".xml");
+	}
+
+	LLSD pose;
+	llifstream infile;
+	infile.open(filename);
+	if (!infile.is_open())
+	{
+		LL_WARNS("Posing") << "Cannot find file in: " << filename << LL_ENDL;
+		return;
+	}
+
+	while (!infile.eof())
+	{
+		S32 count = LLSDSerialize::fromXML(pose, infile);
+		if (count == LLSDParser::PARSE_FAILURE)
+		{
+			LL_WARNS("Posing") << "Failed to parse file: " << filename << LL_ENDL;
+			return;
+		}
+
+		LLJoint* joint = avatar->getJoint(pose["bone"].asString());
+		if (joint)
+		{
+			S32 joint_num = joint->getJointNum();
+			//BD - Position information is only ever written when it is actually safe to do.
+			//     It's safe to assume that IF information is available it's safe to apply.
+			if (pose["position"].isDefined())
+			{
+				positions[joint_num].setValue(pose["position"]);
+			}
+		}
+	}
+	infile.close();
+	return;
+}
+
+void BDFloaterPoser::loadPoseScales(std::string name, LLVector3 *scales)
+{
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (!item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	std::string filename;
+	if (!name.empty())
+	{
+		filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "poses", LLDir::escapePathString(name) + ".xml");
+	}
+
+	LLSD pose;
+	llifstream infile;
+	infile.open(filename);
+	if (!infile.is_open())
+	{
+		LL_WARNS("Posing") << "Cannot find file in: " << filename << LL_ENDL;
+		return;
+	}
+
+	while (!infile.eof())
+	{
+		S32 count = LLSDSerialize::fromXML(pose, infile);
+		if (count == LLSDParser::PARSE_FAILURE)
+		{
+			LL_WARNS("Posing") << "Failed to parse file: " << filename << LL_ENDL;
+			return;
+		}
+
+		LLJoint* joint = avatar->getJoint(pose["bone"].asString());
+		if (joint)
+		{
+			S32 joint_num = joint->getJointNum();
+			//BD - Bone Scales
+			if (pose["scale"].isDefined())
+			{
+				scales[joint_num].setValue(pose["scale"]);
+			}
+		}
+	}
+	infile.close();
+	return;
+}
+
+void BDFloaterPoser::onAnimSave()
+{
+	LLKeyframeMotion* temp_motion = NULL;
+	LLAssetID mMotionID;
+	LLTransactionID	mTransactionID;
+
+	//BD - To make this work we'll first need a unique UUID for this animation.
+	mTransactionID.generate();
+	mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
+	temp_motion->create(mMotionID);
+
+	std::string motion_name = getChild<LLUICtrl>("set_name")->getValue().asString();
+	//U16 motion_major_version = KEYFRAME_MOTION_VERSION;
+	//U16 motion_sub_version = KEYFRAME_MOTION_SUBVERSION;
+	//S32 base_priority = getChild<LLUICtrl>("set_priority")->getValue().asInteger();
+	//LLJoint::JointPriority base_priority = LLJoint::HIGHEST_PRIORITY;
+	F32 duration = getChild<LLUICtrl>("set_duration")->getValue().asReal();
+	//std::string face_emote_name = getChild<LLUICtrl>("set_face_emote")->getValue();
+	//F32 loop_in_time = getChild<LLUICtrl>("set_loop_in")->getValue().asReal();
+	//F32 loop_out_time = getChild<LLUICtrl>("set_loop_out")->getValue().asReal();
+	//S32 loop = getChild<LLUICtrl>("set_loop")->getValue().asBoolean();
+	//F32 ease_in_time = getChild<LLUICtrl>("set_ease_in")->getValue().asReal();
+	//F32 ease_out_time = getChild<LLUICtrl>("set_ease_out")->getValue().asReal();
+	//U32 hand_pose = getChild<LLUICtrl>("set_hand_pose")->getValue().asInteger();
+	//U32 joint_motion_count = getChild<LLUICtrl>("set_active_motions")->getValue().asInteger();
+	//LLUUID emote_name = getChild<LLUICtrl>("set_emote")->getValue();
+
+	//LLKeyframeMotion* motion = (LLKeyframeMotion*)gAgentAvatarp->findMotion(ANIM_BD_POSING_MOTION);
+	temp_motion = (LLKeyframeMotion*)gAgentAvatarp->createMotion(mMotionID);
+	typedef std::map<LLUUID, class LLKeyframeMotion::JointMotionList*> keyframe_data_map_t;
+
+	LLKeyframeMotion::JointMotionList* jointmotion_list;
+	jointmotion_list = LLKeyframeDataCache::getKeyframeData(ANIM_BD_POSING_MOTION);
+	F32 time = 0.f;
+	for (auto item : mAnimEditorScroll->getAllData())
+	{
+		std::string pose_name = item->getColumn(0)->getValue();
+		LLVector3 rotations[134];
+		LLVector3 positions[134];
+		LLVector3 scales[134];
+		loadPoseRotations(pose_name, rotations);
+		loadPosePositions(pose_name, positions);
+		loadPoseScales(pose_name, scales);
+
+		if (!item->getColumn(1)->getValue().asString().empty())
+		{
+			time += item->getColumn(1)->getValue().asReal();
+		}
+
+		LLKeyframeMotion::JointMotion* joint_motion = new LLKeyframeMotion::JointMotion;
+		jointmotion_list->mJointMotionArray.push_back(joint_motion);
+
+		for (S32 joint_num = 0; joint_num < 134; joint_num++)
+		{
+			LLJoint *joint = gAgentAvatarp->getCharacterJoint(joint_num);
+			if (joint)
+			{
+				joint_motion->mJointName = joint->getName();
+				LLPointer<LLJointState> joint_state = temp_motion->findJointState(joint);
+				if (!joint_state)
+				{
+					joint_state = new LLJointState;
+					temp_motion->addJointState(joint_state);
+					joint_state->setJoint(joint); // note: can accept NULL
+					joint_state->setUsage(0);
+				}
+
+				//---------------------------------------------------------------------
+				// get joint priority
+				//---------------------------------------------------------------------
+				S32 joint_priority = LLJoint::HIGHEST_PRIORITY;
+				joint_motion->mPriority = (LLJoint::JointPriority)joint_priority;
+				joint_state->setPriority((LLJoint::JointPriority)joint_priority);
+
+				//BD - Get the number of poses (keys) of our entire animation.
+				joint_motion->mRotationCurve.mNumKeys = 1;
+				joint_motion->mRotationCurve.mInterpolationType = LLKeyframeMotion::IT_LINEAR;
+				if (joint_motion->mRotationCurve.mNumKeys != 0)
+				{
+					joint_state->setUsage(joint_state->getUsage() | LLJointState::ROT);
+				}
+
+				//---------------------------------------------------------------------
+				// scan rotation curve keys
+				//---------------------------------------------------------------------
+				LLKeyframeMotion::RotationCurve *rCurve = &joint_motion->mRotationCurve;
+
+				for (S32 k = 0; k < joint_motion->mRotationCurve.mNumKeys; k++)
+				{
+					//BD - Get the duration of our animation until this pose.
+					U16 time_short = duration;
+					time = U16_to_F32(time_short, 0.f, jointmotion_list->mDuration);
+
+					LLKeyframeMotion::RotationKey rot_key;
+					rot_key.mTime = time;
+					LLVector3 rot_vec = rotations[joint_num];
+					//BD - Rotations need to be in range from 1 to -1 to be unpacked.
+					//     FIX or translate them directly from euler to quaternions.
+					rot_key.mValue.unpackFromVector3(rot_vec);
+
+					if (!(rot_key.mValue.isFinite()))
+					{
+						LL_WARNS() << "non-finite angle in rotation key for animation " << LL_ENDL;
+					}
+
+					rCurve->mKeys.emplace_back(time, rot_key);
+				}
+
+				std::sort(rCurve->mKeys.begin(), rCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
+
+				//---------------------------------------------------------------------
+				// scan position curve header
+				//---------------------------------------------------------------------
+				//BD - Get the number of poses (keys) of our entire animation.
+				joint_motion->mPositionCurve.mNumKeys = 1;
+				joint_motion->mPositionCurve.mInterpolationType = LLKeyframeMotion::IT_LINEAR;
+				if (joint_motion->mPositionCurve.mNumKeys != 0)
+				{
+					joint_state->setUsage(joint_state->getUsage() | LLJointState::POS);
+				}
+
+				//---------------------------------------------------------------------
+				// scan position curve keys
+				//---------------------------------------------------------------------
+				LLKeyframeMotion::PositionCurve *pCurve = &joint_motion->mPositionCurve;
+				BOOL is_pelvis = joint_motion->mJointName == "mPelvis";
+				for (S32 k = 0; k < joint_motion->mPositionCurve.mNumKeys; k++)
+				{
+					U16 time_short = duration;
+					LLKeyframeMotion::PositionKey pos_key;
+					pos_key.mTime = U16_to_F32(time_short, 0.f, jointmotion_list->mDuration);
+
+					pos_key.mValue.mV[VX] = U16_to_F32(positions[joint_num].mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
+					pos_key.mValue.mV[VY] = U16_to_F32(positions[joint_num].mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
+					pos_key.mValue.mV[VZ] = U16_to_F32(positions[joint_num].mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
+
+					if (!(pos_key.mValue.isFinite()))
+					{
+						LL_WARNS() << "non-finite position in key for animation "<< LL_ENDL;
+					}
+
+					pCurve->mKeys.emplace_back(pos_key.mTime, pos_key);
+
+					if (is_pelvis)
+					{
+						jointmotion_list->mPelvisBBox.addPoint(pos_key.mValue);
+					}
+				}
+
+				std::sort(pCurve->mKeys.begin(), pCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
+
+				joint_motion->mUsage = joint_state->getUsage();
+			}
+		}
+	}
+
+	//BD - Work in Progress exporter.
+	/*for (S32 idx = 0; idx > jointmotion_list->getNumJointMotions(); idx++)
+	{
+		LLKeyframeMotion::JointMotion* joint_motion = jointmotion_list->getJointMotion(idx);
+		LLKeyframeMotion::RotationCurve rCurve = joint_motion->mRotationCurve;
+
+		rCurve.mKeys[time];
+	}*/
+	//LLKeyframeMotion::JointMotion* joint_motion = jointmotion_list->getJointMotion(0);
+	//LLKeyframeMotion::RotationCurve rot_courve = joint_motion->mRotationCurve;
+	//LLKeyframeMotion::RotationKey rot_key = rot_courve.mLoopInKey;
+	//LLQuaternion rotation = rot_key.mRotation;
+	//F32 time = rot_key.mTime;
+	//LLDataPackerBinaryBuffer* dp;
+	//BOOL success = TRUE;
+
+	//BD - Lets collect everything we will need.
+	/*std::string motion_name = getChild<LLUICtrl>("set_name")->getValue().asString();
+	//U16 motion_major_version = KEYFRAME_MOTION_VERSION;
+	//U16 motion_sub_version = KEYFRAME_MOTION_SUBVERSION;
+	//S32 base_priority = getChild<LLUICtrl>("set_priority")->getValue().asInteger();
+	LLJoint::JointPriority base_priority = LLJoint::HIGHEST_PRIORITY;
+	F32 duration = getChild<LLUICtrl>("set_duration")->getValue().asReal();
+	std::string face_emote_name = getChild<LLUICtrl>("set_face_emote")->getValue();
+	F32 loop_in_time = getChild<LLUICtrl>("set_loop_in")->getValue().asReal();
+	F32 loop_out_time = getChild<LLUICtrl>("set_loop_out")->getValue().asReal();
+	S32 loop = getChild<LLUICtrl>("set_loop")->getValue().asBoolean();
+	F32 ease_in_time = getChild<LLUICtrl>("set_ease_in")->getValue().asReal();
+	F32 ease_out_time = getChild<LLUICtrl>("set_ease_out")->getValue().asReal();
+	//U32 hand_pose = getChild<LLUICtrl>("set_hand_pose")->getValue().asInteger();
+	//U32 joint_motion_count = getChild<LLUICtrl>("set_active_motions")->getValue().asInteger();
+	LLUUID emote_name = getChild<LLUICtrl>("set_emote")->getValue();
+
+	LLKeyframeMotion::JointMotionList* jointmotion_list = new LLKeyframeMotion::JointMotionList;
+
+	//BD - Reserve for all 134 joints.
+	jointmotion_list->mJointMotionArray.reserve(134);
+
+	LLJoint* joint;
+	for (S32 i = 0; (joint = gAgentAvatarp->getCharacterJoint(i)); ++i)
+	{
+		if (!joint)
+			continue;
+
+		//BD - Let's build joint motions
+		LLKeyframeMotion::JointMotion* joint_motion = jointmotion_list->mJointMotionArray[i];
+
+		//BD - We start with the joint name;
+		joint_motion->mJointName = joint->getName();
+
+		//BD - Add the priority
+		joint_motion->mPriority = LLJoint::HIGHEST_PRIORITY;
+
+		//BD - Define the bone usage
+		S32 usage = 0;
+		if (joint->mHasPosition)
+		{
+			usage = usage & LLJointState::POS;
+		}
+		usage = usage & LLJointState::ROT;
+		usage = usage & LLJointState::POS;
+		joint_motion->mUsage = usage;
+
+		//BD - And finally the fun part.
+		//LLKeyframeMotion::RotationCurve* rot_courve;
+		//LLKeyframeMotion::PositionCurve* pos_courve;
+		//LLKeyframeMotion::ScaleCurve* scale_courve;
+
+		//LLKeyframeMotion::RotationKey* rot_key;
+		//rot_key->mRotation = joint->getRotation();
+		//rot_key->mTime = 0.0f;		
+		//rot_courve->mKeys[0.0f].mRotation = joint->getRotation();
+		//rot_courve->mKeys[0.0f].mTime = 0.0f;
+		joint_motion->mRotationCurve.mKeys[0.0f].mRotation = joint->getRotation();
+		joint_motion->mRotationCurve.mKeys[0.0f].mTime = 0.0f;
+
+		joint_motion->mPositionCurve.mKeys[0.0f].mPosition = joint->getPosition();
+		joint_motion->mPositionCurve.mKeys[0.0f].mTime = 0.0f;
+
+		joint_motion->mScaleCurve.mKeys[0.0f].mScale = joint->getScale();
+		joint_motion->mScaleCurve.mKeys[0.0f].mTime = 0.0f;
+
+		//BD - Add the joint motion to our array.
+		jointmotion_list->mJointMotionArray[i] = joint_motion;
+	}
+	LLKeyframeDataCache::addKeyframeData(mMotionID, jointmotion_list);
+
+	temp_motion->setPriority(base_priority);
+	temp_motion->setEaseIn(ease_in_time);
+	temp_motion->setEaseOut(ease_out_time);
+	temp_motion->setEmote(emote_name);
+	//jointmotion_list->mHandPose = hand_pose;
+	temp_motion->setLoop(loop);
+	temp_motion->setLoopIn(loop_in_time);
+	temp_motion->setLoopOut(loop_out_time);
+
+	if (!jointmotion_list)
+		return;
+
+	jointmotion_list->mBasePriority = base_priority;
+	jointmotion_list->mDuration = duration;
+	jointmotion_list->mEaseInDuration = ease_in_time;
+	jointmotion_list->mEaseOutDuration = ease_out_time;
+	jointmotion_list->mEmoteName = face_emote_name;
+	//jointmotion_list->mHandPose = hand_pose;
+	jointmotion_list->mLoop = loop;
+	jointmotion_list->mLoopInPoint = loop_in_time;
+	jointmotion_list->mLoopOutPoint = loop_out_time;
+	jointmotion_list->mMaxPriority = base_priority;
+	*/
+	temp_motion->dumpToFile(motion_name);
+}
+
+void BDFloaterPoser::onAnimSet()
+{
+	LLScrollListItem* av_item = mAvatarScroll->getFirstSelected();
+	if (!av_item) return;
+
+	LLVOAvatar* avatar = (LLVOAvatar*)av_item->getUserdata();
+	if (!avatar || avatar->isDead()) return;
+
+	F32 value = getChild<LLUICtrl>("anim_time")->getValue().asReal();
+	S32 selected_index = mAnimEditorScroll->getFirstSelectedIndex();
+	Action action = avatar->mAnimatorActions[selected_index];
+	LLScrollListItem* item = mAnimEditorScroll->getFirstSelected();
+	if (item)
+	{
+		if (action.mType == BD_EActionType::WAIT)
+		{
+			avatar->mAnimatorActions[mAnimEditorScroll->getFirstSelectedIndex()].mTime = value;
+			LLScrollListCell* column = item->getColumn(1);
+			column->setValue(value);
+		}
+	}
+}
+
+void BDFloaterPoser::onAnimPlay()
+{
+	//BD - We start the animator frametimer here and set the expiry time to 0.0
+	//     to force the animator to start immediately when hitting the "Start" button.
+	gDragonAnimator.startPlayback();
+
+	//BD - Update our controls when we start the animator. Most of them should
+	//     disable now.
+	onAnimControlsRefresh();
+	onPoseControlsRefresh();
+}
+
+void BDFloaterPoser::onAnimStop()
+{
+	//BD - We only need to stop it here because the .start function resets the timer 
+	//     automatically.
+	gDragonAnimator.stopPlayback();
+
+	//BD - Update our controls when we stop the animator. Most of them should
+	//     enable again.
+	onAnimControlsRefresh();
+	onPoseControlsRefresh();
+}
+
+void BDFloaterPoser::onAnimControlsRefresh()
+{
+	S32 item_count = mAnimEditorScroll->getItemCount();
+	S32 index = mAnimEditorScroll->getFirstSelectedIndex();
+
+	bool is_playing = gDragonAnimator.getIsPlaying();
+	bool selected = index != -1;
+	bool is_wait = false;
+
+	//BD - Don't.
+	if (!is_playing)
+	{
+		LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+		if (item)
+		{
+			LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+			if (avatar || !avatar->isDead())
+			{
+				//BD - Crashfix.
+				if (selected)
+				{
+					is_wait = avatar->mAnimatorActions[index].mType == BD_EActionType::WAIT;
+				}
+			}
+		}
+	}
+
+	getChild<LLUICtrl>("anim_time")->setEnabled(!is_playing && selected && is_wait);
+	getChild<LLUICtrl>("delete_entry")->setEnabled(!is_playing && selected);
+	getChild<LLUICtrl>("move_up")->setEnabled(!is_playing && selected && index != 0);
+	getChild<LLUICtrl>("move_down")->setEnabled(!is_playing && selected && !((index + 1) >= item_count));
+	getChild<LLUICtrl>("add_repeat")->setEnabled(!is_playing);
+	getChild<LLUICtrl>("add_wait")->setEnabled(!is_playing);
+	getChild<LLUICtrl>("play_anim")->setEnabled(!is_playing && (item_count > 0));
+	getChild<LLUICtrl>("stop_anim")->setEnabled(is_playing);
+}
+
+
+////////////////////////////////
+//BD - Misc Functions
+////////////////////////////////
+
+void BDFloaterPoser::onUpdateLayout()
+{
+	if (!this->isMinimized())
+	{
+		bool animator_expanded = getChild<LLButton>("animator")->getValue();
+		bool poses_expanded = getChild<LLButton>("extend")->getValue() || animator_expanded;
+		getChild<LLUICtrl>("poses_layout")->setVisible(poses_expanded);
+		getChild<LLUICtrl>("animator_layout")->setVisible(animator_expanded);
+		getChild<LLUICtrl>("poser_layout")->setVisible(!animator_expanded);
+
+		S32 collapsed_width = getChild<LLPanel>("min_panel")->getRect().getWidth();
+		S32 expanded_width = getChild<LLPanel>("max_panel")->getRect().getWidth();
+		S32 floater_width = (poses_expanded && !animator_expanded) ? expanded_width : collapsed_width;
+		this->reshape(floater_width, this->getRect().getHeight());
+
+		if (animator_expanded)
+		{
+			//BD - Refresh our animation list
+			onAnimListWrite();
+		}
+	}
+}
+
+//BD - Animesh
+void BDFloaterPoser::onAvatarsSelect()
+{
+	//BD - Whenever we select an avatar in the list, check if the selected Avatar is still
+	//     valid and/or if new avatars have become valid for posing.
+	onAvatarsRefresh();
+
+	//BD - Now that we selected an avatar we can refresh the joint list to have all bones
+	//     mapped to that avatar so we can immediately start posing them or continue doing so.
+	//     This will automatically invoke a onJointControlsRefresh()
+	onJointRefresh();
+
+	//BD - Now that we support animating multiple avatars we also need to refresh all controls
+	//     and animation/pose lists for them when we switch to make it as easy as possible to
+	//     quickly switch back and forth and make edits.
+	onUpdateLayout();
+
+	onPoseControlsRefresh();
+	onAnimControlsRefresh();
+
+	//BD - Disable the Start Posing button if we haven't loaded yet.
+	LLScrollListItem* item = mAvatarScroll->getFirstSelected();
+	if (item)
+	{
+		LLVOAvatar* avatar = (LLVOAvatar*)item->getUserdata();
+		if (avatar && avatar->isSelf())
+			mStartPosingBtn->setEnabled(gAgentAvatarp->isFullyLoaded());
+	}
+
+	mStartPosingBtn->setFlashing(true, true);
+}
+
+void BDFloaterPoser::onAvatarsRefresh()
+{
+	//BD - Flag all items first, we're going to unflag them when they are valid.
+	for (LLScrollListItem* item : mAvatarScroll->getAllData())
+	{
+		if (item)
+		{
+			item->setFlagged(TRUE);
+		}
+	}
+
+	bool create_new = true;
+	for (LLCharacter* character : LLCharacter::sInstances)
+	{
+		create_new = true;
+		LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(character);
+		if (avatar && !avatar->isControlAvatar()
+			&& (avatar->isSelf() || gAgent.isGodlike()))
+		{
+			LLUUID uuid = avatar->getID();
+			for (LLScrollListItem* item : mAvatarScroll->getAllData())
+			{
+				if (avatar == item->getUserdata())
+				{
+					item->setFlagged(FALSE);
+					//BD - When we refresh it might happen that we don't have a name for someone
+					//     yet, when this happens the list entry won't be purged and rebuild as
+					//     it will be updated with this part, so we have to update the name in
+					//     case it was still being resolved last time we refreshed and created the
+					//     initial list entry. This prevents the name from missing forever.
+					if (item->getColumn(1)->getValue().asString().empty())
+					{
+						LLAvatarName av_name;
+						LLAvatarNameCache::get(uuid, &av_name);
+						item->getColumn(1)->setValue(av_name.getDisplayName());
+					}
+
+					create_new = false;
+					break;
+				}
+			}
+
+			if (create_new)
+			{
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(uuid, &av_name);
+
+				LLSD row;
+				row["columns"][0]["column"] = "icon";
+				row["columns"][0]["type"] = "icon";
+				row["columns"][0]["value"] = getString("icon_category");
+				row["columns"][1]["column"] = "name";
+				row["columns"][1]["value"] = av_name.getDisplayName();
+				row["columns"][2]["column"] = "uuid";
+				row["columns"][2]["value"] = avatar->getID();
+				row["columns"][3]["column"] = "control_avatar";
+				row["columns"][3]["value"] = false;
+				LLScrollListItem* item = mAvatarScroll->addElement(row);
+				item->setUserdata(avatar);
+
+				//BD - We're just here to find ourselves, break out immediately when we are done.
+				//break;
+			}
+		}
+	}
+
+	//BD - Animesh Support
+	//     Search through all control avatars.
+	for (auto character : LLControlAvatar::sInstances)
+	{
+		create_new = true;
+		LLControlAvatar* avatar = dynamic_cast<LLControlAvatar*>(character);
+		if (avatar && !avatar->isDead() && (avatar->getRegion() == gAgent.getRegion()))
+		{
+			LLUUID uuid = avatar->getID();
+			for (LLScrollListItem* item : mAvatarScroll->getAllData())
+			{
+				if (item)
+				{
+					if (avatar == item->getUserdata())
+					{
+						//BD - Avatar is still valid unflag it from removal.
+						item->setFlagged(FALSE);
+						create_new = false;
+						break;
+					}
+				}
+			}
+
+			if (create_new)
+			{
+				//BD - Avatar was not listed yet, create a new entry.
+				LLSD row;
+				row["columns"][0]["column"] = "icon";
+				row["columns"][0]["type"] = "icon";
+				row["columns"][0]["value"] = getString("icon_object");
+				row["columns"][1]["column"] = "name";
+				row["columns"][1]["value"] = avatar->getFullname();
+				row["columns"][2]["column"] = "uuid";
+				row["columns"][2]["value"] = avatar->getID();
+				row["columns"][3]["column"] = "control_avatar";
+				row["columns"][3]["value"] = true;
+				LLScrollListItem* item = mAvatarScroll->addElement(row);
+				item->setUserdata(avatar);
+			}
+		}
+	}
+
+	//BD - Now safely delete all items so we can start adding the missing ones.
+	mAvatarScroll->deleteFlaggedItems();
+
+	//BD - Make sure we don't have a scrollbar unless we need it.
+	mAvatarScroll->updateLayout();
+}
+
+
+////////////////////////////////
+//BD - Experimental Functions
+////////////////////////////////
+
+/*void BDFloaterPoser::onAnimEdit(LLUICtrl* ctrl, const LLSD& param)
+{
+	getChild<LLMultiSliderCtrl>("key_slider")->clear();
+	LLUUID id = LLUUID("cd9b0386-b26d-e860-0114-d879ee12a777");
+
+	//LLKeyframeMotion* motion = (LLKeyframeMotion*)gAgentAvatarp->findMotion(id);
+	typedef std::map<LLUUID, class LLKeyframeMotion::JointMotionList*> keyframe_data_map_t;
+
+	LLKeyframeMotion::JointMotionList* jointmotion_list;
+	jointmotion_list = LLKeyframeDataCache::getKeyframeData(id);
+	S32 i = 0;
+
+	if (!jointmotion_list)
+	{
+		return;
+	}
+
+	LLScrollListItem* item = mJointScrolls[JOINTS]->getLastSelectedItem();
+	if (!item)
+	{
+		return;
+	}
+
+	LLJoint* joint = (LLJoint*)item->getUserdata();
+	i = joint->mJointNum;
+
+	LLKeyframeMotion::JointMotion* joint_motion = jointmotion_list->getJointMotion(i);
+	LLKeyframeMotion::RotationCurve rot_courve = joint_motion->mRotationCurve;
+	LLKeyframeMotion::RotationKey rot_key;
+	LLQuaternion rotation;
+	F32 time;
+	LLKeyframeMotion::RotationCurve::key_map_t keys = rot_courve.mKeys;
+
+	for (LLKeyframeMotion::RotationCurve::key_map_t::const_iterator iter = keys.begin();
+		iter != keys.end(); ++iter)
+	{
+		time = iter->first;
+		rot_key = iter->second;
+
+		//const std::string& sldr_name = getChild<LLMultiSliderCtrl>("key_slider")->addSlider(time);
+		getChild<LLMultiSliderCtrl>("key_slider")->addSlider(time);
+		//getChild<LLMultiSliderCtrl>("key_slider")->getSliderValue();
+	}
+}
+
+void BDFloaterPoser::onAddKey()
+{
+	//S32 max_sliders = 60;
+
+	//if ((S32)mSliderToKey.size() >= max_sliders)
+	//{
+	//	LLSD args;
+	//	args["MAX"] = max_sliders;
+	//	//LLNotificationsUtil::add("DayCycleTooManyKeyframes", args, LLSD(), LLNotificationFunctorRegistry::instance().DONOTHING);
+	//	return;
+	//}
+
+	// add the slider key
+	std::string key_val = mPoseScroll->getFirstSelected()->getColumn(0)->getValue().asString();
+	BDPoseKey pose_params(key_val);
+
+	F32 time = mTimeSlider->getCurSliderValue();
+	addSliderKey(time, pose_params);
+}
+
+void BDFloaterPoser::addSliderKey(F32 time, BDPoseKey keyframe)
+{
+	// make a slider
+	const std::string& sldr_name = mKeySlider->addSlider(time);
+	if (sldr_name.empty())
+	{
+		return;
+	}
+
+	// set the key
+	SliderKey newKey(keyframe, mKeySlider->getCurSliderValue());
+
+	// add to map
+	mSliderToKey.insert(std::pair<std::string, SliderKey>(sldr_name, newKey));
+}
+
+void BDFloaterPoser::onTimeSliderMoved()
+{
+}
+
+void BDFloaterPoser::onKeyTimeMoved()
+{
+	if (mKeySlider->getValue().size() == 0)
+	{
+		return;
+	}
+
+	// make sure we have a slider
+	const std::string& cur_sldr = mKeySlider->getCurSlider();
+	if (cur_sldr == "")
+	{
+		return;
+	}
+
+	F32 time24 = mKeySlider->getCurSliderValue();
+
+	// check to see if a key exists
+	BDPoseKey key = mSliderToKey[cur_sldr].keyframe;
+	//// _LL_DEBUGS() << "Setting key time: " << time24 << LL_ENDL;
+	mSliderToKey[cur_sldr].time = time24;
+
+	// if it exists, turn on check box
+	//mSkyPresetsCombo->selectByValue(key.toStringVal());
+
+	//mTimeCtrl->setTime24(time24);
+}
+
+void BDFloaterPoser::onKeyTimeChanged()
+{
+	// if no keys, skipped
+	if (mSliderToKey.size() == 0)
+	{
+		return;
+	}
+
+	F32 time24 = getChild<LLTimeCtrl>("time_control")->getTime24();
+
+	const std::string& cur_sldr = mKeySlider->getCurSlider();
+	mKeySlider->setCurSliderValue(time24, TRUE);
+	F32 time = mKeySlider->getCurSliderValue() / 60;
+
+	// now set the key's time in the sliderToKey map
+	//// _LL_DEBUGS() << "Setting key time: " << time << LL_ENDL;
+	mSliderToKey[cur_sldr].time = time;
+
+	//applyTrack();
+}
+
+void BDFloaterPoser::onDeleteKey()
+{
+	if (mSliderToKey.size() == 0)
+	{
+		return;
+	}
+
+	// delete from map
+	const std::string& sldr_name = mKeySlider->getCurSlider();
+	std::map<std::string, SliderKey>::iterator mIt = mSliderToKey.find(sldr_name);
+	mSliderToKey.erase(mIt);
+
+	mKeySlider->deleteCurSlider();
+
+	if (mSliderToKey.size() == 0)
+	{
+		return;
+	}
+
+	const std::string& name = mKeySlider->getCurSlider();
+	//mSkyPresetsCombo->selectByValue(mSliderToKey[name].keyframe.toStringVal());
+	F32 time24 = mSliderToKey[name].time;
+
+	getChild<LLTimeCtrl>("time_control")->setTime24(time24);
+}
+
+void BDFloaterPoser::onAnimSetValue(LLUICtrl* ctrl, const LLSD& param)
+{
+	F32 val = ctrl->getValue().asReal();
+	mKeySlider->setValue(val);
+}*/
diff --git a/indra/newview/bdfloaterposer.h b/indra/newview/bdfloaterposer.h
new file mode 100644
index 00000000000..7f125c9d94f
--- /dev/null
+++ b/indra/newview/bdfloaterposer.h
@@ -0,0 +1,254 @@
+/**
+*
+* Copyright (C) 2018, NiranV Dean
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+*/
+
+
+#ifndef BD_FLOATER_POSER_H
+#define BD_FLOATER_POSER_H
+
+#include "llfloater.h"
+#include "llscrolllistctrl.h"
+#include "llsliderctrl.h"
+//#include "llmultisliderctrl.h"
+//#include "lltimectrl.h"
+#include "lltabcontainer.h"
+#include "llkeyframemotion.h"
+#include "lltoggleablemenu.h"
+#include "llmenubutton.h"
+
+/*struct BDPoseKey
+{
+public:
+	// source of a pose set
+	std::string name;
+
+	// for conversion from LLSD
+	static const int NAME_IDX = 0;
+	static const int SCOPE_IDX = 1;
+
+	inline BDPoseKey(const std::string& n)
+		: name(n)
+	{
+	}
+
+	inline BDPoseKey(LLSD llsd)
+		: name(llsd[NAME_IDX].asString())
+	{
+	}
+
+	inline BDPoseKey() // NOT really valid, just so std::maps can return a default of some sort
+		: name("")
+	{
+	}
+
+	inline BDPoseKey(std::string& stringVal)
+	{
+		size_t len = stringVal.length();
+		if (len > 0)
+		{
+			name = stringVal.substr(0, len - 1);
+		}
+	}
+
+	inline std::string toStringVal() const
+	{
+		std::stringstream str;
+		str << name;
+		return str.str();
+	}
+
+	inline LLSD toLLSD() const
+	{
+		LLSD llsd = LLSD::emptyArray();
+		llsd.append(LLSD(name));
+		return llsd;
+	}
+
+	inline void fromLLSD(const LLSD& llsd)
+	{
+		name = llsd[NAME_IDX].asString();
+	}
+
+	inline bool operator <(const BDPoseKey other) const
+	{
+		if (name < other.name)
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+	inline bool operator ==(const BDPoseKey other) const
+	{
+		return (name == other.name);
+	}
+
+	std::string toString() const;
+};*/
+
+
+typedef enum E_BoneTypes
+{
+	JOINTS = 0,
+	COLLISION_VOLUMES = 1,
+	ATTACHMENT_BONES = 2
+} E_BoneTypes;
+
+typedef enum E_Columns
+{
+	COL_ICON = 0,
+	COL_NAME = 1,
+	COL_ROT_X = 2,
+	COL_ROT_Y = 3,
+	COL_ROT_Z = 4,
+	COL_POS_X = 5,
+	COL_POS_Y = 6,
+	COL_POS_Z = 7,
+	COL_SCALE_X = 8,
+	COL_SCALE_Y = 9,
+	COL_SCALE_Z = 10
+} E_Columns;
+
+class BDFloaterPoser :
+	public LLFloater
+{
+	friend class LLFloaterReg;
+private:
+	BDFloaterPoser(const LLSD& key);
+	/*virtual*/	~BDFloaterPoser();
+	/*virtual*/	BOOL postBuild();
+	/*virtual*/ void draw();
+	/*virtual*/ void onOpen(const LLSD& key);
+	/*virtual*/	void onClose(bool app_quitting);
+
+	//BD - Posing
+	void onClickPoseSave();
+	void onPoseStart();
+	void onPoseDelete();
+	void onPoseRefresh();
+	void onPoseSet(LLUICtrl* ctrl, const LLSD& param);
+	void onPoseControlsRefresh();
+	void onPoseSave(S32 type, F32 time, bool editing);
+	void onPoseLoad();
+	void onPoseLoadSelective(const LLSD& param);
+	void onPoseMenuAction(const LLSD& param);
+	void onPoseScrollRightMouse(LLUICtrl* ctrl, S32 x, S32 y);
+
+	//BD - Joints
+	void onJointRefresh();
+	void onJointSet(LLUICtrl* ctrl, const LLSD& param);
+	void onJointPosSet(LLUICtrl* ctrl, const LLSD& param);
+	void onJointScaleSet(LLUICtrl* ctrl, const LLSD& param);
+	void onJointChangeState();
+	void onJointControlsRefresh();
+	void onJointRotPosScaleReset();
+	void onJointRotationReset();
+	void onJointPositionReset();
+	void onJointScaleReset();
+	void onCollectDefaults();
+
+	//BD - Animating
+	void onAnimAdd(const LLSD& param);
+	void onAnimListWrite();
+	void onAnimMove(const LLSD& param);
+	void onAnimDelete();
+	void onAnimSave();
+	void onAnimSet();
+	void onAnimPlay();
+	void onAnimStop();
+	void onAnimControlsRefresh();
+
+	//BD - Misc
+	void onUpdateLayout();
+
+	//BD - Mirror Bone
+	void toggleMirrorMode(LLUICtrl* ctrl) { mMirrorMode = ctrl->getValue().asBoolean(); }
+	void toggleEasyRotations(LLUICtrl* ctrl) { mEasyRotations = ctrl->getValue().asBoolean(); }
+
+	//BD - Flip Poses
+	void onFlipPose();
+
+	//BD - Animesh
+	void onAvatarsRefresh();
+	void onAvatarsSelect();
+
+	//BD
+	void loadPoseRotations(std::string name, LLVector3 *rotations);
+	void loadPosePositions(std::string name, LLVector3 *rotations);
+	void loadPoseScales(std::string name, LLVector3 *rotations);
+
+private:
+	//BD - Posing
+	LLScrollListCtrl*						mPoseScroll;
+	LLTabContainer*							mJointTabs;
+	LLHandle<LLToggleableMenu>				mPosesMenuHandle;
+
+	std::array<LLUICtrl*, 3>				mRotationSliders;
+	std::array<LLSliderCtrl*, 3>			mPositionSliders;
+	std::array<LLSliderCtrl*, 3>			mScaleSliders;
+	std::array<LLScrollListCtrl*, 3>		mJointScrolls;
+
+	//BD - I really didn't want to do this this way but we have to.
+	//     It's the easiest way doing this.
+	std::map<const std::string, LLVector3>	mDefaultScales;
+	std::map<const std::string, LLVector3>	mDefaultPositions;
+
+	//BD - Animations
+	LLScrollListCtrl*						mAnimEditorScroll;
+
+	//BD - Misc
+	bool									mDelayRefresh;
+	bool									mEasyRotations;
+	
+	//BD - Mirror Bone
+	bool									mMirrorMode;
+
+	//BD - Animesh
+	LLScrollListCtrl*						mAvatarScroll;
+
+	LLButton*								mStartPosingBtn;
+	LLMenuButton*							mLoadPosesBtn;
+
+	//BD - Experimental
+	/*void onAnimEdit(LLUICtrl* ctrl, const LLSD& param);
+	void onAddKey();
+	void onDeleteKey();
+	void addSliderKey(F32 time, BDPoseKey keyframe);
+	void onTimeSliderMoved();
+	void onKeyTimeMoved();
+	void onKeyTimeChanged();
+	void onAnimSetValue(LLUICtrl* ctrl, const LLSD& param);
+
+	/// convenience class for holding keyframes mapped to sliders
+	struct SliderKey
+	{
+	public:
+		SliderKey(BDPoseKey kf, F32 t) : keyframe(kf), time(t) {}
+		SliderKey() : keyframe(), time(0.f) {} // Don't use this default constructor
+
+		BDPoseKey keyframe;
+		F32 time;
+	};
+
+	LLSD 									mAnimJointMap[134][200][2]; // 134 bones, 200 keyframes , 2 stats (rotation | time)
+	std::map<std::string, SliderKey>		mSliderToKey;
+	LLMultiSliderCtrl*						mTimeSlider;
+	LLMultiSliderCtrl*						mKeySlider; */
+};
+
+#endif
diff --git a/indra/newview/bdposingmotion.cpp b/indra/newview/bdposingmotion.cpp
new file mode 100644
index 00000000000..ef8a21e3b2d
--- /dev/null
+++ b/indra/newview/bdposingmotion.cpp
@@ -0,0 +1,261 @@
+/**
+*
+* Copyright (C) 2018, NiranV Dean
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+*/
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "linden_common.h"
+
+#include "llviewerprecompiledheaders.h"
+
+#include "bdposingmotion.h"
+#include "llcharacter.h"
+#include "llviewercontrol.h"
+
+//-----------------------------------------------------------------------------
+// BDPosingMotion()
+// Class Constructor
+//-----------------------------------------------------------------------------
+BDPosingMotion::BDPosingMotion(const LLUUID &id) :
+LLMotion(id),
+	mCharacter(NULL),
+	mTargetJoint(NULL)
+{
+	mName = "custom_pose";
+	//BD - Use slight spherical linear interpolation by default.
+	mInterpolationTime = 0.25f;
+	mInterpolationType = 2;
+
+	for (auto& entry : mJointState)
+	{
+		entry = new LLJointState;
+	}
+}
+
+
+//-----------------------------------------------------------------------------
+// ~BDPosingMotion()
+// Class Destructor
+//-----------------------------------------------------------------------------
+BDPosingMotion::~BDPosingMotion()
+{
+}
+
+//-----------------------------------------------------------------------------
+// BDPosingMotion::onInitialize(LLCharacter *character)
+//-----------------------------------------------------------------------------
+LLMotion::LLMotionInitStatus BDPosingMotion::onInitialize(LLCharacter *character)
+{
+	// save character for future use
+	mCharacter = character;
+
+	for (S32 i = 0; (mTargetJoint = mCharacter->getCharacterJoint(i)); ++i)
+	{
+		mJointState[i]->setJoint(mTargetJoint);
+		//BD - Bones that can support position
+		//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+		if (mTargetJoint->mHasPosition)
+		{
+			mJointState[i]->setUsage(LLJointState::POS | LLJointState::ROT);
+		}
+		else
+		{
+			mJointState[i]->setUsage(LLJointState::ROT);
+		}
+		addJointState(mJointState[i]);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+//-----------------------------------------------------------------------------
+// BDPosingMotion::onActivate()
+//-----------------------------------------------------------------------------
+BOOL BDPosingMotion::onActivate()
+{
+	for (auto joint_state : mJointState)
+	{
+		LLJoint* joint = joint_state->getJoint();
+		if (joint)
+		{
+			joint->setTargetRotation(joint->getRotation());
+			//BD - Bones that can support position
+			//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+			if (joint->mHasPosition)
+			{
+				joint->setTargetPosition(joint->getPosition());
+			}
+		}
+	}
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// BDPosingMotion::onUpdate()
+//-----------------------------------------------------------------------------
+BOOL BDPosingMotion::onUpdate(F32 time, U8* joint_mask)
+{
+	LLQuaternion target_quat;
+	LLQuaternion joint_quat;
+	LLQuaternion last_quat;
+	LLQuaternion next_quat;
+	LLVector3 joint_pos;
+	LLVector3 last_pos;
+	LLVector3 target_pos;
+	LLVector3 next_pos;
+	F32 perc = 0.0f;
+
+	for (auto joint_state : mJointState)
+	{
+		LLJoint* joint = joint_state->getJoint();
+		if (joint)
+		{
+			target_quat = joint->getTargetRotation();
+			joint_quat = joint->getRotation();
+			last_quat = joint->getLastRotation();
+
+			//BD - Merge these two together?
+			perc = llclamp(mInterpolationTimer.getElapsedTimeF32() / mInterpolationTime, 0.0f, 1.0f);
+			//BD - Bones that can support position
+			//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+			if (joint->mHasPosition)
+			{
+				joint_pos = joint->getPosition();
+				target_pos = joint->getTargetPosition();
+				last_pos = joint->getLastPosition();
+				if (target_pos != joint_pos)
+				{
+					if (mInterpolationType == 2)
+					{
+						//BD - Do spherical linear interpolation.
+						//     We emulate the spherical linear interpolation here because
+						//     slerp() does not support LLVector3. mInterpolationTime is always
+						//     in a range between 0.00 and 1.00 which makes it perfect to use
+						//     as percentage directly.
+						//     We use the current joint position rather than the original like
+						//     in linear interpolation to take a fraction of the fraction, this
+						//     re-creates spherical linear interpolation's behavior.
+						joint_pos = lerp(joint_pos, target_pos, mInterpolationTime);
+					}
+					else if (mInterpolationType == 3)
+					{
+						next_pos = joint->getNextPosition();
+						//BD - Do curve interpolation.
+						//     This is a special kind of interpolation where we interpolate towards
+						//     a "middle" pose to a given degree while on our way to the actual final
+						//     pose.
+						joint_pos = lerp(joint_pos, next_pos, perc);
+						joint_pos = lerp(joint_pos, target_pos, 0.5f - abs(0.5f - perc));
+					}
+					else
+					{
+						if (perc >= 1.0f)
+						{
+							//BD - Can be used to do no interpolation too.
+							joint_pos = target_pos;
+							last_pos = joint_pos;
+						}
+						else
+						{
+							//BD - Do linear interpolation.
+							joint_pos = lerp(last_pos, target_pos, perc);
+						}
+					}
+					joint_state->setPosition(joint_pos);
+				}
+			}
+
+			if (target_quat != joint_quat)
+			{
+				if (mInterpolationType == 2)
+				{
+					//BD - Do spherical linear interpolation.
+					joint_quat = slerp(mInterpolationTime, joint_quat, target_quat);
+				}
+				else if (mInterpolationType == 3)
+				{
+					next_pos = joint->getNextPosition();
+					//BD - Do curve interpolation.
+					//     This is a special kind of interpolation where we interpolate towards
+					//     a "middle" pose to a given degree while on our way to the actual final
+					//     pose.
+					joint_quat = lerp(perc, joint_quat, next_quat);
+					joint_quat = lerp(0.5f - abs(0.5f - perc), joint_quat, target_quat);
+				}
+				else
+				{
+					if (perc >= 1.0f)
+					{
+						//BD - Can be used to do no interpolation too.
+						joint_quat = target_quat;
+						last_quat = joint_quat;
+					}
+					else
+					{
+						//BD - Do linear interpolation.
+						joint_quat = lerp(perc, last_quat, target_quat);
+					}
+				}
+				joint_state->setRotation(joint_quat);
+			}
+		}
+	}
+
+	if (perc >= 1.0f && mInterpolationTimer.getStarted()
+		&& (last_quat == joint_quat
+		&& (last_pos == joint_pos)))
+	{
+		mInterpolationTimer.stop();
+	}
+
+	return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// BDPosingMotion::onDeactivate()
+//-----------------------------------------------------------------------------
+void BDPosingMotion::onDeactivate()
+{
+}
+
+//-----------------------------------------------------------------------------
+// addJointState()
+//-----------------------------------------------------------------------------
+void BDPosingMotion::addJointToState(LLJoint *joint)
+{
+	//BD - It is safe to assume that whatever is passed here must be at least some kind of valid
+	//     joint, all code calling this function has null checks in place.
+	S32 i = joint->getJointNum();
+
+	//BD - Don't add collision volumes and attachment bones.
+	if (i > 134)
+		return;
+
+	mJointState[i]->setJoint(joint);
+	//BD - Bones that can support position
+	//     0, 9-37, 39-43, 45-59, 77, 97-107, 110, 112, 115, 117-121, 125, 128-129, 132
+	if (joint->mHasPosition)
+	{
+		mJointState[i]->setUsage(LLJointState::POS | LLJointState::ROT);
+	}
+	else
+	{
+		mJointState[i]->setUsage(LLJointState::ROT);
+	}
+	addJointState(mJointState[i]);
+}
+// End
+
diff --git a/indra/newview/bdposingmotion.h b/indra/newview/bdposingmotion.h
new file mode 100644
index 00000000000..9799194acda
--- /dev/null
+++ b/indra/newview/bdposingmotion.h
@@ -0,0 +1,111 @@
+/**
+*
+* Copyright (C) 2018, NiranV Dean
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+*/
+
+#ifndef LL_BDPOSINGMOTION_H
+#define LL_BDPOSINGMOTION_H
+
+//-----------------------------------------------------------------------------
+// Header files
+//-----------------------------------------------------------------------------
+#include "llmotion.h"
+#include "lljointsolverrp3.h"
+#include "v3dmath.h"
+
+#define MIN_REQUIRED_PIXEL_AREA_POSING 500.f
+
+//-----------------------------------------------------------------------------
+// class BDPosingMotion
+//-----------------------------------------------------------------------------
+class BDPosingMotion :
+	public LLMotion
+{
+public:
+	// Constructor
+	BDPosingMotion(const LLUUID &id);
+
+	// Destructor
+	virtual ~BDPosingMotion();
+
+public:
+	//-------------------------------------------------------------------------
+	// functions to support MotionController and MotionRegistry
+	//-------------------------------------------------------------------------
+
+	// static constructor
+	// all subclasses must implement such a function and register it
+	static LLMotion *create(const LLUUID &id) { return new BDPosingMotion(id); }
+
+public:
+	//-------------------------------------------------------------------------
+	// animation callbacks to be implemented by subclasses
+	//-------------------------------------------------------------------------
+
+	// motions must specify whether or not they loop
+	virtual BOOL getLoop() { return TRUE; }
+
+	// motions must report their total duration
+	virtual F32 getDuration() { return 0.0; }
+
+	// motions must report their "ease in" duration
+	virtual F32 getEaseInDuration() { return 0.0f; }
+
+	// motions must report their "ease out" duration.
+	virtual F32 getEaseOutDuration() { return 0.5f; }
+
+	// motions must report their priority
+	virtual LLJoint::JointPriority getPriority() { return LLJoint::ADDITIVE_PRIORITY; }
+
+	virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; }
+
+	// called to determine when a motion should be activated/deactivated based on avatar pixel coverage
+	virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_POSING; }
+
+	// run-time (post constructor) initialization,
+	// called after parameters have been set
+	// must return true to indicate success and be available for activation
+	virtual LLMotionInitStatus onInitialize(LLCharacter *character);
+
+	// called when a motion is activated
+	// must return TRUE to indicate success, or else
+	// it will be deactivated
+	virtual BOOL onActivate();
+
+	// called per time step
+	// must return TRUE while it is active, and
+	// must return FALSE when the motion is completed.
+	virtual BOOL onUpdate(F32 time, U8* joint_mask);
+
+	// called when a motion is deactivated
+	virtual void onDeactivate();
+
+	void addJointToState(LLJoint *joint);
+
+public:
+	//-------------------------------------------------------------------------
+	// Joint States
+	//-------------------------------------------------------------------------
+	LLCharacter			*mCharacter;
+
+	LLPointer<LLJointState> mJointState[134];
+
+	//-------------------------------------------------------------------------
+	// Joints
+	//-------------------------------------------------------------------------
+	LLJoint*			mTargetJoint;
+};
+
+#endif // LL_LLKEYFRAMEMOTION_H
+
diff --git a/indra/newview/character/avatar_skeleton.xml b/indra/newview/character/avatar_skeleton.xml
index 2241a12545f..3c81b921118 100644
--- a/indra/newview/character/avatar_skeleton.xml
+++ b/indra/newview/character/avatar_skeleton.xml
@@ -1,89 +1,89 @@
 <linden_skeleton num_bones="133" num_collision_volumes="26" version="2.0">
-   <bone aliases="hip avatar_mPelvis" connected="false" end="0.000 0.000 0.084" group="Torso" name="mPelvis" pivot="0.000000 0.000000 1.067015" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-      <collision_volume end="0.030 0.000 0.095" group="Collision" name="PELVIS" pos="-0.01 0 -0.02" rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17" support="base"/>
-      <collision_volume end="-0.100 0.000 0.000" group="Collision" name="BUTT" pos="-0.06 0 -0.1" rot="0.000000 0.00000 0.000000" scale="0.1 0.1 0.1" support="base"/>
+   <bone aliases="hip avatar_mPelvis" connected="false" end="0.000 0.000 0.084" group="Torso" name="mPelvis" pivot="0.000000 0.000000 1.067015" pos="0.000 0.000 1.067" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true" >
+      <collision_volume end="0.030 0.000 0.095" group="Collision" name="PELVIS" pos="-0.01 0 -0.02" rot="0.000000 8.00000 0.000000" scale="0.12 0.16 0.17" support="base" reposition="true"/>
+      <collision_volume end="-0.100 0.000 0.000" group="Collision" name="BUTT" pos="-0.06 0 -0.1" rot="0.000000 0.00000 0.000000" scale="0.1 0.1 0.1" support="base" reposition="true"/>
       <bone connected="true" end="0.000 0.000 -0.084" group="Spine" name="mSpine1" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
          <bone connected="true" end="0.000 0.000 0.084" group="Spine" name="mSpine2" pivot="0.000000 0.000000 -0.084073" pos="0.000 0.000 -0.084" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
             <bone aliases="abdomen avatar_mTorso" connected="true" end="-0.015 0.000 0.205" group="Torso" name="mTorso" pivot="0.000000 0.000000 0.084073" pos="0.000 0.000 0.084" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-               <collision_volume end="0.028 0.000 0.094" group="Collision" name="BELLY" pos="0.028 0 0.04" rot="0.000000 8.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>
-               <collision_volume end="0.000 0.100 0.000" group="Collision" name="LEFT_HANDLE" pos="0.0 0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/>
-               <collision_volume end="0.000 -0.100 0.000" group="Collision" name="RIGHT_HANDLE" pos="0.0 -0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base"/>
-               <collision_volume end="-0.100 0.000 0.000" group="Collision" name="LOWER_BACK" pos="0.0 0.0 0.023" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>
+               <collision_volume end="0.028 0.000 0.094" group="Collision" name="BELLY" pos="0.028 0 0.04" rot="0.000000 8.00000 0.000000" scale="0.09 0.13 0.15" support="base" reposition="true"/>
+               <collision_volume end="0.000 0.100 0.000" group="Collision" name="LEFT_HANDLE" pos="0.0 0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base" reposition="true"/>
+               <collision_volume end="0.000 -0.100 0.000" group="Collision" name="RIGHT_HANDLE" pos="0.0 -0.10 0.058" rot="0.000000 0.00000 0.000000" scale="0.05 0.05 0.05" support="base" reposition="true"/>
+               <collision_volume end="-0.100 0.000 0.000" group="Collision" name="LOWER_BACK" pos="0.0 0.0 0.023" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base" reposition="true"/>
                <bone connected="true" end="0.015 0.000 -0.205" group="Spine" name="mSpine3" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
                   <bone connected="true" end="-0.015 0.000 0.205" group="Spine" name="mSpine4" pivot="0.015368 0.000000 -0.204877" pos="0.015 0.000 -0.205" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
                      <bone aliases="chest avatar_mChest" connected="true" end="-0.010 0.000 0.250" group="Torso" name="mChest" pivot="-0.015368 0.000000 0.204877" pos="-0.015 0.000 0.205" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                        <collision_volume end="-0.096 0.000 0.152" group="Collision" name="CHEST" pos="0.028 0 0.07" rot="0.000000 -10.00000 0.000000" scale="0.11 0.15 0.2" support="base"/>
-                        <collision_volume end="0.080 0.000 -0.006" group="Collision" name="LEFT_PEC" pos="0.119 0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base"/>
-                        <collision_volume end="0.080 0.000 -0.006" group="Collision" name="RIGHT_PEC" pos="0.119 -0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base"/>
-                        <collision_volume end="-0.100 0.000 0.000" group="Collision" name="UPPER_BACK" pos="0.0 0.0 0.017" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base"/>
+                        <collision_volume end="-0.096 0.000 0.152" group="Collision" name="CHEST" pos="0.028 0 0.07" rot="0.000000 -10.00000 0.000000" scale="0.11 0.15 0.2" support="base" reposition="true"/>
+                        <collision_volume end="0.080 0.000 -0.006" group="Collision" name="LEFT_PEC" pos="0.119 0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base" reposition="true"/>
+                        <collision_volume end="0.080 0.000 -0.006" group="Collision" name="RIGHT_PEC" pos="0.119 -0.082 0.042" rot="0.000000 4.29000 0.000000" scale="0.05 0.05 0.05" support="base" reposition="true"/>
+                        <collision_volume end="-0.100 0.000 0.000" group="Collision" name="UPPER_BACK" pos="0.0 0.0 0.017" rot="0.000000 0.00000 0.000000" scale="0.09 0.13 0.15" support="base" reposition="true"/>
                         <bone aliases="neck avatar_mNeck" connected="true" end="0.000 0.000 0.077" group="Torso" name="mNeck" pivot="-0.009507 0.000000 0.251108" pos="-0.010 0.000 0.251" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
                            <collision_volume end="0.000 0.000 0.080" group="Collision" name="NECK" pos="0.0 0 0.02" rot="0.000000 0.000000 0.000000" scale="0.05 0.06 0.08" support="base"/>
                            <bone aliases="head avatar_mHead" connected="true" end="0.000 0.000 0.079" group="Torso" name="mHead" pivot="0.000000 -0.000000 0.075630" pos="0.000 -0.000 0.076" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                              <collision_volume end="0.000 0.000 0.100" group="Collision" name="HEAD" pos="0.02 0 0.07" rot="0.000000 0.000000 0.000000" scale="0.11 0.09 0.12" support="base"/>
-                              <bone aliases="figureHair avatar_mSkull" connected="false" end="0.000 0.000 0.033" group="Extra" name="mSkull" pivot="0.000000 0.000000 0.079000" pos="0.000 0.000 0.079" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
-                              <bone aliases="avatar_mEyeRight" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeRight" pivot="0.098466 -0.036000 0.079000" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 -0.000000" scale="1.000 1.000 1.000" support="base"/>
-                              <bone aliases="avatar_mEyeLeft" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeLeft" pivot="0.098461 0.036000 0.079000" pos="0.098 0.036 0.079" rot="0.000000 -0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
+                              <collision_volume end="0.000 0.000 0.100" group="Collision" name="HEAD" pos="0.02 0 0.07" rot="0.000000 0.000000 0.000000" scale="0.11 0.09 0.12" support="base" reposition="true"/>
+                              <bone aliases="figureHair avatar_mSkull" connected="false" end="0.000 0.000 0.033" group="Extra" name="mSkull" pivot="0.000000 0.000000 0.079000" pos="0.000 0.000 0.079" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true"/>
+                              <bone aliases="avatar_mEyeRight" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeRight" pivot="0.098466 -0.036000 0.079000" pos="0.098 -0.036 0.079" rot="0.000000 0.000000 -0.000000" scale="1.000 1.000 1.000" support="base" reposition="true"/>
+                              <bone aliases="avatar_mEyeLeft" connected="false" end="0.025 0.000 0.000" group="Extra" name="mEyeLeft" pivot="0.098461 0.036000 0.079000" pos="0.098 0.036 0.079" rot="0.000000 -0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true"/>
                               <bone connected="false" end="0.020 0.000 0.000" group="Face" name="mFaceRoot" pivot="0.025000 0.000000 0.045000" pos="0.025 0.000 0.045" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended">
-                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                    <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltRight" pivot="0.073466 -0.036000 0.0339300" pos="0.073 -0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceEyeAltLeft" pivot="0.073461 0.036000 0.0339300" pos="0.073 0.036 0.034" rot="0.000000 0.000000 0.000000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.024 0.004 0.018" group="Face" name="mFaceForeheadLeft" pivot="0.061 0.035 0.083" pos="0.061 0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.024 -0.004 0.018" group="Face" name="mFaceForeheadRight" pivot="0.061 -0.035 0.083" pos="0.061 -0.035 0.083" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.023 0.013 0.000" group="Eyes" name="mFaceEyebrowOuterLeft" pivot="0.064 0.051 0.048" pos="0.064 0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterLeft" pivot="0.070 0.043 0.056" pos="0.070 0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerLeft" pivot="0.075 0.022 0.051" pos="0.075 0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.023 -0.013 0.000" group="Eyes" name="mFaceEyebrowOuterRight" pivot="0.064 -0.051 0.048" pos="0.064 -0.051 0.048" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.027 0.000 0.000" group="Eyes" name="mFaceEyebrowCenterRight" pivot="0.070 -0.043 0.056" pos="0.070 -0.043 0.056" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.026 0.000 0.000" group="Eyes" name="mFaceEyebrowInnerRight" pivot="0.075 -0.022 0.051" pos="0.075 -0.022 0.051" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerLeft" pivot="0.073 0.036 0.034" pos="0.073 0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.027 0.000 0.005" group="Eyes" name="mFaceEyeLidUpperRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.024 0.000 -0.007" group="Eyes" name="mFaceEyeLidLowerRight" pivot="0.073 -0.036 0.034" pos="0.073 -0.036 0.034" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="-0.019 0.018 0.025" group="Ears" name="mFaceEar1Left" pivot="0.000 0.080 0.002" pos="0.000 0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                    <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Left" pivot="-0.019 0.018 0.025" pos="-0.019 0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                  </bone>
-                                 <bone connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                    <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                 <bone connected="false" end="-0.019 -0.018 0.025" group="Ears" name="mFaceEar1Right" pivot="0.000 -0.080 0.002" pos="0.000 -0.080 0.002" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                    <bone connected="true" end="0.000 0.000 0.033" group="Ears" name="mFaceEar2Right" pivot="-0.019 -0.018 0.025" pos="-0.019 -0.018 0.025" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                  </bone>
-                                 <bone connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                 <bone connected="false" end="0.015 0.004 0.000" group="Face" name="mFaceNoseLeft" pivot="0.086 0.015 -0.004" pos="0.086 0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.025 0.000 0.000" group="Face" name="mFaceNoseCenter" pivot="0.102 0.000 0.000" pos="0.102 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.015 -0.004 0.000" group="Face" name="mFaceNoseRight" pivot="0.086 -0.015 -0.004" pos="0.086 -0.015 -0.004" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.013 0.030 0.000" group="Face" name="mFaceCheekLowerLeft" pivot="0.050 0.034 -0.031" pos="0.050 0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.022 0.015 0.000" group="Face" name="mFaceCheekUpperLeft" pivot="0.070 0.034 -0.005" pos="0.070 0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.013 -0.030 0.000" group="Face" name="mFaceCheekLowerRight" pivot="0.050 -0.034 -0.031" pos="0.050 -0.034 -0.031" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.022 -0.015 0.000" group="Face" name="mFaceCheekUpperRight" pivot="0.070 -0.034 -0.005" pos="0.070 -0.034 -0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                  <bone connected="false" end="0.059 0.000 -0.039" group="Mouth" name="mFaceJaw" pivot="-0.001 0.000 -0.015" pos="-0.001 0.000 -0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                    <bone connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                       <bone connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                       <bone connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                       <bone connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                    <bone connected="false" end="0.021 0.000 -0.018" group="Mouth" name="mFaceChin" pivot="0.074 0.000 -0.054" pos="0.074 0.000 -0.054" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethLower" pivot="0.021 0.000 -0.039" pos="0.021 0.000 -0.039" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                       <bone connected="false" end="0.034 0.017 0.005" group="Lips" name="mFaceLipLowerLeft" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                       <bone connected="false" end="0.034 -0.017 0.005" group="Lips" name="mFaceLipLowerRight" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                       <bone connected="false" end="0.040 0.000 0.002" group="Lips" name="mFaceLipLowerCenter" pivot="0.045 0.000 0.000" pos="0.045 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                        <bone connected="false" end="0.022 0.000 0.007" group="Mouth" name="mFaceTongueBase" pivot="0.039 0.000 0.005" pos="0.039 0.000 0.005" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                          <bone connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                          <bone connected="true" end="0.010 0.000 0.000" group="Mouth" name="mFaceTongueTip" pivot="0.022 0.000 0.007" pos="0.022 0.000 0.007" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                        </bone>
                                     </bone>
                                  </bone>
-                                 <bone connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                    <bone connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                 <bone connected="false" end="-0.017 0.000 0.000" group="Face" name="mFaceJawShaper" pivot="0.000 0.000 0.000" pos="0.000 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.036 0.000 0.000" group="Face" name="mFaceForeheadCenter" pivot="0.069 0.000 0.065" pos="0.069 0.000 0.065" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.014 0.000 0.000" group="Nose" name="mFaceNoseBase" pivot="0.094 0.000 -0.016" pos="0.094 0.000 -0.016" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.035 0.000 0.000" group="Mouth" name="mFaceTeethUpper" pivot="0.020 0.000 -0.030" pos="0.020 0.000 -0.030" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                    <bone connected="false" end="0.041 0.015 0.000" group="Lips" name="mFaceLipUpperLeft" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="false" end="0.041 -0.015 0.000" group="Lips" name="mFaceLipUpperRight" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="false" end="0.045 0.051 0.000" group="Lips" name="mFaceLipCornerLeft" pivot="0.028 -0.019 -0.010" pos="0.028 -0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="false" end="0.045 -0.051 0.000" group="Lips" name="mFaceLipCornerRight" pivot="0.028 0.019 -0.010" pos="0.028 0.019 -0.010" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="false" end="0.043 0.000 0.002" group="Lips" name="mFaceLipUpperCenter" pivot="0.045 0.000 -0.003" pos="0.045 0.000 -0.003" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                  </bone>
-                                 <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                 <bone connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                                 <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerLeft" pivot="0.075 0.017 0.032" pos="0.075 0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.016 0.000 0.000" group="Face" name="mFaceEyecornerInnerRight" pivot="0.075 -0.017 0.032" pos="0.075 -0.017 0.032" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                 <bone connected="false" end="0.015 0.000 0.008" group="Nose" name="mFaceNoseBridge" pivot="0.091 0.000 0.020" pos="0.091 0.000 0.020" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                               </bone>
                            </bone>
                         </bone>
                         <bone aliases="lCollar avatar_mCollarLeft" connected="false" end="0.000 0.079 0.000" group="Arms" name="mCollarLeft" pivot="-0.020927 0.084665 0.165396" pos="-0.021 0.085 0.165" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                           <collision_volume end="0.000 0.100 0.000" group="Collision" name="L_CLAVICLE" pos="0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05" support="base"/>
+                           <collision_volume end="0.000 0.100 0.000" group="Collision" name="L_CLAVICLE" pos="0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05" support="base" reposition="true"/>
                            <bone aliases="lShldr avatar_mShoulderLeft" connected="true" end="0.000 0.247 0.000" group="Arms" name="mShoulderLeft" pivot="0.000000 0.079000 -0.000000" pos="0.000 0.079 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                              <collision_volume end="0.000 0.130 -0.003" group="Collision" name="L_UPPER_ARM" pos="0.0 0.12 0.01" rot="-5.000000 0.00000 0.000000" scale="0.05 0.17 0.05" support="base"/>
+                              <collision_volume end="0.000 0.130 -0.003" group="Collision" name="L_UPPER_ARM" pos="0.0 0.12 0.01" rot="-5.000000 0.00000 0.000000" scale="0.05 0.17 0.05" support="base" reposition="true"/>
                               <bone aliases="lForeArm avatar_mElbowLeft" connected="true" end="0.000 0.205 0.000" group="Arms" name="mElbowLeft" pivot="0.000000 0.248000 0.000000" pos="0.000 0.248 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                                 <collision_volume end="0.000 0.100 -0.001" group="Collision" name="L_LOWER_ARM" pos="0.0 0.1 0.0" rot="-3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/>
+                                 <collision_volume end="0.000 0.100 -0.001" group="Collision" name="L_LOWER_ARM" pos="0.0 0.1 0.0" rot="-3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base" reposition="true"/>
                                  <bone aliases="lHand avatar_mWristLeft" connected="true" end="0.000 0.060 0.000" group="Arms" name="mWristLeft" pivot="-0.000000 0.204846 0.000000" pos="-0.000 0.205 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
                                     <collision_volume end="0.005 0.049 -0.001" group="Collision" name="L_HAND" pos="0.01 0.05 0.0" rot="-3.000000 0.00000 -10.000000" scale="0.05 0.08 0.03" support="base"/>
                                     <bone connected="false" end="-0.001 0.040 -0.006" group="Hand" name="mHandMiddle1Left" pivot="0.013 0.101 0.015" pos="0.013 0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
@@ -116,11 +116,11 @@
                            </bone>
                         </bone>
                         <bone aliases="rCollar avatar_mCollarRight" connected="false" end="0.000 -0.079 0.000" group="Arms" name="mCollarRight" pivot="-0.020927 -0.085000 0.165396" pos="-0.021 -0.085 0.165" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                           <collision_volume end="0.000 -0.100 0.000" group="Collision" name="R_CLAVICLE" pos="0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05" support="base"/>
+                           <collision_volume end="0.000 -0.100 0.000" group="Collision" name="R_CLAVICLE" pos="0.02 0 0.02" rot="0.000000 0.00000 0.000000" scale="0.07 0.14 0.05" support="base" reposition="true"/>
                            <bone aliases="rShldr avatar_mShoulderRight" connected="true" end="0.000 -0.247 0.000" group="Arms" name="mShoulderRight" pivot="0.000000 -0.079418 -0.000000" pos="0.000 -0.079 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                              <collision_volume end="0.000 -0.130 -0.003" group="Collision" name="R_UPPER_ARM" pos="0.0 -0.12 0.01" rot="5.000000 0.00000 0.000000" scale="0.05 0.17 0.05" support="base"/>
+                              <collision_volume end="0.000 -0.130 -0.003" group="Collision" name="R_UPPER_ARM" pos="0.0 -0.12 0.01" rot="5.000000 0.00000 0.000000" scale="0.05 0.17 0.05" support="base" reposition="true"/>
                               <bone aliases="rForeArm avatar_mElbowRight" connected="true" end="0.000 -0.205 0.000" group="Arms" name="mElbowRight" pivot="0.000000 -0.248000 -0.000000" pos="0.000 -0.248 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-                                 <collision_volume end="0.000 -0.100 -0.001" group="Collision" name="R_LOWER_ARM" pos="0.0 -0.1 0.0" rot="3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base"/>
+                                 <collision_volume end="0.000 -0.100 -0.001" group="Collision" name="R_LOWER_ARM" pos="0.0 -0.1 0.0" rot="3.000000 0.00000 0.000000" scale="0.04 0.14 0.04" support="base" reposition="true"/>
                                  <bone aliases="rHand avatar_mWristRight" connected="true" end="0.000 -0.060 0.000" group="Arms" name="mWristRight" pivot="-0.000000 -0.205000 -0.000000" pos="0.000 -0.205 -0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
                                     <collision_volume end="0.005 -0.049 -0.001" group="Collision" name="R_HAND" pos="0.01 -0.05 0.0" rot="3.000000 0.00000 10.000000" scale="0.05 0.08 0.03" support="base"/>
                                     <bone connected="false" end="-0.001 -0.040 -0.006" group="Hand" name="mHandMiddle1Right" pivot="0.013 -0.101 0.015" pos="0.013 -0.101 0.015" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
@@ -153,19 +153,19 @@
                            </bone>
                         </bone>
                         <bone connected="false" end="-0.061 0.000 0.000" group="Wing" name="mWingsRoot" pivot="-0.014 0.000 0.000" pos="-0.014 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                           <bone connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                              <bone connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                 <bone connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                    <bone connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                           <bone connected="false" end="-0.168 0.169 0.067" group="Wing" name="mWing1Left" pivot="-0.099 0.105 0.181" pos="-0.099 0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                              <bone connected="true" end="-0.181 0.183 0.000" group="Wing" name="mWing2Left" pivot="-0.168 0.169 0.067" pos="-0.168 0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                 <bone connected="true" end="-0.171 0.173 0.000" group="Wing" name="mWing3Left" pivot="-0.181 0.183 0.000" pos="-0.181 0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                    <bone connected="true" end="-0.146 0.132 0.000" group="Wing" name="mWing4Left" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="true" end="-0.068 0.062 -0.159" group="Wing" name="mWing4FanLeft" pivot="-0.171 0.173 0.000" pos="-0.171 0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                  </bone>
                               </bone>
                            </bone>
-                           <bone connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                              <bone connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                 <bone connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                                    <bone connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
-                                    <bone connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                           <bone connected="false" end="-0.168 -0.169 0.067" group="Wing" name="mWing1Right" pivot="-0.099 -0.105 0.181" pos="-0.099 -0.105 0.181" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                              <bone connected="true" end="-0.181 -0.183 0.000" group="Wing" name="mWing2Right" pivot="-0.168 -0.169 0.067" pos="-0.168 -0.169 0.067" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                 <bone connected="true" end="-0.171 -0.173 0.000" group="Wing" name="mWing3Right" pivot="-0.181 -0.183 0.000" pos="-0.181 -0.183 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                                    <bone connected="true" end="-0.146 -0.132 0.000" group="Wing" name="mWing4Right" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
+                                    <bone connected="true" end="-0.068 -0.062 -0.159" group="Wing" name="mWing4FanRight" pivot="-0.171 -0.173 0.000" pos="-0.171 -0.173 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                                  </bone>
                               </bone>
                            </bone>
@@ -176,36 +176,36 @@
             </bone>
          </bone>
       </bone>
-      <bone aliases="rThigh avatar_mHipRight" connected="false" end="-0.001 0.049 -0.491" group="Legs" name="mHipRight" pivot="0.033620 -0.128806 -0.041086" pos="0.034 -0.129 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-         <collision_volume end="0.000 0.000 -0.200" group="Collision" name="R_UPPER_LEG" pos="-0.02 0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32" support="base"/>
+      <bone aliases="rThigh avatar_mHipRight" connected="false" end="-0.001 0.049 -0.491" group="Legs" name="mHipRight" pivot="0.033620 -0.128806 -0.041086" pos="0.034 -0.129 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true">
+         <collision_volume end="0.000 0.000 -0.200" group="Collision" name="R_UPPER_LEG" pos="-0.02 0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32" support="base" reposition="true"/>
          <bone aliases="rShin avatar_mKneeRight" connected="true" end="-0.029 0.000 -0.469" group="Legs" name="mKneeRight" pivot="-0.000780 0.048635 -0.490922" pos="-0.001 0.049 -0.491" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-            <collision_volume end="-0.010 0.000 -0.150" group="Collision" name="R_LOWER_LEG" pos="-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25" support="base"/>
+            <collision_volume end="-0.010 0.000 -0.150" group="Collision" name="R_LOWER_LEG" pos="-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25" support="base" reposition="true"/>
             <bone aliases="rFoot avatar_mAnkleRight" connected="true" end="0.112 0.000 -0.061" group="Legs" name="mAnkleRight" pivot="-0.028869 0.000000 -0.468494" pos="-0.029 0.000 -0.468" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-               <collision_volume end="0.089 0.000 -0.026" group="Collision" name="R_FOOT" pos="0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05" support="base"/>
-               <bone aliases="avatar_mFootRight" connected="true" end="0.105 -0.010 0.000" group="Extra" name="mFootRight" pivot="0.111956 -0.000000 -0.060637" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
+               <collision_volume end="0.089 0.000 -0.026" group="Collision" name="R_FOOT" pos="0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05" support="base" reposition="true"/>
+               <bone aliases="avatar_mFootRight" connected="true" end="0.105 -0.010 0.000" group="Extra" name="mFootRight" pivot="0.111956 -0.000000 -0.060637" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true">
                   <bone aliases="avatar_mToeRight" connected="false" end="0.020 0.000 0.000" group="Extra" name="mToeRight" pivot="0.105399 -0.010408 -0.000104" pos="0.109 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
                </bone>
             </bone>
          </bone>
       </bone>
-      <bone aliases="lThigh avatar_mHipLeft" connected="false" end="-0.001 -0.046 -0.491" group="Legs" name="mHipLeft" pivot="0.033757 0.126765 -0.040998" pos="0.034 0.127 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-         <collision_volume end="0.000 0.000 -0.200" group="Collision" name="L_UPPER_LEG" pos="-0.02 -0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32" support="base"/>
+      <bone aliases="lThigh avatar_mHipLeft" connected="false" end="-0.001 -0.046 -0.491" group="Legs" name="mHipLeft" pivot="0.033757 0.126765 -0.040998" pos="0.034 0.127 -0.041" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true" >
+         <collision_volume end="0.000 0.000 -0.200" group="Collision" name="L_UPPER_LEG" pos="-0.02 -0.05 -0.22" rot="0.000000 0.00000 0.000000" scale="0.09 0.09 0.32" support="base" reposition="true"/>
          <bone aliases="lShin avatar_mKneeLeft" connected="true" end="-0.029 0.001 -0.469" group="Legs" name="mKneeLeft" pivot="-0.000887 -0.045568 -0.491053" pos="-0.001 -0.046 -0.491" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-            <collision_volume end="-0.010 0.000 -0.150" group="Collision" name="L_LOWER_LEG" pos="-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25" support="base"/>
+            <collision_volume end="-0.010 0.000 -0.150" group="Collision" name="L_LOWER_LEG" pos="-0.02 0.0 -0.2" rot="0.000000 0.00000 0.000000" scale="0.06 0.06 0.25" support="base" reposition="true"/>
             <bone aliases="lFoot avatar_mAnkleLeft" connected="true" end="0.112 0.000 -0.061" group="Legs" name="mAnkleLeft" pivot="-0.028887 0.001378 -0.468449" pos="-0.029 0.001 -0.468" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
-               <collision_volume end="0.089 0.000 -0.026" group="Collision" name="L_FOOT" pos="0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05" support="base"/>
-               <bone aliases="avatar_mFootLeft" connected="true" end="0.105 0.008 0.001" group="Extra" name="mFootLeft" pivot="0.111956 -0.000000 -0.060620" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base">
+               <collision_volume end="0.089 0.000 -0.026" group="Collision" name="L_FOOT" pos="0.077 0.0 -0.041" rot="0.000000 10.00000 0.000000" scale="0.13 0.05 0.05" support="base" reposition="true"/>
+               <bone aliases="avatar_mFootLeft" connected="true" end="0.105 0.008 0.001" group="Extra" name="mFootLeft" pivot="0.111956 -0.000000 -0.060620" pos="0.112 -0.000 -0.061" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base" reposition="true">
                   <bone aliases="avatar_mToeLeft" connected="false" end="0.020 0.000 0.000" group="Extra" name="mToeLeft" pivot="0.105387 0.008270 0.000871" pos="0.109 0.000 0.000" rot="0.000000 0.000000 0.000000" scale="1.000 1.000 1.000" support="base"/>
                </bone>
             </bone>
          </bone>
       </bone>
-      <bone connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-         <bone connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-            <bone connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-               <bone connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                  <bone connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                     <bone connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+      <bone connected="false" end="-0.197 0.000 0.000" group="Tail" name="mTail1" pivot="-0.116 0.000 0.047" pos="-0.116 0.000 0.047" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+         <bone connected="true" end="-0.168 0.000 0.000" group="Tail" name="mTail2" pivot="-0.197 0.000 0.000" pos="-0.197 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+            <bone connected="true" end="-0.142 0.000 0.000" group="Tail" name="mTail3" pivot="-0.168 0.000 0.000" pos="-0.168 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+               <bone connected="true" end="-0.112 0.000 0.000" group="Tail" name="mTail4" pivot="-0.142 0.000 0.000" pos="-0.142 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                  <bone connected="true" end="-0.094 0.000 0.000" group="Tail" name="mTail5" pivot="-0.112 0.000 0.000" pos="-0.112 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
+                     <bone connected="true" end="-0.089 0.000 0.000" group="Tail" name="mTail6" pivot="-0.094 0.000 0.000" pos="-0.094 0.000 0.000" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                   </bone>
                </bone>
             </bone>
@@ -213,17 +213,17 @@
       </bone>
       <bone connected="false" end="0.004 0.000 -0.066" group="Groin" name="mGroin" pivot="0.064 0.000 -0.097" pos="0.064 0.000 -0.097" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
       <bone connected="false" end="-0.204 0.000 0.000" group="Limb" name="mHindLimbsRoot" pivot="-0.200 0.000 0.084" pos="-0.200 0.000 0.084" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-         <bone connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
+         <bone connected="false" end="0.002 -0.046 -0.491" group="Limb" name="mHindLimb1Left" pivot="-0.204 0.129 -0.125" pos="-0.204 0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
             <bone connected="true" end="-0.030 -0.003 -0.468" group="Limb" name="mHindLimb2Left" pivot="0.002 -0.046 -0.491" pos="0.002 -0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
                <bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Left" pivot="-0.030 -0.003 -0.468" pos="-0.030 -0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                  <bone connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                  <bone connected="true" end="0.105 0.008 0.000" group="Limb" name="mHindLimb4Left" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                </bone>
             </bone>
          </bone>
-         <bone connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
+         <bone connected="false" end="0.002 0.046 -0.491" group="Limb" name="mHindLimb1Right" pivot="-0.204 -0.129 -0.125" pos="-0.204 -0.129 -0.125" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true">
             <bone connected="true" end="-0.030 0.003 -0.468" group="Limb" name="mHindLimb2Right" pivot="0.002 0.046 -0.491" pos="0.002 0.046 -0.491" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
                <bone connected="true" end="0.112 0.000 -0.061" group="Limb" name="mHindLimb3Right" pivot="-0.030 0.003 -0.468" pos="-0.030 0.003 -0.468" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended">
-                  <bone connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended"/>
+                  <bone connected="true" end="0.105 -0.008 0.000" group="Limb" name="mHindLimb4Right" pivot="0.112 0.000 -0.061" pos="0.112 0.000 -0.061" rot="0.000 0.000 0.000" scale="1.00 1.00 1.00" support="extended" reposition="true"/>
                </bone>
             </bone>
          </bone>
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 6a6077608b9..c0fbc7fd269 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -401,6 +401,16 @@ class LLAgent : public LLOldEvents::LLObservable
 private:
 	LLFrameTimer	mTypingTimer;
 
+	//--------------------------------------------------------------------
+	//BD - Custom Posing
+	//--------------------------------------------------------------------
+public:
+	void			setPosing()				{ mIsPosing = true; }
+	void			clearPosing()			{ mIsPosing = false; }
+	bool			getPosing() const		{ return mIsPosing; }
+
+	bool			mIsPosing;
+
 	//--------------------------------------------------------------------
 	// AFK
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 29e04e5d8c8..725634a1fd8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4754,6 +4754,9 @@ void LLAppViewer::idle()
 			// Handle automatic walking towards points
 			gAgentPilot.updateTarget();
 			gAgent.autoPilot(&yaw);
+
+			//BD - Animator
+			gDragonAnimator.update();
 		}
 
 		static LLFrameTimer agent_update_timer;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index ccd1df31ca4..fd8e0ff54be 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -177,6 +177,7 @@
 #include "llpreviewtexture.h"
 #include "llscriptfloater.h"
 #include "llsyswellwindow.h"
+#include "bdfloaterposer.h"
 
 // *NOTE: Please add files in alphabetical order to keep merges easy.
 // [RLVa:KB] - Checked: 2010-03-11
@@ -420,6 +421,7 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("quick_settings", "floater_quick_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
 	LLFloaterReg::add("region_tracker", "floater_region_tracker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterRegionTracker>);
 	LLFloaterReg::add("sound_explorer", "floater_explore_sounds.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterExploreSounds>);
+	LLFloaterReg::add("poser", "floater_poser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<BDFloaterPoser>);
 	
 	LLFloaterReg::registerControlVariables(); // Make sure visibility and rect controls get preserved when saving
 }
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index a4922dd9211..41afc349b9e 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -1764,6 +1764,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredImpostorProgram.mName = "Deferred Impostor Shader";
+		gDeferredImpostorProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredImpostorProgram.mFeatures.hasGamma = true;
+		gDeferredImpostorProgram.mFeatures.hasTransport = true;
 		gDeferredImpostorProgram.mFeatures.hasSrgb = true;
 		gDeferredImpostorProgram.mFeatures.encodesNormal = true;
 		//gDeferredImpostorProgram.mFeatures.isDeferred = true;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 839ab74e4bb..b93e29b81e2 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -107,6 +107,10 @@
 #include "rlvmodifiers.h"
 // [/RLVa:KB]
 
+//BD
+#include "llfloaterreg.h"
+#include "bdposingmotion.h"
+
 #include "llgesturemgr.h" //needed to trigger the voice gesticulations
 #include "llvoiceclient.h"
 #include "llvoicevisualizer.h" // Ventrella
@@ -148,7 +152,7 @@ const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208
 const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55");  //"target"
 const LLUUID ANIM_AGENT_WALK_ADJUST	= LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d");  //"walk_adjust"
 const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987");  //"physics_motion"
-
+const LLUUID ANIM_BD_POSING_MOTION = LLUUID("fd29b117-9429-09c4-10cb-933d0b2ab653");  //"custom_motion"
 
 //-----------------------------------------------------------------------------
 // Constants
@@ -689,7 +693,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
 	mCachedInBuddyList(false),
     mIsControlAvatar(false),
     mIsUIAvatar(false),
-    mEnableDefaultMotions(true)
+    mEnableDefaultMotions(true),
+    //BD - Custom Posing
+	mIsPosing(false),
+	mExpiryTime(0.0f),
+	mCurrentAction(0)
 {
 	LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
 
@@ -1126,6 +1134,9 @@ void LLVOAvatar::initClass()
 	gAnimLibrary.animStateSetString(ANIM_AGENT_TARGET,"target");
 	gAnimLibrary.animStateSetString(ANIM_AGENT_WALK_ADJUST,"walk_adjust");
 
+	//BD
+	gAnimLibrary.animStateSetString(ANIM_BD_POSING_MOTION, "custom_pose");
+
     // Where should this be set initially?
     LLJoint::setDebugJointNames(gSavedSettings.getString("DebugAvatarJoints"));
 
@@ -1198,6 +1209,9 @@ void LLVOAvatar::initInstance()
 		registerMotion( ANIM_AGENT_SIT_FEMALE,				LLKeyframeMotion::create );
 		registerMotion( ANIM_AGENT_TARGET,					LLTargetingMotion::create );
 		registerMotion( ANIM_AGENT_WALK_ADJUST,				LLWalkAdjustMotion::create );
+
+		//BD - Jackpot.
+		registerMotion(	ANIM_BD_POSING_MOTION,				BDPosingMotion::create);
 	}
 	
 	LLAvatarAppearance::initInstance();
@@ -2088,6 +2102,14 @@ void LLVOAvatar::resetSkeleton(bool reset_animations)
         return;
     }
 
+	//BD - We need to clear posing here otherwise we'll crash.
+	LLMotion* pose_motion = gAgentAvatarp->findMotion(ANIM_BD_POSING_MOTION);
+	if (pose_motion)
+	{
+		gAgent.clearPosing();
+		gAgentAvatarp->removeMotion(ANIM_BD_POSING_MOTION);
+	}
+
     // Save mPelvis state
     //LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition();
     //LLQuaternion pelvis_rot = getJoint("mPelvis")->getRotation();
@@ -6044,7 +6066,13 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
     // keep appearances in sync, but not so often that animations
     // cause constant jiggling of the body or camera. Possible
     // compromise is to do it on animation changes:
+	//BD - Poser
+	//     Don't refresh our root position while we pose otherwise moving any joint that moves
+	//     mFootLeft will trigger mRoot repositioning.
+	if (!(isSelf() && gAgent.getPosing()))
+	{
     computeBodySize();
+	}
     
 	BOOL result = FALSE;
 
@@ -7182,8 +7210,14 @@ void LLVOAvatar::updateVisualParams()
 	LLCharacter::updateVisualParams();
 
 	if (mLastSkeletonSerialNum != mSkeletonSerialNum)
+	{
+		//BD - Poser
+		//     Don't refresh our root position while we pose otherwise moving any joint that moves
+		//     mFootLeft will trigger mRoot repositioning.
+		if (!(isSelf() && gAgent.getPosing()))
 	{
 		computeBodySize();
+		}
 		mLastSkeletonSerialNum = mSkeletonSerialNum;
 		mRoot->updateWorldMatrixChildren();
 	}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index dbf199ce92e..3c699cff7a0 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -55,6 +55,8 @@
 #include "llviewerstats.h"
 #include "llvovolume.h"
 #include "llavatarrendernotifier.h"
+//BD - Poser
+#include "bdanimator.h"
 
 extern const LLUUID ANIM_AGENT_BODY_NOISE;
 extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@@ -67,6 +69,8 @@ extern const LLUUID ANIM_AGENT_HEAD_ROT;
 extern const LLUUID ANIM_AGENT_PELVIS_FIX;
 extern const LLUUID ANIM_AGENT_TARGET;
 extern const LLUUID ANIM_AGENT_WALK_ADJUST;
+//BD
+extern const LLUUID ANIM_BD_POSING_MOTION;
 
 class LLViewerWearable;
 class LLVoiceVisualizer;
@@ -1151,6 +1155,28 @@ class LLVOAvatar :
  **                                                                            **
  *******************************************************************************/
 
+/********************************************************************************
+ **                                                                            **
+ **                    POSER
+ **/
+
+	//--------------------------------------------------------------------
+	//BD - Custom Posing
+	//--------------------------------------------------------------------
+public:
+	void			setPosing()				{ mIsPosing = true; }
+	void			clearPosing()			{ mIsPosing = false; }
+	bool			getPosing()				{ return mIsPosing; }
+	void			clearAnimList()			{ mAnimatorActions.clear(); }
+
+	bool			mIsPosing;
+	S32				getCurrentActionIndex() { return mCurrentAction; }
+
+	std::vector<Action>				mAnimatorActions;
+	LLFrameTimer					mAnimPlayTimer;
+	F32								mExpiryTime;
+	S32								mCurrentAction;
+
 /********************************************************************************
  **                                                                            **
  **                    SUPPORT CLASSES
diff --git a/indra/newview/skins/default/textures/icons/Inv_Shape.png b/indra/newview/skins/default/textures/icons/Inv_Shape.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5db447b36a57dc33b3f0cd5bc03580599adb5c1
GIT binary patch
literal 693
zcmV;m0!safP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0007fNkl<ZIE|%~
zO-NKx7>1v7=g!>mXPSu|n;P*CF$yD)L`{TR7(tMzE$jzdBoqW?i=x`JYh^@4nncj5
zh$x7l2wPaVE0i|<SoxEw<&5S`&NSV7ov(%0%G6Z{&f@UC=i&Rl_Z%f6{Lj)?5>#{7
zNfd2ZsSfV7T?R}MN&oB9Rzxe>Dz>f9$K^f&tOq>H*_H(;r4&}G<3;c21d$I9fB@iD
zN~tAY5kWP!-v`yOCYXgw*Km7WhzQ|=0AnLFD5WsGI<e^=Ohpoqwjc7~%swDBKLhLM
zBht1#H8NwYD+u_N5va*4UZcA`F7iu)d>)M2gMDwiQQ8~;vr~OQ2pFHQKq&*raZ1&T
zPu@MR`K2Kg&c;l6nS3+aJ<`>BQRb{^zyxey28b>IH0Bf0ow*o#%gtz2Re=8fWIAzu
z{~qA8vws3<2V!dgB9aynQ$&)%V|P5YS6|<#-E4rSC@RU)Dlhb$^={k&FbgC^B<c9m
zi&7{&_tfXf$~YX457!S2Onm8m9w9mwC8d%z{_3VfzKVvm|0cKSP*zs9H`|>&9*f0^
z47|V1t=78fS1&KcVsTdG`VVfYKY9Sja#~&t2%mmp47_{2Thpy@VNp5ev(CrBxcRKJ
zy|Abp-5_UdD!$X5TO0!1O8}FfK9(nEC!2<bta#6n(p|uJ;43iMbEGt9Xvm72%HBSg
zUs(-!7arAbfc<UaXfTvPcBXe2NCBfjOhjxT=JN;M1Vb65Gjo~&zmwP>K%k(s#Y|*c
z(QErp0kOX>BO-R>N@Jaw$g~0*Ds};@0Ru<G`O-f3s^C^&E07Dg7Bok9W#nxNJNg#D
bCnEd;RACKkX>F(n00000NkvXXu0mjfFGV+8

literal 0
HcmV?d00001

diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index cf9d25b10bd..0f4f179218e 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -172,6 +172,7 @@ with the same filename but different name
   <texture name="Command_View_Icon"         file_name="toolbar_icons/view.png"         preload="true" />
   <texture name="Command_Voice_Icon"        file_name="toolbar_icons/nearbyvoice.png"  preload="true" />
   <texture name="Command_Webbrowser_Icon"   file_name="toolbar_icons/web.png"          preload="true" />
+  <texture name="Command_Poser_Icon"        file_name="toolbar_icons/poser.png"        preload="true" />
   <texture name="Caret_Top_Icon"            file_name="toolbar_icons/caret_top.png"    preload="true" scale.left="1" scale.top="28" scale.right="15" scale.bottom="5" />
   <texture name="Caret_Bottom_Icon"         file_name="toolbar_icons/caret_bottom.png" preload="true" scale.left="1" scale.top="23" scale.right="15" scale.bottom="1" />
   <texture name="Caret_Right_Icon"          file_name="toolbar_icons/caret_right.png"  preload="true" scale.left="5" scale.top="15" scale.right="28" scale.bottom="1" />
@@ -326,6 +327,7 @@ with the same filename but different name
   <texture name="Inv_Object_Multi" file_name="icons/Inv_Object_Multi.png" preload="false" />
   <texture name="Inv_Pants" file_name="icons/Inv_Pants.png" preload="false" />
   <texture name="Inv_Script" file_name="icons/Inv_Script.png" preload="false" />
+  <texture name="Inv_Shape" file_name="icons/Inv_Shape.png"  preload="false" />
   <texture name="Inv_Shirt" file_name="icons/Inv_Shirt.png" preload="false" />
   <texture name="Inv_Shoe" file_name="icons/Inv_Shoe.png" preload="false" />
   <texture name="Inv_Skin" file_name="icons/Inv_Skin.png" preload="false" />
@@ -772,6 +774,7 @@ with the same filename but different name
   <texture name="cloud-particle.j2c" use_mips="true" />
   <texture name="transparent.j2c" use_mips="true" />
 
+  <texture name="Transparent" file_name="transparent.tga" preload="true" />
   <texture name="Ticker_Grid" file_name="ticker_visualizer_grid.tga" preload="false" />
 
   <!--WARNING OLD ART BELOW *do not use*-->
diff --git a/indra/newview/skins/default/textures/toolbar_icons/poser.png b/indra/newview/skins/default/textures/toolbar_icons/poser.png
new file mode 100644
index 0000000000000000000000000000000000000000..22c3fbba0672816301190af9a916c781c4d65dfa
GIT binary patch
literal 254
zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+0wn(&ce?|mn3BBRT^Rni_n+Ah<Z%{wL>4nJ
za0`PlBg3pY5<o%r5>H=O_J=$YBFuVgU6+Odh59{R978nDCnqQ{87wOLzuF+e*uX$0
zbx*Uqf5Dai*8kuC>30`RRl2n6zZ=gkgLQB9+J3fAH;!@ZFwkq!*yVgcM%0asO*)mW
zxXq%Fjje4uPkX3>kfK0u_q7d1dM=lfH$VO_tI?x=^Pxu9k<P#)4xz5w%5&Zegp^e5
vvoKu~edNG_1CDbJZx=9-5W4ijla*mlvqp)={on6^PGj(N^>bP0l+XkKX!2L^

literal 0
HcmV?d00001

diff --git a/indra/newview/skins/default/textures/transparent.tga b/indra/newview/skins/default/textures/transparent.tga
new file mode 100644
index 0000000000000000000000000000000000000000..49e5d11a21f391e18b563286837733b8990f34b7
GIT binary patch
literal 49
rcmZQz;9`IQMg~R(1rCP)|Np~87(#+VUBf(sJ^lT3BiuZFT=f_Lkxd94

literal 0
HcmV?d00001

diff --git a/indra/newview/skins/default/xui/en/floater_poser.xml b/indra/newview/skins/default/xui/en/floater_poser.xml
new file mode 100644
index 00000000000..a9f96e9c2b6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_poser.xml
@@ -0,0 +1,1390 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+positioning="centered"
+height="431"
+layout="topleft"
+name="floater_poser"
+title="Poser"
+width="678">
+	<!-- Expanded Size 745 -->
+	<!-- Expanded Size 906 -->
+	<panel
+	height="1"
+	visible="false"
+	name="max_panel"
+	width="906"/>
+	<!-- Collapsed Size 517 -->
+	<!-- Collapsed Size 678 -->
+	<panel
+	height="1"
+	visible="false"
+	name="min_panel"
+	width="678"/>
+	<string
+	name="linear_time" translate="false">
+	0.000+
+	</string>
+	<string
+	name="spherical_time" translate="false">
+	0.001 to 1.0
+	</string>
+	<string
+	name="icon_category" translate="false">
+	Inv_Shape
+	</string>
+	<string
+	name="icon_bone" translate="false">
+	Transparent
+	</string>
+	<string
+	name="icon_object" translate="false">
+	Inv_Object
+	</string>
+	<string
+	name="title_mPelvis" translate="false">
+	Main Body
+	</string>
+	<string
+	name="title_mHead" translate="false">
+	Head
+	</string>
+	<string
+	name="title_mCollarLeft" translate="false">
+	Left Arm
+	</string>
+	<string
+	name="title_mCollarRight" translate="false">
+	Right Arm
+	</string>
+	<string
+	name="title_mWingsRoot" translate="false">
+	Back
+	</string>
+	<string
+	name="title_mHipLeft" translate="false">
+	Left Leg
+	</string>
+	<string
+	name="title_mHipRight" translate="false">
+	Right Leg
+	</string>
+	<string
+	name="title_mTail1" translate="false">
+	Tail
+	</string>
+	<string
+	name="title_mGroin" translate="false">
+	Misc
+	</string>
+	
+	<layout_stack
+	follows="top|left|right"
+	height="425"
+	layout="topleft"
+	left="7"
+	border_size="-4"
+	close_time_constant="0.02"
+	open_time_constant="0.02"
+	mouse_opaque="false"
+	name="poser_stack"
+	orientation="horizontal"
+	top="0"
+	width="666">
+		<layout_panel
+		follows="top|left|right"
+		layout="topleft"
+		height="420"
+		auto_resize="false"
+		visible="true"
+		name="poser_layout"
+		width="162">
+			<panel
+			follows="left|top|bottom"
+			height="420"
+			background_visible="false"
+			layout="topleft"
+			mouse_opaque="false"
+			left="0"
+			name="title"
+			top="0"
+			width="163">
+				<scroll_list
+				column_padding="0"
+				draw_heading="true"
+				height="279"
+				can_sort="false"
+				follows="left|top|right"
+				layout="topleft"
+				left="1"
+				tool_tip="Select the targeted avatar or animesh."
+				width="154"
+				multi_select="false"
+				name="avatar_scroll"
+				top="20">
+				<scroll_list.columns
+				label=""
+				name="icon"
+				relative_width="0.14"  />
+				<scroll_list.columns
+				label="Name"
+				name="name"
+				relative_width="0.86"  />
+				<scroll_list.columns
+				label="UUID"
+				name="uuid"
+				relative_width="0.0"  />
+				</scroll_list>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				label="Refresh Avatars"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="refresh"
+				width="151"
+				top_pad="-1"
+				left="2">
+				<button.commit_callback
+				function="Poser.RefreshAvatars"/>
+				</button>
+				<check_box
+				height="16"
+				initial_value="false"
+				label="Mirror Changes"
+				tool_tip="This option toggles whether all changes to rotations should be mirrored to the opposide side's bone as well. Left Arm will mirror to Right Arm and so on."
+				layout="topleft"
+				left="5"
+				name="Mirror"
+				top_pad="4"
+				width="115">
+				<check_box.commit_callback
+                    function="Joint.ToggleMirror"/>
+				</check_box>
+				<check_box
+				height="16"
+				initial_value="true"
+				label="Easy Rotations"
+				tool_tip="This option toggles whether the poser should display and use simplified rotation axis. This essentially means that when moving any axis, all other axis stay untouched, this can bring the rotations out of place so that 0 0 0 no longer is the default resting position depending on in which order bones were moved. Disabling this option will allow the other axis to be dynamically changed to represent the actual rotations which means sliders you are not touching will change with the slider you are currently moving. This is disabled by default as it may look confusing to the user. It is highly recommended that if you use this you start zeroing out Z then Y and lastly X in this order, otherwise you will not be able to zero out all axis unless you reset the bone rotation."
+				layout="topleft"
+				left="5"
+				name="EasyRotations"
+				top_pad="1"
+				width="115">
+				<check_box.commit_callback
+                    function="Joint.EasyRotations"/>
+				</check_box>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				enabled="true"
+				label="Mirror Pose"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="flip_pose"
+				width="151"
+				top_pad="40"
+				left="2">
+				<button.commit_callback
+				function="Joint.FlipPose"/>
+				</button>
+			</panel>
+		</layout_panel>
+		<layout_panel
+		follows="top|left|right"
+		layout="topleft"
+		height="420"
+		auto_resize="false"
+		visible="true"
+		name="poser_layout"
+		width="490">
+			<panel
+			follows="left|top|bottom"
+			height="420"
+			background_visible="false"
+			layout="topleft"
+			mouse_opaque="false"
+			left="0"
+			name="title"
+			top="0"
+			width="485">
+				<tab_container
+				follows="all"
+				halign="center"
+				height="299"
+				layout="topleft"
+				left="0"
+				enabled="false"
+				name="joints_tabs"
+				tab_height="20"
+				tab_group="1"
+				tab_position="top"
+				top="0"
+				width="483">
+					<panel
+					follows="all"
+					background_visible="false"
+					height="299"
+					layout="topleft"
+					left="0"
+					title="Skeleton"
+					name="joints_panel"
+					top="0"
+					width="481">
+						<scroll_list
+						column_padding="2"
+						draw_heading="true"
+						height="279"
+						follows="left|top|right"
+						can_sort="false"
+						layout="topleft"
+						left="2"
+						width="479"
+						multi_select="true"
+						name="joints_scroll"
+						top="0">
+						<scroll_list.columns
+						label=""
+						name="icon"
+						relative_width="0.04"  />
+						<scroll_list.columns
+						label="Bone Name"
+						name="joint"
+						relative_width="0.33"  />
+						<scroll_list.columns
+						label="Rot X"
+						name="x"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Rot Y"
+						name="y"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Rot Z"
+						name="z"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos X"
+						name="pos_x"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos Y"
+						name="pos_y"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos Z"
+						name="pos_z"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size X"
+						name="scale_x"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Size Y"
+						name="scale_y"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Size Z"
+						name="scale_z"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="#"
+						name="number"
+						relative_width="0.00"  />
+						</scroll_list>
+					</panel>
+					<panel
+					follows="all"
+					background_visible="false"
+					height="299"
+					layout="topleft"
+					left="0"
+					title="Collision Volumes"
+					name="cv_panel"
+					top="0"
+					width="481">
+						<scroll_list
+						column_padding="2"
+						draw_heading="true"
+						height="279"
+						follows="left|top|right"
+						layout="topleft"
+						can_sort="false"
+						left="2"
+						width="478"
+						multi_select="true"
+						name="cv_scroll"
+						top="0">
+						<scroll_list.columns
+						label=""
+						name="icon"
+						relative_width="0.04"  />
+						<scroll_list.columns
+						label="Collision Volume Name"
+						name="joint"
+						relative_width="0.33"  />
+						<scroll_list.columns
+						label="Rot X"
+						name="x"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Rot Y"
+						name="y"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Rot Z"
+						name="z"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Pos X"
+						name="pos_x"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos Y"
+						name="pos_y"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos Z"
+						name="pos_z"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size X"
+						name="scale_x"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size Y"
+						name="scale_y"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size Z"
+						name="scale_z"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="#"
+						name="number"
+						relative_width="0.00"  />
+						</scroll_list>
+					</panel>
+					<panel
+					follows="all"
+					background_visible="false"
+					height="299"
+					layout="topleft"
+					left="0"
+					title="Attachment Bones"
+					name="attach_panel"
+					top="0"
+					width="481">
+						<scroll_list
+						column_padding="2"
+						draw_heading="true"
+						height="279"
+						follows="left|top|right"
+						layout="topleft"
+						can_sort="false"
+						left="2"
+						width="478"
+						multi_select="true"
+						name="attach_scroll"
+						top="0">
+						<scroll_list.columns
+						label=""
+						name="icon"
+						relative_width="0.04"  />
+						<scroll_list.columns
+						label="Attachment Bone Name"
+						name="joint"
+						relative_width="0.33"  />
+						<scroll_list.columns
+						label="Rot X"
+						name="x"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Rot Y"
+						name="y"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Rot Z"
+						name="z"
+						relative_width="0.0"  />
+						<scroll_list.columns
+						label="Pos X"
+						name="pos_x"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos Y"
+						name="pos_y"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Pos Z"
+						name="pos_z"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size X"
+						name="scale_x"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size Y"
+						name="scale_y"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="Size Z"
+						name="scale_z"
+						relative_width="0.10"  />
+						<scroll_list.columns
+						label="#"
+						name="number"
+						relative_width="0.00"  />
+						</scroll_list>
+					</panel>
+				</tab_container>
+				<button
+				height="21"
+				follows="top|left"
+				is_toggle="true"
+				layout="topleft"
+				label="Start Posing"
+				label_selected="Stop Posing"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				button_flash_enable="true"
+				flash_color="0.7 0.7 1 1"
+				button_flash_count="64"
+				button_flash_rate="0.5"
+				name="activate"
+				width="100"
+				top_pad="-1"
+				left="4">
+				<button.commit_callback
+				function="Pose.Start"/>
+				</button>
+				<line_editor
+				commit_on_focus_lost="false"
+				follows="left|top"
+				height="20"
+				label="Enter Pose Name"
+				left_pad="1"
+				enabled="false"
+				top_delta="0"
+				name="pose_name"
+				width="157"/>
+				<line_editor
+				commit_on_focus_lost="false"
+				follows="left|top"
+				height="20"
+				enabled="false"
+				label="0.001 - 1.0"
+				left_pad="1"
+				top_delta="0"
+				name="interpolation_time"
+				width="78"/>
+				<combo_box
+				follows="left|top"
+				height="21"
+				enabled="false"
+				layout="topleft"
+				left_pad="1"
+				top_delta="0"
+				max_chars="135"
+				name="interpolation_type"
+				width="86">
+				<combo_box.item
+				enabled="true"
+				label="None"
+				name="0"
+				value="0" />
+				<combo_box.item
+				enabled="true"
+				label="Linear"
+				name="1"
+				value="1" />
+				<combo_box.item
+				enabled="true"
+				label="Spherical Linear"
+				name="2"
+				value="2" />
+				<combo_box.commit_callback
+				function="Pose.Interpolation"/>
+				</combo_box>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				enabled="false"
+				image_overlay="Icon_Dock_Foreground"
+				image_overlay_alignment="right"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				tool_tip="Save the current pose."
+				name="save_poses"
+				width="25"
+				top_delta="0"
+				left_pad="1">
+				<button.commit_callback
+				function="Pose.Save"/>
+				</button>
+				<button
+				follows="left|top"
+				height="21"
+				is_toggle="true"
+				layout="topleft"
+				image_overlay="Hierarchy_View_On"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="extend"
+				left_pad="1"
+				top_delta="0"
+				width="25" >
+				<button.commit_callback
+				function="Pose.Layout"/>
+				</button>
+				<tab_container
+				follows="all"
+				halign="center"
+				height="95"
+				layout="topleft"
+				left="2"
+				name="modifier_tabs"
+				enabled="false"
+				tab_height="20"
+				tab_group="1"
+				tab_position="top"
+				top_pad="4"
+				width="481">
+					<panel
+					follows="all"
+					background_visible="false"
+					height="95"
+					layout="topleft"
+					left="0"
+					title="Rotation"
+					name="rotation_panel"
+					top="0"
+					width="622">
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Rotation X:"
+						label_width="70"
+						layout="topleft"
+						left="10"
+						max_val="3.142"
+						min_val="-3.142"
+						name="Rotation_X"
+						top_pad="6"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.Set"
+						parameter="0"/>
+						</slider>
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Rotation Y:"
+						label_width="70"
+						layout="topleft"
+						left="10"
+						max_val="3.142"
+						min_val="-3.142"
+						name="Rotation_Y"
+						top_pad="1"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.Set"
+						parameter="1"/>
+						</slider>
+						<slider
+						decimal_digits="3"
+						visible="true"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Rotation Z:"
+						label_width="70"
+						layout="topleft"
+						left="10"
+						max_val="3.142"
+						min_val="-3.142"
+						name="Rotation_Z"
+						top_pad="1"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.Set"
+						parameter="2"/>
+						</slider>
+						<panel
+						follows="top|left|right"
+						height="21"
+						background_visible="false"
+						layout="topleft"
+						mouse_opaque="false"
+						left="0"
+						name="title"
+						top_pad="6"
+						width="480">
+							<button
+							height="21"
+							follows="top|left"
+							layout="topleft"
+							enabled="true"
+							label="Reset Selected Rotation(s)"
+							label_selected="Disable Selected Bone(s)"
+							image_hover_unselected="Toolbar_Middle_Over"
+							image_selected="Toolbar_Middle_Selected"
+							image_unselected="Toolbar_Middle_Off"
+							name="reset_bone_rot"
+							width="238"
+							top="0"
+							left_delta="2">
+							<button.commit_callback
+							function="Joint.ResetJointRotation"/>
+							</button>
+						</panel>
+					</panel>
+					<panel
+					follows="all"
+					background_visible="false"
+					height="95"
+					layout="topleft"
+					left="0"
+					title="Position"
+					name="position_panel"
+					top="0"
+					width="622">
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Position X:"
+						label_width="70"
+						layout="topleft"
+						left="10"
+						max_val="0.5"
+						min_val="-0.5"
+						name="Position_X"
+						top_pad="6"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.PosSet"
+						parameter="0"/>
+						</slider>
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Position Y:"
+						label_width="70"
+						layout="topleft"
+						left_delta="0"
+						max_val="0.5"
+						min_val="-0.5"
+						name="Position_Y"
+						top_pad="1"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.PosSet"
+						parameter="1"/>
+						</slider>
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Position Z:"
+						label_width="70"
+						layout="topleft"
+						left_delta="0"
+						max_val="0.5"
+						min_val="-0.5"
+						name="Position_Z"
+						top_pad="1"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.PosSet"
+						parameter="2"/>
+						</slider>
+						<panel
+						follows="top|left|right"
+						height="21"
+						background_visible="false"
+						layout="topleft"
+						mouse_opaque="false"
+						left="0"
+						name="title"
+						top_pad="6"
+						width="480">
+							<button
+							height="21"
+							follows="top|left"
+							layout="topleft"
+							enabled="true"
+							label="Reset Selected Position(s)"
+							label_selected="Disable Selected Bone(s)"
+							image_hover_unselected="Toolbar_Middle_Over"
+							image_selected="Toolbar_Middle_Selected"
+							image_unselected="Toolbar_Middle_Off"
+							name="reset_bone_pos"
+							width="238"
+							top="0"
+							left_delta="2">
+							<button.commit_callback
+							function="Joint.ResetJointPosition"/>
+							</button>
+						</panel>
+					</panel>
+					<panel
+					follows="all"
+					background_visible="false"
+					height="95"
+					layout="topleft"
+					left="0"
+					title="Scale"
+					name="scale_panel"
+					top="0"
+					width="622">
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Scale X:"
+						label_width="70"
+						layout="topleft"
+						left="10"
+						max_val="2"
+						min_val="0"
+						name="Scale_X"
+						top_pad="6"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.SetScale"
+						parameter="0"/>
+						</slider>
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Scale Y:"
+						label_width="70"
+						layout="topleft"
+						left_delta="0"
+						max_val="2"
+						min_val="0"
+						name="Scale_Y"
+						top_pad="1"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.SetScale"
+						parameter="1"/>
+						</slider>
+						<slider
+						decimal_digits="3"
+						can_edit_text="true"
+						follows="left|top"
+						height="14"
+						increment="0.001"
+						initial_value="0"
+						label="Scale Z:"
+						label_width="70"
+						layout="topleft"
+						left_delta="0"
+						max_val="2"
+						min_val="0"
+						name="Scale_Z"
+						top_pad="1"
+						width="459" >
+						<slider.commit_callback
+						function="Joint.SetScale"
+						parameter="2"/>
+						</slider>
+						<panel
+						follows="top|left|right"
+						height="21"
+						background_visible="false"
+						layout="topleft"
+						mouse_opaque="false"
+						left="0"
+						name="title"
+						top_pad="6"
+						width="480">
+							<button
+							height="21"
+							follows="top|left"
+							layout="topleft"
+							enabled="true"
+							label="Reset Selected Scale(s)"
+							label_selected="Disable Selected Bone(s)"
+							image_hover_unselected="Toolbar_Middle_Over"
+							image_selected="Toolbar_Middle_Selected"
+							image_unselected="Toolbar_Middle_Off"
+							name="reset_bone_scale"
+							width="238"
+							top="0"
+							left_delta="2">
+							<button.commit_callback
+							function="Joint.ResetJointScale"/>
+							</button>
+						</panel>
+					</panel>
+				</tab_container>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				is_toggle="true"
+				enabled="false"
+				label="Activate Selected Bone(s)"
+				label_selected="Disable Selected Bone(s)"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="toggle_bone"
+				width="237"
+				top_pad="-19"
+				left_delta="242">
+				<button.commit_callback
+				function="Joint.ChangeState"/>
+				</button>
+			</panel>
+		</layout_panel>
+		<layout_panel
+		follows="top|left|right"
+		layout="topleft"
+		height="420"
+		visible="false"
+		auto_resize="false"
+		name="poses_layout"
+		width="233">
+			<panel
+			follows="top|left|bottom"
+			height="420"
+			background_visible="false"
+			layout="topleft"
+			mouse_opaque="false"
+			left="2"
+			name="poses_panel"
+			top="0"
+			width="225">
+				<scroll_list
+				column_padding="0"
+				draw_heading="true"
+				height="402"
+				follows="left|top|right"
+				layout="topleft"
+				left="0"
+				tool_tip="Change the interpolation type for the currently selected pose."
+				width="225"
+				multi_select="true"
+				name="poses_scroll"
+				top="0">
+				<scroll_list.columns
+				label="Pose Name"
+				name="name"
+				relative_width="0.66"/>
+				<scroll_list.columns
+				label="Time"
+				name="time"
+				relative_width="0.17"  />
+				<scroll_list.columns
+				label="Type"
+				name="type"
+				relative_width="0.15"  />
+				</scroll_list>
+				<menu_button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				enabled="false"
+				tool_tip="Load the currently selected pose and apply all bone rotations saved in it."
+				image_overlay="Icon_Undock_Foreground"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				menu_filename="menu_poser_poses.xml"
+                menu_position="topright"
+				name="load_poses"
+				width="25"
+				top_pad="-1"
+				left_delta="2"/>
+				<line_editor
+				commit_on_focus_lost="true"
+				follows="left|top"
+				height="20"
+				enabled="false"
+				label="0.001 - 1.0"
+				tool_tip="Change the interpolation time of the currently selected pose."
+				left_pad="1"
+				top_delta="0"
+				name="interp_time"
+				width="79">
+				<line_editor.commit_callback
+				function="Pose.Set"
+				parameter="time"/>
+				</line_editor>
+				<combo_box
+				follows="left|top"
+				height="21"
+				enabled="false"
+				layout="topleft"
+				left_pad="1"
+				top_delta="0"
+				max_chars="135"
+				name="interp_type"
+				width="87">
+				<combo_box.combo_button
+				image_unselected="ToolbarDropDown_Off"
+				image_selected="ToolbarDropDown_Press"
+				image_disabled="ToolbarDropDown_Off" />
+				<combo_box.drop_down_button
+				image_unselected="ToolbarDropDown_Off"
+				image_selected="ToolbarDropDown_Press"
+				image_pressed="ToolbarDropDown_Press" 
+				image_pressed_selected="ToolbarDropDown_Press"
+				image_disabled="ToolbarDropDown_Off" />
+				<combo_box.item
+				enabled="true"
+				label="None"
+				name="0"
+				value="0" />
+				<combo_box.item
+				enabled="true"
+				label="Linear"
+				name="1"
+				value="1" />
+				<combo_box.item
+				enabled="true"
+				label="Spherical Linear"
+				name="2"
+				value="2" />
+				<combo_box.commit_callback
+				function="Pose.Set"
+				parameter="type"/>
+				</combo_box>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				enabled="false"
+				tool_tip="Delete the currently selected pose."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="TrashItem_Off"
+				name="delete_poses"
+				width="27"
+				top_delta="0"
+				left_pad="1">
+				<button.commit_callback
+				function="Pose.Delete"/>
+				</button>
+			</panel>
+		</layout_panel>
+		<layout_panel
+		follows="top|left|right"
+		layout="topleft"
+		height="420"
+		visible="false"
+		auto_resize="false"
+		name="animator_layout"
+		width="261">
+			<panel
+			follows="top|left|bottom"
+			height="420"
+			background_visible="false"
+			layout="topleft"
+			mouse_opaque="false"
+			visible="true"
+			left="0"
+			name="animator_panel"
+			top="0"
+			width="260">
+				<button
+				height="31"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				tool_tip="Add the currently selected pose below the currently selected entry in the animation queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="Arrow_Right"
+				name="add_entry"
+				enabled="false"
+				width="26"
+				top="130"
+				left="0">
+				<button.commit_callback
+				function="Anim.Add"/>
+				</button>
+				<button
+				height="26"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				tool_tip="Add a configurable wait event below the currently selected entry in the animation queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="Conv_toolbar_call_log"
+				name="add_wait"
+				width="26"
+				top_pad="1"
+				left_delta="0">
+				<button.commit_callback
+				function="Anim.Add"
+				parameter="Wait"/>
+				</button>
+				<button
+				height="26"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				tool_tip="Add a repeat event below the currently selected entry in the animation queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="Refresh_Off"
+				name="add_repeat"
+				width="26"
+				top_pad="1"
+				left_delta="0">
+				<button.commit_callback
+				function="Anim.Add"
+				parameter="Repeat"/>
+				</button>
+				<button
+				height="31"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				tool_tip="Delete the currently selected entry in the animation queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="Arrow_Left"
+				name="delete_entry"
+				enabled="false"
+				width="26"
+				top_pad="1"
+				left_delta="0">
+				<button.commit_callback
+				function="Anim.Delete"/>
+				</button>
+				<button
+				height="26"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				enabled="false"
+				tool_tip="Move the currently selected entry one row up in the queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="Arrow_Up"
+				name="move_up"
+				width="26"
+				top_pad="6"
+				left_delta="0">
+				<button.commit_callback
+				function="Anim.Move"
+				parameter="Up"/>
+				</button>
+				<button
+				height="26"
+				follows="top|left"
+				layout="topleft"
+				label=""
+				enabled="false"
+				tool_tip="Move the currently selected entry one row down in the queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				image_overlay="Arrow_Down"
+				name="move_down"
+				width="26"
+				top_pad="1"
+				left_delta="0">
+				<button.commit_callback
+				function="Anim.Move"
+				parameter="Down"/>
+				</button>
+				<panel
+				follows="left|top|right"
+				height="20"
+				bg_visible="true"
+				bg_alpha_color="0.10 0.43 0.77 0.28"
+				layout="topleft"
+				mouse_opaque="false"
+				left_pad="3"
+				name="title"
+				top="0"
+				width="219"/>
+				<text
+				name="first_person_label"
+				follows="left|top"
+				layout="topleft"
+				left_delta="8"
+				height="12"
+				width="350"
+				top_delta="4">
+				Animation Queue:
+				</text>
+				<scroll_list
+				column_padding="2"
+				draw_heading="true"
+				height="379"
+				follows="left|top|right"
+				layout="topleft"
+				can_sort="false"
+				left_delta="-10"
+				width="223"
+				multi_select="true"
+				name="anim_editor_scroll"
+				top_pad="3">
+				<scroll_list.columns
+				label="Action"
+				name="name"
+				relative_width="0.75"/>
+				<scroll_list.columns
+				label="Time"
+				name="time"
+				relative_width="0.25"  />
+				<scroll_list.columns
+				label="Type"
+				name="type"
+				relative_width="0.0"  />
+				</scroll_list>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				label="Play"
+				enabled="false"
+				tool_tip="Start playing the animation queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="play_anim"
+				width="43"
+				top_pad="1"
+				left_delta="2">
+				<button.commit_callback
+				function="Anim.Play"/>
+				</button>
+				<button
+				height="21"
+				follows="top|left"
+				layout="topleft"
+				label="Stop"
+				enabled="false"
+				tool_tip="Stop playing the animation queue."
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="stop_anim"
+				width="43"
+				top_delta="0"
+				left_pad="1">
+				<button.commit_callback
+				function="Anim.Stop"/>
+				</button>
+				<icon
+				follows="left|top|right"
+				image_name="Toolbar_Middle_Off"
+				height="21"
+				width="68"
+				layout="topleft"
+				left_pad="1"
+				top_delta="0"/>
+				<line_editor
+				commit_on_focus_lost="true"
+				follows="left|top"
+				height="20"
+				label="Wait time"
+				tool_tip="Change the time for the wait event."
+				enabled="false"
+				left_pad="1"
+				top_delta="0"
+				name="anim_time"
+				width="62">
+				<line_editor.commit_callback
+				function="Anim.Set"/>
+				</line_editor>
+			</panel>
+		</layout_panel>
+		<layout_panel
+		follows="top|left|right"
+		layout="topleft"
+		height="420"
+		auto_resize="false"
+		visible="true"
+		name="animator_btn_layout"
+		width="30">
+			<panel
+			follows="left|top|bottom"
+			height="420"
+			background_visible="false"
+			layout="topleft"
+			mouse_opaque="false"
+			left="1"
+			name="title"
+			top="0"
+			width="20">
+				<button
+				follows="left|top"
+				height="423"
+				is_toggle="true"
+				layout="topleft"
+				image_overlay="Command_Poser_Icon"
+				image_overlay_color="1 1 1 0.6"
+				image_bottom_pad="1"
+				image_hover_unselected="Toolbar_Middle_Over"
+				image_selected="Toolbar_Middle_Selected"
+				image_unselected="Toolbar_Middle_Off"
+				name="animator"
+				left="1"
+				top="0"
+				width="18" >
+				<button.commit_callback
+				function="Pose.Layout"/>
+				</button>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+	
+	<!--<multi_slider
+	can_edit_text="false"
+	decimal_digits="0"
+	follows="bottom"
+	height="10"
+	increment="0.1"
+	initial_value="0"
+	layout="topleft"
+	left_delta="0"
+	max_sliders="120"
+	max_val="30"
+	min_val="25"
+	name="key_slider"
+	show_text="false"
+	top_pad="3"
+	width="475" />
+	<line_editor
+	commit_on_focus_lost="true"
+	follows="left|top"
+	height="20"
+	label=""
+	enabled="true"
+	left_pad="1"
+	top_delta="0"
+	name="time"
+	width="62">
+	<line_editor.commit_callback
+	function="Anim.Edit"/>
+	</line_editor>-->
+	
+	
+	<!--<multi_slider
+	can_edit_text="true"
+	decimal_digits="0"
+	draw_track="false"
+	follows="bottom"
+	height="10"
+	increment="0.1"
+	initial_value="0"
+	layout="topleft"
+	left="10"
+	max_sliders="60"
+	max_val="60"
+	name="time_slider"
+	show_text="false"
+	top_pad="5"
+	use_triangle="true"
+	width="475" >
+	<multi_slider.commit_callback
+	function="Anim.SetValue"/>
+	</multi_slider>
+	<multi_slider
+	can_edit_text="true"
+	decimal_digits="0"
+	follows="bottom"
+	height="10"
+	increment="0.1"
+	initial_value="0"
+	layout="topleft"
+	left_delta="0"
+	max_sliders="60"
+	max_val="60"
+	name="key_slider"
+	show_text="true"
+	top_pad="0"
+	width="475" />
+	<button
+	height="23"
+	label=" + "
+	label_selected="Add Key"
+	image_hover_unselected="Toolbar_Middle_Over"
+	image_selected="Toolbar_Middle_Selected"
+	image_unselected="Toolbar_Middle_Off"
+	layout="topleft"
+	left_pad="0"
+	name="add_key"
+	top_delta="-20"
+	width="26" />
+	<button
+	height="23"
+	label=" - "
+	label_selected="Delete Key"
+	image_hover_unselected="Toolbar_Middle_Over"
+	image_selected="Toolbar_Middle_Selected"
+	image_unselected="Toolbar_Middle_Off"
+	layout="topleft"
+	name="delete_key"
+	top_pad="0"
+	width="26" />
+	<line_editor
+	commit_on_focus_lost="true"
+	follows="left|top"
+	height="20"
+	label="Wait time"
+	tool_tip="Change the time for the wait event."
+	enabled="true"
+	left_pad="1"
+	top_delta="0"
+	name="time"
+	width="62">
+	<line_editor.commit_callback
+	function="Anim.SetValue"/>
+	</line_editor>-->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_poser_poses.xml b/indra/newview/skins/default/xui/en/menu_poser_poses.xml
new file mode 100644
index 00000000000..17373f0c699
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_poser_poses.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ layout="topleft"
+ name="Settings">
+    <menu_item_call
+     label="Load Rotations only"
+     layout="topleft"
+     name="rotations">
+        <on_click function="Pose.Menu" parameter="rotation"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Load Positions only"
+     layout="topleft"
+     name="positions">
+        <on_click function="Pose.Menu" parameter="position"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Load Scales only"
+     layout="topleft"
+     name="scale">
+        <on_click function="Pose.Menu" parameter="scale"/>
+    </menu_item_call>
+    <menu_item_separator
+     layout="topleft" />
+    <menu_item_call
+     label="Load Rotations &amp; Positions"
+     layout="topleft"
+     name="rotations">
+        <on_click function="Pose.Menu" parameter="rot_pos"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Load Rotations &amp; Scales"
+     layout="topleft"
+     name="rotations">
+        <on_click function="Pose.Menu" parameter="rot_scale"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Load Position &amp; Scales"
+     layout="topleft"
+     name="rotations">
+        <on_click function="Pose.Menu" parameter="pos_scale"/>
+    </menu_item_call>
+    <menu_item_separator
+     layout="topleft" />
+    <menu_item_call
+     label="Load all"
+     layout="topleft"
+     name="rotations">
+        <on_click function="Pose.Menu" parameter="all"/>
+    </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index e34d6f5624f..41015bed8b4 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -680,6 +680,17 @@
      label="World"
      name="World"
      tear_off="true">
+		<menu_item_check
+         label="Poser"
+         name="Poser"
+         use_mac_ctrl="true">
+			<menu_item_check.on_check
+             function="Floater.Visible"
+             parameter="poser" />
+			<menu_item_check.on_click
+             function="Floater.Toggle"
+             parameter="poser" />
+		</menu_item_check>
         <menu_item_call
          label="Resync Animations"
          name="Resync Animations"
-- 
GitLab