diff --git a/autobuild.xml b/autobuild.xml
index 9c114ef0b..5cbedba89 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -802,7 +802,7 @@
fmodstudio
+ darwin64
+
+ archive
+
+ hash
+ fe1a606582fb72d5d1c9ec4a2d906830
+ hash_algorithm
+ md5
+ url
+ https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/darwin64/fmodstudio-2.00.03.192211302-darwin64-192211302.tar.bz2
+
+ name
+ darwin64
+
linux
archive
@@ -836,7 +850,7 @@
hash_algorithm
md5
url
- http://depot.alchemyviewer.org/pub/linux/lib/fmodstudio-1.06.07-linux-201507231333.tar.bz2
+ https://depot.alchemyviewer.org/pub/linux/lib/fmodstudio-1.06.07-linux-201507231333.tar.bz2
name
linux
@@ -846,11 +860,11 @@
archive
hash
- 602e798cc969f2d46315775f1dd43c41
+ 54dbd41322a08a1fc333ca6d96af5502
hash_algorithm
md5
url
- https://bitbucket.org/SingularityViewer/libraries/downloads/fmodstudio-2.00.02.191991250-linux64-191991250.tar.bz2
+ /opt/devel/secondlife/pkg/fmodstudio-2.00.02.191991250-linux64-191991250.tar.bz2
name
linux64
@@ -860,11 +874,11 @@
archive
hash
- 2e18d5c43fad15d869dd96860f1e1871
+ e0e87e0423fa42e4d2997b47b92eac6e
hash_algorithm
md5
url
- https://bitbucket.org/SingularityViewer/libraries/downloads/fmodstudio-2.00.02-windows-191832253.tar.bz2
+ https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows/fmodstudio-2.00.03.192211030-windows-192211030.tar.bz2
name
windows
@@ -874,11 +888,11 @@
archive
hash
- 6146c96719680c2f1a8aaab1dabdef8e
+ c2e55e1bfef7e066a0e40867a64b4cce
hash_algorithm
md5
url
- https://bitbucket.org/SingularityViewer/libraries/downloads/fmodstudio-2.00.02-windows64-191832321.tar.bz2
+ https://pkg.alchemyviewer.org/repository/autobuild-internal/fmodstudio/windows64/fmodstudio-2.00.03.192211029-windows64-192211029.tar.bz2
name
windows64
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index b0572a070..f1999410c 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -436,20 +436,67 @@ class ContextUrl : public LLMemberListener
}
};
-class ContextUrlCopy : public LLMemberListener
+class ContextIDUrl : public LLMemberListener
{
-
- bool handleEvent(LLPointer, const LLSD& userdata) override
+protected:
+ std::string getID(const std::string& type) const
{
const auto& url = get_focused_url();
- const auto& type = userdata.asStringRef();
// Empty works like avatar and group, "object" is an object (you needed to be told this)
- const auto& id = type.empty() ? LLUrlAction::getUserID(url) : LLUrlAction::getObjectId(url);
- LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(id));
+ return type.empty() ? LLUrlAction::getUserID(url) : LLUrlAction::getObjectId(url);
+ }
+};
+
+class ContextUrlCopy : public ContextIDUrl
+{
+ bool handleEvent(LLPointer, const LLSD& userdata) override
+ {
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(getID(userdata.asStringRef())));
return true;
}
};
+class ContextUrlExt : public ContextIDUrl
+{
+ bool handleEvent(LLPointer, const LLSD& userdata) override
+ {
+ std::string cmd = userdata.asStringRef();
+ std::string type;
+ const auto sep = cmd.find(',');
+ if (sep != std::string::npos)
+ {
+ type = cmd.substr(sep);
+ cmd = cmd.substr(0, sep);
+ }
+ mExtCallback(cmd, LLUUID(getID(type)));
+ return true;
+ }
+ LLTextEditor::ext_slurl_cb mExtCallback;
+public:
+ ContextUrlExt(LLTextEditor::ext_slurl_cb cb) : mExtCallback(cb) {}
+};
+
+class ContextUrlExtVisible : public ContextIDUrl
+{
+ bool handleEvent(LLPointer, const LLSD& userdata) override
+ {
+ std::string cmd = userdata["data"];
+ std::string type;
+ const auto sep = cmd.find(',');
+ if (sep != std::string::npos)
+ {
+ type = cmd.substr(sep);
+ cmd = cmd.substr(0, sep);
+ }
+
+ LLMenuGL::sMenuContainer->findControl(userdata["control"].asString())->setValue(mExtVCB(cmd, LLUUID(getID(type))));
+ return true;
+ }
+ LLTextEditor::ext_slurl_visible_cb mExtVCB;
+public:
+ ContextUrlExtVisible(LLTextEditor::ext_slurl_visible_cb vcb) : mExtVCB(vcb) {}
+};
+
void LLTextEditor::spell_correct(void* data)
{
@@ -528,11 +575,13 @@ void LLTextEditor::spell_add(void* data)
}
//static
-void LLTextEditor::addMenuListeners()
+void LLTextEditor::addMenuListeners(ext_slurl_cb cb, ext_slurl_visible_cb vcb)
{
(new ContextText)->registerListener(LLMenuGL::sMenuContainer, "Text");
(new ContextUrl)->registerListener(LLMenuGL::sMenuContainer, "Text.Url");
(new ContextUrlCopy)->registerListener(LLMenuGL::sMenuContainer, "Text.Url.CopyUUID");
+ (new ContextUrlExt(cb))->registerListener(LLMenuGL::sMenuContainer, "Text.Url.Ext");
+ (new ContextUrlExtVisible(vcb))->registerListener(LLMenuGL::sMenuContainer, "Text.Url.ExtVisible");
}
void LLTextEditor::setTrackColor( const LLColor4& color )
@@ -721,8 +770,8 @@ LLMenuGL* LLTextEditor::createUrlContextMenu(S32 x, S32 y, const std::string &in
if (addFriendButton && removeFriendButton)
{
- addFriendButton->setEnabled(!isFriend);
- removeFriendButton->setEnabled(isFriend);
+ addFriendButton->setVisible(!isFriend);
+ removeFriendButton->setVisible(isFriend);
}
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index c8a67fdbd..b5d3eb699 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -80,7 +80,11 @@ public:
static boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
static boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
- static void addMenuListeners();
+
+ typedef std::function ext_slurl_cb;
+ typedef std::function ext_slurl_visible_cb;
+ static void addMenuListeners(ext_slurl_cb cb, ext_slurl_visible_cb vcb);
+
void setKeystrokeCallback(const keystroke_signal_t::slot_type& callback);
virtual LLXMLNodePtr getXML(bool save_children = true) const;
diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp
index 1a9636a44..51122e51b 100644
--- a/indra/newview/llfloateravatarlist.cpp
+++ b/indra/newview/llfloateravatarlist.cpp
@@ -312,6 +312,42 @@ BOOL LLFloaterAvatarList::handleRightMouseDown(S32 x, S32 y, MASK mask)
return LLFloater::handleRightMouseDown(x, y, mask);
}
+bool is_nearby(const LLUUID& id)
+{
+ if (id.isNull()) return false;
+ if (const auto inst = LLFloaterAvatarList::getIfExists())
+ return inst->getAvatarEntry(id);
+ uuid_vec_t avatars;
+ LLWorld::instance().getAvatars(&avatars);
+ return std::find(avatars.begin(), avatars.end(), id) != avatars.end();
+}
+
+void track_av(const LLUUID& id)
+{
+ if (auto inst = LLFloaterAvatarList::getIfExists())
+ if (inst->getAvatarEntry(id))
+ {
+ inst->trackAvatar(id);
+ return;
+ }
+
+ LLWorld::pos_map_t avatars;
+ LLWorld::instance().getAvatars(&avatars);
+ LLTracker::trackLocation(avatars[id], LLStringUtil::null, LLStringUtil::null);
+}
+
+void teleport_to(const LLUUID& id)
+{
+ if (auto entry = LLFloaterAvatarList::instanceExists() ? LLFloaterAvatarList::instance().getAvatarEntry(id) : nullptr)
+ gAgent.teleportViaLocation(entry->getPosition());
+ else
+ {
+ LLWorld::pos_map_t avatars;
+ LLWorld::instance().getAvatars(&avatars);
+ gAgent.teleportViaLocation(avatars[id]);
+ }
+}
+
static void cmd_profile(const LLAvatarListEntry* entry);
static void cmd_toggle_mark(LLAvatarListEntry* entry);
static void cmd_ar(const LLAvatarListEntry* entry);
@@ -369,7 +405,7 @@ namespace
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- LLFloaterAvatarList::instance().doCommand(cmd_teleport, true);
+ teleport_to(get_focused_list_id_selected());
return true;
}
};
@@ -388,13 +424,13 @@ void addMenu(view_listener_t* menu, const std::string& name);
void add_radar_listeners()
{
- addMenu(new RadarTrack(), "Radar.Track");
- addMenu(new RadarMark(), "Radar.Mark");
- addMenu(new RadarFocus(), "Radar.Focus");
- addMenu(new RadarFocusPrev(), "Radar.FocusPrev");
- addMenu(new RadarFocusNext(), "Radar.FocusNext");
- addMenu(new RadarTeleportTo(), "Radar.TeleportTo");
- addMenu(new RadarAnnounceKeys(), "Radar.AnnounceKeys");
+ addMenu(new RadarTrack, "Radar.Track");
+ addMenu(new RadarMark, "Radar.Mark");
+ addMenu(new RadarFocus, "Radar.Focus");
+ addMenu(new RadarFocusPrev, "Radar.FocusPrev");
+ addMenu(new RadarFocusNext, "Radar.FocusNext");
+ addMenu(new RadarTeleportTo, "Radar.TeleportTo");
+ addMenu(new RadarAnnounceKeys, "Radar.AnnounceKeys");
}
BOOL LLFloaterAvatarList::postBuild()
@@ -1099,8 +1135,11 @@ void LLFloaterAvatarList::onClickTrack()
LLScrollListItem* item = mAvatarList->getFirstSelected();
if (!item) return;
- LLUUID agent_id = item->getUUID();
+ trackAvatar(item->getUUID());
+}
+void LLFloaterAvatarList::trackAvatar(const LLUUID& agent_id)
+{
if (mTracking && mTrackedAvatar == agent_id)
{
LLTracker::stopTracking(false);
diff --git a/indra/newview/llfloateravatarlist.h b/indra/newview/llfloateravatarlist.h
index 233eb4618..480e52f52 100644
--- a/indra/newview/llfloateravatarlist.h
+++ b/indra/newview/llfloateravatarlist.h
@@ -266,6 +266,7 @@ public:
void focusOnNext(bool marked_only);
void refreshTracker();
+ void trackAvatar(const LLUUID& agent_id);
void trackAvatar(const LLAvatarListEntry* entry) const;
/**
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b82d26c36..a494a025d 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -63,6 +63,7 @@
#include "lldebugview.h"
#include "llenvmanager.h"
#include "llfirstuse.h"
+#include "llfloateravatarlist.h"
#include "llfloateravatartextures.h"
#include "llfloaterbuy.h"
#include "llfloaterbuycontents.h"
@@ -9255,11 +9256,16 @@ class ListShare : public view_listener_t
}
};
+bool can_show_web_profile()
+{
+ return !gSavedSettings.getString("WebProfileURL").empty();
+}
+
+void show_log_browser(const LLUUID& id);
class ListShowLog : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- void show_log_browser(const LLUUID& id);
for (const LLUUID& id : get_focused_list_ids_selected())
show_log_browser(id);
return true;
@@ -9347,24 +9353,50 @@ void parcel_mod_notice_callback(const uuid_vec_t& ids, S32 choice, boost::functi
cb(*it, choice);
}
+bool is_nearby(const LLUUID& id);
+class ListIsNearby : public view_listener_t
+{
+ bool handleEvent(LLPointer event, const LLSD& userdata)
+ {
+ gMenuHolder->findControl(userdata["control"].asString())->setValue(is_nearby(get_focused_list_id_selected()));
+ return true;
+ }
+};
+
+void track_av(const LLUUID& id);
+class ListTrack : public view_listener_t
+{
+ bool handleEvent(LLPointer event, const LLSD& userdata)
+ {
+ track_av(get_focused_list_id_selected());
+ return true;
+ }
+};
+
void send_eject(const LLUUID& avatar_id, bool ban);
+void confirm_eject(const uuid_vec_t& ids)
+{
+ LLNotificationsUtil::add("EjectAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_eject));
+}
class ListEject : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- const uuid_vec_t& ids = get_focused_list_ids_selected();
- LLNotificationsUtil::add("EjectAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_eject));
+ confirm_eject(get_focused_list_ids_selected());
return true;
}
};
void send_freeze(const LLUUID& avatar_id, bool freeze);
+void confirm_freeze(const uuid_vec_t& ids)
+{
+ LLNotificationsUtil::add("FreezeAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_freeze));
+}
class ListFreeze : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- const uuid_vec_t& ids = get_focused_list_ids_selected();
- LLNotificationsUtil::add("FreezeAvatarFullname", create_args(ids, "AVATAR_NAME"), LLSD(), boost::bind(parcel_mod_notice_callback, ids, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2), send_freeze));
+ confirm_freeze(get_focused_list_ids_selected());
return true;
}
};
@@ -9395,22 +9427,28 @@ void estate_bulk_eject(const uuid_vec_t& ids, bool ban, S32 option)
if (!tphome) send_estate_message("kickestate", strings);
}
+void confirm_estate_ban(const uuid_vec_t& ids)
+{
+ LLNotificationsUtil::add("EstateBanUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, true, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
+}
class ListEstateBan : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- const uuid_vec_t& ids = get_focused_list_ids_selected();
- LLNotificationsUtil::add("EstateBanUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, true, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
+ confirm_estate_ban(get_focused_list_ids_selected());
return true;
}
};
+void confirm_estate_kick(const uuid_vec_t& ids)
+{
+ LLNotificationsUtil::add("EstateKickUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, false, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
+}
class ListEstateEject : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- const uuid_vec_t& ids = get_focused_list_ids_selected();
- LLNotificationsUtil::add("EstateKickUser", create_args(ids, "EVIL_USER"), LLSD(), boost::bind(estate_bulk_eject, ids, false, boost::bind(LLNotificationsUtil::getSelectedOption, _1, _2)));
+ confirm_estate_kick(get_focused_list_ids_selected());
return true;
}
};
@@ -9426,6 +9464,59 @@ class ListToggleMute : public view_listener_t
}
};
+struct MenuSLURLDict : public LLSingleton
+{
+ typedef std::function cb;
+ typedef std::function vcb;
+ typedef std::map> slurl_menu_map;
+ slurl_menu_map mEntries;
+ MenuSLURLDict()
+ {
+ // Text Editor menus
+ LLTextEditor::setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
+ LLTextEditor::setIsFriendCallback(LLAvatarActions::isFriend);
+ LLTextEditor::addMenuListeners(boost::bind(&MenuSLURLDict::action, this, _1, _2), boost::bind(&MenuSLURLDict::visible, this, _1, _2));
+
+ // Add the entries
+ insert("ShowWebProfile", boost::bind(LLAvatarActions::showProfile, _1, true), boost::bind(can_show_web_profile));
+ insert("Pay", LLAvatarActions::pay);
+ insert("Call", LLAvatarActions::startCall);
+ insert("Share", LLAvatarActions::share);
+ insert("AbuseReport", LLFloaterReporter::showFromObject);
+ insert("InviteToGroup", [](const LLUUID& id) { LLAvatarActions::inviteToGroup(id); });
+ insert("BanFromGroup", [](const LLUUID& id) { ban_from_group(uuid_vec_t(1, id)); });
+ insert("ShowLog", [](const LLUUID& id) { show_log_browser(id); });
+ insert("OfferTeleport", [](const LLUUID& id) { LLAvatarActions::offerTeleport(id); }, [](const LLUUID& id) { return LLAvatarActions::canOfferTeleport(id); });
+ insert("RequestTeleport", LLAvatarActions::teleportRequest);
+ void teleport_to(const LLUUID& id);
+ insert("TeleportTo", teleport_to, is_nearby);
+ insert("Focus", LLFloaterAvatarList::setFocusAvatar, is_nearby);
+ insert("ParcelEject", [](const LLUUID& id) { confirm_eject(uuid_vec_t(1, id)); }, is_nearby);
+ insert("Freeze", [](const LLUUID& id) { confirm_freeze(uuid_vec_t(1, id)); }, is_nearby);
+ insert("EstateBan", [](const LLUUID& id) { confirm_estate_ban(uuid_vec_t(1, id)); }, is_nearby);
+ insert("EstateEject", [](const LLUUID & id) { confirm_estate_kick(uuid_vec_t(1, id)); }, is_nearby);
+ insert("Mute", LLAvatarActions::toggleBlock, [](const LLUUID& id) { return LLAvatarActions::canBlock(id) && !LLAvatarActions::isBlocked(id); });
+ insert("Unmute", LLAvatarActions::toggleBlock, LLAvatarActions::isBlocked);
+ }
+
+ void insert(const std::string& key, cb callback, vcb vcallback = nullptr)
+ {
+ mEntries[key] = std::make_pair(callback, vcallback);
+ }
+
+ void action(const std::string& cmd, LLUUID id) const
+ {
+ auto it = mEntries.find(cmd);
+ if (it != mEntries.end())
+ (*it).second.first(id);
+ }
+ bool visible(const std::string& cmd, LLUUID id) const
+ {
+ auto it = mEntries.find(cmd);
+ return it == mEntries.end() || !(*it).second.second || (*it).second.second(id);
+ }
+};
+
LLMediaCtrl* get_focused_media_ctrl()
{
auto media_ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus());
@@ -9807,6 +9898,8 @@ void initialize_menus()
addMenu(new ListStartConference(), "List.StartConference");
addMenu(new ListStartIM(), "List.StartIM");
addMenu(new ListAbuseReport(), "List.AbuseReport");
+ addMenu(new ListIsNearby, "List.IsNearby");
+ addMenu(new ListTrack, "List.Track");
addMenu(new ListEject(), "List.ParcelEject");
addMenu(new ListFreeze(), "List.Freeze");
addMenu(new ListEstateBan(), "List.EstateBan");
@@ -9815,10 +9908,7 @@ void initialize_menus()
add_radar_listeners();
- // Text Editor menus
- LLTextEditor::setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0));
- LLTextEditor::setIsFriendCallback(LLAvatarActions::isFriend);
- LLTextEditor::addMenuListeners();
+ MenuSLURLDict::getInstance();
// Media Ctrl menus
addMenu(new MediaCtrlCopyURL(), "Copy.PageURL");
diff --git a/indra/newview/skins/default/xui/en-us/floater_active_speakers.xml b/indra/newview/skins/default/xui/en-us/floater_active_speakers.xml
index 9a6bf7117..f90862e9f 100644
--- a/indra/newview/skins/default/xui/en-us/floater_active_speakers.xml
+++ b/indra/newview/skins/default/xui/en-us/floater_active_speakers.xml
@@ -6,13 +6,13 @@
-
-
+
diff --git a/indra/newview/skins/default/xui/en-us/menu_avs_list.xml b/indra/newview/skins/default/xui/en-us/menu_avs_list.xml
index 1e66307c2..acec8e1b8 100644
--- a/indra/newview/skins/default/xui/en-us/menu_avs_list.xml
+++ b/indra/newview/skins/default/xui/en-us/menu_avs_list.xml
@@ -4,82 +4,118 @@
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/indra/newview/skins/default/xui/en-us/menu_local_avs.xml b/indra/newview/skins/default/xui/en-us/menu_local_avs.xml
index 2db0e2275..49c076252 100644
--- a/indra/newview/skins/default/xui/en-us/menu_local_avs.xml
+++ b/indra/newview/skins/default/xui/en-us/menu_local_avs.xml
@@ -1,10 +1,10 @@
-
+
-
+
Rumplstiltskin Califragilistic