summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/lllineeditor.cpp2
-rw-r--r--indra/llui/llurlentry.cpp32
-rw-r--r--indra/llui/llurlentry.h15
-rw-r--r--indra/llui/llurlregistry.cpp6
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llagentwearables.cpp33
-rw-r--r--indra/newview/llagentwearables.h2
-rw-r--r--indra/newview/llappearancemgr.cpp94
-rw-r--r--indra/newview/llappearancemgr.h2
-rw-r--r--indra/newview/llimview.cpp2
-rw-r--r--indra/newview/llnavigationbar.cpp1
-rw-r--r--indra/newview/lloutfitslist.cpp38
-rw-r--r--indra/newview/lloutfitslist.h8
-rw-r--r--indra/newview/llpanelgroupnotices.cpp3
-rw-r--r--indra/newview/llpaneloutfitedit.cpp37
-rw-r--r--indra/newview/llpaneloutfitedit.h4
-rw-r--r--indra/newview/llteleporthistory.cpp12
-rw-r--r--indra/newview/llteleporthistorystorage.cpp7
-rw-r--r--indra/newview/lltoastalertpanel.cpp14
-rw-r--r--indra/newview/llviewerinventory.cpp67
-rw-r--r--indra/newview/llviewermessage.cpp43
-rw-r--r--indra/newview/llviewerregion.cpp20
-rw-r--r--indra/newview/llviewerregion.h3
-rw-r--r--indra/newview/llwearablelist.cpp4
-rw-r--r--indra/newview/skins/default/xui/en/floater_outgoing_call.xml2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/en/outfit_accordion_tab.xml18
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_edit.xml24
29 files changed, 464 insertions, 44 deletions
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 843f72d8e4..45f9de8e8d 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1440,7 +1440,7 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
BOOL LLLineEditor::canDoDelete() const
{
- return ( !mReadOnly && (!mPassDelete || (hasSelection() || (getCursor() < mText.length()))) );
+ return ( !mReadOnly && mText.length() > 0 && (!mPassDelete || (hasSelection() || (getCursor() < mText.length()))) );
}
void LLLineEditor::doDelete()
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 736de651da..3375c13c94 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -765,3 +765,35 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
{
return getUrl(url);
}
+
+//
+// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
+//
+LLUrlEntryIcon::LLUrlEntryIcon()
+{
+ mPattern = boost::regex("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>",
+ boost::regex::perl|boost::regex::icase);
+ mDisabledLink = true;
+}
+
+std::string LLUrlEntryIcon::getUrl(const std::string &url) const
+{
+ return LLStringUtil::null;
+}
+
+std::string LLUrlEntryIcon::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return LLStringUtil::null;
+}
+
+std::string LLUrlEntryIcon::getIcon(const std::string &url)
+{
+ // Grep icon info between <icon>...</icon> tags
+ // matches[1] contains the icon name/path
+ boost::match_results<std::string::const_iterator> matches;
+ mIcon = (boost::regex_match(url, matches, mPattern) && matches[1].matched)
+ ? matches[1]
+ : LLStringUtil::null;
+ LLStringUtil::trim(mIcon);
+ return mIcon;
+}
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 29575d752c..71f030677a 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -77,7 +77,7 @@ public:
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
/// Return an icon that can be displayed next to Urls of this type
- std::string getIcon() const { return mIcon; }
+ virtual std::string getIcon(const std::string &url) { return mIcon; }
/// Return the color to render the displayed text
LLUIColor getColor() const { return mColor; }
@@ -296,4 +296,17 @@ public:
/*virtual*/ std::string getUrl(const std::string &string) const;
};
+///
+/// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
+///
+class LLUrlEntryIcon : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryIcon();
+ /*virtual*/ std::string getUrl(const std::string &string) const;
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getIcon(const std::string &url);
+};
+
+
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 0a70aa586a..4341286eb4 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -45,6 +45,7 @@ LLUrlRegistry::LLUrlRegistry()
{
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
+ registerUrl(new LLUrlEntryIcon());
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
@@ -135,7 +136,8 @@ static bool stringHasUrl(const std::string &text)
text.find(".net") != std::string::npos ||
text.find(".edu") != std::string::npos ||
text.find(".org") != std::string::npos ||
- text.find("<nolink>") != std::string::npos);
+ text.find("<nolink>") != std::string::npos ||
+ text.find("<icon") != std::string::npos);
}
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
@@ -177,7 +179,7 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getUrl(url),
match_entry->getLabel(url, cb),
match_entry->getTooltip(url),
- match_entry->getIcon(),
+ match_entry->getIcon(url),
match_entry->getColor(),
match_entry->getMenuName(),
match_entry->getLocation(url),
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4ca23e14a1..a6dbe00759 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10994,5 +10994,16 @@
<integer>2048</integer>
</map>
<!-- End of back compatibility settings -->
+ <key>teleport_offer_invitation_max_length</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum length of teleport offer invitation line editor. 254 - max_location_url_length(76) = 178</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>178</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 466f2d499d..8a880e5ace 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -2031,6 +2031,39 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)
}
}
+bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool closer_to_body)
+{
+ if (!item) return false;
+ if (!item->isWearableType()) return false;
+
+ wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(item->getWearableType());
+ if (wearable_iter == mWearableDatas.end()) return false;
+
+ wearableentry_vec_t& wearable_vec = wearable_iter->second;
+ if (wearable_vec.empty()) return false;
+
+ const LLUUID& asset_id = item->getAssetUUID();
+
+ //nowhere to move if the wearable is already on any boundary (closest to the body/furthest from the body)
+ if (closer_to_body && asset_id == wearable_vec.front()->getAssetID()) return false;
+ if (!closer_to_body && asset_id == wearable_vec.back()->getAssetID()) return false;
+
+ for (U32 i = 0; i < wearable_vec.size(); ++i)
+ {
+ LLWearable* wearable = wearable_vec[i];
+ if (!wearable) continue;
+ if (wearable->getAssetID() != asset_id) continue;
+
+ //swapping wearables
+ U32 swap_i = closer_to_body ? i-1 : i+1;
+ wearable_vec[i] = wearable_vec[swap_i];
+ wearable_vec[swap_i] = wearable;
+ return true;
+ }
+
+ return false;
+}
+
void LLAgentWearables::updateServer()
{
sendAgentWearablesUpdate();
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 585fd3f8b3..d3b18f68f1 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -82,6 +82,8 @@ public:
void animateAllWearableParams(F32 delta, BOOL upload_bake);
+ bool moveWearable(const LLViewerInventoryItem* item, bool closer_to_body);
+
//--------------------------------------------------------------------
// Accessors
//--------------------------------------------------------------------
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 9e02886e4f..6aefecc787 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -122,6 +122,38 @@ private:
bool mAppend;
};
+
+//Inventory callback updating "dirty" state when destroyed
+class LLUpdateDirtyState: public LLInventoryCallback
+{
+public:
+ LLUpdateDirtyState() {}
+ virtual ~LLUpdateDirtyState(){ LLAppearanceMgr::getInstance()->updateIsDirty(); }
+ virtual void fire(const LLUUID&) {}
+};
+
+
+//Inventory collect functor collecting wearables of a specific wearable type
+class LLFindClothesOfType : public LLInventoryCollectFunctor
+{
+public:
+ LLFindClothesOfType(EWearableType type) : mWearableType(type) {}
+ virtual ~LLFindClothesOfType() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+ {
+ if (!item) return false;
+ if (item->getType() != LLAssetType::AT_CLOTHING) return false;
+
+ LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ if (!vitem || vitem->getWearableType() != mWearableType) return false;
+
+ return true;
+ }
+
+ const EWearableType mWearableType;
+};
+
+
LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy():
mFireCount(0)
{
@@ -1593,8 +1625,11 @@ bool LLAppearanceMgr::updateBaseOutfit()
// in a Base Outfit we do not remove items, only links
purgeCategory(base_outfit_id, false);
+
+ LLPointer<LLInventoryCallback> dirty_state_updater = new LLUpdateDirtyState();
+
//COF contains only links so we copy to the Base Outfit only links
- shallowCopyCategoryContents(getCOF(), base_outfit_id, NULL);
+ shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater);
return true;
}
@@ -1802,6 +1837,63 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)
}
}
+
+bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body)
+{
+ if (!item || !item->isWearableType()) return false;
+ if (item->getType() != LLAssetType::AT_CLOTHING) return false;
+ if (!gInventory.isObjectDescendentOf(item->getUUID(), getCOF())) return false;
+
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLFindClothesOfType filter_wearables_of_type(item->getWearableType());
+ gInventory.collectDescendentsIf(getCOF(), cats, items, true, filter_wearables_of_type);
+ if (items.empty()) return false;
+
+ //*TODO all items are not guarantied to have valid descriptions (check?)
+ std::sort(items.begin(), items.end(), WearablesOrderComparator(item->getWearableType()));
+
+ if (closer_to_body && items.front() == item) return false;
+ if (!closer_to_body && items.back() == item) return false;
+
+ LLInventoryModel::item_array_t::iterator it = std::find(items.begin(), items.end(), item);
+ if (items.end() == it) return false;
+
+
+ //swapping descriptions
+ closer_to_body ? --it : ++it;
+ LLViewerInventoryItem* swap_item = *it;
+ if (!swap_item) return false;
+ std::string tmp = swap_item->LLInventoryItem::getDescription();
+ swap_item->setDescription(item->LLInventoryItem::getDescription());
+ item->setDescription(tmp);
+
+
+ //items need to be updated on a dataserver
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+ gInventory.updateItem(item);
+
+ swap_item->setComplete(TRUE);
+ swap_item->updateServer(FALSE);
+ gInventory.updateItem(swap_item);
+
+ //to cause appearance of the agent to be updated
+ bool result = false;
+ if (result = gAgentWearables.moveWearable(item, closer_to_body))
+ {
+ gAgentAvatarp->wearableUpdated(item->getWearableType(), TRUE);
+ }
+
+ setOutfitDirty(true);
+
+ //*TODO do we need to notify observers here in such a way?
+ gInventory.notifyObservers();
+
+ return result;
+}
+
+
//#define DUMP_CAT_VERBOSE
void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg)
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index efb5274c5b..a308a3efa9 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -141,6 +141,8 @@ public:
LLUUID makeNewOutfitLinks(const std::string& new_folder_name);
+ bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body);
+
protected:
LLAppearanceMgr();
~LLAppearanceMgr();
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 909878207c..f03026715d 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -1767,6 +1767,8 @@ void LLOutgoingCallDialog::show(const LLSD& key)
getChild<LLTextBox>("leaving")->setVisible(true);
}
break;
+ // STATE_READY is here to show appropriate text for ad-hoc and group calls when floater is shown(EXT-6893)
+ case LLVoiceChannel::STATE_READY :
case LLVoiceChannel::STATE_RINGING :
if(show_oldchannel)
{
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index e11df06d86..0341f2c693 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -375,7 +375,6 @@ void LLNavigationBar::draw()
if(mPurgeTPHistoryItems)
{
LLTeleportHistory::getInstance()->purgeItems();
- onTeleportHistoryChanged();
mPurgeTPHistoryItems = false;
}
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index ad42d80467..cce4f94028 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -168,26 +168,21 @@ void LLOutfitsList::refreshList(const LLUUID& category_id)
std::string name = cat->getName();
- // *TODO: create accordion tabs and lists from XML.
- LLAccordionCtrlTab::Params params;
- params.name(name);
- params.title(name);
- params.rect(LLRect(0, 0, 315, 20));
- params.display_children(false);
- LLAccordionCtrlTab* tab = LLUICtrlFactory::create<LLAccordionCtrlTab>(params);
+ static LLXMLNodePtr accordionXmlNode = getAccordionTabXMLNode();
- mAccordion->addCollapsibleCtrl(tab);
-
- LLFlatListView::Params list_params;
- LLWearableItemsList* list = LLUICtrlFactory::create<LLWearableItemsList>(list_params);
+ accordionXmlNode->setAttributeString("name", name);
+ accordionXmlNode->setAttributeString("title", name);
+ LLAccordionCtrlTab* tab = LLUICtrlFactory::defaultBuilder<LLAccordionCtrlTab>(accordionXmlNode, NULL, NULL);
- tab->addChild(list, 0);
- tab->setDisplayChildren(false);
+ // *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
+ tab->setDisplayChildren(false);
+ mAccordion->addCollapsibleCtrl(tab);
// Map the new tab with outfit category UUID.
mOutfitsMap.insert(LLOutfitsList::outfits_map_value_t(cat_id, tab));
// Start observing the new outfit category.
+ LLWearableItemsList* list = tab->getChild<LLWearableItemsList>("wearable_items_list");
mCategoriesObserver->addCategory(cat_id, boost::bind(&LLWearableItemsList::updateList, list, cat_id));
// Fetch the new outfit contents.
@@ -262,4 +257,21 @@ void LLOutfitsList::setFilterSubString(const std::string& string)
mFilterSubString = string;
}
+
+//////////////////////////////////////////////////////////////////////////
+// Private methods
+//////////////////////////////////////////////////////////////////////////
+LLXMLNodePtr LLOutfitsList::getAccordionTabXMLNode()
+{
+ LLXMLNodePtr xmlNode = NULL;
+ bool success = LLUICtrlFactory::getLayeredXMLNode("outfit_accordion_tab.xml", xmlNode);
+ if (!success)
+ {
+ llwarns << "Failed to read xml of Outfit's Accordion Tab from outfit_accordion_tab.xml" << llendl;
+ return NULL;
+ }
+
+ return xmlNode;
+}
+
// EOF
diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h
index 892e0a862a..f1756ce873 100644
--- a/indra/newview/lloutfitslist.h
+++ b/indra/newview/lloutfitslist.h
@@ -59,6 +59,14 @@ public:
void setFilterSubString(const std::string& string);
private:
+ /**
+ * Reads xml with accordion tab and Flat list from xml file.
+ *
+ * @return LLPointer to XMLNode with accordion tab and flat list.
+ */
+ LLXMLNodePtr getAccordionTabXMLNode();
+
+
LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index 8da19d1574..f7d76bc069 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -656,6 +656,9 @@ void LLPanelGroupNotices::setGroupID(const LLUUID& id)
if(mViewMessage)
mViewMessage->clear();
+
+ if(mViewInventoryName)
+ mViewInventoryName->clear();
activate();
}
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index e139cb31d6..ae181e2819 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -73,6 +73,9 @@ const U64 WEARABLE_MASK = (1LL << LLInventoryType::IT_WEARABLE);
const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LLInventoryType::IT_OBJECT);
const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK;
+static const std::string SAVE_BTN("save_btn");
+static const std::string REVERT_BTN("revert_btn");
+
class LLInventoryLookObserver : public LLInventoryObserver
{
public:
@@ -221,10 +224,9 @@ BOOL LLPanelOutfitEdit::postBuild()
mEditWearableBtn->setVisible(FALSE);
mEditWearableBtn->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this));
- childSetAction("revert_btn", boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));
+ childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance()));
- childSetAction("save_btn", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));
- childSetAction("save_as_btn", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true));
+ childSetAction(SAVE_BTN, boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));
childSetAction("save_flyout_btn", boost::bind(&LLPanelOutfitEdit::showSaveMenu, this));
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar save_registar;
@@ -234,10 +236,22 @@ BOOL LLPanelOutfitEdit::postBuild()
mWearableListManager = new LLFilteredWearableListManager(
getChild<LLInventoryItemsList>("filtered_wearables_list"), ALL_ITEMS_MASK);
+
+ childSetAction("move_closer_btn", boost::bind(&LLPanelOutfitEdit::moveWearable, this, true));
+ childSetAction("move_further_btn", boost::bind(&LLPanelOutfitEdit::moveWearable, this, false));
return TRUE;
}
+void LLPanelOutfitEdit::moveWearable(bool closer_to_body)
+{
+ LLViewerInventoryItem* wearable_to_move = gInventory.getItem(mLookContents->getSelectionInterface()->getCurrentID());
+ LLAppearanceMgr::getInstance()->moveWearable(wearable_to_move, closer_to_body);
+
+ //*TODO why not to listen to inventory?
+ updateLookInfo();
+}
+
void LLPanelOutfitEdit::showAddWearablesPanel()
{
childSetVisible("add_wearables_panel", childGetValue("add_btn"));
@@ -267,6 +281,8 @@ void LLPanelOutfitEdit::saveOutfit(bool as_new)
{
panel_outfits_inventory->onSave();
}
+
+ //*TODO how to get to know when base outfit is updated or new outfit is created?
}
void LLPanelOutfitEdit::showSaveMenu()
@@ -542,10 +558,12 @@ void LLPanelOutfitEdit::lookFetched(void)
columns[0]["value"] = item->getName();
columns[1]["column"] = "look_item_sort";
columns[1]["type"] = "text"; // TODO: multi-wearable sort "type" should go here.
- columns[1]["value"] = "BAR"; // TODO: Multi-wearable sort index should go here
+ columns[1]["value"] = item->LLInventoryItem::getDescription();
mLookContents->addElement(row);
}
+
+ updateVerbs();
}
void LLPanelOutfitEdit::updateLookInfo()
@@ -589,4 +607,15 @@ void LLPanelOutfitEdit::displayCurrentOutfit()
updateLookInfo();
}
+//private
+void LLPanelOutfitEdit::updateVerbs()
+{
+ bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty();
+
+ childSetEnabled(SAVE_BTN, outfit_is_dirty);
+ childSetEnabled(REVERT_BTN, outfit_is_dirty);
+
+ mSaveMenu->setItemEnabled("save_outfit", outfit_is_dirty);
+}
+
// EOF
diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h
index 308ee23115..b6f121d484 100644
--- a/indra/newview/llpaneloutfitedit.h
+++ b/indra/newview/llpaneloutfitedit.h
@@ -87,6 +87,8 @@ public:
// Sends a request for data about the given parcel, which will
// only update the location if there is none already available.
+ void moveWearable(bool closer_to_body);
+
void showAddWearablesPanel();
void showWearablesFilter();
void showFilteredWearablesPanel();
@@ -110,6 +112,8 @@ public:
private:
+ void updateVerbs();
+
//*TODO got rid of mCurrentOutfitID
LLUUID mCurrentOutfitID;
diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp
index dcc85392f7..15684337f4 100644
--- a/indra/newview/llteleporthistory.cpp
+++ b/indra/newview/llteleporthistory.cpp
@@ -136,6 +136,7 @@ void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
if (mCurrentItem < 0 || mCurrentItem >= (int) mItems.size()) // sanity check
{
llwarns << "Invalid current item. (this should not happen)" << llendl;
+ llassert(!"Invalid current teleport histiry item");
return;
}
LLVector3 new_pos_local = gAgent.getPosAgentFromGlobal(new_pos);
@@ -166,6 +167,17 @@ void LLTeleportHistory::onHistoryChanged()
void LLTeleportHistory::purgeItems()
{
+ if (mItems.size() == 0) // no entries yet (we're called before login)
+ {
+ // If we don't return here the history will get into inconsistent state, hence:
+ // 1) updateCurrentLocation() will malfunction,
+ // so further teleports will not properly update the history;
+ // 2) mHistoryChangedSignal subscribers will be notified
+ // of such an invalid change. (EXT-6798)
+ // Both should not happen.
+ return;
+ }
+
if (mItems.size() > 0)
{
mItems.erase(mItems.begin(), mItems.end()-1);
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index c635f91423..430d62e15e 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -89,6 +89,13 @@ void LLTeleportHistoryStorage::onTeleportHistoryChange()
if (!th)
return;
+ // Hacky sanity check. (EXT-6798)
+ if (th->getItems().size() == 0)
+ {
+ llassert(!"Inconsistent teleport history state");
+ return;
+ }
+
const LLTeleportHistoryItem &item = th->getItems()[th->getCurrentItemIndex()];
addItem(item.mTitle, item.mGlobalPos);
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 986ccdf19b..2b529a4e50 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -50,6 +50,7 @@
#include "llnotifications.h"
#include "llfunctorregistry.h"
#include "llrootview.h"
+#include "llviewercontrol.h" // for gSavedSettings
const S32 MAX_ALLOWED_MSG_WIDTH = 400;
const F32 DEFAULT_BUTTON_DELAY = 0.5f;
@@ -279,7 +280,18 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
mLineEditor->reshape(leditor_rect.getWidth(), leditor_rect.getHeight());
mLineEditor->setRect(leditor_rect);
mLineEditor->setText(edit_text_contents);
- mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);
+
+ // decrease limit of line editor of teleport offer dialog to avoid truncation of
+ // location URL in invitation message, see EXT-6891
+ if ("OfferTeleport" == mNotification->getName())
+ {
+ mLineEditor->setMaxTextLength(gSavedSettings.getS32(
+ "teleport_offer_invitation_max_length"));
+ }
+ else
+ {
+ mLineEditor->setMaxTextLength(STD_STRING_STR_LEN - 1);
+ }
LLToastPanel::addChild(mLineEditor);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index f434d15843..a23e42ea9e 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -67,6 +67,40 @@
#include "llviewermessage.h"
///----------------------------------------------------------------------------
+/// Helper class to store special inventory item names
+///----------------------------------------------------------------------------
+class LLLocalizedInventoryItemsDictionary : public LLSingleton<LLLocalizedInventoryItemsDictionary>
+{
+public:
+ std::map<std::string, std::string> mInventoryItemsDict;
+
+ LLLocalizedInventoryItemsDictionary()
+ {
+ mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape");
+ mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin");
+ mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair");
+ mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes");
+ mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt");
+ mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants");
+ mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes");
+ mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks");
+ mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket");
+ mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves");
+ mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt");
+ mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt");
+ mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt");
+ mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha");
+ mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo");
+ mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable");
+
+ mInventoryItemsDict["New Script"] = LLTrans::getString("New Script");
+ mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder");
+ mInventoryItemsDict["Contents"] = LLTrans::getString("Contents");
+ }
+};
+
+
+///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
///----------------------------------------------------------------------------
@@ -316,6 +350,18 @@ BOOL LLViewerInventoryItem::unpackMessage(LLSD item)
BOOL LLViewerInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num)
{
BOOL rv = LLInventoryItem::unpackMessage(msg, block, block_num);
+
+ std::string localized_str;
+
+ std::map<std::string, std::string>::const_iterator dictionary_iter;
+
+ dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.find(mName);
+
+ if(dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end())
+ {
+ mName = dictionary_iter->second;
+ }
+
mIsComplete = TRUE;
return rv;
}
@@ -867,6 +913,25 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
U32 next_owner_perm,
LLPointer<LLInventoryCallback> cb)
{
+ //check if name is equal to one of special inventory items names
+ //EXT-5839
+ std::string server_name = name;
+
+ {
+ std::map<std::string, std::string>::const_iterator dictionary_iter;
+
+ for (dictionary_iter = LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.begin();
+ dictionary_iter != LLLocalizedInventoryItemsDictionary::getInstance()->mInventoryItemsDict.end();
+ dictionary_iter++)
+ {
+ const std::string& localized_name = dictionary_iter->second;
+ if(localized_name == name)
+ {
+ server_name = dictionary_iter->first;
+ }
+ }
+ }
+
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_CreateInventoryItem);
msg->nextBlock(_PREHASH_AgentData);
@@ -880,7 +945,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
msg->addU8Fast(_PREHASH_WearableType, (U8)wtype);
- msg->addStringFast(_PREHASH_Name, name);
+ msg->addStringFast(_PREHASH_Name, server_name);
msg->addStringFast(_PREHASH_Description, desc);
gAgent.sendReliableMessage();
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ba0c8d464d..e12457550a 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1933,7 +1933,7 @@ protected:
}
};
-static void parse_lure_bucket(const std::string& bucket,
+static bool parse_lure_bucket(const std::string& bucket,
U64& region_handle,
LLVector3& pos,
LLVector3& look_at,
@@ -1945,15 +1945,25 @@ static void parse_lure_bucket(const std::string& bucket,
tokenizer tokens(bucket, sep);
tokenizer::iterator iter = tokens.begin();
- S32 gx = boost::lexical_cast<S32>((*(iter)).c_str());
- S32 gy = boost::lexical_cast<S32>((*(++iter)).c_str());
- S32 rx = boost::lexical_cast<S32>((*(++iter)).c_str());
- S32 ry = boost::lexical_cast<S32>((*(++iter)).c_str());
- S32 rz = boost::lexical_cast<S32>((*(++iter)).c_str());
- S32 lx = boost::lexical_cast<S32>((*(++iter)).c_str());
- S32 ly = boost::lexical_cast<S32>((*(++iter)).c_str());
- S32 lz = boost::lexical_cast<S32>((*(++iter)).c_str());
-
+ S32 gx,gy,rx,ry,rz,lx,ly,lz;
+ try
+ {
+ gx = boost::lexical_cast<S32>((*(iter)).c_str());
+ gy = boost::lexical_cast<S32>((*(++iter)).c_str());
+ rx = boost::lexical_cast<S32>((*(++iter)).c_str());
+ ry = boost::lexical_cast<S32>((*(++iter)).c_str());
+ rz = boost::lexical_cast<S32>((*(++iter)).c_str());
+ lx = boost::lexical_cast<S32>((*(++iter)).c_str());
+ ly = boost::lexical_cast<S32>((*(++iter)).c_str());
+ lz = boost::lexical_cast<S32>((*(++iter)).c_str());
+ }
+ catch( boost::bad_lexical_cast& )
+ {
+ LL_WARNS("parse_lure_bucket")
+ << "Couldn't parse lure bucket."
+ << LL_ENDL;
+ return false;
+ }
// Grab region access
region_access = SIM_ACCESS_MIN;
if (++iter != tokens.end())
@@ -1978,6 +1988,7 @@ static void parse_lure_bucket(const std::string& bucket,
look_at.setVec((F32)lx, (F32)ly, (F32)lz);
region_handle = to_region_handle(gx, gy);
+ return true;
}
void process_improved_im(LLMessageSystem *msg, void **user_data)
@@ -2615,15 +2626,21 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
U64 region_handle;
U8 region_access;
std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size);
- parse_lure_bucket(region_info, region_handle, pos, look_at, region_access);
+ std::string region_access_str = LLStringUtil::null;
+ std::string region_access_icn = LLStringUtil::null;
- std::string region_access_str = LLViewerRegion::accessToString(region_access);
+ if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access))
+ {
+ region_access_str = LLViewerRegion::accessToString(region_access);
+ region_access_icn = LLViewerRegion::getAccessIcon(region_access);
+ }
LLSD args;
// *TODO: Translate -> [FIRST] [LAST] (maybe)
args["NAME_SLURL"] = LLSLURL::buildCommand("agent", from_id, "about");
args["MESSAGE"] = message;
- args["MATURITY"] = region_access_str;
+ args["MATURITY_STR"] = region_access_str;
+ args["MATURITY_ICON"] = region_access_icn;
LLSD payload;
payload["from_id"] = from_id;
payload["lure_id"] = session_id;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 07d4ac664f..c48668df9a 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -627,6 +627,26 @@ std::string LLViewerRegion::accessToString(U8 sim_access)
}
// static
+std::string LLViewerRegion::getAccessIcon(U8 sim_access)
+{
+ switch(sim_access)
+ {
+ case SIM_ACCESS_MATURE:
+ return "Parcel_M_Dark";
+
+ case SIM_ACCESS_ADULT:
+ return "Parcel_R_Light";
+
+ case SIM_ACCESS_PG:
+ return "Parcel_PG_Light";
+
+ case SIM_ACCESS_MIN:
+ default:
+ return "";
+ }
+}
+
+// static
std::string LLViewerRegion::accessToShortString(U8 sim_access)
{
switch(sim_access) /* Flawfinder: ignore */
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 49d0900f2a..5c4d5a61fd 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -203,6 +203,9 @@ public:
// Returns "M", "PG", "A" etc.
static std::string accessToShortString(U8 sim_access);
+
+ // Return access icon name
+ static std::string getAccessIcon(U8 sim_access);
// helper function which just makes sure all interested parties
// can process the message.
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index b2de31218b..20266706da 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -235,9 +235,7 @@ LLWearable* LLWearableList::createNewWearable( EWearableType type )
LLWearable *wearable = generateNewWearable();
wearable->setType( type );
- LLSD item_name = LLSD().with("[WEARABLE_ITEM]", wearable->getTypeLabel());
- std::string name = LLTrans::getString("NewWearable");
- LLStringUtil::format(name, item_name);
+ std::string name = LLTrans::getString( LLWearableDictionary::getTypeDefaultNewName(wearable->getType()) );
wearable->setName( name );
LLPermissions perm;
diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
index 5ea207675b..9db6568ee3 100644
--- a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
@@ -119,7 +119,7 @@ No Answer. Please try again later.
layout="topleft"
left="77"
name="leaving"
- top="52"
+ top="62"
width="315"
word_wrap="true">
Leaving [CURRENT_CHAT].
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 5d184fea3a..4479a3dd4d 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5168,7 +5168,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you th
type="offer">
[NAME_SLURL] has offered to teleport you to their location:
-[MESSAGE], ([MATURITY])
+[MESSAGE] - [MATURITY_STR] &lt;icon&gt;[MATURITY_ICON]&lt;/icon&gt;
<form name="form">
<button
index="0"
diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml
new file mode 100644
index 0000000000..d00b1bfb7b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- *NOTE: mantipov: this xml is intended to be used inside panel_outfits_list.xml for each outfit folder-->
+<!-- All accordion tabs in the My Appearance/My Outfits panel will be created from this one at runtume-->
+<accordion_tab
+ display_children="false"
+ follows="all"
+ height="40"
+ layout="topleft"
+ name="Mockup Tab"
+ title="Mockup Tab"
+ width="0">
+ <wearable_items_list
+ allow_select="true"
+ follows="all"
+ keep_one_selected="true"
+ name="wearable_items_list"
+ />
+</accordion_tab>
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
index 184ea54fcb..5dbd8bfe6a 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
@@ -17,7 +17,7 @@
layout="topleft"
left_delta="3"
left="0"
- max_length="512"
+ max_length="1024"
name="chat_box"
text_pad_left="5"
text_pad_right="25"
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index b1f0ff15cb..314d2389ae 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -222,6 +222,30 @@
top="1"
width="31" />
<button
+ follows="bottom|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Movement_Forward_On"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="move_closer_btn"
+ top="1"
+ width="31" />
+ <button
+ follows="bottom|left"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Movement_Backward_On"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ left_pad="1"
+ name="move_further_btn"
+ top="1"
+ width="31" />
+ <button
follows="bottom|right"
height="25"
image_hover_unselected="Toolbar_Middle_Over"