summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags2
-rwxr-xr-xindra/llinventory/llfoldertype.cpp2
-rwxr-xr-xindra/llmath/lloctree.h15
-rw-r--r--indra/llprimitive/lllslconstants.h19
-rwxr-xr-xindra/llui/llchatentry.cpp10
-rwxr-xr-xindra/llui/llfolderview.cpp22
-rwxr-xr-xindra/llui/lltexteditor.cpp5
-rwxr-xr-xindra/llui/lltexteditor.h2
-rwxr-xr-xindra/llui/lltooltip.cpp3
-rwxr-xr-xindra/llwindow/lldxhardware.cpp178
-rwxr-xr-xindra/llwindow/llwindowwin32.cpp34
-rwxr-xr-xindra/lscript/lscript_byteformat.h19
-rwxr-xr-xindra/lscript/lscript_compile/indra.l37
-rwxr-xr-xindra/lscript/lscript_compile/indra.y37
-rwxr-xr-xindra/lscript/lscript_compile/lscript_tree.cpp159
-rwxr-xr-xindra/lscript/lscript_compile/lscript_tree.h33
-rwxr-xr-xindra/newview/CMakeLists.txt11
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/settings.xml43
-rwxr-xr-xindra/newview/featuretable_mac.txt6
-rwxr-xr-xindra/newview/llagent.cpp16
-rwxr-xr-xindra/newview/llagentcamera.cpp2
-rwxr-xr-xindra/newview/llappearancemgr.cpp15
-rwxr-xr-xindra/newview/llappviewer.cpp8
-rwxr-xr-xindra/newview/llcolorswatch.h3
-rwxr-xr-xindra/newview/llconversationmodel.cpp9
-rw-r--r--indra/newview/llconversationmodel.h2
-rwxr-xr-xindra/newview/lldrawpoolbump.cpp2
-rwxr-xr-xindra/newview/llfloateravatarpicker.cpp4
-rwxr-xr-xindra/newview/llfloatercolorpicker.cpp14
-rw-r--r--indra/newview/llfloatergroupbulkban.cpp134
-rw-r--r--indra/newview/llfloatergroupbulkban.h48
-rwxr-xr-xindra/newview/llfloaterimcontainer.cpp118
-rwxr-xr-xindra/newview/llfloaterimcontainer.h4
-rwxr-xr-xindra/newview/llfloatertools.cpp6
-rwxr-xr-xindra/newview/llfloaterwebcontent.cpp16
-rwxr-xr-xindra/newview/llfloaterwebcontent.h1
-rwxr-xr-xindra/newview/llgroupactions.cpp5
-rwxr-xr-xindra/newview/llgroupmgr.cpp200
-rwxr-xr-xindra/newview/llgroupmgr.h81
-rwxr-xr-xindra/newview/llimview.cpp33
-rwxr-xr-xindra/newview/llimview.h8
-rwxr-xr-xindra/newview/llinventorybridge.cpp42
-rwxr-xr-xindra/newview/llinventorybridge.h1
-rwxr-xr-xindra/newview/llinventorypanel.cpp8
-rwxr-xr-xindra/newview/lllocalbitmaps.cpp17
-rwxr-xr-xindra/newview/lllocalbitmaps.h1
-rwxr-xr-xindra/newview/llmanipscale.cpp106
-rwxr-xr-xindra/newview/llmanipscale.h8
-rwxr-xr-xindra/newview/llmaniptranslate.cpp2
-rwxr-xr-xindra/newview/llnamelistctrl.cpp33
-rwxr-xr-xindra/newview/llnamelistctrl.h13
-rw-r--r--indra/newview/llpanelgroupbulk.cpp421
-rw-r--r--indra/newview/llpanelgroupbulk.h74
-rw-r--r--indra/newview/llpanelgroupbulkban.cpp259
-rw-r--r--indra/newview/llpanelgroupbulkban.h49
-rw-r--r--indra/newview/llpanelgroupbulkimpl.h99
-rwxr-xr-xindra/newview/llpanelgroupinvite.cpp9
-rwxr-xr-xindra/newview/llpanelgrouplandmoney.cpp33
-rwxr-xr-xindra/newview/llpanelgrouproles.cpp807
-rwxr-xr-xindra/newview/llpanelgrouproles.h65
-rwxr-xr-xindra/newview/llpanelland.cpp2
-rwxr-xr-xindra/newview/llpanellandmarks.cpp1
-rwxr-xr-xindra/newview/llpanelplaceprofile.cpp10
-rwxr-xr-xindra/newview/llpanelplaceprofile.h1
-rwxr-xr-xindra/newview/llpanelteleporthistory.cpp62
-rwxr-xr-xindra/newview/llpreview.cpp2
-rwxr-xr-xindra/newview/llpreviewscript.cpp332
-rwxr-xr-xindra/newview/llsidepanelinventory.cpp12
-rwxr-xr-xindra/newview/llspatialpartition.cpp1
-rwxr-xr-xindra/newview/llstartup.cpp1
-rwxr-xr-xindra/newview/lltooldraganddrop.cpp90
-rwxr-xr-xindra/newview/lltoolpie.cpp12
-rwxr-xr-xindra/newview/llviewercontrol.cpp1
-rw-r--r--indra/newview/llviewerfoldertype.cpp2
-rwxr-xr-xindra/newview/llviewermenu.cpp2
-rwxr-xr-xindra/newview/llviewermessage.cpp13
-rwxr-xr-xindra/newview/llviewerregion.cpp34
-rwxr-xr-xindra/newview/llviewerwindow.cpp2
-rwxr-xr-xindra/newview/llvovolume.cpp4
-rwxr-xr-xindra/newview/pipeline.cpp1
-rw-r--r--indra/newview/roles_constants.h106
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml6
-rwxr-xr-xindra/newview/skins/default/xui/da/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/de/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_report_abuse.xml128
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_tools.xml20
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_conversation.xml9
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_object.xml19
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml52
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml108
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_group_invite.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_group_roles.xml946
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_place_profile.xml18
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_teleport_history_item.xml15
-rwxr-xr-xindra/newview/skins/default/xui/en/role_actions.xml5
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml1
-rwxr-xr-xindra/newview/skins/default/xui/es/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/fr/panel_preferences_privacy.xml4
-rwxr-xr-xindra/newview/skins/default/xui/it/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ja/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pt/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ru/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/tr/panel_preferences_privacy.xml2
-rwxr-xr-xindra/newview/skins/default/xui/zh/panel_preferences_privacy.xml2
108 files changed, 4139 insertions, 1326 deletions
diff --git a/.hgtags b/.hgtags
index 18da825621..4d2aec7673 100755
--- a/.hgtags
+++ b/.hgtags
@@ -484,3 +484,5 @@ bba9b3722eea08949e4ff69591f736bf0f808434 3.7.8-release
a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
91dae9494b4d147541c7a01902334ba19a7ec05e 3.7.10-release
64799eb298834073a3e9992cd8d27c3cb9d30b10 3.7.11-release
+3b44ea8988cb902f0dda8429e8d5e4569e304532 3.7.12-release
+d86a7e1bc96d27b683f951d3701d5b7042158c68 3.7.13-release
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 8b568ea560..5f8aaae20b 100755
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -92,7 +92,7 @@ LLFolderDictionary::LLFolderDictionary()
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
- addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", FALSE));
+ addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", FALSE));
addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index 02220c41d8..7b5240c651 100755
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -36,6 +36,8 @@
extern U32 gOctreeMaxCapacity;
+extern float gOctreeMinSize;
+
/*#define LL_OCTREE_PARANOIA_CHECK 0
#if LL_DARWIN
#define LL_OCTREE_MAX_CAPACITY 32
@@ -106,6 +108,7 @@ public:
: mParent((oct_node*)parent),
mOctant(octant)
{
+ llassert(size[0] >= gOctreeMinSize*0.5f);
//always keep a NULL terminated list to avoid out of bounds exceptions in debug builds
mData.push_back(NULL);
mDataEnd = &mData[0];
@@ -213,7 +216,7 @@ public:
F32 size = mSize[0];
F32 p_size = size * 2.f;
- return (radius <= 0.001f && size <= 0.001f) ||
+ return (radius <= gOctreeMinSize && size <= gOctreeMinSize) ||
(radius <= p_size && radius > size);
}
@@ -319,7 +322,7 @@ public:
//is it here?
if (isInside(data->getPositionGroup()))
{
- if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) ||
+ if (((getElementCount() < gOctreeMaxCapacity || getSize()[0] <= gOctreeMinSize) && contains(data->getBinRadius()) ||
(data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity)))
{ //it belongs here
mData.push_back(NULL);
@@ -356,8 +359,9 @@ public:
LLVector4a val;
val.setSub(center, getCenter());
val.setAbs(val);
-
- S32 lt = val.lessThan(LLVector4a::getEpsilon()).getGatheredBits() & 0x7;
+ LLVector4a min_diff(gOctreeMinSize);
+
+ S32 lt = val.lessThan(min_diff).getGatheredBits() & 0x7;
if( lt == 0x7 )
{
@@ -389,6 +393,7 @@ public:
}
#endif
+ llassert(size[0] >= gOctreeMinSize*0.5f);
//make the new kid
child = new LLOctreeNode<T>(center, size, this);
addChild(child);
@@ -796,6 +801,8 @@ public:
this->setSize(size2);
this->updateMinMax();
+ llassert(size[0] >= gOctreeMinSize);
+
//copy our children to a new branch
LLOctreeNode<T>* newnode = new LLOctreeNode<T>(center, size, this);
diff --git a/indra/llprimitive/lllslconstants.h b/indra/llprimitive/lllslconstants.h
index 926ce32d75..b6baf98211 100644
--- a/indra/llprimitive/lllslconstants.h
+++ b/indra/llprimitive/lllslconstants.h
@@ -239,4 +239,23 @@ const U32 LSL_STATUS_INTERNAL_ERROR = 1999;
// Start per-function errors below, starting at 2000:
const U32 LSL_STATUS_WHITELIST_FAILED = 2001;
+
+const S32 LSL_XP_ERROR_NONE = 0;
+const S32 LSL_XP_ERROR_THROTTLED = 1;
+const S32 LSL_XP_ERROR_EXPERIENCES_DISABLED = 2;
+const S32 LSL_XP_ERROR_INVALID_PARAMETERS = 3;
+const S32 LSL_XP_ERROR_NOT_PERMITTED = 4;
+const S32 LSL_XP_ERROR_NO_EXPERIENCE = 5;
+const S32 LSL_XP_ERROR_NOT_FOUND = 6;
+const S32 LSL_XP_ERROR_INVALID_EXPERIENCE = 7;
+const S32 LSL_XP_ERROR_EXPERIENCE_DISABLED = 8;
+const S32 LSL_XP_ERROR_EXPERIENCE_SUSPENDED = 9;
+const S32 LSL_XP_ERROR_UNKNOWN_ERROR = 10;
+const S32 LSL_XP_ERROR_QUOTA_EXCEEDED = 11;
+const S32 LSL_XP_ERROR_STORE_DISABLED = 12;
+const S32 LSL_XP_ERROR_STORAGE_EXCEPTION = 13;
+const S32 LSL_XP_ERROR_KEY_NOT_FOUND = 14;
+const S32 LSL_XP_ERROR_RETRY_UPDATE = 15;
+const S32 LSL_XP_ERROR_MATURITY_EXCEEDED = 16;
+
#endif
diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp
index c04b70eb64..dac001afab 100755
--- a/indra/llui/llchatentry.cpp
+++ b/indra/llui/llchatentry.cpp
@@ -51,6 +51,7 @@ LLChatEntry::LLChatEntry(const Params& p)
mCurrentHistoryLine = mLineHistory.begin();
mAutoIndent = false;
+ keepSelectionOnReturn(true);
}
LLChatEntry::~LLChatEntry()
@@ -179,15 +180,6 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask)
{
BOOL handled = FALSE;
- // In the case of a chat entry, pressing RETURN when something is selected
- // should NOT erase the selection (unlike a notecard, for example)
- if (key == KEY_RETURN)
- {
- endOfDoc();
- startSelection();
- endSelection();
- }
-
LLTextEditor::handleSpecialKey(key, mask);
switch(key)
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index bc2388dd28..cca26f335a 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -1130,18 +1130,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
if((mSelectedItems.size() > 0) && mScrollContainer)
{
LLFolderViewItem* last_selected = getCurSelectedItem();
+ BOOL shift_select = mask & MASK_SHIFT;
+ // don't shift select down to children of folders (they are implicitly selected through parent)
+ LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select);
- if (!mKeyboardSelection)
+ if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected)))
{
setSelection(last_selected, FALSE, TRUE);
mKeyboardSelection = TRUE;
}
- LLFolderViewItem* next = NULL;
- if (mask & MASK_SHIFT)
+ if (shift_select)
{
- // don't shift select down to children of folders (they are implicitly selected through parent)
- next = last_selected->getNextOpenNode(FALSE);
if (next)
{
if (next->isSelected())
@@ -1158,7 +1158,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
}
else
{
- next = last_selected->getNextOpenNode();
if( next )
{
if (next == last_selected)
@@ -1194,18 +1193,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
if((mSelectedItems.size() > 0) && mScrollContainer)
{
LLFolderViewItem* last_selected = mSelectedItems.back();
+ BOOL shift_select = mask & MASK_SHIFT;
+ // don't shift select down to children of folders (they are implicitly selected through parent)
+ LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select);
- if (!mKeyboardSelection)
+ if (!mKeyboardSelection || (!shift_select && prev == this))
{
setSelection(last_selected, FALSE, TRUE);
mKeyboardSelection = TRUE;
}
- LLFolderViewItem* prev = NULL;
- if (mask & MASK_SHIFT)
+ if (shift_select)
{
- // don't shift select down to children of folders (they are implicitly selected through parent)
- prev = last_selected->getPreviousOpenNode(FALSE);
if (prev)
{
if (prev->isSelected())
@@ -1222,7 +1221,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask )
}
else
{
- prev = last_selected->getPreviousOpenNode();
if( prev )
{
if (prev == this)
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 90e3606998..576e8f7600 100755
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -260,7 +260,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mContextMenu(NULL),
mShowContextMenu(p.show_context_menu),
mEnableTooltipPaste(p.enable_tooltip_paste),
- mPassDelete(FALSE)
+ mPassDelete(FALSE),
+ mKeepSelectionOnReturn(false)
{
mSourceID.generate();
@@ -1653,7 +1654,7 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask)
case KEY_RETURN:
if (mask == MASK_NONE)
{
- if( hasSelection() )
+ if( hasSelection() && !mKeepSelectionOnReturn )
{
deleteSelection(FALSE);
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 2408613824..f6bdf917b4 100755
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -282,6 +282,7 @@ protected:
bool mParseOnTheFly;
void updateLinkSegments();
+ void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; }
class LLViewBorder* mBorder;
private:
@@ -316,6 +317,7 @@ private:
bool mShowContextMenu;
bool mEnableTooltipPaste;
bool mPassDelete;
+ bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
LLUUID mSourceID;
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 5e1f12996e..7f2224870d 100755
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -477,7 +477,8 @@ void LLToolTipMgr::show(const std::string& msg)
void LLToolTipMgr::show(const LLToolTip::Params& params)
{
if (!params.styled_message.isProvided()
- && (!params.message.isProvided() || params.message().empty())) return;
+ && (!params.message.isProvided() || params.message().empty())
+ && !params.image.isProvided()) return;
// fill in default tooltip params from tool_tip.xml
LLToolTip::Params params_with_defaults(params);
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index ba5bc8fcfb..e7afef63f8 100755
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -34,9 +34,12 @@
#include <dxdiag.h>
#undef INITGUID
+#include <wbemidl.h>
+
#include <boost/tokenizer.hpp>
#include "lldxhardware.h"
+
#include "llerror.h"
#include "llstring.h"
@@ -53,11 +56,160 @@ LLDXHardware gDXHardware;
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
-std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName)
+typedef BOOL ( WINAPI* PfnCoSetProxyBlanket )( IUnknown* pProxy, DWORD dwAuthnSvc, DWORD dwAuthzSvc,
+ OLECHAR* pServerPrincName, DWORD dwAuthnLevel, DWORD dwImpLevel,
+ RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities );
+
+HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam )
{
HRESULT hr;
+ bool bGotMemory = false;
+ HRESULT hrCoInitialize = S_OK;
+ IWbemLocator* pIWbemLocator = nullptr;
+ IWbemServices* pIWbemServices = nullptr;
+ BSTR pNamespace = nullptr;
+
+ *pdwAdapterRam = 0;
+ hrCoInitialize = CoInitialize( 0 );
+
+ hr = CoCreateInstance( CLSID_WbemLocator,
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_IWbemLocator,
+ ( LPVOID* )&pIWbemLocator );
+#ifdef PRINTF_DEBUGGING
+ if( FAILED( hr ) ) wprintf( L"WMI: CoCreateInstance failed: 0x%0.8x\n", hr );
+#endif
+
+ if( SUCCEEDED( hr ) && pIWbemLocator )
+ {
+ // Using the locator, connect to WMI in the given namespace.
+ pNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );
+
+ hr = pIWbemLocator->ConnectServer( pNamespace, nullptr, nullptr, 0L,
+ 0L, nullptr, nullptr, &pIWbemServices );
+#ifdef PRINTF_DEBUGGING
+ if( FAILED( hr ) ) wprintf( L"WMI: pIWbemLocator->ConnectServer failed: 0x%0.8x\n", hr );
+#endif
+ if( SUCCEEDED( hr ) && pIWbemServices != 0 )
+ {
+ HINSTANCE hinstOle32 = nullptr;
+
+ hinstOle32 = LoadLibraryW( L"ole32.dll" );
+ if( hinstOle32 )
+ {
+ PfnCoSetProxyBlanket pfnCoSetProxyBlanket = nullptr;
+
+ pfnCoSetProxyBlanket = ( PfnCoSetProxyBlanket )GetProcAddress( hinstOle32, "CoSetProxyBlanket" );
+ if( pfnCoSetProxyBlanket != 0 )
+ {
+ // Switch security level to IMPERSONATE.
+ pfnCoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr,
+ RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, 0 );
+ }
+
+ FreeLibrary( hinstOle32 );
+ }
+
+ IEnumWbemClassObject* pEnumVideoControllers = nullptr;
+ BSTR pClassName = nullptr;
+
+ pClassName = SysAllocString( L"Win32_VideoController" );
+
+ hr = pIWbemServices->CreateInstanceEnum( pClassName, 0,
+ nullptr, &pEnumVideoControllers );
+#ifdef PRINTF_DEBUGGING
+ if( FAILED( hr ) ) wprintf( L"WMI: pIWbemServices->CreateInstanceEnum failed: 0x%0.8x\n", hr );
+#endif
+
+ if( SUCCEEDED( hr ) && pEnumVideoControllers )
+ {
+ IWbemClassObject* pVideoControllers[10] = {0};
+ DWORD uReturned = 0;
+ BSTR pPropName = nullptr;
+
+ // Get the first one in the list
+ pEnumVideoControllers->Reset();
+ hr = pEnumVideoControllers->Next( 5000, // timeout in 5 seconds
+ 10, // return the first 10
+ pVideoControllers,
+ &uReturned );
+#ifdef PRINTF_DEBUGGING
+ if( FAILED( hr ) ) wprintf( L"WMI: pEnumVideoControllers->Next failed: 0x%0.8x\n", hr );
+ if( uReturned == 0 ) wprintf( L"WMI: pEnumVideoControllers uReturned == 0\n" );
+#endif
+
+ VARIANT var;
+ if( SUCCEEDED( hr ) )
+ {
+ bool bFound = false;
+ for( UINT iController = 0; iController < uReturned; iController++ )
+ {
+ if ( !pVideoControllers[iController] )
+ continue;
+
+ pPropName = SysAllocString( L"PNPDeviceID" );
+ hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr );
+#ifdef PRINTF_DEBUGGING
+ if( FAILED( hr ) )
+ wprintf( L"WMI: pVideoControllers[iController]->Get PNPDeviceID failed: 0x%0.8x\n", hr );
+#endif
+ if( SUCCEEDED( hr ) )
+ {
+ if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 )
+ bFound = true;
+ }
+ VariantClear( &var );
+ if( pPropName ) SysFreeString( pPropName );
+
+ if( bFound )
+ {
+ pPropName = SysAllocString( L"AdapterRAM" );
+ hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr );
+#ifdef PRINTF_DEBUGGING
+ if( FAILED( hr ) )
+ wprintf( L"WMI: pVideoControllers[iController]->Get AdapterRAM failed: 0x%0.8x\n",
+ hr );
+#endif
+ if( SUCCEEDED( hr ) )
+ {
+ bGotMemory = true;
+ *pdwAdapterRam = var.ulVal;
+ }
+ VariantClear( &var );
+ if( pPropName ) SysFreeString( pPropName );
+ break;
+ }
+ SAFE_RELEASE( pVideoControllers[iController] );
+ }
+ }
+ }
+
+ if( pClassName )
+ SysFreeString( pClassName );
+ SAFE_RELEASE( pEnumVideoControllers );
+ }
+
+ if( pNamespace )
+ SysFreeString( pNamespace );
+ SAFE_RELEASE( pIWbemServices );
+ }
+
+ SAFE_RELEASE( pIWbemLocator );
+
+ if( SUCCEEDED( hrCoInitialize ) )
+ CoUninitialize();
+
+ if( bGotMemory )
+ return S_OK;
+ else
+ return E_FAIL;
+}
+
+void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize)
+{
+ HRESULT hr;
VARIANT var;
- WCHAR wszPropValue[256];
VariantInit( &var );
hr = containerp->GetProp(wszPropName, &var );
@@ -76,13 +228,19 @@ std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName)
wcscpy( wszPropValue, (var.boolVal) ? L"true" : L"false" ); /* Flawfinder: ignore */
break;
case VT_BSTR:
- wcsncpy( wszPropValue, var.bstrVal, 255 ); /* Flawfinder: ignore */
- wszPropValue[255] = 0;
+ wcsncpy( wszPropValue, var.bstrVal, outputSize-1 ); /* Flawfinder: ignore */
+ wszPropValue[outputSize-1] = 0;
break;
}
}
// Clear the variant (this is needed to free BSTR memory)
VariantClear( &var );
+}
+
+std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName)
+{
+ WCHAR wszPropValue[256];
+ get_wstring(containerp, wszPropName, wszPropValue, 256);
return utf16str_to_utf8str(wszPropValue);
}
@@ -361,8 +519,18 @@ BOOL LLDXHardware::getInfo(BOOL vram_only)
goto LCleanup;
}
- // Get the English VRAM string
+ DWORD vram = 0;
+
+ WCHAR deviceID[512];
+
+ get_wstring(device_containerp, L"szDeviceID", deviceID, 512);
+
+ if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram)))
{
+ mVRAM = vram/(1024*1024);
+ }
+ else
+ { // Get the English VRAM string
std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish");
// We don't need the device any more
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 19961d5759..cd2be87fad 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -86,6 +86,18 @@ void show_window_creation_error(const std::string& title)
LL_WARNS("Window") << title << LL_ENDL;
}
+HGLRC SafeCreateContext(HDC hdc)
+{
+ __try
+ {
+ return wglCreateContext(hdc);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ return NULL;
+ }
+}
+
//static
BOOL LLWindowWin32::sIsClassRegistered = FALSE;
@@ -1167,14 +1179,15 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
return FALSE;
}
- if (!(mhRC = wglCreateContext(mhDC)))
+
+ if (!(mhRC = SafeCreateContext(mhDC)))
{
close();
OSMessageBox(mCallbacks->translateString("MBGLContextErr"),
mCallbacks->translateString("MBError"), OSMB_OK);
return FALSE;
}
-
+
if (!wglMakeCurrent(mhDC, mhRC))
{
close();
@@ -1832,6 +1845,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// This helps prevent avatar walking after maximizing the window by double-clicking the title bar.
static bool sHandleLeftMouseUp = true;
+ // Ignore the double click received right after activating app.
+ // This is to avoid triggering double click teleport after returning focus (see MAINT-3786).
+ static bool sHandleDoubleClick = true;
+
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
@@ -1959,6 +1976,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
}
+ if (!activating)
+ {
+ sHandleDoubleClick = false;
+ }
+
window_imp->mCallbacks->handleActivateApp(window_imp, activating);
break;
@@ -2183,6 +2205,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN");
// A click in a non-client area, e.g. title bar or window border.
sHandleLeftMouseUp = false;
+ sHandleDoubleClick = true;
}
break;
@@ -2227,6 +2250,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
//case WM_RBUTTONDBLCLK:
{
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK");
+
+ if (!sHandleDoubleClick)
+ {
+ sHandleDoubleClick = true;
+ break;
+ }
+
// Because we move the cursor position in the app, we need to query
// to find out where the cursor at the time the event is handled.
// If we don't do this, many clicks could get buffered up, and if the
diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h
index 54031aaf05..a4703b7a61 100755
--- a/indra/lscript/lscript_byteformat.h
+++ b/indra/lscript/lscript_byteformat.h
@@ -355,6 +355,10 @@ typedef enum e_lscript_state_event_type
LSTT_REMOTE_DATA,
LSTT_HTTP_RESPONSE,
LSTT_HTTP_REQUEST,
+ LSTT_EXPERMISSIONS,
+ LSTT_TRANSACTION_RESULT,
+ LSTT_PATH_UPDATE,
+ LSTT_EXPERMISSIONS_DENIED,
LSTT_EOF,
LSTT_STATE_BEGIN = LSTT_STATE_ENTRY,
@@ -397,7 +401,11 @@ const U64 LSCRIPTStateBitField[LSTT_EOF] =
0x0000000040000000, // LSTT_OBJECT_REZ
0x0000000080000000, // LSTT_REMOTE_DATA
0x0000000100000000LL, // LSTT_HTTP_RESPOSE
- 0x0000000200000000LL // LSTT_HTTP_REQUEST
+ 0x0000000200000000LL, // LSTT_HTTP_REQUEST
+ 0x0000000400000000LL, // LSTT_EXPERMISSIONS
+ 0x0000000800000000LL, // LSTT_TRANSACTION_RESULT
+ 0x0000001000000000LL, // LSTT_PATH_UPDATE
+ 0x0000002000000000LL, //LSTT_EXPERMISSIONS_DENIED
};
inline S32 get_event_handler_jump_position(U64 bit_field, LSCRIPTStateEventType type)
@@ -511,6 +519,7 @@ typedef enum e_lscript_runtime_faults
LSRF_TOO_MANY_LISTENS,
LSRF_NESTING_LISTS,
LSRF_CLI,
+ LSRF_INVALID_STATE,
LSRF_EOF
} LSCRIPTRunTimeFaults;
@@ -551,10 +560,10 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =
(0x1 << 10),// SCRIPT_PERMISSION_TRACK_CAMERA
(0x1 << 11),// SCRIPT_PERMISSION_CONTROL_CAMERA
(0x1 << 12),// SCRIPT_PERMISSION_TELEPORT
- (0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE,
- (0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT,
- (0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS,
- (0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS,
+ (0x1 << 13),// SCRIPT_PERMISSION_EXPERIENCE
+ (0x1 << 14),// SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT
+ (0x1 << 15),// SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS
+ (0x1 << 16),// SCRIPT_PERMISSION_RETURN_OBJECTS
};
// http_request string constants
diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l
index aad7c317d2..c2e21335e9 100755
--- a/indra/lscript/lscript_compile/indra.l
+++ b/indra/lscript/lscript_compile/indra.l
@@ -132,6 +132,8 @@ int yyerror(const char *fmt, ...);
"money" { count(); return(MONEY); }
"email" { count(); return(EMAIL); }
"run_time_permissions" { count(); return(RUN_TIME_PERMISSIONS); }
+"experience_permissions" { count(); return(EXPERIENCE_PERMISSIONS); }
+"experience_permissions_denied" { count(); return(EXPERIENCE_PERMISSIONS_DENIED); }
"changed" { count(); return(INVENTORY); }
"attach" { count(); return(ATTACH); }
"dataserver" { count(); return(DATASERVER); }
@@ -393,7 +395,6 @@ int yyerror(const char *fmt, ...);
"PSYS_PART_END_ALPHA" { count(); yylval.ival = LLPS_PART_END_ALPHA; return (INTEGER_CONSTANT); }
"PSYS_PART_END_SCALE" { count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }
"PSYS_PART_MAX_AGE" { count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); }
-
"PSYS_PART_BLEND_FUNC_SOURCE" { count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); }
"PSYS_PART_BLEND_FUNC_DEST" { count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); }
"PSYS_PART_START_GLOW" { count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); }
@@ -419,7 +420,6 @@ int yyerror(const char *fmt, ...);
"PSYS_PART_BF_SOURCE_ALPHA" { count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA" { count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
-
"PSYS_SRC_MAX_AGE" { count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); }
"PSYS_SRC_PATTERN" { count(); yylval.ival = LLPS_SRC_PATTERN; return(INTEGER_CONSTANT); }
"PSYS_SRC_INNERANGLE" { count(); yylval.ival = LLPS_SRC_INNERANGLE; return(INTEGER_CONSTANT); }
@@ -737,22 +737,23 @@ int yyerror(const char *fmt, ...);
"STATUS_INTERNAL_ERROR" { count(); yylval.ival = LSL_STATUS_INTERNAL_ERROR; return(INTEGER_CONSTANT); }
"STATUS_WHITELIST_FAILED" { count(); yylval.ival = LSL_STATUS_WHITELIST_FAILED; return(INTEGER_CONSTANT); }
-"XP_ERROR_NONE" { const char* sval= "no error"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_THROTTLED" { const char* sval= "exceeded throttle"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_EXPERIENCES_DISABLED" { const char* sval= "experiences are disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_INVALID_PARAMETERS" { const char* sval= "invalid parameters"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_NOT_PERMITTED" { const char* sval= "operation not permitted"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_NO_EXPERIENCE" { const char* sval= "script not associated with an experience";yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_NOT_FOUND" { const char* sval= "not found"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_INVALID_EXPERIENCE" { const char* sval= "invalid experience"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_EXPERIENCE_DISABLED" { const char* sval= "experience is disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_EXPERIENCE_SUSPENDED" { const char* sval= "experience is suspended"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_UNKNOWN_ERROR" { const char* sval= "unknown error"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_QUOTA_EXCEEDED" { const char* sval= "experience data quota exceeded"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_STORE_DISABLED" { const char* sval= "key-value store is disabled"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_STORAGE_EXCEPTION" { const char* sval= "key-value store communication failed"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_KEY_NOT_FOUND" { const char* sval= "key doesn't exist"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
-"XP_ERROR_RETRY_UPDATE" { const char* sval= "retry update"; yylval.sval = new char[strlen(sval)+1]; strcpy(yylval.sval, sval); return(STRING_CONSTANT); }
+"XP_ERROR_NONE" { count(); yylval.ival = LSL_XP_ERROR_NONE ; return (INTEGER_CONSTANT); }
+"XP_ERROR_THROTTLED" { count(); yylval.ival = LSL_XP_ERROR_THROTTLED ; return (INTEGER_CONSTANT); }
+"XP_ERROR_EXPERIENCES_DISABLED" { count(); yylval.ival = LSL_XP_ERROR_EXPERIENCES_DISABLED; return (INTEGER_CONSTANT); }
+"XP_ERROR_INVALID_PARAMETERS" { count(); yylval.ival = LSL_XP_ERROR_INVALID_PARAMETERS ; return (INTEGER_CONSTANT); }
+"XP_ERROR_NOT_PERMITTED" { count(); yylval.ival = LSL_XP_ERROR_NOT_PERMITTED ; return (INTEGER_CONSTANT); }
+"XP_ERROR_NO_EXPERIENCE" { count(); yylval.ival = LSL_XP_ERROR_NO_EXPERIENCE ; return (INTEGER_CONSTANT); }
+"XP_ERROR_NOT_FOUND" { count(); yylval.ival = LSL_XP_ERROR_NOT_FOUND ; return (INTEGER_CONSTANT); }
+"XP_ERROR_INVALID_EXPERIENCE" { count(); yylval.ival = LSL_XP_ERROR_INVALID_EXPERIENCE ; return (INTEGER_CONSTANT); }
+"XP_ERROR_EXPERIENCE_DISABLED" { count(); yylval.ival = LSL_XP_ERROR_EXPERIENCE_DISABLED ; return (INTEGER_CONSTANT); }
+"XP_ERROR_EXPERIENCE_SUSPENDED" { count(); yylval.ival = LSL_XP_ERROR_EXPERIENCE_SUSPENDED; return (INTEGER_CONSTANT); }
+"XP_ERROR_UNKNOWN_ERROR" { count(); yylval.ival = LSL_XP_ERROR_UNKNOWN_ERROR ; return (INTEGER_CONSTANT); }
+"XP_ERROR_QUOTA_EXCEEDED" { count(); yylval.ival = LSL_XP_ERROR_QUOTA_EXCEEDED ; return (INTEGER_CONSTANT); }
+"XP_ERROR_STORE_DISABLED" { count(); yylval.ival = LSL_XP_ERROR_STORE_DISABLED ; return (INTEGER_CONSTANT); }
+"XP_ERROR_STORAGE_EXCEPTION" { count(); yylval.ival = LSL_XP_ERROR_STORAGE_EXCEPTION ; return (INTEGER_CONSTANT); }
+"XP_ERROR_KEY_NOT_FOUND" { count(); yylval.ival = LSL_XP_ERROR_KEY_NOT_FOUND ; return (INTEGER_CONSTANT); }
+"XP_ERROR_RETRY_UPDATE" { count(); yylval.ival = LSL_XP_ERROR_RETRY_UPDATE ; return (INTEGER_CONSTANT); }
+"XP_ERROR_MATURITY_EXCEEDED" { count(); yylval.ival = LSL_XP_ERROR_MATURITY_EXCEEDED ; return (INTEGER_CONSTANT); }
{L}({L}|{N})* { count(); yylval.sval = new char[strlen(yytext) + 1]; strcpy(yylval.sval, yytext); return(IDENTIFIER); }
diff --git a/indra/lscript/lscript_compile/indra.y b/indra/lscript/lscript_compile/indra.y
index a0a034d21c..c451eee3d8 100755
--- a/indra/lscript/lscript_compile/indra.y
+++ b/indra/lscript/lscript_compile/indra.y
@@ -15,7 +15,6 @@
#pragma warning (disable : 4702) // warning C4702: unreachable code
#pragma warning( disable : 4065 ) // warning: switch statement contains 'default' but no 'case' labels
#endif
-
%}
%union
@@ -75,6 +74,8 @@
%token MONEY
%token EMAIL
%token RUN_TIME_PERMISSIONS
+%token EXPERIENCE_PERMISSIONS
+%token EXPERIENCE_PERMISSIONS_DENIED
%token INVENTORY
%token ATTACH
%token DATASERVER
@@ -180,6 +181,8 @@
%type <event> money
%type <event> email
%type <event> run_time_permissions
+%type <event> experience_permissions
+%type <event> experience_permissions_denied
%type <event> inventory
%type <event> attach
%type <event> dataserver
@@ -788,6 +791,16 @@ event
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
gAllocationManager->addAllocation($$);
}
+ | experience_permissions compound_statement
+ {
+ $$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
+ gAllocationManager->addAllocation($$);
+ }
+ | experience_permissions_denied compound_statement
+ {
+ $$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
+ gAllocationManager->addAllocation($$);
+ }
| inventory compound_statement
{
$$ = new LLScriptEventHandler(gLine, gColumn, $1, $2);
@@ -1040,6 +1053,28 @@ run_time_permissions
}
;
+experience_permissions
+ : EXPERIENCE_PERMISSIONS '(' LLKEY IDENTIFIER ')'
+ {
+ LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4);
+ gAllocationManager->addAllocation(id1);
+ $$ = new LLScriptEXPEvent(gLine, gColumn, id1);
+ gAllocationManager->addAllocation($$);
+ }
+ ;
+
+experience_permissions_denied
+ : EXPERIENCE_PERMISSIONS_DENIED '(' LLKEY IDENTIFIER ',' INTEGER IDENTIFIER ')'
+ {
+ LLScriptIdentifier *id1 = new LLScriptIdentifier(gLine, gColumn, $4);
+ gAllocationManager->addAllocation(id1);
+ LLScriptIdentifier *id2 = new LLScriptIdentifier(gLine, gColumn, $7);
+ gAllocationManager->addAllocation(id2);
+ $$ = new LLScriptEXPDeniedEvent(gLine, gColumn, id1, id2);
+ gAllocationManager->addAllocation($$);
+ }
+ ;
+
inventory
: INVENTORY '(' INTEGER IDENTIFIER ')'
{
diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index 8a70dd9ac1..4215596c8b 100755
--- a/indra/lscript/lscript_compile/lscript_tree.cpp
+++ b/indra/lscript/lscript_compile/lscript_tree.cpp
@@ -3844,6 +3844,156 @@ S32 LLScriptNotAtTarget::getSize()
return 0;
}
+
+void LLScriptEXPEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "experience_permissions( key ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ checkForDuplicateHandler(fp, this, scope, "experience_permissions");
+ if (scope->checkEntry(mName->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just tryng to determine how much space the variable needs
+ if (mName->mScopeEntry)
+ {
+ mName->mScopeEntry->mOffset = (S32)count;
+ mName->mScopeEntry->mSize = 4;
+ count += mName->mScopeEntry->mSize;
+ }
+ }
+ break;
+
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "experience_permissions";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
+#endif
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "experience_permissions( valuetype [ScriptTypes]LindenLab.SecondLife.Key ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )");
+ break;
+ default:
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptEXPEvent::getSize()
+{
+ // key = 4
+ return 4;
+}
+
+
+void LLScriptEXPDeniedEvent::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
+{
+ if (gErrorToText.getErrors())
+ {
+ return;
+ }
+ switch(pass)
+ {
+ case LSCP_PRETTY_PRINT:
+ case LSCP_EMIT_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "experience_permissions_denied( key ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", integer ");
+ mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )\n");
+ break;
+ case LSCP_SCOPE_PASS1:
+ checkForDuplicateHandler(fp, this, scope, "experience_permissions_denied");
+ if (scope->checkEntry(mName->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mName->mScopeEntry = scope->addEntry(mName->mName, LIT_VARIABLE, LST_KEY);
+ }
+ if (scope->checkEntry(mReason->mName))
+ {
+ gErrorToText.writeError(fp, this, LSERROR_DUPLICATE_NAME);
+ }
+ else
+ {
+ mReason->mScopeEntry = scope->addEntry(mReason->mName, LIT_VARIABLE, LST_INTEGER);
+ }
+ break;
+ case LSCP_RESOURCE:
+ {
+ // we're just trying to determine how much space the variable needs
+ if (mName->mScopeEntry)
+ {
+ mName->mScopeEntry->mOffset = (S32)count;
+ mName->mScopeEntry->mSize = 4;
+ count += mName->mScopeEntry->mSize;
+
+ mReason->mScopeEntry->mOffset = (S32)count;
+ mReason->mScopeEntry->mSize = 4;
+ count += mReason->mScopeEntry->mSize;
+ }
+ }
+ break;
+
+ case LSCP_EMIT_BYTE_CODE:
+ {
+#ifdef LSL_INCLUDE_DEBUG_INFO
+ char name[] = "experience_permissions_denied";
+ chunk->addBytes(name, strlen(name) + 1);
+ chunk->addBytes(mName->mName, strlen(mName->mName) + 1);
+ chunk->addBytes(mReason->mName, strlen(mReason->mName) + 1);
+#endif
+ }
+ break;
+ case LSCP_EMIT_CIL_ASSEMBLY:
+ fdotabs(fp, tabs, tabsize);
+ fprintf(fp, "experience_permissions_denied( valuetype [ScriptTypes]LindenLab.SecondLife.Key ");
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, ", int32 ");
+ mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ fprintf(fp, " )");
+ break;
+ default:
+ mName->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ mReason->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL);
+ break;
+ }
+}
+
+S32 LLScriptEXPDeniedEvent::getSize()
+{
+ // key = 4 + integer
+ return LSCRIPTDataSize[LST_KEY]+LSCRIPTDataSize[LST_INTEGER];
+}
+
void LLScriptAtRotTarget::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata)
{
if (gErrorToText.getErrors())
@@ -8569,6 +8719,7 @@ void LLScriptReturn::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePa
}
}
prunearg = TRUE;
+ break;
case LSCP_TYPE:
// if there is a return expression, it must be promotable to the return type of the function
if (mExpression)
@@ -9767,7 +9918,13 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom
mScopeEntry->mFunctionArgs.addType(LST_STRING);
mScopeEntry->mFunctionArgs.addType(LST_STRING);
break;
-
+ case LSTT_EXPERMISSIONS:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ break;
+ case LSTT_EXPERMISSIONS_DENIED:
+ mScopeEntry->mFunctionArgs.addType(LST_KEY);
+ mScopeEntry->mFunctionArgs.addType(LST_INTEGER);
+ break;
default:
break;
}
diff --git a/indra/lscript/lscript_compile/lscript_tree.h b/indra/lscript/lscript_compile/lscript_tree.h
index 047c220b17..38a69cece8 100755
--- a/indra/lscript/lscript_compile/lscript_tree.h
+++ b/indra/lscript/lscript_compile/lscript_tree.h
@@ -627,6 +627,39 @@ public:
LLScriptIdentifier *mRTPermissions;
};
+class LLScriptEXPEvent : public LLScriptEvent
+{
+public:
+ LLScriptEXPEvent(S32 line, S32 col, LLScriptIdentifier *name)
+ : LLScriptEvent(line, col, LSTT_EXPERMISSIONS), mName(name)
+ {
+ }
+
+ ~LLScriptEXPEvent() {}
+
+ void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);
+ S32 getSize();
+
+ LLScriptIdentifier *mName;
+};
+
+class LLScriptEXPDeniedEvent : public LLScriptEvent
+{
+public:
+ LLScriptEXPDeniedEvent(S32 line, S32 col, LLScriptIdentifier *name, LLScriptIdentifier *reason)
+ : LLScriptEvent(line, col, LSTT_EXPERMISSIONS_DENIED), mName(name), mReason(reason)
+ {
+ }
+
+ ~LLScriptEXPDeniedEvent() {}
+
+ void recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass pass, LSCRIPTPruneType ptype, BOOL &prunearg, LLScriptScope *scope, LSCRIPTType &type, LSCRIPTType basetype, U64 &count, LLScriptByteCodeChunk *chunk, LLScriptByteCodeChunk *heap, S32 stacksize, LLScriptScopeEntry *entry, S32 entrycount, LLScriptLibData **ldata);
+ S32 getSize();
+
+ LLScriptIdentifier *mName;
+ LLScriptIdentifier *mReason;
+};
+
class LLScriptChatEvent : public LLScriptEvent
{
public:
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index f124987d5b..752508ea5e 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -232,8 +232,6 @@ set(viewer_SOURCE_FILES
llfloatereditwater.cpp
llfloaterenvironmentsettings.cpp
llfloaterevent.cpp
- llfloaterfacebook.cpp
- llfloaterflickr.cpp
llfloaterexperiencepicker.cpp
llfloaterexperienceprofile.cpp
llfloaterexperiences.cpp
@@ -243,6 +241,7 @@ set(viewer_SOURCE_FILES
llfloatergesture.cpp
llfloatergodtools.cpp
llfloatergotoline.cpp
+ llfloatergroupbulkban.cpp
llfloatergroupinvite.cpp
llfloatergroups.cpp
llfloaterhandler.cpp
@@ -421,6 +420,8 @@ set(viewer_SOURCE_FILES
llpanelface.cpp
llpanelgenerictip.cpp
llpanelgroup.cpp
+ llpanelgroupbulk.cpp
+ llpanelgroupbulkban.cpp
llpanelgroupexperiences.cpp
llpanelgroupgeneral.cpp
llpanelgroupinvite.cpp
@@ -845,8 +846,6 @@ set(viewer_HEADER_FILES
llfloatereditwater.h
llfloaterenvironmentsettings.h
llfloaterevent.h
- llfloaterfacebook.h
- llfloaterflickr.h
llfloaterexperiencepicker.h
llfloaterexperienceprofile.h
llfloaterexperiences.h
@@ -856,6 +855,7 @@ set(viewer_HEADER_FILES
llfloatergesture.h
llfloatergodtools.h
llfloatergotoline.h
+ llfloatergroupbulkban.h
llfloatergroupinvite.h
llfloatergroups.h
llfloaterhandler.h
@@ -1027,6 +1027,9 @@ set(viewer_HEADER_FILES
llpanelface.h
llpanelgenerictip.h
llpanelgroup.h
+ llpanelgroupbulk.h
+ llpanelgroupbulkimpl.h
+ llpanelgroupbulkban.h
llpanelgroupexperiences.h
llpanelgroupgeneral.h
llpanelgroupinvite.h
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index f7e5aa84c2..35c6ac5179 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-3.7.12
+3.7.14
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d2fbb822b1..000362ebfd 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -6118,16 +6118,16 @@
<integer>0</integer>
</map>
<key>MemoryLogFrequency</key>
- <map>
- <key>Comment</key>
- <string>Seconds between display of Memory in log (0 for never)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>600.0</real>
- </map>
+ <map>
+ <key>Comment</key>
+ <string>Seconds between display of Memory in log (0 for never)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>30.0</real>
+ </map>
<key>MemoryPrivatePoolEnabled</key>
<map>
<key>Comment</key>
@@ -8023,6 +8023,18 @@
<integer>128</integer>
</map>
+ <key>OctreeMinimumNodeSize</key>
+ <map>
+ <key>Comment</key>
+ <string>Minimum size of any octree node</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.01</real>
+ </map>
+
<key>OctreeStaticObjectSizeFactor</key>
<map>
<key>Comment</key>
@@ -15417,6 +15429,17 @@
<key>Value</key>
<integer>7000</integer>
</map>
+ <key>DisablePrecacheDelayAfterTeleporting</key>
+ <map>
+ <key>Comment</key>
+ <string>Disables the artificial delay in the viewer that precaches some incoming assets</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>VersionChannelName</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index a2d68eb550..628a96e988 100755
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 36
+version 37
// The version number above should be implemented IF AND ONLY IF some
// change has been made that is sufficiently important to justify
// resetting the graphics preferences of all users to the recommended
@@ -60,7 +60,7 @@ WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
-RenderTextureMemoryMultiple 1 0.5
+RenderTextureMemoryMultiple 1 1
RenderCompressTextures 1 1
RenderShaderLightingMaxLevel 1 3
RenderDeferred 1 1
@@ -522,7 +522,7 @@ list ATI_Mobility_Radeon_9600
Disregard96DefaultDrawDistance 1 0
list NVIDIA_GeForce_8600
-RenderTextureMemoryMultiple 1 0.375
+RenderTextureMemoryMultiple 1 1
RenderUseImpostors 0 0
UseOcclusion 0 0
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 3d5f6c43ee..bd6025feea 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -827,12 +827,9 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal
//-----------------------------------------------------------------------------
void LLAgent::setRegion(LLViewerRegion *regionp)
{
- bool notifyRegionChange;
-
llassert(regionp);
if (mRegionp != regionp)
{
- notifyRegionChange = true;
std::string ip = regionp->getHost().getString();
LL_INFOS("AgentLocation") << "Moving agent into region: " << regionp->getName()
@@ -885,10 +882,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
// Pass new region along to metrics components that care about this level of detail.
LLAppViewer::metricsUpdateRegion(regionp->getHandle());
}
- else
- {
- notifyRegionChange = false;
- }
+
mRegionp = regionp;
// TODO - most of what follows probably should be moved into callbacks
@@ -911,11 +905,8 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
LLFloaterMove::sUpdateFlyingStatus();
- if (notifyRegionChange)
- {
- LL_DEBUGS("AgentLocation") << "Calling RegionChanged callbacks" << LL_ENDL;
- mRegionChangedSignal();
- }
+ LL_DEBUGS("AgentLocation") << "Calling RegionChanged callbacks" << LL_ENDL;
+ mRegionChangedSignal();
}
@@ -1430,6 +1421,7 @@ void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb)
{
LLDoNotDisturbNotificationStorage::getInstance()->updateNotifications();
}
+ gIMMgr->updateDNDMessageStatus();
}
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index d1dfbe3315..7b0496ea45 100755
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -913,6 +913,8 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)
F32 max_distance = llmin(mDrawDistance - DIST_FUDGE,
LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE );
+ max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154
+
if (new_distance > max_distance)
{
new_distance = max_distance;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 6797dab839..9451a30341 100755
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1341,15 +1341,15 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
LLNotificationsUtil::add("CannotWearTrash");
return false;
}
- else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), LLAppearanceMgr::instance().getCOF())) // EXT-84911
+ else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911
{
return false;
}
switch (item_to_wear->getType())
{
- case LLAssetType::AT_CLOTHING:
- if (gAgentWearables.areWearablesLoaded())
+ case LLAssetType::AT_CLOTHING:
+ if (gAgentWearables.areWearablesLoaded())
{
if (!cb && do_update)
{
@@ -1367,7 +1367,8 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
addCOFItemLink(item_to_wear, cb);
}
break;
- case LLAssetType::AT_BODYPART:
+
+ case LLAssetType::AT_BODYPART:
// TODO: investigate wearables may not be loaded at this point EXT-8231
// Remove the existing wearables of the same type.
@@ -1379,10 +1380,12 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear,
}
addCOFItemLink(item_to_wear, cb);
break;
- case LLAssetType::AT_OBJECT:
+
+ case LLAssetType::AT_OBJECT:
rez_attachment(item_to_wear, NULL, replace);
break;
- default: return false;;
+
+ default: return false;;
}
return true;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c65bddc58b..cd9e5da7a7 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -100,6 +100,7 @@
#include "llspellcheck.h"
#include "llscenemonitor.h"
#include "llavatarrenderinfoaccountant.h"
+#include "lllocalbitmaps.h"
// Linden library includes
#include "llavatarnamecache.h"
@@ -1759,7 +1760,9 @@ bool LLAppViewer::cleanup()
#if 0 // this seems to get us stuck in an infinite loop...
gTransferManager.cleanup();
#endif
-
+
+ LLLocalBitmapMgr::cleanupClass();
+
// Note: this is where gWorldMap used to be deleted.
// Note: this is where gHUDManager used to be deleted.
@@ -3191,7 +3194,8 @@ bool LLAppViewer::initWindow()
#ifdef LL_DARWIN
//Satisfy both MAINT-3135 (OSX 10.6 and earlier) MAINT-3288 (OSX 10.7 and later)
if (getOSInfo().mMajorVer == 10 && getOSInfo().mMinorVer < 7)
- gViewerWindow->getWindow()->setOldResize(true);
+ if ( getOSInfo().mMinorVer == 6 && getOSInfo().mBuild < 8 )
+ gViewerWindow->getWindow()->setOldResize(true);
#endif
if (gSavedSettings.getBOOL("WindowMaximized"))
diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h
index df907567ab..380fdccfa3 100755
--- a/indra/newview/llcolorswatch.h
+++ b/indra/newview/llcolorswatch.h
@@ -56,6 +56,7 @@ public:
Optional<LLUIImage*> alpha_background_image;
Optional<commit_callback_t> cancel_callback;
Optional<commit_callback_t> select_callback;
+ Optional<commit_callback_t> preview_callback;
Optional<LLUIColor> border_color;
Optional<S32> label_width;
Optional<S32> label_height;
@@ -84,6 +85,7 @@ public:
void setCanApplyImmediately(BOOL apply) { mCanApplyImmediately = apply; }
void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; }
void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; }
+ void setPreviewCallback(commit_callback_t cb) { mPreviewCallback = cb; }
void setFallbackImage(LLPointer<LLUIImage> image) { mFallbackImage = image; }
void showPicker(BOOL take_focus);
@@ -109,6 +111,7 @@ protected:
bool mCanApplyImmediately;
commit_callback_t mOnCancelCallback,
mOnSelectCallback;
+ commit_callback_t mPreviewCallback;
S32 mLabelWidth,
mLabelHeight;
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 74b77f760d..6e32ce60ec 100755
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -51,6 +51,7 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u
mConvType(CONV_UNKNOWN),
mLastActiveTime(0.0),
mDisplayModeratorOptions(false),
+ mDisplayGroupBanOptions(false),
mAvatarNameCacheConnection()
{
}
@@ -63,6 +64,7 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte
mConvType(CONV_UNKNOWN),
mLastActiveTime(0.0),
mDisplayModeratorOptions(false),
+ mDisplayGroupBanOptions(false),
mAvatarNameCacheConnection()
{
}
@@ -75,6 +77,7 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod
mConvType(CONV_UNKNOWN),
mLastActiveTime(0.0),
mDisplayModeratorOptions(false),
+ mDisplayGroupBanOptions(false),
mAvatarNameCacheConnection()
{
}
@@ -159,6 +162,12 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("ModerateVoiceMute"));
items.push_back(std::string("ModerateVoiceUnmute"));
}
+
+ if ((getType() != CONV_SESSION_1_ON_1) && mDisplayGroupBanOptions)
+ {
+ items.push_back(std::string("Group Ban Separator"));
+ items.push_back(std::string("BanMember"));
+ }
}
}
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index dc74506c53..56e1a26709 100644
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -143,6 +143,7 @@ protected:
bool mNeedsRefresh; // Flag signaling to the view that something changed for this item
F64 mLastActiveTime;
bool mDisplayModeratorOptions;
+ bool mDisplayGroupBanOptions;
boost::signals2::connection mAvatarNameCacheConnection;
};
@@ -206,6 +207,7 @@ public:
void dumpDebugData();
void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; }
void setDisplayModeratorRole(bool displayRole);
+ void setGroupBanVisible(bool visible) { mDisplayGroupBanOptions = visible; }
private:
void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 211a96b32d..67d1642639 100755
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -155,7 +155,7 @@ void LLStandardBumpmap::addstandard()
LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id));
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLGLTexture::LOCAL) ;
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL );
- gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ;
+ gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0, 30.f) ;
LLStandardBumpmap::sStandardBumpmapCount++;
}
diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp
index 3e032d0e4a..513c33e60d 100755
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -796,7 +796,7 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled()
{
bool ret_val = visibleItemsSelected();
- if ( ret_val && mOkButtonValidateSignal.num_slots() )
+ if ( ret_val )
{
std::string acvtive_panel_name;
LLScrollListCtrl* list = NULL;
@@ -827,7 +827,7 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled()
getSelectedAvatarData(list, avatar_ids, avatar_names);
if (avatar_ids.size() >= 1)
{
- ret_val = mOkButtonValidateSignal(avatar_ids);
+ ret_val = mOkButtonValidateSignal.num_slots()?mOkButtonValidateSignal(avatar_ids):true;
}
else
{
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 9425f5645e..0c59ba9a6d 100755
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -342,6 +342,11 @@ void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
curG = curGIn;
curB = curBIn;
+ if (mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
+
// update corresponding HSL values and
LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL);
@@ -369,6 +374,11 @@ void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn )
// update corresponding RGB values and
hslToRgb ( curH, curS, curL, curR, curG, curB );
+
+ if (mApplyImmediateCheck->get())
+ {
+ LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
+ }
}
//////////////////////////////////////////////////////////////////////////////
@@ -458,10 +468,6 @@ void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data)
void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te )
{
setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]);
- if (mApplyImmediateCheck->get())
- {
- LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE );
- }
}
void LLFloaterColorPicker::onMouseCaptureLost()
diff --git a/indra/newview/llfloatergroupbulkban.cpp b/indra/newview/llfloatergroupbulkban.cpp
new file mode 100644
index 0000000000..54a2283b13
--- /dev/null
+++ b/indra/newview/llfloatergroupbulkban.cpp
@@ -0,0 +1,134 @@
+/**
+* @file llfloatergroupbulkban.cpp
+* @brief Floater to ban Residents from a group.
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatergroupbulkban.h"
+#include "llpanelgroupbulkban.h"
+#include "lltrans.h"
+#include "lldraghandle.h"
+
+
+class LLFloaterGroupBulkBan::impl
+{
+public:
+ impl(const LLUUID& group_id) : mGroupID(group_id), mBulkBanPanelp(NULL) {}
+ ~impl() {}
+
+ static void closeFloater(void* data);
+
+public:
+ LLUUID mGroupID;
+ LLPanelGroupBulkBan* mBulkBanPanelp;
+
+ static std::map<LLUUID, LLFloaterGroupBulkBan*> sInstances;
+};
+
+//
+// Globals
+//
+std::map<LLUUID, LLFloaterGroupBulkBan*> LLFloaterGroupBulkBan::impl::sInstances;
+
+void LLFloaterGroupBulkBan::impl::closeFloater(void* data)
+{
+ LLFloaterGroupBulkBan* floaterp = (LLFloaterGroupBulkBan*)data;
+ if(floaterp)
+ floaterp->closeFloater();
+}
+
+//-----------------------------------------------------------------------------
+// Implementation
+//-----------------------------------------------------------------------------
+LLFloaterGroupBulkBan::LLFloaterGroupBulkBan(const LLUUID& group_id/*=LLUUID::null*/)
+ : LLFloater(group_id)
+{
+ S32 floater_header_size = getHeaderHeight();
+ LLRect contents;
+
+ mImpl = new impl(group_id);
+ mImpl->mBulkBanPanelp = new LLPanelGroupBulkBan(group_id);
+
+ contents = mImpl->mBulkBanPanelp->getRect();
+ contents.mTop -= floater_header_size;
+
+ setTitle(mImpl->mBulkBanPanelp->getString("GroupBulkBan"));
+ mImpl->mBulkBanPanelp->setCloseCallback(impl::closeFloater, this);
+ mImpl->mBulkBanPanelp->setRect(contents);
+
+ addChild(mImpl->mBulkBanPanelp);
+}
+
+LLFloaterGroupBulkBan::~LLFloaterGroupBulkBan()
+{
+ if(mImpl->mGroupID.notNull())
+ {
+ impl::sInstances.erase(mImpl->mGroupID);
+ }
+
+ delete mImpl->mBulkBanPanelp;
+ delete mImpl;
+}
+
+void LLFloaterGroupBulkBan::showForGroup(const LLUUID& group_id, uuid_vec_t* agent_ids)
+{
+ const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = floater_params.header_height;
+ LLRect contents;
+
+ // Make sure group_id isn't null
+ if (group_id.isNull())
+ {
+ llwarns << "LLFloaterGroupInvite::showForGroup with null group_id!" << llendl;
+ return;
+ }
+
+ // If we don't have a floater for this group, create one.
+ LLFloaterGroupBulkBan* fgb = get_if_there(impl::sInstances,
+ group_id,
+ (LLFloaterGroupBulkBan*)NULL);
+ if (!fgb)
+ {
+ fgb = new LLFloaterGroupBulkBan(group_id);
+ contents = fgb->mImpl->mBulkBanPanelp->getRect();
+ contents.mTop += floater_header_size;
+ fgb->setRect(contents);
+ fgb->getDragHandle()->setRect(contents);
+ fgb->getDragHandle()->setTitle(fgb->mImpl->mBulkBanPanelp->getString("GroupBulkBan"));
+
+ impl::sInstances[group_id] = fgb;
+
+ fgb->mImpl->mBulkBanPanelp->clear();
+ }
+
+ if (agent_ids != NULL)
+ {
+ fgb->mImpl->mBulkBanPanelp->addUsers(*agent_ids);
+ }
+
+ fgb->center();
+ fgb->openFloater();
+ fgb->mImpl->mBulkBanPanelp->update();
+}
diff --git a/indra/newview/llfloatergroupbulkban.h b/indra/newview/llfloatergroupbulkban.h
new file mode 100644
index 0000000000..5b680a1ba4
--- /dev/null
+++ b/indra/newview/llfloatergroupbulkban.h
@@ -0,0 +1,48 @@
+/**
+* @file llfloatergroupbulkban.h
+* @brief This floater is a wrapper for LLPanelGroupBulkBan, which
+* is used to ban Residents from a specific group.
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLFLOATERGROUPBULKBAN_H
+#define LL_LLFLOATERGROUPBULKBAN_H
+
+#include "llfloater.h"
+#include "lluuid.h"
+
+class LLFloaterGroupBulkBan : public LLFloater
+{
+public:
+ virtual ~LLFloaterGroupBulkBan();
+
+ static void showForGroup(const LLUUID& group_id, uuid_vec_t* agent_ids = NULL);
+
+protected:
+ LLFloaterGroupBulkBan(const LLUUID& group_id = LLUUID::null);
+
+ class impl;
+ impl* mImpl;
+};
+
+#endif // LL_LLFLOATERGROUPBULKBAN_H
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index ebb44561da..be8195b5ee 100755
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -532,6 +532,7 @@ void LLFloaterIMContainer::draw()
{
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
participant_model->setModeratorOptionsVisible(isGroupModerator() && participant_model->getUUID() != gAgentID);
+ participant_model->setGroupBanVisible(haveAbilityToBan() && participant_model->getUUID() != gAgentID);
current_participant_model++;
}
@@ -1150,6 +1151,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec
{
toggleAllowTextChat(userID);
}
+ else if ("ban_member" == command)
+ {
+ banSelectedMember(userID);
+ }
}
else if (selectedIDS.size() > 1)
{
@@ -1271,6 +1276,22 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
uuid_vec_t uuids;
getParticipantUUIDs(uuids);
+
+ //If there is group or ad-hoc chat in multiselection, everything needs to be disabled
+ if(uuids.size() > 1)
+ {
+ const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList();
+ LLConversationItem * conversationItem;
+ for(std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it)
+ {
+ conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem());
+ if((conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) || (conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC))
+ {
+ return false;
+ }
+ }
+ }
+
if ("conversation_log" == item)
{
return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
@@ -1376,6 +1397,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return LLAvatarActions::canCall();
}
+ else if ("can_open_voice_conversation" == item)
+ {
+ return is_single_select && LLAvatarActions::canCall();
+ }
else if ("can_zoom_in" == item)
{
return is_single_select && gObjectList.findObject(single_id);
@@ -1388,6 +1413,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
{
return LLAvatarActions::canOfferTeleport(uuids);
}
+ else if ("can_ban_member" == item)
+ {
+ return canBanSelectedMember(single_id);
+ }
else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item))
{
// *TODO : get that out of here...
@@ -1810,6 +1839,95 @@ bool LLFloaterIMContainer::isGroupModerator()
return false;
}
+bool LLFloaterIMContainer::haveAbilityToBan()
+{
+ LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant();
+ if (NULL == speaker_manager)
+ {
+ LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+ return false;
+ }
+ LLUUID group_uuid = speaker_manager->getSessionID();
+
+ return gAgent.isInGroup(group_uuid) && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS);
+}
+
+bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid)
+{
+ LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant();
+ if (NULL == speaker_manager)
+ {
+ LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+ return false;
+ }
+ LLUUID group_uuid = speaker_manager->getSessionID();
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid);
+ if(!gdatap)
+ {
+ LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;
+ return false;
+ }
+
+ if (!gdatap->mMembers.size())
+ {
+ return false;
+ }
+
+ LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
+ if (mi == gdatap->mMembers.end())
+ {
+ return false;
+ }
+
+ LLGroupMemberData* member_data = (*mi).second;
+ // Is the member an owner?
+ if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
+ {
+ return false;
+ }
+
+ if( gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) &&
+ gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)
+{
+ LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant();
+ if (NULL == speaker_manager)
+ {
+ LL_WARNS() << "Speaker manager is missing" << LL_ENDL;
+ return;
+ }
+
+ LLUUID group_uuid = speaker_manager->getSessionID();
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid);
+ if(!gdatap)
+ {
+ LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;
+ return;
+ }
+ std::vector<LLUUID> ids;
+ ids.push_back(participant_uuid);
+
+ LLGroupBanData ban_data;
+ gdatap->createBanEntry(participant_uuid, ban_data);
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids);
+ LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids);
+ LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid);
+ LLSD args;
+ std::string name;
+ gCacheName->getFullName(participant_uuid, name);
+ args["AVATAR_NAME"] = name;
+ args["GROUP_NAME"] = gdatap->mName;
+ LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
+
+}
+
void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID)
{
if (!gAgent.getRegion()) return;
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index f6d973b9b3..5ea9fd399b 100755
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -167,12 +167,16 @@ private:
LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp);
LLSpeakerMgr * getSpeakerMgrForSelectedParticipant();
bool isGroupModerator();
+ bool haveAbilityToBan();
+ bool canBanSelectedMember(const LLUUID& participant_uuid);
+ LLUUID getGroupUIIDForSelectedParticipant();
bool isMuted(const LLUUID& avatar_id);
void moderateVoice(const std::string& command, const LLUUID& userID);
void moderateVoiceAllParticipants(bool unmute);
void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute);
void toggleAllowTextChat(const LLUUID& participant_uuid);
void toggleMute(const LLUUID& participant_id, U32 flags);
+ void banSelectedMember(const LLUUID& participant_uuid);
void openNearbyChat();
bool isParticipantListExpanded();
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index afbd7ba5e2..bd5d2207b4 100755
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -1069,9 +1069,9 @@ void LLFloaterTools::setGridMode(S32 mode)
void LLFloaterTools::onClickGridOptions()
{
- LLFloaterReg::showInstance("build_options");
- // RN: this makes grid options dependent on build tools window
- //floaterp->addDependentFloater(LLFloaterBuildOptions::getInstance(), FALSE);
+ LLFloater* floaterp = LLFloaterReg::showInstance("build_options");
+ // position floater next to build tools, not over
+ floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp));
}
// static
diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp
index bbfd855bc8..7f599073d5 100755
--- a/indra/newview/llfloaterwebcontent.cpp
+++ b/indra/newview/llfloaterwebcontent.cpp
@@ -74,8 +74,7 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params )
mShowPageTitle(params.show_page_title),
mAllowNavigation(true),
mCurrentURL(""),
- mDisplayURL(""),
- mSecureURL(false)
+ mDisplayURL("")
{
mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
@@ -331,9 +330,6 @@ void LLFloaterWebContent::draw()
mBtnBack->setEnabled( mWebBrowser->canNavigateBack() && mAllowNavigation);
mBtnForward->setEnabled( mWebBrowser->canNavigateForward() && mAllowNavigation);
- // Show/hide the lock icon
- mSecureLockIcon->setVisible(mSecureURL && !mAddressCombo->hasFocus());
-
LLFloater::draw();
}
@@ -378,8 +374,6 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
// we populate the status bar with URLs as they change so clear it now we're done
const std::string end_str = "";
mStatusBarText->setText( end_str );
- mAddressCombo->setLeftTextPadding(22);
- mAddressCombo->setLeftTextPadding(2);
}
else if(event == MEDIA_EVENT_CLOSE_REQUEST)
{
@@ -446,10 +440,10 @@ void LLFloaterWebContent::set_current_url(const std::string& url)
static const std::string secure_prefix = std::string("https://");
std::string prefix = mCurrentURL.substr(0, secure_prefix.length());
LLStringUtil::toLower(prefix);
- mSecureURL = (prefix == secure_prefix);
-
- // Hack : we move the text a bit to make space for the lock icon in the secure URL case
- mDisplayURL = (mSecureURL ? " " + mCurrentURL : mCurrentURL);
+ bool secure_url = (prefix == secure_prefix);
+ mSecureLockIcon->setVisible(secure_url);
+ mAddressCombo->setLeftTextPadding(secure_url ? 22 : 2);
+ mDisplayURL = mCurrentURL;
// Clean up browsing list (prevent dupes) and add/select the new URL to it
mAddressCombo->remove(mCurrentURL);
diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h
index f5faa39e3d..4291fd9f2c 100755
--- a/indra/newview/llfloaterwebcontent.h
+++ b/indra/newview/llfloaterwebcontent.h
@@ -113,7 +113,6 @@ protected:
std::string mUUID;
bool mShowPageTitle;
bool mAllowNavigation;
- bool mSecureURL; // true when the current url is prefixed "https://"
};
#endif // LL_LLFLOATERWEBCONTENT_H
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index f514729aa1..913efd6434 100755
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -149,7 +149,7 @@ public:
void changed(LLGroupChange gc)
{
- if (gc == GC_MEMBER_DATA && !mRequestProcessed)
+ if (gc == GC_PROPERTIES && !mRequestProcessed)
{
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId);
if (!gdatap)
@@ -159,9 +159,6 @@ public:
else if (!gdatap->isMemberDataComplete())
{
LL_WARNS() << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << LL_ENDL;
- }
- else
- {
processGroupData();
mRequestProcessed = true;
}
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index d5b817ce76..56e671d902 100755
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -234,11 +234,11 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :
mMemberCount(0),
mRoleCount(0),
mReceivedRoleMemberPairs(0),
- mMemberDataComplete(FALSE),
- mRoleDataComplete(FALSE),
- mRoleMemberDataComplete(FALSE),
- mGroupPropertiesDataComplete(FALSE),
- mPendingRoleMemberRequest(FALSE),
+ mMemberDataComplete(false),
+ mRoleDataComplete(false),
+ mRoleMemberDataComplete(false),
+ mGroupPropertiesDataComplete(false),
+ mPendingRoleMemberRequest(false),
mAccessTime(0.0f)
{
mMemberVersion.generate();
@@ -427,7 +427,7 @@ void LLGroupMgrGroupData::removeMemberData()
delete mi->second;
}
mMembers.clear();
- mMemberDataComplete = FALSE;
+ mMemberDataComplete = false;
mMemberVersion.generate();
}
@@ -449,8 +449,8 @@ void LLGroupMgrGroupData::removeRoleData()
}
mRoles.clear();
mReceivedRoleMemberPairs = 0;
- mRoleDataComplete = FALSE;
- mRoleMemberDataComplete = FALSE;
+ mRoleDataComplete = false;
+ mRoleMemberDataComplete= false;
}
void LLGroupMgrGroupData::removeRoleMemberData()
@@ -474,7 +474,7 @@ void LLGroupMgrGroupData::removeRoleMemberData()
}
mReceivedRoleMemberPairs = 0;
- mRoleMemberDataComplete = FALSE;
+ mRoleMemberDataComplete= false;
}
LLGroupMgrGroupData::~LLGroupMgrGroupData()
@@ -750,6 +750,20 @@ void LLGroupMgrGroupData::cancelRoleChanges()
// Clear out all changes!
mRoleChanges.clear();
}
+
+void LLGroupMgrGroupData::createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data)
+{
+ mBanList[ban_id] = ban_data;
+}
+
+void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)
+{
+ mBanList.erase(ban_id);
+}
+
+
+
+
//
// LLGroupMgr
//
@@ -959,12 +973,12 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
if (group_datap->mMembers.size() == (U32)group_datap->mMemberCount)
{
- group_datap->mMemberDataComplete = TRUE;
+ group_datap->mMemberDataComplete = true;
group_datap->mMemberRequestID.setNull();
// We don't want to make role-member data requests until we have all the members
if (group_datap->mPendingRoleMemberRequest)
{
- group_datap->mPendingRoleMemberRequest = FALSE;
+ group_datap->mPendingRoleMemberRequest = false;
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
}
}
@@ -1034,7 +1048,7 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
group_datap->mMemberCount = num_group_members;
group_datap->mRoleCount = num_group_roles + 1; // Add the everyone role.
- group_datap->mGroupPropertiesDataComplete = TRUE;
+ group_datap->mGroupPropertiesDataComplete = true;
group_datap->mChanged = TRUE;
LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
@@ -1111,12 +1125,12 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
if (group_datap->mRoles.size() == (U32)group_datap->mRoleCount)
{
- group_datap->mRoleDataComplete = TRUE;
+ group_datap->mRoleDataComplete = true;
group_datap->mRoleDataRequestID.setNull();
// We don't want to make role-member data requests until we have all the role data
if (group_datap->mPendingRoleMemberRequest)
{
- group_datap->mPendingRoleMemberRequest = FALSE;
+ group_datap->mPendingRoleMemberRequest = false;
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
}
}
@@ -1225,7 +1239,7 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
}
}
- group_datap->mRoleMemberDataComplete = TRUE;
+ group_datap->mRoleMemberDataComplete= true;
group_datap->mRoleMembersRequestID.setNull();
}
@@ -1849,6 +1863,138 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
// Responder class for capability group management
+class GroupBanDataResponder : public LLHTTPClient::Responder
+{
+public:
+ GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh=false);
+ virtual ~GroupBanDataResponder() {}
+ virtual void httpSuccess();
+ virtual void httpFailure();
+private:
+ LLUUID mGroupID;
+ BOOL mForceRefresh;
+};
+
+GroupBanDataResponder::GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh) :
+ mGroupID(gropup_id),
+ mForceRefresh(force_refresh)
+{}
+
+void GroupBanDataResponder::httpFailure()
+{
+ LL_WARNS("GrpMgr") << "Error receiving group member data [status:"
+ << mStatus << "]: " << mContent << LL_ENDL;
+}
+
+void GroupBanDataResponder::httpSuccess()
+{
+ if (mContent.has("ban_list"))
+ {
+ // group ban data received
+ LLGroupMgr::processGroupBanRequest(mContent);
+ }
+ else if (mForceRefresh)
+ {
+ // no ban data received, refreshing data after successful operation
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
+ }
+}
+
+void LLGroupMgr::sendGroupBanRequest( EBanRequestType request_type,
+ const LLUUID& group_id,
+ U32 ban_action, /* = BAN_NO_ACTION */
+ const std::vector<LLUUID> ban_list) /* = std::vector<LLUUID>() */
+{
+ LLViewerRegion* currentRegion = gAgent.getRegion();
+ if(!currentRegion)
+ {
+ LL_WARNS("GrpMgr") << "Agent does not have a current region. Uh-oh!" << LL_ENDL;
+ return;
+ }
+
+ // Check to make sure we have our capabilities
+ if(!currentRegion->capabilitiesReceived())
+ {
+ LL_WARNS("GrpMgr") << " Capabilities not received!" << LL_ENDL;
+ return;
+ }
+
+ // Get our capability
+ std::string cap_url = currentRegion->getCapability("GroupAPIv1");
+ if(cap_url.empty())
+ {
+ return;
+ }
+ cap_url += "?group_id=" + group_id.asString();
+
+ LLSD body = LLSD::emptyMap();
+ body["ban_action"] = (LLSD::Integer)(ban_action & ~BAN_UPDATE);
+ // Add our list of potential banned residents to the list
+ body["ban_ids"] = LLSD::emptyArray();
+ LLSD ban_entry;
+
+ uuid_vec_t::const_iterator iter = ban_list.begin();
+ for(;iter != ban_list.end(); ++iter)
+ {
+ ban_entry = (*iter);
+ body["ban_ids"].append(ban_entry);
+ }
+
+ LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(group_id, ban_action & BAN_UPDATE);
+ switch(request_type)
+ {
+ case REQUEST_GET:
+ LLHTTPClient::get(cap_url, grp_ban_responder);
+ break;
+ case REQUEST_POST:
+ LLHTTPClient::post(cap_url, body, grp_ban_responder);
+ break;
+ case REQUEST_PUT:
+ case REQUEST_DEL:
+ break;
+ }
+}
+
+
+void LLGroupMgr::processGroupBanRequest(const LLSD& content)
+{
+ // Did we get anything in content?
+ if(!content.size())
+ {
+ LL_WARNS("GrpMgr") << "No group member data received." << LL_ENDL;
+ return;
+ }
+
+ LLUUID group_id = content["group_id"].asUUID();
+
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if (!gdatap)
+ return;
+
+ LLSD::map_const_iterator i = content["ban_list"].beginMap();
+ LLSD::map_const_iterator iEnd = content["ban_list"].endMap();
+ for(;i != iEnd; ++i)
+ {
+ const LLUUID ban_id(i->first);
+ LLSD ban_entry(i->second);
+
+ LLGroupBanData ban_data;
+ if(ban_entry.has("ban_date"))
+ {
+ ban_data.mBanDate = ban_entry["ban_date"].asDate();
+ // TODO: Ban Reason
+ }
+
+ gdatap->createBanEntry(ban_id, ban_data);
+ }
+
+ gdatap->mChanged = TRUE;
+ LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST);
+}
+
+
+
+// Responder class for capability group management
class GroupMemberDataResponder : public LLHTTPClient::Responder
{
LOG_CLASS(GroupMemberDataResponder);
@@ -1941,7 +2087,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
if(num_members < 1)
return;
- LLUUID group_id = content["group_id"].asUUID();
+ LLUUID group_id = content["group_id"].asUUID();
LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
if(!group_datap)
@@ -2008,6 +2154,22 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
online_status,
is_owner);
+ LLGroupMemberData* member_old = group_datap->mMembers[member_id];
+ if (member_old && group_datap->mRoleMemberDataComplete)
+ {
+ LLGroupMemberData::role_list_t::iterator rit = member_old->roleBegin();
+ LLGroupMemberData::role_list_t::iterator end = member_old->roleEnd();
+
+ for ( ; rit != end; ++rit)
+ {
+ data->addRole((*rit).first,(*rit).second);
+ }
+ }
+ else
+ {
+ group_datap->mRoleMemberDataComplete = false;
+ }
+
group_datap->mMembers[member_id] = data;
}
@@ -2024,12 +2186,12 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id);
- group_datap->mMemberDataComplete = TRUE;
+ group_datap->mMemberDataComplete = true;
group_datap->mMemberRequestID.setNull();
// Make the role-member data request
- if (group_datap->mPendingRoleMemberRequest)
+ if (group_datap->mPendingRoleMemberRequest || !group_datap->mRoleMemberDataComplete)
{
- group_datap->mPendingRoleMemberRequest = FALSE;
+ group_datap->mPendingRoleMemberRequest = false;
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id);
}
diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h
index 9b62ecac48..2e94e8d9a0 100755
--- a/indra/newview/llgroupmgr.h
+++ b/indra/newview/llgroupmgr.h
@@ -33,8 +33,10 @@
#include <string>
#include <map>
+// Forward Declarations
class LLMessageSystem;
-
+class LLGroupRoleData;
+class LLGroupMgr;
enum LLGroupChange
{
@@ -43,9 +45,12 @@ enum LLGroupChange
GC_ROLE_DATA,
GC_ROLE_MEMBER_DATA,
GC_TITLES,
+ GC_BANLIST,
GC_ALL
};
+const U32 GB_MAX_BANNED_AGENTS = 500;
+
class LLGroupMgrObserver
{
public:
@@ -65,8 +70,6 @@ public:
virtual void changed(const LLUUID& group_id, LLGroupChange gc) = 0;
};
-class LLGroupRoleData;
-
class LLGroupMemberData
{
friend class LLGroupMgrGroupData;
@@ -201,6 +204,17 @@ struct lluuid_pair_less
}
};
+
+struct LLGroupBanData
+{
+ LLGroupBanData(): mBanDate() {}
+ ~LLGroupBanData() {}
+
+ LLDate mBanDate;
+ // TODO: std:string ban_reason;
+};
+
+
struct LLGroupTitle
{
std::string mTitle;
@@ -208,8 +222,6 @@ struct LLGroupTitle
BOOL mSelected;
};
-class LLGroupMgr;
-
class LLGroupMgrGroupData
{
friend class LLGroupMgr;
@@ -239,11 +251,11 @@ public:
void recalcAllAgentPowers();
void recalcAgentPowers(const LLUUID& agent_id);
- BOOL isMemberDataComplete() { return mMemberDataComplete; }
- BOOL isRoleDataComplete() { return mRoleDataComplete; }
- BOOL isRoleMemberDataComplete() { return mRoleMemberDataComplete; }
- BOOL isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; }
-
+ bool isMemberDataComplete() { return mMemberDataComplete; }
+ bool isRoleDataComplete() { return mRoleDataComplete; }
+ bool isRoleMemberDataComplete() { return mRoleMemberDataComplete; }
+ bool isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; }
+
bool isSingleMemberNotOwner();
F32 getAccessTime() const { return mAccessTime; }
@@ -251,17 +263,26 @@ public:
const LLUUID& getMemberVersion() const { return mMemberVersion; }
+ void clearBanList() { mBanList.clear(); }
+ void getBanList(const LLUUID& group_id, LLGroupBanData& ban_data);
+ const LLGroupBanData& getBanEntry(const LLUUID& ban_id) { return mBanList[ban_id]; }
+
+ void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData());
+ void removeBanEntry(const LLUUID& ban_id);
+
+
public:
typedef std::map<LLUUID,LLGroupMemberData*> member_list_t;
typedef std::map<LLUUID,LLGroupRoleData*> role_list_t;
typedef std::map<lluuid_pair,LLRoleMemberChange,lluuid_pair_less> change_map_t;
typedef std::map<LLUUID,LLRoleData> role_data_map_t;
+ typedef std::map<LLUUID,LLGroupBanData> ban_list_t;
+
member_list_t mMembers;
role_list_t mRoles;
-
-
change_map_t mRoleMemberChanges;
role_data_map_t mRoleChanges;
+ ban_list_t mBanList;
std::vector<LLGroupTitle> mTitles;
@@ -292,12 +313,12 @@ private:
LLUUID mTitlesRequestID;
U32 mReceivedRoleMemberPairs;
- BOOL mMemberDataComplete;
- BOOL mRoleDataComplete;
- BOOL mRoleMemberDataComplete;
- BOOL mGroupPropertiesDataComplete;
+ bool mMemberDataComplete;
+ bool mRoleDataComplete;
+ bool mRoleMemberDataComplete;
+ bool mGroupPropertiesDataComplete;
- BOOL mPendingRoleMemberRequest;
+ bool mPendingRoleMemberRequest;
F32 mAccessTime;
// Generate a new ID every time mMembers
@@ -325,6 +346,23 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>
LOG_CLASS(LLGroupMgr);
public:
+ enum EBanRequestType
+ {
+ REQUEST_GET = 0,
+ REQUEST_POST,
+ REQUEST_PUT,
+ REQUEST_DEL
+ };
+
+ enum EBanRequestAction
+ {
+ BAN_NO_ACTION = 0,
+ BAN_CREATE = 1,
+ BAN_DELETE = 2,
+ BAN_UPDATE = 4
+ };
+
+public:
LLGroupMgr();
~LLGroupMgr();
@@ -357,8 +395,14 @@ public:
static void sendGroupMemberInvites(const LLUUID& group_id, std::map<LLUUID,LLUUID>& role_member_pairs);
static void sendGroupMemberEjects(const LLUUID& group_id,
uuid_vec_t& member_ids);
+
+ static void sendGroupBanRequest(EBanRequestType request_type,
+ const LLUUID& group_id,
+ U32 ban_action = BAN_NO_ACTION,
+ const uuid_vec_t ban_list = uuid_vec_t());
+
+ static void processGroupBanRequest(const LLSD& content);
- // BAKER
void sendCapGroupMembersRequest(const LLUUID& group_id);
static void processCapGroupMembersRequest(const LLSD& content);
@@ -403,4 +447,3 @@ private:
#endif
-
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 1b0f370536..8d8239611c 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -410,6 +410,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
mOtherParticipantIsAvatar(true),
mStartCallOnInitialize(false),
mStartedAsIMCall(voice),
+ mIsDNDsend(false),
mAvatarNameCacheConnection()
{
// set P2P type by default
@@ -3315,6 +3316,38 @@ bool LLIMMgr::isVoiceCall(const LLUUID& session_id)
return im_session->mStartedAsIMCall;
}
+void LLIMMgr::updateDNDMessageStatus()
+{
+ if (LLIMModel::getInstance()->mId2SessionMap.empty()) return;
+
+ std::map<LLUUID, LLIMModel::LLIMSession*>::const_iterator it = LLIMModel::getInstance()->mId2SessionMap.begin();
+ for (; it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
+ {
+ LLIMModel::LLIMSession* session = (*it).second;
+
+ if (session->isP2P())
+ {
+ setDNDMessageSent(session->mSessionID,false);
+ }
+ }
+}
+
+bool LLIMMgr::isDNDMessageSend(const LLUUID& session_id)
+{
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!im_session) return false;
+
+ return im_session->mIsDNDsend;
+}
+
+void LLIMMgr::setDNDMessageSent(const LLUUID& session_id, bool is_send)
+{
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (!im_session) return;
+
+ im_session->mIsDNDsend = is_send;
+}
+
void LLIMMgr::addNotifiedNonFriendSessionID(const LLUUID& session_id)
{
mNotifiedNonFriendSessions.insert(session_id);
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 1426bada95..f92eff4845 100755
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -138,6 +138,8 @@ public:
bool mHasOfflineMessage;
+ bool mIsDNDsend;
+
private:
void onAdHocNameCache(const LLAvatarName& av_name);
@@ -441,6 +443,12 @@ public:
bool isVoiceCall(const LLUUID& session_id);
+ void updateDNDMessageStatus();
+
+ bool isDNDMessageSend(const LLUUID& session_id);
+
+ void setDNDMessageSent(const LLUUID& session_id, bool is_send);
+
void addNotifiedNonFriendSessionID(const LLUUID& session_id);
bool isNonFriendSessionNotified(const LLUUID& session_id);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 5df28ccb73..87335cd5e6 100755
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4593,6 +4593,10 @@ public:
virtual void changed(U32 mask)
{
mBridgep->refreshFolderViewItem();
+ if (mask & LLFriendObserver::ONLINE)
+ {
+ mBridgep->checkSearchBySuffixChanges();
+ }
}
protected:
LLCallingCardBridge* mBridgep;
@@ -4627,6 +4631,44 @@ void LLCallingCardBridge::refreshFolderViewItem()
}
}
+void LLCallingCardBridge::checkSearchBySuffixChanges()
+{
+ if (!mDisplayName.empty())
+ {
+ // changes in mDisplayName are processed by rename function and here it will be always same
+ // suffixes are also of fixed length, and we are processing change of one at a time,
+ // so it should be safe to use length (note: mSearchableName is capitalized)
+ S32 old_length = mSearchableName.length();
+ S32 new_length = mDisplayName.length() + getLabelSuffix().length();
+ if (old_length == new_length)
+ {
+ return;
+ }
+ mSearchableName.assign(mDisplayName);
+ mSearchableName.append(getLabelSuffix());
+ LLStringUtil::toUpper(mSearchableName);
+ if (new_length<old_length)
+ {
+ LLInventoryFilter* filter = getInventoryFilter();
+ if (filter && mPassedFilter && mSearchableName.find(filter->getFilterSubString()) == std::string::npos)
+ {
+ // string no longer contains substring
+ // we either have to update all parents manually or restart filter.
+ // dirtyFilter will not work here due to obsolete descendants' generations
+ getInventoryFilter()->setModified(LLFolderViewFilter::FILTER_MORE_RESTRICTIVE);
+ }
+ }
+ else
+ {
+ if (getInventoryFilter())
+ {
+ // mSearchableName became longer, we gained additional suffix and need to repeat filter check.
+ dirtyFilter();
+ }
+ }
+ }
+}
+
// virtual
void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string action)
{
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 02134c7cc5..7dac830098 100755
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -421,6 +421,7 @@ public:
void* cargo_data,
std::string& tooltip_msg);
void refreshFolderViewItem();
+ void checkSearchBySuffixChanges();
protected:
LLCallingCardObserver* mObserver;
};
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index e74e58015a..a4a85e2e8d 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -547,6 +547,14 @@ void LLInventoryPanel::modelChanged(U32 mask)
// Item is to be moved and we found its new parent in the panel's directory, so move the item's UI.
view_item->addToFolder(new_parent);
addItemID(viewmodel_item->getUUID(), view_item);
+ if (mInventory)
+ {
+ const LLUUID trash_id = mInventory->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if (trash_id != model_item->getParentUUID() && (mask & LLInventoryObserver::INTERNAL) && new_parent->isOpen())
+ {
+ setSelection(item_id, FALSE);
+ }
+ }
}
else
{
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 8e4950f5c2..b91e37d596 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -190,7 +190,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
{
// decode is successful, we can safely proceed.
LLUUID old_id = LLUUID::null;
- if (!(optional_firstupdate == UT_FIRSTUSE) && !mWorldID.isNull())
+ if ((optional_firstupdate != UT_FIRSTUSE) && !mWorldID.isNull())
{
old_id = mWorldID;
}
@@ -206,15 +206,18 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
gTextureList.addImage(texture);
- if (!optional_firstupdate == UT_FIRSTUSE)
+ if (optional_firstupdate != UT_FIRSTUSE)
{
// seek out everything old_id uses and replace it with mWorldID
replaceIDs(old_id, mWorldID);
// remove old_id from gimagelist
LLViewerFetchedTexture* image = gTextureList.findImage(old_id);
- gTextureList.deleteImage(image);
- image->unref();
+ if (image != NULL)
+ {
+ gTextureList.deleteImage(image);
+ image->unref();
+ }
}
mUpdateRetries = LL_LOCAL_UPDATE_RETRIES;
@@ -824,6 +827,12 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr()
{
}
+void LLLocalBitmapMgr::cleanupClass()
+{
+ std::for_each(sBitmapList.begin(), sBitmapList.end(), DeletePointer());
+ sBitmapList.clear();
+}
+
bool LLLocalBitmapMgr::addUnit()
{
bool add_successful = false;
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index 47c077dcab..a15ea10801 100755
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -117,6 +117,7 @@ class LLLocalBitmapMgr
~LLLocalBitmapMgr();
public:
+ static void cleanupClass();
static bool addUnit();
static void delUnit(LLUUID tracking_id);
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 109d6b31b2..2810941d83 100755
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -66,9 +66,8 @@ const F32 SNAP_GUIDE_SCREEN_OFFSET = 0.05f;
const F32 SNAP_GUIDE_SCREEN_LENGTH = 0.7f;
const F32 SELECTED_MANIPULATOR_SCALE = 1.2f;
const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
-const S32 NUM_MANIPULATORS = 14;
-const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] =
+const LLManip::EManipPart MANIPULATOR_IDS[LLManipScale::NUM_MANIPULATORS] =
{
LLManip::LL_CORNER_NNN,
LLManip::LL_CORNER_NNP,
@@ -143,18 +142,16 @@ inline void LLManipScale::conditionalHighlight( U32 part, const LLColor4* highli
LLColor4 default_highlight( 1.f, 1.f, 1.f, 1.f );
LLColor4 default_normal( 0.7f, 0.7f, 0.7f, 0.6f );
LLColor4 invisible(0.f, 0.f, 0.f, 0.f);
- F32 manipulator_scale = 1.f;
for (S32 i = 0; i < NUM_MANIPULATORS; i++)
{
if((U32)MANIPULATOR_IDS[i] == part)
{
- manipulator_scale = mManipulatorScales[i];
+ mScaledBoxHandleSize = mManipulatorScales[i] * mBoxHandleSize[i];
break;
}
}
- mScaledBoxHandleSize = mBoxHandleSize * manipulator_scale;
if (mManipPart != (S32)LL_NO_PART && mManipPart != (S32)part)
{
gGL.color4fv( invisible.mV );
@@ -181,7 +178,6 @@ void LLManipScale::handleSelect()
LLManipScale::LLManipScale( LLToolComposite* composite )
:
LLManip( std::string("Scale"), composite ),
- mBoxHandleSize( 1.f ),
mScaledBoxHandleSize( 1.f ),
mLastMouseX( -1 ),
mLastMouseY( -1 ),
@@ -196,17 +192,16 @@ LLManipScale::LLManipScale( LLToolComposite* composite )
mSnapRegime(SNAP_REGIME_NONE),
mScaleSnappedValue(0.f)
{
- mManipulatorScales = new F32[NUM_MANIPULATORS];
for (S32 i = 0; i < NUM_MANIPULATORS; i++)
{
mManipulatorScales[i] = 1.f;
+ mBoxHandleSize[i] = 1.f;
}
}
LLManipScale::~LLManipScale()
{
for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer());
- delete[] mManipulatorScales;
}
void LLManipScale::render()
@@ -216,6 +211,7 @@ void LLManipScale::render()
LLGLDepthTest gls_depth(GL_TRUE);
LLGLEnable gl_blend(GL_BLEND);
LLGLEnable gls_alpha_test(GL_ALPHA_TEST);
+ LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
if( canAffectSelection() )
{
@@ -237,42 +233,48 @@ void LLManipScale::render()
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
- mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
- mBoxHandleSize /= gAgentCamera.mHUDCurZoom;
+ for (S32 i = 0; i < NUM_MANIPULATORS; i++)
+ {
+ mBoxHandleSize[i] = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
+ mBoxHandleSize[i] /= gAgentCamera.mHUDCurZoom;
+ }
}
else
{
- F32 range_squared = dist_vec_squared(gAgentCamera.getCameraPositionAgent(), center_agent);
- F32 range_from_agent_squared = dist_vec_squared(gAgent.getPositionAgent(), center_agent);
-
- // Don't draw manip if object too far away
- if (gSavedSettings.getBOOL("LimitSelectDistance"))
+ for (S32 i = 0; i < NUM_MANIPULATORS; i++)
{
- F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance");
- if (range_from_agent_squared > max_select_distance * max_select_distance)
+ LLVector3 manipulator_pos = bbox.localToAgent(unitVectorToLocalBBoxExtent(partToUnitVector(MANIPULATOR_IDS[i]), bbox));
+ F32 range_squared = dist_vec_squared(gAgentCamera.getCameraPositionAgent(), manipulator_pos);
+ F32 range_from_agent_squared = dist_vec_squared(gAgent.getPositionAgent(), manipulator_pos);
+
+ // Don't draw manip if object too far away
+ if (gSavedSettings.getBOOL("LimitSelectDistance"))
{
- return;
+ F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance");
+ if (range_from_agent_squared > max_select_distance * max_select_distance)
+ {
+ return;
+ }
}
- }
- if (range_squared > 0.001f * 0.001f)
- {
- // range != zero
- F32 fraction_of_fov = BOX_HANDLE_BASE_SIZE / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
- F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
- mBoxHandleSize = (F32) sqrtf(range_squared) * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR;
- }
- else
- {
- // range == zero
- mBoxHandleSize = BOX_HANDLE_BASE_FACTOR;
+ if (range_squared > 0.001f * 0.001f)
+ {
+ // range != zero
+ F32 fraction_of_fov = BOX_HANDLE_BASE_SIZE / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
+ F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
+ mBoxHandleSize[i] = (F32) sqrtf(range_squared) * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR;
+ }
+ else
+ {
+ // range == zero
+ mBoxHandleSize[i] = BOX_HANDLE_BASE_FACTOR;
+ }
}
}
////////////////////////////////////////////////////////////////////////
// Draw bounding box
- LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
LLVector3 pos_agent = bbox.getPositionAgent();
LLQuaternion rot = bbox.getRotation();
@@ -564,7 +566,7 @@ void LLManipScale::renderFaces( const LLBBox& bbox )
// +------------+ | (texture coordinates)
// | | |
// | 1 | (*) --->s
- // | +X |
+ // | +X |
// | |
// (+++) (+-+)| |(+--) (++-) (+++)
// +------------+------------+------------+------------+
@@ -679,32 +681,32 @@ void LLManipScale::renderFaces( const LLBBox& bbox )
{
case 0:
conditionalHighlight( LL_FACE_POSZ, &z_highlight_color, &z_normal_color );
- renderAxisHandle( ctr, LLVector3( ctr.mV[VX], ctr.mV[VY], max.mV[VZ] ) );
+ renderAxisHandle( LL_FACE_POSZ, ctr, LLVector3( ctr.mV[VX], ctr.mV[VY], max.mV[VZ] ) );
break;
case 1:
conditionalHighlight( LL_FACE_POSX, &x_highlight_color, &x_normal_color );
- renderAxisHandle( ctr, LLVector3( max.mV[VX], ctr.mV[VY], ctr.mV[VZ] ) );
+ renderAxisHandle( LL_FACE_POSX, ctr, LLVector3( max.mV[VX], ctr.mV[VY], ctr.mV[VZ] ) );
break;
case 2:
conditionalHighlight( LL_FACE_POSY, &y_highlight_color, &y_normal_color );
- renderAxisHandle( ctr, LLVector3( ctr.mV[VX], max.mV[VY], ctr.mV[VZ] ) );
+ renderAxisHandle( LL_FACE_POSY, ctr, LLVector3( ctr.mV[VX], max.mV[VY], ctr.mV[VZ] ) );
break;
case 3:
conditionalHighlight( LL_FACE_NEGX, &x_highlight_color, &x_normal_color );
- renderAxisHandle( ctr, LLVector3( min.mV[VX], ctr.mV[VY], ctr.mV[VZ] ) );
+ renderAxisHandle( LL_FACE_NEGX, ctr, LLVector3( min.mV[VX], ctr.mV[VY], ctr.mV[VZ] ) );
break;
case 4:
conditionalHighlight( LL_FACE_NEGY, &y_highlight_color, &y_normal_color );
- renderAxisHandle( ctr, LLVector3( ctr.mV[VX], min.mV[VY], ctr.mV[VZ] ) );
+ renderAxisHandle( LL_FACE_NEGY, ctr, LLVector3( ctr.mV[VX], min.mV[VY], ctr.mV[VZ] ) );
break;
case 5:
conditionalHighlight( LL_FACE_NEGZ, &z_highlight_color, &z_normal_color );
- renderAxisHandle( ctr, LLVector3( ctr.mV[VX], ctr.mV[VY], min.mV[VZ] ) );
+ renderAxisHandle( LL_FACE_NEGZ, ctr, LLVector3( ctr.mV[VX], ctr.mV[VY], min.mV[VZ] ) );
break;
}
}
@@ -714,10 +716,10 @@ void LLManipScale::renderFaces( const LLBBox& bbox )
void LLManipScale::renderEdges( const LLBBox& bbox )
{
LLVector3 extent = bbox.getExtentLocal();
- F32 edge_width = mBoxHandleSize * .6f;
for( U32 part = LL_EDGE_MIN; part <= LL_EDGE_MAX; part++ )
{
+ F32 edge_width = mBoxHandleSize[part] * .6f;
LLVector3 direction = edgeToUnitVector( part );
LLVector3 center_to_edge = unitVectorToLocalBBoxExtent( direction, bbox );
@@ -778,14 +780,14 @@ void LLManipScale::renderBoxHandle( F32 x, F32 y, F32 z )
}
-void LLManipScale::renderAxisHandle( const LLVector3& start, const LLVector3& end )
+void LLManipScale::renderAxisHandle( U32 part, const LLVector3& start, const LLVector3& end )
{
if( getShowAxes() )
{
// Draws a single "jacks" style handle: a long, retangular box from start to end.
LLVector3 offset_start = end - start;
offset_start.normalize();
- offset_start = start + mBoxHandleSize * offset_start;
+ offset_start = start + mBoxHandleSize[part] * offset_start;
LLVector3 delta = end - offset_start;
LLVector3 pos = offset_start + 0.5f * delta;
@@ -794,9 +796,9 @@ void LLManipScale::renderAxisHandle( const LLVector3& start, const LLVector3& en
{
gGL.translatef( pos.mV[VX], pos.mV[VY], pos.mV[VZ] );
gGL.scalef(
- mBoxHandleSize + llabs(delta.mV[VX]),
- mBoxHandleSize + llabs(delta.mV[VY]),
- mBoxHandleSize + llabs(delta.mV[VZ]));
+ mBoxHandleSize[part] + llabs(delta.mV[VX]),
+ mBoxHandleSize[part] + llabs(delta.mV[VY]),
+ mBoxHandleSize[part] + llabs(delta.mV[VZ]));
gBox.render();
}
gGL.popMatrix();
@@ -1663,15 +1665,15 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
arrow_dir = snap_line_start - snap_line_center;
arrow_dir.normalize();
- gGL.vertex3fv((snap_line_start + arrow_dir * mBoxHandleSize).mV);
- gGL.vertex3fv((snap_line_start + arrow_span * mBoxHandleSize).mV);
- gGL.vertex3fv((snap_line_start - arrow_span * mBoxHandleSize).mV);
+ gGL.vertex3fv((snap_line_start + arrow_dir * mSnapRegimeOffset * 0.1f).mV);
+ gGL.vertex3fv((snap_line_start + arrow_span * mSnapRegimeOffset * 0.1f).mV);
+ gGL.vertex3fv((snap_line_start - arrow_span * mSnapRegimeOffset * 0.1f).mV);
arrow_dir = snap_line_end - snap_line_center;
arrow_dir.normalize();
- gGL.vertex3fv((snap_line_end + arrow_dir * mBoxHandleSize).mV);
- gGL.vertex3fv((snap_line_end + arrow_span * mBoxHandleSize).mV);
- gGL.vertex3fv((snap_line_end - arrow_span * mBoxHandleSize).mV);
+ gGL.vertex3fv((snap_line_end + arrow_dir * mSnapRegimeOffset * 0.1f).mV);
+ gGL.vertex3fv((snap_line_end + arrow_span * mSnapRegimeOffset * 0.1f).mV);
+ gGL.vertex3fv((snap_line_end - arrow_span * mSnapRegimeOffset * 0.1f).mV);
}
gGL.end();
}
@@ -1727,7 +1729,7 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
{
F32 alpha = (1.f - (1.f * ((F32)llabs(i) / (F32)num_ticks_per_side2)));
LLVector3 tick_pos = mScaleCenter + (mScaleDir * (grid_multiple2 + i) * smallest_subdivision2);
-
+
F32 cur_subdivisions = llclamp(getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit2, mTickPixelSpacing2), sGridMinSubdivisionLevel, sGridMaxSubdivisionLevel);
if (fmodf((F32)(i + sub_div_offset_2), (sGridMaxSubdivisionLevel / cur_subdivisions)) != 0.f)
@@ -1780,7 +1782,7 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox)
if (fmodf((F32)(i + label_sub_div_offset_1), (sGridMaxSubdivisionLevel / llmin(sGridMaxSubdivisionLevel, getSubdivisionLevel(tick_pos, mScaleDir, mScaleSnapUnit1, tick_label_spacing)))) == 0.f)
{
LLVector3 text_origin = tick_pos + (mSnapGuideDir1 * mSnapRegimeOffset * (1.f + tick_scale));
-
+
EGridMode grid_mode = LLSelectMgr::getInstance()->getGridMode();
F32 tick_value;
if (grid_mode == GRID_MODE_WORLD)
diff --git a/indra/newview/llmanipscale.h b/indra/newview/llmanipscale.h
index e1da7a1bb5..7cc3c99810 100755
--- a/indra/newview/llmanipscale.h
+++ b/indra/newview/llmanipscale.h
@@ -71,7 +71,7 @@ public:
ManipulatorHandle(LLVector3 pos, EManipPart id, EScaleManipulatorType type):mPosition(pos), mManipID(id), mType(type){}
};
-
+ static const S32 NUM_MANIPULATORS = 14;
LLManipScale( LLToolComposite* composite );
~LLManipScale();
@@ -98,7 +98,7 @@ private:
void renderFaces( const LLBBox& local_bbox );
void renderEdges( const LLBBox& local_bbox );
void renderBoxHandle( F32 x, F32 y, F32 z );
- void renderAxisHandle( const LLVector3& start, const LLVector3& end );
+ void renderAxisHandle( U32 part, const LLVector3& start, const LLVector3& end );
void renderGuidelinesPart( const LLBBox& local_bbox );
void renderSnapGuides( const LLBBox& local_bbox );
@@ -142,7 +142,6 @@ private:
};
- F32 mBoxHandleSize; //!< The size of the handles at the corners of the bounding box.
F32 mScaledBoxHandleSize; //!< Handle size after scaling for selection feedback.
LLVector3d mDragStartPointGlobal;
LLVector3d mDragStartCenterGlobal; //!< The center of the bounding box of all selected objects at time of drag start.
@@ -171,7 +170,8 @@ private:
LLVector3 mScaleDir; //!< The direction of the scaling action. In face-dragging this is aligned with one of the cardinal axis relative to the prim, but in corner-dragging this is along the diagonal.
F32 mScaleSnappedValue; //!< The distance of the current position nearest the mouse location, measured along mScaleDir. Is measured either from the center or from the far face/corner depending upon whether uniform scaling is true or false respectively.
ESnapRegimes mSnapRegime; //<! Which, if any, snap regime the cursor is currently residing in.
- F32* mManipulatorScales;
+ F32 mManipulatorScales[NUM_MANIPULATORS];
+ F32 mBoxHandleSize[NUM_MANIPULATORS]; // The size of the handles at the corners of the bounding box
};
#endif // LL_MANIPSCALE_H
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index ff0d25d203..8a89131c43 100755
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -1246,7 +1246,7 @@ void LLManipTranslate::renderSnapGuides()
// find distance to nearest smallest grid unit
F32 offset_nearest_grid_unit = fmodf(dist_grid_axis, smallest_grid_unit_scale);
// how many smallest grid units are we away from largest grid scale?
- S32 sub_div_offset = llround(fmod(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale);
+ S32 sub_div_offset = llround(fmodf(dist_grid_axis - offset_nearest_grid_unit, getMinGridScale() / sGridMinSubdivisionLevel) / smallest_grid_unit_scale);
S32 num_ticks_per_side = llmax(1, llfloor(0.5f * guide_size_meters / smallest_grid_unit_scale));
LLGLDepthTest gls_depth(GL_FALSE);
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index 91866e5ca2..54e4c6c1da 100755
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -64,7 +64,8 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)
mNameColumnIndex(p.name_column.column_index),
mNameColumn(p.name_column.column_name),
mAllowCallingCardDrop(p.allow_calling_card_drop),
- mShortNames(p.short_names)
+ mShortNames(p.short_names),
+ mPendingLookupsRemaining(0)
{}
// public
@@ -337,6 +338,17 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
mAvatarNameCacheConnections.erase(it);
}
mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, item->getHandle()));
+
+ if(mPendingLookupsRemaining <= 0)
+ {
+ // BAKER TODO:
+ // We might get into a state where mPendingLookupsRemaining might
+ // go negative. So just reset it right now and figure out if it's
+ // possible later :)
+ mPendingLookupsRemaining = 0;
+ mNameListCompleteSignal(false);
+ }
+ mPendingLookupsRemaining++;
}
break;
}
@@ -388,6 +400,8 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)
{
selectNthItem(idx); // not sure whether this is needed, taken from previous implementation
deleteSingleItem(idx);
+
+ mPendingLookupsRemaining--;
}
}
@@ -429,6 +443,23 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,
}
}
+ //////////////////////////////////////////////////////////////////////////
+ // BAKER - FIX NameListCtrl
+ //if (mPendingLookupsRemaining <= 0)
+ {
+ // We might get into a state where mPendingLookupsRemaining might
+ // go negative. So just reset it right now and figure out if it's
+ // possible later :)
+ //mPendingLookupsRemaining = 0;
+
+ mNameListCompleteSignal(true);
+ }
+ //else
+ {
+ // mPendingLookupsRemaining--;
+ }
+ //////////////////////////////////////////////////////////////////////////
+
dirtyColumns();
}
diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h
index 4ed260d847..2c40eeaaca 100755
--- a/indra/newview/llnamelistctrl.h
+++ b/indra/newview/llnamelistctrl.h
@@ -67,6 +67,7 @@ class LLNameListCtrl
: public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl>
{
public:
+ typedef boost::signals2::signal<void(bool)> namelist_complete_signal_t;
typedef enum e_name_type
{
@@ -156,7 +157,7 @@ public:
/*virtual*/ void updateColumns(bool force_update);
- /*virtual*/ void mouseOverHighlightNthItem( S32 index );
+ /*virtual*/ void mouseOverHighlightNthItem( S32 index );
private:
void showInspector(const LLUUID& avatar_id, bool is_group);
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item);
@@ -168,6 +169,16 @@ private:
bool mShortNames; // display name only, no SLID
typedef std::map<LLUUID, boost::signals2::connection> avatar_name_cache_connection_map_t;
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
+
+ S32 mPendingLookupsRemaining;
+ namelist_complete_signal_t mNameListCompleteSignal;
+
+public:
+ boost::signals2::connection setOnNameListCompleteCallback(boost::function<void(bool)> onNameListCompleteCallback)
+ {
+ return mNameListCompleteSignal.connect(onNameListCompleteCallback);
+ }
+
};
diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp
new file mode 100644
index 0000000000..1eafc5bd64
--- /dev/null
+++ b/indra/newview/llpanelgroupbulk.cpp
@@ -0,0 +1,421 @@
+/**
+* @file llpanelgroupbulk.cpp
+* @brief Implementation of llpanelgroupbulk
+* @author Baker@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelgroupbulk.h"
+#include "llpanelgroupbulkimpl.h"
+
+#include "llagent.h"
+#include "llavatarnamecache.h"
+#include "llfloateravatarpicker.h"
+#include "llbutton.h"
+#include "llcallingcard.h"
+#include "llcombobox.h"
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+// Implementation of llpanelgroupbulkimpl.h functions
+//////////////////////////////////////////////////////////////////////////
+LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
+ mGroupID(group_id),
+ mBulkAgentList(NULL),
+ mOKButton(NULL),
+ mRemoveButton(NULL),
+ mGroupName(NULL),
+ mLoadingText(),
+ mTooManySelected(),
+ mCloseCallback(NULL),
+ mCloseCallbackUserData(NULL),
+ mAvatarNameCacheConnection(),
+ mRoleNames(NULL),
+ mOwnerWarning(),
+ mAlreadyInGroup(),
+ mConfirmedOwnerInvite(false),
+ mListFullNotificationSent(false)
+{}
+
+LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl()
+{
+ if(mAvatarNameCacheConnection.connected())
+ {
+ mAvatarNameCacheConnection.disconnect();
+ }
+}
+
+void LLPanelGroupBulkImpl::callbackClickAdd(void* userdata)
+{
+ LLPanelGroupBulk* panelp = (LLPanelGroupBulk*)userdata;
+
+ if(panelp)
+ {
+ //Right now this is hard coded with some knowledge that it is part
+ //of a floater since the avatar picker needs to be added as a dependent
+ //floater to the parent floater.
+ //Soon the avatar picker will be embedded into this panel
+ //instead of being it's own separate floater. But that is next week.
+ //This will do for now. -jwolk May 10, 2006
+ LLView* button = panelp->findChild<LLButton>("add_button");
+ LLFloater* root_floater = gFloaterView->getParentFloater(panelp);
+ LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(
+ boost::bind(callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button);
+ if(picker)
+ {
+ root_floater->addDependentFloater(picker);
+ }
+ }
+}
+
+void LLPanelGroupBulkImpl::callbackClickRemove(void* userdata)
+{
+ LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata;
+ if (selfp)
+ selfp->handleRemove();
+}
+
+void LLPanelGroupBulkImpl::callbackClickCancel(void* userdata)
+{
+ LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata;
+ if(selfp)
+ (*(selfp->mCloseCallback))(selfp->mCloseCallbackUserData);
+}
+
+void LLPanelGroupBulkImpl::callbackSelect(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata;
+ if (selfp)
+ selfp->handleSelection();
+}
+
+void LLPanelGroupBulkImpl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data)
+{
+ std::vector<std::string> names;
+ for (S32 i = 0; i < (S32)agent_ids.size(); i++)
+ {
+ LLAvatarName av_name;
+ if (LLAvatarNameCache::get(agent_ids[i], &av_name))
+ {
+ onAvatarNameCache(agent_ids[i], av_name, user_data);
+ }
+ else
+ {
+ LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*) user_data;
+ if (selfp)
+ {
+ if (selfp->mAvatarNameCacheConnection.connected())
+ {
+ selfp->mAvatarNameCacheConnection.disconnect();
+ }
+ // *TODO : Add a callback per avatar name being fetched.
+ selfp->mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_ids[i],boost::bind(onAvatarNameCache, _1, _2, user_data));
+ }
+ }
+ }
+}
+
+void LLPanelGroupBulkImpl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, void* user_data)
+{
+ LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*) user_data;
+
+ if (selfp)
+ {
+ if (selfp->mAvatarNameCacheConnection.connected())
+ {
+ selfp->mAvatarNameCacheConnection.disconnect();
+ }
+ std::vector<std::string> names;
+ uuid_vec_t agent_ids;
+ agent_ids.push_back(agent_id);
+ names.push_back(av_name.getCompleteName());
+
+ selfp->addUsers(names, agent_ids);
+ }
+}
+
+void LLPanelGroupBulkImpl::handleRemove()
+{
+ std::vector<LLScrollListItem*> selection = mBulkAgentList->getAllSelected();
+ if (selection.empty())
+ return;
+
+ std::vector<LLScrollListItem*>::iterator iter;
+ for(iter = selection.begin(); iter != selection.end(); ++iter)
+ {
+ mInviteeIDs.erase((*iter)->getUUID());
+ }
+
+ mBulkAgentList->deleteSelectedItems();
+ mRemoveButton->setEnabled(FALSE);
+
+ if( mOKButton && mOKButton->getEnabled() &&
+ mBulkAgentList->isEmpty())
+ {
+ mOKButton->setEnabled(FALSE);
+ }
+}
+
+void LLPanelGroupBulkImpl::handleSelection()
+{
+ std::vector<LLScrollListItem*> selection = mBulkAgentList->getAllSelected();
+ if (selection.empty())
+ mRemoveButton->setEnabled(FALSE);
+ else
+ mRemoveButton->setEnabled(TRUE);
+}
+
+void LLPanelGroupBulkImpl::addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids)
+{
+ std::string name;
+ LLUUID id;
+
+ if(mListFullNotificationSent)
+ {
+ return;
+ }
+
+ if( !mListFullNotificationSent &&
+ (names.size() + mInviteeIDs.size() > MAX_GROUP_INVITES))
+ {
+ mListFullNotificationSent = true;
+
+ // Fail! Show a warning and don't add any names.
+ LLSD msg;
+ msg["MESSAGE"] = mTooManySelected;
+ LLNotificationsUtil::add("GenericAlert", msg);
+ return;
+ }
+
+ for (S32 i = 0; i < (S32)names.size(); ++i)
+ {
+ name = names[i];
+ id = agent_ids[i];
+
+ if(mInviteeIDs.find(id) != mInviteeIDs.end())
+ {
+ continue;
+ }
+
+ //add the name to the names list
+ LLSD row;
+ row["id"] = id;
+ row["columns"][0]["value"] = name;
+
+ mBulkAgentList->addElement(row);
+ mInviteeIDs.insert(id);
+
+ // We've successfully added someone to the list.
+ if(mOKButton && !mOKButton->getEnabled())
+ mOKButton->setEnabled(TRUE);
+ }
+}
+
+void LLPanelGroupBulkImpl::setGroupName(std::string name)
+{
+ if(mGroupName)
+ mGroupName->setText(name);
+}
+
+
+LLPanelGroupBulk::LLPanelGroupBulk(const LLUUID& group_id) :
+ LLPanel(),
+ mImplementation(new LLPanelGroupBulkImpl(group_id)),
+ mPendingGroupPropertiesUpdate(false),
+ mPendingRoleDataUpdate(false),
+ mPendingMemberDataUpdate(false)
+{}
+
+LLPanelGroupBulk::~LLPanelGroupBulk()
+{
+ delete mImplementation;
+}
+
+void LLPanelGroupBulk::clear()
+{
+ mImplementation->mInviteeIDs.clear();
+
+ if(mImplementation->mBulkAgentList)
+ mImplementation->mBulkAgentList->deleteAllItems();
+
+ if(mImplementation->mOKButton)
+ mImplementation->mOKButton->setEnabled(FALSE);
+}
+
+void LLPanelGroupBulk::update()
+{
+ updateGroupName();
+ updateGroupData();
+}
+
+void LLPanelGroupBulk::draw()
+{
+ LLPanel::draw();
+ update();
+}
+
+void LLPanelGroupBulk::updateGroupName()
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
+
+ if( gdatap &&
+ gdatap->isGroupPropertiesDataComplete())
+ {
+ // Only do work if the current group name differs
+ if(mImplementation->mGroupName->getText().compare(gdatap->mName) != 0)
+ mImplementation->setGroupName(gdatap->mName);
+ }
+ else
+ {
+ mImplementation->setGroupName(mImplementation->mLoadingText);
+ }
+}
+
+void LLPanelGroupBulk::updateGroupData()
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
+ if(gdatap && gdatap->isGroupPropertiesDataComplete())
+ {
+ mPendingGroupPropertiesUpdate = false;
+ }
+ else
+ {
+ if(!mPendingGroupPropertiesUpdate)
+ {
+ mPendingGroupPropertiesUpdate = true;
+ LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
+ }
+ }
+
+ if(gdatap && gdatap->isRoleDataComplete())
+ {
+ mPendingRoleDataUpdate = false;
+ }
+ else
+ {
+ if(!mPendingRoleDataUpdate)
+ {
+ mPendingRoleDataUpdate = true;
+ LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
+ }
+ }
+
+ if(gdatap && gdatap->isMemberDataComplete())
+ {
+ mPendingMemberDataUpdate = false;
+ }
+ else
+ {
+ if(!mPendingMemberDataUpdate)
+ {
+ mPendingMemberDataUpdate = true;
+ LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
+ }
+ }
+}
+
+void LLPanelGroupBulk::addUserCallback(const LLUUID& id, const LLAvatarName& av_name)
+{
+ std::vector<std::string> names;
+ uuid_vec_t agent_ids;
+ agent_ids.push_back(id);
+ names.push_back(av_name.getAccountName());
+
+ mImplementation->addUsers(names, agent_ids);
+}
+
+void LLPanelGroupBulk::setCloseCallback(void (*close_callback)(void*), void* data)
+{
+ mImplementation->mCloseCallback = close_callback;
+ mImplementation->mCloseCallbackUserData = data;
+}
+
+void LLPanelGroupBulk::addUsers(uuid_vec_t& agent_ids)
+{
+ std::vector<std::string> names;
+ for (S32 i = 0; i < (S32)agent_ids.size(); i++)
+ {
+ std::string fullname;
+ LLUUID agent_id = agent_ids[i];
+ LLViewerObject* dest = gObjectList.findObject(agent_id);
+ if(dest && dest->isAvatar())
+ {
+ LLNameValue* nvfirst = dest->getNVPair("FirstName");
+ LLNameValue* nvlast = dest->getNVPair("LastName");
+ if(nvfirst && nvlast)
+ {
+ fullname = LLCacheName::buildFullName(
+ nvfirst->getString(), nvlast->getString());
+
+ }
+ if (!fullname.empty())
+ {
+ names.push_back(fullname);
+ }
+ else
+ {
+ llwarns << "llPanelGroupBulk: Selected avatar has no name: " << dest->getID() << llendl;
+ names.push_back("(Unknown)");
+ }
+ }
+ else
+ {
+ //looks like user try to invite offline friend
+ //for offline avatar_id gObjectList.findObject() will return null
+ //so we need to do this additional search in avatar tracker, see EXT-4732
+ if (LLAvatarTracker::instance().isBuddy(agent_id))
+ {
+ LLAvatarName av_name;
+ if (!LLAvatarNameCache::get(agent_id, &av_name))
+ {
+ // actually it should happen, just in case
+ LLAvatarNameCache::get(LLUUID(agent_id), boost::bind(&LLPanelGroupBulk::addUserCallback, this, _1, _2));
+ // for this special case!
+ //when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence
+ // removed id will be added in callback
+ agent_ids.erase(agent_ids.begin() + i);
+ }
+ else
+ {
+ names.push_back(av_name.getAccountName());
+ }
+ }
+ }
+ }
+ mImplementation->mListFullNotificationSent = false;
+ mImplementation->addUsers(names, agent_ids);
+}
+
diff --git a/indra/newview/llpanelgroupbulk.h b/indra/newview/llpanelgroupbulk.h
new file mode 100644
index 0000000000..25ae71ab86
--- /dev/null
+++ b/indra/newview/llpanelgroupbulk.h
@@ -0,0 +1,74 @@
+/**
+* @file llpanelgroupbulk.h
+* @brief Header file for llpanelgroupbulk
+* @author Baker@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLPANELGROUPBULK_H
+#define LL_LLPANELGROUPBULK_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+
+class LLAvatarName;
+class LLGroupMgrGroupData;
+class LLPanelGroupBulkImpl;
+
+// Base panel class for bulk group invite / ban floaters
+class LLPanelGroupBulk : public LLPanel
+{
+public:
+ LLPanelGroupBulk(const LLUUID& group_id);
+ /*virtual*/ ~LLPanelGroupBulk();
+
+public:
+ static void callbackClickSubmit(void* userdata) {}
+ virtual void submit() = 0;
+
+public:
+ virtual void clear();
+ virtual void update();
+ virtual void draw();
+
+protected:
+ virtual void updateGroupName();
+ virtual void updateGroupData();
+
+public:
+ // this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers().
+ virtual void addUserCallback(const LLUUID& id, const LLAvatarName& av_name);
+ virtual void setCloseCallback(void (*close_callback)(void*), void* data);
+
+ virtual void addUsers(uuid_vec_t& agent_ids);
+
+public:
+ LLPanelGroupBulkImpl* mImplementation;
+
+protected:
+ bool mPendingGroupPropertiesUpdate;
+ bool mPendingRoleDataUpdate;
+ bool mPendingMemberDataUpdate;
+};
+
+#endif // LL_LLPANELGROUPBULK_H
+
diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp
new file mode 100644
index 0000000000..cf1f0bc32f
--- /dev/null
+++ b/indra/newview/llpanelgroupbulkban.cpp
@@ -0,0 +1,259 @@
+/**
+* @file llpanelgroupbulkban.cpp
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelgroupbulkban.h"
+#include "llpanelgroupbulk.h"
+#include "llpanelgroupbulkimpl.h"
+
+#include "llagent.h"
+#include "llavatarnamecache.h"
+#include "llavataractions.h"
+#include "llfloateravatarpicker.h"
+#include "llbutton.h"
+#include "llcallingcard.h"
+#include "llcombobox.h"
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llnamelistctrl.h"
+#include "llnotificationsutil.h"
+#include "llscrolllistitem.h"
+#include "llslurl.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "lluictrlfactory.h"
+#include "llviewerwindow.h"
+
+#include <boost/foreach.hpp>
+
+LLPanelGroupBulkBan::LLPanelGroupBulkBan(const LLUUID& group_id) : LLPanelGroupBulk(group_id)
+{
+ // Pass on construction of this panel to the control factory.
+ buildFromFile( "panel_group_bulk_ban.xml");
+}
+
+BOOL LLPanelGroupBulkBan::postBuild()
+{
+ BOOL recurse = TRUE;
+
+ mImplementation->mLoadingText = getString("loading");
+ mImplementation->mGroupName = getChild<LLTextBox>("group_name_text", recurse);
+ mImplementation->mBulkAgentList = getChild<LLNameListCtrl>("banned_agent_list", recurse);
+ if ( mImplementation->mBulkAgentList )
+ {
+ mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE);
+ mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation);
+ }
+
+ LLButton* button = getChild<LLButton>("add_button", recurse);
+ if ( button )
+ {
+ // default to opening avatarpicker automatically
+ // (*impl::callbackClickAdd)((void*)this);
+ button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this);
+ }
+
+ mImplementation->mRemoveButton =
+ getChild<LLButton>("remove_button", recurse);
+ if ( mImplementation->mRemoveButton )
+ {
+ mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation);
+ mImplementation->mRemoveButton->setEnabled(FALSE);
+ }
+
+ mImplementation->mOKButton =
+ getChild<LLButton>("ban_button", recurse);
+ if ( mImplementation->mOKButton )
+ {
+ mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this);
+ mImplementation->mOKButton->setEnabled(FALSE);
+ }
+
+ button = getChild<LLButton>("cancel_button", recurse);
+ if ( button )
+ {
+ button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation);
+ }
+
+ mImplementation->mTooManySelected = getString("ban_selection_too_large");
+ mImplementation->mBanNotPermitted = getString("ban_not_permitted");
+ mImplementation->mBanLimitFail = getString("ban_limit_fail");
+ mImplementation->mCannotBanYourself = getString("cant_ban_yourself");
+
+ update();
+ return TRUE;
+}
+
+// TODO: Refactor the shitty callback functions with void* -- just use boost::bind to call submit() instead.
+void LLPanelGroupBulkBan::callbackClickSubmit(void* userdata)
+{
+ LLPanelGroupBulkBan* selfp = (LLPanelGroupBulkBan*)userdata;
+
+ if(selfp)
+ selfp->submit();
+}
+
+
+void LLPanelGroupBulkBan::submit()
+{
+ if (!gAgent.hasPowerInGroup(mImplementation->mGroupID, GP_GROUP_BAN_ACCESS))
+ {
+ // Fail! Agent no longer have ban rights. Permissions could have changed after button was pressed.
+ LLSD msg;
+ msg["MESSAGE"] = mImplementation->mBanNotPermitted;
+ LLNotificationsUtil::add("GenericAlert", msg);
+ (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+ return;
+ }
+ LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);
+ if (group_datap && group_datap->mBanList.size() >= GB_MAX_BANNED_AGENTS)
+ {
+ // Fail! Size limit exceeded. List could have updated after button was pressed.
+ LLSD msg;
+ msg["MESSAGE"] = mImplementation->mBanLimitFail;
+ LLNotificationsUtil::add("GenericAlert", msg);
+ (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+ return;
+ }
+ std::vector<LLUUID> banned_agent_list;
+ std::vector<LLScrollListItem*> agents = mImplementation->mBulkAgentList->getAllData();
+ std::vector<LLScrollListItem*>::iterator iter = agents.begin();
+ for(;iter != agents.end(); ++iter)
+ {
+ LLScrollListItem* agent = *iter;
+ banned_agent_list.push_back(agent->getUUID());
+ }
+
+ const S32 MAX_BANS_PER_REQUEST = 100; // Max bans per request. 100 to match server cap.
+ if (banned_agent_list.size() > MAX_BANS_PER_REQUEST)
+ {
+ // Fail!
+ LLSD msg;
+ msg["MESSAGE"] = mImplementation->mTooManySelected;
+ LLNotificationsUtil::add("GenericAlert", msg);
+ (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+ return;
+ }
+
+ // remove already banned users and yourself from request.
+ std::vector<LLAvatarName> banned_avatar_names;
+ std::vector<LLAvatarName> out_of_limit_names;
+ bool banning_self = FALSE;
+ std::vector<LLUUID>::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID());
+ if (conflict != banned_agent_list.end())
+ {
+ banned_agent_list.erase(conflict);
+ banning_self = TRUE;
+ }
+ if (group_datap)
+ {
+ BOOST_FOREACH(const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair, group_datap->mBanList)
+ {
+ const LLUUID& group_ban_agent_id = group_ban_pair.first;
+ std::vector<LLUUID>::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id);
+ if (conflict != banned_agent_list.end())
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(group_ban_agent_id, &av_name);
+ banned_avatar_names.push_back(av_name);
+
+ banned_agent_list.erase(conflict);
+ if (banned_agent_list.size() == 0)
+ {
+ break;
+ }
+ }
+ }
+ // this check should always be the last one before we send the request.
+ // Otherwise we have a possibility of cutting more then we need to.
+ if (banned_agent_list.size() > GB_MAX_BANNED_AGENTS - group_datap->mBanList.size())
+ {
+ std::vector<LLUUID>::iterator exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size();
+ for (std::vector<LLUUID>::iterator itor = exeedes_limit ;
+ itor != banned_agent_list.end(); ++itor)
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(*itor, &av_name);
+ out_of_limit_names.push_back(av_name);
+ }
+ banned_agent_list.erase(exeedes_limit,banned_agent_list.end());
+ }
+ }
+
+ // sending request and ejecting members
+ if (banned_agent_list.size() != 0)
+ {
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list);
+ LLGroupMgr::getInstance()->sendGroupMemberEjects(mImplementation->mGroupID, banned_agent_list);
+ }
+
+ // building notification
+ if (banned_avatar_names.size() > 0 || banning_self || out_of_limit_names.size() > 0)
+ {
+ std::string reasons;
+ if(banned_avatar_names.size() > 0)
+ {
+ reasons = "\n " + buildResidentsArgument(banned_avatar_names, "residents_already_banned");
+ }
+
+ if(banning_self)
+ {
+ reasons += "\n " + mImplementation->mCannotBanYourself;
+ }
+
+ if(out_of_limit_names.size() > 0)
+ {
+ reasons += "\n " + buildResidentsArgument(out_of_limit_names, "ban_limit_reached");
+ }
+
+ LLStringUtil::format_map_t msg_args;
+ msg_args["[REASONS]"] = reasons;
+ LLSD msg;
+ if (banned_agent_list.size() == 0)
+ {
+ msg["MESSAGE"] = getString("ban_failed", msg_args);
+ }
+ else
+ {
+ msg["MESSAGE"] = getString("partial_ban", msg_args);
+ }
+ LLNotificationsUtil::add("GenericAlert", msg);
+ }
+
+ //then close
+ (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);
+}
+
+std::string LLPanelGroupBulkBan::buildResidentsArgument(std::vector<LLAvatarName> avatar_names, const std::string &format)
+{
+ std::string names_string;
+ LLAvatarActions::buildResidentsString(avatar_names, names_string);
+ LLStringUtil::format_map_t args;
+ args["[RESIDENTS]"] = names_string;
+ return getString(format, args);
+}
diff --git a/indra/newview/llpanelgroupbulkban.h b/indra/newview/llpanelgroupbulkban.h
new file mode 100644
index 0000000000..9060d275f9
--- /dev/null
+++ b/indra/newview/llpanelgroupbulkban.h
@@ -0,0 +1,49 @@
+/**
+* @file llpanelgroupbulkban.h
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLPANELGROUPBULKBAN_H
+#define LL_LLPANELGROUPBULKBAN_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+#include "llpanelgroupbulk.h"
+
+class LLAvatarName;
+
+class LLPanelGroupBulkBan : public LLPanelGroupBulk
+{
+public:
+ LLPanelGroupBulkBan(const LLUUID& group_id);
+ ~LLPanelGroupBulkBan() {}
+
+ virtual BOOL postBuild();
+
+ static void callbackClickSubmit(void* userdata);
+ virtual void submit();
+private:
+ std::string buildResidentsArgument(std::vector<LLAvatarName> avatar_names, const std::string &format);
+};
+
+#endif // LL_LLPANELGROUPBULKBAN_H
diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h
new file mode 100644
index 0000000000..d3a48e5a9a
--- /dev/null
+++ b/indra/newview/llpanelgroupbulkimpl.h
@@ -0,0 +1,99 @@
+/**
+* @file llpanelgroupbulkimpl.h
+* @brief Class definition for implementation class of LLPanelGroupBulk
+* @author Baker@lindenlab.com
+*
+* $LicenseInfo:firstyear=2013&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2013, Linden Research, Inc.
+*
+* 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
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+* $/LicenseInfo$
+*/
+#ifndef LL_LLPANELGROUPBULKIMPL_H
+#define LL_LLPANELGROUPBULKIMPL_H
+
+#include "llpanel.h"
+#include "lluuid.h"
+
+class LLAvatarName;
+class LLNameListCtrl;
+class LLTextBox;
+class LLComboBox;
+
+//////////////////////////////////////////////////////////////////////////
+// Implementation found in llpanelgroupbulk.cpp
+//////////////////////////////////////////////////////////////////////////
+class LLPanelGroupBulkImpl
+{
+public:
+ LLPanelGroupBulkImpl(const LLUUID& group_id);
+ ~LLPanelGroupBulkImpl();
+
+ static void callbackClickAdd(void* userdata);
+ static void callbackClickRemove(void* userdata);
+
+ static void callbackClickCancel(void* userdata);
+
+ static void callbackSelect(LLUICtrl* ctrl, void* userdata);
+ static void callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data);
+
+ static void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, void* user_data);
+
+ void handleRemove();
+ void handleSelection();
+
+ void addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids);
+ void setGroupName(std::string name);
+
+
+public:
+ static const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap.
+
+
+ LLUUID mGroupID;
+
+ LLNameListCtrl* mBulkAgentList;
+ LLButton* mOKButton;
+ LLButton* mRemoveButton;
+ LLTextBox* mGroupName;
+
+ std::string mLoadingText;
+ std::string mTooManySelected;
+ std::string mBanNotPermitted;
+ std::string mBanLimitFail;
+ std::string mCannotBanYourself;
+
+ std::set<LLUUID> mInviteeIDs;
+
+ void (*mCloseCallback)(void* data);
+ void* mCloseCallbackUserData;
+ boost::signals2::connection mAvatarNameCacheConnection;
+
+ // The following are for the LLPanelGroupInvite subclass only.
+ // These aren't needed for LLPanelGroupBulkBan, but if we have to add another
+ // group bulk floater for some reason, we'll have these objects too.
+public:
+ LLComboBox* mRoleNames;
+ std::string mOwnerWarning;
+ std::string mAlreadyInGroup;
+ bool mConfirmedOwnerInvite;
+ bool mListFullNotificationSent;
+};
+
+#endif // LL_LLPANELGROUPBULKIMPL_H
+
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index dd13e8abf4..236ad861a5 100755
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -260,7 +260,7 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)
//else if they have the limited add to roles power
//we add every role the user is in
//else we just add to everyone
- bool is_owner = member_data->isInRole(gdatap->mOwnerRole);
+ bool is_owner = member_data->isOwner();
bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
GP_ROLE_ASSIGN_MEMBER);
bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
@@ -492,7 +492,7 @@ void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids)
}
else
{
- LL_WARNS() << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << LL_ENDL;
+ llwarns << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << llendl;
names.push_back("(Unknown)");
}
}
@@ -579,7 +579,7 @@ void LLPanelGroupInvite::updateLists()
{
waiting = true;
}
- if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete())
+ if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete())
{
if ( mImplementation->mRoleNames )
{
@@ -607,6 +607,7 @@ void LLPanelGroupInvite::updateLists()
{
LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID);
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID);
+ LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID);
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID);
}
mPendingUpdate = TRUE;
@@ -654,7 +655,7 @@ BOOL LLPanelGroupInvite::postBuild()
}
mImplementation->mOKButton =
- getChild<LLButton>("ok_button", recurse);
+ getChild<LLButton>("invite_button", recurse);
if ( mImplementation->mOKButton )
{
mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation);
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index 106f6c25f1..375c54479d 100755
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -421,27 +421,14 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
msg->getUUID("QueryData", "OwnerID", owner_id, 0);
msg->getUUID("TransactionData", "TransactionID", trans_id);
+ S32 total_contribution = 0;
if(owner_id.isNull())
{
// special block which has total contribution
++first_block;
-
- S32 total_contribution;
+
msg->getS32("QueryData", "ActualArea", total_contribution, 0);
mPanel.getChild<LLUICtrl>("total_contributed_land_value")->setTextArg("[AREA]", llformat("%d", total_contribution));
-
- S32 committed;
- msg->getS32("QueryData", "BillableArea", committed, 0);
- mPanel.getChild<LLUICtrl>("total_land_in_use_value")->setTextArg("[AREA]", llformat("%d", committed));
-
- S32 available = total_contribution - committed;
- mPanel.getChild<LLUICtrl>("land_available_value")->setTextArg("[AREA]", llformat("%d", available));
-
- if ( mGroupOverLimitTextp && mGroupOverLimitIconp )
- {
- mGroupOverLimitIconp->setVisible(available < 0);
- mGroupOverLimitTextp->setVisible(available < 0);
- }
}
if ( trans_id != mTransID ) return;
@@ -460,7 +447,8 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
std::string sim_name;
std::string land_sku;
std::string land_type;
-
+ S32 committed = 0;
+
for(S32 i = first_block; i < count; ++i)
{
msg->getUUID("QueryData", "OwnerID", owner_id, i);
@@ -489,6 +477,9 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
S32 region_y = llround(global_y) % REGION_WIDTH_UNITS;
std::string location = sim_name + llformat(" (%d, %d)", region_x, region_y);
std::string area;
+ committed+=billable_area;
+
+
if(billable_area == actual_area)
{
area = llformat("%d", billable_area);
@@ -525,6 +516,16 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg)
mGroupParcelsp->addElement(row);
}
+
+ mPanel.getChild<LLUICtrl>("total_land_in_use_value")->setTextArg("[AREA]", llformat("%d", committed));
+
+ S32 available = total_contribution - committed;
+ mPanel.getChild<LLUICtrl>("land_available_value")->setTextArg("[AREA]", llformat("%d", available));
+ if ( mGroupOverLimitTextp && mGroupOverLimitIconp )
+ {
+ mGroupOverLimitIconp->setVisible(available < 0);
+ mGroupOverLimitTextp->setVisible(available < 0);
+ }
}
}
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 3bf325f9ab..1d7ba4d741 100755
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llpanelgrouproles.cpp
* @brief Panel for roles information about a particular group.
*
@@ -32,6 +32,7 @@
#include "llavatarnamecache.h"
#include "llbutton.h"
#include "llfiltereditor.h"
+#include "llfloatergroupbulkban.h"
#include "llfloatergroupinvite.h"
#include "llavataractions.h"
#include "lliconctrl.h"
@@ -109,8 +110,10 @@ bool agentCanAddToRole(const LLUUID& group_id,
return false;
}
-// static
+// LLPanelGroupRoles /////////////////////////////////////////////////////
+
+// static
LLPanelGroupRoles::LLPanelGroupRoles()
: LLPanelGroupTab(),
mCurrentTab(NULL),
@@ -297,7 +300,6 @@ bool LLPanelGroupRoles::onModalClose(const LLSD& notification, const LLSD& respo
return false;
}
-
bool LLPanelGroupRoles::apply(std::string& mesg)
{
// Pass this along to the currently visible sub tab.
@@ -334,7 +336,6 @@ void LLPanelGroupRoles::update(LLGroupChange gc)
{
if (mGroupID.isNull()) return;
-
LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
if (panelp)
{
@@ -351,39 +352,33 @@ void LLPanelGroupRoles::activate()
{
// Start requesting member and role data if needed.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
- //if (!gdatap || mFirstUse)
+ if (!gdatap || !gdatap->isMemberDataComplete() )
{
- // Check member data.
-
- if (!gdatap || !gdatap->isMemberDataComplete() )
- {
- LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
- }
-
- // Check role data.
- if (!gdatap || !gdatap->isRoleDataComplete() )
- {
- // Mildly hackish - clear all pending changes
- cancel();
+ LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
+ }
- LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
- }
+ if (!gdatap || !gdatap->isRoleDataComplete() )
+ {
+ // Mildly hackish - clear all pending changes
+ cancel();
- // Check role-member mapping data.
- if (!gdatap || !gdatap->isRoleMemberDataComplete() )
- {
- LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
- }
+ LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
+ }
- // Need this to get base group member powers
- if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
- {
- LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
- }
+ // Check role-member mapping data.
+ if (!gdatap || !gdatap->isRoleMemberDataComplete() )
+ {
+ LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+ }
- mFirstUse = FALSE;
+ // Need this to get base group member powers
+ if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
+ {
+ LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);
}
+ mFirstUse = FALSE;
+
LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();
if (panelp) panelp->activate();
}
@@ -412,15 +407,38 @@ BOOL LLPanelGroupRoles::hasModal()
return panelp->hasModal();
}
+void LLPanelGroupRoles::setGroupID(const LLUUID& id)
+{
+ LLPanelGroupTab::setGroupID(id);
+
+ LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab");
+ LLPanelGroupRolesSubTab* group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab");
+ LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab");
+ LLPanelGroupBanListSubTab* group_ban_tab = findChild<LLPanelGroupBanListSubTab>("banlist_sub_tab");
+
+ if(group_members_tab) group_members_tab->setGroupID(id);
+ if(group_roles_tab) group_roles_tab->setGroupID(id);
+ if(group_actions_tab) group_actions_tab->setGroupID(id);
+ if(group_ban_tab) group_ban_tab->setGroupID(id);
+
+ LLButton* button = getChild<LLButton>("member_invite");
+ if ( button )
+ button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
+
+ if(mSubTabContainer)
+ mSubTabContainer->selectTab(1);
+ group_roles_tab->mFirstOpen = TRUE;
+ activate();
+}
+
-////////////////////////////
-// LLPanelGroupSubTab
-////////////////////////////
+// LLPanelGroupSubTab ////////////////////////////////////////////////////
LLPanelGroupSubTab::LLPanelGroupSubTab()
: LLPanelGroupTab(),
mHeader(NULL),
mFooter(NULL),
mActivated(false),
+ mHasGroupBanPower(false),
mSearchEditor(NULL)
{
}
@@ -542,9 +560,10 @@ void LLPanelGroupSubTab::buildActionsList(LLScrollListCtrl* ctrl,
return;
}
+ mHasGroupBanPower = false;
+
std::vector<LLRoleActionSet*>::iterator ras_it = LLGroupMgr::getInstance()->mRoleActionSets.begin();
std::vector<LLRoleActionSet*>::iterator ras_end = LLGroupMgr::getInstance()->mRoleActionSets.end();
-
for ( ; ras_it != ras_end; ++ras_it)
{
buildActionCategory(ctrl,
@@ -674,6 +693,31 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
row["columns"][column_index]["value"] = (*ra_it)->mDescription;
row["columns"][column_index]["font"] = "SANSSERIF_SMALL";
+ if(mHasGroupBanPower)
+ {
+ // The ban ability is being set. Prevent these abilities from being manipulated
+ if((*ra_it)->mPowerBit == GP_MEMBER_EJECT)
+ {
+ row["enabled"] = false;
+ }
+ else if((*ra_it)->mPowerBit == GP_ROLE_REMOVE_MEMBER)
+ {
+ row["enabled"] = false;
+ }
+ }
+ else
+ {
+ // The ban ability is not set. Allow these abilities to be manipulated
+ if((*ra_it)->mPowerBit == GP_MEMBER_EJECT)
+ {
+ row["enabled"] = true;
+ }
+ else if((*ra_it)->mPowerBit == GP_ROLE_REMOVE_MEMBER)
+ {
+ row["enabled"] = true;
+ }
+ }
+
LLScrollListItem* item = ctrl->addElement(row, ADD_BOTTOM, (*ra_it));
if (-1 != check_box_index)
@@ -709,6 +753,15 @@ void LLPanelGroupSubTab::buildActionCategory(LLScrollListCtrl* ctrl,
check->setTentative(TRUE);
}
}
+
+ // Regardless of whether or not this ability is allowed by all or some, we want to prevent
+ // the group managers from accidentally disabling either of the two additional abilities
+ // tied with GP_GROUP_BAN_ACCESS.
+ if( (allowed_by_all & GP_GROUP_BAN_ACCESS) == GP_GROUP_BAN_ACCESS ||
+ (allowed_by_some & GP_GROUP_BAN_ACCESS) == GP_GROUP_BAN_ACCESS)
+ {
+ mHasGroupBanPower = true;
+ }
}
}
@@ -728,11 +781,8 @@ void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)
}
}
-////////////////////////////
-// LLPanelGroupMembersSubTab
-////////////////////////////
-
+// LLPanelGroupMembersSubTab /////////////////////////////////////////////
static LLPanelInjector<LLPanelGroupMembersSubTab> t_panel_group_members_subtab("panel_group_members_subtab");
LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()
@@ -813,6 +863,13 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
mEjectBtn->setEnabled(FALSE);
}
+ mBanBtn = parent->getChild<LLButton>("member_ban", recurse);
+ if(mBanBtn)
+ {
+ mBanBtn->setClickedCallback(onBanMember, this);
+ mBanBtn->setEnabled(FALSE);
+ }
+
return TRUE;
}
@@ -826,34 +883,6 @@ void LLPanelGroupMembersSubTab::setGroupID(const LLUUID& id)
LLPanelGroupSubTab::setGroupID(id);
}
-void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id)
-{
- if(mRolesList) mRolesList->deleteAllItems();
- if(mAssignedMembersList) mAssignedMembersList->deleteAllItems();
- if(mAllowedActionsList) mAllowedActionsList->deleteAllItems();
-
- if(mRoleName) mRoleName->clear();
- if(mRoleDescription) mRoleDescription->clear();
- if(mRoleTitle) mRoleTitle->clear();
-
- mHasRoleChange = FALSE;
-
- setFooterEnabled(FALSE);
-
- LLPanelGroupSubTab::setGroupID(id);
-}
-void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id)
-{
- if(mActionList) mActionList->deleteAllItems();
- if(mActionRoles) mActionRoles->deleteAllItems();
- if(mActionMembers) mActionMembers->deleteAllItems();
-
- if(mActionDescription) mActionDescription->clear();
-
- LLPanelGroupSubTab::setGroupID(id);
-}
-
-
// static
void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)
{
@@ -919,8 +948,8 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
LLGroupMgrGroupData::role_list_t::iterator iter = gdatap->mRoles.begin();
LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
- BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID,
- GP_MEMBER_EJECT);
+ BOOL can_ban_members = gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS);
+ BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_EJECT);
BOOL member_is_owner = FALSE;
for( ; iter != end; ++iter)
@@ -967,6 +996,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
{
// Can't remove other owners.
cb_enable = FALSE;
+ can_ban_members = FALSE;
break;
}
}
@@ -986,14 +1016,14 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
}
// If anyone selected is in any role besides 'Everyone' then they can't be ejected.
- if (role_id.notNull() && (count > 0))
- {
+ if (role_id.notNull() && (count > 0))
+ {
can_eject_members = FALSE;
- if (role_id == gdatap->mOwnerRole)
- {
- member_is_owner = TRUE;
- }
- }
+ if (role_id == gdatap->mOwnerRole)
+ {
+ member_is_owner = TRUE;
+ }
+ }
LLRoleData rd;
if (gdatap->getRoleData(role_id,rd))
@@ -1050,7 +1080,10 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
mAssignedRolesList->setEnabled(TRUE);
if (gAgent.isGodlike())
+ {
can_eject_members = TRUE;
+ // can_ban_members = TRUE;
+ }
if (!can_eject_members && !member_is_owner)
{
@@ -1063,10 +1096,41 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
{
can_eject_members = TRUE;
+ //can_ban_members = TRUE;
}
}
+
+ }
+
+ // ... or we can eject them because we have all the requisite powers...
+ if( gAgent.hasPowerInGroup(mGroupID, GP_ROLE_REMOVE_MEMBER) &&
+ !member_is_owner)
+ {
+ if( gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_EJECT))
+ {
+ can_eject_members = TRUE;
+ }
+
+ if( gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS))
+ {
+ can_ban_members = TRUE;
+ }
}
+
+ uuid_vec_t::const_iterator member_iter = selected_members.begin();
+ uuid_vec_t::const_iterator member_end = selected_members.end();
+ for ( ; member_iter != member_end; ++member_iter)
+ {
+ // Don't count the agent.
+ if ((*member_iter) == gAgent.getID())
+ {
+ can_eject_members = FALSE;
+ can_ban_members = FALSE;
+ }
+ }
+
+ mBanBtn->setEnabled(can_ban_members);
mEjectBtn->setEnabled(can_eject_members);
}
@@ -1104,61 +1168,26 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
}
void LLPanelGroupMembersSubTab::handleEjectMembers()
-{
+{
+ //send down an eject message
+ uuid_vec_t selected_members;
+
std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
if (selection.empty()) return;
-
- S32 selection_count = selection.size();
- if (selection_count == 1)
- {
- LLSD args;
- LLUUID selected_avatar = mMembersList->getValue().asUUID();
- std::string fullname = LLSLURL("agent", selected_avatar, "inspect").getSLURLString();
- args["AVATAR_NAME"] = fullname;
- LLSD payload;
- LLNotificationsUtil::add("EjectGroupMemberWarning",
- args,
- payload,
- boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
- }
- else
- {
- LLSD args;
- args["COUNT"] = llformat("%d", selection_count);
- LLSD payload;
- LLNotificationsUtil::add("EjectGroupMembersWarning",
- args,
- payload,
- boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
- }
-}
-bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- if (0 == option) // Eject button
+ std::vector<LLScrollListItem*>::iterator itor;
+ for (itor = selection.begin() ;
+ itor != selection.end(); ++itor)
{
- //send down an eject message
- uuid_vec_t selected_members;
-
- std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
- if (selection.empty()) return false;
-
- std::vector<LLScrollListItem*>::iterator itor;
- for (itor = selection.begin() ;
- itor != selection.end(); ++itor)
- {
- LLUUID member_id = (*itor)->getUUID();
- selected_members.push_back( member_id );
- }
-
- mMembersList->deleteSelectedItems();
-
- sendEjectNotifications(mGroupID, selected_members);
-
- LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
+ LLUUID member_id = (*itor)->getUUID();
+ selected_members.push_back( member_id );
}
- return false;
+
+ mMembersList->deleteSelectedItems();
+
+ sendEjectNotifications(mGroupID, selected_members);
+
+ LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
}
void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)
@@ -1191,7 +1220,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
BOOL is_owner_role = ( gdatap->mOwnerRole == role_id );
LLUUID member_id;
-
std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
if (selection.empty())
@@ -1202,7 +1230,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ;
itor != selection.end(); ++itor)
{
-
member_id = (*itor)->getUUID();
//see if we requested a change for this member before
@@ -1268,7 +1295,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
FALSE);
}
-
// static
void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)
{
@@ -1307,6 +1333,15 @@ void LLPanelGroupMembersSubTab::activate()
update(GC_ALL);
mActivated = true;
}
+ else
+ {
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ // Members can be removed outside of this tab, checking changes
+ if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount()))
+ {
+ update(GC_MEMBER_DATA);
+ }
+ }
}
void LLPanelGroupMembersSubTab::deactivate()
@@ -1701,13 +1736,12 @@ void LLPanelGroupMembersSubTab::updateMembers()
return;
}
- //cleanup list only for first iretation
+ //cleanup list only for first iteration
if(mMemberProgress == gdatap->mMembers.begin())
{
mMembersList->deleteAllItems();
}
-
LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();
LLTimer update_time;
@@ -1764,12 +1798,44 @@ void LLPanelGroupMembersSubTab::updateMembers()
handleMemberSelect();
}
+void LLPanelGroupMembersSubTab::onBanMember(void* user_data)
+{
+ LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
+ self->handleBanMember();
+}
+void LLPanelGroupMembersSubTab::handleBanMember()
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if(!gdatap)
+ {
+ LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL;
+ return;
+ }
-////////////////////////////
-// LLPanelGroupRolesSubTab
-////////////////////////////
+ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
+ if(selection.empty())
+ {
+ return;
+ }
+ uuid_vec_t ban_ids;
+ std::vector<LLScrollListItem*>::iterator itor;
+ for(itor = selection.begin(); itor != selection.end(); ++itor)
+ {
+ LLUUID ban_id = (*itor)->getUUID();
+ ban_ids.push_back(ban_id);
+
+ LLGroupBanData ban_data;
+ gdatap->createBanEntry(ban_id, ban_data);
+ }
+
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_CREATE, ban_ids);
+ handleEjectMembers();
+}
+
+
+// LLPanelGroupRolesSubTab ///////////////////////////////////////////////
static LLPanelInjector<LLPanelGroupRolesSubTab> t_panel_group_roles_subtab("panel_group_roles_subtab");
LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
@@ -1783,7 +1849,7 @@ LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab()
mMemberVisibleCheck(NULL),
mDeleteRoleButton(NULL),
mCreateRoleButton(NULL),
-
+ mFirstOpen(TRUE),
mHasRoleChange(FALSE)
{
}
@@ -1885,6 +1951,7 @@ void LLPanelGroupRolesSubTab::deactivate()
LL_DEBUGS() << "LLPanelGroupRolesSubTab::deactivate()" << LL_ENDL;
LLPanelGroupSubTab::deactivate();
+ mFirstOpen = FALSE;
}
bool LLPanelGroupRolesSubTab::needsApply(std::string& mesg)
@@ -1892,6 +1959,12 @@ bool LLPanelGroupRolesSubTab::needsApply(std::string& mesg)
LL_DEBUGS() << "LLPanelGroupRolesSubTab::needsApply()" << LL_ENDL;
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if(!gdatap)
+ {
+ llwarns << "Unable to get group data for group " << mGroupID << llendl;
+ return false;
+ }
+
return (mHasRoleChange // Text changed in current role
|| (gdatap && gdatap->pendingRoleChanges())); // Pending role changes in the group
@@ -1902,7 +1975,7 @@ bool LLPanelGroupRolesSubTab::apply(std::string& mesg)
LL_DEBUGS() << "LLPanelGroupRolesSubTab::apply()" << LL_ENDL;
saveRoleChanges(true);
-
+ mFirstOpen = FALSE;
LLGroupMgr::getInstance()->sendGroupRoleChanges(mGroupID);
notifyObservers();
@@ -2039,14 +2112,17 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
}
}
- if (!gdatap || !gdatap->isMemberDataComplete())
+ if(!mFirstOpen)
{
- LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
- }
-
- if (!gdatap || !gdatap->isRoleMemberDataComplete())
- {
- LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+ if (!gdatap || !gdatap->isMemberDataComplete())
+ {
+ LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
+ }
+
+ if (!gdatap || !gdatap->isRoleMemberDataComplete())
+ {
+ LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
+ }
}
if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
@@ -2062,6 +2138,9 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)
{
LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data);
+ if (!self)
+ return;
+
self->handleRoleSelect();
}
@@ -2241,40 +2320,115 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
LLRoleAction* rap = (LLRoleAction*)action_item->getUserdata();
U64 power = rap->mPowerBit;
- if (check->get())
+ bool isEnablingAbility = check->get();
+ LLRoleData rd;
+ LLSD args;
+
+ if (isEnablingAbility &&
+ !force &&
+ ((GP_ROLE_ASSIGN_MEMBER == power) || (GP_ROLE_CHANGE_ACTIONS == power) ))
{
- if (!force && ( (GP_ROLE_ASSIGN_MEMBER == power)
- || (GP_ROLE_CHANGE_ACTIONS == power) ))
- {
- // Uncheck the item, for now. It will be
- // checked if they click 'Yes', below.
- check->set(FALSE);
+ // Uncheck the item, for now. It will be
+ // checked if they click 'Yes', below.
+ check->set(FALSE);
- LLRoleData rd;
- LLSD args;
+ LLRoleData rd;
+ LLSD args;
- if ( gdatap->getRoleData(role_id, rd) )
+ if ( gdatap->getRoleData(role_id, rd) )
+ {
+ args["ACTION_NAME"] = rap->mDescription;
+ args["ROLE_NAME"] = rd.mRoleName;
+ mHasModal = TRUE;
+ std::string warning = "AssignDangerousActionWarning";
+ if (GP_ROLE_CHANGE_ACTIONS == power)
{
- args["ACTION_NAME"] = rap->mDescription;
- args["ROLE_NAME"] = rd.mRoleName;
- mHasModal = TRUE;
- std::string warning = "AssignDangerousActionWarning";
- if (GP_ROLE_CHANGE_ACTIONS == power)
- {
- warning = "AssignDangerousAbilityWarning";
- }
- LLNotificationsUtil::add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
+ warning = "AssignDangerousAbilityWarning";
}
- else
- {
+ LLNotificationsUtil::add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
+ }
+ else
+ {
LL_WARNS() << "Unable to look up role information for role id: "
<< role_id << LL_ENDL;
+ }
+ }
+
+ if(GP_GROUP_BAN_ACCESS == power)
+ {
+ std::string warning = isEnablingAbility ? "AssignBanAbilityWarning" : "RemoveBanAbilityWarning";
+
+ //////////////////////////////////////////////////////////////////////////
+ // Get role data for both GP_ROLE_REMOVE_MEMBER and GP_MEMBER_EJECT
+ // Add description and role name to LLSD
+ // Pop up dialog saying "Yo, you also granted these other abilities when you did this!"
+ if ( gdatap->getRoleData(role_id, rd) )
+ {
+ args["ACTION_NAME"] = rap->mDescription;
+ args["ROLE_NAME"] = rd.mRoleName;
+ mHasModal = TRUE;
+
+ std::vector<LLScrollListItem*> all_data = mAllowedActionsList->getAllData();
+ std::vector<LLScrollListItem*>::iterator ad_it = all_data.begin();
+ std::vector<LLScrollListItem*>::iterator ad_end = all_data.end();
+ LLRoleAction* adp;
+ for( ; ad_it != ad_end; ++ad_it)
+ {
+ adp = (LLRoleAction*)(*ad_it)->getUserdata();
+ if(adp->mPowerBit == GP_MEMBER_EJECT)
+ {
+ args["ACTION_NAME_2"] = adp->mDescription;
+ }
+ else if(adp->mPowerBit == GP_ROLE_REMOVE_MEMBER)
+ {
+ args["ACTION_NAME_3"] = adp->mDescription;
+ }
}
+
+ LLNotificationsUtil::add(warning, args);
}
else
{
- gdatap->addRolePower(role_id,power);
+ llwarns << "Unable to look up role information for role id: "
+ << role_id << llendl;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+
+ LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.find(role_id);
+ U64 current_role_powers = GP_NO_POWERS;
+ if (rit != gdatap->mRoles.end())
+ {
+ current_role_powers = ((*rit).second->getRoleData().mRolePowers);
+ }
+
+ if(isEnablingAbility)
+ {
+ power |= (GP_ROLE_REMOVE_MEMBER | GP_MEMBER_EJECT);
+ current_role_powers |= power;
}
+ else
+ {
+ current_role_powers &= ~GP_GROUP_BAN_ACCESS;
+ }
+
+ mAllowedActionsList->deleteAllItems();
+ buildActionsList( mAllowedActionsList,
+ current_role_powers,
+ current_role_powers,
+ boost::bind(&LLPanelGroupRolesSubTab::handleActionCheck, this, _1, false),
+ TRUE,
+ FALSE,
+ FALSE);
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Adding non-specific ability to role
+ //////////////////////////////////////////////////////////////////////////
+ if(isEnablingAbility)
+ {
+ gdatap->addRolePower(role_id, power);
}
else
{
@@ -2283,6 +2437,7 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force)
mHasRoleChange = TRUE;
notifyObservers();
+
}
bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check)
@@ -2302,7 +2457,6 @@ bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD&
return false;
}
-
// static
void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)
{
@@ -2480,13 +2634,28 @@ void LLPanelGroupRolesSubTab::saveRoleChanges(bool select_saved_role)
mHasRoleChange = FALSE;
}
}
-////////////////////////////
-// LLPanelGroupActionsSubTab
-////////////////////////////
-static LLPanelInjector<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab");
+void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id)
+{
+ if(mRolesList) mRolesList->deleteAllItems();
+ if(mAssignedMembersList) mAssignedMembersList->deleteAllItems();
+ if(mAllowedActionsList) mAllowedActionsList->deleteAllItems();
+
+ if(mRoleName) mRoleName->clear();
+ if(mRoleDescription) mRoleDescription->clear();
+ if(mRoleTitle) mRoleTitle->clear();
+
+ mHasRoleChange = FALSE;
+
+ setFooterEnabled(FALSE);
+
+ LLPanelGroupSubTab::setGroupID(id);
+}
+// LLPanelGroupActionsSubTab /////////////////////////////////////////////
+static LLPanelInjector<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab");
+
LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab()
: LLPanelGroupSubTab()
{
@@ -2659,26 +2828,298 @@ void LLPanelGroupActionsSubTab::handleActionSelect()
}
}
-void LLPanelGroupRoles::setGroupID(const LLUUID& id)
+void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id)
{
- LLPanelGroupTab::setGroupID(id);
+ if(mActionList) mActionList->deleteAllItems();
+ if(mActionRoles) mActionRoles->deleteAllItems();
+ if(mActionMembers) mActionMembers->deleteAllItems();
+
+ if(mActionDescription) mActionDescription->clear();
+
+ LLPanelGroupSubTab::setGroupID(id);
+}
+
+
+// LLPanelGroupBanListSubTab /////////////////////////////////////////////
+static LLPanelInjector<LLPanelGroupBanListSubTab> t_panel_group_ban_subtab("panel_group_banlist_subtab");
+
+LLPanelGroupBanListSubTab::LLPanelGroupBanListSubTab()
+ : LLPanelGroupSubTab(),
+ mBanList(NULL),
+ mCreateBanButton(NULL),
+ mDeleteBanButton(NULL)
+{}
+
+BOOL LLPanelGroupBanListSubTab::postBuildSubTab(LLView* root)
+{
+ LLPanelGroupSubTab::postBuildSubTab(root);
+
+ // Upcast parent so we can ask it for sibling controls.
+ LLPanelGroupRoles* parent = (LLPanelGroupRoles*)root;
+
+ // Look recursively from the parent to find all our widgets.
+ bool recurse = true;
- LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab");
- LLPanelGroupRolesSubTab* group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab");
- LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab");
+ mHeader = parent->getChild<LLPanel>("banlist_header", recurse);
+ mFooter = parent->getChild<LLPanel>("banlist_footer", recurse);
+
+ mBanList = parent->getChild<LLNameListCtrl>("ban_list", recurse);
+
+ mCreateBanButton = parent->getChild<LLButton>("ban_create", recurse);
+ mDeleteBanButton = parent->getChild<LLButton>("ban_delete", recurse);
+ mRefreshBanListButton = parent->getChild<LLButton>("ban_refresh", recurse);
+ mBanCountText = parent->getChild<LLTextBase>("ban_count", recurse);
- if(group_members_tab) group_members_tab->setGroupID(id);
- if(group_roles_tab) group_roles_tab->setGroupID(id);
- if(group_actions_tab) group_actions_tab->setGroupID(id);
+ if(!mBanList || !mCreateBanButton || !mDeleteBanButton || !mRefreshBanListButton || !mBanCountText)
+ return FALSE;
- LLButton* button = getChild<LLButton>("member_invite");
- if ( button )
- button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE));
+ mBanList->setCommitOnSelectionChange(TRUE);
+ mBanList->setCommitCallback(onBanEntrySelect, this);
- if(mSubTabContainer)
- mSubTabContainer->selectTab(1);
+ mCreateBanButton->setClickedCallback(onCreateBanEntry, this);
+ mCreateBanButton->setEnabled(FALSE);
- activate();
+ mDeleteBanButton->setClickedCallback(onDeleteBanEntry, this);
+ mDeleteBanButton->setEnabled(FALSE);
+
+ mRefreshBanListButton->setClickedCallback(onRefreshBanList, this);
+ mRefreshBanListButton->setEnabled(FALSE);
+
+ setBanCount(0);
+
+ mBanList->setOnNameListCompleteCallback(boost::bind(&LLPanelGroupBanListSubTab::onBanListCompleted, this, _1));
+
+ populateBanList();
+
+ setFooterEnabled(FALSE);
+ return TRUE;
}
+void LLPanelGroupBanListSubTab::activate()
+{
+ LLPanelGroupSubTab::activate();
+
+ mBanList->deselectAllItems();
+ mDeleteBanButton->setEnabled(FALSE);
+ LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if (group_datap)
+ {
+ mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) &&
+ group_datap->mBanList.size() < GB_MAX_BANNED_AGENTS);
+ setBanCount(group_datap->mBanList.size());
+ }
+ else
+ {
+ mCreateBanButton->setEnabled(FALSE);
+ setBanCount(0);
+ }
+
+ // BAKER: Should I really request everytime activate() is called?
+ // Perhaps I should only do it on a force refresh, or if an action on the list happens...
+ // Because it's not going to live-update the list anyway... You'd have to refresh if you
+ // wanted to see someone else's additions anyway...
+ //
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
+
+ setFooterEnabled(FALSE);
+ update(GC_ALL);
+}
+
+void LLPanelGroupBanListSubTab::update(LLGroupChange gc)
+{
+ populateBanList();
+}
+
+void LLPanelGroupBanListSubTab::draw()
+{
+ LLPanelGroupSubTab::draw();
+
+ // BAKER: Might be good to put it here instead of update, maybe.. See how often draw gets hit.
+ //if(
+ // populateBanList();
+}
+
+void LLPanelGroupBanListSubTab::onBanEntrySelect(LLUICtrl* ctrl, void* user_data)
+{
+ LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+ if (!self)
+ return;
+
+ self->handleBanEntrySelect();
+}
+
+void LLPanelGroupBanListSubTab::handleBanEntrySelect()
+{
+ if (gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS))
+ {
+ mDeleteBanButton->setEnabled(TRUE);
+ }
+}
+
+void LLPanelGroupBanListSubTab::onCreateBanEntry(void* user_data)
+{
+ LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+ if (!self)
+ return;
+
+ self->handleCreateBanEntry();
+}
+
+void LLPanelGroupBanListSubTab::handleCreateBanEntry()
+{
+ LLFloaterGroupBulkBan::showForGroup(mGroupID);
+ //populateBanList();
+}
+
+void LLPanelGroupBanListSubTab::onDeleteBanEntry(void* user_data)
+{
+ LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+ if (!self)
+ return;
+
+ self->handleDeleteBanEntry();
+}
+
+void LLPanelGroupBanListSubTab::handleDeleteBanEntry()
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if(!gdatap)
+ {
+ LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL;
+ return;
+ }
+
+ std::vector<LLScrollListItem*> selection = mBanList->getAllSelected();
+ if(selection.empty())
+ {
+ return;
+ }
+
+ bool can_ban_members = false;
+ if (gAgent.isGodlike() ||
+ gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS))
+ {
+ can_ban_members = true;
+ }
+
+ // Owners can ban anyone in the group.
+ LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID());
+ if (mi != gdatap->mMembers.end())
+ {
+ LLGroupMemberData* member_data = (*mi).second;
+ if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
+ {
+ can_ban_members = true;
+ }
+ }
+
+ if(!can_ban_members)
+ return;
+
+ std::vector<LLUUID> ban_ids;
+ std::vector<LLScrollListItem*>::iterator itor;
+ for(itor = selection.begin(); itor != selection.end(); ++itor)
+ {
+ LLUUID ban_id = (*itor)->getUUID();
+ ban_ids.push_back(ban_id);
+
+ gdatap->removeBanEntry(ban_id);
+ mBanList->removeNameItem(ban_id);
+
+ // Removing an item removes the selection, we shouldn't be able to click
+ // the button anymore until we reselect another entry.
+ mDeleteBanButton->setEnabled(FALSE);
+ }
+
+ // update ban-count related elements
+ mCreateBanButton->setEnabled(TRUE);
+ setBanCount(gdatap->mBanList.size());
+
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_DELETE, ban_ids);
+}
+
+void LLPanelGroupBanListSubTab::onRefreshBanList(void* user_data)
+{
+ LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data);
+ if (!self)
+ return;
+
+ self->handleRefreshBanList();
+}
+
+void LLPanelGroupBanListSubTab::handleRefreshBanList()
+{
+ mRefreshBanListButton->setEnabled(FALSE);
+ LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID);
+}
+
+void LLPanelGroupBanListSubTab::onBanListCompleted(bool isComplete)
+{
+ if(isComplete)
+ {
+ mRefreshBanListButton->setEnabled(TRUE);
+ populateBanList();
+ }
+}
+
+void LLPanelGroupBanListSubTab::setBanCount(U32 ban_count)
+{
+ LLStringUtil::format_map_t args;
+ args["[COUNT]"] = llformat("%d", ban_count);
+ args["[LIMIT]"] = llformat("%d", GB_MAX_BANNED_AGENTS);
+ mBanCountText->setText(getString("ban_count_template", args));
+}
+
+void LLPanelGroupBanListSubTab::populateBanList()
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
+ if(!gdatap)
+ {
+ LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL;
+ return;
+ }
+
+ mBanList->deleteAllItems();
+ std::map<LLUUID,LLGroupBanData>::const_iterator entry = gdatap->mBanList.begin();
+ for(; entry != gdatap->mBanList.end(); entry++)
+ {
+ LLNameListCtrl::NameItem ban_entry;
+ ban_entry.value = entry->first;
+ LLGroupBanData bd = entry->second;
+
+ ban_entry.columns.add().column("name").font.name("SANSSERIF_SMALL").style("NORMAL");
+
+ // Baker TODO: MAINT-
+ // Check out utc_to_pacific_time()
+
+ std::string ban_date_str = bd.mBanDate.toHTTPDateString("%Y/%m/%d");
+// time_t utc_time;
+// utc_time = time_corrected();
+// LLSD substitution;
+// substitution["datetime"] = (S32) utc_time;
+// LLStringUtil::format (ban_date_str, substitution);
+
+ //LL_INFOS("BAKER") << "[BAKER] BAN_DATE: " << bd.mBanDate.toHTTPDateString("%Y/%m/%d") << LL_ENDL;
+ //LL_INFOS("BAKER") << "[BAKER] BAN_DATE_MODIFIED: " << ban_date_str << LL_ENDL;
+
+ //ban_entry.columns.add().column("ban_date").value(ban_date_str.font.name("SANSSERIF_SMALL").style("NORMAL");
+ ban_entry.columns.add().column("ban_date").value(bd.mBanDate.toHTTPDateString("%Y/%m/%d")).font.name("SANSSERIF_SMALL").style("NORMAL");
+
+ mBanList->addNameItemRow(ban_entry);
+ }
+
+ mRefreshBanListButton->setEnabled(TRUE);
+ mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) &&
+ gdatap->mBanList.size() < GB_MAX_BANNED_AGENTS);
+ setBanCount(gdatap->mBanList.size());
+}
+
+void LLPanelGroupBanListSubTab::setGroupID(const LLUUID& id)
+{
+ if(mBanList)
+ mBanList->deleteAllItems();
+
+ setFooterEnabled(FALSE);
+ LLPanelGroupSubTab::setGroupID(id);
+}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index baa2d40c7e..540b24ada6 100755
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -39,11 +39,9 @@ class LLScrollListCtrl;
class LLScrollListItem;
class LLTextEditor;
-// Forward declare for friend usage.
-//virtual BOOL LLPanelGroupSubTab::postBuildSubTab(LLView*);
-
typedef std::map<std::string,std::string> icon_map_t;
+
class LLPanelGroupRoles : public LLPanelGroupTab
{
public:
@@ -92,6 +90,7 @@ protected:
std::string mWantApplyMesg;
};
+
class LLPanelGroupSubTab : public LLPanelGroupTab
{
public:
@@ -143,10 +142,14 @@ protected:
icon_map_t mActionIcons;
bool mActivated;
-
+
+ bool mHasGroupBanPower; // Used to communicate between action sets due to the dependency between
+ // GP_GROUP_BAN_ACCESS and GP_EJECT_MEMBER and GP_ROLE_REMOVE_MEMBER
+
void setOthersVisible(BOOL b);
};
+
class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab
{
public:
@@ -173,6 +176,10 @@ public:
void handleRoleCheck(const LLUUID& role_id,
LLRoleMemberChangeType type);
+ static void onBanMember(void* user_data);
+ void handleBanMember();
+
+
void applyMemberChanges();
bool addOwnerCB(const LLSD& notification, const LLSD& response);
@@ -206,6 +213,7 @@ protected:
LLScrollListCtrl* mAssignedRolesList;
LLScrollListCtrl* mAllowedActionsList;
LLButton* mEjectBtn;
+ LLButton* mBanBtn;
BOOL mChanged;
BOOL mPendingMemberUpdate;
@@ -219,6 +227,7 @@ protected:
avatar_name_cache_connection_map_t mAvatarNameCacheConnections;
};
+
class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab
{
public:
@@ -241,7 +250,7 @@ public:
static void onActionCheck(LLUICtrl*, void*);
bool addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check);
-
+
static void onPropertiesKey(LLLineEditor*, void*);
void onDescriptionKeyStroke(LLTextEditor* caller);
@@ -260,6 +269,9 @@ public:
void saveRoleChanges(bool select_saved_role);
virtual void setGroupID(const LLUUID& id);
+
+ BOOL mFirstOpen;
+
protected:
void handleActionCheck(LLUICtrl* ctrl, bool force);
LLSD createRoleItem(const LLUUID& role_id, std::string name, std::string title, S32 members);
@@ -281,6 +293,7 @@ protected:
std::string mRemoveEveryoneTxt;
};
+
class LLPanelGroupActionsSubTab : public LLPanelGroupSubTab
{
public:
@@ -308,4 +321,46 @@ protected:
};
+class LLPanelGroupBanListSubTab : public LLPanelGroupSubTab
+{
+public:
+ LLPanelGroupBanListSubTab();
+ virtual ~LLPanelGroupBanListSubTab() {}
+
+ virtual BOOL postBuildSubTab(LLView* root);
+
+ virtual void activate();
+ virtual void update(LLGroupChange gc);
+ virtual void draw();
+
+ static void onBanEntrySelect(LLUICtrl* ctrl, void* user_data);
+ void handleBanEntrySelect();
+
+ static void onCreateBanEntry(void* user_data);
+ void handleCreateBanEntry();
+
+ static void onDeleteBanEntry(void* user_data);
+ void handleDeleteBanEntry();
+
+ static void onRefreshBanList(void* user_data);
+ void handleRefreshBanList();
+
+ void onBanListCompleted(bool isComplete);
+
+protected:
+ void setBanCount(U32 ban_count);
+ void populateBanList();
+
+public:
+ virtual void setGroupID(const LLUUID& id);
+
+protected:
+ LLNameListCtrl* mBanList;
+ LLButton* mCreateBanButton;
+ LLButton* mDeleteBanButton;
+ LLButton* mRefreshBanListButton;
+ LLTextBase* mBanCountText;
+
+};
+
#endif // LL_LLPANELGROUPROLES_H
diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp
index 9b21fbf6b7..acdb16f432 100755
--- a/indra/newview/llpanelland.cpp
+++ b/indra/newview/llpanelland.cpp
@@ -145,7 +145,7 @@ void LLPanelLandInfo::refresh()
&& ((gAgent.getID() == auth_buyer_id)
|| (auth_buyer_id.isNull())));
- if (is_public)
+ if (is_public && !LLViewerParcelMgr::getInstance()->getParcelSelection()->getMultipleOwners())
{
getChildView("button buy land")->setEnabled(TRUE);
}
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 67cbc91332..75a3584a1e 100755
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -1263,6 +1263,7 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg
break;
}
+ updateVerbs();
return true;
}
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
index e501486ecb..ed91d277dd 100755
--- a/indra/newview/llpanelplaceprofile.cpp
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -129,6 +129,7 @@ BOOL LLPanelPlaceProfile::postBuild()
mEstateNameText = getChild<LLTextBox>("estate_name");
mEstateRatingText = getChild<LLTextBox>("estate_rating");
+ mEstateRatingIcon = getChild<LLIconCtrl>("estate_rating_icon");
mEstateOwnerText = getChild<LLTextBox>("estate_owner");
mCovenantText = getChild<LLTextEditor>("covenant");
@@ -201,6 +202,7 @@ void LLPanelPlaceProfile::resetLocation()
mEstateNameText->setValue(loading);
mEstateRatingText->setValue(loading);
+ mEstateRatingIcon->setValue(loading);
mEstateOwnerText->setValue(loading);
mCovenantText->setValue(loading);
@@ -348,6 +350,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
mParcelRatingIcon->setValue(icon_m);
mRegionRatingIcon->setValue(icon_m);
+ mEstateRatingIcon->setValue(icon_m);
break;
case SIM_ACCESS_ADULT:
@@ -355,6 +358,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
mParcelRatingIcon->setValue(icon_r);
mRegionRatingIcon->setValue(icon_r);
+ mEstateRatingIcon->setValue(icon_r);
break;
default:
@@ -362,6 +366,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
mParcelRatingIcon->setValue(icon_pg);
mRegionRatingIcon->setValue(icon_pg);
+ mEstateRatingIcon->setValue(icon_pg);
}
std::string rating = LLViewerRegion::accessToString(sim_access);
@@ -483,8 +488,9 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
gCacheName->getGroup(parcel->getGroupID(),
boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2));
- gCacheName->getGroup(parcel->getGroupID(),
- boost::bind(&LLPanelPlaceInfo::onNameCache, mParcelOwner, _2));
+ std::string owner =
+ LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString();
+ mParcelOwner->setText(owner);
}
else
{
diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h
index 01adfd4940..4547e14b2e 100755
--- a/indra/newview/llpanelplaceprofile.h
+++ b/indra/newview/llpanelplaceprofile.h
@@ -103,6 +103,7 @@ private:
LLTextBox* mEstateNameText;
LLTextBox* mEstateRatingText;
+ LLIconCtrl* mEstateRatingIcon;
LLTextBox* mEstateOwnerText;
LLTextEditor* mCovenantText;
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 652d2be6f6..3de9dc2f80 100755
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -45,6 +45,7 @@
#include "llviewermenu.h"
#include "lllandmarkactions.h"
#include "llclipboard.h"
+#include "lltrans.h"
// Maximum number of items that can be added to a list in one pass.
// Used to limit time spent for items list update per frame.
@@ -55,7 +56,8 @@ static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
class LLTeleportHistoryFlatItem : public LLPanel
{
public:
- LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl);
+ LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name,
+ LLDate date, const std::string &hl);
virtual ~LLTeleportHistoryFlatItem();
virtual BOOL postBuild();
@@ -66,8 +68,11 @@ public:
void setIndex(S32 index) { mIndex = index; }
const std::string& getRegionName() { return mRegionName;}
void setRegionName(const std::string& name);
+ void setDate(LLDate date);
void setHighlightedText(const std::string& text);
void updateTitle();
+ void updateTimestamp();
+ std::string getTimestamp();
/*virtual*/ void setValue(const LLSD& value);
@@ -84,12 +89,14 @@ private:
LLButton* mProfileBtn;
LLTextBox* mTitle;
+ LLTextBox* mTimeTextBox;
LLTeleportHistoryPanel::ContextMenu *mContextMenu;
S32 mIndex;
std::string mRegionName;
std::string mHighlight;
+ LLDate mDate;
LLRootHandle<LLTeleportHistoryFlatItem> mItemHandle;
};
@@ -121,11 +128,13 @@ private:
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name, const std::string &hl)
+LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name,
+ LLDate date, const std::string &hl)
: LLPanel(),
mIndex(index),
mContextMenu(context_menu),
mRegionName(region_name),
+ mDate(date),
mHighlight(hl)
{
buildFromFile( "panel_teleport_history_item.xml");
@@ -140,11 +149,14 @@ BOOL LLTeleportHistoryFlatItem::postBuild()
{
mTitle = getChild<LLTextBox>("region");
+ mTimeTextBox = getChild<LLTextBox>("timestamp");
+
mProfileBtn = getChild<LLButton>("profile_btn");
mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
updateTitle();
+ updateTimestamp();
return true;
}
@@ -179,6 +191,38 @@ void LLTeleportHistoryFlatItem::setRegionName(const std::string& name)
mRegionName = name;
}
+void LLTeleportHistoryFlatItem::setDate(LLDate date)
+{
+ mDate = date;
+}
+
+std::string LLTeleportHistoryFlatItem::getTimestamp()
+{
+ const LLDate &date = mDate;
+ std::string timestamp = "";
+
+ LLDate now = LLDate::now();
+ S32 now_year, now_month, now_day, now_hour, now_min, now_sec;
+ now.split(&now_year, &now_month, &now_day, &now_hour, &now_min, &now_sec);
+
+ const S32 seconds_in_day = 24 * 60 * 60;
+ S32 seconds_today = now_hour * 60 * 60 + now_min * 60 + now_sec;
+ S32 time_diff = (S32) now.secondsSinceEpoch() - (S32) date.secondsSinceEpoch();
+
+ // Only show timestamp for today and yesterday
+ if(time_diff < seconds_today + seconds_in_day)
+ {
+ timestamp = "[" + LLTrans::getString("TimeHour12")+"]:["
+ + LLTrans::getString("TimeMin")+"] ["+ LLTrans::getString("TimeAMPM")+"]";
+ LLSD substitution;
+ substitution["datetime"] = (S32) date.secondsSinceEpoch();
+ LLStringUtil::format(timestamp, substitution);
+ }
+
+ return timestamp;
+
+}
+
void LLTeleportHistoryFlatItem::updateTitle()
{
static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
@@ -190,6 +234,17 @@ void LLTeleportHistoryFlatItem::updateTitle()
mHighlight);
}
+void LLTeleportHistoryFlatItem::updateTimestamp()
+{
+ static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
+
+ LLTextUtil::textboxSetHighlightedVal(
+ mTimeTextBox,
+ LLStyle::Params().color(sFgColor),
+ getTimestamp(),
+ mHighlight);
+}
+
void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
getChildView("hovered_icon")->setVisible( true);
@@ -248,9 +303,11 @@ LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
{
item->setIndex(cur_item_index);
item->setRegionName(persistent_item.mTitle);
+ item->setDate(persistent_item.mDate);
item->setHighlightedText(hl);
item->setVisible(TRUE);
item->updateTitle();
+ item->updateTimestamp();
}
else
{
@@ -264,6 +321,7 @@ LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
item = new LLTeleportHistoryFlatItem(cur_item_index,
context_menu,
persistent_item.mTitle,
+ persistent_item.mDate,
hl);
mItems.push_back(item->getItemHandle());
}
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index 6d032ad3d3..398f4e6e42 100755
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -90,6 +90,7 @@ void LLPreview::setObjectID(const LLUUID& object_id)
{
loadAsset();
}
+ refreshFromItem();
}
void LLPreview::setItem( LLInventoryItem* item )
@@ -99,6 +100,7 @@ void LLPreview::setItem( LLInventoryItem* item )
{
loadAsset();
}
+ refreshFromItem();
}
const LLInventoryItem *LLPreview::getItem() const
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 6830998a8a..ffaffbe538 100755
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -93,15 +93,15 @@
const std::string HELLO_LSL =
"default\n"
"{\n"
- " state_entry()\n"
- " {\n"
- " llSay(0, \"Hello, Avatar!\");\n"
- " }\n"
+ " state_entry()\n"
+ " {\n"
+ " llSay(0, \"Hello, Avatar!\");\n"
+ " }\n"
"\n"
- " touch_start(integer total_number)\n"
- " {\n"
- " llSay(0, \"Touched.\");\n"
- " }\n"
+ " touch_start(integer total_number)\n"
+ " {\n"
+ " llSay(0, \"Touched.\");\n"
+ " }\n"
"}\n";
const std::string HELP_LSL_PORTAL_TOPIC = "LSL_Portal";
@@ -125,20 +125,20 @@ static bool have_script_upload_cap(LLUUID& object_id)
class ExperienceResponder : public LLHTTPClient::Responder
{
public:
- ExperienceResponder(const LLHandle<LLLiveLSLEditor>& parent):mParent(parent)
- {
- }
+ ExperienceResponder(const LLHandle<LLLiveLSLEditor>& parent):mParent(parent)
+ {
+ }
- LLHandle<LLLiveLSLEditor> mParent;
+ LLHandle<LLLiveLSLEditor> mParent;
- /*virtual*/ void httpSuccess()
- {
- LLLiveLSLEditor* parent = mParent.get();
- if(!parent)
- return;
+ /*virtual*/ void httpSuccess()
+ {
+ LLLiveLSLEditor* parent = mParent.get();
+ if(!parent)
+ return;
- parent->setExperienceIds(getContent()["experience_ids"]);
- }
+ parent->setExperienceIds(getContent()["experience_ids"]);
+ }
};
/// ---------------------------------------------------------------------------
@@ -219,7 +219,7 @@ private:
protected:
LLLineEditor* mSearchBox;
LLLineEditor* mReplaceBox;
- void onSearchBoxCommit();
+ void onSearchBoxCommit();
};
LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL;
@@ -430,51 +430,51 @@ LLScriptEdCore::~LLScriptEdCore()
void LLLiveLSLEditor::experienceChanged()
{
- if(mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID())
- {
- mScriptEd->enableSave(getIsModifiable());
- //getChildView("Save_btn")->setEnabled(TRUE);
- mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID());
- updateExperiencePanel();
- }
+ if(mScriptEd->getAssociatedExperience() != mExperiences->getSelectedValue().asUUID())
+ {
+ mScriptEd->enableSave(getIsModifiable());
+ //getChildView("Save_btn")->setEnabled(TRUE);
+ mScriptEd->setAssociatedExperience(mExperiences->getSelectedValue().asUUID());
+ updateExperiencePanel();
+ }
}
void LLLiveLSLEditor::onViewProfile( LLUICtrl *ui, void* userdata )
{
- LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
+ LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
- LLUUID id;
- if(self->mExperienceEnabled->get())
- {
- id=self->mScriptEd->getAssociatedExperience();
- if(id.notNull())
- {
- LLFloaterReg::showInstance("experience_profile", id, true);
- }
- }
+ LLUUID id;
+ if(self->mExperienceEnabled->get())
+ {
+ id=self->mScriptEd->getAssociatedExperience();
+ if(id.notNull())
+ {
+ LLFloaterReg::showInstance("experience_profile", id, true);
+ }
+ }
}
void LLLiveLSLEditor::onToggleExperience( LLUICtrl *ui, void* userdata )
{
- LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
+ LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
- LLUUID id;
- if(self->mExperienceEnabled->get())
- {
- if(self->mScriptEd->getAssociatedExperience().isNull())
- {
- id=self->mExperienceIds.beginArray()->asUUID();
- }
- }
+ LLUUID id;
+ if(self->mExperienceEnabled->get())
+ {
+ if(self->mScriptEd->getAssociatedExperience().isNull())
+ {
+ id=self->mExperienceIds.beginArray()->asUUID();
+ }
+ }
- if(id != self->mScriptEd->getAssociatedExperience())
- {
- self->mScriptEd->enableSave(self->getIsModifiable());
- }
- self->mScriptEd->setAssociatedExperience(id);
+ if(id != self->mScriptEd->getAssociatedExperience())
+ {
+ self->mScriptEd->enableSave(self->getIsModifiable());
+ }
+ self->mScriptEd->setAssociatedExperience(id);
- self->updateExperiencePanel();
+ self->updateExperiencePanel();
}
BOOL LLScriptEdCore::postBuild()
@@ -883,7 +883,7 @@ bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLS
case 2: // "Cancel"
default:
// If we were quitting, we didn't really mean it.
- LLAppViewer::instance()->abortQuit();
+ LLAppViewer::instance()->abortQuit();
break;
}
return false;
@@ -918,8 +918,8 @@ void LLScriptEdCore::onBtnDynamicHelp()
LLKeywordToken *token;
LLKeywords::keyword_iterator_t token_it;
for (token_it = mEditor->keywordsBegin();
- token_it != mEditor->keywordsEnd();
- ++token_it)
+ token_it != mEditor->keywordsEnd();
+ ++token_it)
{
token = token_it->second;
help_combo->add(wstring_to_utf8str(token->getToken()));
@@ -1273,55 +1273,55 @@ bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata)
LLUUID LLScriptEdCore::getAssociatedExperience()const
{
- return mAssociatedExperience;
+ return mAssociatedExperience;
}
void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids )
{
- mExperienceIds=experience_ids;
- updateExperiencePanel();
+ mExperienceIds=experience_ids;
+ updateExperiencePanel();
}
void LLLiveLSLEditor::updateExperiencePanel()
{
- if(mScriptEd->getAssociatedExperience().isNull())
- {
- mExperienceEnabled->set(FALSE);
- mExperiences->setVisible(FALSE);
- if(mExperienceIds.size()>0)
- {
- mExperienceEnabled->setEnabled(TRUE);
- mExperienceEnabled->setToolTip(getString("add_experiences"));
- }
- else
- {
- mExperienceEnabled->setEnabled(FALSE);
- mExperienceEnabled->setToolTip(getString("no_experiences"));
- }
- getChild<LLButton>("view_profile")->setVisible(FALSE);
- }
- else
+ if(mScriptEd->getAssociatedExperience().isNull())
+ {
+ mExperienceEnabled->set(FALSE);
+ mExperiences->setVisible(FALSE);
+ if(mExperienceIds.size()>0)
+ {
+ mExperienceEnabled->setEnabled(TRUE);
+ mExperienceEnabled->setToolTip(getString("add_experiences"));
+ }
+ else
+ {
+ mExperienceEnabled->setEnabled(FALSE);
+ mExperienceEnabled->setToolTip(getString("no_experiences"));
+ }
+ getChild<LLButton>("view_profile")->setVisible(FALSE);
+ }
+ else
{
mExperienceEnabled->setToolTip(getString("experience_enabled"));
mExperienceEnabled->setEnabled(getIsModifiable());
mExperiences->setVisible(TRUE);
mExperienceEnabled->set(TRUE);
getChild<LLButton>("view_profile")->setToolTip(getString("show_experience_profile"));
- buildExperienceList();
- }
+ buildExperienceList();
+ }
}
void LLLiveLSLEditor::buildExperienceList()
{
- mExperiences->clearRows();
- bool foundAssociated=false;
+ mExperiences->clearRows();
+ bool foundAssociated=false;
const LLUUID& associated = mScriptEd->getAssociatedExperience();
LLUUID last;
LLScrollListItem* item;
- for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it)
- {
- LLUUID id = it->asUUID();
+ for(LLSD::array_const_iterator it = mExperienceIds.beginArray(); it != mExperienceIds.endArray(); ++it)
+ {
+ LLUUID id = it->asUUID();
EAddPosition position = ADD_BOTTOM;
if(id == associated)
{
@@ -1339,9 +1339,9 @@ void LLLiveLSLEditor::buildExperienceList()
{
mExperiences->add(experience[LLExperienceCache::NAME].asString(), id, position);
}
- }
+ }
- if(!foundAssociated )
+ if(!foundAssociated )
{
const LLSD& experience = LLExperienceCache::get(associated);
if(experience.isDefined())
@@ -1354,7 +1354,7 @@ void LLLiveLSLEditor::buildExperienceList()
last = associated;
}
item->setEnabled(FALSE);
- }
+ }
if(last.notNull())
{
@@ -1371,27 +1371,27 @@ void LLLiveLSLEditor::buildExperienceList()
void LLScriptEdCore::setAssociatedExperience( const LLUUID& experience_id )
{
- mAssociatedExperience = experience_id;
+ mAssociatedExperience = experience_id;
}
void LLLiveLSLEditor::requestExperiences()
{
- if (!getIsModifiable())
- {
- return;
- }
+ if (!getIsModifiable())
+ {
+ return;
+ }
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string lookup_url=region->getCapability("GetCreatorExperiences");
- if(!lookup_url.empty())
- {
- LLHTTPClient::get(lookup_url, new ExperienceResponder(getDerivedHandle<LLLiveLSLEditor>()));
- }
- }
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ std::string lookup_url=region->getCapability("GetCreatorExperiences");
+ if(!lookup_url.empty())
+ {
+ LLHTTPClient::get(lookup_url, new ExperienceResponder(getDerivedHandle<LLLiveLSLEditor>()));
+ }
+ }
}
@@ -1414,7 +1414,7 @@ std::string LLScriptEdContainer::getTmpFileName()
std::string script_id = mObjectUUID.asString() + "_" + mItemUUID.asString();
// Use MD5 sum to make the file name shorter and not exceed maximum path length.
- char script_id_hash_str[33]; /* Flawfinder: ignore */
+ char script_id_hash_str[33]; /* Flawfinder: ignore */
LLMD5 script_id_hash((const U8 *)script_id.c_str());
script_id_hash.hex_digest(script_id_hash_str);
@@ -1953,14 +1953,14 @@ BOOL LLLiveLSLEditor::postBuild()
mScriptEd->mEditor->setFocus(TRUE);
- mExperiences = getChild<LLComboBox>("Experiences...");
- mExperiences->setCommitCallback(boost::bind(&LLLiveLSLEditor::experienceChanged, this));
-
- mExperienceEnabled = getChild<LLCheckBoxCtrl>("enable_xp");
-
- childSetCommitCallback("enable_xp", onToggleExperience, this);
- childSetCommitCallback("view_profile", onViewProfile, this);
-
+ mExperiences = getChild<LLComboBox>("Experiences...");
+ mExperiences->setCommitCallback(boost::bind(&LLLiveLSLEditor::experienceChanged, this));
+
+ mExperienceEnabled = getChild<LLCheckBoxCtrl>("enable_xp");
+
+ childSetCommitCallback("enable_xp", onToggleExperience, this);
+ childSetCommitCallback("view_profile", onViewProfile, this);
+
return LLPreview::postBuild();
}
@@ -2006,56 +2006,56 @@ void LLLiveLSLEditor::loadAsset()
{
LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(object->getInventoryObject(mItemUUID));
- if(item)
- {
- ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
-
- bool isGodlike = gAgent.isGodlike();
- bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
- mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE);
-
- if(!isGodlike && (!copyManipulate || !mIsModifiable))
- {
- mItem = new LLViewerInventoryItem(item);
- mScriptEd->setScriptText(getString("not_allowed"), FALSE);
- mScriptEd->mEditor->makePristine();
- mScriptEd->enableSave(FALSE);
- mAssetStatus = PREVIEW_ASSET_LOADED;
- }
- else if(copyManipulate || isGodlike)
- {
- mItem = new LLViewerInventoryItem(item);
- // request the text from the object
- LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID
- gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
- gAgent.getID(),
- gAgent.getSessionID(),
- item->getPermissions().getOwner(),
- object->getID(),
- item->getUUID(),
- item->getAssetUUID(),
- item->getType(),
- &LLLiveLSLEditor::onLoadComplete,
- (void*)user_data,
- TRUE);
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_GetScriptRunning);
- msg->nextBlockFast(_PREHASH_Script);
- msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID);
- msg->addUUIDFast(_PREHASH_ItemID, mItemUUID);
- msg->sendReliable(object->getRegion()->getHost());
- mAskedForRunningInfo = TRUE;
- mAssetStatus = PREVIEW_ASSET_LOADING;
- }
- }
-
- if(mItem.isNull())
- {
+ if(item)
+ {
+ ExperienceAssociationResponder::fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle<LLLiveLSLEditor>(), _1));
+
+ bool isGodlike = gAgent.isGodlike();
+ bool copyManipulate = gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE);
+ mIsModifiable = gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE);
+
+ if(!isGodlike && (!copyManipulate || !mIsModifiable))
+ {
+ mItem = new LLViewerInventoryItem(item);
+ mScriptEd->setScriptText(getString("not_allowed"), FALSE);
+ mScriptEd->mEditor->makePristine();
+ mScriptEd->enableSave(FALSE);
+ mAssetStatus = PREVIEW_ASSET_LOADED;
+ }
+ else if(copyManipulate || isGodlike)
+ {
+ mItem = new LLViewerInventoryItem(item);
+ // request the text from the object
+ LLUUID* user_data = new LLUUID(mItemUUID); // ^ mObjectUUID
+ gAssetStorage->getInvItemAsset(object->getRegion()->getHost(),
+ gAgent.getID(),
+ gAgent.getSessionID(),
+ item->getPermissions().getOwner(),
+ object->getID(),
+ item->getUUID(),
+ item->getAssetUUID(),
+ item->getType(),
+ &LLLiveLSLEditor::onLoadComplete,
+ (void*)user_data,
+ TRUE);
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_GetScriptRunning);
+ msg->nextBlockFast(_PREHASH_Script);
+ msg->addUUIDFast(_PREHASH_ObjectID, mObjectUUID);
+ msg->addUUIDFast(_PREHASH_ItemID, mItemUUID);
+ msg->sendReliable(object->getRegion()->getHost());
+ mAskedForRunningInfo = TRUE;
+ mAssetStatus = PREVIEW_ASSET_LOADING;
+ }
+ }
+
+ if(mItem.isNull())
+ {
mScriptEd->setScriptText(LLStringUtil::null, FALSE);
mScriptEd->mEditor->makePristine();
mAssetStatus = PREVIEW_ASSET_LOADED;
- mIsModifiable = FALSE;
- }
+ mIsModifiable = FALSE;
+ }
refreshFromItem();
// This is commented out, because we don't completely
@@ -2634,15 +2634,15 @@ BOOL LLLiveLSLEditor::monoChecked() const
void LLLiveLSLEditor::setAssociatedExperience( LLHandle<LLLiveLSLEditor> editor, const LLSD& experience )
{
- LLLiveLSLEditor* scriptEd = editor.get();
- if(scriptEd)
- {
- LLUUID id;
- if(experience.has(LLExperienceCache::EXPERIENCE_ID))
- {
- id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
- }
- scriptEd->mScriptEd->setAssociatedExperience(id);
- scriptEd->updateExperiencePanel();
- }
+ LLLiveLSLEditor* scriptEd = editor.get();
+ if(scriptEd)
+ {
+ LLUUID id;
+ if(experience.has(LLExperienceCache::EXPERIENCE_ID))
+ {
+ id=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
+ }
+ scriptEd->mScriptEd->setAssociatedExperience(id);
+ scriptEd->updateExperiencePanel();
+ }
}
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
index 2556714792..4970eec636 100755
--- a/indra/newview/llsidepanelinventory.cpp
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -257,12 +257,9 @@ void LLSidepanelInventory::updateInbox()
//
// Track inbox folder changes
//
-
- const bool do_not_create_folder = false;
-
- const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder);
+ const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
- // Set up observer to listen for creation of inbox if at least one of them doesn't exist
+ // Set up observer to listen for creation of inbox if it doesn't exist
if (inbox_id.isNull())
{
observeInboxCreation();
@@ -270,6 +267,11 @@ void LLSidepanelInventory::updateInbox()
// Set up observer for inbox changes, if we have an inbox already
else
{
+ // Consolidate Received items
+ // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention,
+ // things can get messy and conventions broken. This call puts everything back together in its right place.
+ gInventory.consolidateForType(inbox_id, LLFolderType::FT_INBOX);
+
// Enable the display of the inbox if it exists
enableInbox(true);
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 7b894d8d98..0a8257f42b 100755
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -62,6 +62,7 @@ static U32 sZombieGroups = 0;
U32 LLSpatialGroup::sNodeCount = 0;
U32 gOctreeMaxCapacity;
+F32 gOctreeMinSize;
BOOL LLSpatialGroup::sNoDelete = FALSE;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index ebdb5bc4e6..884d0cc8d2 100755
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -2838,6 +2838,7 @@ void LLStartUp::initNameCache()
// capabilities for display name lookup
LLAvatarNameCache::initClass(false,gSavedSettings.getBOOL("UsePeopleAPI"));
LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames"));
+ LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames"));
}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index d307a31843..eabf6f0497 100755
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1584,13 +1584,22 @@ static void give_inventory_cb(const LLSD& notification, const LLSD& response)
const LLUUID& session_id = payload["session_id"];
const LLUUID& agent_id = payload["agent_id"];
LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]);
- if (NULL == inv_item)
+ LLViewerInventoryCategory * inv_cat = gInventory.getCategory(payload["item_id"]);
+ if (NULL == inv_item && NULL == inv_cat)
{
- llassert(NULL != inv_item);
+ llassert( FALSE );
return;
}
-
- if (LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id))
+ bool successfully_shared;
+ if (inv_item)
+ {
+ successfully_shared = LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id);
+ }
+ else
+ {
+ successfully_shared = LLGiveInventory::doGiveInventoryCategory(agent_id, inv_cat, session_id);
+ }
+ if (successfully_shared)
{
if ("avatarpicker" == payload["d&d_dest"].asString())
{
@@ -1600,8 +1609,8 @@ static void give_inventory_cb(const LLSD& notification, const LLSD& response)
}
}
-static void show_item_sharing_confirmation(const std::string name,
- LLViewerInventoryItem* inv_item,
+static void show_object_sharing_confirmation(const std::string name,
+ LLInventoryObject* inv_item,
const LLSD& dest,
const LLUUID& dest_agent,
const LLUUID& session_id = LLUUID::null)
@@ -1611,32 +1620,28 @@ static void show_item_sharing_confirmation(const std::string name,
llassert(NULL != inv_item);
return;
}
- if(gInventory.getItem(inv_item->getUUID())
- && LLGiveInventory::isInventoryGiveAcceptable(inv_item))
- {
- LLSD substitutions;
- substitutions["RESIDENTS"] = name;
- substitutions["ITEMS"] = inv_item->getName();
- LLSD payload;
- payload["agent_id"] = dest_agent;
- payload["item_id"] = inv_item->getUUID();
- payload["session_id"] = session_id;
- payload["d&d_dest"] = dest.asString();
- LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb);
- }
+ LLSD substitutions;
+ substitutions["RESIDENTS"] = name;
+ substitutions["ITEMS"] = inv_item->getName();
+ LLSD payload;
+ payload["agent_id"] = dest_agent;
+ payload["item_id"] = inv_item->getUUID();
+ payload["session_id"] = session_id;
+ payload["d&d_dest"] = dest.asString();
+ LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb);
}
static void get_name_cb(const LLUUID& id,
const std::string& full_name,
- LLViewerInventoryItem* inv_item,
+ LLInventoryObject* inv_obj,
const LLSD& dest,
const LLUUID& dest_agent)
{
- show_item_sharing_confirmation(full_name,
- inv_item,
- dest,
- id,
- LLUUID::null);
+ show_object_sharing_confirmation(full_name,
+ inv_obj,
+ dest,
+ id,
+ LLUUID::null);
}
// function used as drag-and-drop handler for simple agent give inventory requests
@@ -1662,10 +1667,11 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
case DAD_GESTURE:
case DAD_CALLINGCARD:
case DAD_MESH:
+ case DAD_CATEGORY:
{
- LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
- if(gInventory.getItem(inv_item->getUUID())
- && LLGiveInventory::isInventoryGiveAcceptable(inv_item))
+ LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data;
+ if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID())
+ && LLGiveInventory::isInventoryGiveAcceptable(dynamic_cast<LLInventoryItem*>(inv_obj))))
{
// *TODO: get multiple object transfers working
*accept = ACCEPT_YES_COPY_SINGLE;
@@ -1682,40 +1688,18 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
// Otherwise set up a callback to show the dialog when the name arrives.
if (gCacheName->getFullName(dest_agent, fullname))
{
- show_item_sharing_confirmation(fullname, inv_item, dest, dest_agent, LLUUID::null);
+ show_object_sharing_confirmation(fullname, inv_obj, dest, dest_agent, LLUUID::null);
}
else
{
- gCacheName->get(dest_agent, false, boost::bind(&get_name_cb, _1, _2, inv_item, dest, dest_agent));
+ gCacheName->get(dest_agent, false, boost::bind(&get_name_cb, _1, _2, inv_obj, dest, dest_agent));
}
return true;
}
// If an IM session with destination agent is found item offer will be logged in this session.
- show_item_sharing_confirmation(session->mName, inv_item, dest, dest_agent, session_id);
- }
- }
- else
- {
- // It's not in the user's inventory (it's probably
- // in an object's contents), so disallow dragging
- // it here. You can't give something you don't
- // yet have.
- *accept = ACCEPT_NO;
- }
- break;
- }
- case DAD_CATEGORY:
- {
- LLViewerInventoryCategory* inv_cat = (LLViewerInventoryCategory*)cargo_data;
- if( gInventory.getCategory( inv_cat->getUUID() ) )
- {
- // *TODO: get multiple object transfers working
- *accept = ACCEPT_YES_COPY_SINGLE;
- if(drop)
- {
- LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id);
+ show_object_sharing_confirmation(session->mName, inv_obj, dest, dest_agent, session_id);
}
}
else
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 558159775f..6881ec4563 100755
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -1672,17 +1672,7 @@ BOOL LLToolPie::handleRightClickPick()
{
name = node->mName;
}
- std::string mute_msg;
- if (LLMuteList::getInstance()->isMuted(object->getID(), name))
- {
- mute_msg = LLTrans::getString("UnmuteObject");
- }
- else
- {
- mute_msg = LLTrans::getString("MuteObject2");
- }
-
- gMenuHolder->getChild<LLUICtrl>("Object Mute")->setValue(mute_msg);
+
gMenuObject->show(x, y);
showVisualContextMenuEffect();
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 70d3fc9462..5020518454 100755
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -368,6 +368,7 @@ static bool handleRepartition(const LLSD&)
if (gPipeline.isInit())
{
gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+ gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
gObjectList.repartitionObjects();
}
return true;
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 2c196ece51..0401de7e69 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -136,7 +136,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible");
- addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
+ addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Received Items", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible));
addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true));
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b23e23f32e..8c9429c05d 100755
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -7815,7 +7815,7 @@ void handle_report_bug(const LLSD& param)
replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getViewerInfoString());
LLSLURL location_url;
LLAgentUI::buildSLURL(location_url);
- replace["[LOCATION]"] = location_url.getSLURLString();
+ replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString());
LLUIString file_bug_url = gSavedSettings.getString("ReportBugURL");
file_bug_url.setArgs(replace);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 4ac11c97d7..929affe311 100755
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2465,10 +2465,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
&& from_id.notNull() //not a system message
&& to_id.notNull()) //not global message
{
- // return a standard "do not disturb" message, but only do it to online IM
- // (i.e. not other auto responses and not store-and-forward IM)
-
- send_do_not_disturb_message(msg, from_id, session_id);
// now store incoming IM in chat history
@@ -2489,6 +2485,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
region_id,
position,
true);
+
+ if (!gIMMgr->isDNDMessageSend(session_id))
+ {
+ // return a standard "do not disturb" message, but only do it to online IM
+ // (i.e. not other auto responses and not store-and-forward IM)
+ send_do_not_disturb_message(msg, from_id, session_id);
+ gIMMgr->setDNDMessageSent(session_id, true);
+ }
+
}
else if (from_id.isNull())
{
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index d216fb6ed9..f70ed68e49 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -2571,40 +2571,69 @@ void LLViewerRegion::unpackRegionHandshake()
{
LLUUID tmp_id;
+ bool changed = false;
+
+ // Get the 4 textures for land
msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id);
+ changed |= (tmp_id != compp->getDetailTextureID(0));
compp->setDetailTextureID(0, tmp_id);
+
msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id);
+ changed |= (tmp_id != compp->getDetailTextureID(1));
compp->setDetailTextureID(1, tmp_id);
+
msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id);
+ changed |= (tmp_id != compp->getDetailTextureID(2));
compp->setDetailTextureID(2, tmp_id);
+
msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id);
+ changed |= (tmp_id != compp->getDetailTextureID(3));
compp->setDetailTextureID(3, tmp_id);
+ // Get the start altitude and range values for land textures
F32 tmp_f32;
msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32);
+ changed |= (tmp_f32 != compp->getStartHeight(0));
compp->setStartHeight(0, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32);
+ changed |= (tmp_f32 != compp->getStartHeight(1));
compp->setStartHeight(1, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32);
+ changed |= (tmp_f32 != compp->getStartHeight(2));
compp->setStartHeight(2, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32);
+ changed |= (tmp_f32 != compp->getStartHeight(3));
compp->setStartHeight(3, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32);
+ changed |= (tmp_f32 != compp->getHeightRange(0));
compp->setHeightRange(0, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32);
+ changed |= (tmp_f32 != compp->getHeightRange(1));
compp->setHeightRange(1, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32);
+ changed |= (tmp_f32 != compp->getHeightRange(2));
compp->setHeightRange(2, tmp_f32);
+
msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32);
+ changed |= (tmp_f32 != compp->getHeightRange(3));
compp->setHeightRange(3, tmp_f32);
// If this is an UPDATE (params already ready, we need to regenerate
// all of our terrain stuff, by
if (compp->getParamsReady())
{
- //this line creates frame stalls on region crossing and removing it appears to have no effect
- //getLand().dirtyAllPatches();
+ // Update if the land changed
+ if (changed)
+ {
+ getLand().dirtyAllPatches();
+ }
}
else
{
@@ -2692,6 +2721,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("GetObjectCost");
capabilityNames.append("GetObjectPhysicsData");
capabilityNames.append("GetTexture");
+ capabilityNames.append("GroupAPIv1");
capabilityNames.append("GroupMemberData");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index d052906bee..4d263c118b 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1075,7 +1075,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK
// *HACK: this should be rolled into the composite tool logic, not
// hardcoded at the top level.
- if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
+ if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
{
// If the current tool didn't process the click, we should show
// the pie menu. This can be done by passing the event to the pie
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 945d3711f0..a83e2e020e 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1287,9 +1287,9 @@ BOOL LLVOVolume::calcLOD()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) &&
mDrawable->getFace(0))
{
- //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
+ //setDebugText(llformat("%.2f:%.2f, %d", mDrawable->mDistanceWRTCamera, radius, cur_detail));
- //setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
+ setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
}
if (cur_detail != mLOD)
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 7d7b32f305..3dfe1e5992 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -492,6 +492,7 @@ void LLPipeline::init()
refreshCachedSettings();
gOctreeMaxCapacity = gSavedSettings.getU32("OctreeMaxNodeCapacity");
+ gOctreeMinSize = gSavedSettings.getF32("OctreeMinimumNodeSize");
sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD");
sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips");
diff --git a/indra/newview/roles_constants.h b/indra/newview/roles_constants.h
index 65ec290200..24792dd731 100644
--- a/indra/newview/roles_constants.h
+++ b/indra/newview/roles_constants.h
@@ -53,101 +53,103 @@ enum LLRoleChangeType
// KNOWN HOLES: use these for any single bit powers you need
// bit 0x1 << 46
-// bit 0x1 << 51 and above
+// bit 0x1 << 52 and above
// These powers were removed to make group roles simpler
// bit 0x1 << 41 (GP_ACCOUNTING_VIEW)
// bit 0x1 << 46 (GP_PROPOSAL_VIEW)
const U64 GP_NO_POWERS = 0x0;
-const U64 GP_ALL_POWERS = 0xFFFFFFFFFFFFFFFFLL;
+const U64 GP_ALL_POWERS = 0xFFFFffffFFFFffffLL;
// Membership
-const U64 GP_MEMBER_INVITE = 0x1 << 1; // Invite member
-const U64 GP_MEMBER_EJECT = 0x1 << 2; // Eject member from group
-const U64 GP_MEMBER_OPTIONS = 0x1 << 3; // Toggle "Open enrollment" and change "Signup Fee"
-const U64 GP_MEMBER_VISIBLE_IN_DIR = 0x1LL << 47;
+const U64 GP_MEMBER_INVITE = 0x1LL << 1; // Invite member
+const U64 GP_MEMBER_EJECT = 0x1LL << 2; // Eject member from group
+const U64 GP_MEMBER_OPTIONS = 0x1LL << 3; // Toggle "Open enrollment" and change "Signup Fee"
+const U64 GP_MEMBER_VISIBLE_IN_DIR = 0x1LL << 47;
// Roles
-const U64 GP_ROLE_CREATE = 0x1 << 4; // Create new roles
-const U64 GP_ROLE_DELETE = 0x1 << 5; // Delete roles
-const U64 GP_ROLE_PROPERTIES = 0x1 << 6; // Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?)
-const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED = 0x1 << 7; // Assign Member to a Role that the assigner is in
-const U64 GP_ROLE_ASSIGN_MEMBER = 0x1 << 8; // Assign Member to Role
-const U64 GP_ROLE_REMOVE_MEMBER = 0x1 << 9; // Remove Member from Role
-const U64 GP_ROLE_CHANGE_ACTIONS = 0x1 << 10; // Change actions a role can perform
+const U64 GP_ROLE_CREATE = 0x1LL << 4; // Create new roles
+const U64 GP_ROLE_DELETE = 0x1LL << 5; // Delete roles
+const U64 GP_ROLE_PROPERTIES = 0x1LL << 6; // Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?)
+const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED = 0x1LL << 7; // Assign Member to a Role that the assigner is in
+const U64 GP_ROLE_ASSIGN_MEMBER = 0x1LL << 8; // Assign Member to Role
+const U64 GP_ROLE_REMOVE_MEMBER = 0x1LL << 9; // Remove Member from Role
+const U64 GP_ROLE_CHANGE_ACTIONS = 0x1LL << 10; // Change actions a role can perform
// Group Identity
-const U64 GP_GROUP_CHANGE_IDENTITY = 0x1 << 11; // Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes
+const U64 GP_GROUP_CHANGE_IDENTITY = 0x1LL << 11; // Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes
// Parcel Management
-const U64 GP_LAND_DEED = 0x1 << 12; // Deed Land and Buy Land for Group
-const U64 GP_LAND_RELEASE = 0x1 << 13; // Release Land (to Gov. Linden)
-const U64 GP_LAND_SET_SALE_INFO = 0x1 << 14; // Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land")
-const U64 GP_LAND_DIVIDE_JOIN = 0x1 << 15; // Divide and Join Parcels
+const U64 GP_LAND_DEED = 0x1LL << 12; // Deed Land and Buy Land for Group
+const U64 GP_LAND_RELEASE = 0x1LL << 13; // Release Land (to Gov. Linden)
+const U64 GP_LAND_SET_SALE_INFO = 0x1LL << 14; // Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land")
+const U64 GP_LAND_DIVIDE_JOIN = 0x1LL << 15; // Divide and Join Parcels
// Parcel Identity
-const U64 GP_LAND_FIND_PLACES = 0x1 << 17; // Toggle "Show in Find Places" and Set Category.
-const U64 GP_LAND_CHANGE_IDENTITY = 0x1 << 18; // Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox
-const U64 GP_LAND_SET_LANDING_POINT = 0x1 << 19; // Set Landing Point
+const U64 GP_LAND_FIND_PLACES = 0x1LL << 17; // Toggle "Show in Find Places" and Set Category.
+const U64 GP_LAND_CHANGE_IDENTITY = 0x1LL << 18; // Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox
+const U64 GP_LAND_SET_LANDING_POINT = 0x1LL << 19; // Set Landing Point
// Parcel Settings
-const U64 GP_LAND_CHANGE_MEDIA = 0x1 << 20; // Change Media Settings
-const U64 GP_LAND_EDIT = 0x1 << 21; // Toggle Edit Land
-const U64 GP_LAND_OPTIONS = 0x1 << 22; // Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes
+const U64 GP_LAND_CHANGE_MEDIA = 0x1LL << 20; // Change Media Settings
+const U64 GP_LAND_EDIT = 0x1LL << 21; // Toggle Edit Land
+const U64 GP_LAND_OPTIONS = 0x1LL << 22; // Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes
// Parcel Powers
-const U64 GP_LAND_ALLOW_EDIT_LAND = 0x1 << 23; // Bypass Edit Land Restriction
-const U64 GP_LAND_ALLOW_FLY = 0x1 << 24; // Bypass Fly Restriction
-const U64 GP_LAND_ALLOW_CREATE = 0x1 << 25; // Bypass Create/Edit Objects Restriction
-const U64 GP_LAND_ALLOW_LANDMARK = 0x1 << 26; // Bypass Landmark Restriction
-const U64 GP_LAND_ALLOW_SET_HOME = 0x1 << 28; // Bypass Set Home Point Restriction
-const U64 GP_LAND_ALLOW_HOLD_EVENT = 0x1LL << 41; // Allowed to hold events on group-owned land
-
+const U64 GP_LAND_ALLOW_EDIT_LAND = 0x1LL << 23; // Bypass Edit Land Restriction
+const U64 GP_LAND_ALLOW_FLY = 0x1LL << 24; // Bypass Fly Restriction
+const U64 GP_LAND_ALLOW_CREATE = 0x1LL << 25; // Bypass Create/Edit Objects Restriction
+const U64 GP_LAND_ALLOW_LANDMARK = 0x1LL << 26; // Bypass Landmark Restriction
+const U64 GP_LAND_ALLOW_SET_HOME = 0x1LL << 28; // Bypass Set Home Point Restriction
+const U64 GP_LAND_ALLOW_HOLD_EVENT = 0x1LL << 41; // Allowed to hold events on group-owned land
// Parcel Access
-const U64 GP_LAND_MANAGE_ALLOWED = 0x1 << 29; // Manage Allowed List
-const U64 GP_LAND_MANAGE_BANNED = 0x1 << 30; // Manage Banned List
-const U64 GP_LAND_MANAGE_PASSES = 0x1LL << 31; // Change Sell Pass Settings
-const U64 GP_LAND_ADMIN = 0x1LL << 32; // Eject and Freeze Users on the land
+const U64 GP_LAND_MANAGE_ALLOWED = 0x1LL << 29; // Manage Allowed List
+const U64 GP_LAND_MANAGE_BANNED = 0x1LL << 30; // Manage Banned List
+const U64 GP_LAND_MANAGE_PASSES = 0x1LL << 31; // Change Sell Pass Settings
+const U64 GP_LAND_ADMIN = 0x1LL << 32; // Eject and Freeze Users on the land
// Parcel Content
-const U64 GP_LAND_RETURN_GROUP_SET = 0x1LL << 33; // Return objects on parcel that are set to group
-const U64 GP_LAND_RETURN_NON_GROUP = 0x1LL << 34; // Return objects on parcel that are not set to group
-const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48; // Return objects on parcel that are owned by the group
+const U64 GP_LAND_RETURN_GROUP_SET = 0x1LL << 33; // Return objects on parcel that are set to group
+const U64 GP_LAND_RETURN_NON_GROUP = 0x1LL << 34; // Return objects on parcel that are not set to group
+const U64 GP_LAND_RETURN_GROUP_OWNED = 0x1LL << 48; // Return objects on parcel that are owned by the group
// Select a power-bit based on an object's relationship to a parcel.
const U64 GP_LAND_RETURN = GP_LAND_RETURN_GROUP_OWNED
| GP_LAND_RETURN_GROUP_SET
| GP_LAND_RETURN_NON_GROUP;
-const U64 GP_LAND_GARDENING = 0x1LL << 35; // Parcel Gardening - plant and move linden trees
+const U64 GP_LAND_GARDENING = 0x1LL << 35; // Parcel Gardening - plant and move linden trees
// Object Management
-const U64 GP_OBJECT_DEED = 0x1LL << 36; // Deed Object
-const U64 GP_OBJECT_MANIPULATE = 0x1LL << 38; // Manipulate Group Owned Objects (Move, Copy, Mod)
-const U64 GP_OBJECT_SET_SALE = 0x1LL << 39; // Set Group Owned Object for Sale
+const U64 GP_OBJECT_DEED = 0x1LL << 36; // Deed Object
+const U64 GP_OBJECT_MANIPULATE = 0x1LL << 38; // Manipulate Group Owned Objects (Move, Copy, Mod)
+const U64 GP_OBJECT_SET_SALE = 0x1LL << 39; // Set Group Owned Object for Sale
// Accounting
-const U64 GP_ACCOUNTING_ACCOUNTABLE = 0x1LL << 40; // Pay Group Liabilities and Receive Group Dividends
+const U64 GP_ACCOUNTING_ACCOUNTABLE = 0x1LL << 40; // Pay Group Liabilities and Receive Group Dividends
// Notices
-const U64 GP_NOTICES_SEND = 0x1LL << 42; // Send Notices
-const U64 GP_NOTICES_RECEIVE = 0x1LL << 43; // Receive Notices and View Notice History
+const U64 GP_NOTICES_SEND = 0x1LL << 42; // Send Notices
+const U64 GP_NOTICES_RECEIVE = 0x1LL << 43; // Receive Notices and View Notice History
// Proposals
// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_START = 0x1LL << 44; // Start Proposal
+const U64 GP_PROPOSAL_START = 0x1LL << 44; // Start Proposal
// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_VOTE = 0x1LL << 45; // Vote on Proposal
+const U64 GP_PROPOSAL_VOTE = 0x1LL << 45; // Vote on Proposal
// Group chat moderation related
-const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
-const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
-const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
+const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
+const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
+const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
+
+const U64 GP_EXPERIENCE_ADMIN = 0x1LL << 49; // has admin rights to any experiences owned by this group
+const U64 GP_EXPERIENCE_CREATOR = 0x1LL << 50; // can sign scripts for experiences owned by this group
-const U64 GP_EXPERIENCE_ADMIN = 0x1LL << 49; // has admin rights to any experiences owned by this group
-const U64 GP_EXPERIENCE_CREATOR = 0x1LL << 50; // can sign scripts for experiences owned by this group
+// Group Banning
+const U64 GP_GROUP_BAN_ACCESS = 0x1LL << 51; // Allows access to ban / un-ban agents from a group.
const U64 GP_DEFAULT_MEMBER = GP_ACCOUNTING_ACCOUNTABLE
| GP_LAND_ALLOW_SET_HOME
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 85981c1c41..393c8314b2 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -246,7 +246,7 @@ with the same filename but different name
<texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" />
<texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
- <texture name="Icon_For_Sale" file_name="icons/Icon_For_sale.png" preload="false" />
+ <texture name="Icon_For_Sale" file_name="icons/Icon_For_Sale.png" preload="false" />
<texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
<texture name="Icon_Gear_Foreground" file_name="windows/Icon_Gear_Foreground.png" preload="false" />
@@ -347,8 +347,8 @@ with the same filename but different name
<texture name="ModelImport_Status_Warning" file_name="lag_status_warning.tga" preload="false"/>
<texture name="ModelImport_Status_Error" file_name="red_x.png" preload="false"/>
- <texture name="MouseLook_View_Off" file_name="bottomtray/MouseLook_view_off.png" preload="false" />
- <texture name="MouseLook_View_On" file_name="bottomtray/MouseLook_view_on.png" preload="false" />
+ <texture name="MouseLook_View_Off" file_name="bottomtray/Mouselook_View_Off.png" preload="false" />
+ <texture name="MouseLook_View_On" file_name="bottomtray/Mouselook_View_On.png" preload="false" />
<texture name="Move_Fly_Off" file_name="bottomtray/Move_Fly_Off.png" preload="false" />
<texture name="Move_Run_Off" file_name="bottomtray/Move_Run_Off.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml
index 0df330b016..6d48180707 100755
--- a/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Lokationer, billeder, web, søge historik)
</text>
- <check_box label="Vis dig selv i søgeresultater" name="online_searchresults"/>
+ <check_box label="Vis min profil info i søgeresultater" name="online_searchresults"/>
<check_box label="Kun venner og grupper ved jeg er online" name="online_visibility"/>
<check_box label="Kun venner og grupper kan sende besked til mig" name="voice_call_friends_only_check"/>
<check_box label="Slå mikrofon fra når opkald slutter" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
index e21bed6bb5..afde50b981 100755
--- a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Standorte, Bilder, Web, Suchverlauf)
</text>
- <check_box label="In Suchergebnissen anzeigen" name="online_searchresults"/>
+ <check_box label="Zeigen Sie mein Profil Informationen in Suchergebnisse" name="online_searchresults"/>
<check_box label="Nur Freunde und Gruppen wissen, dass ich online bin" name="online_visibility"/>
<check_box label="Nur Freunde und Gruppen können mich anrufen oder mir eine IM schicken" name="voice_call_friends_only_check"/>
<check_box label="Mikrofon ausschalten, wenn Anrufe beendet werden" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 9668cfa526..ef2f158a86 100755
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -72,7 +72,7 @@ Second Life is brought to you by the Lindens:
top_pad="10"
width="435"
word_wrap="true">
-Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase
+Philip, Andrew, Doug, Richard, Phoenix, Ian, Mark, Robin, Dan, Char, Ryan, Eric, Jim, Lee, Jeff, Michael, Kelly, Steve, Catherine, Bub, Ramzi, Jill, Jeska, Don, Kona, Callum, Charity, Jack, Shawn, babbage, James, Lauren, Blue, Brent, Reuben, Pathfinder, Jesse, Patsy, Torley, Bo, Cyn, Jonathan, Gia, Annette, Ginsu, Harry, Lex, Runitai, Guy, Cornelius, Beth, Swiss, Thumper, Wendy, Teeple, Seth, Dee, Mia, Sally, Liana, Aura, Beez, Milo, Red, Gulliver, Marius, Joe, Jose, Dore, Justin, Nora, Morpheus, Lexie, Amber, Chris, Xan, Leyla, Walker, Sabin, Joshua, Hiromi, Tofu, Fritz, June, Jean, Ivy, Dez, Ken, Betsy, Which, Spike, Rob, Zee, Dustin, George, Claudia, del, Matthew, jane, jay, Adrian, Yool, Rika, Yoz, siobhan, Qarl, Benjamin, Beast, Everett, madhavi, Christopher, Izzy, stephany, Jeremy, sean, adreanne, Pramod, Tobin, sejong, Iridium, maurice, kj, Meta, kari, JP, bert, kyle, Jon, Socrates, Bridie, Ivan, maria, Aric, Coco, Periapse, sandy, Storrs, Lotte, Colossus, Brad, Pastrami, Zen, BigPapi, Banzai, Sardonyx, Mani, Garry, Jaime, Neuro, Samuel, Niko, CeeLo, Austin, Soft, Poppy, emma, tessa, angelo, kurz, alexa, Sue, CG, Blake, Erica, Brett, Bevis, kristen, Q, simon, Enus, MJ, laurap, Kip, Scouse, Ron, Ram, kend, Marty, Prospero, melissa, kraft, Nat, Seraph, Hamilton, Lordan, Green, miz, Ashlei, Trinity, Ekim, Echo, Charlie, Rowan, Rome, Jt, Doris, benoc, Christy, Bao, Kate, Tj, Patch, Cheah, Johan, Brandy, Angela, Oreh, Cogsworth, Lan, Mitchell, Space, Bambers, Einstein, Bender, Malbers, Matias, Maggie, Rothman, Milton, Niall, Marin, Allison, Mango, Andrea, Katt, Yi, Ambroff, Rico, Raymond, Gail, Christa, William, Dawn, Usi, Dynamike, M, Corr, Dante, Molly, kaylee, Danica, Kelv, Lil, jacob, Nya, Rodney, elsie, Blondin, Grant, Nyx, Devin, Monty, Minerva, Keira, Katie, Jenn, Makai, Clare, Joy, Cody, Gayathri, FJ, spider, Oskar, Landon, Jarv, Noelle, Al, Doc, Gray, Vir, t, Maestro, Simone, Shannon, yang, Courtney, Scott, charlene, Quixote, Susan, Zed, Amanda, Katelin, Esbee, JoRoan, Enkidu, roxie, Scarlet, Merov, Kevin, Judy, Rand, Newell, Les, Dessie, Galen, Michon, Geo, Siz, Calyle, Pete, Praveen, Callen, Sheldon, Pink, Nelson, jenelle, Terrence, Nathan, Juan, Sascha, Huseby, Karina, Kaye, Kotler, Lis, Darv, Charrell, Dakota, Kimmora, Theeba, Taka, Mae, Perry, Ducot, dana, Esther, Dough, gisele, Doten, Viale, Fisher, jessieann, ashley, Torres, delby, rountree, kurt, Slaton, Madison, Rue, Gino, Wen, Casssandra, Brodesky, Squid, Gez, Rakesh, Gecko, Ladan, Tony, Tatem, Squire, Falcon, BK, Crimp, Tiggs, Bacon, Coyot, Carmilla, Webb, Sea, Arch, Jillian, Jason, Bernard, Vogt, Peggy, dragon, Pup, xandix, Wallace, Bewest, Inoshiro, Rhett, AG, Aimee, Ghengis, Itiaes, Eli, Steffan, Epic, Grapes, Stone, Prep, Scobu, Robert, Alain, Carla, Vicky, Tia, Alec, Taras, Lisa, Oz, Ariane, Log, House, Kazu, Kim, Drofnas, Tyler, Campbell, Michele, Madeline, Nelly, Baron, Thor, Lori, Hele, Fredrik, Teddy, Pixie, Berry, Gabrielle, Alfonso, Brooke, Wolf, Ringo, Cru, Charlar, Rodvik, Gibson, Elise, Bagman, Greger, Leonidas, Jerm, Leslie, CB, Brenda, Durian, Carlo, mm, Zeeshan, Caleb, Max, Elikak, Mercille, Steph, Chase, Baker
</text_editor>
<text
follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index 9561f67941..c50c8c02fe 100755
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -203,47 +203,15 @@
<combo_box.item
label="Age &gt; Age play"
name="Age__Age_play"
- value="31" />
+ value="31" />
<combo_box.item
- label="Age &gt; Adult Resident on Teen Second Life"
- name="Age__Adult_resident_on_Teen_Second_Life"
- value="32" />
- <combo_box.item
- label="Age &gt; Underage Resident outside of Teen Second Life"
- name="Age__Underage_resident_outside_of_Teen_Second_Life"
- value="33" />
- <combo_box.item
- label="Assault &gt; Combat sandbox / unsafe area"
- name="Assault__Combat_sandbox___unsafe_area"
- value="34" />
- <combo_box.item
- label="Assault &gt; Safe area"
+ label="Assault &gt; Shooting, pushing, or shoving another Resident in a Safe Area"
name="Assault__Safe_area"
- value="35" />
- <combo_box.item
- label="Assault &gt; Weapons testing sandbox"
- name="Assault__Weapons_testing_sandbox"
- value="36" />
- <combo_box.item
- label="Commerce &gt; Failure to deliver product or service"
- name="Commerce__Failure_to_deliver_product_or_service"
- value="38" />
+ value="35" />
<combo_box.item
label="Disclosure &gt; Real world information"
name="Disclosure__Real_world_information"
- value="39" />
- <combo_box.item
- label="Disclosure &gt; Remotely monitoring chat"
- name="Disclosure__Remotely_monitoring chat"
- value="40" />
- <combo_box.item
- label="Disclosure &gt; Second Life information/chat/IMs"
- name="Disclosure__Second_Life_information_chat_IMs"
- value="41" />
- <combo_box.item
- label="Disturbing the peace &gt; Unfair use of region resources"
- name="Disturbing_the_peace__Unfair_use_of_region_resources"
- value="42" />
+ value="39" />
<combo_box.item
label="Disturbing the peace &gt; Excessive scripted objects"
name="Disturbing_the_peace__Excessive_scripted_objects"
@@ -255,51 +223,15 @@
<combo_box.item
label="Disturbing the peace &gt; Repetitive spam"
name="Disturbing_the_peace__Repetitive_spam"
- value="45" />
- <combo_box.item
- label="Disturbing the peace &gt; Unwanted advert spam"
- name="Disturbing_the_peace__Unwanted_advert_spam"
- value="46" />
- <combo_box.item
- label="Fraud &gt; L$"
- name="Fraud__L$"
- value="47" />
- <combo_box.item
- label="Fraud &gt; Land"
- name="Fraud__Land"
- value="48" />
- <combo_box.item
- label="Fraud &gt; Pyramid scheme or chain letter"
- name="Fraud__Pyramid_scheme_or_chain_letter"
- value="49" />
+ value="45" />
<combo_box.item
- label="Fraud &gt; US$"
+ label="Fraud &gt; L$ or USD $"
name="Fraud__US$"
- value="50" />
+ value="50" />
<combo_box.item
- label="Harassment &gt; Advert farms / visual spam"
- name="Harassment__Advert_farms___visual_spam"
- value="51" />
- <combo_box.item
- label="Harassment &gt; Defaming individuals or groups"
- name="Harassment__Defaming_individuals_or_groups"
- value="52" />
- <combo_box.item
- label="Harassment &gt; Impeding movement"
- name="Harassment__Impeding_movement"
- value="53" />
- <combo_box.item
- label="Harassment &gt; Sexual harassment"
- name="Harassment__Sexual_harassment"
- value="54" />
- <combo_box.item
- label="Harassment &gt; Solicting/inciting others to violate ToS"
+ label="Harassment &gt; Targeted behavior intended to disrupt"
name="Harassment__Solicting_inciting_others_to_violate_ToS"
- value="55" />
- <combo_box.item
- label="Harassment &gt; Verbal abuse"
- name="Harassment__Verbal_abuse"
- value="56" />
+ value="55" />
<combo_box.item
label="Indecency &gt; Broadly offensive content or conduct"
name="Indecency__Broadly_offensive_content_or_conduct"
@@ -309,49 +241,21 @@
name="Indecency__Inappropriate_avatar_name"
value="59" />
<combo_box.item
- label="Indecency &gt; Inappropriate content or conduct in a PG region"
+ label="Indecency &gt; Inappropriate content or conduct for Region Rating"
name="Indecency__Mature_content_in_PG_region"
- value="60" />
- <combo_box.item
- label="Indecency &gt; Inappropriate content or conduct in a Moderate region"
- name="Indecency__Inappropriate_content_in_Mature_region"
- value="69" />
- <combo_box.item
- label="Intellectual property infringement &gt; Content Removal"
- name="Intellectual_property_infringement_Content_Removal"
- value="66" />
- <combo_box.item
- label="Intellectual property infringement &gt; CopyBot or Permissions Exploit"
- name="Intellectual_property_infringement_CopyBot_or_Permissions_Exploit"
- value="37" />
+ value="60" />
<combo_box.item
label="Intolerance"
name="Intolerance"
- value="61" />
- <combo_box.item
- label="Land &gt; Abuse of sandbox resources"
- name="Land__Abuse_of_sandbox_resources"
- value="62" />
+ value="61" />
<combo_box.item
- label="Land &gt; Encroachment &gt; Objects/textures"
+ label="Land &gt; Encroachment &gt; Objects or textures"
name="Land__Encroachment__Objects_textures"
- value="63" />
+ value="63" />
<combo_box.item
- label="Land &gt; Encroachment &gt; Particles"
- name="Land__Encroachment__Particles"
- value="64" />
- <combo_box.item
- label="Land &gt; Encroachment &gt; Trees/plants"
- name="Land__Encroachment__Trees_plants"
- value="65" />
- <combo_box.item
- label="Wagering/gambling"
+ label="Wagering or Gambling"
name="Wagering_gambling"
- value="67" />
- <combo_box.item
- label="Other"
- name="Other"
- value="68" />
+ value="67" />
</combo_box>
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index 8b9733df17..3c28233875 100755
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -150,7 +150,7 @@
parameter="Land" />
</button>
<text
- height="30"
+ height="20"
word_wrap="true"
use_ellipses="true"
type="string"
@@ -294,24 +294,14 @@
<check_box
control_name="ScaleUniform"
height="19"
- label=""
+ label="Stretch Both Sides"
layout="topleft"
left="143"
name="checkbox uniform"
top="48"
- width="20" />
- <text
- height="19"
- label="Stretch Both Sides"
- left_delta="20"
- name="checkbox uniform label"
- top_delta="2"
- width="120"
- layout="topleft"
- follows="top|left"
- wrap="true">
- Stretch Both Sides
- </text>
+ label_text.wrap="true"
+ label_text.width="100"
+ width="134" />
<check_box
control_name="ScaleStretchTextures"
height="19"
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index 31b1d091ee..ed362b36e5 100755
--- a/indra/newview/skins/default/xui/en/menu_conversation.xml
+++ b/indra/newview/skins/default/xui/en/menu_conversation.xml
@@ -17,6 +17,7 @@
layout="topleft"
name="open_voice_conversation">
<on_click function="Avatar.DoToSelected" parameter="open_voice_conversation"/>
+ <on_enable function="Avatar.EnableItem" parameter="can_open_voice_conversation"/>
</menu_item_call>
<menu_item_call
label="Disconnect from voice"
@@ -213,4 +214,12 @@
<on_enable function="Avatar.EnableItem" parameter="can_moderate_voice" />
</menu_item_call>
</context_menu>
+ <menu_item_separator layout="topleft" name="Group Ban Separator"/>
+ <menu_item_call
+ label="Ban member"
+ layout="topleft"
+ name="BanMember">
+ <on_click function="Avatar.DoToSelected" parameter="ban_member" />
+ <on_enable function="Avatar.EnableItem" parameter="can_ban_member" />
+ </menu_item_call>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index 52ab7da515..5c98a98d3d 100755
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -130,17 +130,24 @@
function="Object.ReportAbuse" />
<menu_item_call.on_enable
function="Object.EnableReportAbuse" />
- </menu_item_call>
+ </menu_item_call>
<menu_item_call
- enabled="false"
- label="Block"
- name="Object Mute">
- <menu_item_call.on_click
+ label="Block"
+ name="Object Mute">
+ <menu_item_call.on_click
function="Object.Mute" />
- <menu_item_call.on_enable
+ <menu_item_call.on_visible
function="Object.EnableMute" />
</menu_item_call>
<menu_item_call
+ label="Unblock"
+ name="Object Unmute">
+ <menu_item_call.on_click
+ function="Object.Mute" />
+ <menu_item_call.on_visible
+ function="Object.EnableUnmute" />
+ </menu_item_call>
+ <menu_item_call
enabled="false"
label="Return"
name="Return...">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index b81d8cfc6e..c910f2eae8 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -506,7 +506,35 @@ Add this Ability to &apos;[ROLE_NAME]&apos;?
notext="No"
yestext="Yes"/>
</notification>
-
+
+ <notification
+ icon="alertmodal.tga"
+ name="AssignBanAbilityWarning"
+ type="alertmodal">
+You are about to add the Ability &apos;[ACTION_NAME]&apos; to the Role &apos;[ROLE_NAME]&apos;.
+
+ *WARNING*
+Any Member in a Role with this Ability will also be granted the Abilities &apos;[ACTION_NAME_2]&apos; and &apos;[ACTION_NAME_3]&apos;
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="RemoveBanAbilityWarning"
+ type="alertmodal">
+You are removing the Ability &apos;[ACTION_NAME]&apos; to the Role &apos;[ROLE_NAME]&apos;.
+
+ *WARNING*
+Removing this ability will NOT remove the Abilities &apos;[ACTION_NAME_2]&apos; and &apos;[ACTION_NAME_3]&apos;.
+
+If you no longer wish to have these abilities granted to this role, disable them immediately!
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="EjectGroupMemberWarning"
@@ -3747,6 +3775,28 @@ Leave Group?
</notification>
<notification
+ icon="aler.tga"
+ name="GroupDepartError"
+ type="alert">
+Unable to leave group: [reason].
+ <tag>reason</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alert.tga"
+ name="GroupDepart"
+ type="alert">
+You have left the group [group_name].
+ <tag>group_name</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alert.tga"
name="ConfirmKick"
type="alert">
diff --git a/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml
new file mode 100644
index 0000000000..509dcf354e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="330"
+ label="Ban Residents"
+ layout="topleft"
+ left="0"
+ name="bulk_ban_panel"
+ top="330"
+ width="210">
+ <panel.string
+ name="loading">
+ (loading...)
+ </panel.string>
+ <panel.string
+ name="ban_selection_too_large">
+ Group bans not sent: too many Residents selected. Group bans are limited to 100 per request.
+ </panel.string>
+ <panel.string
+ name="ban_not_permitted">
+ Group ban not sent: you do not have 'Manage ban list' ability.
+ </panel.string>
+ <panel.string
+ name="ban_limit_fail">
+ Group ban not sent: your group have reached limit of allowed ban records.
+ </panel.string>
+ <panel.string
+ name="partial_ban">
+ Some group bans were not sent:
+[REASONS]
+ </panel.string>
+ <panel.string
+ name="ban_failed">
+ Group bans were not sent:
+[REASONS]
+ </panel.string>
+ <panel.string
+ name="residents_already_banned">
+ - The following resident(s) are already banned: [RESIDENTS].
+ </panel.string>
+ <panel.string
+ name="ban_limit_reached">
+ - Ban limit reached, following agents not banned: [RESIDENTS].
+ </panel.string>
+ <panel.string
+ name="cant_ban_yourself">
+ - You cannot ban yourself from a group.
+ </panel.string>
+ <text
+ type="string"
+ length="1"
+ height="54"
+ layout="topleft"
+ left="7"
+ name="help_text"
+ top="28"
+ word_wrap="true"
+ width="200">
+ You can select multiple Residents to ban from your group. Click &apos;Open Resident Chooser&apos; to start.
+ </text>
+ <button
+ height="20"
+ label="Open Resident Chooser"
+ layout="topleft"
+ left_delta="-2"
+ name="add_button"
+ top_delta="44"
+ width="200" />
+ <name_list
+ allow_calling_card_drop="true"
+ column_padding="0"
+ height="174"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="banned_agent_list"
+ tool_tip="Hold the Ctrl key and click Resident names to multi-select"
+ top_pad="4"
+ width="200" />
+ <button
+ height="20"
+ label="Remove Selected from List"
+ layout="topleft"
+ left_delta="0"
+ name="remove_button"
+ tool_tip="Removes the Residents selected above from the ban list"
+ top_pad="4"
+ width="200" />
+ <button
+ height="20"
+ label="Ban Residents"
+ layout="topleft"
+ left="4"
+ name="ban_button"
+ top_delta="30"
+ width="135" />
+ <button
+ height="20"
+ label="Cancel"
+ layout="topleft"
+ left_pad="2"
+ name="cancel_button"
+ top_delta="0"
+ width="65" />
+ <string
+ name="GroupBulkBan">
+ Group Ban
+ </string>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml
index 124c0596c3..ebb460deb0 100755
--- a/indra/newview/skins/default/xui/en/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml
@@ -76,7 +76,7 @@
Choose what Role to assign them to:
</text>
<combo_box
- height="16"
+ height="20"
layout="topleft"
left_delta="0"
name="role_name"
@@ -88,7 +88,7 @@
label="Send Invitations"
layout="topleft"
left="4"
- name="ok_button"
+ name="invite_button"
top="356"
width="135" />
<button
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 9ac5b8800e..dac4371a38 100755
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -118,6 +118,13 @@ clicking on their names.
left_pad="10"
name="member_eject"
width="100" />
+ <button
+ height="23"
+ label="Ban Member(s)"
+ follows="top|left"
+ left_pad="10"
+ name="member_ban"
+ width="100" />
</panel>
<panel
border="false"
@@ -138,454 +145,535 @@ clicking on their names.
right="-5"
name="show_all_button"
width="100" />-->
- <panel.string
- name="help_text">
- Roles have a title and an allowed list of Abilities
-that Members can perform. Members can belong to
-one or more Roles. A group can have up to 10 Roles,
-including the Everyone and Owner Roles.
- </panel.string>
- <panel.string
- name="cant_delete_role">
- The &apos;Everyone&apos; and &apos;Owners&apos; Roles are special and can't be deleted.
- </panel.string>
- <panel.string
- name="power_folder_icon" translate="false">
- Inv_FolderClosed
- </panel.string>
- <panel.string
- name="power_all_have_icon" translate="false">
- Checkbox_On
- </panel.string>
- <panel.string
- name="power_partial_icon" translate="false">
- Checkbox_Off
- </panel.string>
- <filter_editor
- layout="topleft"
- top="5"
- left="5"
- right="-5"
- height="22"
- search_button_visible="false"
- follows="left|top|right"
- label="Filter Roles"
- name="filter_input" />
- <scroll_list
- column_padding="0"
- draw_heading="true"
- draw_stripes="false"
- heading_height="23"
- height="132"
- layout="topleft"
- search_column="1"
- left="0"
- follows="left|top|right"
- right="-1"
- name="role_list"
- top_pad="2"
- width="310">
- <scroll_list.columns
- label="Role"
- name="name"
- relative_width="0.45" />
- <scroll_list.columns
- label="Title"
- name="title"
- relative_width="0.45" />
- <scroll_list.columns
- label="#"
- name="members"
- relative_width="0.15" />
- </scroll_list>
- <button
- follows="top|left"
- height="23"
- label="New Role"
- layout="topleft"
- left="0"
- name="role_create"
- width="120" />
- <button
- height="23"
- follows="top|left"
- label="Delete Role"
- layout="topleft"
- left_pad="10"
- name="role_delete"
- width="120" />
- </panel>
- <panel
- border="false"
- height="303"
- label="ABILITIES"
- layout="topleft"
- left="0"
- right="-1"
- help_topic="roles_actions_tab"
- name="actions_sub_tab"
- class="panel_group_actions_subtab"
- tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
- width="310">
- <panel.string
- name="help_text">
- Abilities allow Members in Roles to do specific
-things in this group. There&apos;s a broad variety of Abilities.
- </panel.string>
- <panel.string
- name="power_folder_icon" translate="false">
- Inv_FolderClosed
- </panel.string>
- <panel.string
- name="power_all_have_icon" translate="false">
- Checkbox_On
- </panel.string>
- <panel.string
- name="power_partial_icon" translate="false">
- Checkbox_Off
- </panel.string>
- <filter_editor
- layout="topleft"
- top="5"
- left="5"
- right="-5"
- height="22"
- search_button_visible="false"
- follows="left|top|right"
- label="Filter Abilities"
- name="filter_input" />
- <scroll_list
- column_padding="0"
- draw_stripes="true"
- height="200"
- follows="left|top|right"
- layout="topleft"
- left="0"
- right="-1"
- name="action_list"
- search_column="2"
- tool_tip="Select an Ability to view more details"
- top_pad="5"
- width="300">
- <scroll_list.columns
- label=""
- name="icon"
- width="2" />
- <scroll_list.columns
- label=""
- name="checkbox"
- width="20" />
- <scroll_list.columns
- label=""
- name="action"
- width="270" />
- </scroll_list>
- </panel>
- </tab_container>
+ <panel.string
+ name="help_text">
+ Roles have a title and an allowed list of Abilities
+ that Members can perform. Members can belong to
+ one or more Roles. A group can have up to 10 Roles,
+ including the Everyone and Owner Roles.
+ </panel.string>
+ <panel.string
+ name="cant_delete_role">
+ The &apos;Everyone&apos; and &apos;Owners&apos; Roles are special and can't be deleted.
+ </panel.string>
+ <panel.string
+ name="power_folder_icon" translate="false">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string
+ name="power_all_have_icon" translate="false">
+ Checkbox_On
+ </panel.string>
+ <panel.string
+ name="power_partial_icon" translate="false">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor
+ layout="topleft"
+ top="5"
+ left="5"
+ right="-5"
+ height="22"
+ search_button_visible="false"
+ follows="left|top|right"
+ label="Filter Roles"
+ name="filter_input" />
+ <scroll_list
+ column_padding="0"
+ draw_heading="true"
+ draw_stripes="false"
+ heading_height="23"
+ height="132"
+ layout="topleft"
+ search_column="1"
+ left="0"
+ follows="left|top|right"
+ right="-1"
+ name="role_list"
+ top_pad="2"
+ width="310">
+ <scroll_list.columns
+ label="Role"
+ name="name"
+ relative_width="0.45" />
+ <scroll_list.columns
+ label="Title"
+ name="title"
+ relative_width="0.45" />
+ <scroll_list.columns
+ label="#"
+ name="members"
+ relative_width="0.15" />
+ </scroll_list>
+ <button
+ follows="top|left"
+ height="23"
+ label="New Role"
+ layout="topleft"
+ left="0"
+ name="role_create"
+ width="120" />
+ <button
+ height="23"
+ follows="top|left"
+ label="Delete Role"
+ layout="topleft"
+ left_pad="10"
+ name="role_delete"
+ width="120" />
+ </panel>
<panel
- height="350"
- background_visible="false"
- bg_alpha_color="FloaterUnfocusBorderColor"
+ border="false"
+ height="303"
+ label="ABILITIES"
layout="topleft"
- follows="top|left|right"
left="0"
right="-1"
- width="313"
- mouse_opaque="false"
- name="members_footer"
- top="325"
- visible="false">
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- top="8"
- text_color="EmphasisColor"
- name="static"
- width="300">
- Assigned Roles
- </text>
- <scroll_list
- draw_stripes="true"
- follows="left|top|right"
- height="150"
- layout="topleft"
- left="0"
- right="-1"
- name="member_assigned_roles"
- top_pad="0">
- <scroll_list.columns
- label=""
- name="checkbox"
- width="20" />
- <scroll_list.columns
- label=""
- name="role"
- width="270" />
- </scroll_list>
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- top_pad="5"
- text_color="EmphasisColor"
- name="static2"
- width="285">
- Allowed Abilities
- </text>
- <scroll_list
- draw_stripes="true"
- follows="left|top|right"
- height="150"
- layout="topleft"
- left="0"
- right="-1"
- name="member_allowed_actions"
- search_column="2"
- tool_tip="For details of each allowed ability see the abilities tab"
- top_pad="0">
- <scroll_list.columns
- label=""
- name="icon"
- width="2" />
- <scroll_list.columns
- label=""
- name="checkbox"
- width="20" />
- <scroll_list.columns
- label=""
- name="action"
- width="270" />
- </scroll_list>
+ help_topic="roles_actions_tab"
+ name="actions_sub_tab"
+ class="panel_group_actions_subtab"
+ tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
+ width="310">
+ <panel.string
+ name="help_text">
+ Abilities allow Members in Roles to do specific
+ things in this group. There&apos;s a broad variety of Abilities.
+ </panel.string>
+ <panel.string
+ name="power_folder_icon" translate="false">
+ Inv_FolderClosed
+ </panel.string>
+ <panel.string
+ name="power_all_have_icon" translate="false">
+ Checkbox_On
+ </panel.string>
+ <panel.string
+ name="power_partial_icon" translate="false">
+ Checkbox_Off
+ </panel.string>
+ <filter_editor
+ layout="topleft"
+ top="5"
+ left="5"
+ right="-5"
+ height="22"
+ search_button_visible="false"
+ follows="left|top|right"
+ label="Filter Abilities"
+ name="filter_input" />
+ <scroll_list
+ column_padding="0"
+ draw_stripes="true"
+ height="200"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ right="-1"
+ name="action_list"
+ search_column="2"
+ tool_tip="Select an Ability to view more details"
+ top_pad="5"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="action"
+ width="270" />
+ </scroll_list>
</panel>
<panel
- height="550"
- background_visible="false"
- bg_alpha_color="FloaterUnfocusBorderColor"
+ border="false"
+ height="303"
+ label="BANNED RESIDENTS"
layout="topleft"
- follows="top|left|right"
left="0"
right="-1"
- width="313"
- mouse_opaque="false"
- name="roles_footer"
- top_delta="0"
- top="209"
- visible="false">
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- top="5"
- name="static"
- width="300">
- Role Name
- </text>
- <line_editor
- type="string"
- height="20"
- layout="topleft"
- left="0"
- follows="left|top|right"
- right="-1"
- max_length_bytes="20"
- name="role_name"
- top_pad="0"
- width="300">
- </line_editor>
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- name="static3"
- top_pad="5"
- width="300">
- Role Title
- </text>
- <line_editor
- type="string"
- height="20"
- layout="topleft"
- left="0"
- follows="left|top|right"
- right="-1"
- max_length_bytes="20"
- name="role_title"
- top_pad="0"
- width="300">
- </line_editor>
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- name="static2"
- top_pad="5"
- width="200">
- Description
- </text>
- <text_editor
- type="string"
- layout="topleft"
- left="0"
- follows="left|top|right"
- right="-1"
- max_length="295"
- height="35"
- name="role_description"
- top_pad="0"
- width="300"
- word_wrap="true">
- </text_editor>
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- text_color="EmphasisColor"
- name="static4"
- top_pad="5"
- width="300">
- Assigned Members
- </text>
- <name_list
- draw_stripes="true"
- height="128"
- layout="topleft"
- left="0"
- follows="left|top|right"
- right="-1"
- name="role_assigned_members"
- top_pad="0"
- width="300" />
- <check_box
- height="15"
- label="Reveal members"
- left="5"
- layout="topleft"
- name="role_visible_in_list"
- tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."
- top_pad="4"
- width="300" />
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- text_color="EmphasisColor"
- name="static5"
- top_pad="2"
- width="300">
- Allowed Abilities
- </text>
- <scroll_list
- draw_stripes="true"
- height="140"
- layout="topleft"
- left="0"
- follows="left|top|right"
- right="-1"
- name="role_allowed_actions"
- search_column="2"
- tool_tip="For details of each allowed ability see the abilities tab"
- top_pad="0"
- width="300">
- <scroll_list.columns
- label=""
- name="icon"
- width="2" />
- <scroll_list.columns
- label=""
- name="checkbox"
- width="20" />
- <scroll_list.columns
- label=""
- name="action"
- width="270" />
- </scroll_list>
+ help_topic="roles_banlist_tab"
+ name="banlist_sub_tab"
+ class="panel_group_banlist_subtab"
+ tool_tip="View the banned residents from this group."
+ width="310">
+ <panel.string
+ name="help_text">
+ Any resident on the ban list will be unable to join the group.
+ </panel.string>
+ <panel.string
+ name="ban_count_template">
+ Ban count: [COUNT]/[LIMIT]
+ </panel.string>
+ <name_list
+ column_padding="0"
+ draw_heading="true"
+ height="400"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ right="-1"
+ multi_select="true"
+ name="ban_list"
+ short_names="false"
+ top_pad="5">
+ <name_list.columns
+ label="Resident"
+ name="name"
+ font.name="SANSSERIF_SMALL"
+ font.style="NORMAL"
+ relative_width="0.7" />
+ <name_list.columns
+ label="Date Banned"
+ name="ban_date"
+ relative_width="0.3" />
+ </name_list>
+ <button
+ follows="top|left"
+ height="23"
+ label="Ban Resident(s)"
+ layout="topleft"
+ left="3"
+ name="ban_create"
+ tool_tip="Ban residents from your group"
+ width="120" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Remove Ban(s)"
+ layout="topleft"
+ left_pad="5"
+ name="ban_delete"
+ tool_tip="Unban selected residents from your group"
+ width="120" />
+ <button
+ follows="top|left"
+ height="23"
+ width="23"
+ image_overlay="Refresh_Off"
+ layout="topleft"
+ left_pad="5"
+ name="ban_refresh"
+ tool_tip="Refresh the ban list"
+ />
+ <text
+ type="string"
+ height="18"
+ left_pad="5"
+ follows="top|left"
+ layout="topleft"
+ name="ban_count"
+ width="100">
+ </text>
</panel>
- <panel
- height="424"
- background_visible="false"
- bg_alpha_color="FloaterUnfocusBorderColor"
+ </tab_container>
+ <panel
+ height="350"
+ background_visible="false"
+ bg_alpha_color="FloaterUnfocusBorderColor"
+ layout="topleft"
+ follows="top|left|right"
+ left="0"
+ right="-1"
+ width="313"
+ mouse_opaque="false"
+ name="members_footer"
+ top="325"
+ visible="false">
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ top="8"
+ text_color="EmphasisColor"
+ name="static"
+ width="300">
+ Assigned Roles
+ </text>
+ <scroll_list
+ draw_stripes="true"
+ follows="left|top|right"
+ height="150"
layout="topleft"
- follows="top|left|right"
left="0"
right="-1"
- width="313"
- mouse_opaque="false"
- name="actions_footer"
- top_delta="0"
- top="255"
- visible="false">
- <text_editor
- bg_readonly_color="Transparent"
- text_readonly_color="EmphasisColor"
- font="SansSerifSmall"
- type="string"
- enabled="false"
- halign="left"
- layout="topleft"
+ name="member_assigned_roles"
+ top_pad="0">
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="role"
+ width="270" />
+ </scroll_list>
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ top_pad="5"
+ text_color="EmphasisColor"
+ name="static2"
+ width="285">
+ Allowed Abilities
+ </text>
+ <scroll_list
+ draw_stripes="true"
follows="left|top|right"
- left="0"
- right="-1"
- height="90"
- max_length="512"
- name="action_description"
- top="0"
- word_wrap="true">
- This Ability is &apos;Eject Members from this Group&apos;. Only an Owner can eject another Owner.
- </text_editor>
- <text
+ height="150"
+ layout="topleft"
+ left="0"
+ right="-1"
+ name="member_allowed_actions"
+ search_column="2"
+ tool_tip="For details of each allowed ability see the abilities tab"
+ top_pad="0">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="action"
+ width="270" />
+ </scroll_list>
+ </panel>
+ <panel
+ height="550"
+ background_visible="false"
+ bg_alpha_color="FloaterUnfocusBorderColor"
+ layout="topleft"
+ follows="top|left|right"
+ left="0"
+ right="-1"
+ width="313"
+ mouse_opaque="false"
+ name="roles_footer"
+ top_delta="0"
+ top="209"
+ visible="false">
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ top="5"
+ name="static"
+ width="300">
+ Role Name
+ </text>
+ <line_editor
+ type="string"
+ height="20"
+ layout="topleft"
+ left="0"
+ follows="left|top|right"
+ right="-1"
+ max_length_bytes="20"
+ name="role_name"
+ top_pad="0"
+ width="300">
+ </line_editor>
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ name="static3"
+ top_pad="5"
+ width="300">
+ Role Title
+ </text>
+ <line_editor
+ type="string"
+ height="20"
+ layout="topleft"
+ left="0"
+ follows="left|top|right"
+ right="-1"
+ max_length_bytes="20"
+ name="role_title"
+ top_pad="0"
+ width="300">
+ </line_editor>
+ <text
type="string"
height="16"
layout="topleft"
follows="left|top"
left="5"
name="static2"
- top_pad="1"
- width="300">
- Roles with this ability
- </text>
- <scroll_list
- height="172"
- layout="topleft"
- follows="left|top|right"
- left="5"
- right="-1"
- name="action_roles"
- top_pad="0"
- width="300" />
- <text
- type="string"
- height="16"
- layout="topleft"
- follows="left|top"
- left="5"
- name="static3"
top_pad="5"
- width="300">
- Members with this ability
- </text>
- <name_list
- height="122"
- follows="left|top|right"
- layout="topleft"
- left="5"
- right="-1"
- name="action_members"
- top_pad="0"
- width="300" />
- </panel>
+ width="200">
+ Description
+ </text>
+ <text_editor
+ type="string"
+ layout="topleft"
+ left="0"
+ follows="left|top|right"
+ right="-1"
+ max_length="295"
+ height="35"
+ name="role_description"
+ top_pad="0"
+ width="300"
+ word_wrap="true">
+ </text_editor>
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ text_color="EmphasisColor"
+ name="static4"
+ top_pad="5"
+ width="300">
+ Assigned Members
+ </text>
+ <name_list
+ draw_stripes="true"
+ height="128"
+ layout="topleft"
+ left="0"
+ follows="left|top|right"
+ right="-1"
+ name="role_assigned_members"
+ top_pad="0"
+ width="300" />
+ <check_box
+ height="15"
+ label="Reveal members"
+ left="5"
+ layout="topleft"
+ name="role_visible_in_list"
+ tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."
+ top_pad="4"
+ width="300" />
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ text_color="EmphasisColor"
+ name="static5"
+ top_pad="2"
+ width="300">
+ Allowed Abilities
+ </text>
+ <scroll_list
+ draw_stripes="true"
+ height="140"
+ layout="topleft"
+ left="0"
+ follows="left|top|right"
+ right="-1"
+ name="role_allowed_actions"
+ search_column="2"
+ tool_tip="For details of each allowed ability see the abilities tab"
+ top_pad="0"
+ width="300">
+ <scroll_list.columns
+ label=""
+ name="icon"
+ width="2" />
+ <scroll_list.columns
+ label=""
+ name="checkbox"
+ width="20" />
+ <scroll_list.columns
+ label=""
+ name="action"
+ width="270" />
+ </scroll_list>
+ </panel>
+ <panel
+ height="424"
+ background_visible="false"
+ bg_alpha_color="FloaterUnfocusBorderColor"
+ layout="topleft"
+ follows="top|left|right"
+ left="0"
+ right="-1"
+ width="313"
+ mouse_opaque="false"
+ name="actions_footer"
+ top_delta="0"
+ top="255"
+ visible="false">
+ <text_editor
+ bg_readonly_color="Transparent"
+ text_readonly_color="EmphasisColor"
+ font="SansSerifSmall"
+ type="string"
+ enabled="false"
+ halign="left"
+ layout="topleft"
+ follows="left|top|right"
+ left="0"
+ right="-1"
+ height="90"
+ max_length="512"
+ name="action_description"
+ top="0"
+ word_wrap="true">
+ This Ability is &apos;Eject Members from this Group&apos;. Only an Owner can eject another Owner.
+ </text_editor>
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ name="static2"
+ top_pad="1"
+ width="300">
+ Roles with this ability
+ </text>
+ <scroll_list
+ height="172"
+ layout="topleft"
+ follows="left|top|right"
+ left="5"
+ right="-1"
+ name="action_roles"
+ top_pad="0"
+ width="300" />
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="5"
+ name="static3"
+ top_pad="5"
+ width="300">
+ Members with this ability
+ </text>
+ <name_list
+ height="122"
+ follows="left|top|right"
+ layout="topleft"
+ left="5"
+ right="-1"
+ name="action_members"
+ top_pad="0"
+ width="300" />
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index 308acf0c0c..30239d6d01 100755
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -220,7 +220,7 @@
<layout_stack
border_size="0"
clip="false"
- follows="left|top|right"
+ follows="left|top"
height="50"
layout="topleft"
mouse_opaque="false"
@@ -251,10 +251,10 @@
</layout_panel>
<layout_panel
follows="left|right"
- height="60"
+ height="50"
layout="topleft"
min_height="50"
- min_width="60"
+ min_width="50"
mouse_opaque="false"
name="for_sale_panel"
top="0"
@@ -264,7 +264,7 @@
height="50"
image_name="ForSale_Badge"
layout="topleft"
- left="10"
+ left="0"
name="icon_for_sale"
top="0"
width="50" />
@@ -762,11 +762,19 @@
top_pad="5"
value="Rating:"
width="80" />
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="0"
+ name="estate_rating_icon"
+ width="18" />
<text
follows="left|top|right"
height="15"
layout="topleft"
- left_pad="0"
+ left_pad="10"
name="estate_rating"
top_delta="0"
width="187" />
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 78743d26bb..d7ffb73dda 100755
--- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -47,7 +47,7 @@
<check_box
height="16"
enabled="false"
- label="Show me in Search results"
+ label="Show my profile info in Search results"
layout="topleft"
left="30"
name="online_searchresults"
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
index c5b0be0616..26cac06648 100755
--- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
@@ -47,7 +47,20 @@
text_color="White"
top="4"
value="..."
- width="330" />
+ width="290" />
+ <text
+ follows="right"
+ height="20"
+ layout="topleft"
+ left_pad="5"
+ right="-20"
+ parse_urls="false"
+ use_ellipses="true"
+ name="timestamp"
+ text_color="White"
+ top="4"
+ value="..."
+ width="45" />
<button
follows="right"
height="20"
diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml
index df38a7c9c8..c2e7c706d6 100755
--- a/indra/newview/skins/default/xui/en/role_actions.xml
+++ b/indra/newview/skins/default/xui/en/role_actions.xml
@@ -9,7 +9,10 @@
<action description="Eject Members from this Group"
longdescription="Eject Members from this Group using the &apos;Eject&apos; button in the Roles section &gt; Members tab. An Owner can eject anyone except another Owner. If you&apos;re not an Owner, a Member can be ejected from a group if, and only if, they&apos;re only in the Everyone Role, and NO other Roles. To remove Members from Roles, you need to have the &apos;Remove Members from Roles&apos; Ability."
name="member eject" value="2" />
- <action
+ <action description="Manage ban list"
+ longdescription="Allows the group member to ban / un-ban Residents from this group."
+ name="allow ban" value="51" />
+ <action
description="Toggle &apos;Open Enrollment&apos; and change &apos;Enrollment fee&apos;"
longdescription="Toggle &apos;Open Enrollment&apos; to let new Members join without an invitation, and change the &apos;Enrollment fee&apos; in the General section."
name="member options" value="3" />
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1bf1ee930c..8ecc5090c7 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -3774,6 +3774,7 @@ Abuse Report</string>
<string name="LocalEstimateUSD">US$ [AMOUNT]</string>
<!-- Group Profile roles and powers -->
+ <string name="Group Ban">Group Ban</string>
<string name="Membership">Membership</string>
<string name="Roles">Roles</string>
<string name="Group Identity">Group Identity</string>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml
index c162130af6..fe312e3587 100755
--- a/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Localizaciones, imágenes, web, historial de búsqueda)
</text>
- <check_box label="Mostrarme en los resultados de la búsqueda" name="online_searchresults"/>
+ <check_box label="Mostrarme información de perfil en los resultados de la búsqueda" name="online_searchresults"/>
<check_box label="Sólo saben si estoy conectado mis amigos y grupos" name="online_visibility"/>
<check_box label="Sólo pueden llamarme o mandarme un MI mis amigos y grupos" name="voice_call_friends_only_check"/>
<check_box label="Desconectar el micrófono cuando finalicen las llamadas" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml
index cf1a374da6..a89676d119 100755
--- a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml
@@ -7,13 +7,13 @@
<text name="cache_size_label_l">
(endroits, images, web, historique des recherches)
</text>
- <check_box label="M&apos;afficher dans les résultats de recherche" name="online_searchresults"/>
+ <check_box label="Afficher mon profil d&apos;infos dans les résultats de recherche" name="online_searchresults"/>
<check_box label="Seuls mes amis et groupes voient quand je suis en ligne" name="online_visibility"/>
<check_box label="Seuls mes amis et groupes peuvent m&apos;appeler ou m&apos;envoyer un IM" name="voice_call_friends_only_check"/>
<check_box label="Fermer le micro à la fin d&apos;un appel" name="auto_disengage_mic_check"/>
<check_box label="Afficher mes repères favoris à la connexion (liste déroulante Lieu de départ)" name="favorites_on_login_check"/>
<text name="Logs:">
- Journaux de chat :
+ Journaux de chat :
</text>
<check_box label="Sauvegarder les chats près de moi sur mon ordinateur" name="log_nearby_chat"/>
<check_box label="Sauvegarder les IM sur mon ordinateur" name="log_instant_messages"/>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml
index 41e7a59139..241ed8f162 100755
--- a/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Luoghi, immagini, web, cronologia ricerche)
</text>
- <check_box label="Mostrami nei risultati della ricerca" name="online_searchresults"/>
+ <check_box label="Mostra il mio profilo info nei risultati di ricerca" name="online_searchresults"/>
<check_box label="Solo amici e gruppi mi vedono online" name="online_visibility"/>
<check_box label="Solo amici e gruppi possono chiamarmi o mandarmi IM" name="voice_call_friends_only_check"/>
<check_box label="Spegnere il microfono alla chiusura delle chiamate" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml
index 420bbed572..3787f390e4 100755
--- a/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(位置、画像、web、検索履歴)
</text>
- <check_box label="検索結果に表示" name="online_searchresults"/>
+ <check_box label="検索結果に自分のプロフィール情報を表示する" name="online_searchresults"/>
<check_box label="私のオンライン状態を確認できるのは、フレンドとグループだけ" name="online_visibility"/>
<check_box label="フレンドとグループ以外からはコールと IM を受信しない" name="voice_call_friends_only_check"/>
<check_box label="コールが終了したら自動的にマイクのスイッチを切る" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml
index 5af2fed142..30b64bc977 100755
--- a/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Miejsca, obrazy, przeglądarka internetowa, wyszukiwarka historii)
</text>
- <check_box label="Pokaż mój profil w wynikach wyszukiwarki" name="online_searchresults"/>
+ <check_box label="Pokaż mój informacje profilu w wynikach wyszukiwania" name="online_searchresults"/>
<check_box label="Mój status online jest dostępny tylko dla znajomych i grup do których należę" name="online_visibility"/>
<check_box label="Możliwość wysyłania wiadomości prywatnej (IM) oraz rozmowy głosowej tylko dla &#10;znajomych i grup do których należę" name="voice_call_friends_only_check" top_pad="15"/>
<check_box label="Wyłącz mikrofon po zakończeniu rozmowy głosowej" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
index d7fb585e35..8ca05c948a 100755
--- a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Locações, imagens, web, histórico de busca)
</text>
- <check_box label="Mostrar nos resultados de busca" name="online_searchresults"/>
+ <check_box label="Mostrar meu perfil info em resultados de busca" name="online_searchresults"/>
<check_box label="Apenas amigos e grupos sabem que estou online" name="online_visibility"/>
<check_box label="Apenas amigos e grupos podem me chamar ou enviar MI" name="voice_call_friends_only_check"/>
<check_box label="Desligar o microfone quando terminar chamadas" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml
index 20bb839eed..ed6bed439c 100755
--- a/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Места, картинки, страницы, журнал поиска)
</text>
- <check_box label="Показывать меня в результатах поиска" name="online_searchresults"/>
+ <check_box label="Показывать информацию моего профиля в результатах поиска" name="online_searchresults"/>
<check_box label="Только друзья и группы видят, когда я на связи" name="online_visibility"/>
<check_box label="Только друзья и группы могут звонить мне и отправлять IM" name="voice_call_friends_only_check"/>
<check_box label="Отключать микрофон по окончании разговора" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml
index 9111594979..285670a6ac 100755
--- a/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(Konumlar, görüntüler, web, arama geçmişi)
</text>
- <check_box label="Arama sonuçlarında beni göster" name="online_searchresults"/>
+ <check_box label="Arama sonuçlarında profil bilgilerini göster" name="online_searchresults"/>
<check_box label="Çevrimiçi olduğumu sadece arkadaşlar ve gruplar bilsin" name="online_visibility"/>
<check_box label="Sadece arkadaşlar ve gruplar beni arasın veya Aİ göndersin" name="voice_call_friends_only_check"/>
<check_box label="Aramaları sonlandırırken mikrofonu kapat" name="auto_disengage_mic_check"/>
diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml
index 07fdfd87e3..d768cacb94 100755
--- a/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml
@@ -7,7 +7,7 @@
<text name="cache_size_label_l">
(位置、圖像、網頁、搜尋的歷史紀錄)
</text>
- <check_box label="將我顯示在搜尋的結果中" name="online_searchresults"/>
+ <check_box label="顯示在搜索結果我的個人資料信息" name="online_searchresults"/>
<check_box label="只有我的朋友和群組知道我上線" name="online_visibility"/>
<check_box label="只有我的朋友和群組可以 IM 或與我通話。" name="voice_call_friends_only_check"/>
<check_box label="當通話結束時關閉麥克風" name="auto_disengage_mic_check"/>