diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index b5b8e2f022..f73cc3aaa4 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -32,6 +32,8 @@
#include "llagent.h"
#include "llappearancemgr.h"
#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llnotifications.h"
#include "lltextbox.h"
#include "llviewercontrol.h"
@@ -181,40 +183,75 @@ void LLFloaterLinkReplace::onStartClicked()
LL_WARNS() << "Cannot replace. Source and target are identical." << LL_ENDL;
return;
}
+
+ const LLUUID& source_item_id = gInventory.getLinkedItemID(mSourceUUID);
+ LLViewerInventoryItem *source_item = gInventory.getItem(source_item_id);
+ const LLUUID& target_item_id = gInventory.getLinkedItemID(mTargetUUID);
+ LLViewerInventoryItem *target_item = gInventory.getItem(target_item_id);
- LLInventoryModel::cat_array_t cat_array;
- LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
- gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
- cat_array,
- mRemainingInventoryItems,
- LLInventoryModel::INCLUDE_TRASH,
- is_linked_item_match);
- LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
- if (mRemainingInventoryItems.size() > 0)
+ LLNotification::Params params("ConfirmReplaceLink");
+ params.functor.function(boost::bind(&LLFloaterLinkReplace::onStartClickedResponse, this, _1, _2));
+ if (source_item && source_item->isWearableType() && source_item->getWearableType() <= LLWearableType::WT_EYES)
{
- LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
- // FIRE-17695 - option to bulk delete links.
- //if (target_item)
- if (target_item || mDeleteOnly)
- //
+ if(target_item && target_item->isWearableType() && source_item->getWearableType() == target_item->getWearableType())
{
- mRemainingItems = (U32)mRemainingInventoryItems.size();
-
- LLStringUtil::format_map_t args;
- args["NUM"] = llformat("%d", mRemainingItems);
- mStatusText->setText(getString("ItemsRemaining", args));
-
- mStartBtn->setEnabled(FALSE);
- mRefreshBtn->setEnabled(FALSE);
-
- mEventTimer.start();
- tick();
+ LLNotifications::instance().forceResponse(params, 0);
}
else
{
- mStatusText->setText(getString("TargetNotFound"));
- LL_WARNS() << "Link replace target not found." << LL_ENDL;
+ LLSD args;
+ args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType());
+ params.substitutions(args);
+ LLNotifications::instance().add(params);
+ }
+ }
+ else
+ {
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+}
+
+void LLFloaterLinkReplace::onStartClickedResponse(const LLSD& notification, const LLSD& response)
+{
+
+ if (LLNotificationsUtil::getSelectedOption(notification, response) == 0)
+ {
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLLinkedItemIDMatches is_linked_item_match(mSourceUUID);
+ gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ mRemainingInventoryItems,
+ LLInventoryModel::INCLUDE_TRASH,
+ is_linked_item_match);
+ LL_INFOS() << "Found " << mRemainingInventoryItems.size() << " inventory links that need to be replaced." << LL_ENDL;
+
+ if (mRemainingInventoryItems.size() > 0)
+ {
+ LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID);
+ // FIRE-17695 - option to bulk delete links.
+ //if (target_item)
+ if (target_item || mDeleteOnly)
+ //
+ {
+ mRemainingItems = (U32)mRemainingInventoryItems.size();
+
+ LLStringUtil::format_map_t args;
+ args["NUM"] = llformat("%d", mRemainingItems);
+ mStatusText->setText(getString("ItemsRemaining", args));
+
+ mStartBtn->setEnabled(FALSE);
+ mRefreshBtn->setEnabled(FALSE);
+
+ mEventTimer.start();
+ tick();
+ }
+ else
+ {
+ mStatusText->setText(getString("TargetNotFound"));
+ LL_WARNS() << "Link replace target not found." << LL_ENDL;
+ }
}
}
}
diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h
index e10febd1cd..614b9c9663 100644
--- a/indra/newview/llfloaterlinkreplace.h
+++ b/indra/newview/llfloaterlinkreplace.h
@@ -95,6 +95,7 @@ public:
private:
void checkEnableStart();
void onStartClicked();
+ void onStartClickedResponse(const LLSD& notification, const LLSD& response);
void decreaseOpenItemCount();
void updateFoundLinks();
void processBatch(LLInventoryModel::item_array_t items);
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index e1b2fa670d..c5b586aa98 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -62,9 +62,8 @@ static const S32 HPAD = 25;
static const S32 BTN_HPAD = 8;
LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal)
- : LLToastPanel(notification),
+ : LLCheckBoxToastPanel(notification),
mDefaultOption( 0 ),
- mCheck(NULL),
mCaution(notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH),
mLabel(notification->getName()),
mLineEditor(NULL)
@@ -361,20 +360,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
}
}
- std::string ignore_label;
-
- if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label);
- }
- if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label);
- }
- else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
- {
- setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label);
- }
+ setCheckBoxes(HPAD, VPAD);
// *TODO: check necessity of this code
//gFloaterView->adjustToFitScreen(this, FALSE);
@@ -394,46 +380,6 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
LLTransientFloaterMgr::GLOBAL, this);
}
-bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::string& check_control )
-{
- mCheck = LLUICtrlFactory::getInstance()->createFromFile("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
-
- if(!mCheck)
- {
- return false;
- }
-
- const LLFontGL* font = mCheck->getFont();
- const S32 LINE_HEIGHT = font->getLineHeight();
-
- std::vector lines;
- boost::split(lines, check_title, boost::is_any_of("\n"));
-
- // Extend dialog for "check next time"
- S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD;
- S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
- max_msg_width = llmax(max_msg_width, check_width);
- S32 dialog_width = max_msg_width + 2 * HPAD;
-
- S32 dialog_height = LLToastPanel::getRect().getHeight();
- dialog_height += LINE_HEIGHT * lines.size();
- dialog_height += LINE_HEIGHT / 2;
-
- LLToastPanel::reshape( dialog_width, dialog_height, FALSE );
-
- S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
-
- // set check_box's attributes
- LLRect check_rect;
- mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT*lines.size()));
- mCheck->setLabel(check_title);
- mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1));
-
- LLToastPanel::addChild(mCheck);
-
- return true;
-}
-
void LLToastAlertPanel::setVisible( BOOL visible )
{
// only make the "ding" sound if it's newly visible
@@ -584,16 +530,3 @@ void LLToastAlertPanel::onButtonPressed( const LLSD& data, S32 button )
mNotification->respond(response); // new notification reponse
}
-
-void LLToastAlertPanel::onClickIgnore(LLUICtrl* ctrl)
-{
- // checkbox sometimes means "hide and do the default" and
- // other times means "warn me again". Yuck. JC
- BOOL check = ctrl->getValue().asBoolean();
- if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
- {
- // question was "show again" so invert value to get "ignore"
- check = !check;
- }
- mNotification->setIgnored(check);
-}
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index d1be5e018e..21310822c4 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -46,7 +46,7 @@ class LLLineEditor;
*/
class LLToastAlertPanel
- : public LLToastPanel
+ : public LLCheckBoxToastPanel
{
LOG_CLASS(LLToastAlertPanel);
public:
@@ -75,13 +75,11 @@ public:
virtual void draw();
virtual void setVisible( BOOL visible );
- bool setCheckBox( const std::string&, const std::string& );
void setCaution(BOOL val = TRUE) { mCaution = val; }
// If mUnique==TRUE only one copy of this message should exist
void setUnique(BOOL val = TRUE) { mUnique = val; }
void setEditTextArgs(const LLSD& edit_args);
- void onClickIgnore(LLUICtrl* ctrl);
void onButtonPressed(const LLSD& data, S32 button);
private:
@@ -106,7 +104,6 @@ private:
std::vector mButtonData;
S32 mDefaultOption;
- LLCheckBoxCtrl* mCheck;
BOOL mCaution;
BOOL mUnique;
LLUIString mLabel;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 5538dc5400..c7fcdcde8a 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -33,6 +33,7 @@
// library includes
#include "lldbstrings.h"
+#include "llcheckboxctrl.h"
#include "lllslconstants.h"
#include "llnotifications.h"
#include "lluiconstants.h"
@@ -59,7 +60,7 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal;
LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)
-: LLToastPanel(notification),
+: LLCheckBoxToastPanel(notification),
LLInstanceTracker(notification->getID())
{
init(rect, show_images);
@@ -434,6 +435,11 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
//.xml file intially makes info panel only follow left/right/top. This is so that when control buttons are added the info panel
//can shift upward making room for the buttons inside mControlPanel. After the buttons are added, the info panel can then be set to follow 'all'.
mInfoPanel->setFollowsAll();
+
+ // Add checkboxes if nessesary.
+ setCheckBoxes(HPAD * 3, VPAD * 4, mInfoPanel);
+
+ // Snap to message, then to checkbox if present
// FIRE-17100: Customizable number of rows in a script dialog
//snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
if (mIsScriptDialog)
@@ -447,6 +453,11 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images )
snapToMessageHeight(mTextBox, LLToastPanel::MAX_TEXT_LENGTH);
}
//
+ if (mCheck)
+ {
+ S32 new_panel_height = mCheck->getRect().getHeight() + getRect().getHeight();
+ reshape(getRect().getWidth(), new_panel_height);
+ }
// reshape the panel to its previous size
if (current_rect.notEmpty())
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index e4a75acfda..a5a637c6fa 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -47,7 +47,7 @@ class LLNotificationForm;
* @deprecated this class will be removed after all toast panel types are
* implemented in separate classes.
*/
-class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker
+class LLToastNotifyPanel: public LLCheckBoxToastPanel, public LLInstanceTracker
{
public:
/**
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index c96eb36320..1840540473 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -27,6 +27,7 @@
#include "llviewerprecompiledheaders.h"
#include "lldbstrings.h"
+#include "llcheckboxctrl.h"
#include "llpanelgenerictip.h"
#include "llpanelonlinestatus.h"
#include "llnotifications.h"
@@ -34,6 +35,8 @@
#include "lltoastpanel.h"
#include "lltoastscriptquestion.h"
+#include
+
//static
const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
// 'magic numbers', consider initializing (512+20) part from xml/notifications
@@ -151,3 +154,93 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(
return res;
}
+
+LLCheckBoxToastPanel::LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf)
+: LLToastPanel(p_ntf),
+mCheck(NULL)
+{
+
+}
+
+void LLCheckBoxToastPanel::setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view)
+{
+ std::string ignore_label;
+ LLNotificationFormPtr form = mNotification->getForm();
+
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+ else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+ {
+ setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label, boost::bind(&LLCheckBoxToastPanel::onCommitCheckbox, this, _1), h_pad, v_pad, parent_view);
+ }
+}
+
+bool LLCheckBoxToastPanel::setCheckBox(const std::string& check_title,
+ const std::string& check_control,
+ const commit_signal_t::slot_type& cb,
+ const S32 &h_pad,
+ const S32 &v_pad,
+ LLView *parent_view)
+{
+ mCheck = LLUICtrlFactory::getInstance()->createFromFile("alert_check_box.xml", this, LLPanel::child_registry_t::instance());
+
+ if (!mCheck)
+ {
+ return false;
+ }
+
+ const LLFontGL* font = mCheck->getFont();
+ const S32 LINE_HEIGHT = font->getLineHeight();
+
+ std::vector lines;
+ boost::split(lines, check_title, boost::is_any_of("\n"));
+
+ // Extend dialog for "check next time"
+ S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * h_pad;
+ S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line
+ max_msg_width = llmax(max_msg_width, check_width);
+ S32 dialog_width = max_msg_width + 2 * h_pad;
+
+ S32 dialog_height = LLToastPanel::getRect().getHeight();
+ dialog_height += LINE_HEIGHT * lines.size();
+ dialog_height += LINE_HEIGHT / 2;
+
+ LLToastPanel::reshape(dialog_width, dialog_height, FALSE);
+
+ S32 msg_x = (LLToastPanel::getRect().getWidth() - max_msg_width) / 2;
+
+ // set check_box's attributes
+ LLRect check_rect;
+ mCheck->setRect(check_rect.setOriginAndSize(msg_x, v_pad + BTN_HEIGHT + LINE_HEIGHT / 2, max_msg_width, LINE_HEIGHT*lines.size()));
+ mCheck->setLabel(check_title);
+ mCheck->setCommitCallback(cb);
+
+ if (parent_view)
+ {
+ // assume that width and height autoadjusts to toast
+ parent_view->addChild(mCheck);
+ }
+ else
+ {
+ LLToastPanel::addChild(mCheck);
+ }
+
+ return true;
+}
+
+void LLCheckBoxToastPanel::onCommitCheckbox(LLUICtrl* ctrl)
+{
+ BOOL check = ctrl->getValue().asBoolean();
+ if (mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN)
+ {
+ // question was "show again" so invert value to get "ignore"
+ check = !check;
+ }
+ mNotification->setIgnored(check);
+}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 6a9b72a5ae..f4c758ade9 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -64,4 +64,23 @@ protected:
S32 computeSnappedToMessageHeight(LLTextBase* message, S32 maxLineCount);
};
+class LLCheckBoxCtrl;
+
+// Wrapper with support for 'don't ask again' checkbox
+class LLCheckBoxToastPanel : public LLToastPanel
+{
+public:
+ LLCheckBoxToastPanel(const LLNotificationPtr& p_ntf);
+ virtual ~LLCheckBoxToastPanel() {};
+
+ // set checkboxes acording to defaults from form
+ void setCheckBoxes(const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+ // set single checkbox
+ bool setCheckBox(const std::string&, const std::string&, const commit_signal_t::slot_type& cb, const S32 &h_pad, const S32 &v_pad, LLView *parent_view = NULL);
+protected:
+ void onCommitCheckbox(LLUICtrl* ctrl);
+
+ LLCheckBoxCtrl* mCheck;
+};
+
#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 94e77f0dc8..d03c00ae8c 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -154,6 +154,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
@@ -3058,6 +3061,8 @@ void LLViewerObject::fetchInventoryFromServer()
if (!isInventoryPending())
{
delete mInventory;
+
+ // Results in processTaskInv
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_RequestTaskInventory);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -3067,11 +3072,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();
@@ -3258,30 +3296,32 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
// 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)
+ 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
+ // 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);
}
-
- if (ft->mSerial < object->mExpectedInventorySerialNum)
+ else if (ft->mSerial < object->mExpectedInventorySerialNum)
{
- // out of date message, record to current serial for loop protection, but do not load it
- // just drop xfer to restart on idle
+ // 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() << "Somehow task serial decreased, out of order packet?" << LL_ENDL;
+ LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL;
}
object->mInventorySerialNum = ft->mSerial;
- object->mInvRequestXFerId = 0;
- object->mInvRequestState = INVENTORY_REQUEST_STOPPED;
+ 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;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 69c541794f..47feafe5fd 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -639,9 +639,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.
@@ -828,8 +832,9 @@ protected:
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/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 12f492b747..ed075aeed9 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -365,16 +365,19 @@ void update_statistics()
record(LLStatViewer::REBUILD_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Sort Draw State")));
record(LLStatViewer::RENDER_STACKTIME, last_frame_recording.getSum(*stat_type_t::getInstance("Render Geometry")));
- LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
- if (cdp)
+ if (gAgent.getRegion() && isAgentAvatarValid())
{
- sample(LLStatViewer::SIM_PING, F64Milliseconds (cdp->getPingDelay()));
- gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1);
- gSimPingCount++;
- }
- else
- {
- sample(LLStatViewer::SIM_PING, U32Seconds(10));
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
+ if (cdp)
+ {
+ sample(LLStatViewer::SIM_PING, F64Milliseconds(cdp->getPingDelay()));
+ gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1);
+ gSimPingCount++;
+ }
+ else
+ {
+ sample(LLStatViewer::SIM_PING, U32Seconds(10));
+ }
}
if (LLViewerStats::instance().getRecording().getSum(LLStatViewer::FPS))
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index ddc026ac14..6b85cb3eb2 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8876,8 +8876,7 @@ void LLPipeline::renderDeferredLighting()
}
const LLViewerObject *vobj = drawablep->getVObj();
- if(vobj && vobj->getAvatar()
- && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList())
+ if((vobj && vobj->getAvatar() && (vobj->getAvatar()->isTooComplex() || vobj->getAvatar()->isInMuteList()))
|| (vobj && dist_vec(vobj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip))
{
continue;
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 9c3386d126..8da73bb855 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -6471,6 +6471,20 @@ Are you sure you want to permanently delete the contents of your Lost And Found?
yestext="Yes"/>
+
+You're about to replace '[TYPE]' body part link with the item which doesn't match the type.
+Are you sure you want to proceed?
+ confirm
+
+
+
-
+
No se pudo hacer la compra
diff --git a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
index b7db6f5383..c295172abf 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -1,25 +1,67 @@
-
-
- Acheter [LINDENS] L$ pour environ [LOCALAMOUNT]
- Vous avez besoin de plus de L$
- Contact du LindeX en cours...
- Acheter des L$
- Je possède
- [AMT] L$
- Je veux acheter
- L$
- Pour
- environ [LOCALAMOUNT]
- Estimation en cours...
- [ACTION]
- Mon nouveau solde sera de
- [AMT] L$
- [http://www.secondlife.com/my/account/payment_method_management.php méthode de payement] | [http://www.secondlife.com/my/account/currency.php devise]
- Ressaisissez le montant pour voir le taux de change actuel
- Confirmer cet achat n'achète que des L$, pas l'objet.
- Vous n'achetez pas assez de L$. Veuillez augmenter le montant.
+
+
+
+ Achetez [LINDENS] L$ pour environ [LOCALAMOUNT]
+
+
+ Plus de L$ sont requis
+
+
+ En train de contacter
+le Lindex...
+
+
+ Acheter des L$
+
+
+ J'ai
+
+
+ [AMT] L$
+
+
+ Je veux acheter
+
+
+ L$
+
+
+ 1234
+
+
+ Pour
+
+
+ environ [LOCALAMOUNT]
+
+
+ Estimation en cours...
+
+
+ [ACTION]
+
+
+ Mon nouveau solde sera de
+
+
+ [AMT] L$
+
+
+ [http://www.secondlife.com/my/account/payment_method_management.php mode de paiement] | [http://www.secondlife.com/my/account/currency.php devise]
+
+
+ Saisissez à nouveau le montant pour voir le taux de change actuel.
+
+
+ Confirmer cet achat n'achète que des L$, pas l'objet.
+
+
+ Vous n'achetez pas assez de L$. Veuillez augmenter le montant.
+
- Achat impossible
-
+
+ Achat impossible
+
+
diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency.xml b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
index 6d71b17c5e..b58dbd3174 100644
--- a/indra/newview/skins/default/xui/it/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/it/floater_buy_currency.xml
@@ -51,7 +51,7 @@ l'oggetto.
-
+
Impossibile acquistare