summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llwindow/llwindowsdl.cpp4
-rw-r--r--indra/newview/app_settings/settings.xml33
-rw-r--r--indra/newview/llappviewer.cpp136
-rw-r--r--indra/newview/llappviewer.h6
-rw-r--r--indra/newview/llfloaterpreference.cpp5
-rw-r--r--indra/newview/llstartup.cpp48
-rw-r--r--indra/newview/llstartup.h6
-rw-r--r--indra/newview/llviewermenu.cpp10
-rw-r--r--indra/newview/llviewermessage.cpp4
-rw-r--r--indra/newview/rlvdefines.h1
-rw-r--r--indra/newview/rlvhandler.cpp101
-rw-r--r--indra/newview/rlvhelper.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml7
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_privacy.xml69
15 files changed, 330 insertions, 109 deletions
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index b733ee9015..0a117be1fc 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 13826358b5..76ee635bae 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1172,6 +1172,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>0</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>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 91232c0bed..8ff66c6fe2 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -278,6 +278,13 @@ 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;
+#endif
+
static LLAppViewerListener sAppViewerListener(LLAppViewer::instance);
////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
@@ -1349,7 +1356,7 @@ bool LLAppViewer::doFrame()
TimePoint fpsLimitFrameStartTime = std::chrono::steady_clock::now();
#ifdef LL_DISCORD
- LLStartUp::runDiscordCallbacks();
+ discordpp::RunCallbacks();
#endif
LL_RECORD_BLOCK_TIME(FTM_FRAME);
@@ -5937,3 +5944,130 @@ void LLAppViewer::metricsSend(bool enable_reporting)
// resolution in time.
gViewerAssetStats->restart();
}
+
+#ifdef LL_DISCORD
+
+void LLAppViewer::initDiscordSocial()
+{
+ gDiscordTimestampsStart = time(nullptr);
+ gDiscordClient = std::make_shared<discordpp::Client>();
+ gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) {
+ if (status == discordpp::Client::Status::Ready)
+ {
+ updateDiscordActivity();
+ }
+ });
+ if (gSavedSettings.getBOOL("EnableDiscord"))
+ {
+ gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, gSecAPIHandler->loadCredential("Discord")->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) {
+ if (result.Successful())
+ gDiscordClient->Connect();
+ });
+ }
+}
+
+void LLAppViewer::handleDiscordSocial(const LLSD& value)
+{
+ static const uint64_t APPLICATION_ID = 1393451183741599796;
+ if (value.asBoolean())
+ {
+ discordpp::AuthorizationArgs args{};
+ args.SetClientId(APPLICATION_ID);
+ args.SetScopes(discordpp::Client::GetDefaultPresenceScopes());
+ auto codeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier();
+ args.SetCodeChallenge(codeVerifier.Challenge());
+ gDiscordClient->Authorize(args, [codeVerifier](auto result, auto code, auto redirectUri) {
+ if (result.Successful())
+ {
+ gDiscordClient->GetToken(APPLICATION_ID, code, codeVerifier.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();
+ });
+ LLSD authenticator = LLSD::emptyMap();
+ authenticator["token"] = accessToken;
+ gSecAPIHandler->saveCredential(gSecAPIHandler->createCredential("Discord", LLSD::emptyMap(), authenticator), true);
+ });
+ }
+ else
+ {
+ gSavedSettings.setBOOL("EnableDiscord", false);
+ }
+ });
+ }
+ else
+ {
+ gDiscordClient->RevokeToken(APPLICATION_ID, gSecAPIHandler->loadCredential("Discord")->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) {
+ if (result.Successful())
+ gDiscordClient->Disconnect();
+ auto cred = new LLCredential("Discord");
+ gSecAPIHandler->deleteCredential(cred);
+ });
+ }
+}
+
+void LLAppViewer::updateDiscordActivity()
+{
+ 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;
+ }
+
+ if (gSavedSettings.getBOOL("ShowDiscordActivityDetails"))
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(gAgent.getID(), &av_name);
+ auto name = av_name.getUserName();
+ auto displayName = av_name.getDisplayName();
+ if (name != displayName)
+ name = displayName + " (" + name + ")";
+ activity.SetDetails(name);
+ }
+
+ if (gSavedSettings.getBOOL("ShowDiscordActivityState"))
+ {
+ 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;
+ }
+ auto location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z);
+ activity.SetState(location);
+
+ auto world = LLWorld::getInstance();
+ uuid_vec_t chat_radius_uuids, near_me_uuids;
+ auto position = gAgent.getPositionGlobal();
+ world->getAvatars(&chat_radius_uuids, NULL, position, CHAT_NORMAL_RADIUS);
+ world->getAvatars(&near_me_uuids, NULL, position, gSavedSettings.getF32("MPVNearMeRange"));
+ discordpp::ActivityParty party;
+ party.SetId(location);
+ party.SetCurrentSize(chat_radius_uuids.size());
+ party.SetMaxSize(near_me_uuids.size());
+ activity.SetParty(party);
+ }
+
+ gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {});
+}
+
+#endif
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index bafe952659..3b6488dade 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -251,6 +251,12 @@ public:
// Note: mQuitRequested can be aborted by user.
void outOfMemorySoftQuit();
+#ifdef LL_DISCORD
+ static void initDiscordSocial();
+ static void handleDiscordSocial(const LLSD& value);
+ static void updateDiscordActivity();
+#endif
+
protected:
virtual bool initWindow(); // Initialize the viewer's window.
virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index fdac390e8a..4c8122bf71 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::handleDiscordSocial, _2));
+ 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/llstartup.cpp b/indra/newview/llstartup.cpp
index 834b99555e..dfad169813 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
//
@@ -2340,6 +2327,10 @@ bool idle_startup()
do_startup_frame();
}
+#ifdef LL_DISCORD
+ LLAppViewer::updateDiscordActivity();
+#endif
+
return true;
}
@@ -3447,35 +3438,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 73fda339b5..e04054aaa4 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -8957,13 +8957,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 =
@@ -9942,9 +9935,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..d6f1b96a7b 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3072,6 +3072,10 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
}
}
+#ifdef LL_DISCORD
+ LLAppViewer::updateDiscordActivity();
+#endif
+
if ( LLTracker::isTracking(NULL) )
{
// Check distance to beacon, if < 5m, remove beacon
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 f83876fe7d..6c7511796b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1818,13 +1818,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 &amp; Hits"
name="Bumps, Pushes &amp;amp; Hits">
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>