summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml33
-rw-r--r--indra/newview/llappearancemgr.cpp41
-rw-r--r--indra/newview/llexpandabletextbox.cpp2
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp3
-rw-r--r--indra/newview/llfloatermodelpreview.cpp4
-rw-r--r--indra/newview/llimview.cpp84
-rw-r--r--indra/newview/llinventorymodelbackgroundfetch.cpp18
-rw-r--r--indra/newview/lllogchat.cpp35
-rw-r--r--indra/newview/llmeshrepository.cpp10
-rw-r--r--indra/newview/llscriptfloater.cpp131
-rw-r--r--indra/newview/llscriptfloater.h17
-rw-r--r--indra/newview/llviewerobject.cpp18
-rw-r--r--indra/newview/llviewerobject.h4
-rw-r--r--indra/newview/llviewertexteditor.cpp4
-rw-r--r--indra/newview/llvoavatar.cpp7
-rw-r--r--indra/newview/llvovolume.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml114
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml2
19 files changed, 461 insertions, 80 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 097a9ac7b9..f0a91fd407 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1619,6 +1619,17 @@
<key>Value</key>
<string>default</string>
</map>
+ <key>ChatAutocompleteGestures</key>
+ <map>
+ <key>Comment</key>
+ <string>Auto-complete gestures in nearby chat</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>ChatBarStealsFocus</key>
<map>
<key>Comment</key>
@@ -10168,6 +10179,17 @@
<key>Value</key>
<integer>10</integer>
</map>
+ <key>MaxAttachmentComplexity</key>
+ <map>
+ <key>Comment</key>
+ <string>Attachment's render weight limit</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>1.0E6</real>
+ </map>
<key>ComplexityChangesPopUpDelay</key>
<map>
<key>Comment</key>
@@ -10734,6 +10756,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>ScriptDialogLimitations</key>
+ <map>
+ <key>Comment</key>
+ <string>Limits amount of dialogs per script (0 - per object, 1 - per channel, 2 - per channel for attachments, 3 - per channel for HUDs, 4 -unconstrained for HUDs)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>SecondLifeEnterprise</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index feb981217d..c928cf0601 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -2917,11 +2917,32 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar()
removeItemsFromAvatar(ids_to_remove);
}
-void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb)
+class LLUpdateOnCOFLinkRemove : public LLInventoryCallback
{
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+public:
+ LLUpdateOnCOFLinkRemove(const LLUUID& remove_item_id, LLPointer<LLInventoryCallback> cb = NULL):
+ mItemID(remove_item_id),
+ mCB(cb)
+ {
+ }
- LLInventoryModel::cat_array_t cat_array;
+ /* virtual */ void fire(const LLUUID& item_id)
+ {
+ // just removed cof link, "(wear)" suffix depends on presence of link, so update label
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, mItemID);
+ if (mCB.notNull())
+ {
+ mCB->fire(item_id);
+ }
+ }
+
+private:
+ LLUUID mItemID;
+ LLPointer<LLInventoryCallback> mCB;
+};
+
+void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInventoryCallback> cb)
+{ LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(LLAppearanceMgr::getCOF(),
cat_array,
@@ -2932,12 +2953,20 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer<LLInve
const LLInventoryItem* item = item_array.at(i).get();
if (item->getIsLinkType() && item->getLinkedUUID() == item_id)
{
- bool immediate_delete = false;
if (item->getType() == LLAssetType::AT_OBJECT)
{
- immediate_delete = true;
+ // Immediate delete
+ remove_inventory_item(item->getUUID(), cb, true);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ }
+ else
+ {
+ // Delayed delete
+ // Pointless to update item_id label here since link still exists and first notifyObservers
+ // call will restore (wear) suffix, mark for update after deletion
+ LLPointer<LLUpdateOnCOFLinkRemove> cb_label = new LLUpdateOnCOFLinkRemove(item_id, cb);
+ remove_inventory_item(item->getUUID(), cb_label, false);
}
- remove_inventory_item(item->getUUID(), cb, immediate_delete);
}
}
}
diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 314b859cea..711a87dc99 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -44,7 +44,7 @@ public:
mExpanderLabel(more_text)
{}
- /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
// more label always spans width of text box
if (num_chars == 0)
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 40ae22bb4e..7895a5ff48 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -485,7 +485,8 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke()
KEY key = gKeyboard->currentKey();
// Ignore "special" keys, like backspace, arrows, etc.
- if (length > 1
+ if (gSavedSettings.getBOOL("ChatAutocompleteGestures")
+ && length > 1
&& raw_text[0] == '/'
&& key < KEY_SPECIAL)
{
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index c654817849..b3885bf36c 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1262,6 +1262,10 @@ LLModelPreview::~LLModelPreview()
// glod.dll!glodShutdown() + 0x77 bytes
//
//glodShutdown();
+ if(mModelLoader)
+ {
+ mModelLoader->shutdown();
+ }
}
U32 LLModelPreview::calcResourceCost()
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index ff8b8b0403..bcda9baa9a 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -2677,49 +2677,57 @@ void LLIMMgr::addMessage(
LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg);
LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id);
- skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
- if(skip_message)
+ if (session)
{
- gIMMgr->leaveSession(new_session_id);
- }
- // When we get a new IM, and if you are a god, display a bit
- // of information about the source. This is to help liaisons
- // when answering questions.
- if(gAgent.isGodlike())
- {
- // *TODO:translate (low priority, god ability)
- std::ostringstream bonus_info;
- bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
- << parent_estate_id
- << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
- << ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
-
- // once we have web-services (or something) which returns
- // information about a region id, we can print this out
- // and even have it link to map-teleport or something.
- //<< "*** region_id: " << region_id << std::endl
- //<< "*** position: " << position << std::endl;
+ skip_message &= !session->isGroupSessionType(); // Do not skip group chats...
+ if (skip_message)
+ {
+ gIMMgr->leaveSession(new_session_id);
+ }
+ // When we get a new IM, and if you are a god, display a bit
+ // of information about the source. This is to help liaisons
+ // when answering questions.
+ if (gAgent.isGodlike())
+ {
+ // *TODO:translate (low priority, god ability)
+ std::ostringstream bonus_info;
+ bonus_info << LLTrans::getString("***") + " " + LLTrans::getString("IMParentEstate") + ":" + " "
+ << parent_estate_id
+ << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+ << ((parent_estate_id == 5) ? "," + LLTrans::getString("IMTeen") : "");
+
+ // once we have web-services (or something) which returns
+ // information about a region id, we can print this out
+ // and even have it link to map-teleport or something.
+ //<< "*** region_id: " << region_id << std::endl
+ //<< "*** position: " << position << std::endl;
+
+ LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
+ }
- LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str());
- }
+ // Logically it would make more sense to reject the session sooner, in another area of the
+ // code, but the session has to be established inside the server before it can be left.
+ if (LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !from_linden)
+ {
+ LL_WARNS() << "Leaving IM session from initiating muted resident " << from << LL_ENDL;
+ if (!gIMMgr->leaveSession(new_session_id))
+ {
+ LL_INFOS() << "Session " << new_session_id << " does not exist." << LL_ENDL;
+ }
+ return;
+ }
- // Logically it would make more sense to reject the session sooner, in another area of the
- // code, but the session has to be established inside the server before it can be left.
- if (LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !from_linden)
- {
- LL_WARNS() << "Leaving IM session from initiating muted resident " << from << LL_ENDL;
- if(!gIMMgr->leaveSession(new_session_id))
+ //Play sound for new conversations
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE))
{
- LL_INFOS() << "Session " << new_session_id << " does not exist." << LL_ENDL;
+ make_ui_sound("UISndNewIncomingIMSession");
}
- return;
}
-
- //Play sound for new conversations
- if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation") == TRUE))
- {
- make_ui_sound("UISndNewIncomingIMSession");
- }
+ else
+ {
+ // Failed to create a session, most likely due to empty name (name cache failed?)
+ LL_WARNS() << "Failed to create IM session " << fixed_session_name << LL_ENDL;
+ }
}
if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)
@@ -3022,7 +3030,7 @@ void LLIMMgr::inviteToSession(
LLIncomingCallDialog::processCallResponse(1, payload);
return;
}
- else if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagAll & ~LLMute::flagVoiceChat))
+ else if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagAll & ~LLMute::flagVoiceChat) && !voice_invite)
{
LL_INFOS() << "Rejecting session invite from initiating muted resident " << caller_name << LL_ENDL;
return;
diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp
index a8919db828..406c8b89d0 100644
--- a/indra/newview/llinventorymodelbackgroundfetch.cpp
+++ b/indra/newview/llinventorymodelbackgroundfetch.cpp
@@ -76,13 +76,6 @@
// * Review the download rate throttling. Slow then fast?
// Detect bandwidth usage and speed up when it drops?
//
-// * A lot of calls to notifyObservers(). It looks like
-// these could be collapsed by maintaining a 'dirty'
-// bit and there appears to be an attempt to do this.
-// But it isn't used or is used in a limited fashion.
-// Are there semanic issues requiring a call after certain
-// updateItem() calls?
-//
// * An error on a fetch could be due to one item in the batch.
// If the batch were broken up, perhaps more of the inventory
// would download. (Handwave here, not certain this is an
@@ -393,6 +386,12 @@ void LLInventoryModelBackgroundFetch::bulkFetch()
{
// Process completed background HTTP requests
gInventory.handleResponses(false);
+ // Just processed a bunch of items.
+ // Note: do we really need notifyObservers() here?
+ // OnIdle it will be called anyway due to Add flag for processed item.
+ // It seems like in some cases we are updaiting on fail (no flag),
+ // but is there anything to update?
+ gInventory.notifyObservers();
}
if ((mFetchCount > max_concurrent_fetches) ||
@@ -711,7 +710,6 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res
titem->setParent(lost_uuid);
titem->updateParentOnServer(FALSE);
gInventory.updateItem(titem);
- gInventory.notifyObservers();
}
}
}
@@ -784,8 +782,6 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res
{
fetcher->setAllFoldersFetched();
}
-
- gInventory.notifyObservers();
}
@@ -828,7 +824,6 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http
fetcher->setAllFoldersFetched();
}
}
- gInventory.notifyObservers();
}
@@ -866,7 +861,6 @@ void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::Http
fetcher->setAllFoldersFetched();
}
}
- gInventory.notifyObservers();
}
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index b9194c6c67..5abd99d36f 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -67,7 +67,8 @@ const std::string LL_IM_FROM("from");
const std::string LL_IM_FROM_ID("from_id");
const std::string LL_TRANSCRIPT_FILE_EXTENSION("txt");
-const static std::string IM_SEPARATOR(": ");
+const static char IM_SYMBOL_SEPARATOR(':');
+const static std::string IM_SEPARATOR(std::string() + IM_SYMBOL_SEPARATOR + " ");
const static std::string NEW_LINE("\n");
const static std::string NEW_LINE_SPACE_PREFIX("\n ");
const static std::string TWO_SPACES(" ");
@@ -838,7 +839,7 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
}
if (im[LL_IM_TIME].isDefined())
-{
+ {
std::string timestamp = im[LL_IM_TIME].asString();
boost::trim(timestamp);
ostr << '[' << timestamp << ']' << TWO_SPACES;
@@ -851,9 +852,29 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
{
std::string from = im[LL_IM_FROM].asString();
boost::trim(from);
- if (from.size())
+
+ std::size_t found = from.find(IM_SYMBOL_SEPARATOR);
+ std::size_t len = from.size();
+ std::size_t start = 0;
+ while (found != std::string::npos)
{
- ostr << from << IM_SEPARATOR;
+ std::size_t sub_len = found - start;
+ if (sub_len > 0)
+ {
+ ostr << from.substr(start, sub_len);
+ }
+ LLURI::encodeCharacter(ostr, IM_SYMBOL_SEPARATOR);
+ start = found + 1;
+ found = from.find(IM_SYMBOL_SEPARATOR, start);
+ }
+ if (start < len)
+ {
+ std::string str_end = from.substr(start, len - start);
+ ostr << str_end;
+ }
+ if (len > 0)
+ {
+ ostr << IM_SEPARATOR;
}
}
@@ -865,7 +886,7 @@ void LLChatLogFormatter::format(const LLSD& im, std::ostream& ostr) const
boost::replace_all(im_text, NEW_LINE, NEW_LINE_SPACE_PREFIX);
ostr << im_text;
}
- }
+}
bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params)
{
@@ -912,7 +933,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
if (!boost::regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false;
bool has_name = name_and_text[IDX_NAME].matched;
- std::string name = name_and_text[IDX_NAME];
+ std::string name = LLURI::unescape(name_and_text[IDX_NAME]);
//we don't need a name/text separator
if (has_name && name.length() && name[name.length()-1] == ':')
@@ -933,7 +954,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
U32 divider_pos = stuff.find(NAME_TEXT_DIVIDER);
if (divider_pos != std::string::npos && divider_pos < (stuff.length() - NAME_TEXT_DIVIDER.length()))
{
- im[LL_IM_FROM] = stuff.substr(0, divider_pos);
+ im[LL_IM_FROM] = LLURI::unescape(stuff.substr(0, divider_pos));
im[LL_IM_TEXT] = stuff.substr(divider_pos + NAME_TEXT_DIVIDER.length());
return true;
}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 1a533dace7..f7e0e32256 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -3626,7 +3626,15 @@ void LLMeshRepository::notifyLoadedMeshes()
//popup queued error messages from background threads
while (!mUploadErrorQ.empty())
{
- LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front());
+ LLSD substitutions(mUploadErrorQ.front());
+ if (substitutions.has("DETAILS"))
+ {
+ LLNotificationsUtil::add("MeshUploadErrorDetails", substitutions);
+ }
+ else
+ {
+ LLNotificationsUtil::add("MeshUploadError", substitutions);
+ }
mUploadErrorQ.pop();
}
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 1d021ec28f..b2c450aa0c 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -40,6 +40,7 @@
#include "lltoastnotifypanel.h"
#include "lltoastscripttextbox.h"
#include "lltrans.h"
+#include "llviewerobjectlist.h"
#include "llviewerwindow.h"
#include "llfloaterimsession.h"
@@ -61,6 +62,7 @@ LLUUID notification_id_to_object_id(const LLUUID& notification_id)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+
LLScriptFloater::LLScriptFloater(const LLSD& key)
: LLDockableFloater(NULL, true, key)
, mScriptForm(NULL)
@@ -346,6 +348,11 @@ void LLScriptFloater::hideToastsIfNeeded()
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLScriptFloaterManager::LLScriptFloaterManager()
+{
+ gSavedSettings.getControl("ScriptDialogLimitations")->getCommitSignal()->connect(boost::bind(&clearScriptNotifications));
+}
+
void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
{
if(notification_id.isNull())
@@ -365,16 +372,86 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
// LLDialog can spawn only one instance, LLLoadURL and LLGiveInventory can spawn unlimited number of instances
if(OBJ_SCRIPT == obj_type)
{
- // If an Object spawns more-than-one floater, only the newest one is shown.
- // The previous is automatically closed.
- script_notification_map_t::const_iterator it = findUsingObjectId(object_id);
+ static LLCachedControl<U32> script_dialog_limitations(gSavedSettings, "ScriptDialogLimitations", 0);
+ script_notification_map_t::const_iterator it = mNotifications.end();
+ switch (script_dialog_limitations)
+ {
+ case SCRIPT_PER_CHANNEL:
+ {
+ // If an Object spawns more-than-one floater per channel, only the newest one is shown.
+ // The previous is automatically closed.
+ LLNotificationPtr notification = LLNotifications::instance().find(notification_id);
+ if (notification)
+ {
+ it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger());
+ }
+ break;
+ }
+ case SCRIPT_ATTACHMENT_PER_CHANNEL:
+ {
+ LLViewerObject* objectp = gObjectList.findObject(object_id);
+ if (objectp && objectp->getAttachmentItemID().notNull()) //in user inventory
+ {
+ LLNotificationPtr notification = LLNotifications::instance().find(notification_id);
+ if (notification)
+ {
+ it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger());
+ }
+ }
+ else
+ {
+ it = findUsingObjectId(object_id);
+ }
+ break;
+ }
+ case SCRIPT_HUD_PER_CHANNEL:
+ {
+ LLViewerObject* objectp = gObjectList.findObject(object_id);
+ if (objectp && objectp->isHUDAttachment())
+ {
+ LLNotificationPtr notification = LLNotifications::instance().find(notification_id);
+ if (notification)
+ {
+ it = findUsingObjectIdAndChannel(object_id, notification->getPayload()["chat_channel"].asInteger());
+ }
+ }
+ else
+ {
+ it = findUsingObjectId(object_id);
+ }
+ break;
+ }
+ case SCRIPT_HUD_UNCONSTRAINED:
+ {
+ LLViewerObject* objectp = gObjectList.findObject(object_id);
+ if (objectp && objectp->isHUDAttachment())
+ {
+ // don't remove existing floaters
+ break;
+ }
+ else
+ {
+ it = findUsingObjectId(object_id);
+ }
+ break;
+ }
+ case SCRIPT_PER_OBJECT:
+ default:
+ {
+ // If an Object spawns more-than-one floater, only the newest one is shown.
+ // The previous is automatically closed.
+ it = findUsingObjectId(object_id);
+ break;
+ }
+ }
+
if(it != mNotifications.end())
{
LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel();
if (NULL != chiclet_panelp)
{
LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(it->first);
- if(NULL != chicletp)
+ if (NULL != chicletp)
{
// Pass the new_message icon state further.
set_new_message = chicletp->getShowNewMessagesIcon();
@@ -383,7 +460,7 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
}
LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first);
- if(floater)
+ if (floater)
{
// Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142.
set_new_message |= !floater->hasFocus();
@@ -579,6 +656,23 @@ LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloate
return mNotifications.end();
}
+LLScriptFloaterManager::script_notification_map_t::const_iterator LLScriptFloaterManager::findUsingObjectIdAndChannel(const LLUUID& object_id, S32 im_channel)
+{
+ script_notification_map_t::const_iterator it = mNotifications.begin();
+ for (; mNotifications.end() != it; ++it)
+ {
+ if (object_id == it->second)
+ {
+ LLNotificationPtr notification = LLNotifications::instance().find(it->first);
+ if (notification && (im_channel == notification->getPayload()["chat_channel"].asInteger()))
+ {
+ return it;
+ }
+ }
+ }
+ return mNotifications.end();
+}
+
void LLScriptFloaterManager::saveFloaterPosition(const LLUUID& object_id, const FloaterPositionInfo& fpi)
{
if(object_id.notNull())
@@ -612,6 +706,33 @@ void LLScriptFloaterManager::setFloaterVisible(const LLUUID& notification_id, bo
}
}
+//static
+void LLScriptFloaterManager::clearScriptNotifications()
+{
+ LLScriptFloaterManager* inst = LLScriptFloaterManager::getInstance();
+ static const object_type_map TYPE_MAP = initObjectTypeMap();
+
+ script_notification_map_t::const_iterator ntf_it = inst->mNotifications.begin();
+ while (inst->mNotifications.end() != ntf_it)
+ {
+ LLUUID notification_id = ntf_it->first;
+ ntf_it++; // onRemoveNotification() erases notification
+ LLNotificationPtr notification = LLNotifications::instance().find(notification_id);
+ if (notification)
+ {
+ object_type_map::const_iterator map_it = TYPE_MAP.find(notification->getName());
+ if (map_it != TYPE_MAP.end() && map_it->second == OBJ_SCRIPT)
+ {
+ if (notification != NULL && !notification->isCancelled())
+ {
+ LLNotificationsUtil::cancel(notification);
+ }
+ inst->onRemoveNotification(notification_id);
+ }
+ }
+ }
+}
+
//////////////////////////////////////////////////////////////////
bool LLScriptFloater::isScriptTextbox(LLNotificationPtr notification)
diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h
index c0b84abdcb..0192a8893e 100644
--- a/indra/newview/llscriptfloater.h
+++ b/indra/newview/llscriptfloater.h
@@ -41,7 +41,7 @@ class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager>
// *TODO
// LLScriptFloaterManager and LLScriptFloater will need some refactoring after we
// know how script notifications should look like.
- LLSINGLETON_EMPTY_CTOR(LLScriptFloaterManager);
+ LLSINGLETON(LLScriptFloaterManager);
public:
typedef enum e_object_type
@@ -53,6 +53,15 @@ public:
OBJ_UNKNOWN
}EObjectType;
+ typedef enum e_limitation_type
+ {
+ SCRIPT_PER_OBJECT = 0,
+ SCRIPT_PER_CHANNEL = 1,
+ SCRIPT_ATTACHMENT_PER_CHANNEL,
+ SCRIPT_HUD_PER_CHANNEL,
+ SCRIPT_HUD_UNCONSTRAINED
+ }ELimitationType;
+
/**
* Handles new notifications.
* Saves notification and object ids, removes old notification if needed, creates script chiclet
@@ -104,6 +113,11 @@ public:
protected:
+ /**
+ * Removes all script-dialog notifications
+ */
+ static void clearScriptNotifications();
+
typedef std::map<std::string, EObjectType> object_type_map;
static object_type_map initObjectTypeMap();
@@ -112,6 +126,7 @@ protected:
typedef std::map<LLUUID, LLUUID> script_notification_map_t;
script_notification_map_t::const_iterator findUsingObjectId(const LLUUID& object_id);
+ script_notification_map_t::const_iterator findUsingObjectIdAndChannel(const LLUUID& object_id, S32 im_channel);
private:
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 45dbd95bea..1d6daed9cc 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -6274,6 +6274,24 @@ BOOL LLViewerObject::isTempAttachment() const
return (mID.notNull() && (mID == mAttachmentItemID));
}
+BOOL LLViewerObject::isHiglightedOrBeacon() const
+{
+ if (LLFloaterReg::instanceVisible("beacons") && (gPipeline.getRenderBeacons(NULL) || gPipeline.getRenderHighlights(NULL)))
+ {
+ BOOL has_media = (getMediaType() == LLViewerObject::MEDIA_SET);
+ BOOL is_scripted = !isAvatar() && !getParent() && flagScripted();
+ BOOL is_physical = !isAvatar() && flagUsePhysics();
+
+ return (isParticleSource() && gPipeline.getRenderParticleBeacons(NULL))
+ || (isAudioSource() && gPipeline.getRenderSoundBeacons(NULL))
+ || (has_media && gPipeline.getRenderMOAPBeacons(NULL))
+ || (is_scripted && gPipeline.getRenderScriptedBeacons(NULL))
+ || (is_scripted && flagHandleTouch() && gPipeline.getRenderScriptedTouchBeacons(NULL))
+ || (is_physical && gPipeline.getRenderPhysicalBeacons(NULL));
+ }
+ return FALSE;
+}
+
const LLUUID &LLViewerObject::getAttachmentItemID() const
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 1e8f3f4ec2..24fcf0517e 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -178,6 +178,8 @@ public:
virtual BOOL isHUDAttachment() const { return FALSE; }
virtual BOOL isTempAttachment() const;
+ virtual BOOL isHiglightedOrBeacon() const;
+
virtual void updateRadius() {};
virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius()
@@ -388,7 +390,7 @@ public:
// Create if necessary
LLAudioSource *getAudioSource(const LLUUID& owner_id);
- bool isAudioSource() {return mAudioSourcep != NULL;}
+ BOOL isAudioSource() const {return mAudioSourcep != NULL;}
U8 getMediaType() const;
void setMediaType(U8 media_type);
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 9e09971ced..7d2d6e25c7 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -176,7 +176,7 @@ public:
mToolTip = inv_item->getName() + '\n' + inv_item->getDescription();
}
- /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
+ /*virtual*/ bool getDimensionsF32(S32 first_char, S32 num_chars, F32& width, S32& height) const
{
if (num_chars == 0)
{
@@ -185,7 +185,7 @@ public:
}
else
{
- width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str());
+ width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidthF32(mLabel.c_str());
height = llmax(mImage->getHeight(), mStyle->getFont()->getLineHeight());
}
return false;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f6a16f7da1..3968266c27 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -119,7 +119,7 @@ const F32 MAX_HOVER_Z = 2.0;
const F32 MIN_HOVER_Z = -2.0;
const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f;
-const F32 MAX_ATTACHMENT_COMPLEXITY = 1.0e6f;
+const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f;
using namespace LLAvatarAppearanceDefines;
@@ -9018,6 +9018,9 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
* the official viewer for consideration.
*****************************************************************/
static const U32 COMPLEXITY_BODY_PART_COST = 200;
+ static LLCachedControl<F32> max_complexity_setting(gSavedSettings,"MaxAttachmentComplexity");
+ F32 max_attachment_complexity = max_complexity_setting;
+ max_attachment_complexity = llmax(max_attachment_complexity, DEFAULT_MAX_ATTACHMENT_COMPLEXITY);
// Diagnostic list of all textures on our avatar
static std::set<LLUUID> all_textures;
@@ -9099,7 +9102,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
<< " children: " << attachment_children_cost
<< LL_ENDL;
// Limit attachment complexity to avoid signed integer flipping of the wearer's ACI
- cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, MAX_ATTACHMENT_COMPLEXITY);
+ cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity);
}
}
}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 657babd92c..90ba814a15 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3977,7 +3977,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
start_face = face;
end_face = face+1;
}
-
+ pick_transparent |= isHiglightedOrBeacon();
bool special_cursor = specialHoverCursor();
for (S32 i = start_face; i < end_face; ++i)
{
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 4f5f0ac02c..ebe1fdc4c7 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -909,6 +909,108 @@ Please invite members within 48 hours.
<notification
icon="alertmodal.tga"
+ name="JoinGroupInaccessible"
+ type="alertmodal">
+This group is not accessible to you.
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupError"
+ type="alertmodal">
+Error processing your group membership request.
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupError"
+ type="alertmodal">
+Unable to join group: [reason]
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <tag>reason</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupTrialUser"
+ type="alertmodal">
+Sorry, trial users can't join groups.
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupMaxGroups"
+ type="alertmodal">
+You cannot join '[group_name]':
+You are already a member of [group_count] groups, the maximum number allowed is [max_groups]
+ <tag>success</tag>
+ <tag>group_id</tag>
+ <tag>group_name</tag>
+ <tag>group_count</tag>
+ <tag>max_groups</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupClosedEnrollment"
+ type="alertmodal">
+You cannot join '[group_name]':
+The group no longer has open enrollment.
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupSuccess"
+ type="alertmodal">
+You have been added to the group
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="JoinGroupInsufficientFunds"
+ type="alertmodal">
+Unable to transfer the required L$ [membership_fee] membership fee.
+ <tag>group_id</tag>
+ <tag>success</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="LandBuyPass"
type="alertmodal">
<tag>fail</tag>
@@ -8501,12 +8603,22 @@ Select residents to share with.
</notification>
<notification
- name="MeshUploadError"
+ name="MeshUploadErrorDetails"
icon="alert.tga"
type="alert">
[LABEL] failed to upload: [MESSAGE] [IDENTIFIER]
[DETAILS]See SecondLife.log for details
</notification>
+
+ <notification
+ name="MeshUploadError"
+ icon="alert.tga"
+ type="alert">
+ [LABEL] failed to upload: [MESSAGE]
+[IDENTIFIER]
+
+See SecondLife.log for details
+ </notification>
<notification
name="MeshUploadPermError"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index 440c6613d5..78f771cd51 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -9,6 +9,18 @@
name="chat"
top="1"
width="517">
+
+ <check_box
+ control_name="ChatAutocompleteGestures"
+ height="16"
+ initial_value="true"
+ label="Auto-complete gestures in nearby chat"
+ layout="topleft"
+ top="17"
+ left="13"
+ name="auto_complete_gestures"
+ width="330">
+ </check_box>
<panel
border="false"
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index 2dae1025ec..b7b67147eb 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -586,7 +586,7 @@
label_width="205"
left="10"
max_val="100"
- min_val="0.1"
+ min_val="-100"
name="rptctrl"
width="265" />
<spinner