From dce50cd6d6f8a832e1f1684c3eeeb9c9b246c5a0 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Fri, 27 Mar 2020 05:09:33 -0400
Subject: [PATCH] Add copy utilities to all the avatar menus and clean up
 inworld attachment/avatar menus

---
 indra/newview/CMakeLists.txt                  |   6 +-
 indra/newview/alavataractions.cpp             | 154 +++++++
 indra/newview/alavataractions.h               |  64 +++
 indra/newview/alviewermenu.cpp                |  58 +++
 indra/newview/alviewermenu.h                  |  28 ++
 indra/newview/llchathistory.cpp               |   2 +
 indra/newview/llconversationmodel.cpp         |   9 +
 indra/newview/lldrawpoolavatar.cpp            |   3 +
 indra/newview/llfloaterimcontainer.cpp        |  43 +-
 indra/newview/llpanelpeoplemenus.cpp          |  34 +-
 indra/newview/llpanelprofile.cpp              |  34 +-
 indra/newview/llpanelprofile.h                |   1 -
 indra/newview/llviewermenu.cpp                |   3 +
 indra/newview/llviewermenu.h                  |   6 +
 .../default/xui/en/menu_attachment_other.xml  | 375 ++++++++++--------
 .../skins/default/xui/en/menu_avatar_icon.xml |  48 +++
 .../default/xui/en/menu_avatar_other.xml      | 273 +++++++------
 .../default/xui/en/menu_conversation.xml      |  50 ++-
 .../default/xui/en/menu_im_conversation.xml   |  50 ++-
 .../skins/default/xui/en/menu_name_field.xml  |  67 ++--
 .../default/xui/en/menu_people_nearby.xml     |  48 +++
 .../xui/en/menu_people_nearby_multiselect.xml |  48 +++
 22 files changed, 1060 insertions(+), 344 deletions(-)
 create mode 100644 indra/newview/alavataractions.cpp
 create mode 100644 indra/newview/alavataractions.h
 create mode 100644 indra/newview/alviewermenu.cpp
 create mode 100644 indra/newview/alviewermenu.h

diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3d2ede71693..baa7cc1b8c8 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -110,8 +110,10 @@ include_directories(SYSTEM
     )
 
 set(viewer_SOURCE_FILES
+    alavataractions.cpp
     alchatcommand.cpp
     alunzip.cpp
+    alviewermenu.cpp
     groupchatlistener.cpp
     llaccountingcostmanager.cpp
     llaisapi.cpp
@@ -746,8 +748,10 @@ set(VIEWER_BINARY_NAME "secondlife-bin" CACHE STRING
 set(viewer_HEADER_FILES
     CMakeLists.txt
     ViewerInstall.cmake
-    alunzip.h
+    alavataractions.h
     alchatcommand.h
+    alunzip.h
+    alviewermenu.h
     groupchatlistener.h
     llaccountingcost.h
     llaccountingcostmanager.h
diff --git a/indra/newview/alavataractions.cpp b/indra/newview/alavataractions.cpp
new file mode 100644
index 00000000000..a4f0233f839
--- /dev/null
+++ b/indra/newview/alavataractions.cpp
@@ -0,0 +1,154 @@
+/** 
+ * @file alavataractions.cpp
+ * @brief Friend-related actions (add, remove, offer teleport, etc)
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, Rye Mutt <rye@alchemyviewer.org>
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * $/LicenseInfo$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llavatarnamecache.h"
+#include "llclipboard.h"
+
+#include "alavataractions.h"
+#include "llslurl.h"
+#include "llviewercontrol.h"
+
+// static
+void ALAvatarActions::copyData(const LLUUID& id, ECopyDataType type)
+{
+	if (id.isNull())
+		return;
+
+	uuid_vec_t ids;
+	ids.push_back(id);
+	copyData(ids, type);
+}
+
+// static
+void ALAvatarActions::copyData(const uuid_vec_t& ids, ECopyDataType type)
+{
+	if (!ids.empty())
+	{
+		std::string data_string;
+		static LLCachedControl<std::string> seperator(gSavedSettings, "AlchemyCopySeperator", ", ");
+		for (const LLUUID& id : ids)
+		{
+			if (id.isNull())
+				continue;
+
+			if (!data_string.empty())
+				data_string.append(seperator);
+
+			switch (type)
+			{
+			case E_DATA_USER_NAME:
+			{
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(id, &av_name);
+				data_string.append(av_name.getUserName());
+				break;
+			}
+			case E_DATA_ACCOUNT_NAME:
+			{
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(id, &av_name);
+				data_string.append(av_name.getAccountName());
+				break;
+			}
+			case E_DATA_DISPLAY_NAME:
+			{
+				LLAvatarName av_name;
+				LLAvatarNameCache::get(id, &av_name);
+				data_string.append(av_name.getDisplayName(true));
+				break;
+			}
+			case E_DATA_SLURL:
+				data_string.append(LLSLURL("agent", id, "about").getSLURLString());
+				break;
+			case E_DATA_UUID:
+				data_string.append(id.asString());
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (!data_string.empty())
+		{
+			LLWString wdata_str = utf8str_to_wstring(data_string);
+			LLClipboard::instance().copyToClipboard(wdata_str, 0, wdata_str.length());
+		}
+	}
+}
+
+// static
+void ALAvatarActions::copyData(const LLUUID& id, const LLSD& userdata)
+{
+	const std::string item_name = userdata.asString();
+	if (item_name == "user_name")
+	{
+		copyData(id, E_DATA_USER_NAME);
+	}
+	else if (item_name == "account_name")
+	{
+		copyData(id, E_DATA_ACCOUNT_NAME);
+	}
+	else if (item_name == "display_name")
+	{
+		copyData(id, E_DATA_DISPLAY_NAME);
+	}
+	else if (item_name == "id")
+	{
+		copyData(id, E_DATA_UUID);
+	}
+	else if (item_name == "slurl")
+	{
+		copyData(id, E_DATA_SLURL);
+	}
+}
+
+// static
+void ALAvatarActions::copyData(const uuid_vec_t& ids, const LLSD& userdata)
+{
+	const std::string item_name = userdata.asString();
+	if (item_name == "user_name")
+	{
+		copyData(ids, E_DATA_USER_NAME);
+	}
+	else if (item_name == "account_name")
+	{
+		copyData(ids, E_DATA_ACCOUNT_NAME);
+	}
+	else if (item_name == "display_name")
+	{
+		copyData(ids, E_DATA_DISPLAY_NAME);
+	}
+	else if (item_name == "id")
+	{
+		copyData(ids, E_DATA_UUID);
+	}
+	else if (item_name == "slurl")
+	{
+		copyData(ids, E_DATA_SLURL);
+	}
+}
\ No newline at end of file
diff --git a/indra/newview/alavataractions.h b/indra/newview/alavataractions.h
new file mode 100644
index 00000000000..896eeaa93dc
--- /dev/null
+++ b/indra/newview/alavataractions.h
@@ -0,0 +1,64 @@
+/** 
+ * @file alavataractions.h
+ * @brief Friend-related actions (add, remove, offer teleport, etc)
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, Rye Mutt <rye@alchemyviewer.org>
+ * 
+ * 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.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * $/LicenseInfo$
+ */
+
+#ifndef AL_ALAVATARACTIONS_H
+#define AL_ALAVATARACTIONS_H
+
+#include "llsd.h"
+#include "lluuid.h"
+
+#include <string>
+#include <vector>
+
+class LLAvatarName;
+class LLInventoryPanel;
+class LLFloater;
+class LLView;
+
+/**
+ * Friend-related actions (add, remove, offer teleport, etc)
+ */
+class ALAvatarActions
+{
+public:
+	/**
+     * Copy the selected avatar's name, slurl, or UUID to clipboard
+	 */
+	enum ECopyDataType : U32
+	{
+		E_DATA_USER_NAME = 0,
+		E_DATA_ACCOUNT_NAME,
+		E_DATA_DISPLAY_NAME,
+		E_DATA_SLURL,
+		E_DATA_UUID
+	};
+
+	static void copyData(const LLUUID& id, ECopyDataType type);
+	static void copyData(const uuid_vec_t& ids, ECopyDataType type);
+	static void copyData(const LLUUID& id, const LLSD& userdata);
+	static void copyData(const uuid_vec_t& id, const LLSD& userdata);
+};
+
+#endif // AL_ALAVATARACTIONS_H
diff --git a/indra/newview/alviewermenu.cpp b/indra/newview/alviewermenu.cpp
new file mode 100644
index 00000000000..bd0c586d044
--- /dev/null
+++ b/indra/newview/alviewermenu.cpp
@@ -0,0 +1,58 @@
+/**
+* @file alviewermenu.cpp
+* @brief Builds menus out of items. Imagine the fast, easy, fun Alchemy style
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Copyright (C) 2013 Alchemy Developer Group
+*
+* 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.
+* $/LicenseInfo$
+**/
+
+#include "llviewerprecompiledheaders.h"
+#include "alviewermenu.h"
+
+// library
+#include "llview.h"
+
+// newview
+#include "alavataractions.h"
+#include "llselectmgr.h"
+#include "llviewermenu.h"
+#include "llviewerobject.h"
+#include "llvoavatar.h"
+
+namespace
+{
+	bool avatar_copy_data(const LLSD& userdata)
+	{
+		LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
+		if (!objectp)
+			return false;
+
+		LLVOAvatar* avatarp = find_avatar_from_object(objectp);
+		if (avatarp)
+		{
+			ALAvatarActions::copyData(avatarp->getID(), userdata);
+			return true;
+		}
+		return false;
+	}
+}
+
+////////////////////////////////////////////////////////
+
+void ALViewerMenu::initialize_menus()
+{
+	//LLUICtrl::EnableCallbackRegistry::Registrar& enable = LLUICtrl::EnableCallbackRegistry::currentRegistrar();
+	LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
+	commit.add("Avatar.CopyData", [](LLUICtrl* ctrl, const LLSD& param) { avatar_copy_data(param); });
+}
diff --git a/indra/newview/alviewermenu.h b/indra/newview/alviewermenu.h
new file mode 100644
index 00000000000..eb28c6be113
--- /dev/null
+++ b/indra/newview/alviewermenu.h
@@ -0,0 +1,28 @@
+/**
+* @file alviewermenu.cpp
+* @brief Builds menus out of items. Imagine the fast, easy, fun Alchemy style
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Copyright (C) 2013 Alchemy Developer Group
+*
+* 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.
+* $/LicenseInfo$
+**/
+
+#ifndef AL_LLVIEWERMENU_H
+#define AL_LLVIEWERMENU_H
+
+namespace ALViewerMenu
+{
+	void initialize_menus();
+}
+
+#endif // AL_VIEWERMENU_H
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 04912893972..a91299ff085 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -33,6 +33,7 @@
 #include "llavatarnamecache.h"
 #include "llinstantmessage.h"
 
+#include "alavataractions.h"
 #include "llimview.h"
 #include "llcommandhandler.h"
 #include "llpanel.h"
@@ -866,6 +867,7 @@ class LLChatHistoryHeader: public LLPanel
 			LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 			LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
 			registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+			registrar.add("AvatarIcon.CopyData", [&](LLUICtrl* ctrl, const LLSD& param) { ALAvatarActions::copyData(mAvatarID, param); });
 			registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
 			registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
 			registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index c2581368899..b94c2780edd 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -185,6 +185,15 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
 			items.push_back(std::string("Group Ban Separator"));
 			items.push_back(std::string("BanMember"));
 		}
+
+
+		items.push_back(std::string("separator_utils"));
+		items.push_back(std::string("utils_menu"));
+		items.push_back(std::string("copy_username"));
+		items.push_back(std::string("copy_display_name"));
+		items.push_back(std::string("copy_account_name"));
+		items.push_back(std::string("copy_slurl"));
+		items.push_back(std::string("copy_uuid"));
 	}
 }
 
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index a4b42e0df93..007e8f51c84 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1738,6 +1738,9 @@ void LLDrawPoolAvatar::getRiggedGeometry(
 	face->setIndicesIndex(0);
 		
 	//rigged faces do not batch textures
+	if (face->getTextureIndex() != 255)
+		face->setDrawInfo(nullptr);
+
 	face->setTextureIndex(255);
 
 	if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 05cb89b6353..25e9cd50c5e 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -34,6 +34,7 @@
 #include "lllayoutstack.h"
 #include "llfloaterimnearbychat.h"
 
+#include "alavataractions.h"
 #include "llagent.h"
 #include "llavataractions.h"
 #include "llavatariconctrl.h"
@@ -717,7 +718,7 @@ void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& float
 	typedef conversations_widgets_map::value_type conv_pair;
 	LLFloaterIMNearbyChat *nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
 
-	BOOST_FOREACH(conv_pair item, mConversationsWidgets)
+	for(const conv_pair& item : mConversationsWidgets)
 	{
 		LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(item.second);
 		if (widget)
@@ -1191,6 +1192,26 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
 		{
 			banSelectedMember(userID);
 		}
+		else if ("copy_username" == command)
+		{
+			ALAvatarActions::copyData(userID, ALAvatarActions::E_DATA_USER_NAME);
+		}
+		else if ("copy_display_name" == command)
+		{
+			ALAvatarActions::copyData(userID, ALAvatarActions::E_DATA_DISPLAY_NAME);
+		}
+		else if ("copy_account_name" == command)
+		{
+			ALAvatarActions::copyData(userID, ALAvatarActions::E_DATA_ACCOUNT_NAME);
+		}
+		else if ("copy_slurl" == command)
+		{
+			ALAvatarActions::copyData(userID, ALAvatarActions::E_DATA_SLURL);
+		}
+		else if ("copy_uuid" == command)
+		{
+			ALAvatarActions::copyData(userID, ALAvatarActions::E_DATA_UUID);
+		}
 	}
 	else if (selectedIDS.size() > 1)
 	{
@@ -1210,6 +1231,26 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
 		{
 			LLAvatarActions::removeFriendsDialog(selectedIDS);
 		}
+		else if ("copy_username" == command)
+		{
+			ALAvatarActions::copyData(selectedIDS, ALAvatarActions::E_DATA_USER_NAME);
+		}
+		else if ("copy_display_name" == command)
+		{
+			ALAvatarActions::copyData(selectedIDS, ALAvatarActions::E_DATA_DISPLAY_NAME);
+		}
+		else if ("copy_account_name" == command)
+		{
+			ALAvatarActions::copyData(selectedIDS, ALAvatarActions::E_DATA_ACCOUNT_NAME);
+		}
+		else if ("copy_slurl" == command)
+		{
+			ALAvatarActions::copyData(selectedIDS, ALAvatarActions::E_DATA_SLURL);
+		}
+		else if ("copy_uuid" == command)
+		{
+			ALAvatarActions::copyData(selectedIDS, ALAvatarActions::E_DATA_UUID);
+		}
 	}
 }
 
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index f3c693a29aa..51fc37a9d21 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -33,6 +33,7 @@
 #include "llpanelpeoplemenus.h"
 
 // newview
+#include "alavataractions.h"
 #include "llagent.h"
 #include "llagentdata.h"			// for gAgentID
 #include "llavataractions.h"
@@ -86,7 +87,7 @@ LLContextMenu* PeopleContextMenu::createMenu()
 		registrar.add("Avatar.Calllog",			boost::bind(&LLAvatarActions::viewChatHistory,			id));
 		registrar.add("Avatar.Freeze",			boost::bind(&LLAvatarActions::freezeAvatar,					id));
 		registrar.add("Avatar.Eject",			boost::bind(&PeopleContextMenu::eject,					this));
-
+		registrar.add("Avatar.CopyData",		[&](LLUICtrl* ctrl, const LLSD& param){ ALAvatarActions::copyData(id, param);});
 
 		enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
 		enable_registrar.add("Avatar.CheckItem",  boost::bind(&PeopleContextMenu::checkContextMenuItem,	this, _2));
@@ -107,7 +108,8 @@ LLContextMenu* PeopleContextMenu::createMenu()
 		registrar.add("Avatar.RemoveFriend",	boost::bind(&LLAvatarActions::removeFriendsDialog,		mUUIDs));
 		// registrar.add("Avatar.Share",		boost::bind(&LLAvatarActions::startIM,					mUUIDs)); // *TODO: unimplemented
 		// registrar.add("Avatar.Pay",			boost::bind(&LLAvatarActions::pay,						mUUIDs)); // *TODO: unimplemented
-		
+		registrar.add("Avatar.CopyData",		[&](LLUICtrl* ctrl, const LLSD& param) { ALAvatarActions::copyData(mUUIDs, param); });
+
 		enable_registrar.add("Avatar.EnableItem",	boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2));
 
 		// create the context menu from the XUI
@@ -132,6 +134,13 @@ void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
 		items.push_back(std::string("share"));
 		items.push_back(std::string("pay"));
 		items.push_back(std::string("offer_teleport"));
+		items.push_back(std::string("separator_utils"));
+		items.push_back(std::string("utils_menu"));
+		items.push_back(std::string("copy_username"));
+		items.push_back(std::string("copy_display_name"));
+		items.push_back(std::string("copy_account_name"));
+		items.push_back(std::string("copy_slurl"));
+		items.push_back(std::string("copy_uuid"));
 	}
 	else 
 	{
@@ -150,6 +159,13 @@ void PeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
 		items.push_back(std::string("share"));
 		items.push_back(std::string("pay"));
 		items.push_back(std::string("block_unblock"));
+		items.push_back(std::string("separator_utils"));
+		items.push_back(std::string("utils_menu"));
+		items.push_back(std::string("copy_username"));
+		items.push_back(std::string("copy_display_name"));
+		items.push_back(std::string("copy_account_name"));
+		items.push_back(std::string("copy_slurl"));
+		items.push_back(std::string("copy_uuid"));
 	}
 
     hide_context_entries(menu, items, disabled_items);
@@ -432,6 +448,13 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
 		items.push_back(std::string("share"));
 		items.push_back(std::string("pay"));
 		items.push_back(std::string("offer_teleport"));
+		items.push_back(std::string("separator_utils"));
+		items.push_back(std::string("utils_menu"));
+		items.push_back(std::string("copy_username"));
+		items.push_back(std::string("copy_display_name"));
+		items.push_back(std::string("copy_account_name"));
+		items.push_back(std::string("copy_slurl"));
+		items.push_back(std::string("copy_uuid"));
 	}
 	else 
 	{
@@ -453,6 +476,13 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags)
 		items.push_back(std::string("block_unblock"));
 		items.push_back(std::string("freeze"));
 		items.push_back(std::string("eject"));
+		items.push_back(std::string("separator_utils"));
+		items.push_back(std::string("utils_menu"));
+		items.push_back(std::string("copy_username"));
+		items.push_back(std::string("copy_display_name"));
+		items.push_back(std::string("copy_account_name"));
+		items.push_back(std::string("copy_slurl"));
+		items.push_back(std::string("copy_uuid"));
 	}
 
     hide_context_entries(menu, items, disabled_items);
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 175e9658b04..6d6ba1ce0c4 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -47,6 +47,7 @@
 #include "llgrouplist.h"
 
 // Newview
+#include "alavataractions.h"
 #include "llagent.h" //gAgent
 #include "llagentpicksinfo.h"
 #include "llavataractions.h"
@@ -293,7 +294,7 @@ BOOL LLPanelProfileSecondLife::postBuild()
     mSecondLifePic->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onCommitTexture, this));
 
     LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit;
-    commit.add("Profile.CopyName", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); });
+    commit.add("Profile.CopyName", [this](LLUICtrl*, const LLSD& userdata) { ALAvatarActions::copyData(getAvatarId(), userdata); });
 
     LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable;
     enable.add("Profile.EnableCall",                [this](LLUICtrl*, const LLSD&) { return mVoiceStatus; });
@@ -782,37 +783,6 @@ void LLPanelProfileSecondLife::onCommitTexture()
     }
 }
 
-void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata)
-{
-    LLAvatarName av_name;
-    if (!LLAvatarNameCache::get(getAvatarId(), &av_name))
-    {
-        // shouldn't happen, button(menu) is supposed to be invisible while name is fetching
-        LL_WARNS() << "Failed to get agent data" << LL_ENDL;
-        return;
-    }
-
-    const std::string item_name = userdata.asString();
-    LLWString wstr;
-    if (item_name == "display")
-    {
-        wstr = utf8str_to_wstring(av_name.getDisplayName(true));
-    }
-    else if (item_name == "name")
-    {
-        wstr = utf8str_to_wstring(av_name.getAccountName());
-    }
-    else if (item_name == "id")
-    {
-        wstr = utf8str_to_wstring(getAvatarId().asString());
-    }
-    else if (item_name == "slurl")
-    {
-        wstr = utf8str_to_wstring(LLSLURL("agent", getAvatarId(), "about").getSLURLString());
-    }
-    LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size());
-}
-
 void LLPanelProfileSecondLife::onAvatarNameCacheSetName(const LLUUID& agent_id, const LLAvatarName& av_name)
 {
     if (av_name.getDisplayName().empty())
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index 49e86c39981..1696294fca3 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -178,7 +178,6 @@ class LLPanelProfileSecondLife
     /*virtual*/ void updateButtons();
 	void onClickSetName();
 	void onCommitTexture();
-	void onCommitMenu(const LLSD& userdata);
 	void onAvatarNameCacheSetName(const LLUUID& id, const LLAvatarName& av_name);
 
 private:
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index f5759d2e962..c615e9fd593 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -43,6 +43,7 @@
 #include "llviewereventrecorder.h"
 
 // newview includes
+#include "alviewermenu.h"
 #include "llagent.h"
 #include "llagentaccess.h"
 #include "llagentbenefits.h"
@@ -9877,4 +9878,6 @@ void initialize_menus()
 		enable.add("RLV.EnableIfNot", boost::bind(&rlvMenuEnableIfNot, _2));
 	}
 // [/RLVa:KB]
+
+	ALViewerMenu::initialize_menus();
 }
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index 8dc6c3634b8..12fb2b354f3 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -37,6 +37,8 @@ class LLView;
 class LLParcelSelection;
 class LLObjectSelection;
 class LLSelectNode;
+class LLViewerObject;
+class LLVOAvatar;
 
 // [RLVa:KB] - Checked: RLVa-2.0.0
 void set_use_wireframe(bool useWireframe);
@@ -141,6 +143,10 @@ bool enable_pay_object();
 bool enable_buy_object();
 bool handle_go_to();
 
+// find avatar from object methods
+LLVOAvatar* find_avatar_from_object(LLViewerObject* object);
+LLVOAvatar* find_avatar_from_object(const LLUUID& object_id);
+
 // Export to XML or Collada
 void handle_export_selected( void * );
 
diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
index b955d8313f7..eb7dcadace7 100644
--- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml
@@ -3,192 +3,237 @@
 <context_menu
  layout="topleft"
  name="Avatar Pie">
+  <menu_item_call
+   label="View Profile"
+   name="Profile...">
+    <menu_item_call.on_click
+     function="ShowAgentProfile"
+     parameter="hit object" />
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_call
+    enabled="false"
+    label="Add Friend"
+    name="Add Friend">
+    <menu_item_call.on_click
+     function="Avatar.AddFriend" />
+    <menu_item_call.on_enable
+     function="Avatar.EnableAddFriend" />
+    <menu_item_call.on_visible
+     function="Avatar.EnableAddFriend" />
+  </menu_item_call>
+  <menu_item_call
+   label="IM"
+   name="Send IM...">
+    <menu_item_call.on_click
+     function="Avatar.SendIM" />
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_call
+   label="Call"
+   name="Call">
+    <menu_item_call.on_click
+     function="Avatar.Call" />
+    <menu_item_call.on_enable
+     function="Avatar.EnableCall" />
+  </menu_item_call>
+  <menu_item_call
+     label="Invite to Group"
+     name="Invite...">
+    <menu_item_call.on_click
+     function="Avatar.InviteToGroup" />
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_separator />
+  <context_menu
+   label="Appearance"
+   name="Appearance">
     <menu_item_call
-     label="View Profile"
-     name="Profile...">
-        <menu_item_call.on_click
-         function="ShowAgentProfile"
-         parameter="hit object" />
-        <menu_item_call.on_enable
-         function="RLV.CanShowName" />
+      label="Reset Skeleton"
+      name="Reset Skeleton">
+      <menu_item_call.on_click
+       function="Avatar.ResetSkeleton" />
     </menu_item_call>
-   <menu_item_call
-     enabled="false"
-     label="Add Friend"
-     name="Add Friend">
-        <menu_item_call.on_click
-         function="Avatar.AddFriend" />
-        <menu_item_call.on_enable
-         function="Avatar.EnableAddFriend" />
+    <menu_item_call
+     label="Reset Skeleton And Animations"
+     name="Reset Skeleton And Animations">
+      <menu_item_call.on_click
+       function="Avatar.ResetSkeletonAndAnimations" />
+    </menu_item_call>
+    <menu_item_separator />
+    <menu_item_check
+      name="RenderNormally"
+      label="Normally Render">
+      <menu_item_check.on_check
+        function="Avatar.CheckImpostorMode"
+        parameter="0" />
+      <menu_item_check.on_click
+	      function="Avatar.SetImpostorMode"
+	      parameter="0" />
+    </menu_item_check>
+    <menu_item_check
+      name="AlwaysRenderFully"
+      label="Always Render">
+      <menu_item_check.on_check
+        function="Avatar.CheckImpostorMode"
+        parameter="2" />
+      <menu_item_check.on_click
+	      function="Avatar.SetImpostorMode"
+	      parameter="2" />
+    </menu_item_check>
+    <menu_item_check
+      name="DoNotRender"
+      label="Never Render">
+      <menu_item_check.on_check
+        function="Avatar.CheckImpostorMode"
+        parameter="1" />
+      <menu_item_check.on_click
+	      function="Avatar.SetImpostorMode"
+	      parameter="1" />
+    </menu_item_check>
+    <menu_item_separator />
+    <menu_item_call
+      label="Render Exceptions..."
+      name="RenderExceptions">
+      <menu_item_call.on_click
+        function="Floater.ToggleOrBringToFront"
+        parameter="avatar_render_settings" />
+    </menu_item_call>
+  </context_menu>
+  <context_menu
+   label="Utilities"
+   name="Utilities">
+    <menu_item_call
+     label="Debug Textures"
+     name="Debug...">
+      <menu_item_call.on_click
+       function="Avatar.Debug" />
+      <menu_item_call.on_visible
+       function="IsGodCustomerService"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Dump XML"
+         name="Dump XML">
+      <menu_item_call.on_click
+       function="Advanced.AppearanceToXML" />
+      <menu_item_call.on_visible
+       function="Advanced.EnableAppearanceToXML"/>
     </menu_item_call>
     <menu_item_call
-     label="IM"
-     name="Send IM...">
-        <menu_item_call.on_click
-         function="Avatar.SendIM" />
-        <menu_item_call.on_enable
-         function="RLV.CanShowName" />
+     label="Copy Username"
+     name="Copy Username">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="user_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
     </menu_item_call>
     <menu_item_call
-     label="Call"
-     name="Call">
-        <menu_item_call.on_click
-         function="Avatar.Call" />
-        <menu_item_call.on_enable
-         function="Avatar.EnableCall" />
+     label="Copy Display Name"
+     name="Copy Display Name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
     </menu_item_call>
-      <menu_item_call
-         label="Invite to Group"
-         name="Invite...">
-        <menu_item_call.on_click
-         function="Avatar.InviteToGroup" />
-        <menu_item_call.on_enable
-         function="RLV.CanShowName" />
-      </menu_item_call>
-   <menu_item_separator />
-
-     <menu_item_call label="Reset Skeleton"
-       layout="topleft"
-       name="Reset Skeleton">
-       <menu_item_call.on_click
-        function="Avatar.ResetSkeleton" />
-     </menu_item_call>
-
-     <menu_item_call label="Reset Skeleton And Animations"
-       layout="topleft"
-       name="Reset Skeleton And Animations">
-       <menu_item_call.on_click
-        function="Avatar.ResetSkeletonAndAnimations" />
-     </menu_item_call>
-
-   <menu_item_separator />
+    <menu_item_call
+     label="Copy Account Name"
+     name="Copy Account Name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="Copy SLurl">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="Copy ID">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="id"/>
+    </menu_item_call>
+  </context_menu>
+  <context_menu
+   label="Manage"
+   name="Manage">
     <menu_item_call
      enabled="false"
      label="Block"
      name="Avatar Mute">
-        <menu_item_call.on_click
-         function="Avatar.Mute" />
-        <menu_item_call.on_enable
-         function="Avatar.EnableMute" />
+      <menu_item_call.on_click
+       function="Avatar.Mute" />
+      <menu_item_call.on_enable
+       function="Avatar.EnableMute" />
+    </menu_item_call>
+    <menu_item_call
+     enabled="false"
+     label="Block Particle Owner"
+     name="Mute Particle">
+      <menu_item_call.on_click
+       function="Particle.Mute" />
+      <menu_item_call.on_enable
+       function="EnableMuteParticle" />
     </menu_item_call>
     <menu_item_call
      label="Report"
      name="abuse">
-        <menu_item_call.on_click
-         function="Avatar.ReportAbuse" />
+      <menu_item_call.on_click
+       function="Avatar.ReportAbuse" />
     </menu_item_call>
-        <menu_item_call
-         label="Freeze"
-         name="Freeze...">
-            <menu_item_call.on_click
-             function="Avatar.Freeze" />
-            <menu_item_call.on_visible
-             function="Avatar.EnableFreezeEject"/>
-        </menu_item_call>
-        <menu_item_call
-         label="Eject"
-         name="Eject...">
-            <menu_item_call.on_click
-             function="Avatar.Eject" />
-            <menu_item_call.on_visible
-             function="Avatar.EnableFreezeEject"/>
-        </menu_item_call>
-        <menu_item_call
-         label="Debug Textures"
-         name="Debug...">
-            <menu_item_call.on_click
-             function="Avatar.Debug" />
-            <menu_item_call.on_visible
-             function="IsGodCustomerService"/>
-        </menu_item_call>
     <menu_item_call
-		 label="Dump XML"
-         name="Dump XML">
-            <menu_item_call.on_click
-             function="Advanced.AppearanceToXML" />
-            <menu_item_call.on_visible
-             function="Advanced.EnableAppearanceToXML"/>
-    </menu_item_call>
-	    <menu_item_call
-         label="Zoom In"
-          name="Zoom In">
-        <menu_item_call.on_click
-           function="Tools.LookAtSelection"
-           parameter="zoom" />
+     label="Freeze"
+     name="Freeze...">
+      <menu_item_call.on_click
+       function="Avatar.Freeze" />
+      <menu_item_call.on_visible
+       function="Avatar.EnableFreezeEject"/>
     </menu_item_call>
-   <menu_item_call
-     enabled="false"
-     label="Pay"
-     name="Pay...">
-        <menu_item_call.on_click
-         function="PayObject" />
-        <menu_item_call.on_enable
-         function="EnablePayAvatar" />
+    <menu_item_call
+     label="Eject"
+     name="Eject...">
+      <menu_item_call.on_click
+       function="Avatar.Eject" />
+      <menu_item_call.on_visible
+       function="Avatar.EnableFreezeEject"/>
     </menu_item_call>
-   <menu_item_separator />
-   <menu_item_call
-       label="Object Profile"
-       name="Object Inspect">
-         <menu_item_call.on_click
-          function="Object.Inspect" />
-         <menu_item_call.on_enable
-          function="Object.EnableInspect" />
-   </menu_item_call>
-
-   <menu_item_separator />
-      <context_menu
-       label="Render Avatar"
-       layout="topleft"
-        name="Render Avatar">
-      <menu_item_check
-        name="RenderNormally"
-        label="Default">
-        <menu_item_check.on_check
-          function="Avatar.CheckImpostorMode"
-          parameter="0" />
-	    <menu_item_check.on_click
-	      function="Avatar.SetImpostorMode"
-	      parameter="0" />
-      </menu_item_check>
-      <menu_item_check
-        name="AlwaysRenderFully"
-        label="Always">
-        <menu_item_check.on_check
-          function="Avatar.CheckImpostorMode"
-          parameter="2" />
-	    <menu_item_check.on_click
-	      function="Avatar.SetImpostorMode"
-	      parameter="2" />
-      </menu_item_check>
-      <menu_item_check
-        name="DoNotRender"
-        label="Never">
-        <menu_item_check.on_check
-          function="Avatar.CheckImpostorMode"
-          parameter="1" />
-	    <menu_item_check.on_click
-	      function="Avatar.SetImpostorMode"
-	      parameter="1" />
-      </menu_item_check>
-      <menu_item_separator />
-      <menu_item_call
-        label="Exceptions..."
-        name="RenderExceptions">
-        <menu_item_call.on_click
-          function="Floater.ToggleOrBringToFront"
-          parameter="avatar_render_settings" />
-      </menu_item_call>
-      </context_menu>
-  <menu_item_separator
-       layout="topleft" name="Impostor seperator"/>
-
+  </context_menu>
+  <menu_item_separator />
   <menu_item_call
-     enabled="false"
-     label="Block Particle Owner"
-     name="Mute Particle">
+     label="Zoom In"
+      name="Zoom In">
+    <menu_item_call.on_click
+       function="Tools.LookAtSelection"
+       parameter="zoom" />
+  </menu_item_call>
+  <menu_item_call
+    enabled="false"
+    label="Pay"
+    name="Pay...">
+    <menu_item_call.on_click
+     function="PayObject" />
+    <menu_item_call.on_enable
+     function="EnablePayAvatar" />
+  </menu_item_call>
+  <menu_item_separator />
+  <menu_item_call
+      label="Object Profile"
+      name="Object Inspect">
     <menu_item_call.on_click
-     function="Particle.Mute" />
+     function="Object.Inspect" />
     <menu_item_call.on_enable
-     function="EnableMuteParticle" />
+     function="Object.EnableInspect" />
   </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
index 05ab4d35a0d..d33c5d5c4d8 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_icon.xml
@@ -148,4 +148,52 @@
       <on_click function="AvatarIcon.Action" parameter="ban_member" />
       <on_enable function="AvatarIcon.Enable" parameter="can_ban_member" />
     </menu_item_call>
+  <menu_item_separator />
+  <context_menu
+   label="Utilities"
+   name="Utilities">
+    <menu_item_call
+     label="Copy Username"
+     name="Copy Username">
+      <menu_item_call.on_click
+       function="AvatarIcon.CopyData"
+       parameter="user_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Display Name"
+     name="Copy Display Name">
+      <menu_item_call.on_click
+       function="AvatarIcon.CopyData"
+       parameter="display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Account Name"
+     name="Copy Account Name">
+      <menu_item_call.on_click
+       function="AvatarIcon.CopyData"
+       parameter="account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="Copy SLurl">
+      <menu_item_call.on_click
+       function="AvatarIcon.CopyData"
+       parameter="slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="Copy ID">
+      <menu_item_call.on_click
+       function="AvatarIcon.CopyData"
+       parameter="id"/>
+    </menu_item_call>
+  </context_menu>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
index f2babde290b..da9c87862c3 100644
--- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml
+++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml
@@ -20,6 +20,8 @@
          function="Avatar.AddFriend" />
         <menu_item_call.on_enable
          function="Avatar.EnableAddFriend" />
+        <menu_item_call.on_visible
+         function="Avatar.EnableAddFriend" />
     </menu_item_call>
     <menu_item_call
      label="IM"
@@ -48,70 +50,170 @@
     
    <menu_item_separator />
 
-     <menu_item_call label="Reset Skeleton"
-       layout="topleft"
-       name="Reset Skeleton">
-       <menu_item_call.on_click
-        function="Avatar.ResetSkeleton" />
-     </menu_item_call>
-
-  <menu_item_call label="Reset Skeleton And Animations"
-       layout="topleft"
-       name="Reset Skeleton And Animations">
-       <menu_item_call.on_click
-        function="Avatar.ResetSkeletonAndAnimations" />
-  </menu_item_call>
-
-   <menu_item_separator />
-   
-     <menu_item_call
+  <context_menu
+   label="Appearance"
+   name="Appearance">
+    <menu_item_call
+      label="Reset Skeleton"
+      name="Reset Skeleton">
+      <menu_item_call.on_click
+       function="Avatar.ResetSkeleton" />
+    </menu_item_call>
+    <menu_item_call
+     label="Reset Skeleton And Animations"
+     name="Reset Skeleton And Animations">
+      <menu_item_call.on_click
+       function="Avatar.ResetSkeletonAndAnimations" />
+    </menu_item_call>
+    <menu_item_separator />
+    <menu_item_check
+      name="RenderNormally"
+      label="Normally Render">
+      <menu_item_check.on_check
+        function="Avatar.CheckImpostorMode"
+        parameter="0" />
+      <menu_item_check.on_click
+	      function="Avatar.SetImpostorMode"
+	      parameter="0" />
+    </menu_item_check>
+    <menu_item_check
+      name="AlwaysRenderFully"
+      label="Always Render">
+      <menu_item_check.on_check
+        function="Avatar.CheckImpostorMode"
+        parameter="2" />
+      <menu_item_check.on_click
+	      function="Avatar.SetImpostorMode"
+	      parameter="2" />
+    </menu_item_check>
+    <menu_item_check
+      name="DoNotRender"
+      label="Never Render">
+      <menu_item_check.on_check
+        function="Avatar.CheckImpostorMode"
+        parameter="1" />
+      <menu_item_check.on_click
+	      function="Avatar.SetImpostorMode"
+	      parameter="1" />
+    </menu_item_check>
+    <menu_item_separator />
+    <menu_item_call
+      label="Render Exceptions..."
+      name="RenderExceptions">
+      <menu_item_call.on_click
+        function="Floater.ToggleOrBringToFront"
+        parameter="avatar_render_settings" />
+    </menu_item_call>
+  </context_menu>
+  <context_menu
+   label="Utilities"
+   name="Utilities">
+    <menu_item_call
+     label="Debug Textures"
+     name="Debug...">
+      <menu_item_call.on_click
+       function="Avatar.Debug" />
+      <menu_item_call.on_visible
+       function="IsGodCustomerService"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Dump XML"
+         name="Dump XML">
+      <menu_item_call.on_click
+       function="Advanced.AppearanceToXML" />
+      <menu_item_call.on_visible
+       function="Advanced.EnableAppearanceToXML"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Username"
+     name="Copy Username">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="user_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Display Name"
+     name="Copy Display Name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Account Name"
+     name="Copy Account Name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="Copy SLurl">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="Copy ID">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="id"/>
+    </menu_item_call>
+  </context_menu>
+  <context_menu
+   label="Manage"
+   name="Manage">
+    <menu_item_call
      enabled="false"
      label="Block"
      name="Avatar Mute">
-        <menu_item_call.on_click
-         function="Avatar.Mute" />
-        <menu_item_call.on_enable
-         function="Avatar.EnableMute" />
+      <menu_item_call.on_click
+       function="Avatar.Mute" />
+      <menu_item_call.on_enable
+       function="Avatar.EnableMute" />
+    </menu_item_call>
+    <menu_item_call
+     enabled="false"
+     label="Block Particle Owner"
+     name="Mute Particle">
+      <menu_item_call.on_click
+       function="Particle.Mute" />
+      <menu_item_call.on_enable
+       function="EnableMuteParticle" />
     </menu_item_call>
     <menu_item_call
      label="Report"
      name="abuse">
-        <menu_item_call.on_click
-         function="Avatar.ReportAbuse" />
-    </menu_item_call>
-        <menu_item_call
-         label="Freeze"
-         name="Freeze...">
-            <menu_item_call.on_click
-             function="Avatar.Freeze" />
-            <menu_item_call.on_visible
-             function="Avatar.EnableFreezeEject"/>
-        </menu_item_call>
-        <menu_item_call
-         label="Eject"
-         name="Eject...">
-            <menu_item_call.on_click
-             function="Avatar.Eject" />
-            <menu_item_call.on_visible
-             function="Avatar.EnableFreezeEject"/>
-        </menu_item_call>
-        <menu_item_call
-         label="Debug Textures"
-         name="Debug...">
-            <menu_item_call.on_click
-             function="Avatar.Debug" />
-            <menu_item_call.on_visible
-             function="IsGodCustomerService"/>
-        </menu_item_call>
-    <menu_item_call
-		 label="Dump XML"
-         name="Dump XML">
-            <menu_item_call.on_click
-             function="Advanced.AppearanceToXML" />
-            <menu_item_call.on_visible
-             function="Advanced.EnableAppearanceToXML"/>
+      <menu_item_call.on_click
+       function="Avatar.ReportAbuse" />
+    </menu_item_call>
+    <menu_item_call
+     label="Freeze"
+     name="Freeze...">
+      <menu_item_call.on_click
+       function="Avatar.Freeze" />
+      <menu_item_call.on_visible
+       function="Avatar.EnableFreezeEject"/>
+    </menu_item_call>
+    <menu_item_call
+     label="Eject"
+     name="Eject...">
+      <menu_item_call.on_click
+       function="Avatar.Eject" />
+      <menu_item_call.on_visible
+       function="Avatar.EnableFreezeEject"/>
     </menu_item_call>
-	    <menu_item_call
+  </context_menu>
+   <menu_item_separator />
+   	    <menu_item_call
          label="Zoom In"
           name="Zoom In">
         <menu_item_call.on_click
@@ -126,63 +228,4 @@
         <menu_item_call.on_enable
          function="EnablePayAvatar" />
     </menu_item_call>
-
-   <menu_item_separator />
-    
- <context_menu
-       label="Render Avatar"
-       layout="topleft"
-        name="Render Avatar">
-      <menu_item_check
-        name="RenderNormally"
-        label="Default">
-        <menu_item_check.on_check
-          function="Avatar.CheckImpostorMode"
-          parameter="0" />
-	    <menu_item_check.on_click
-	      function="Avatar.SetImpostorMode"
-	      parameter="0" />
-      </menu_item_check>
-      <menu_item_check
-        name="AlwaysRenderFully"
-        label="Always">
-        <menu_item_check.on_check
-          function="Avatar.CheckImpostorMode"
-          parameter="2" />
-	    <menu_item_check.on_click
-	      function="Avatar.SetImpostorMode"
-	      parameter="2" />
-      </menu_item_check>
-      <menu_item_check
-        name="DoNotRender"
-        label="Never">
-        <menu_item_check.on_check
-          function="Avatar.CheckImpostorMode"
-          parameter="1" />
-	    <menu_item_check.on_click
-	      function="Avatar.SetImpostorMode"
-	      parameter="1" />
-      </menu_item_check>
-      <menu_item_separator />
-      <menu_item_call
-        label="Exceptions..."
-        name="RenderExceptions">
-        <menu_item_call.on_click
-          function="Floater.ToggleOrBringToFront"
-          parameter="avatar_render_settings" />
-      </menu_item_call>
-      </context_menu>
-
-  <menu_item_separator 
-    layout="topleft"  name="Impostor seperator"/>
-
-  <menu_item_call
-     enabled="false"
-     label="Block Particle Owner"
-     name="Mute Particle">
-    <menu_item_call.on_click
-     function="Particle.Mute" />
-    <menu_item_call.on_enable
-     function="EnableMuteParticle" />
-  </menu_item_call>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index ed362b36e54..0276550fe0f 100644
--- a/indra/newview/skins/default/xui/en/menu_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -221,5 +221,53 @@
 		 name="BanMember">
 			<on_click function="Avatar.DoToSelected" parameter="ban_member" />
 			<on_enable function="Avatar.EnableItem" parameter="can_ban_member" />
-	</menu_item_call>		
+	</menu_item_call>
+  <menu_item_separator name="separator_utils"/>
+  <context_menu
+   label="Utilities"
+   name="utils_menu">
+    <menu_item_call
+     label="Copy Username"
+     name="copy_username">
+      <menu_item_call.on_click
+       function="Avatar.DoToSelected"
+       parameter="copy_username"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Display Name"
+     name="copy_display_name">
+      <menu_item_call.on_click
+       function="Avatar.DoToSelected"
+       parameter="copy_display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Account Name"
+     name="copy_account_name">
+      <menu_item_call.on_click
+       function="Avatar.DoToSelected"
+       parameter="copy_account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="copy_slurl">
+      <menu_item_call.on_click
+       function="Avatar.DoToSelected"
+       parameter="copy_slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="copy_uuid">
+      <menu_item_call.on_click
+       function="Avatar.DoToSelected"
+       parameter="copy_uuid"/>
+    </menu_item_call>
+  </context_menu>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_im_conversation.xml b/indra/newview/skins/default/xui/en/menu_im_conversation.xml
index 43287c6ec36..dd65c1331d9 100644
--- a/indra/newview/skins/default/xui/en/menu_im_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_im_conversation.xml
@@ -95,7 +95,53 @@
         <on_click function="Avatar.GearDoToSelected" parameter="mute_unmute" />
         <on_enable function="Avatar.EnableGearItem" parameter="can_block" />
     </menu_item_check>
-    <menu_item_separator
-     layout="topleft"/>
+  <menu_item_separator name="separator_utils"/>
+  <context_menu
+   label="Utilities"
+   name="utils_menu">
+    <menu_item_call
+     label="Copy Username"
+     name="copy_username">
+      <menu_item_call.on_click
+       function="Avatar.GearDoToSelected"
+       parameter="copy_username"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Display Name"
+     name="copy_display_name">
+      <menu_item_call.on_click
+       function="Avatar.GearDoToSelected"
+       parameter="copy_display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Account Name"
+     name="copy_account_name">
+      <menu_item_call.on_click
+       function="Avatar.GearDoToSelected"
+       parameter="copy_account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="copy_slurl">
+      <menu_item_call.on_click
+       function="Avatar.GearDoToSelected"
+       parameter="copy_slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="copy_uuid">
+      <menu_item_call.on_click
+       function="Avatar.GearDoToSelected"
+       parameter="copy_uuid"/>
+    </menu_item_call>
+  </context_menu>
 </toggleable_menu>
 
diff --git a/indra/newview/skins/default/xui/en/menu_name_field.xml b/indra/newview/skins/default/xui/en/menu_name_field.xml
index 5b02c843e1b..c88373dd080 100644
--- a/indra/newview/skins/default/xui/en/menu_name_field.xml
+++ b/indra/newview/skins/default/xui/en/menu_name_field.xml
@@ -1,28 +1,47 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <toggleable_menu
  name="CopyMenu">
-    <menu_item_call
-     label="Copy Display Name"
-     layout="topleft"
-     name="copy_display">
-      <on_click function="Profile.CopyName" parameter="display"/>
-    </menu_item_call>
-    <menu_item_call
-     label="Copy Agent Name"
-     layout="topleft"
-     name="copy_name">
-        <on_click function="Profile.CopyName" parameter="name"/>
-    </menu_item_call>
-    <menu_item_call
-     label="Copy Agent Id"
-     layout="topleft"
-     name="copy_id">
-      <on_click function="Profile.CopyName" parameter="id"/>
-    </menu_item_call>
-    <menu_item_call
-     label="Copy Agent SLurl"
-     layout="topleft"
-     name="copy_id">
-      <on_click function="Profile.CopyName" parameter="slurl"/>
-    </menu_item_call>  
+  <menu_item_call
+ label="Copy Username"
+ name="copy_username">
+  <menu_item_call.on_click
+     function="Profile.CopyName"
+     parameter="user_name"/>
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_call
+   label="Copy Display Name"
+   name="copy_display_name">
+    <menu_item_call.on_click
+     function="Profile.CopyName"
+     parameter="display_name"/>
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_call
+   label="Copy Account Name"
+   name="account_name">
+    <menu_item_call.on_click
+     function="Profile.CopyName"
+     parameter="account_name"/>
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_call
+   label="Copy SLurl"
+   name="copy_slurl">
+    <menu_item_call.on_click
+     function="Profile.CopyName"
+     parameter="slurl"/>
+    <menu_item_call.on_enable
+     function="RLV.CanShowName" />
+  </menu_item_call>
+  <menu_item_call
+   label="Copy ID"
+   name="copy_uuid">
+    <menu_item_call.on_click
+     function="Profile.CopyName"
+     parameter="id"/>
+  </menu_item_call>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
index c1500d4e7c8..a4d48a92632 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml
@@ -159,4 +159,52 @@
         <menu_item_call.on_visible
          function="Avatar.EnableFreezeEject"/>
     </menu_item_call>
+    <menu_item_separator name="separator_utils" />
+  <context_menu
+   label="Utilities"
+   name="utils_menu">
+    <menu_item_call
+     label="Copy Username"
+     name="copy_username">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="user_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Display Name"
+     name="copy_display_name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Account Name"
+     name="copy_account_name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="copy_slurl">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="copy_uuid">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="id"/>
+    </menu_item_call>
+  </context_menu>
 </context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
index 5f973088fdd..6ebba578682 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
@@ -66,4 +66,52 @@
       function="Avatar.EnableItem"
       parameter="can_offer_teleport"/>
     </menu_item_call>
+    <menu_item_separator name="separator_utils" />
+  <context_menu
+   label="Utilities"
+   name="utils_menu">
+    <menu_item_call
+     label="Copy Username"
+     name="copy_username">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="user_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Display Name"
+     name="copy_display_name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="display_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy Account Name"
+     name="copy_account_name">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="account_name"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy SLurl"
+     name="copy_slurl">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="slurl"/>
+      <menu_item_call.on_enable
+       function="RLV.CanShowName" />
+    </menu_item_call>
+    <menu_item_call
+     label="Copy ID"
+     name="copy_uuid">
+      <menu_item_call.on_click
+       function="Avatar.CopyData"
+       parameter="id"/>
+    </menu_item_call>
+  </context_menu>
 </context_menu>
-- 
GitLab