diff options
24 files changed, 390 insertions, 205 deletions
@@ -19,7 +19,7 @@ $ cd build-`uname -s|tr '[:upper:]' '[:lower:]'`-`uname -m` ### Arch ``` -$ sudo pacman -S cmake base-devel python apr-util boost fltk glm glu hunspell minizip nanosvg libnghttp2 openjpeg2 libpipewire sdl2 vlc libvorbis xxhash +$ sudo pacman -S cmake base-devel sed python apr-util boost fltk glm glu hunspell minizip nanosvg libnghttp2 openjpeg2 libpipewire sdl2 vlc libvorbis xxhash $ export LL_BUILD="-O3 -std=c++20 -fPIC -DLL_LINUX=1" ``` build with FMOD Studio: ([register with fmod to get linux package][fmod] and then place the `.tar.gz` in `~/Downloads`) diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 69332e36b6..1f9a841032 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -106,6 +106,10 @@ bool hasHIDPI = 0; # include <X11/Xutil.h> #endif //LL_X11 +#if LL_WINDOWS && !LL_MESA_HEADLESS +#pragma comment(lib, "dinput8") +#endif + // TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar // set of reasons): Stash a pointer to the LLWindowSDL object here and // maintain in the constructor and destructor. This assumes that there will diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index bfd313cdde..ad5732a8cc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1161,6 +1161,39 @@ <key>Value</key> <integer>1</integer> </map> + <key>EnableDiscord</key> + <map> + <key>Comment</key> + <string>When set, connect to Discord to enable Rich Presence</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowDiscordActivityDetails</key> + <map> + <key>Comment</key> + <string>When set, show avatar name on Discord Rich Presence</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowDiscordActivityState</key> + <map> + <key>Comment</key> + <string>When set, show location on Discord Rich Presence</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>EnableDiskCacheDebugInfo</key> <map> <key>Comment</key> @@ -14336,17 +14369,6 @@ <key>Value</key> <integer>0</integer> </map> - <key>MPVNearMeRange</key> - <map> - <key>Comment</key> - <string>Search radius in the people panel</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>F32</string> - <key>Value</key> - <integer>4096</integer> - </map> <key>RenderVSyncEnabled</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d69fe8328d..1cd58b7101 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1289,6 +1289,12 @@ const LLVector3 &LLAgent::getPositionAgent() return mFrameAgent.getOrigin(); } +void LLAgent::setAvatarsPositions(const std::map<LLUUID, LLVector3d>& avatarsPositions) +{ + mAvatarsPositions.clear(); + mAvatarsPositions = avatarsPositions; +} + boost::signals2::connection LLAgent::whenPositionChanged(position_signal_t::slot_type fn) { return mOnPositionChanged.connect(fn); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index b475782946..a2d2ecea9f 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -195,6 +195,8 @@ public: // Call once per frame to update position, angles (radians). void updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y); void setPositionAgent(const LLVector3 ¢er); + void setAvatarsPositions(const std::map<LLUUID, LLVector3d>& avatarsPositions); + const std::map<LLUUID, LLVector3d>& getAvatarsPositions() const { return mAvatarsPositions;} boost::signals2::connection whenPositionChanged(position_signal_t::slot_type fn); @@ -205,6 +207,7 @@ private: position_signal_t mOnPositionChanged; LLVector3d mLastTestGlobal; + std::map<LLUUID, LLVector3d> mAvatarsPositions; //-------------------------------------------------------------------- // Velocity diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index cc0556b601..cc40cc6c07 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -278,6 +278,16 @@ using namespace LL; #pragma warning (disable:4702) #endif +#ifdef LL_DISCORD +#define DISCORDPP_IMPLEMENTATION +#include <discordpp.h> +static std::shared_ptr<discordpp::Client> gDiscordClient; +static uint64_t gDiscordTimestampsStart; +static std::string gDiscordActivityDetails; +static int32_t gDiscordPartyCurrentSize; +static int32_t gDiscordPartyMaxSize; +#endif + static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor @@ -1364,7 +1374,10 @@ bool LLAppViewer::doFrame() TimePoint fpsLimitFrameStartTime = std::chrono::steady_clock::now(); #ifdef LL_DISCORD - LLStartUp::runDiscordCallbacks(); + { + LL_PROFILE_ZONE_NAMED("discord_callbacks"); + discordpp::RunCallbacks(); + } #endif LL_RECORD_BLOCK_TIME(FTM_FRAME); @@ -5926,3 +5939,104 @@ void LLAppViewer::metricsSend(bool enable_reporting) // resolution in time. gViewerAssetStats->restart(); } + +#ifdef LL_DISCORD + +void LLAppViewer::initDiscordSocial() +{ + gDiscordPartyCurrentSize = 1; + gDiscordPartyMaxSize = 0; + gDiscordTimestampsStart = time(nullptr); + gDiscordClient = std::make_shared<discordpp::Client>(); + gDiscordClient->SetApplicationId(1393451183741599796); + updateDiscordActivity(); +} + +void LLAppViewer::updateDiscordActivity() +{ + LL_PROFILE_ZONE_SCOPED; + + static LLCachedControl<bool> integration_enabled(gSavedSettings, "EnableDiscord", true); + if (!integration_enabled) + { + gDiscordClient->ClearRichPresence(); + return; + } + + discordpp::Activity activity; + activity.SetType(discordpp::ActivityTypes::Playing); + discordpp::ActivityTimestamps timestamps; + timestamps.SetStart(gDiscordTimestampsStart); + activity.SetTimestamps(timestamps); + + if (gAgent.getID() == LLUUID::null) + { + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); + return; + } + + static LLCachedControl<bool> show_details(gSavedSettings, "ShowDiscordActivityDetails", false); + if (show_details) + { + if (gDiscordActivityDetails.empty()) + { + LLAvatarName av_name; + LLAvatarNameCache::get(gAgent.getID(), &av_name); + gDiscordActivityDetails = av_name.getUserName(); + auto displayName = av_name.getDisplayName(); + if (gDiscordActivityDetails != displayName) + gDiscordActivityDetails = displayName + " (" + gDiscordActivityDetails + ")"; + } + activity.SetDetails(gDiscordActivityDetails); + } + + auto agent_pos_region = gAgent.getPositionAgent(); + S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f); + S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f); + S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f); + F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared(); + const F32 FLY_CUTOFF = 6.f; + const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; + const F32 WALK_CUTOFF = 1.5f; + const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; + if (velocity_mag_sq > FLY_CUTOFF_SQ) + { + pos_x -= pos_x % 4; + pos_y -= pos_y % 4; + } + else if (velocity_mag_sq > WALK_CUTOFF_SQ) + { + pos_x -= pos_x % 2; + pos_y -= pos_y % 2; + } + + std::string location = "Hidden Region"; + static LLCachedControl<bool> show_state(gSavedSettings, "ShowDiscordActivityState", false); + if (show_state) + { + location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z); + } + activity.SetState(location); + + discordpp::ActivityParty party; + party.SetId(location); + party.SetCurrentSize(gDiscordPartyCurrentSize); + party.SetMaxSize(gDiscordPartyMaxSize); + activity.SetParty(party); + + gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); +} + +void LLAppViewer::updateDiscordPartyCurrentSize(int32_t size) +{ + gDiscordPartyCurrentSize = size; + updateDiscordActivity(); +} + +void LLAppViewer::updateDiscordPartyMaxSize(int32_t size) +{ + gDiscordPartyMaxSize = size; + updateDiscordActivity(); +} + +#endif diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 3da0246ccf..b7202d0c91 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -250,6 +250,13 @@ public: // Note: mQuitRequested can be aborted by user. void outOfMemorySoftQuit(); +#ifdef LL_DISCORD + static void initDiscordSocial(); + static void updateDiscordActivity(); + static void updateDiscordPartyCurrentSize(int32_t size); + static void updateDiscordPartyMaxSize(int32_t size); +#endif + protected: virtual bool initWindow(); // Initialize the viewer's window. virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 5f9d03ca66..e29be0c757 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -48,12 +48,11 @@ #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings #include "lltooldraganddrop.h" -#include "llworld.h" static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); // Last interaction time update period. -static const F32 LIT_UPDATE_PERIOD = 1; +static const F32 LIT_UPDATE_PERIOD = 5; // Maximum number of avatars that can be added to a list in one pass. // Used to limit time spent for avatar list update per frame. @@ -205,13 +204,25 @@ void LLAvatarList::draw() if ((mShowLastInteractionTime || mAvatarDistance || mAvatarArrivalTime) && mLITUpdateTimer->hasExpired()) { - if (mAvatarArrivalTime) + if (mAvatarArrivalTime || mAvatarDistance) { - updateAvatarArrivalTime(); - } - if (mAvatarDistance) - { - updateAvatarDistance(); + std::vector<LLPanel*> items; + getItems(items); + for (auto it = items.begin(); it != items.end(); it++) + { + auto item = static_cast<LLAvatarListItem*>(*it); + if (mAvatarArrivalTime) + { + auto secs_since = LLDate::now().secondsSinceEpoch() - LLRecentPeople::instance().getArrivalTimeByID(item->getAvatarId()); + if (secs_since >= 0) + item->setAvatarArrivalTime(secs_since); + } + if (mAvatarDistance) + { + auto avatarsPositions = gAgent.getAvatarsPositions(); + item->setAvatarDistance(dist_vec(avatarsPositions[item->getAvatarId()], gAgent.getPositionGlobal())); + } + } } if (mShowLastInteractionTime) { @@ -554,46 +565,6 @@ void LLAvatarList::computeDifference( LLCommonUtils::computeDifference(vnew_unsorted, vcur, vadded, vremoved); } -void LLAvatarList::updateAvatarArrivalTime() -{ - std::vector<LLPanel*> items; - getItems(items); - auto uuids = getIDs(); - std::vector<LLVector3d> positions; - auto me_pos = gAgent.getPositionGlobal(); - LLWorld::getInstance()->getAvatars(&uuids, &positions, me_pos, gSavedSettings.getF32("MPVNearMeRange")); - LLRecentPeople::instance().updateAvatarsArrivalTime(uuids); - for (auto it = items.begin(); it != items.end(); it++) - { - auto item = static_cast<LLAvatarListItem*>(*it); - auto secs_since = LLDate::now().secondsSinceEpoch() - LLRecentPeople::instance().getArrivalTimeByID(item->getAvatarId()); - if (secs_since >= 0) - item->setAvatarArrivalTime(secs_since); - } -} - - void LLAvatarList::updateAvatarDistance() -{ - std::vector<LLPanel*> items; - getItems(items); - auto uuids = getIDs(); - std::vector<LLVector3d> positions; - auto me_pos = gAgent.getPositionGlobal(); - LLWorld::getInstance()->getAvatars(&uuids, &positions, me_pos, gSavedSettings.getF32("MPVNearMeRange")); - std::map <LLUUID, LLVector3d> avatarsPositions; - auto pos_it = positions.begin(); - auto id_it = uuids.begin(); - for (;pos_it != positions.end() && id_it != uuids.end(); ++pos_it, ++id_it) - { - avatarsPositions[*id_it] = *pos_it; - } - for (auto it = items.begin(); it != items.end(); it++) - { - auto item = static_cast<LLAvatarListItem*>(*it); - item->setAvatarDistance(dist_vec(avatarsPositions[item->getAvatarId()], me_pos)); - } -} - // Refresh shown time of our last interaction with all listed avatars. void LLAvatarList::updateLastInteractionTimes() { diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 97b4f05985..e6e0728a3f 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -114,8 +114,6 @@ protected: const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved); - void updateAvatarArrivalTime(); - void updateAvatarDistance(); void updateLastInteractionTimes(); void rebuildNames(); void onItemDoubleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c881821153..36a68a7017 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -366,6 +366,11 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering +#ifdef LL_DISCORD + gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); + gSavedSettings.getControl("ShowDiscordActivityDetails")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); + gSavedSettings.getControl("ShowDiscordActivityState")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity)); +#endif } void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 72fa553023..01541968de 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -160,6 +160,7 @@ public: mAvatarsPositions[*id_it] = *pos_it; } }; + const id_to_pos_map_t& getAvatarsPositions() const { return mAvatarsPositions; } protected: virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const @@ -841,10 +842,15 @@ void LLPanelPeople::updateNearbyList() std::vector<LLVector3d> positions; - LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); + LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); mNearbyList->setDirty(); +#ifdef LL_DISCORD + if (gSavedSettings.getBOOL("EnableDiscord")) + LLAppViewer::updateDiscordPartyMaxSize(mNearbyList->getIDs().size()); +#endif DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); + gAgent.setAvatarsPositions(DISTANCE_COMPARATOR.getAvatarsPositions()); LLActiveSpeakerMgr::instance().update(true); } diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 4956c188fb..12a9d5e9b7 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -1026,6 +1026,10 @@ void LLLocalSpeakerMgr::updateSpeakerList() uuid_vec_t avatar_ids; std::vector<LLVector3d> positions; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); +#ifdef LL_DISCORD + if (gSavedSettings.getBOOL("EnableDiscord")) + LLAppViewer::updateDiscordPartyCurrentSize(avatar_ids.size()); +#endif for(U32 i=0; i<avatar_ids.size(); i++) { setSpeaker(avatar_ids[i]); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 834b99555e..8d010553a0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -217,12 +217,6 @@ #include "fsfloatersearch.h" -#ifdef LL_DISCORD -#define DISCORDPP_IMPLEMENTATION -#include <discordpp.h> -static std::shared_ptr<discordpp::Client> gDiscordClient; -#endif - // // exported globals // @@ -758,14 +752,7 @@ bool idle_startup() } #ifdef LL_DISCORD - gDiscordClient = std::make_shared<discordpp::Client>(); - gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) { - if (status == discordpp::Client::Status::Ready) { - discordpp::Activity activity; - activity.SetType(discordpp::ActivityTypes::Playing); - gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {}); - } - }); + LLAppViewer::initDiscordSocial(); #endif // @@ -3447,35 +3434,6 @@ bool LLStartUp::startLLProxy() return proxy_ok; } -#ifdef LL_DISCORD - -void LLStartUp::runDiscordCallbacks() -{ - discordpp::RunCallbacks(); -} - -void LLStartUp::handleDiscordSocial() -{ - static const uint64_t DISCORD_APPLICATION_ID = 1393451183741599796; - discordpp::AuthorizationArgs discordAuthArgs{}; - discordAuthArgs.SetClientId(DISCORD_APPLICATION_ID); - discordAuthArgs.SetScopes(discordpp::Client::GetDefaultPresenceScopes()); - auto discordCodeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier(); - discordAuthArgs.SetCodeChallenge(discordCodeVerifier.Challenge()); - gDiscordClient->Authorize(discordAuthArgs, [discordCodeVerifier](auto result, auto code, auto redirectUri) { - if (result.Successful()) { - gDiscordClient->GetToken(DISCORD_APPLICATION_ID, code, discordCodeVerifier.Verifier(), redirectUri, [](discordpp::ClientResult result, std::string accessToken, std::string, discordpp::AuthorizationTokenType, int32_t, std::string) { - gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, accessToken, [](discordpp::ClientResult result) { - if (result.Successful()) - gDiscordClient->Connect(); - }); - }); - } - }); -} - -#endif - bool login_alert_done(const LLSD& notification, const LLSD& response) { LLPanelLogin::giveFocus(); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index cf1d38bb18..a827fbc487 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -128,12 +128,6 @@ public: static bool startLLProxy(); // Initialize the SOCKS 5 proxy static LLViewerStats::PhaseMap& getPhases() { return *sPhases; } - -#ifdef LL_DISCORD - static void runDiscordCallbacks(); - static void handleDiscordSocial(); -#endif - private: friend class LLStartupListener; static LLSLURL sStartSLURL; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 0d71bbe9ce..4ad5e3837f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -145,6 +145,7 @@ #include "llwindow.h" #include "llpathfindingmanager.h" #include "llstartup.h" +#include "llappviewer.h" #include "boost/unordered_map.hpp" #include <boost/regex.hpp> #include <boost/algorithm/string.hpp> @@ -9037,13 +9038,6 @@ void handle_report_bug(const LLSD& param) LLWeb::loadURLExternal(url); } -#ifdef LL_DISCORD -void handle_discord_social(const LLSD& param) -{ - LLStartUp::handleDiscordSocial(); -} -#endif - void handle_buy_currency_test() { std::string url = @@ -10024,9 +10018,6 @@ void initialize_menus() commit.add("Advanced.WebContentTest", boost::bind(&handle_web_content_test, _2)); // this one opens the Web Content floater commit.add("Advanced.ShowURL", boost::bind(&handle_show_url, _2)); commit.add("Advanced.ReportBug", boost::bind(&handle_report_bug, _2)); -#ifdef LL_DISCORD - commit.add("Advanced.DiscordSocial", boost::bind(&handle_discord_social, _2)); -#endif view_listener_t::addMenu(new LLAdvancedBuyCurrencyTest(), "Advanced.BuyCurrencyTest"); view_listener_t::addMenu(new LLAdvancedDumpSelectMgr(), "Advanced.DumpSelectMgr"); view_listener_t::addMenu(new LLAdvancedDumpInventory(), "Advanced.DumpInventory"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 47d7d42bf7..86bd11d1eb 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3072,6 +3072,11 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) } } +#ifdef LL_DISCORD + if (gSavedSettings.getBOOL("EnableDiscord")) + LLAppViewer::updateDiscordActivity(); +#endif + if ( LLTracker::isTracking(NULL) ) { // Check distance to beacon, if < 5m, remove beacon diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e8ad7822de..7ffe2b7c92 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -817,15 +817,14 @@ LLVOAvatar::~LLVOAvatar() { sInstances.remove(this); - if (gSavedSettings.getBOOL("IMShowArrivalsDepartures")) + static LLCachedControl<bool> show_arrival_departures(gSavedSettings, "IMShowArrivalsDepartures", false); + if (show_arrival_departures && !isSelf()) { - LLAvatarName av_name; - LLAvatarNameCache::get(getID(), &av_name); - auto display_name = av_name.getDisplayName(); - if (!display_name.empty()) + auto full_name = getFullname(); + if (!full_name.empty()) { - LLChat chat{llformat("%s left.", display_name.c_str())}; - chat.mFromName = display_name; + LLChat chat{llformat("%s left.", full_name.c_str())}; + chat.mFromName = full_name; chat.mFromID = getID(); LLSD args; args["COLOR"] = "ChatHistoryTextColor"; @@ -2582,31 +2581,21 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, { mDebugExistenceTimer.reset(); debugAvatarRezTime("AvatarRezArrivedNotification", "avatar arrived"); - if (gSavedSettings.getBOOL("IMShowArrivalsDepartures")) - { - uuid_vec_t uuids; - std::vector<LLVector3d> positions; - LLWorld::getInstance()->getAvatars(&uuids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); - auto pos_it = positions.begin(); - auto id_it = uuids.begin(); - for (;pos_it != positions.end() && id_it != uuids.end(); ++pos_it, ++id_it) - { - if (*id_it == getID() && !isSelf()) - { - LLAvatarName av_name; - LLAvatarNameCache::get(getID(), &av_name); - auto display_name = av_name.getDisplayName(); - if (!display_name.empty()) - { - LLChat chat{llformat("%s arrived (%.1f m).", display_name.c_str(), dist_vec(*pos_it, gAgent.getPositionGlobal()))}; - chat.mFromName = display_name; - chat.mFromID = getID(); - LLSD args; - args["COLOR"] = "ChatHistoryTextColor"; - LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); - } - break; - } + static LLCachedControl<bool> show_arrival_departures(gSavedSettings, "IMShowArrivalsDepartures", false); + if (show_arrival_departures && !isSelf()) + { + auto full_name = getFullname(); + if (!full_name.empty()) + { + auto avatarsPositions = gAgent.getAvatarsPositions(); + auto id = getID(); + auto avatarPosition = avatarsPositions[id]; + LLChat chat{std::string{full_name + " arrived" + (avatarPosition.isExactlyZero() ? "" : llformat(" (%.1f m)", dist_vec(avatarPosition, gAgent.getPositionGlobal()))) + "."}}; + chat.mFromName = full_name; + chat.mFromID = id; + LLSD args; + args["COLOR"] = "ChatHistoryTextColor"; + LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); } } } diff --git a/indra/newview/rlvdefines.h b/indra/newview/rlvdefines.h index 649aa75d14..4437adcf1b 100644 --- a/indra/newview/rlvdefines.h +++ b/indra/newview/rlvdefines.h @@ -98,6 +98,7 @@ namespace Rlv SitGround, Unsit, Detach, + RemOutfit, GetInv, Attach, AttachOver, diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 066543987f..2cc06b3bbc 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -29,6 +29,7 @@ #include "llagent.h" #include "llstartup.h" #include "llappearancemgr.h" +#include "llinventoryfunctions.h" #include "llinventorymodel.h" #include "llmoveview.h" #include "llviewercontrol.h" @@ -243,9 +244,11 @@ ECmdRet ReplyHandler<EBehaviour::GetSitID>::onCommand(const RlvCommand& rlvCmd, template<> template<> ECmdRet ReplyHandler<EBehaviour::GetInv>::onCommand(const RlvCommand& rlvCmd, std::string& strReply) { - auto folderID = findDescendentCategoryIDByName(gInventory.getRootFolderID(), "#RLV"); - if (folderID == LLUUID::null) + auto folderID = gInventory.getRootFolderID(); + LLNameCategoryCollector has_name("#RLV"); + if (!gInventory.hasMatchingDirectDescendent(folderID, has_name)) return ECmdRet::FailedNoSharedRoot; + folderID = findDescendentCategoryIDByName(folderID, "#RLV"); strReply = ""; LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; @@ -305,55 +308,91 @@ ECmdRet ForceHandler<EBehaviour::Unsit>::onCommand(const RlvCommand& rlvCmd) } template<> template<> -ECmdRet ForceHandler<EBehaviour::Attach>::onCommand(const RlvCommand& rlvCmd) +ECmdRet ForceHandler<EBehaviour::RemOutfit>::onCommand(const RlvCommand& rlvCmd) { - auto rlvFolderID = findDescendentCategoryIDByName(gInventory.getRootFolderID(), "#RLV"); - if (rlvFolderID == LLUUID::null) - return ECmdRet::FailedNoSharedRoot; std::vector<std::string> optionList; auto option = rlvCmd.getOption(); - if (!option.empty()) + if (option.empty()) + { + LLAppearanceMgr::instance().removeAllClothesFromAvatar(); + } + else { - auto folderID = findDescendentCategoryIDByName(rlvFolderID, option); - if (folderID == LLUUID::null) + LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(option); + if (type >= LLWearableType::WT_SHAPE + && type < LLWearableType::WT_COUNT + && (gAgentWearables.getWearableCount(type) > 0)) { - Util::parseStringList(option, optionList, "/"); - auto iter = optionList.begin(); - for(; optionList.end() != iter; ++iter) - { - auto name = *iter; - if (!name.empty()) - folderID = findDescendentCategoryIDByName(folderID, name); - } + U32 wearable_index = gAgentWearables.getWearableCount(type) - 1; + LLUUID item_id = gAgentWearables.getWearableItemID(type,wearable_index); + LLAppearanceMgr::instance().removeItemFromAvatar(item_id); } - LLAppearanceMgr::instance().replaceCurrentOutfit(folderID); } return ECmdRet::Succeeded; } +#define RESTRAINED_LOVE_OUTFIT(A) \ + auto folderID = gInventory.getRootFolderID();\ + LLNameCategoryCollector has_name("#RLV");\ + if (!gInventory.hasMatchingDirectDescendent(folderID, has_name))\ + return ECmdRet::FailedNoSharedRoot;\ + folderID = findDescendentCategoryIDByName(folderID, "#RLV");\ + std::vector<std::string> optionList;\ + auto option = rlvCmd.getOption();\ + if (!option.empty())\ + {\ + folderID = findDescendentCategoryIDByName(folderID, option);\ + if (folderID == LLUUID::null)\ + {\ + Util::parseStringList(option, optionList, "/");\ + auto iter = optionList.begin();\ + for(; optionList.end() != iter; ++iter)\ + {\ + auto name = *iter;\ + if (!name.empty())\ + folderID = findDescendentCategoryIDByName(folderID, name);\ + }\ + }\ + A\ + }\ + return ECmdRet::Succeeded; + +#define RESTRAINED_LOVE_REPLACE \ + LLAppearanceMgr::instance().replaceCurrentOutfit(folderID); + +#define RESTRAINED_LOVE_ADD \ + LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); + +template<> template<> +ECmdRet ForceHandler<EBehaviour::Attach>::onCommand(const RlvCommand& rlvCmd) +{ + RESTRAINED_LOVE_OUTFIT(RESTRAINED_LOVE_REPLACE); +} + template<> template<> ECmdRet ForceHandler<EBehaviour::AttachOver>::onCommand(const RlvCommand& rlvCmd) { - auto rlvFolderID = findDescendentCategoryIDByName(gInventory.getRootFolderID(), "#RLV"); - if (rlvFolderID == LLUUID::null) + RESTRAINED_LOVE_OUTFIT(RESTRAINED_LOVE_ADD); +} + +template<> template<> +ECmdRet ForceHandler<EBehaviour::Detach>::onCommand(const RlvCommand& rlvCmd) +{ + auto folderID = gInventory.getRootFolderID(); + LLNameCategoryCollector has_name("#RLV"); + if (!gInventory.hasMatchingDirectDescendent(folderID, has_name)) return ECmdRet::FailedNoSharedRoot; + folderID = findDescendentCategoryIDByName(folderID, "#RLV"); std::vector<std::string> optionList; auto option = rlvCmd.getOption(); if (!option.empty()) { - auto folderID = findDescendentCategoryIDByName(rlvFolderID, option); - if (folderID == LLUUID::null) + LLNameCategoryCollector is_named(option); + if (gInventory.hasMatchingDirectDescendent(folderID, is_named)) { - Util::parseStringList(option, optionList, "/"); - auto iter = optionList.begin(); - for(; optionList.end() != iter; ++iter) - { - auto name = *iter; - if (!name.empty()) - folderID = findDescendentCategoryIDByName(folderID, name); - } + folderID = findDescendentCategoryIDByName(folderID, option); + LLAppearanceMgr::instance().takeOffOutfit(folderID); } - LLAppearanceMgr::instance().addCategoryToCurrentOutfit(folderID); } return ECmdRet::Succeeded; } diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 4a0b394acb..2c14434194 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -60,8 +60,10 @@ BehaviourDictionary::BehaviourDictionary() addEntry(new ForceProcessor<EBehaviour::Sit>("sit")); addEntry(new ForceProcessor<EBehaviour::SitGround>("sitground")); addEntry(new ForceProcessor<EBehaviour::Unsit>("unsit")); + addEntry(new ForceProcessor<EBehaviour::RemOutfit>("remoutfit")); addEntry(new ForceProcessor<EBehaviour::Attach>("attach")); addEntry(new ForceProcessor<EBehaviour::AttachOver>("attachover")); + addEntry(new ForceProcessor<EBehaviour::Detach>("detach")); // AddRem addEntry(new BehaviourProcessor<EBehaviour::Sit>("sit")); diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 04514e8a52..5fff9b7bc0 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -110,13 +110,6 @@ </menu_item_call> <menu_item_separator/> <menu_item_call - label="Discord Social" - name="Discord Social"> - <menu_item_call.on_click - function="Advanced.DiscordSocial"/> - </menu_item_call> - <menu_item_separator/> - <menu_item_call label="About [APP_NAME]" name="About Second Life"> <menu_item_call.on_click diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index cf76a1ace9..e8a8e7e4c1 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1876,13 +1876,6 @@ function="World.EnvPreset" </menu_item_call> <menu_item_separator/> - <menu_item_call - label="Discord Social" - name="Discord Social"> - <menu_item_call.on_click - function="Advanced.DiscordSocial"/> - </menu_item_call> - <menu_item_separator/> <menu_item_call label="Bumps, Pushes & Hits" name="Bumps, Pushes &amp; Hits"> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index f1c03fdaa8..0766cc06ee 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -177,6 +177,25 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip function="People.DelFriend" /> </dnd_button> </panel> + <slider + control_name="NearMeRange" + decimal_digits="0" + increment="1" + follows="left|top" + left="5" + min_val="0" + max_val="4096" + label="Range:" + name="near_me_range" + tool_tip="Nearby people range" + width="230"/> + <text + type="string" + follows="left|top" + left_delta="225" + name="near_me_range_text2"> + m + </text> <layout_stack clip="false" follows="all" @@ -216,7 +235,7 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip <avatar_list allow_select="true" follows="all" - height="211" + height="197" ignore_online_status="true" layout="topleft" left="3" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index f1a38dc894..809c001904 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -1,15 +1,31 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<panel + <panel border="true" follows="left|top|right|bottom" - height="408" - label="Communication" + height="438" + label="Privacy" layout="topleft" left="102" - name="im" + name="Privacy panel" top="1" width="517"> + <tab_container + top_pad="0" + enabled="true" + follows="left|top" + height="430" + width="517" + left_delta="0" + name="privacy_tab_container" + tab_position="top" + tab_stop="false"> + <panel + label="General" + name="privacy_preferences_general" + layout="topleft" + follows="top|left"> + <panel.string name="log_in_to_change"> log in to change @@ -114,3 +130,48 @@ (People and/or Objects you have blocked) </text> </panel> + + <panel + label="Discord" + name="privacy_preferences_discord" + layout="topleft" + follows="top|left"> + + <check_box + control_name="EnableDiscord" + height="16" + enabled="true" + label="Enable Discord integration" + layout="topleft" + left="30" + name="enable_discord" + top_pad="20" + width="350" /> + + <check_box + enabled_control="EnableDiscord" + control_name="ShowDiscordActivityDetails" + height="16" + enabled="true" + label="Show avatar name" + layout="topleft" + left="30" + name="show_name" + top_pad="20" + width="350" /> + + <check_box + enabled_control="EnableDiscord" + control_name="ShowDiscordActivityState" + height="16" + enabled="false" + label="Show location" + layout="topleft" + left="30" + name="show_location" + top_pad="20" + width="350" /> + </panel> + </tab_container> + +</panel> |