From 18e1aead704e0605ceefb9e47db9acdb4c40928e Mon Sep 17 00:00:00 2001
From: McCabe Maxsted
Date: Sun, 6 Sep 2009 21:51:06 -0700
Subject: Added Emerald viewer's animation list

---
 linden/indra/newview/CMakeLists.txt                |   3 +
 linden/indra/newview/jcfloater_animation_list.cpp  | 462 +++++++++++++++++++++
 linden/indra/newview/jcfloater_animation_list.h    |  88 ++++
 linden/indra/newview/llviewermenu.cpp              |   6 +
 .../default/xui/en-us/floater_animation_list.xml   |  74 ++++
 .../skins/default/xui/en-us/menu_viewer.xml        |   4 +
 6 files changed, 637 insertions(+)
 create mode 100644 linden/indra/newview/jcfloater_animation_list.cpp
 create mode 100644 linden/indra/newview/jcfloater_animation_list.h
 create mode 100644 linden/indra/newview/skins/default/xui/en-us/floater_animation_list.xml

(limited to 'linden/indra')

diff --git a/linden/indra/newview/CMakeLists.txt b/linden/indra/newview/CMakeLists.txt
index fee4d4d..5a83624 100644
--- a/linden/indra/newview/CMakeLists.txt
+++ b/linden/indra/newview/CMakeLists.txt
@@ -61,6 +61,7 @@ include_directories(
     )
 
 set(viewer_SOURCE_FILES
+	jcfloater_animation_list.cpp
     llagent.cpp
     llagentdata.cpp
     llagentlanguage.cpp
@@ -454,6 +455,7 @@ set(viewer_HEADER_FILES
     CMakeLists.txt
     ViewerInstall.cmake
 
+	jcfloater_animation_list.h
     llagent.h
     llagentdata.h
     llagentlanguage.h
@@ -1023,6 +1025,7 @@ set(viewer_XUI_FILES
     skins/default/xui/en-us/floater_about_land.xml
     skins/default/xui/en-us/floater_about.xml
     skins/default/xui/en-us/floater_active_speakers.xml
+    skins/default/xui/en-us/floater_animation_list.xml
     skins/default/xui/en-us/floater_animation_preview.xml
     skins/default/xui/en-us/floater_auction.xml
     skins/default/xui/en-us/floater_audio_volume.xml
diff --git a/linden/indra/newview/jcfloater_animation_list.cpp b/linden/indra/newview/jcfloater_animation_list.cpp
new file mode 100644
index 0000000..d913292
--- /dev/null
+++ b/linden/indra/newview/jcfloater_animation_list.cpp
@@ -0,0 +1,462 @@
+/* Copyright (c) 2009
+ *
+ * Modular Systems Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Neither the name Modular Systems Ltd nor the names of its contributors
+ *      may be used to endorse or promote products derived from this
+ *      software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS LTD AND CONTRIBUTORS �AS IS�
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lluuid.h"
+#include "lluictrlfactory.h"
+#include "llvoavatar.h"
+
+#include "llagent.h"
+
+#include "llscrolllistctrl.h"
+
+#include "llviewerobjectlist.h"
+
+#include "jcfloater_animation_list.h"
+
+#include "llviewercontrol.h"
+
+#include "llinventorymodel.h"
+
+#include "llcategory.h"
+
+#include "llfloaterchat.h"
+
+#include "llfloateravatarinfo.h"
+
+
+
+
+
+//std::map<LLUUID, AObjectData>	JCFloaterAnimList::mObjectOwners;
+
+JCFloaterAnimList::JCFloaterAnimList(const LLSD& seed) : 
+	LLFloater(std::string("animation list")),
+	mAnimList(0)
+{
+	BOOL no_open = FALSE;
+	LLUICtrlFactory::getInstance()->buildFloater(this, "floater_animation_list.xml",&getFactoryMap(),no_open);
+}
+
+JCFloaterAnimList::~JCFloaterAnimList()
+{
+}
+
+//static 
+bool JCFloaterAnimList::visible(LLFloater* instance, const LLSD& key)
+{
+	return VisibilityPolicy<LLFloater>::visible(instance, key);
+}
+
+//static 
+void JCFloaterAnimList::show(LLFloater* instance, const LLSD& key)
+{
+	VisibilityPolicy<LLFloater>::show(instance, key);
+}
+
+//static 
+void JCFloaterAnimList::hide(LLFloater* instance, const LLSD& key)
+{
+	VisibilityPolicy<LLFloater>::hide(instance, key);
+}
+
+void JCFloaterAnimList::onVisibilityChange(BOOL new_visibility)
+{
+	if(!new_visibility) {
+		// *HACK: clean up memory on hiding
+		mObjectOwners.clear();
+	}
+}
+
+BOOL JCFloaterAnimList::postBuild()
+{
+	mAnimList = getChild<LLScrollListCtrl>("animation_list");
+	mAnimList->setCallbackUserData(this);
+	mAnimList->setDoubleClickCallback(onDoubleClick);
+	mAnimList->sortByColumn("animation_uuid", TRUE);
+
+	childSetAction("Stop Selected",StopSelected,this);
+	childSetAction("Revoke Selected",RevokeSelected,this);
+	childSetAction("Stop+Revoke Selected",StopRevokeSelected,this);
+	childSetAction("Open Owner Profile",OpenProfile,this);
+
+	return 1;
+}
+
+void JCFloaterAnimList::StopSelected(void *userdata )
+{
+	JCFloaterAnimList *self = (JCFloaterAnimList*)userdata;
+	LLDynamicArray<LLUUID> ids;
+	std::vector< LLScrollListItem * > items = self->mAnimList->getAllSelected();
+	for( std::vector< LLScrollListItem * >::iterator itr = items.begin(); itr != items.end(); itr++ )
+	{
+		LLScrollListItem *item = *itr;
+		const LLUUID &id = item->getColumn(LIST_ANIMATION_UUID)->getValue().asUUID();
+		if( ids.find(id) == LLDynamicArray<LLUUID>::FAIL )
+		{
+			ids.put(id);
+		}
+	}
+	gAgent.sendAnimationRequests(ids,ANIM_REQUEST_STOP);
+}
+
+void JCFloaterAnimList::RevokeSelected(void *userdata )
+{
+	JCFloaterAnimList *self = (JCFloaterAnimList*)userdata;
+	LLDynamicArray<LLUUID> ids;
+	std::vector< LLScrollListItem * > items = self->mAnimList->getAllSelected();
+	for( std::vector< LLScrollListItem * >::iterator itr = items.begin(); itr != items.end(); itr++ )
+	{
+		LLScrollListItem *item = *itr;
+		const LLUUID &id = item->getColumn(LIST_OBJECT_UUID)->getValue().asUUID();
+		if( ids.find(id) == LLDynamicArray<LLUUID>::FAIL )
+		{
+			ids.put(id);
+		}
+	}
+	if( !ids.empty() )
+	{
+		for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
+		{
+			LLUUID id = *itr;
+			LLMessageSystem* msg = gMessageSystem;
+			msg->newMessageFast(_PREHASH_RevokePermissions);
+			msg->nextBlockFast(_PREHASH_AgentData);
+			msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+			msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+			msg->nextBlockFast(_PREHASH_Data);
+			msg->addUUIDFast(_PREHASH_ObjectID, id);
+			msg->addU32Fast(_PREHASH_ObjectPermissions, U32_MAX);
+			gAgent.sendReliableMessage();
+		}
+	}
+}
+
+void JCFloaterAnimList::StopRevokeSelected(void *userdata )
+{
+	StopSelected(userdata);
+	RevokeSelected(userdata);
+}
+
+void JCFloaterAnimList::OpenProfile(void *userdata )
+{
+	JCFloaterAnimList *self = (JCFloaterAnimList*)userdata;
+	std::vector< LLScrollListItem * > items = self->mAnimList->getAllSelected();
+	if(!items.empty())
+	{
+		//LLVOAvatar* avatarp = gAgent.getAvatarObject();	
+		for(std::vector< LLScrollListItem * >::iterator itr = items.begin(); itr != items.end(); ++itr)
+		{
+			LLScrollListItem *item = *itr;
+			const LLUUID &object_id = item->getColumn(LIST_OBJECT_UUID)->getValue().asUUID();
+			LLFloaterAvatarInfo::showFromDirectory(self->mObjectOwners[object_id].owner_id);
+		}
+	}
+}
+
+/*void JCFloaterAnimList::ReturnSelected(void *userdata )
+{
+	JCFloaterAnimList *self = (JCFloaterAnimList*)userdata;
+	LLDynamicArray<LLUUID> ids = self->mAnimList->getSelectedIDs();
+	if(ids.size() > 0)
+	{
+		LLVOAvatar* avatarp = gAgent.getAvatarObject();	
+		for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
+		{
+			LLUUID id = *itr;
+
+		}
+	}
+}*/
+
+void JCFloaterAnimList::draw()
+{
+	refresh();
+	LLFloater::draw();
+}
+//LLScrollListCtrl::getSelectedIDs();
+void JCFloaterAnimList::refresh()
+{
+	LLDynamicArray<LLUUID> selected = mAnimList->getSelectedIDs();
+	S32 scrollpos = mAnimList->getScrollPos();
+	mAnimList->deleteAllItems();
+	LLVOAvatar* avatarp = gAgent.getAvatarObject();		
+	if (avatarp)
+	{
+		LLVOAvatar::AnimSourceIterator ai;
+
+		for(ai = avatarp->mAnimationSources.begin(); ai != avatarp->mAnimationSources.end(); ++ai)
+		{
+			LLSD element;
+			const LLUUID &aifirst = ai->first;
+			LLViewerInventoryItem* item = gInventory.getItem(findItemID(ai->second,0));
+
+			// *NOTE: conceal id to prevent bugs, use
+			// item->getColumn(LIST_ANIMATION_UUID)->getValue().asUUID()
+			// instead
+			element["id"] = LLUUID::null.combine(ai->second);
+			element["columns"][LIST_ANIMATION_NAME]["column"] = "Anim Name";
+			element["columns"][LIST_ANIMATION_NAME]["type"] = "text";
+			element["columns"][LIST_ANIMATION_NAME]["color"] = gColors.getColor("DefaultListText").getValue();
+			if(item)
+			{
+				element["columns"][LIST_ANIMATION_NAME]["value"] = item->getName();//ai->second//"avatar_icon";
+			}else
+			{
+				element["columns"][LIST_ANIMATION_NAME]["value"] = "Not in Inventory";
+			}
+			element["columns"][LIST_ANIMATION_UUID]["column"] = "Animation UUID";
+			element["columns"][LIST_ANIMATION_UUID]["type"] = "text";
+			element["columns"][LIST_ANIMATION_UUID]["color"] = gColors.getColor("DefaultListText").getValue();
+			element["columns"][LIST_ANIMATION_UUID]["value"] = ai->second;
+			element["columns"][LIST_OBJECT_UUID]["column"] = "Source Object UUID";
+			element["columns"][LIST_OBJECT_UUID]["type"] = "text";
+			element["columns"][LIST_OBJECT_UUID]["color"] = gColors.getColor("DefaultListText").getValue();
+			element["columns"][LIST_OBJECT_UUID]["value"] = aifirst;
+			element["columns"][LIST_OBJECT_OWNER]["column"] = "Source Owner";
+			element["columns"][LIST_OBJECT_OWNER]["type"] = "text";
+			element["columns"][LIST_OBJECT_OWNER]["color"] = gColors.getColor("DefaultListText").getValue();
+			std::string name("?");
+			LLViewerObject *object = gObjectList.findObject(aifirst);
+			bool is_first = ( mObjectOwners.count( aifirst ) == 0 );
+			bool just_shown = false;
+			LLUUID owner_id(LLUUID::null);
+
+			if( !is_first )
+			{
+				name = mObjectOwners[aifirst].owner_name;
+				owner_id = mObjectOwners[aifirst].owner_id;
+			}
+
+			if( object )
+			{
+				if( object->permYouOwner() )
+				{
+					owner_id = gAgent.getID();
+					gAgent.getName(name);
+				}
+				else
+				{
+					object = (LLViewerObject *) object->getRoot();
+					if( object->isAvatar() )
+					{
+						owner_id = object->getID();
+						name = ((LLVOAvatar *)object)->getFullname();
+					}
+				}
+			}
+
+			{
+				AObjectData &data = mObjectOwners[aifirst];
+				if( object )
+				{
+					if( !data.in_object_list )
+					{
+						just_shown = true;
+						data.in_object_list = true;
+					}
+					data.root_id = ( (LLViewerObject*)object->getRoot() )->getID();
+				}
+				data.owner_name = name;
+				data.owner_id = owner_id;
+			}
+
+			if( is_first || just_shown ) {
+				if( name == "?" && !aifirst.isNull()) {
+					LLMessageSystem* msg = gMessageSystem;
+					msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
+					msg->nextBlockFast(_PREHASH_AgentData);
+					msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+					msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+					msg->nextBlockFast(_PREHASH_ObjectData);
+					msg->addU32Fast(_PREHASH_RequestFlags, 0 );
+					if( object )
+					{
+						LL_INFOS("Avatar List") << "Sending RequestObjectPropertiesFamily packet for id( " << aifirst.asString() << " ) on object( " << object->getID().asString() << " )" << LL_ENDL;
+						msg->addUUIDFast(_PREHASH_ObjectID, object->getID());
+					}
+					else
+					{
+						LL_INFOS("Avatar List") << "Sending RequestObjectPropertiesFamily packet for id( " << aifirst.asString() << " )" << LL_ENDL;
+						msg->addUUIDFast(_PREHASH_ObjectID, aifirst);
+					}
+					gAgent.sendReliableMessage();
+				}
+			}
+			element["columns"][LIST_OBJECT_OWNER]["value"] = name;
+			mAnimList->addElement(element, ADD_BOTTOM);
+			//LLViewerObject* objectp = gObjectList.findObject(ai->first);
+			//if(objectp)
+			//{
+			//	//objectp->
+			//}
+
+			//object_ids.insert(ai->first);
+			//animation_ids.insert(ai->second);
+		}
+	}
+
+	mAnimList->sortItems();
+	mAnimList->selectMultiple(selected);
+	mAnimList->setScrollPos(scrollpos);
+}
+
+void JCFloaterAnimList::callbackLoadOwnerName(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
+{
+	LLUUID *oid = (LLUUID*)data;
+	JCFloaterAnimList *self = JCFloaterAnimList::getInstance(LLSD());
+	if(self->mObjectOwners.count( *oid ) > 0)
+	{
+		self->mObjectOwners[*oid].owner_name = first + " " + last;
+	}
+	delete oid;
+}
+
+void JCFloaterAnimList::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data)
+{
+	if(!JCFloaterAnimList::instanceVisible(LLSD())) return;
+	JCFloaterAnimList *self = JCFloaterAnimList::getInstance(LLSD());
+	LLUUID object_id;
+	U32 request_flags;
+	LLUUID creator_id;
+	LLUUID owner_id;
+	LLUUID group_id;
+	LLUUID extra_id;
+	U32 base_mask, owner_mask, group_mask, everyone_mask, next_owner_mask;
+	LLSaleInfo sale_info;
+	LLCategory category;
+	msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags,	request_flags );
+	msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID,		object_id );
+	msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID,		owner_id );
+	msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID,		group_id );
+	msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_BaseMask,		base_mask );
+	msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_OwnerMask,		owner_mask );
+	msg->getU32Fast(_PREHASH_ObjectData,_PREHASH_GroupMask,		group_mask );
+	msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_EveryoneMask,	everyone_mask );
+	msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_NextOwnerMask, next_owner_mask);
+	sale_info.unpackMessage(msg, _PREHASH_ObjectData);
+	category.unpackMessage(msg, _PREHASH_ObjectData);
+	LLUUID last_owner_id;
+	msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id );
+	std::string name;
+	msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, name);
+	std::string desc;
+	msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc);
+
+	for( std::map<LLUUID, AObjectData>::iterator di = self->mObjectOwners.begin(); di != self->mObjectOwners.end(); di++ )
+	{
+		const LLUUID &id = di->first;
+		const AObjectData &data = di->second;
+		
+		if(data.root_id == object_id || data.owner_id == object_id)
+		{
+			LLUUID* ref = new LLUUID(id);
+			self->mObjectOwners[id].owner_id = owner_id;
+			gCacheName->get(owner_id, FALSE, callbackLoadOwnerName, (void*)ref);
+		}
+	}
+}
+
+const LLUUID& JCFloaterAnimList::findItemID(const LLUUID& asset_id, BOOL copyable_only)
+{
+	LLViewerInventoryCategory::cat_array_t cats;
+	LLViewerInventoryItem::item_array_t items;
+	LLAssetIDMatches asset_id_matches(asset_id);
+	gInventory.collectDescendentsIf(LLUUID::null,
+							cats,
+							items,
+							LLInventoryModel::INCLUDE_TRASH,
+							asset_id_matches);
+
+	if (items.count())
+	{
+		// search for copyable version first
+		for (S32 i = 0; i < items.count(); i++)
+		{
+			LLInventoryItem* itemp = items[i];
+			LLPermissions item_permissions = itemp->getPermissions();
+			if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+			{
+				return itemp->getUUID();
+			}
+		}
+		// otherwise just return first instance, unless copyable requested
+		if (copyable_only)
+		{
+			return LLUUID::null;
+		}
+		else
+		{
+			return items[0]->getUUID();
+		}
+	}
+
+	return LLUUID::null;
+}
+
+/*void JCFloaterAnimList::onClickCopyAnimationUUID(void *userdata)
+{
+	LLFloaterAvatarList *self = (LLFloaterAvatarList*)userdata;
+ 	LLScrollListItem *item = self->mAvatarList->getFirstSelected();
+
+	if ( NULL == item ) return;
+
+	LLUUID agent_id = item->getUUID();
+
+	char buffer[UUID_STR_LENGTH];		
+	agent_id.toString(buffer);
+
+	gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
+}*/
+
+void JCFloaterAnimList::onDoubleClick(void *userdata)
+{
+	//JCFloaterAnimList *self = (JCFloaterAnimList*)userdata;
+ 	//LLScrollListItem *item =   self->mAnimList->getFirstSelected();
+	//if(!item)return;
+	//LLUUID agent_id = item->getUUID();
+
+	//gAgent.setFocusObject(gObjectList.findObject(agent_id));
+	//gAgent.setFocusOnAvatar(FALSE, TRUE);
+}
+
+void JCFloaterAnimList::close(bool app)
+{
+	//sInstance->setVisible(0);
+//#ifdef RECONSTRUCT_ON_TOGGLE
+//	sInstance = NULL;
+	LLFloater::close(app);
+//#else
+//	sInstance->setVisible(!(sInstance->getVisible()));
+//#endif
+}
+
diff --git a/linden/indra/newview/jcfloater_animation_list.h b/linden/indra/newview/jcfloater_animation_list.h
new file mode 100644
index 0000000..d8262f0
--- /dev/null
+++ b/linden/indra/newview/jcfloater_animation_list.h
@@ -0,0 +1,88 @@
+/* Copyright (c) 2009
+ *
+ * Modular Systems Ltd. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Neither the name Modular Systems Ltd nor the names of its contributors
+ *      may be used to endorse or promote products derived from this
+ *      software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MODULAR SYSTEMS LTD AND CONTRIBUTORS �AS IS�
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MODULAR SYSTEMS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "llfloater.h"
+#include "lluuid.h"
+#include "llstring.h"
+
+struct AObjectData
+{
+	std::string owner_name;
+	LLUUID owner_id;
+	LLUUID root_id;
+	bool in_object_list;
+};
+
+class JCFloaterAnimList : public LLFloater, public LLUISingleton<JCFloaterAnimList, JCFloaterAnimList>
+{
+public:
+	JCFloaterAnimList(const LLSD& seed);
+	virtual ~JCFloaterAnimList();
+
+	/*virtual*/ BOOL postBuild();
+	/*virtual*/ void draw();
+	/*virtual*/ void onVisibilityChange(BOOL new_visibility);
+
+	/*virtual*/ void close(bool app = 0);
+	 void refresh();
+
+	const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
+
+	static void callbackLoadOwnerName(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data);
+
+	static void processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data);
+
+	static bool visible(LLFloater* instance, const LLSD& key);
+	static void show(LLFloater* instance, const LLSD& key);
+	static void hide(LLFloater* instance, const LLSD& key);
+
+private:
+
+	enum ANIMATION_COLUMN_ORDER
+	{
+		LIST_ANIMATION_NAME,
+		LIST_ANIMATION_UUID,
+		LIST_OBJECT_UUID,
+		LIST_OBJECT_OWNER
+	};
+
+	LLScrollListCtrl* mAnimList;
+
+	std::map<LLUUID, AObjectData> mObjectOwners;
+
+	static void StopSelected(void *userdata );
+	static void RevokeSelected(void *userdata );
+	static void StopRevokeSelected(void *userdata );
+	static void OpenProfile(void *userdata );
+	static void onDoubleClick(void *userdata);
+
+};
+
diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp
index 3be857e..b937894 100644
--- a/linden/indra/newview/llviewermenu.cpp
+++ b/linden/indra/newview/llviewermenu.cpp
@@ -210,6 +210,8 @@
 
 #include "lltexlayer.h"
 
+#include "jcfloater_animation_list.h"
+
 void init_client_menu(LLMenuGL* menu);
 void init_server_menu(LLMenuGL* menu);
 
@@ -5218,6 +5220,10 @@ class LLShowFloater : public view_listener_t
 		{
 			LLFloaterActiveSpeakers::toggleInstance(LLSD());
 		}
+		else if (floater_name == "animation list")
+		{
+			JCFloaterAnimList::toggleInstance(LLSD());
+		}
 		else if (floater_name == "inworld browser")
 		{
 			LLFloaterMediaBrowser::toggle();
diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_animation_list.xml b/linden/indra/newview/skins/default/xui/en-us/floater_animation_list.xml
new file mode 100644
index 0000000..be7de86
--- /dev/null
+++ b/linden/indra/newview/skins/default/xui/en-us/floater_animation_list.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater
+	name="animation list"
+	title="Animation List"
+	can_resize="true"
+	can_minimize="true"
+	can_close="true"
+	can_drag_on_left="false"
+    rect_control="FloaterAnimationListRect"
+	min_width="1000"
+	min_height="275"
+	>
+	<scroll_list
+		    name="animation_list"
+		    left="10"
+		    right="-10"
+		    top="-20"
+		    bottom="100"
+		    column_padding="0"
+		    can_resize="true"
+		    follows="left|top|bottom|right"
+		    draw_heading="true"
+		    multi_select="true"
+		    search_column="1"
+		    tool_tip="Hold shift or control while clicking to select multiple thingers"
+		    >
+		<!-- Icons relating to the avatar, currently: tracking, and marked -->
+		<column name="Anim Name" label="Anim Name" width="250"/>
+    <column name="Animation UUID" label="Animation UUID" width="250"/>
+    <!--<column name="object_name" label="Distance" dynamicwidth="true"/>-->
+		<column name="Source Object UUID" label="Source Object UUID" width="250"/>
+    <column name="Source Owner" label="Source Owner" width="250"/>
+    <!-- What the avatar is doing: producing sounds, rezzing, particles, etc -->
+	</scroll_list>
+	<panel 
+	       name="options"
+	       left="10"
+	       right="-10"
+         top="90"	
+	       bottom="10"	
+	       border="true"
+	       mouse_opaque="true"
+	       bevel_style="in"
+	       background_visible="true"
+	       background_opaque="true"
+	       follows="left|right|bottom"
+	       bg_opaque_color="0,0,0,0.3"
+	       bg_alpha_color="blue"
+	       can_resize="false"
+	>
+	</panel>
+
+  <button bottom="55" follows="left|bottom" font="SansSerifSmall" halign="center"
+       height="20" label="Stop Selected" left_delta="5"
+       mouse_opaque="true" name="Stop Selected"
+       tool_tip="Stop selected animations" width="150" />
+  <button bottom_delta="0" follows="left|bottom" font="SansSerifSmall" halign="center"
+       height="20" label="Revoke Selected" left_delta="155"
+       mouse_opaque="true" name="Revoke Selected"
+       tool_tip="Revokes animation permissions for object associated with the selections" width="150" />
+  <button bottom_delta="0" follows="left|bottom" font="SansSerifSmall" halign="center"
+       height="20" label="Stop+Revoke Selected" left_delta="155"
+       mouse_opaque="true" name="Stop+Revoke Selected"
+       tool_tip="Revokes animation permissions for object(s) associated with the selections, as well as stopping the anim" width="150" />
+  <button bottom_delta="0" follows="left|bottom" font="SansSerifSmall" halign="center"
+       height="20" label="Open Owner Profile" left_delta="155"
+       mouse_opaque="true" name="Open Owner Profile"
+       tool_tip="Opens profile of the owner(s) of object(s) associated with the selections" width="150" />
+  <button bottom_delta="-25" enabled="false" follows="left|bottom" font="SansSerifSmall" halign="center"
+       height="20" label="Return Object" left_delta="-465"
+       mouse_opaque="true" name="Return Object"
+       tool_tip="Returns object(s) selected, if you have land powers" width="150" />
+
+</floater>
\ No newline at end of file
diff --git a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
index 86b5315..b091be2 100644
--- a/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
+++ b/linden/indra/newview/skins/default/xui/en-us/menu_viewer.xml
@@ -893,6 +893,10 @@
       <on_click function="Advanced.TogglePhantom" userdata="" />
       <on_check function="Advanced.CheckPhantom" userdata="" />
     </menu_item_check>
+    <menu_item_check label="Animation List" name="Animation List">
+      <on_click function="ShowFloater" userdata="animation list" />
+      <on_check function="FloaterVisible" userdata="animation list" />
+    </menu_item_check>
     <menu_item_check name="Show Mouselook Crosshairs"
                      label="Show Mouselook Crosshairs">
       <on_click function="ToggleControl"
-- 
cgit v1.1