summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt8
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/llagentcamera.cpp6
-rw-r--r--indra/newview/llagentcamera.h1
-rw-r--r--indra/newview/llappviewer.cpp3
-rw-r--r--indra/newview/llfloaterexperiences.cpp8
-rw-r--r--indra/newview/llfloatergesture.cpp53
-rw-r--r--indra/newview/llfloatergesture.h3
-rw-r--r--indra/newview/llfloatermodelpreview.cpp9
-rw-r--r--indra/newview/llfloaterpreference.cpp70
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llfloaterproperties.cpp2
-rw-r--r--indra/newview/llhudeffectbeam.cpp12
-rw-r--r--indra/newview/llhudeffectlookat.cpp20
-rw-r--r--indra/newview/llhudeffectpointat.cpp20
-rw-r--r--indra/newview/llhudeffecttrail.cpp12
-rw-r--r--indra/newview/llimprocessing.cpp55
-rw-r--r--indra/newview/llinventorybridge.cpp2
-rw-r--r--indra/newview/llinventoryfilter.cpp74
-rw-r--r--indra/newview/llinventoryfilter.h3
-rw-r--r--indra/newview/llnotificationlistitem.cpp1
-rw-r--r--indra/newview/llselectmgr.cpp107
-rw-r--r--indra/newview/llselectmgr.h19
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp142
-rw-r--r--indra/newview/llsidepaneliteminfo.h15
-rw-r--r--indra/newview/llsidepaneltaskinfo.cpp63
-rw-r--r--indra/newview/llsidepaneltaskinfo.h1
-rw-r--r--indra/newview/llstartup.cpp18
-rw-r--r--indra/newview/llstatusbar.cpp35
-rw-r--r--indra/newview/llstatusbar.h3
-rw-r--r--indra/newview/lltexturecache.cpp95
-rw-r--r--indra/newview/lltexturecache.h3
-rw-r--r--indra/newview/lltoolgrab.cpp11
-rw-r--r--indra/newview/lltoolpie.cpp32
-rw-r--r--indra/newview/llviewerdisplay.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp10
-rw-r--r--indra/newview/llviewermessage.cpp237
-rw-r--r--indra/newview/llviewermessage.h3
-rw-r--r--indra/newview/llviewerobject.cpp261
-rw-r--r--indra/newview/llviewerobject.h14
-rw-r--r--indra/newview/llviewerwindow.cpp45
-rw-r--r--indra/newview/llviewerwindow.h5
-rw-r--r--indra/newview/llvoavatar.cpp24
-rw-r--r--indra/newview/llvoiceclient.cpp23
-rw-r--r--indra/newview/llvoiceclient.h6
-rw-r--r--indra/newview/skins/default/xui/en/menu_gesture_gear.xml10
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml54
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml26
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml8
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
-rw-r--r--indra/newview/skins/default/xui/en/teleport_strings.xml3
-rw-r--r--indra/newview/skins/default/xui/ru/notifications.xml4
53 files changed, 1208 insertions, 463 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b8789da66b..694e89ab99 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1377,8 +1377,12 @@ if (DARWIN)
PROPERTIES
COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}"
# BugsplatMac is a module, imported with @import. That language feature
- # demands these switches.
- COMPILE_FLAGS "-fmodules -fcxx-modules"
+ # demands these -f switches.
+ # Xcode 10.2 requires that Objective-C++ headers declare nullability of
+ # pointer variables. As of 2019-06-26, the BugsplatMac version we're using
+ # does not yet do so in its own header files. This -W flag prevents fatal
+ # warnings.
+ COMPILE_FLAGS "-fmodules -fcxx-modules -Wno-nullability-completeness"
)
find_library(AGL_LIBRARY AGL)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 49601ae98f..b4919c6e48 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11219,6 +11219,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>BasicUITooltips</key>
+ <map>
+ <key>Comment</key>
+ <string>Show tooltips for various 2D UI elements like buttons or checkboxes, won't supress tooltips like drag'n'drop, inworld, links or media</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>ShowHoverTips</key>
<map>
<key>Comment</key>
@@ -13133,6 +13144,17 @@
<key>Value</key>
<real>3</real>
</map>
+ <key>HUDScaleFactor</key>
+ <map>
+ <key>Comment</key>
+ <string>Scale of HUD attachments</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0</real>
+ </map>
<key>UIScaleFactor</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 92a3026096..fd8797481d 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -807,6 +807,12 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction)
startCameraAnimation();
}
+F32 LLAgentCamera::getAgentHUDTargetZoom()
+{
+ static LLCachedControl<F32> hud_scale_factor(gSavedSettings, "HUDScaleFactor");
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ return (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) ? hud_scale_factor*gAgentCamera.mHUDTargetZoom : hud_scale_factor;
+}
//-----------------------------------------------------------------------------
// cameraOrbitAround()
diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h
index d087de1e2f..a4bc8434b0 100644
--- a/indra/newview/llagentcamera.h
+++ b/indra/newview/llagentcamera.h
@@ -266,6 +266,7 @@ public:
F32 getCameraZoomFraction(); // Get camera zoom as fraction of minimum and maximum zoom
void setCameraZoomFraction(F32 fraction); // Set camera zoom as fraction of minimum and maximum zoom
F32 calcCameraFOVZoomFactor();
+ F32 getAgentHUDTargetZoom();
//--------------------------------------------------------------------
// Pan
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c8dcbb87c1..12a459b2b8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -2145,6 +2145,9 @@ void watchdog_llerrs_callback(const std::string &error_string)
{
gLLErrorActivated = true;
+ gDebugInfo["FatalMessage"] = error_string;
+ LLAppViewer::instance()->writeDebugInfo();
+
#ifdef LL_WINDOWS
RaiseException(0,0,0,0);
#else
diff --git a/indra/newview/llfloaterexperiences.cpp b/indra/newview/llfloaterexperiences.cpp
index fdc1b47334..184e39402a 100644
--- a/indra/newview/llfloaterexperiences.cpp
+++ b/indra/newview/llfloaterexperiences.cpp
@@ -74,10 +74,6 @@ BOOL LLFloaterExperiences::postBuild()
getChild<LLTabContainer>("xp_tabs")->addTabPanel(new LLPanelExperienceLog());
resizeToTabs();
-
- LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
- boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
-
return TRUE;
}
@@ -163,6 +159,10 @@ void LLFloaterExperiences::refreshContents()
void LLFloaterExperiences::onOpen( const LLSD& key )
{
+ LLEventPumps::instance().obtain("experience_permission").stopListening("LLFloaterExperiences");
+ LLEventPumps::instance().obtain("experience_permission").listen("LLFloaterExperiences",
+ boost::bind(&LLFloaterExperiences::updatePermissions, this, _1));
+
LLViewerRegion* region = gAgent.getRegion();
if(region)
{
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index b840d37c4d..e778e8eb9e 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -41,6 +41,7 @@
#include "llkeyboard.h"
#include "llmenugl.h"
#include "llmultigesture.h"
+#include "llnotificationsutil.h"
#include "llpreviewgesture.h"
#include "llscrolllistctrl.h"
#include "lltrans.h"
@@ -125,6 +126,7 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key)
mCommitCallbackRegistrar.add("Gesture.Action.ShowPreview", boost::bind(&LLFloaterGesture::onClickEdit, this));
mCommitCallbackRegistrar.add("Gesture.Action.CopyPaste", boost::bind(&LLFloaterGesture::onCopyPasteAction, this, _2));
mCommitCallbackRegistrar.add("Gesture.Action.SaveToCOF", boost::bind(&LLFloaterGesture::addToCurrentOutFit, this));
+ mCommitCallbackRegistrar.add("Gesture.Action.Rename", boost::bind(&LLFloaterGesture::onRenameSelected, this));
mEnableCallbackRegistrar.add("Gesture.EnableAction", boost::bind(&LLFloaterGesture::isActionEnabled, this, _2));
}
@@ -430,6 +432,19 @@ bool LLFloaterGesture::isActionEnabled(const LLSD& command)
{
return mGestureList->getAllSelected().size() == 1;
}
+ else if ("rename_gesture" == command_name)
+ {
+ if (mGestureList->getAllSelected().size() == 1)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(mGestureList->getCurrentID());
+
+ if (item && item->getPermissions().allowModifyBy(gAgentID))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
return true;
}
@@ -514,6 +529,44 @@ void LLFloaterGesture::onActivateBtnClick()
}
}
+void LLFloaterGesture::onRenameSelected()
+{
+ LLViewerInventoryItem* gesture = gInventory.getItem(mGestureList->getCurrentID());
+ if (!gesture)
+ {
+ return;
+ }
+
+ LLSD args;
+ args["NAME"] = gesture->getName();
+
+ LLSD payload;
+ payload["gesture_id"] = mGestureList->getCurrentID();
+
+ LLNotificationsUtil::add("RenameGesture", args, payload, boost::bind(onGestureRename, _1, _2));
+
+}
+
+void LLFloaterGesture::onGestureRename(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0) return; // canceled
+
+ std::string new_name = response["new_name"].asString();
+ LLInventoryObject::correctInventoryName(new_name);
+ if (!new_name.empty())
+ {
+ LLUUID item_id = notification["payload"]["gesture_id"].asUUID();
+ LLViewerInventoryItem* gesture = gInventory.getItem(item_id);
+ if (gesture && (gesture->getName() != new_name))
+ {
+ LLSD updates;
+ updates["name"] = new_name;
+ update_inventory_item(item_id, updates, NULL);
+ }
+ }
+}
+
void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
{
std::string command_name = command.asString();
diff --git a/indra/newview/llfloatergesture.h b/indra/newview/llfloatergesture.h
index 8efb3e6461..1d702c6704 100644
--- a/indra/newview/llfloatergesture.h
+++ b/indra/newview/llfloatergesture.h
@@ -95,6 +95,9 @@ private:
void onCommitList();
void onCopyPasteAction(const LLSD& command);
void onDeleteSelected();
+ void onRenameSelected();
+
+ static void onGestureRename(const LLSD& notification, const LLSD& response);
LLUUID mSelectedID;
LLUUID mGestureFolderID;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index cb58cfdd0a..7705c1a76f 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -3014,6 +3014,15 @@ void LLModelPreview::updateStatusMessages()
{
mFMP->childDisable("ok_btn");
}
+
+ if (mModelNoErrors && mLodsWithParsingError.empty())
+ {
+ mFMP->childEnable("calculate_btn");
+ }
+ else
+ {
+ mFMP->childDisable("calculate_btn");
+ }
//add up physics triangles etc
S32 phys_tris = 0;
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 64961fc99c..27a597a631 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -124,7 +124,9 @@ char const* const VISIBILITY_DEFAULT = "default";
char const* const VISIBILITY_HIDDEN = "hidden";
//control value for middle mouse as talk2push button
-const static std::string MIDDLE_MOUSE_CV = "MiddleMouse";
+const static std::string MIDDLE_MOUSE_CV = "MiddleMouse"; // for voice client and redability
+const static std::string MOUSE_BUTTON_4_CV = "MouseButton4";
+const static std::string MOUSE_BUTTON_5_CV = "MouseButton5";
/// This must equal the maximum value set for the IndirectMaxComplexity slider in panel_preferences_graphics1.xml
static const U32 INDIRECT_MAX_ARC_OFF = 101; // all the way to the right == disabled
@@ -168,6 +170,7 @@ public:
void setParent(LLFloaterPreference* parent) { mParent = parent; }
BOOL handleKeyHere(KEY key, MASK mask);
+ BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
static void onCancel(void* user_data);
private:
@@ -211,6 +214,25 @@ BOOL LLVoiceSetKeyDialog::handleKeyHere(KEY key, MASK mask)
return result;
}
+BOOL LLVoiceSetKeyDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
+{
+ BOOL result = FALSE;
+ if (down
+ && (clicktype == LLMouseHandler::CLICK_MIDDLE || clicktype == LLMouseHandler::CLICK_BUTTON4 || clicktype == LLMouseHandler::CLICK_BUTTON5)
+ && mask == 0)
+ {
+ mParent->setMouse(clicktype);
+ result = TRUE;
+ closeFloater();
+ }
+ else
+ {
+ result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
+ }
+
+ return result;
+}
+
//static
void LLVoiceSetKeyDialog::onCancel(void* user_data)
{
@@ -1694,6 +1716,41 @@ void LLFloaterPreference::setKey(KEY key)
getChild<LLUICtrl>("modifier_combo")->onCommit();
}
+void LLFloaterPreference::setMouse(LLMouseHandler::EClickType click)
+{
+ std::string bt_name;
+ std::string ctrl_value;
+ switch (click)
+ {
+ case LLMouseHandler::CLICK_MIDDLE:
+ bt_name = "middle_mouse";
+ ctrl_value = MIDDLE_MOUSE_CV;
+ break;
+ case LLMouseHandler::CLICK_BUTTON4:
+ bt_name = "button4_mouse";
+ ctrl_value = MOUSE_BUTTON_4_CV;
+ break;
+ case LLMouseHandler::CLICK_BUTTON5:
+ bt_name = "button5_mouse";
+ ctrl_value = MOUSE_BUTTON_5_CV;
+ break;
+ default:
+ break;
+ }
+
+ if (!ctrl_value.empty())
+ {
+ LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
+ // We are using text control names for readability and compatibility with voice
+ p2t_line_editor->setControlValue(ctrl_value);
+ LLPanel* advanced_preferences = dynamic_cast<LLPanel*>(p2t_line_editor->getParent());
+ if (advanced_preferences)
+ {
+ p2t_line_editor->setValue(advanced_preferences->getString(bt_name));
+ }
+ }
+}
+
void LLFloaterPreference::onClickSetMiddleMouse()
{
LLUICtrl* p2t_line_editor = getChild<LLUICtrl>("modifier_combo");
@@ -2431,10 +2488,19 @@ BOOL LLPanelPreference::postBuild()
if (hasChild("modifier_combo", TRUE))
{
//localizing if push2talk button is set to middle mouse
- if (MIDDLE_MOUSE_CV == getChild<LLUICtrl>("modifier_combo")->getValue().asString())
+ std::string modifier_value = getChild<LLUICtrl>("modifier_combo")->getValue().asString();
+ if (MIDDLE_MOUSE_CV == modifier_value)
{
getChild<LLUICtrl>("modifier_combo")->setValue(getString("middle_mouse"));
}
+ else if (MOUSE_BUTTON_4_CV == modifier_value)
+ {
+ getChild<LLUICtrl>("modifier_combo")->setValue(getString("button4_mouse"));
+ }
+ else if (MOUSE_BUTTON_5_CV == modifier_value)
+ {
+ getChild<LLUICtrl>("modifier_combo")->setValue(getString("button5_mouse"));
+ }
}
//////////////////////PanelSetup ///////////////////
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 1b8229ada6..d46f0deb7a 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -148,6 +148,7 @@ public:
void onSelectSkin();
void onClickSetKey();
void setKey(KEY key);
+ void setMouse(LLMouseHandler::EClickType click);
void onClickSetMiddleMouse();
void onClickSetSounds();
void onClickEnablePopup();
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index fbb7432f71..64ad40f419 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -85,7 +85,7 @@ public:
}
virtual void changed(U32 mask);
private:
- LLFloaterProperties* mFloater;
+ LLFloaterProperties* mFloater; // Not a handle because LLFloaterProperties is managing LLPropertiesObserver
};
void LLPropertiesObserver::changed(U32 mask)
diff --git a/indra/newview/llhudeffectbeam.cpp b/indra/newview/llhudeffectbeam.cpp
index 54e683e048..d1d83e6e03 100644
--- a/indra/newview/llhudeffectbeam.cpp
+++ b/indra/newview/llhudeffectbeam.cpp
@@ -90,7 +90,7 @@ void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
memset(packed_data, 0, 41);
if (mSourceObject)
{
- htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
}
if (mTargetObject)
@@ -104,11 +104,11 @@ void LLHUDEffectBeam::packData(LLMessageSystem *mesgsys)
if (mTargetObject)
{
- htonmemcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[17]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
- htonmemcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
+ htolememcpy(&(packed_data[17]), mTargetPos.mdV, MVT_LLVector3d, 24);
}
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
}
@@ -131,7 +131,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 41, blocknum);
- htonmemcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
+ htolememcpy(source_id.mData, packed_data, MVT_LLUUID, 16);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp)
@@ -143,7 +143,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
if (use_target_object)
{
- htonmemcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
+ htolememcpy(target_id.mData, &packed_data[17], MVT_LLUUID, 16);
LLViewerObject *objp = gObjectList.findObject(target_id);
if (objp)
@@ -153,7 +153,7 @@ void LLHUDEffectBeam::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
else
{
- htonmemcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
+ htolememcpy(new_target.mdV, &(packed_data[17]), MVT_LLVector3d, 24);
setTargetPos(new_target);
}
diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp
index f46152dcec..6898dce7b1 100644
--- a/indra/newview/llhudeffectlookat.cpp
+++ b/indra/newview/llhudeffectlookat.cpp
@@ -269,29 +269,29 @@ void LLHUDEffectLookAt::packData(LLMessageSystem *mesgsys)
if (mSourceObject)
{
- htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
}
else
{
- htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
}
// pack both target object and position
// position interpreted as offset if target object is non-null
if (mTargetObject)
{
- htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
- htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
}
- htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
+ htolememcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
U8 lookAtTypePacked = (U8)mTargetType;
- htonmemcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
+ htolememcpy(&(packed_data[LOOKAT_TYPE]), &lookAtTypePacked, MVT_U8, 1);
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
@@ -325,7 +325,7 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
- htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
+ htolememcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp && objp->isAvatar())
@@ -338,11 +338,11 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
return;
}
- htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
+ htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
objp = gObjectList.findObject(target_id);
- htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
+ htolememcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
if (objp)
{
@@ -358,7 +358,7 @@ void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
U8 lookAtTypeUnpacked = 0;
- htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
+ htolememcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1);
mTargetType = (ELookAtType)lookAtTypeUnpacked;
if (mTargetType == LOOKAT_TARGET_NONE)
diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp
index cc772c8f5c..ecf6d42d69 100644
--- a/indra/newview/llhudeffectpointat.cpp
+++ b/indra/newview/llhudeffectpointat.cpp
@@ -107,28 +107,28 @@ void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys)
if (mSourceObject)
{
- htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
}
else
{
- htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
}
// pack both target object and position
// position interpreted as offset if target object is non-null
if (mTargetObject)
{
- htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
- htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
+ htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
}
- htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
+ htolememcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
U8 pointAtTypePacked = (U8)mTargetType;
- htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
+ htolememcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
@@ -164,10 +164,10 @@ void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
- htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
- htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
- htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
- htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
+ htolememcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
+ htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
+ htolememcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
+ htolememcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp && objp->isAvatar())
diff --git a/indra/newview/llhudeffecttrail.cpp b/indra/newview/llhudeffecttrail.cpp
index fc6efdb840..2ba8aa422b 100644
--- a/indra/newview/llhudeffecttrail.cpp
+++ b/indra/newview/llhudeffecttrail.cpp
@@ -87,15 +87,15 @@ void LLHUDEffectSpiral::packData(LLMessageSystem *mesgsys)
if (mSourceObject)
{
- htonmemcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(packed_data, mSourceObject->mID.mData, MVT_LLUUID, 16);
}
if (mTargetObject)
{
- htonmemcpy(packed_data + 16, mTargetObject->mID.mData, MVT_LLUUID, 16);
+ htolememcpy(packed_data + 16, mTargetObject->mID.mData, MVT_LLUUID, 16);
}
if (!mPositionGlobal.isExactlyZero())
{
- htonmemcpy(packed_data + 32, mPositionGlobal.mdV, MVT_LLVector3d, 24);
+ htolememcpy(packed_data + 32, mPositionGlobal.mdV, MVT_LLVector3d, 24);
}
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 56);
}
@@ -116,9 +116,9 @@ void LLHUDEffectSpiral::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData,
packed_data, EFFECT_SIZE, blocknum, EFFECT_SIZE);
- htonmemcpy(object_id.mData, packed_data, MVT_LLUUID, 16);
- htonmemcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16);
- htonmemcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24);
+ htolememcpy(object_id.mData, packed_data, MVT_LLUUID, 16);
+ htolememcpy(target_object_id.mData, packed_data + 16, MVT_LLUUID, 16);
+ htolememcpy(mPositionGlobal.mdV, packed_data + 32, MVT_LLVector3d, 24);
LLViewerObject *objp = NULL;
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index d59c301210..322a5f410c 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -715,7 +715,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
{
info = new LLOfferInfo();
- info->mIM = IM_GROUP_NOTICE;
+ info->mIM = dialog;
info->mFromID = from_id;
info->mFromGroup = from_group;
info->mTransactionID = session_id;
@@ -854,39 +854,18 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
}
else // IM_TASK_INVENTORY_OFFERED
{
- if (offline == IM_OFFLINE && session_id.isNull() && aux_id.notNull() && binary_bucket_size > sizeof(S8)* 5)
- {
- // cap received offline message
- std::string str_bucket = ll_safe_string((char*)binary_bucket, binary_bucket_size);
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
- tokenizer tokens(str_bucket, sep);
- tokenizer::iterator iter = tokens.begin();
-
- info->mType = (LLAssetType::EType)(atoi((*(iter++)).c_str()));
- // Note There is more elements in 'tokens' ...
-
- info->mObjectID = LLUUID::null;
- info->mFromObject = TRUE;
- }
- else
- {
- if (sizeof(S8) != binary_bucket_size)
- {
- LL_WARNS("Messaging") << "Malformed inventory offer from object" << LL_ENDL;
- delete info;
- break;
- }
- info->mType = (LLAssetType::EType) binary_bucket[0];
- info->mObjectID = LLUUID::null;
- info->mFromObject = TRUE;
- }
+ info->mType = (LLAssetType::EType) binary_bucket[0];
+ info->mObjectID = LLUUID::null;
+ info->mFromObject = TRUE;
}
+ // In the case of an offline message, the transaction id will be in aux_id and th session_id will be null
+ // (conversely when online the transaction id is passed as session_id)
+ info->mTransactionID = session_id.isNull() ? aux_id : session_id;
+
info->mIM = dialog;
info->mFromID = from_id;
info->mFromGroup = from_group;
- info->mTransactionID = session_id;
info->mFolderID = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(info->mType));
info->mFromName = name;
@@ -896,12 +875,18 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
if (is_muted)
{
// Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
- LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
- fetch_item->startFetch();
- delete fetch_item;
-
- // Same as closing window
- info->forceResponse(IOR_DECLINE);
+ if (IM_INVENTORY_OFFERED == dialog)
+ {
+ LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID);
+ fetch_item->startFetch();
+ delete fetch_item;
+ // Same as closing window
+ info->forceResponse(IOR_DECLINE);
+ }
+ else
+ {
+ info->forceResponse(IOR_MUTE);
+ }
}
// old logic: busy mode must not affect interaction with objects (STORM-565)
// new logic: inventory offers from in-world objects should be auto-declined (CHUI-519)
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 349ba6183b..6d2d533c9d 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -4662,7 +4662,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
{
LLInventoryObject::object_list_t inventory_objects;
object->getInventoryContents(inventory_objects);
- int contents_count = inventory_objects.size()-1; //subtract one for containing folder
+ int contents_count = inventory_objects.size();
LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count, cat_and_wear->mFolderResponded,
cat_and_wear->mReplace);
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 16385928b4..e8bc915f22 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -42,7 +42,7 @@
#include "llviewerfoldertype.h"
#include "llradiogroup.h"
#include "llstartup.h"
-
+#include <boost/regex.hpp>
// linden library includes
#include "llclipboard.h"
#include "lltrans.h"
@@ -116,7 +116,39 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
break;
}
- bool passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
+
+ bool passed = true;
+ if (!mExactToken.empty() && (mSearchType == SEARCHTYPE_NAME))
+ {
+ passed = false;
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(" ");
+ tokenizer tokens(desc, sep);
+
+ for (auto token_iter : tokens)
+ {
+ if (token_iter == mExactToken)
+ {
+ passed = true;
+ break;
+ }
+ }
+ }
+ else if ((mFilterTokens.size() > 0) && (mSearchType == SEARCHTYPE_NAME))
+ {
+ for (auto token_iter : mFilterTokens)
+ {
+ if (desc.find(token_iter) == std::string::npos)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ passed = (mFilterSubString.size() ? desc.find(mFilterSubString) != std::string::npos : true);
+ }
+
passed = passed && checkAgainstFilterType(listener);
passed = passed && checkAgainstPermissions(listener);
passed = passed && checkAgainstFilterLinks(listener);
@@ -693,6 +725,38 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
if (mFilterSubString != filter_sub_string_new)
{
+
+ mFilterTokens.clear();
+ if (filter_sub_string_new.find_first_of("+") != std::string::npos)
+ {
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep("+");
+ tokenizer tokens(filter_sub_string_new, sep);
+
+ for (auto token_iter : tokens)
+ {
+ mFilterTokens.push_back(token_iter);
+ }
+ }
+
+ std::string old_token = mExactToken;
+ mExactToken.clear();
+ bool exact_token_changed = false;
+ if (mFilterTokens.empty() && filter_sub_string_new.size() > 2)
+ {
+ boost::regex mPattern = boost::regex("\"\\s*([^<]*)?\\s*\"",
+ boost::regex::perl | boost::regex::icase);
+ boost::match_results<std::string::const_iterator> matches;
+ mExactToken = (boost::regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched)
+ ? matches[1]
+ : LLStringUtil::null;
+ if ((old_token.empty() && !mExactToken.empty())
+ || (!old_token.empty() && mExactToken.empty()))
+ {
+ exact_token_changed = true;
+ }
+ }
+
// hitting BACKSPACE, for example
const BOOL less_restrictive = mFilterSubString.size() >= filter_sub_string_new.size()
&& !mFilterSubString.substr(0, filter_sub_string_new.size()).compare(filter_sub_string_new);
@@ -702,7 +766,11 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
&& !filter_sub_string_new.substr(0, mFilterSubString.size()).compare(mFilterSubString);
mFilterSubString = filter_sub_string_new;
- if (less_restrictive)
+ if (exact_token_changed)
+ {
+ setModified(FILTER_RESTART);
+ }
+ else if (less_restrictive)
{
setModified(FILTER_LESS_RESTRICTIVE);
}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 4a1fec8454..3f24211f41 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -327,6 +327,9 @@ private:
std::string mEmptyLookupMessage;
ESearchType mSearchType;
+
+ std::vector<std::string> mFilterTokens;
+ std::string mExactToken;
};
#endif
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
index b405d3dca2..6a79a0c68c 100644
--- a/indra/newview/llnotificationlistitem.cpp
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -262,6 +262,7 @@ std::set<std::string> LLTransactionNotificationListItem::getTypes()
std::set<std::string> types;
types.insert("PaymentReceived");
types.insert("PaymentSent");
+ types.insert("UploadPayment");
return types;
}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 90f8f84ea4..f849fecaf6 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -153,6 +153,53 @@ struct LLDeRezInfo
// Imports
//
+//-----------------------------------------------------------------------------
+// ~LLSelectionCallbackData()
+//-----------------------------------------------------------------------------
+
+LLSelectionCallbackData::LLSelectionCallbackData()
+{
+ LLSelectMgr *instance = LLSelectMgr::getInstance();
+ LLObjectSelectionHandle selection = instance->getSelection();
+ if (!selection->getNumNodes())
+ {
+ return;
+ }
+ mSelectedObjects = new LLObjectSelection();
+
+ for (LLObjectSelection::iterator iter = selection->begin();
+ iter != selection->end();)
+ {
+ LLObjectSelection::iterator curiter = iter++;
+
+ LLSelectNode *nodep = *curiter;
+ LLViewerObject* objectp = nodep->getObject();
+
+ if (!objectp)
+ {
+ mSelectedObjects->mSelectType = SELECT_TYPE_WORLD;
+ }
+ else
+ {
+ LLSelectNode* new_nodep = new LLSelectNode(*nodep);
+ mSelectedObjects->addNode(new_nodep);
+
+ if (objectp->isHUDAttachment())
+ {
+ mSelectedObjects->mSelectType = SELECT_TYPE_HUD;
+ }
+ else if (objectp->isAttachment())
+ {
+ mSelectedObjects->mSelectType = SELECT_TYPE_ATTACHMENT;
+ }
+ else
+ {
+ mSelectedObjects->mSelectType = SELECT_TYPE_WORLD;
+ }
+ }
+ }
+}
+
//
// Functions
@@ -4119,20 +4166,20 @@ void LLSelectMgr::packMultipleUpdate(LLSelectNode* node, void *user_data)
if (type & UPD_POSITION)
{
- htonmemcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12);
+ htolememcpy(&data[offset], &(object->getPosition().mV), MVT_LLVector3, 12);
offset += 12;
}
if (type & UPD_ROTATION)
{
LLQuaternion quat = object->getRotation();
LLVector3 vec = quat.packToVector3();
- htonmemcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12);
+ htolememcpy(&data[offset], &(vec.mV), MVT_LLQuaternion, 12);
offset += 12;
}
if (type & UPD_SCALE)
{
//LL_INFOS() << "Sending object scale " << object->getScale() << LL_ENDL;
- htonmemcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12);
+ htolememcpy(&data[offset], &(object->getScale().mV), MVT_LLVector3, 12);
offset += 12;
}
gMessageSystem->addBinaryDataFast(_PREHASH_Data, data, offset);
@@ -4475,9 +4522,19 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
{
- LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
+ sendAttach(mSelectedObjects, attachment_point, replace);
+}
+
+void LLSelectMgr::sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace)
+{
+ if (selection_handle.isNull())
+ {
+ return;
+ }
- if (!attach_object || !isAgentAvatarValid() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD)
+ LLViewerObject* attach_object = selection_handle->getFirstRootObject();
+
+ if (!attach_object || !isAgentAvatarValid() || selection_handle->mSelectType != SELECT_TYPE_WORLD)
{
return;
}
@@ -4495,6 +4552,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
}
sendListToRegions(
+ selection_handle,
"ObjectAttach",
packAgentIDAndSessionAndAttachment,
packObjectIDAndRotation,
@@ -4506,6 +4564,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
// After "ObjectAttach" server will unsubscribe us from properties updates
// so either deselect objects or resend selection after attach packet reaches server
// In case of build_mode LLPanelObjectInventory::refresh() will deal with selection
+ // Still unsubscribe even in case selection_handle is not current selection
deselectAll();
}
}
@@ -5047,7 +5106,17 @@ void LLSelectMgr::packPermissions(LLSelectNode* node, void *user_data)
void LLSelectMgr::sendListToRegions(const std::string& message_name,
void (*pack_header)(void *user_data),
void (*pack_body)(LLSelectNode* node, void *user_data),
- void (*log_func)(LLSelectNode* node, void *user_data),
+ void (*log_func)(LLSelectNode* node, void *user_data),
+ void *user_data,
+ ESendType send_type)
+{
+ sendListToRegions(mSelectedObjects, message_name, pack_header, pack_body, log_func, user_data, send_type);
+}
+void LLSelectMgr::sendListToRegions(LLObjectSelectionHandle selected_handle,
+ const std::string& message_name,
+ void (*pack_header)(void *user_data),
+ void (*pack_body)(LLSelectNode* node, void *user_data),
+ void (*log_func)(LLSelectNode* node, void *user_data),
void *user_data,
ESendType send_type)
{
@@ -5073,7 +5142,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
return true;
}
} func;
- getSelection()->applyToNodes(&func);
+ selected_handle->applyToNodes(&func);
std::queue<LLSelectNode*> nodes_to_send;
@@ -5116,25 +5185,25 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
{
case SEND_ONLY_ROOTS:
if(message_name == "ObjectBuy")
- getSelection()->applyToRootNodes(&pushroots);
+ selected_handle->applyToRootNodes(&pushroots);
else
- getSelection()->applyToRootNodes(&pushall);
+ selected_handle->applyToRootNodes(&pushall);
break;
case SEND_INDIVIDUALS:
- getSelection()->applyToNodes(&pushall);
+ selected_handle->applyToNodes(&pushall);
break;
case SEND_ROOTS_FIRST:
// first roots...
- getSelection()->applyToNodes(&pushroots);
+ selected_handle->applyToNodes(&pushroots);
// then children...
- getSelection()->applyToNodes(&pushnonroots);
+ selected_handle->applyToNodes(&pushnonroots);
break;
case SEND_CHILDREN_FIRST:
// first children...
- getSelection()->applyToNodes(&pushnonroots);
+ selected_handle->applyToNodes(&pushnonroots);
// then roots...
- getSelection()->applyToNodes(&pushroots);
+ selected_handle->applyToNodes(&pushroots);
break;
default:
@@ -6686,8 +6755,7 @@ void LLSelectMgr::updateSelectionCenter()
if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid())
{
// reset hud ZOOM
- gAgentCamera.mHUDTargetZoom = 1.f;
- gAgentCamera.mHUDCurZoom = 1.f;
+ resetAgentHUDZoom();
}
mShowSelection = FALSE;
@@ -7060,8 +7128,11 @@ BOOL LLSelectMgr::setForceSelection(BOOL force)
void LLSelectMgr::resetAgentHUDZoom()
{
- gAgentCamera.mHUDTargetZoom = 1.f;
- gAgentCamera.mHUDCurZoom = 1.f;
+ if (gAgentCamera.mHUDTargetZoom != 1)
+ {
+ gAgentCamera.mHUDTargetZoom = 1.f;
+ gAgentCamera.mHUDCurZoom = 1.f;
+ }
}
void LLSelectMgr::getAgentHUDZoom(F32 &target_zoom, F32 &current_zoom) const
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 3e8bfdb00e..3bed484b58 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -239,6 +239,7 @@ class LLObjectSelection : public LLRefCount
{
friend class LLSelectMgr;
friend class LLSafeHandle<LLObjectSelection>;
+ friend class LLSelectionCallbackData;
protected:
~LLObjectSelection();
@@ -396,6 +397,16 @@ extern template class LLSelectMgr* LLSingleton<class LLSelectMgr>::getInstance()
// For use with getFirstTest()
struct LLSelectGetFirstTest;
+// temporary storage, Ex: to attach objects after autopilot
+class LLSelectionCallbackData
+{
+public:
+ LLSelectionCallbackData();
+ LLObjectSelectionHandle getSelection() { return mSelectedObjects; }
+private:
+ LLObjectSelectionHandle mSelectedObjects;
+};
+
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr>
{
LLSINGLETON(LLSelectMgr);
@@ -740,6 +751,7 @@ public:
// canceled
void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info);
void sendAttach(U8 attachment_point, bool replace);
+ void sendAttach(LLObjectSelectionHandle selection_handle, U8 attachment_point, bool replace);
void sendDetach();
void sendDropAttachment();
void sendLink();
@@ -787,6 +799,13 @@ private:
void (*log_func)(LLSelectNode* node, void *user_data),
void *user_data,
ESendType send_type);
+ void sendListToRegions( LLObjectSelectionHandle selected_handle,
+ const std::string& message_name,
+ void (*pack_header)(void *user_data),
+ void (*pack_body)(LLSelectNode* node, void *user_data),
+ void (*log_func)(LLSelectNode* node, void *user_data),
+ void *user_data,
+ ESendType send_type);
static void packAgentID( void *);
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index 2503e2a5e2..d508621b41 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -49,6 +49,29 @@
#include "llviewerregion.h"
+class PropertiesChangedCallback : public LLInventoryCallback
+{
+public:
+ PropertiesChangedCallback(LLHandle<LLPanel> sidepanel_handle, LLUUID &item_id, S32 id)
+ : mHandle(sidepanel_handle), mItemId(item_id), mId(id)
+ {}
+
+ void fire(const LLUUID &inv_item)
+ {
+ // inv_item can be null for some reason
+ LLSidepanelItemInfo* sidepanel = dynamic_cast<LLSidepanelItemInfo*>(mHandle.get());
+ if (sidepanel)
+ {
+ // sidepanel waits only for most recent update
+ sidepanel->onUpdateCallback(mItemId, mId);
+ }
+ }
+private:
+ LLHandle<LLPanel> mHandle;
+ LLUUID mItemId;
+ S32 mId;
+};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLItemPropertiesObserver
//
@@ -68,7 +91,7 @@ public:
}
virtual void changed(U32 mask);
private:
- LLSidepanelItemInfo* mFloater;
+ LLSidepanelItemInfo* mFloater; // Not a handle because LLSidepanelItemInfo is managing LLItemPropertiesObserver
};
void LLItemPropertiesObserver::changed(U32 mask)
@@ -115,7 +138,7 @@ public:
S32 serial_num,
void* user_data);
private:
- LLSidepanelItemInfo* mFloater;
+ LLSidepanelItemInfo* mFloater; // Not a handle because LLSidepanelItemInfo is managing LLObjectInventoryObserver
};
/*virtual*/
@@ -138,6 +161,7 @@ LLSidepanelItemInfo::LLSidepanelItemInfo(const LLPanel::Params& p)
: LLSidepanelInventorySubpanel(p)
, mItemID(LLUUID::null)
, mObjectInventoryObserver(NULL)
+ , mUpdatePendingId(-1)
{
mPropertiesObserver = new LLItemPropertiesObserver(this);
}
@@ -168,19 +192,19 @@ BOOL LLSidepanelItemInfo::postBuild()
// owner permissions
// Permissions debug text
// group permissions
- getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckShareWithGroup")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
// everyone permissions
- getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckEveryoneCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
// next owner permissions
- getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
- getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
- getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this));
+ getChild<LLUICtrl>("CheckNextOwnerModify")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
+ getChild<LLUICtrl>("CheckNextOwnerCopy")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
+ getChild<LLUICtrl>("CheckNextOwnerTransfer")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitPermissions, this, _1));
// Mark for sale or not, and sale info
- getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+ getChild<LLUICtrl>("CheckPurchase")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
// Change sale type, and sale info
- getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+ getChild<LLUICtrl>("ComboBoxSaleType")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
// "Price" label for edit
- getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this));
+ getChild<LLUICtrl>("Edit Cost")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitSaleInfo, this, _1));
refresh();
return TRUE;
}
@@ -192,11 +216,16 @@ void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
// Start monitoring changes in the object inventory to update
// selected inventory item properties in Item Profile panel. See STORM-148.
startObjectInventoryObserver();
+ mUpdatePendingId = -1;
}
void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
{
- mItemID = item_id;
+ if (mItemID != item_id)
+ {
+ mItemID = item_id;
+ mUpdatePendingId = -1;
+ }
}
const LLUUID& LLSidepanelItemInfo::getObjectID() const
@@ -209,6 +238,15 @@ const LLUUID& LLSidepanelItemInfo::getItemID() const
return mItemID;
}
+void LLSidepanelItemInfo::onUpdateCallback(const LLUUID& item_id, S32 received_update_id)
+{
+ if (mItemID == item_id && mUpdatePendingId == received_update_id)
+ {
+ mUpdatePendingId = -1;
+ refresh();
+ }
+}
+
void LLSidepanelItemInfo::reset()
{
LLSidepanelInventorySubpanel::reset();
@@ -242,24 +280,16 @@ void LLSidepanelItemInfo::refresh()
"LabelItemName",
"LabelItemDesc",
"LabelCreatorName",
- "LabelOwnerName",
- "CheckOwnerModify",
- "CheckOwnerCopy",
- "CheckOwnerTransfer",
- "CheckShareWithGroup",
- "CheckEveryoneCopy",
- "CheckNextOwnerModify",
- "CheckNextOwnerCopy",
- "CheckNextOwnerTransfer",
- "CheckPurchase",
- "Edit Cost"
+ "LabelOwnerName"
};
for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
{
getChildView(no_item_names[t])->setEnabled(false);
}
-
+
+ setPropertiesFieldsEnabled(false);
+
const std::string hide_names[]={
"BaseMaskDebug",
"OwnerMaskDebug",
@@ -297,6 +327,11 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
llassert(item);
if (!item) return;
+ if (mUpdatePendingId != -1)
+ {
+ return;
+ }
+
// do not enable the UI for incomplete items.
BOOL is_complete = item->isFinished();
const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType());
@@ -726,6 +761,26 @@ void LLSidepanelItemInfo::stopObjectInventoryObserver()
mObjectInventoryObserver = NULL;
}
+void LLSidepanelItemInfo::setPropertiesFieldsEnabled(bool enabled)
+{
+ const std::string fields[] = {
+ "CheckOwnerModify",
+ "CheckOwnerCopy",
+ "CheckOwnerTransfer",
+ "CheckShareWithGroup",
+ "CheckEveryoneCopy",
+ "CheckNextOwnerModify",
+ "CheckNextOwnerCopy",
+ "CheckNextOwnerTransfer",
+ "CheckPurchase",
+ "Edit Cost"
+ };
+ for (size_t t = 0; t<LL_ARRAY_SIZE(fields); ++t)
+ {
+ getChildView(fields[t])->setEnabled(false);
+ }
+}
+
void LLSidepanelItemInfo::onClickCreator()
{
LLViewerInventoryItem* item = findItem();
@@ -793,10 +848,18 @@ void LLSidepanelItemInfo::onCommitDescription()
}
}
-// static
-void LLSidepanelItemInfo::onCommitPermissions()
+void LLSidepanelItemInfo::onCommitPermissions(LLUICtrl* ctrl)
+{
+ if (ctrl)
+ {
+ // will be enabled by response from server
+ ctrl->setEnabled(false);
+ }
+ updatePermissions();
+}
+
+void LLSidepanelItemInfo::updatePermissions()
{
- //LL_INFOS() << "LLSidepanelItemInfo::onCommitPermissions()" << LL_ENDL;
LLViewerInventoryItem* item = findItem();
if(!item) return;
@@ -884,19 +947,17 @@ void LLSidepanelItemInfo::onCommitPermissions()
}
// static
-void LLSidepanelItemInfo::onCommitSaleInfo()
+void LLSidepanelItemInfo::onCommitSaleInfo(LLUICtrl* ctrl)
{
+ if (ctrl)
+ {
+ // will be enabled by response from server
+ ctrl->setEnabled(false);
+ }
//LL_INFOS() << "LLSidepanelItemInfo::onCommitSaleInfo()" << LL_ENDL;
updateSaleInfo();
}
-// static
-void LLSidepanelItemInfo::onCommitSaleType()
-{
- //LL_INFOS() << "LLSidepanelItemInfo::onCommitSaleType()" << LL_ENDL;
- updateSaleInfo();
-}
-
void LLSidepanelItemInfo::updateSaleInfo()
{
LLViewerInventoryItem* item = findItem();
@@ -977,7 +1038,12 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
if (mObjectID.isNull())
{
// This is in the agent's inventory.
- item->updateServer(FALSE);
+ // Mark update as pending and wait only for most recent one in case user requested for couple
+ // Once update arrives or any of ids change drop pending id.
+ mUpdatePendingId++;
+ LLPointer<LLInventoryCallback> callback = new PropertiesChangedCallback(getHandle(), mItemID, mUpdatePendingId);
+ update_inventory_item(item.get(), callback);
+ //item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@@ -1002,6 +1068,7 @@ void LLSidepanelItemInfo::onCommitChanges(LLPointer<LLViewerInventoryItem> item)
// prevents flashing in content tab and some duplicated request.
object->dirtyInventory();
}
+ setPropertiesFieldsEnabled(false);
}
}
}
@@ -1030,7 +1097,6 @@ void LLSidepanelItemInfo::save()
{
onCommitName();
onCommitDescription();
- onCommitPermissions();
- onCommitSaleInfo();
- onCommitSaleType();
+ updatePermissions();
+ updateSaleInfo();
}
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h
index 74cf7afe35..5f29254182 100644
--- a/indra/newview/llsidepaneliteminfo.h
+++ b/indra/newview/llsidepaneliteminfo.h
@@ -57,6 +57,9 @@ public:
const LLUUID& getObjectID() const;
const LLUUID& getItemID() const;
+ // if received update and item id (from callback) matches internal ones, update UI
+ void onUpdateCallback(const LLUUID& item_id, S32 received_update_id);
+
protected:
/*virtual*/ void refresh();
/*virtual*/ void save();
@@ -71,12 +74,16 @@ private:
void startObjectInventoryObserver();
void stopObjectInventoryObserver();
+ void setPropertiesFieldsEnabled(bool enabled);
LLUUID mItemID; // inventory UUID for the inventory item.
LLUUID mObjectID; // in-world task UUID, or null if in agent inventory.
LLItemPropertiesObserver* mPropertiesObserver; // for syncing changes to item
LLObjectInventoryObserver* mObjectInventoryObserver; // for syncing changes to items inside an object
-
+
+ // We can send multiple properties updates simultaneously, make sure only last response counts and there won't be a race condition.
+ S32 mUpdatePendingId;
+
//
// UI Elements
//
@@ -85,9 +92,9 @@ protected:
void onClickOwner();
void onCommitName();
void onCommitDescription();
- void onCommitPermissions();
- void onCommitSaleInfo();
- void onCommitSaleType();
+ void onCommitPermissions(LLUICtrl* ctrl);
+ void updatePermissions();
+ void onCommitSaleInfo(LLUICtrl* ctrl);
void updateSaleInfo();
void onCommitChanges(LLPointer<LLViewerInventoryItem> item);
};
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp
index f03c7abc4d..7fa06f51e3 100644
--- a/indra/newview/llsidepaneltaskinfo.cpp
+++ b/indra/newview/llsidepaneltaskinfo.cpp
@@ -174,9 +174,6 @@ BOOL LLSidepanelTaskInfo::postBuild()
void LLSidepanelTaskInfo::disableAll()
{
- mDAPermModify->setEnabled(FALSE);
- mDAPermModify->setValue(LLStringUtil::null);
-
mDACreatorName->setValue(LLStringUtil::null);
mDACreatorName->setEnabled(FALSE);
@@ -184,18 +181,42 @@ void LLSidepanelTaskInfo::disableAll()
mDAOwnerName->setValue(LLStringUtil::null);
mDAOwnerName->setEnabled(FALSE);
- mDAButtonSetGroup->setEnabled(FALSE);
-
mDAObjectName->setValue(LLStringUtil::null);
mDAObjectName->setEnabled(FALSE);
mDAName->setEnabled(FALSE);
mDADescription->setEnabled(FALSE);
mDAObjectDescription->setValue(LLStringUtil::null);
mDAObjectDescription->setEnabled(FALSE);
-
+
+ mDAPathfindingAttributes->setEnabled(FALSE);
+ mDAPathfindingAttributes->setValue(LLStringUtil::null);
+
+ mDAButtonSetGroup->setEnabled(FALSE);
+ mDAButtonDeed->setEnabled(FALSE);
+
+ mDAPermModify->setEnabled(FALSE);
+ mDAPermModify->setValue(LLStringUtil::null);
+ mDAEditCost->setValue(LLStringUtil::null);
+ mDAComboSaleType->setValue(LLSaleInfo::FS_COPY);
+
+ disablePermissions();
+
+ mDAB->setVisible(FALSE);
+ mDAO->setVisible(FALSE);
+ mDAG->setVisible(FALSE);
+ mDAE->setVisible(FALSE);
+ mDAN->setVisible(FALSE);
+ mDAF->setVisible(FALSE);
+
+ mOpenBtn->setEnabled(FALSE);
+ mPayBtn->setEnabled(FALSE);
+ mBuyBtn->setEnabled(FALSE);
+}
+
+void LLSidepanelTaskInfo::disablePermissions()
+{
mDACheckboxShareWithGroup->setValue(FALSE);
mDACheckboxShareWithGroup->setEnabled(FALSE);
- mDAButtonDeed->setEnabled(FALSE);
mDACheckboxAllowEveryoneMove->setValue(FALSE);
mDACheckboxAllowEveryoneMove->setEnabled(FALSE);
@@ -217,33 +238,17 @@ void LLSidepanelTaskInfo::disableAll()
//checkbox include in search
mDASearchCheck->setValue(FALSE);
mDASearchCheck->setEnabled(FALSE);
-
- mDAComboSaleType->setValue(LLSaleInfo::FS_COPY);
+
mDAComboSaleType->setEnabled(FALSE);
-
- mDAEditCost->setValue(LLStringUtil::null);
+
mDAEditCost->setEnabled(FALSE);
-
+
mDALabelClickAction->setEnabled(FALSE);
if (mDAComboClickAction)
{
mDAComboClickAction->setEnabled(FALSE);
mDAComboClickAction->clear();
}
-
- mDAPathfindingAttributes->setEnabled(FALSE);
- mDAPathfindingAttributes->setValue(LLStringUtil::null);
-
- mDAB->setVisible(FALSE);
- mDAO->setVisible(FALSE);
- mDAG->setVisible(FALSE);
- mDAE->setVisible(FALSE);
- mDAN->setVisible(FALSE);
- mDAF->setVisible(FALSE);
-
- mOpenBtn->setEnabled(FALSE);
- mPayBtn->setEnabled(FALSE);
- mBuyBtn->setEnabled(FALSE);
}
void LLSidepanelTaskInfo::refresh()
@@ -972,6 +977,12 @@ void LLSidepanelTaskInfo::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32
BOOL new_state = check->get();
LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm);
+
+ LLSidepanelTaskInfo* self = (LLSidepanelTaskInfo*)data;
+ if (self)
+ {
+ self->disablePermissions();
+ }
}
// static
diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h
index cbfb07874b..dc259cb22d 100644
--- a/indra/newview/llsidepaneltaskinfo.h
+++ b/indra/newview/llsidepaneltaskinfo.h
@@ -95,6 +95,7 @@ protected:
static void doClickAction(U8 click_action);
void disableAll();
+ void disablePermissions();
private:
LLNameBox* mLabelGroupName; // group name
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 6e0a36be49..bef27cfb99 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1625,7 +1625,14 @@ bool idle_startup()
if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
{
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ if (gRememberPassword)
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+ }
reset_login();
}
return FALSE;
@@ -2360,7 +2367,14 @@ void use_circuit_callback(void**, S32 result)
{
// Make sure user knows something bad happened. JC
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ if (gRememberPassword)
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ }
+ else
+ {
+ LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status);
+ }
reset_login();
}
else
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index f3c270a97b..c4e09b6767 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -243,16 +243,24 @@ BOOL LLStatusBar::postBuild()
mPanelNearByMedia->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
mPanelNearByMedia->setVisible(FALSE);
+ updateBalancePanelPosition();
+
// Hook up and init for filtering
mFilterEdit = getChild<LLSearchEditor>( "search_menu_edit" );
mSearchPanel = getChild<LLPanel>( "menu_search_panel" );
- mSearchPanel->setVisible(gSavedSettings.getBOOL("MenuSearch"));
+ BOOL search_panel_visible = gSavedSettings.getBOOL("MenuSearch");
+ mSearchPanel->setVisible(search_panel_visible);
mFilterEdit->setKeystrokeCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
mFilterEdit->setCommitCallback(boost::bind(&LLStatusBar::onUpdateFilterTerm, this));
collectSearchableItems();
gSavedSettings.getControl("MenuSearch")->getCommitSignal()->connect(boost::bind(&LLStatusBar::updateMenuSearchVisibility, this, _2));
+ if (search_panel_visible)
+ {
+ updateMenuSearchPosition();
+ }
+
return TRUE;
}
@@ -361,17 +369,7 @@ void LLStatusBar::setBalance(S32 balance)
std::string label_str = getString("buycurrencylabel", string_args);
mBoxBalance->setValue(label_str);
- // Resize the L$ balance background to be wide enough for your balance plus the buy button
- {
- const S32 HPAD = 24;
- LLRect balance_rect = mBoxBalance->getTextBoundingRect();
- LLRect buy_rect = getChildView("buyL")->getRect();
- LLRect shop_rect = getChildView("goShop")->getRect();
- LLView* balance_bg_view = getChildView("balance_bg");
- LLRect balance_bg_rect = balance_bg_view->getRect();
- balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
- balance_bg_view->setShape(balance_bg_rect);
- }
+ updateBalancePanelPosition();
// If the search panel is shown, move this according to the new balance width. Parcel text will reshape itself in setParcelInfoText
if (mSearchPanel && mSearchPanel->getVisible())
@@ -659,6 +657,19 @@ void LLStatusBar::updateMenuSearchPosition()
mSearchPanel->setShape( searchRect );
}
+void LLStatusBar::updateBalancePanelPosition()
+{
+ // Resize the L$ balance background to be wide enough for your balance plus the buy button
+ const S32 HPAD = 24;
+ LLRect balance_rect = mBoxBalance->getTextBoundingRect();
+ LLRect buy_rect = getChildView("buyL")->getRect();
+ LLRect shop_rect = getChildView("goShop")->getRect();
+ LLView* balance_bg_view = getChildView("balance_bg");
+ LLRect balance_bg_rect = balance_bg_view->getRect();
+ balance_bg_rect.mLeft = balance_bg_rect.mRight - (buy_rect.getWidth() + shop_rect.getWidth() + balance_rect.getWidth() + HPAD);
+ balance_bg_view->setShape(balance_bg_rect);
+}
+
// Implements secondlife:///app/balance/request to request a L$ balance
// update via UDP message system. JC
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index 403d590aca..cad877f799 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -114,7 +114,8 @@ private:
std::unique_ptr< ll::statusbar::SearchData > mSearchData;
void collectSearchableItems();
void updateMenuSearchVisibility( const LLSD& data );
- void updateMenuSearchPosition();
+ void updateMenuSearchPosition(); // depends onto balance position
+ void updateBalancePanelPosition();
private:
LLTextBox *mTextTime;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e5af47ab6c..f3bb574191 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -53,6 +53,7 @@ const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by
const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
const S32 TEXTURE_FAST_CACHE_ENTRY_OVERHEAD = sizeof(S32) * 4; //w, h, c, level
const S32 TEXTURE_FAST_CACHE_ENTRY_SIZE = 16 * 16 * 4 + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD;
+const F32 TEXTURE_LAZY_PURGE_TIME_LIMIT = .004f; // 4ms. Would be better to autoadjust, but there is a major cache rework in progress.
class LLTextureCacheWorker : public LLWorkerClass
{
@@ -1669,6 +1670,91 @@ void LLTextureCache::purgeAllTextures(bool purge_directories)
LL_INFOS() << "The entire texture cache is cleared." << LL_ENDL ;
}
+void LLTextureCache::purgeTexturesLazy(F32 time_limit_sec)
+{
+ if (mReadOnly)
+ {
+ return;
+ }
+
+ if (!mThreaded)
+ {
+ LLAppViewer::instance()->pauseMainloopTimeout();
+ }
+
+ // time_limit doesn't account for lock time
+ LLMutexLock lock(&mHeaderMutex);
+
+ if (mPurgeEntryList.empty())
+ {
+ // Read the entries list and form list of textures to purge
+ std::vector<Entry> entries;
+ U32 num_entries = openAndReadEntries(entries);
+ if (!num_entries)
+ {
+ return; // nothing to purge
+ }
+
+ // Use mTexturesSizeMap to collect UUIDs of textures with bodies
+ typedef std::set<std::pair<U32, S32> > time_idx_set_t;
+ std::set<std::pair<U32, S32> > time_idx_set;
+ for (size_map_t::iterator iter1 = mTexturesSizeMap.begin();
+ iter1 != mTexturesSizeMap.end(); ++iter1)
+ {
+ if (iter1->second > 0)
+ {
+ id_map_t::iterator iter2 = mHeaderIDMap.find(iter1->first);
+ if (iter2 != mHeaderIDMap.end())
+ {
+ S32 idx = iter2->second;
+ time_idx_set.insert(std::make_pair(entries[idx].mTime, idx));
+ }
+ else
+ {
+ LL_ERRS("TextureCache") << "mTexturesSizeMap / mHeaderIDMap corrupted." << LL_ENDL;
+ }
+ }
+ }
+
+ S64 cache_size = mTexturesSizeTotal;
+ S64 purged_cache_size = (sCacheMaxTexturesSize * (S64)((1.f - TEXTURE_CACHE_PURGE_AMOUNT) * 100)) / 100;
+ for (time_idx_set_t::iterator iter = time_idx_set.begin();
+ iter != time_idx_set.end(); ++iter)
+ {
+ S32 idx = iter->second;
+ if (cache_size >= purged_cache_size)
+ {
+ cache_size -= entries[idx].mBodySize;
+ mPurgeEntryList.push_back(std::pair<S32, Entry>(idx, entries[idx]));
+ }
+ else
+ {
+ break;
+ }
+ }
+ LL_DEBUGS("TextureCache") << "Formed Purge list of " << mPurgeEntryList.size() << " entries" << LL_ENDL;
+ }
+ else
+ {
+ // Remove collected entried
+ LLTimer timer;
+ while (!mPurgeEntryList.empty() && timer.getElapsedTimeF32() < time_limit_sec)
+ {
+ S32 idx = mPurgeEntryList.back().first;
+ Entry entry = mPurgeEntryList.back().second;
+ mPurgeEntryList.pop_back();
+ // make sure record is still valid
+ id_map_t::iterator iter_header = mHeaderIDMap.find(entry.mID);
+ if (iter_header != mHeaderIDMap.end() && iter_header->second == idx)
+ {
+ std::string tex_filename = getTextureFileName(entry.mID);
+ removeEntry(idx, entry, tex_filename);
+ writeEntryToHeaderImmediately(idx, entry);
+ }
+ }
+ }
+}
+
void LLTextureCache::purgeTextures(bool validate)
{
if (mReadOnly)
@@ -1928,11 +2014,10 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
}
if (mDoPurge)
{
- // NOTE: This may cause an occasional hiccup,
- // but it really needs to be done on the control thread
- // (i.e. here)
- purgeTextures(false);
- mDoPurge = FALSE;
+ // NOTE: Needs to be done on the control thread
+ // (i.e. here)
+ purgeTexturesLazy(TEXTURE_LAZY_PURGE_TIME_LIMIT);
+ mDoPurge = !mPurgeEntryList.empty();
}
LLMutexLock lock(&mWorkersMutex);
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 81ea7aeee2..da59290930 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -155,6 +155,7 @@ private:
void readHeaderCache();
void clearCorruptedCache();
void purgeAllTextures(bool purge_directories);
+ void purgeTexturesLazy(F32 time_limit_sec);
void purgeTextures(bool validate);
LLAPRFile* openHeaderEntriesFile(bool readonly, S32 offset);
void closeHeaderEntriesFile();
@@ -225,6 +226,8 @@ private:
typedef std::map<S32, Entry> idx_entry_map_t;
idx_entry_map_t mUpdatedEntryMap;
+ typedef std::vector<std::pair<S32, Entry> > idx_entry_vector_t;
+ idx_entry_vector_t mPurgeEntryList;
// Statics
static F32 sHeaderCacheVersion;
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index f3e661e71a..429664e743 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -721,9 +721,14 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask)
!objectp->isHUDAttachment() &&
objectp->getRoot() == gAgentAvatarp->getRoot())
{
- // force focus to point in space where we were looking previously
- gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
- gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ // we are essentially editing object position
+ if (!gSavedSettings.getBOOL("EditCameraMovement"))
+ {
+ // force focus to point in space where we were looking previously
+ // Example of use: follow cam scripts shouldn't affect you when movng objects arouns
+ gAgentCamera.setFocusGlobal(gAgentCamera.calcFocusPositionTargetGlobal(), LLUUID::null);
+ gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE);
+ }
}
else
{
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 2a87bce134..47227f987d 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -874,37 +874,9 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
static bool needs_tooltip(LLSelectNode* nodep)
{
- if (!nodep)
+ if (!nodep || !nodep->mValid)
return false;
-
- LLViewerObject* object = nodep->getObject();
- LLViewerObject *parent = (LLViewerObject *)object->getParent();
- if (object->flagHandleTouch()
- || (parent && parent->flagHandleTouch())
- || object->flagTakesMoney()
- || (parent && parent->flagTakesMoney())
- || object->flagAllowInventoryAdd()
- )
- {
- return true;
- }
-
- U8 click_action = final_click_action(object);
- if (click_action != 0)
- {
- return true;
- }
-
- if (nodep->mValid)
- {
- bool anyone_copy = anyone_copy_selection(nodep);
- bool for_sale = for_sale_selection(nodep);
- if (anyone_copy || for_sale)
- {
- return true;
- }
- }
- return false;
+ return true;
}
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 5924dbc260..a3d946c4d4 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1087,7 +1087,7 @@ void render_hud_attachments()
// clamp target zoom level to reasonable values
gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
// smoothly interpolate current zoom level
- gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLSmoothInterpolation::getInterpolant(0.03f));
+ gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.getAgentHUDTargetZoom(), LLSmoothInterpolation::getInterpolant(0.03f));
if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
{
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 52b2c631fa..1566736f17 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -6672,10 +6672,10 @@ private:
static void onNearAttachObject(BOOL success, void *user_data);
void confirmReplaceAttachment(S32 option, LLViewerJointAttachment* attachment_point);
-
- struct CallbackData
+ class CallbackData : public LLSelectionCallbackData
{
- CallbackData(LLViewerJointAttachment* point, bool replace) : mAttachmentPoint(point), mReplace(replace) {}
+ public:
+ CallbackData(LLViewerJointAttachment* point, bool replace) : LLSelectionCallbackData(), mAttachmentPoint(point), mReplace(replace) {}
LLViewerJointAttachment* mAttachmentPoint;
bool mReplace;
@@ -6716,8 +6716,8 @@ void LLObjectAttachToAvatar::onNearAttachObject(BOOL success, void *user_data)
// interpret 0 as "default location"
attachment_id = 0;
}
- LLSelectMgr::getInstance()->sendAttach(attachment_id, cb_data->mReplace);
- }
+ LLSelectMgr::getInstance()->sendAttach(cb_data->getSelection(), attachment_id, cb_data->mReplace);
+ }
LLObjectAttachToAvatar::setObjectSelection(NULL);
delete cb_data;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 6e5c77e4a9..5b9c39af9f 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1671,8 +1671,20 @@ void LLOfferInfo::fromLLSD(const LLSD& params)
*this = params;
}
-void LLOfferInfo::send_auto_receive_response(void)
-{
+void LLOfferInfo::sendReceiveResponse(bool accept, const LLUUID &destination_folder_id)
+{
+ if(IM_INVENTORY_OFFERED == mIM)
+ {
+ // add buddy to recent people list
+ LLRecentPeople::instance().add(mFromID);
+ }
+
+ if (mTransactionID.isNull())
+ {
+ // Not provided, message won't work
+ return;
+ }
+
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -1691,23 +1703,42 @@ void LLOfferInfo::send_auto_receive_response(void)
msg->addU32Fast(_PREHASH_ParentEstateID, 0);
msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
-
- // Auto Receive Message. The math for the dialog works, because the accept
+
+ // ACCEPT. The math for the dialog works, because the accept
// for inventory_offered, task_inventory_offer or
// group_notice_inventory is 1 greater than the offer integer value.
// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
- sizeof(mFolderID.mData));
- // send the message
- msg->sendReliable(mHost);
-
- if(IM_INVENTORY_OFFERED == mIM)
+ // Decline for inventory_offered, task_inventory_offer or
+ // group_notice_inventory is 2 greater than the offer integer value.
+
+ EInstantMessage im = mIM;
+ if (mIM == IM_GROUP_NOTICE_REQUESTED)
{
- // add buddy to recent people list
- LLRecentPeople::instance().add(mFromID);
+ // Request has no responder dialogs
+ im = IM_GROUP_NOTICE;
+ }
+
+ if (accept)
+ {
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(im + 1));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(destination_folder_id.mData),
+ sizeof(destination_folder_id.mData));
}
+ else
+ {
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(im + 2));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
+ }
+ // send the message
+ msg->sendReliable(mHost);
+
+ // transaction id is usable only once
+ // Note: a bit of a hack, clicking group notice attachment will not close notice
+ // so we reset no longer usable transaction id to know not to send message again
+ // Once capabilities for responses will be implemented LLOfferInfo will have to
+ // remember that it already responded in another way and ignore IOR_DECLINE
+ mTransactionID.setNull();
}
void LLOfferInfo::handleRespond(const LLSD& notification, const LLSD& response)
@@ -1767,7 +1798,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here:
from_string = chatHistory_string = mFromName;
-
+
+ // accept goes to proper folder, decline gets accepted to trash, muted gets declined
+ bool accept_to_trash = true;
+
LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm());
switch(button)
@@ -1799,11 +1833,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
}
break;
case IM_GROUP_NOTICE:
+ case IM_GROUP_NOTICE_REQUESTED:
opener = new LLOpenTaskGroupOffer;
- send_auto_receive_response();
+ sendReceiveResponse(true, mFolderID);
break;
case IM_TASK_INVENTORY_OFFERED:
- case IM_GROUP_NOTICE_REQUESTED:
// This is an offer from a task or group.
// We don't use a new instance of an opener
// We instead use the singular observer gOpenTaskOffer
@@ -1838,6 +1872,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
{
modified_form->setElementEnabled("Mute", false);
}
+ accept_to_trash = false; // for notices, but IOR_MUTE normally doesn't happen for notices
// MUTE falls through to decline
case IOR_DECLINE:
{
@@ -1851,21 +1886,32 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
{
chat.mMuted = TRUE;
+ accept_to_trash = false; // will send decline message
}
// *NOTE dzaporozhan
// Disabled logging to old chat floater to fix crash in group notices - EXT-4149
// LLFloaterChat::addChatHistory(chat);
- LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
- discard_agent_offer->startFetch();
- if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
+ if (mObjectID.notNull()) //make sure we can discard
{
- discard_agent_offer->done();
+ LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
+ discard_agent_offer->startFetch();
+ if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished()))
+ {
+ discard_agent_offer->done();
+ }
+ else
+ {
+ opener = discard_agent_offer;
+ }
}
- else
+ else if (mIM == IM_GROUP_NOTICE)
{
- opener = discard_agent_offer;
+ // group notice needs to request object to trash so that user will see it later
+ // Note: muted agent offers go to trash, not sure if we should do same for notices
+ LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ sendReceiveResponse(accept_to_trash, trash);
}
if (modified_form != NULL)
@@ -1878,9 +1924,14 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
}
default:
// close button probably
- // The item has already been fetched and is in your inventory, we simply won't highlight it
+ // In case of agent offers item has already been fetched and is in your inventory, we simply won't highlight it
// OR delete it if the notification gets killed, since we don't want that to be a vector for
// losing inventory offers.
+ if (mIM == IM_GROUP_NOTICE)
+ {
+ LLUUID trash = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ sendReceiveResponse(true, trash);
+ }
break;
}
@@ -1925,29 +1976,10 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
}
}
}
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_MessageBlock);
- msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
- msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addUUIDFast(_PREHASH_ID, mTransactionID);
- msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
- std::string name;
- LLAgentUI::buildFullname(name);
- msg->addStringFast(_PREHASH_FromAgentName, name);
- msg->addStringFast(_PREHASH_Message, "");
- msg->addU32Fast(_PREHASH_ParentEstateID, 0);
- msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
- msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
- LLInventoryObserver* opener = NULL;
-
+
std::string from_string; // Used in the pop-up.
std::string chatHistory_string; // Used in chat history.
+
if (mFromObject == TRUE)
{
if (mFromGroup)
@@ -1991,23 +2023,15 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
from_string = chatHistory_string = mFromName;
}
- bool is_do_not_disturb = gAgent.isDoNotDisturb();
-
+ LLUUID destination;
+ bool accept = true;
+
+ // If user accepted, accept to proper folder, if user discarded, accept to trash.
switch(button)
{
case IOR_ACCEPT:
- // ACCEPT. The math for the dialog works, because the accept
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 1 greater than the offer integer value.
- // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
- // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
- sizeof(mFolderID.mData));
- // send the message
- msg->sendReliable(mHost);
-
- //don't spam them if they are getting flooded
+ destination = mFolderID;
+ //don't spam user if flooded
if (check_offer_throttle(mFromName, true))
{
log_message = "<nolink>" + chatHistory_string + "</nolink> " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString(".");
@@ -2015,66 +2039,24 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
args["MESSAGE"] = log_message;
LLNotificationsUtil::add("SystemMessageTip", args);
}
-
- // we will want to open this item when it comes back.
- LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
- << LL_ENDL;
- switch (mIM)
- {
- case IM_TASK_INVENTORY_OFFERED:
- case IM_GROUP_NOTICE:
- case IM_GROUP_NOTICE_REQUESTED:
- {
- // This is an offer from a task or group.
- // We don't use a new instance of an opener
- // We instead use the singular observer gOpenTaskOffer
- // Since it already exists, we don't need to actually do anything
- }
- break;
- default:
- LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
- break;
- } // end switch (mIM)
break;
-
case IOR_MUTE:
// MUTE falls through to decline
+ accept = false;
case IOR_DECLINE:
- // DECLINE. The math for the dialog works, because the decline
- // for inventory_offered, task_inventory_offer or
- // group_notice_inventory is 2 greater than the offer integer value.
- // Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED,
- // or IM_GROUP_NOTICE_INVENTORY_DECLINED
default:
// close button probably (or any of the fall-throughs from above)
- msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
- // send the message
- msg->sendReliable(mHost);
-
- if (gSavedSettings.getBOOL("LogInventoryDecline"))
- {
- LLStringUtil::format_map_t log_message_args;
- log_message_args["DESC"] = mDesc;
- log_message_args["NAME"] = mFromName;
- log_message = LLTrans::getString("InvOfferDecline", log_message_args);
-
- LLSD args;
- args["MESSAGE"] = log_message;
- LLNotificationsUtil::add("SystemMessageTip", args);
- }
-
- if (is_do_not_disturb && (!mFromGroup && !mFromObject))
+ destination = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if (accept && LLMuteList::getInstance()->isMuted(mFromID, mFromName))
{
- send_do_not_disturb_message(msg,mFromID);
+ // Note: muted offers are usually declined automatically,
+ // but user can mute object after receiving message
+ accept = false;
}
break;
}
-
- if(opener)
- {
- gInventory.addObserver(opener);
- }
+
+ sendReceiveResponse(accept, destination);
if(!mPersist)
{
@@ -4045,6 +4027,8 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList);
S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList);
+ LL_DEBUGS("Messaging", "Motion") << "Processing " << num_blocks << " Animations" << LL_ENDL;
+
//clear animation flags
avatarp->mSignaledAnimations.clear();
@@ -4057,8 +4041,6 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i);
mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i);
- LL_DEBUGS("Messaging") << "Anim sequence ID: " << anim_sequence_id << LL_ENDL;
-
avatarp->mSignaledAnimations[animation_id] = anim_sequence_id;
// *HACK: Disabling flying mode if it has been enabled shortly before the agent
@@ -4097,6 +4079,14 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)
avatarp->mAnimationSources.insert(LLVOAvatar::AnimationSourceMap::value_type(object_id, animation_id));
}
}
+ LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id
+ << " Animation id: " << animation_id
+ << " From block: " << object_id << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("Messaging", "Motion") << "Anim sequence ID: " << anim_sequence_id
+ << " Animation id: " << animation_id << LL_ENDL;
}
}
}
@@ -5163,12 +5153,27 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
}
}
- // Error Notification can come with and without reason
- if (notificationID == "JoinGroupError" && llsdBlock.has("reason"))
- {
- LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock);
- return true;
- }
+ // Error Notification can come with and without reason
+ if (notificationID == "JoinGroupError")
+ {
+ if (llsdBlock.has("reason"))
+ {
+ LLNotificationsUtil::add("JoinGroupErrorReason", llsdBlock);
+ return true;
+ }
+ if (llsdBlock.has("group_id"))
+ {
+ LLGroupData agent_gdatap;
+ bool is_member = gAgent.getGroupData(llsdBlock["group_id"].asUUID(), agent_gdatap);
+ if (is_member)
+ {
+ LLSD args;
+ args["reason"] = LLTrans::getString("AlreadyInGroup");
+ LLNotificationsUtil::add("JoinGroupErrorReason", args);
+ return true;
+ }
+ }
+ }
LLNotificationsUtil::add(notificationID, llsdBlock);
return true;
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index 2d6636f30d..78829a6a56 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -254,7 +254,7 @@ public:
/*virtual*/ void fromLLSD(const LLSD& params);
/*virtual*/ void handleRespond(const LLSD& notification, const LLSD& response);
- void send_auto_receive_response(void);
+ void send_auto_receive_response() { sendReceiveResponse(true, mFolderID); }
// TODO - replace all references with handleRespond()
bool inventory_offer_callback(const LLSD& notification, const LLSD& response);
@@ -264,6 +264,7 @@ private:
void initRespondFunctionMap();
std::string getSanitizedDescription();
+ void sendReceiveResponse(bool accept, const LLUUID &destination_folder_id);
typedef boost::function<bool (const LLSD&, const LLSD&)> respond_function_t;
typedef std::map<std::string, respond_function_t> respond_function_map_t;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 1353a27982..8d7bfa42ed 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -142,6 +142,9 @@ const F32 PHYSICS_TIMESTEP = 1.f / 45.f;
const U32 MAX_INV_FILE_READ_FAILS = 25;
const S32 MAX_OBJECT_BINARY_DATA_SIZE = 60 + 16;
+const F64 INVENTORY_UPDATE_WAIT_TIME_DESYNC = 5; // seconds
+const F64 INVENTORY_UPDATE_WAIT_TIME_OUTDATED = 1;
+
static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object");
// static
@@ -269,6 +272,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mPixelArea(1024.f),
mInventory(NULL),
mInventorySerialNum(0),
+ mExpectedInventorySerialNum(0),
mInvRequestState(INVENTORY_REQUEST_STOPPED),
mInvRequestXFerId(0),
mInventoryDirty(FALSE),
@@ -1279,7 +1283,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
case (60 + 16):
// pull out collision normal for avatar
- htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@@ -1287,23 +1291,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
this_update_precision = 32;
// this is a terse update
// pos
- htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// vel
- htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// acc
- htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// theta
{
LLVector3 vec;
- htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
new_rot.unpackFromVector3(vec);
}
count += sizeof(LLVector3);
// omega
- htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
if (new_angv.isExactlyZero())
{
// reset rotation time
@@ -1319,7 +1323,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
break;
case(32 + 16):
// pull out collision normal for avatar
- htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@@ -1329,7 +1333,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// This is a terse 16 update, so treat data as an array of U16's.
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1340,7 +1344,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1351,7 +1355,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size)));
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1362,7 +1366,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size)));
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4);
+ htolememcpy(valswizzle, &data[count], MVT_U16Quat, 4);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1374,7 +1378,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1570,7 +1574,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
{
case(60 + 16):
// pull out collision normal for avatar
- htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@@ -1578,23 +1582,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// this is a terse 32 update
// pos
this_update_precision = 32;
- htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// vel
- htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// acc
- htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
count += sizeof(LLVector3);
// theta
{
LLVector3 vec;
- htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
new_rot.unpackFromVector3(vec);
}
count += sizeof(LLVector3);
// omega
- htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ htolememcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
if (new_angv.isExactlyZero())
{
// reset rotation time
@@ -1610,7 +1614,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
break;
case(32 + 16):
// pull out collision normal for avatar
- htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ htolememcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
((LLVOAvatar*)this)->setFootPlane(collision_plane);
count += sizeof(LLVector4);
// fall through
@@ -1620,7 +1624,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1631,7 +1635,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1642,7 +1646,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size));
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1653,7 +1657,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
U16_to_F32(val[VZ], -size, size));
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8);
+ htolememcpy(valswizzle, &data[count], MVT_U16Quat, 8);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -1665,7 +1669,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
#ifdef LL_BIG_ENDIAN
- htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ htolememcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
val = valswizzle;
#else
val = (U16 *) &data[count];
@@ -2802,13 +2806,13 @@ void LLViewerObject::doUpdateInventory(
{
// best guess.
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
- --mInventorySerialNum;
+ --mExpectedInventorySerialNum;
}
else
{
// dummy it up.
perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
- --mInventorySerialNum;
+ --mExpectedInventorySerialNum;
}
}
LLViewerInventoryItem* oldItem = item;
@@ -2816,7 +2820,11 @@ void LLViewerObject::doUpdateInventory(
new_item->setPermissions(perm);
mInventory->push_front(new_item);
doInventoryCallback();
- ++mInventorySerialNum;
+ ++mExpectedInventorySerialNum;
+ }
+ else if (is_new)
+ {
+ ++mExpectedInventorySerialNum;
}
}
@@ -2883,7 +2891,7 @@ void LLViewerObject::moveInventory(const LLUUID& folder_id,
if(!item->getPermissions().allowCopyBy(gAgent.getID()))
{
deleteInventoryItem(item_id);
- ++mInventorySerialNum;
+ ++mExpectedInventorySerialNum;
}
}
}
@@ -2974,6 +2982,8 @@ void LLViewerObject::fetchInventoryFromServer()
if (!isInventoryPending())
{
delete mInventory;
+
+ // Results in processTaskInv
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_RequestTaskInventory);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -2983,11 +2993,44 @@ void LLViewerObject::fetchInventoryFromServer()
msg->addU32Fast(_PREHASH_LocalID, mLocalID);
msg->sendReliable(mRegionp->getHost());
- // this will get reset by dirtyInventory or doInventoryCallback
+ // This will get reset by doInventoryCallback or processTaskInv
mInvRequestState = INVENTORY_REQUEST_PENDING;
}
}
+void LLViewerObject::fetchInventoryDelayed(const F64 &time_seconds)
+{
+ // unless already waiting, drop previous request and shedule an update
+ if (mInvRequestState != INVENTORY_REQUEST_WAIT)
+ {
+ if (mInvRequestXFerId != 0)
+ {
+ // abort download.
+ gXferManager->abortRequestById(mInvRequestXFerId, -1);
+ mInvRequestXFerId = 0;
+ }
+ mInvRequestState = INVENTORY_REQUEST_WAIT; // affects isInventoryPending()
+ LLCoros::instance().launch("LLViewerObject::fetchInventoryDelayedCoro()",
+ boost::bind(&LLViewerObject::fetchInventoryDelayedCoro, mID, time_seconds));
+ }
+}
+
+//static
+void LLViewerObject::fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds)
+{
+ llcoro::suspendUntilTimeout(time_seconds);
+ LLViewerObject *obj = gObjectList.findObject(task_inv);
+ if (obj)
+ {
+ // Might be good idea to prolong delay here in case expected serial changed.
+ // As it is, it will get a response with obsolete serial and will delay again.
+
+ // drop waiting state to unlock isInventoryPending()
+ obj->mInvRequestState = INVENTORY_REQUEST_STOPPED;
+ obj->fetchInventoryFromServer();
+ }
+}
+
LLControlAvatar *LLViewerObject::getControlAvatar()
{
return getRootEdit()->mControlAvatar.get();
@@ -3146,74 +3189,97 @@ S32 LLFilenameAndTask::sCount = 0;
// static
void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
{
- LLUUID task_id;
- msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
- LLViewerObject* object = gObjectList.findObject(task_id);
- if(!object)
- {
- LL_WARNS() << "LLViewerObject::processTaskInv object "
- << task_id << " does not exist." << LL_ENDL;
- return;
- }
+ LLUUID task_id;
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
+ LLViewerObject* object = gObjectList.findObject(task_id);
+ if (!object)
+ {
+ LL_WARNS() << "LLViewerObject::processTaskInv object "
+ << task_id << " does not exist." << LL_ENDL;
+ return;
+ }
- LLFilenameAndTask* ft = new LLFilenameAndTask;
- ft->mTaskID = task_id;
- // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
- msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+ LLFilenameAndTask* ft = new LLFilenameAndTask;
+ ft->mTaskID = task_id;
+ // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
+ msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
- if (ft->mSerial < object->mInventorySerialNum)
- {
- // viewer did some changes to inventory that were not saved yet.
- LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
- object->mInventorySerialNum = ft->mSerial;
- }
+ if (ft->mSerial == object->mInventorySerialNum
+ && ft->mSerial < object->mExpectedInventorySerialNum)
+ {
+ // Loop Protection.
+ // We received same serial twice.
+ // Viewer did some changes to inventory that couldn't be saved server side
+ // or something went wrong to cause serial to be out of sync.
+ // Drop xfer and restart after some time, assign server's value as expected
+ LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
+ object->mExpectedInventorySerialNum = ft->mSerial;
+ object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC);
+ }
+ else if (ft->mSerial < object->mExpectedInventorySerialNum)
+ {
+ // Out of date message, record to current serial for loop protection, but do not load it
+ // Drop xfer and restart after some time
+ if (ft->mSerial < object->mInventorySerialNum)
+ {
+ LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL;
+ }
+ object->mInventorySerialNum = ft->mSerial;
+ object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED);
+ }
+ else if (ft->mSerial >= object->mExpectedInventorySerialNum)
+ {
+ // We received version we expected or newer. Load it.
+ object->mInventorySerialNum = ft->mSerial;
+ object->mExpectedInventorySerialNum = ft->mSerial;
- std::string unclean_filename;
- msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
- ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+ std::string unclean_filename;
+ msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
+ ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
- if(ft->mFilename.empty())
- {
- LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
- // mock up some inventory to make a drop target.
- if(object->mInventory)
- {
- object->mInventory->clear(); // will deref and delete it
- }
- else
- {
- object->mInventory = new LLInventoryObject::object_list_t();
- }
- LLPointer<LLInventoryObject> obj;
- obj = new LLInventoryObject(object->mID, LLUUID::null,
- LLAssetType::AT_CATEGORY,
- "Contents");
- object->mInventory->push_front(obj);
- object->doInventoryCallback();
- delete ft;
- return;
- }
- U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
- ft->mFilename, LL_PATH_CACHE,
- object->mRegionp->getHost(),
- TRUE,
- &LLViewerObject::processTaskInvFile,
- (void**)ft,
- LLXferManager::HIGH_PRIORITY);
- if (object->mInvRequestState == INVENTORY_XFER)
- {
- if (new_id > 0 && new_id != object->mInvRequestXFerId)
- {
- // we started new download.
- gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
- object->mInvRequestXFerId = new_id;
- }
- }
- else
- {
- object->mInvRequestState = INVENTORY_XFER;
- object->mInvRequestXFerId = new_id;
- }
+ if (ft->mFilename.empty())
+ {
+ LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
+ // mock up some inventory to make a drop target.
+ if (object->mInventory)
+ {
+ object->mInventory->clear(); // will deref and delete it
+ }
+ else
+ {
+ object->mInventory = new LLInventoryObject::object_list_t();
+ }
+ LLPointer<LLInventoryObject> obj;
+ obj = new LLInventoryObject(object->mID, LLUUID::null,
+ LLAssetType::AT_CATEGORY,
+ "Contents");
+ object->mInventory->push_front(obj);
+ object->doInventoryCallback();
+ delete ft;
+ return;
+ }
+ U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+ ft->mFilename, LL_PATH_CACHE,
+ object->mRegionp->getHost(),
+ TRUE,
+ &LLViewerObject::processTaskInvFile,
+ (void**)ft,
+ LLXferManager::HIGH_PRIORITY);
+ if (object->mInvRequestState == INVENTORY_XFER)
+ {
+ if (new_id > 0 && new_id != object->mInvRequestXFerId)
+ {
+ // we started new download.
+ gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
+ object->mInvRequestXFerId = new_id;
+ }
+ }
+ else
+ {
+ object->mInvRequestState = INVENTORY_XFER;
+ object->mInvRequestXFerId = new_id;
+ }
+ }
}
void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -3227,6 +3293,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
&& ft->mSerial >= object->mInventorySerialNum)
{
object->mInventorySerialNum = ft->mSerial;
+ LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL;
+ if (ft->mSerial < object->mExpectedInventorySerialNum)
+ {
+ // User managed to change something while inventory was loading
+ LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL;
+ }
+
if (object->loadTaskInvFile(ft->mFilename))
{
@@ -3376,7 +3449,7 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
msg->addUUIDFast(_PREHASH_ItemID, item_id);
msg->sendReliable(mRegionp->getHost());
deleteInventoryItem(item_id);
- ++mInventorySerialNum;
+ ++mExpectedInventorySerialNum;
}
bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 873b300489..e9ae26939a 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -474,6 +474,8 @@ public:
void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.
void updateTextureInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
LLInventoryObject* getInventoryObject(const LLUUID& item_id);
+
+ // Get content except for root category
void getInventoryContents(LLInventoryObject::object_list_t& objects);
LLInventoryObject* getInventoryRoot();
LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id);
@@ -623,9 +625,13 @@ private:
static void initObjectDataMap();
- // forms task inventory request if none are pending
+ // forms task inventory request if none are pending, marks request as pending
void fetchInventoryFromServer();
+ // forms task inventory request after some time passed, marks request as pending
+ void fetchInventoryDelayed(const F64 &time_seconds);
+ static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds);
+
public:
//
// Viewer-side only types - use the LL_PCODE_APP mask.
@@ -804,12 +810,14 @@ protected:
typedef std::list<LLInventoryCallbackInfo*> callback_list_t;
callback_list_t mInventoryCallbacks;
S16 mInventorySerialNum;
+ S16 mExpectedInventorySerialNum;
enum EInventoryRequestState
{
INVENTORY_REQUEST_STOPPED,
- INVENTORY_REQUEST_PENDING,
- INVENTORY_XFER
+ INVENTORY_REQUEST_WAIT, // delay before requesting
+ INVENTORY_REQUEST_PENDING, // just did fetchInventoryFromServer()
+ INVENTORY_XFER // processed response from 'fetch', now doing an xfer
};
EInventoryRequestState mInvRequestState;
U64 mInvRequestXFerId;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index c3cf07e9c7..ea846805c2 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -938,6 +938,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
mLeftMouseDown = down;
buttonname = "Left Double Click";
break;
+ case LLMouseHandler::CLICK_BUTTON4:
+ buttonname = "Button 4";
+ break;
+ case LLMouseHandler::CLICK_BUTTON5:
+ buttonname = "Button 5";
+ break;
}
LLView::sMouseHandlerMessage.clear();
@@ -1115,7 +1121,7 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK m
BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = TRUE;
- LLVoiceClient::getInstance()->middleMouseState(true);
+ LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, true);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
// Always handled as far as the OS is concerned.
@@ -1267,17 +1273,47 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
return result;
}
-
+
BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
- LLVoiceClient::getInstance()->middleMouseState(false);
+ LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, false);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
// Always handled as far as the OS is concerned.
return TRUE;
}
+BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down)
+{
+ switch (button)
+ {
+ case 4:
+ LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON4, down);
+ handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON4, down);
+ break;
+ case 5:
+ LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON5, down);
+ handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON5, down);
+ break;
+ default:
+ break;
+ }
+
+ // Always handled as far as the OS is concerned.
+ return TRUE;
+}
+
+BOOL LLViewerWindow::handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button)
+{
+ return handleOtherMouse(window, pos, mask, button, TRUE);
+}
+
+BOOL LLViewerWindow::handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button)
+{
+ return handleOtherMouse(window, pos, mask, button, FALSE);
+}
+
// WARNING: this is potentially called multiple times per frame
void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask)
{
@@ -3331,7 +3367,8 @@ void LLViewerWindow::updateUI()
LLRect screen_sticky_rect = mRootView->getLocalRect();
S32 local_x, local_y;
- if (gSavedSettings.getBOOL("DebugShowXUINames"))
+ static LLCachedControl<bool> debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0);
+ if (debug_show_xui_names)
{
LLToolTip::Params params;
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 071a3632dd..d084642fdc 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -192,7 +192,10 @@ public:
/*virtual*/ BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
- /*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ /*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
+ /*virtual*/ BOOL handleOtherMouseDown(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
+ /*virtual*/ BOOL handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK mask, S32 button);
+ BOOL handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down);
/*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data);
void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
void handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask);
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index b5db5d4a48..a974c66ee4 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -78,6 +78,7 @@
#include "llselectmgr.h"
#include "llsprite.h"
#include "lltargetingmotion.h"
+#include "lltoolmgr.h"
#include "lltoolmorph.h"
#include "llviewercamera.h"
#include "llviewertexlayer.h"
@@ -5646,7 +5647,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
}
else
{
- LL_WARNS() << "Failed to start motion!" << LL_ENDL;
+ LL_WARNS("Motion") << "Failed to start motion!" << LL_ENDL;
}
}
else //stop animation
@@ -5753,13 +5754,13 @@ LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
{
- LL_DEBUGS() << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
+ LL_DEBUGS("Motion") << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LLUUID remap_id = remapMotionID(id);
if (remap_id != id)
{
- LL_DEBUGS() << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
+ LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
}
if (isSelf() && remap_id == ANIM_AGENT_AWAY)
@@ -5775,13 +5776,13 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
//-----------------------------------------------------------------------------
BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
{
- LL_DEBUGS() << "motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
+ LL_DEBUGS("Motion") << "Motion requested " << id.asString() << " " << gAnimLibrary.animationName(id) << LL_ENDL;
LLUUID remap_id = remapMotionID(id);
if (remap_id != id)
{
- LL_DEBUGS() << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
+ LL_DEBUGS("Motion") << "motion resultant " << remap_id.asString() << " " << gAnimLibrary.animationName(remap_id) << LL_ENDL;
}
if (isSelf())
@@ -7320,6 +7321,19 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
{
gAgentCamera.changeCameraToMouselook();
}
+
+ if (gAgentCamera.getFocusOnAvatar() && LLToolMgr::getInstance()->inEdit())
+ {
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
+ if (node && node->mValid)
+ {
+ LLViewerObject* root_object = node->getObject();
+ if (root_object == sit_object)
+ {
+ LLFloaterTools::sPreviousFocusOnAvatar = true;
+ }
+ }
+ }
}
if (mDrawable.isNull())
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 5c107cc10b..bce399a940 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -125,7 +125,7 @@ LLVoiceClient::LLVoiceClient()
mPTTDirty(true),
mPTT(true),
mUsePTT(true),
- mPTTIsMiddleMouse(false),
+ mPTTMouseButton(0),
mPTTKey(0),
mPTTIsToggle(false),
mUserPTTState(false),
@@ -638,13 +638,22 @@ bool LLVoiceClient::getPTTIsToggle()
void LLVoiceClient::setPTTKey(std::string &key)
{
+ // Value is stored as text for readability
if(key == "MiddleMouse")
{
- mPTTIsMiddleMouse = true;
+ mPTTMouseButton = LLMouseHandler::CLICK_MIDDLE;
+ }
+ else if(key == "MouseButton4")
+ {
+ mPTTMouseButton = LLMouseHandler::CLICK_BUTTON4;
+ }
+ else if (key == "MouseButton5")
+ {
+ mPTTMouseButton = LLMouseHandler::CLICK_BUTTON5;
}
else
{
- mPTTIsMiddleMouse = false;
+ mPTTMouseButton = 0;
if(!LLKeyboard::keyFromString(key, &mPTTKey))
{
// If the call failed, don't match any key.
@@ -681,7 +690,7 @@ void LLVoiceClient::keyDown(KEY key, MASK mask)
return;
}
- if (!mPTTIsMiddleMouse && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
+ if (mPTTMouseButton == 0 && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
{
bool down = gKeyboard->getKeyDown(mPTTKey);
if (down)
@@ -693,7 +702,7 @@ void LLVoiceClient::keyDown(KEY key, MASK mask)
}
void LLVoiceClient::keyUp(KEY key, MASK mask)
{
- if (!mPTTIsMiddleMouse && (key == mPTTKey))
+ if (mPTTMouseButton == 0 && (key == mPTTKey))
{
bool down = gKeyboard->getKeyDown(mPTTKey);
if (!down)
@@ -702,9 +711,9 @@ void LLVoiceClient::keyUp(KEY key, MASK mask)
}
}
}
-void LLVoiceClient::middleMouseState(bool down)
+void LLVoiceClient::updateMouseState(S32 click, bool down)
{
- if(mPTTIsMiddleMouse && LLAgent::isActionAllowed("speak"))
+ if(mPTTMouseButton == click && LLAgent::isActionAllowed("speak"))
{
inputUserControlState(down);
}
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 758e9cecd7..fbc85fd977 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -418,8 +418,8 @@ public:
// PTT key triggering
void keyDown(KEY key, MASK mask);
void keyUp(KEY key, MASK mask);
- void middleMouseState(bool down);
-
+ void updateMouseState(S32 click, bool down);
+
boost::signals2::connection MicroChangedCallback(const micro_changed_signal_t::slot_type& cb ) { return mMicroChangedSignal.connect(cb); }
@@ -485,7 +485,7 @@ protected:
bool mPTT;
bool mUsePTT;
- bool mPTTIsMiddleMouse;
+ S32 mPTTMouseButton;
KEY mPTTKey;
bool mPTTIsToggle;
bool mUserPTTState;
diff --git a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
index c1458977ca..5cae643e44 100644
--- a/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_gesture_gear.xml
@@ -12,6 +12,16 @@
function="Gesture.Action.ToogleActiveState" />
</menu_item_call>
<menu_item_call
+ label="Rename"
+ layout="topleft"
+ name="rename">
+ <on_click
+ function="Gesture.Action.Rename" />
+ <on_enable
+ function="Gesture.EnableAction"
+ parameter="rename_gesture" />
+ </menu_item_call>
+ <menu_item_call
label="Copy"
layout="topleft"
name="copy_gesture">
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 7bb7b5d62c..ab42b76b3b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -17,9 +17,11 @@
</menu_item_call>
<menu_item_call
label="Appearance..."
- name="ChangeOutfit">
+ name="ChangeOutfit"
+ shortcut="control|O">
<menu_item_call.on_click
- function="CustomizeAvatar" />
+ function="Floater.ToggleOrBringToFront"
+ parameter="appearance" />
<menu_item_call.on_enable
function="Edit.EnableCustomizeAvatar" />
</menu_item_call>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index f72767cceb..30e8f7cedc 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2480,6 +2480,13 @@ Sorry, but the system was unable to complete your region crossing in a timely fa
</notification>
<notification
icon="alertmodal.tga"
+ name="preexisting_tport"
+ type="alertmodal">
+ <tag>fail</tag>
+Sorry, but the system was unable to start your teleport. Please try again in a few minutes.
+ </notification>
+ <notification
+ icon="alertmodal.tga"
name="no_host"
type="alertmodal">
<tag>fail</tag>
@@ -3093,6 +3100,29 @@ See https://wiki.secondlife.com/wiki/Adding_Spelling_Dictionaries
<notification
icon="alertmodal.tga"
+ label="Rename Gesture"
+ name="RenameGesture"
+ type="alertmodal">
+ New gesture name:
+ <tag>confirm</tag>
+ <form name="form">
+ <input name="new_name" type="text" width="300">
+ [NAME]
+ </input>
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Cancel"
+ text="Cancel"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="RemoveFromFriends"
type="alertmodal">
<tag>friendship</tag>
@@ -3547,6 +3577,30 @@ You can either check your Internet connection and try again in a few minutes, cl
<notification
icon="alertmodal.tga"
+ name="LoginPacketNeverReceivedNoTP"
+ type="alertmodal">
+ <tag>fail</tag>
+We&apos;re having trouble connecting. There may be a problem with your Internet connection or the [SECOND_LIFE_GRID].
+
+You can either check your Internet connection and try again in a few minutes or click Help to view the [SUPPORT_SITE].
+ <url option="1" name="url">
+ http://secondlife.com/support/
+ </url>
+ <form name="form">
+ <button
+ default="true"
+ index="0"
+ name="OK"
+ text="OK"/>
+ <button
+ index="1"
+ name="Help"
+ text="Help"/>
+ </form>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="WelcomeChooseSex"
type="alertmodal">
Your character will appear in a moment.
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 4f0bb9d3b7..8296438d4c 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -143,6 +143,32 @@
name="ui_scale_slider"
top_pad="-14"
width="250" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="33"
+ name="HUD Size:"
+ top_pad="20"
+ width="100">
+ HUD Scale:
+ </text>
+ <slider
+ control_name="HUDScaleFactor"
+ decimal_digits="2"
+ follows="left|top"
+ height="17"
+ increment="0.1"
+ initial_value="1"
+ layout="topleft"
+ left_pad="0"
+ max_val="2.0"
+ min_val="1.0"
+ name="ui_scale_slider"
+ top_pad="-14"
+ width="250" />
<check_box
control_name="ShowScriptErrors"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 8f2e81b9f7..649403184d 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -13,6 +13,14 @@
name="middle_mouse">
Middle Mouse
</panel.string>
+ <panel.string
+ name="button4_mouse">
+ Mouse Button 4
+ </panel.string>
+ <panel.string
+ name="button5_mouse">
+ Mouse Button 5
+ </panel.string>
<slider
control_name="AudioLevelMaster"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 9eedc45aa9..292c2a6293 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2637,6 +2637,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="Debits">Debits</string>
<string name="Total">Total</string>
<string name="NoGroupDataFound">No group data found for group </string>
+ <string name="AlreadyInGroup">You are already in this group </string>
<!-- floater IM bonus_info: When a Linden with Admin/god status receives a new IM this displays the estate (Mainland vs. teen grid) of the source avatar.
This is to help Lindens when answering questions. -->
diff --git a/indra/newview/skins/default/xui/en/teleport_strings.xml b/indra/newview/skins/default/xui/en/teleport_strings.xml
index 5a9a16d344..57f8bb542d 100644
--- a/indra/newview/skins/default/xui/en/teleport_strings.xml
+++ b/indra/newview/skins/default/xui/en/teleport_strings.xml
@@ -39,6 +39,9 @@ Go to &apos;Welcome Island Public&apos; to repeat the tutorial.
<message name="expired_region_handoff">
Sorry, but the system was unable to complete your region crossing in a timely fashion. Please try again in a few minutes.
</message>
+ <message name="preexisting_tport">
+ Sorry, but the system was unable to start your teleport. Please try again in a few minutes.
+ </message>
<message name="no_host">
Unable to find teleport destination. The destination may be temporarily unavailable or no longer exists. Please try again in a few minutes.
</message>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index 08accc39fe..1e4f9e9abb 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -1436,9 +1436,9 @@
<usetemplate name="okcancelbuttons" notext="Продолжить" yestext="Создать аккаунт..."/>
</notification>
<notification name="LoginPacketNeverReceived">
- Возникли неполадки при подключении. Возможно, проблема с вашим подключением к интернету или [SECOND_LIFE_GRID].
+ Возникли неполадки при подключении. Возможно, проблема с вашим подключением к интернету или [SECOND_LIFE_GRID] временно недоступна.
-Варианты ваших действий: проверьте подключение к интернету и повторите попытку через несколько минут, нажмите кнопку «Справка» для перехода к [SUPPORT_SITE] или кнопку «Телепортация», чтобы телепортироваться домой.
+Вы можете проверить подключение к интернету, повторить попытку через несколько минут, нажать кнопку «Справка» для перехода на [SUPPORT_SITE] или нажать кнопку «Телепортация», чтобы телепортироваться домой.
<url name="url">
http://secondlife.com/support/
</url>