diff options
172 files changed, 2998 insertions, 1001 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 9b31e5032a..49c9c2cb1d 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -190,6 +190,13 @@ Ansariel Hiller STORM-2094 MAINT-5756 MAINT-4677 + MAINT-6300 + MAINT-6397 + MAINT-6432 + MAINT-6513 + MAINT-6514 + MAINT-6552 + STORM-2133 Aralara Rajal Arare Chantilly CHUIBUG-191 @@ -787,6 +794,7 @@ Kitty Barnett MAINT-6152 MAINT-6153 MAINT-6154 + MAINT-6568 Kolor Fall Komiko Okamoto Korvel Noh @@ -1262,6 +1270,7 @@ Sovereign Engineer MAINT-6107 STORM-2107 MAINT-6218 + MAINT-2141 SpacedOut Frye VWR-34 VWR-45 diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp index 60721977cd..7ea42a3fc0 100644 --- a/indra/llcommon/indra_constants.cpp +++ b/indra/llcommon/indra_constants.cpp @@ -60,6 +60,10 @@ const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On d const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver +const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER +const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER +const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER + const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 02f063f5e8..fda84aa5a8 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -197,6 +197,10 @@ LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF; LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1; LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2; +LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD; +LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD_2D; +LL_COMMON_API extern const LLUUID IMG_TRANSPARENT; + LL_COMMON_API extern const LLUUID IMG_BLOOM1; LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL; LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL; diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index a548c96002..86f407cdb0 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -294,9 +294,11 @@ void LLScopedLock::unlock() bool ll_apr_warn_status(apr_status_t status) { if(APR_SUCCESS == status) return false; +#if !LL_LINUX char buf[MAX_STRING]; /* Flawfinder: ignore */ apr_strerror(status, buf, sizeof(buf)); LL_WARNS("APR") << "APR: " << buf << LL_ENDL; +#endif return true; } diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 645c29d770..e38fc5b2a6 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -275,6 +275,8 @@ LLEventPumps::~LLEventPumps() #pragma warning (push) #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally #endif +const std::string LLEventPump::ANONYMOUS = std::string(); + LLEventPump::LLEventPump(const std::string& name, bool tweak): // Register every new instance with LLEventPumps @@ -313,145 +315,162 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL const NameList& after, const NameList& before) { - // Check for duplicate name before connecting listener to mSignal - ConnectionMap::const_iterator found = mConnections.find(name); - // In some cases the user might disconnect a connection explicitly -- or - // might use LLEventTrackable to disconnect implicitly. Either way, we can - // end up retaining in mConnections a zombie connection object that's - // already been disconnected. Such a connection object can't be - // reconnected -- nor, in the case of LLEventTrackable, would we want to - // try, since disconnection happens with the destruction of the listener - // object. That means it's safe to overwrite a disconnected connection - // object with the new one we're attempting. The case we want to prevent - // is only when the existing connection object is still connected. - if (found != mConnections.end() && found->second.connected()) - { - throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name + - "' on " + typeid(*this).name() + " '" + getName() + "'"); - } - // Okay, name is unique, try to reconcile its dependencies. Specify a new - // "node" value that we never use for an mSignal placement; we'll fix it - // later. - DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before); - // What if this listener has been added, removed and re-added? In that - // case newNode already has a non-negative value because we never remove a - // listener from mDeps. But keep processing uniformly anyway in case the - // listener was added back with different dependencies. Then mDeps.sort() - // would put it in a different position, and the old newNode placement - // value would be wrong, so we'd have to reassign it anyway. Trust that - // re-adding a listener with the same dependencies is the trivial case for - // mDeps.sort(): it can just replay its cache. - DependencyMap::sorted_range sorted_range; - try - { - // Can we pick an order that works including this new entry? - sorted_range = mDeps.sort(); - } - catch (const DependencyMap::Cycle& e) - { - // No: the new node's after/before dependencies have made mDeps - // unsortable. If we leave the new node in mDeps, it will continue - // to screw up all future attempts to sort()! Pull it out. - mDeps.remove(name); - throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + - " '" + getName() + "' would cause cycle: " + e.what()); - } - // Walk the list to verify that we haven't changed the order. - float previous = 0.0, myprev = 0.0; - DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop - for (DependencyMap::sorted_iterator dmi = sorted_range.begin(); - dmi != sorted_range.end(); ++dmi) + float nodePosition = 1.0; + + // if the supplied name is empty we are not interested in the ordering mechanism + // and can bypass attempting to find the optimal location to insert the new + // listener. We'll just tack it on to the end. + if (!name.empty()) // should be the same as testing against ANONYMOUS { - // Since we've added the new entry with an invalid placement, - // recognize it and skip it. - if (dmi->first == name) + // Check for duplicate name before connecting listener to mSignal + ConnectionMap::const_iterator found = mConnections.find(name); + // In some cases the user might disconnect a connection explicitly -- or + // might use LLEventTrackable to disconnect implicitly. Either way, we can + // end up retaining in mConnections a zombie connection object that's + // already been disconnected. Such a connection object can't be + // reconnected -- nor, in the case of LLEventTrackable, would we want to + // try, since disconnection happens with the destruction of the listener + // object. That means it's safe to overwrite a disconnected connection + // object with the new one we're attempting. The case we want to prevent + // is only when the existing connection object is still connected. + if (found != mConnections.end() && found->second.connected()) { - // Remember the iterator belonging to our new node, and which - // placement value was 'previous' at that point. - mydmi = dmi; - myprev = previous; - continue; + throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name + + "' on " + typeid(*this).name() + " '" + getName() + "'"); } - // If the new node has rearranged the existing nodes, we'll find - // that their placement values are no longer in increasing order. - if (dmi->second < previous) + // Okay, name is unique, try to reconcile its dependencies. Specify a new + // "node" value that we never use for an mSignal placement; we'll fix it + // later. + DependencyMap::node_type& newNode = mDeps.add(name, -1.0, after, before); + // What if this listener has been added, removed and re-added? In that + // case newNode already has a non-negative value because we never remove a + // listener from mDeps. But keep processing uniformly anyway in case the + // listener was added back with different dependencies. Then mDeps.sort() + // would put it in a different position, and the old newNode placement + // value would be wrong, so we'd have to reassign it anyway. Trust that + // re-adding a listener with the same dependencies is the trivial case for + // mDeps.sort(): it can just replay its cache. + DependencyMap::sorted_range sorted_range; + try { - // This is another scenario in which we'd better back out the - // newly-added node from mDeps -- but don't do it yet, we want to - // traverse the existing mDeps to report on it! - // Describe the change to the order of our listeners. Copy - // everything but the newest listener to a vector we can sort to - // obtain the old order. - typedef std::vector< std::pair<float, std::string> > SortNameList; - SortNameList sortnames; - for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end()); - cdmi != cdmend; ++cdmi) + // Can we pick an order that works including this new entry? + sorted_range = mDeps.sort(); + } + catch (const DependencyMap::Cycle& e) + { + // No: the new node's after/before dependencies have made mDeps + // unsortable. If we leave the new node in mDeps, it will continue + // to screw up all future attempts to sort()! Pull it out. + mDeps.remove(name); + throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + + " '" + getName() + "' would cause cycle: " + e.what()); + } + // Walk the list to verify that we haven't changed the order. + float previous = 0.0, myprev = 0.0; + DependencyMap::sorted_iterator mydmi = sorted_range.end(); // need this visible after loop + for (DependencyMap::sorted_iterator dmi = sorted_range.begin(); + dmi != sorted_range.end(); ++dmi) + { + // Since we've added the new entry with an invalid placement, + // recognize it and skip it. + if (dmi->first == name) { - if (cdmi->first != name) - { - sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first)); - } + // Remember the iterator belonging to our new node, and which + // placement value was 'previous' at that point. + mydmi = dmi; + myprev = previous; + continue; } - std::sort(sortnames.begin(), sortnames.end()); - std::ostringstream out; - out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName() - << "' would move previous listener '" << dmi->first << "'\nwas: "; - SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end()); - if (sni != snend) + // If the new node has rearranged the existing nodes, we'll find + // that their placement values are no longer in increasing order. + if (dmi->second < previous) { - out << sni->second; - while (++sni != snend) + // This is another scenario in which we'd better back out the + // newly-added node from mDeps -- but don't do it yet, we want to + // traverse the existing mDeps to report on it! + // Describe the change to the order of our listeners. Copy + // everything but the newest listener to a vector we can sort to + // obtain the old order. + typedef std::vector< std::pair<float, std::string> > SortNameList; + SortNameList sortnames; + for (DependencyMap::sorted_iterator cdmi(sorted_range.begin()), cdmend(sorted_range.end()); + cdmi != cdmend; ++cdmi) { - out << ", " << sni->second; + if (cdmi->first != name) + { + sortnames.push_back(SortNameList::value_type(cdmi->second, cdmi->first)); + } } - } - out << "\nnow: "; - DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end()); - if (ddmi != ddmend) - { - out << ddmi->first; - while (++ddmi != ddmend) + std::sort(sortnames.begin(), sortnames.end()); + std::ostringstream out; + out << "New listener '" << name << "' on " << typeid(*this).name() << " '" << getName() + << "' would move previous listener '" << dmi->first << "'\nwas: "; + SortNameList::const_iterator sni(sortnames.begin()), snend(sortnames.end()); + if (sni != snend) { - out << ", " << ddmi->first; + out << sni->second; + while (++sni != snend) + { + out << ", " << sni->second; + } } + out << "\nnow: "; + DependencyMap::sorted_iterator ddmi(sorted_range.begin()), ddmend(sorted_range.end()); + if (ddmi != ddmend) + { + out << ddmi->first; + while (++ddmi != ddmend) + { + out << ", " << ddmi->first; + } + } + // NOW remove the offending listener node. + mDeps.remove(name); + // Having constructed a description of the order change, inform caller. + throw OrderChange(out.str()); } - // NOW remove the offending listener node. - mDeps.remove(name); - // Having constructed a description of the order change, inform caller. - throw OrderChange(out.str()); + // This node becomes the previous one. + previous = dmi->second; } - // This node becomes the previous one. - previous = dmi->second; - } - // We just got done with a successful mDeps.add(name, ...) call. We'd - // better have found 'name' somewhere in that sorted list! - assert(mydmi != sorted_range.end()); - // Four cases: - // 0. name is the only entry: placement 1.0 - // 1. name is the first of several entries: placement (next placement)/2 - // 2. name is between two other entries: placement (myprev + (next placement))/2 - // 3. name is the last entry: placement ceil(myprev) + 1.0 - // Since we've cleverly arranged for myprev to be 0.0 if name is the - // first entry, this folds down to two cases. Case 1 is subsumed by - // case 2, and case 0 is subsumed by case 3. So we need only handle - // cases 2 and 3, which means we need only detect whether name is the - // last entry. Increment mydmi to see if there's anything beyond. - if (++mydmi != sorted_range.end()) - { - // The new node isn't last. Place it between the previous node and - // the successor. - newNode = (myprev + mydmi->second)/2.f; - } - else - { - // The new node is last. Bump myprev up to the next integer, add - // 1.0 and use that. - newNode = std::ceil(myprev) + 1.f; + // We just got done with a successful mDeps.add(name, ...) call. We'd + // better have found 'name' somewhere in that sorted list! + assert(mydmi != sorted_range.end()); + // Four cases: + // 0. name is the only entry: placement 1.0 + // 1. name is the first of several entries: placement (next placement)/2 + // 2. name is between two other entries: placement (myprev + (next placement))/2 + // 3. name is the last entry: placement ceil(myprev) + 1.0 + // Since we've cleverly arranged for myprev to be 0.0 if name is the + // first entry, this folds down to two cases. Case 1 is subsumed by + // case 2, and case 0 is subsumed by case 3. So we need only handle + // cases 2 and 3, which means we need only detect whether name is the + // last entry. Increment mydmi to see if there's anything beyond. + if (++mydmi != sorted_range.end()) + { + // The new node isn't last. Place it between the previous node and + // the successor. + newNode = (myprev + mydmi->second) / 2.f; + } + else + { + // The new node is last. Bump myprev up to the next integer, add + // 1.0 and use that. + newNode = std::ceil(myprev) + 1.f; + } + + nodePosition = newNode; } // Now that newNode has a value that places it appropriately in mSignal, // connect it. - LLBoundListener bound = mSignal->connect(newNode, listener); - mConnections[name] = bound; + LLBoundListener bound = mSignal->connect(nodePosition, listener); + + if (!name.empty()) + { // note that we are not tracking anonymous listeners here either. + // This means that it is the caller's responsibility to either assign + // to a TempBoundListerer (scoped_connection) or manually disconnect + // when done. + mConnections[name] = bound; + } return bound; } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index ba4fcd766e..694951e699 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -365,6 +365,8 @@ typedef boost::signals2::trackable LLEventTrackable; class LL_COMMON_API LLEventPump: public LLEventTrackable { public: + static const std::string ANONYMOUS; // constant for anonymous listeners. + /** * Exception thrown by LLEventPump(). You are trying to instantiate an * LLEventPump (subclass) using the same name as some other instance, and @@ -476,6 +478,12 @@ public: * instantiate your listener, then passing the same name on each listen() * call, allows us to optimize away the second and subsequent dependency * sorts. + * + * If name is set to LLEventPump::ANONYMOUS listen will bypass the entire + * dependency and ordering calculation. In this case, it is critical that + * the result be assigned to a LLTempBoundListener or the listener is + * manually disconnected when no longer needed since there will be no + * way to later find and disconnect this listener manually. * * If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a * listener, listen() will inspect the components of that expression. If a diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f3b8999883..c45db3b185 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -576,6 +576,33 @@ std::string utf8str_truncate(const std::string& utf8str, const S32 max_len) } } +std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len) +{ + if (0 == symbol_len) + { + return std::string(); + } + if ((S32)utf8str.length() <= symbol_len) + { + return utf8str; + } + else + { + int len = 0, byteIndex = 0; + const char* aStr = utf8str.c_str(); + size_t origSize = utf8str.size(); + + for (byteIndex = 0; len < symbol_len && byteIndex < origSize; byteIndex++) + { + if ((aStr[byteIndex] & 0xc0) != 0x80) + { + len += 1; + } + } + return utf8str.substr(0, byteIndex); + } +} + std::string utf8str_substChar( const std::string& utf8str, const llwchar target_char, diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 393f6d7a8c..a40db0f8cc 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -564,6 +564,17 @@ LL_COMMON_API S32 utf8str_compare_insensitive( const std::string& rhs); /** +* @brief Properly truncate a utf8 string to a maximum character count. +* +* If symbol_len is longer than the string passed in, the return +* value == utf8str. +* @param utf8str A valid utf8 string to truncate. +* @param symbol_len The maximum number of symbols in the return value. +* @return Returns a valid utf8 string with symbol count <= max_len. +*/ +LL_COMMON_API std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len); + +/** * @brief Replace all occurences of target_char with replace_char * * @param utf8str A utf8 string to process. diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 4be677a4b0..0f23754096 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -181,6 +181,10 @@ protected: // Map of known bad assets typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t; +// *TODO: these typedefs are passed into the VFS via a legacy C function pointer +// future project would be to convert these to C++ callables (std::function<>) so that +// we can use bind and remove the userData parameter. +// typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status); diff --git a/indra/llmessage/llavatarname.cpp b/indra/llmessage/llavatarname.cpp index d12f157910..d2115ee499 100644 --- a/indra/llmessage/llavatarname.cpp +++ b/indra/llmessage/llavatarname.cpp @@ -166,7 +166,7 @@ void LLAvatarName::setExpires(F64 expires) mExpires = LLFrameTimer::getTotalSeconds() + expires; } -std::string LLAvatarName::getCompleteName() const +std::string LLAvatarName::getCompleteName(bool use_parentheses) const { std::string name; if (sUseDisplayNames) @@ -182,7 +182,14 @@ std::string LLAvatarName::getCompleteName() const name = mDisplayName; if(sUseUsernames) { - name += " (" + mUsername + ")"; + if(use_parentheses) + { + name += " (" + mUsername + ")"; + } + else + { + name += " [ " + mUsername + " ]"; + } } } } @@ -220,7 +227,7 @@ std::string LLAvatarName::getDisplayName() const } } -std::string LLAvatarName::getUserName() const +std::string LLAvatarName::getUserName(bool lowercase) const { std::string name; if (mLegacyLastName.empty() || (mLegacyLastName == "Resident")) @@ -238,7 +245,15 @@ std::string LLAvatarName::getUserName() const } else { - name = mLegacyFirstName + " " + mLegacyLastName; + if(lowercase) + { + name = mLegacyFirstName + "." + mLegacyLastName; + LLStringUtil::toLower(name); + } + else + { + name = mLegacyFirstName + " " + mLegacyLastName; + } } return name; } diff --git a/indra/llmessage/llavatarname.h b/indra/llmessage/llavatarname.h index 1cb3ae421f..192f43f07c 100644 --- a/indra/llmessage/llavatarname.h +++ b/indra/llmessage/llavatarname.h @@ -65,7 +65,7 @@ public: // For normal names, returns "James Linden (james.linden)" // When display names are disabled returns just "James Linden" - std::string getCompleteName() const; + std::string getCompleteName(bool use_parentheses = true) const; // Returns "James Linden" or "bobsmith123 Resident" for backwards // compatibility with systems like voice and muting @@ -80,7 +80,7 @@ public: // Returns "James Linden" or "bobsmith123 Resident" // Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name // Also used for backwards compatibility with systems like voice and muting - std::string getUserName() const; + std::string getUserName(bool lowercase = false) const; // Returns "james.linden" or the legacy name for very old names std::string getAccountName() const { return mUsername; } diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 7742cbc182..9bf38fb336 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -642,7 +642,7 @@ HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request) mHttpRequest(request) { mBoundListener = LLEventPumps::instance().obtain("mainloop"). - listen(LLEventPump::inventName(), boost::bind(&HttpRequestPumper::pollRequest, this, _1)); + listen(LLEventPump::ANONYMOUS, boost::bind(&HttpRequestPumper::pollRequest, this, _1)); } HttpRequestPumper::~HttpRequestPumper() diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 720986a411..00bde8dbc3 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -2235,7 +2235,11 @@ std::string LLDAELoader::getElementLabel(daeElement *element) // retrieve index to distinguish items inside same parent size_t ind = 0; parent->getChildren().find(element, ind); - index_string = "_" + boost::lexical_cast<std::string>(ind); + + if (ind > 0) + { + index_string = "_" + boost::lexical_cast<std::string>(ind); + } // if parent has a name or ID, use it std::string name = parent->getAttribute("name"); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 14f75a2352..69038a8627 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1326,7 +1326,7 @@ void LLFloater::setMinimized(BOOL minimize) } mMinimized = FALSE; - + setFrontmost(); // Reshape *after* setting mMinimized reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE ); } @@ -1575,6 +1575,7 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask) if(offerClickToButton(x, y, mask, BUTTON_TEAR_OFF)) return TRUE; if(offerClickToButton(x, y, mask, BUTTON_DOCK)) return TRUE; + setFrontmost(TRUE, FALSE); // Otherwise pass to drag handle for movement return mDragHandle->handleMouseDown(x, y, mask); } @@ -1649,7 +1650,7 @@ void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key) } } -void LLFloater::setFrontmost(BOOL take_focus) +void LLFloater::setFrontmost(BOOL take_focus, BOOL restore) { LLMultiFloater* hostp = getHost(); if (hostp) @@ -1665,7 +1666,7 @@ void LLFloater::setFrontmost(BOOL take_focus) LLFloaterView * parent = dynamic_cast<LLFloaterView*>( getParent() ); if (parent) { - parent->bringToFront(this, take_focus); + parent->bringToFront(this, take_focus, restore); } // Make sure to set the appropriate transparency type (STORM-732). @@ -2320,7 +2321,10 @@ void LLFloaterView::restoreAll() for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { LLFloater* floaterp = (LLFloater*)*child_it; - floaterp->setMinimized(FALSE); + if (floaterp) + { + floaterp->setMinimized(FALSE); + } } // *FIX: make sure dependents are restored @@ -2394,7 +2398,7 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF } -void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) +void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore) { if (!child) return; @@ -2478,7 +2482,12 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { sendChildToFront(child); } - child->setMinimized(FALSE); + + if(restore) + { + child->setMinimized(FALSE); + } + if (give_focus && !gFocusMgr.childHasKeyboardFocus(child)) { child->setFocus(TRUE); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index ef7c6180d2..165f67499b 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -310,7 +310,7 @@ public: /*virtual*/ void setVisible(BOOL visible); // do not override /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override - void setFrontmost(BOOL take_focus = TRUE); + void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); // Defaults to false. @@ -547,7 +547,7 @@ public: void setCycleMode(BOOL mode) { mFocusCycleMode = mode; } BOOL getCycleMode() const { return mFocusCycleMode; } - void bringToFront( LLFloater* child, BOOL give_focus = TRUE ); + void bringToFront( LLFloater* child, BOOL give_focus = TRUE, BOOL restore = TRUE ); void highlightFocusedFloater(); void unhighlightFocusedFloater(); void focusFrontFloater(); diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 3282c5f726..f9664e0658 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -684,6 +684,13 @@ void LLFolderView::draw() } } + if (mRenameItem && mRenamer && mRenamer->getVisible() && !getVisibleRect().overlaps(mRenamer->getRect())) + { + // renamer is not connected to the item we are renaming in any form so manage it manually + // TODO: consider stopping on any scroll action instead of when out of visible area + finishRenamingItem(); + } + // skip over LLFolderViewFolder::draw since we don't want the folder icon, label, // and arrow for the root folder LLView::draw(); @@ -1629,9 +1636,9 @@ void LLFolderView::update() if (mNeedsAutoSelect) { LL_RECORD_BLOCK_TIME(FTM_AUTO_SELECT); - // select new item only if a filtered item not currently selected + // select new item only if a filtered item not currently selected and there was a selection LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible())) + if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 114dd7bd2f..b5deefd653 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -242,6 +242,8 @@ public: bool useLabelSuffix() { return mUseLabelSuffix; } virtual void updateMenu(); + void finishRenamingItem( void ); + // Note: We may eventually have to move that method up the hierarchy to LLFolderViewItem. LLHandle<LLFolderView> getHandle() const { return getDerivedHandle<LLFolderView>(); } @@ -255,7 +257,6 @@ protected: void commitRename( const LLSD& data ); void onRenamerLost(); - void finishRenamingItem( void ); void closeRenamer( void ); bool selectFirstItem(); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index 3def0386e1..3d618548c4 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -127,6 +127,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mIsSelected( FALSE ), mIsCurSelection( FALSE ), mSelectPending(FALSE), + mIsItemCut(false), + mCutGeneration(0), mLabelStyle( LLFontGL::NORMAL ), mHasVisibleChildren(FALSE), mIsFolderComplete(true), @@ -694,6 +696,19 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L return mIsCurSelection; } +/*virtual*/ bool LLFolderViewItem::isFadeItem() +{ + LLClipboard& clipboard = LLClipboard::instance(); + if (mCutGeneration != clipboard.getGeneration()) + { + mCutGeneration = clipboard.getGeneration(); + mIsItemCut = clipboard.isCutMode() + && ((getParentFolder() && getParentFolder()->isFadeItem()) + || getViewModelItem()->isCutToClipboard()); + } + return mIsItemCut; +} + void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeyboardFocus, const LLUIColor &selectColor, const LLUIColor &flashColor, const LLUIColor &focusOutlineColor, const LLUIColor &mouseOverColor) { @@ -875,6 +890,12 @@ void LLFolderViewItem::draw() } LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; + + if (isFadeItem()) + { + // Fade out item color to indicate it's being cut + color.mV[VALPHA] *= 0.5f; + } drawLabel(font, text_left, y, color, right_x); //--------------------------------------------------------------------------------// @@ -882,7 +903,7 @@ void LLFolderViewItem::draw() // if (!mLabelSuffix.empty()) { - font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor, + font->renderUTF8( mLabelSuffix, 0, right_x, y, isFadeItem() ? color : (LLColor4)sSuffixColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } @@ -972,6 +993,11 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) mIndentation = (getParentFolder()) ? getParentFolder()->getIndentation() + mLocalIndentation : 0; + + if(isOpen() && folder->isOpen()) + { + requestArrange(); + } } static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange"); diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index 0322c8836d..61c39e0175 100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -121,8 +121,11 @@ protected: mIsMouseOverTitle, mAllowWear, mAllowDrop, - mSelectPending; - + mSelectPending, + mIsItemCut; + + S32 mCutGeneration; + LLUIColor mFontColor; LLUIColor mFontHighlightColor; @@ -145,6 +148,7 @@ protected: virtual void addFolder(LLFolderViewFolder*) { } virtual bool isHighlightAllowed(); virtual bool isHighlightActive(); + virtual bool isFadeItem(); virtual bool isFlashing() { return false; } virtual void setFlashState(bool) { } diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index a395af537a..641241a88c 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -173,6 +173,7 @@ public: virtual BOOL isItemCopyable() const = 0; virtual BOOL copyToClipboard() const = 0; virtual BOOL cutToClipboard() = 0; + virtual bool isCutToClipboard() { return false; }; virtual BOOL isClipboardPasteable() const = 0; virtual void pasteFromClipboard() = 0; diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index a08cf91a69..492c9315d1 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -400,12 +400,7 @@ void LLLineEditor::setText(const LLStringExplicit &new_text) if (mMaxLengthChars) { - LLWString truncated_wstring = utf8str_to_wstring(truncated_utf8); - if (truncated_wstring.size() > (U32)mMaxLengthChars) - { - truncated_wstring = truncated_wstring.substr(0, mMaxLengthChars); - } - mText.assign(wstring_to_utf8str(truncated_wstring)); + mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars)); } if (all_selected) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 616c42895c..c7d7535f87 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -177,6 +177,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) : LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)), mURLClickSignal(NULL), mIsFriendSignal(NULL), + mIsObjectBlockedSignal(NULL), mMaxTextByteLength( p.max_text_length ), mFont(p.font), mFontShadow(p.font_shadow), @@ -268,6 +269,8 @@ LLTextBase::~LLTextBase() { mSegments.clear(); delete mURLClickSignal; + delete mIsFriendSignal; + delete mIsObjectBlockedSignal; } void LLTextBase::initFromParams(const LLTextBase::Params& p) @@ -1942,6 +1945,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url)); registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url, true)); registrar.add("Url.Block", boost::bind(&LLUrlAction::blockObject, url)); + registrar.add("Url.Unblock", boost::bind(&LLUrlAction::unblockObject, url)); registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url)); @@ -1968,6 +1972,19 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) removeFriendButton->setEnabled(isFriend); } } + + if (mIsObjectBlockedSignal) + { + bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url)); + LLView* blockButton = mPopupMenu->getChild<LLView>("block_object"); + LLView* unblockButton = mPopupMenu->getChild<LLView>("unblock_object"); + + if (blockButton && unblockButton) + { + blockButton->setVisible(!is_blocked); + unblockButton->setVisible(is_blocked); + } + } if (mPopupMenu) { @@ -3022,6 +3039,15 @@ boost::signals2::connection LLTextBase::setIsFriendCallback(const is_friend_sign return mIsFriendSignal->connect(cb); } +boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb) +{ + if (!mIsObjectBlockedSignal) + { + mIsObjectBlockedSignal = new is_blocked_signal_t(); + } + return mIsObjectBlockedSignal->connect(cb); +} + // // LLTextSegment // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index c6ce5efcb8..85641fd899 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -270,6 +270,7 @@ public: friend class LLUICtrlFactory; typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t; + typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t; struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams> { @@ -456,6 +457,7 @@ public: virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb); + boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb); void setWordWrap(bool wrap); LLScrollContainer* getScrollContainer() const { return mScroller; } @@ -685,6 +687,7 @@ protected: // Used to check if user with given ID is avatar's friend is_friend_signal_t* mIsFriendSignal; + is_blocked_signal_t* mIsObjectBlockedSignal; LLUIString mLabel; // text label that is visible when no user text provided }; diff --git a/indra/llui/lltextutil.cpp b/indra/llui/lltextutil.cpp index fff04b34f2..f6b2ee1dc0 100644 --- a/indra/llui/lltextutil.cpp +++ b/indra/llui/lltextutil.cpp @@ -56,6 +56,26 @@ void LLTextUtil::textboxSetHighlightedVal(LLTextBox *txtbox, const LLStyle::Para txtbox->appendText(text.substr(hl_begin + hl_len), false, normal_style); } +void LLTextUtil::textboxSetGreyedVal(LLTextBox *txtbox, const LLStyle::Params& normal_style, const std::string& text, const std::string& greyed) +{ + static LLUIColor sGreyedTextColor = LLUIColorTable::instance().getColor("Gray", LLColor4::grey); + + size_t greyed_begin = 0, greyed_len = greyed.size(); + + if (greyed_len == 0 || (greyed_begin = text.find(greyed)) == std::string::npos) + { + txtbox->setText(text, normal_style); + return; + } + + LLStyle::Params greyed_style = normal_style; + greyed_style.color = sGreyedTextColor; + txtbox->setText(LLStringUtil::null); // clear text + txtbox->appendText(text.substr(0, greyed_begin), false, normal_style); + txtbox->appendText(text.substr(greyed_begin, greyed_len), false, greyed_style); + txtbox->appendText(text.substr(greyed_begin + greyed_len), false, normal_style); +} + const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str) { static const std::string PHONE_SEPARATOR = LLUI::sSettingGroups["config"]->getString("AvalinePhoneSeparator"); diff --git a/indra/llui/lltextutil.h b/indra/llui/lltextutil.h index 1be81ffd62..a9c143e445 100644 --- a/indra/llui/lltextutil.h +++ b/indra/llui/lltextutil.h @@ -52,6 +52,12 @@ namespace LLTextUtil const std::string& text, const std::string& hl); + void textboxSetGreyedVal( + LLTextBox *txtbox, + const LLStyle::Params& normal_style, + const std::string& text, + const std::string& greyed); + /** * Formats passed phone number to be more human readable. * diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp index 324ceb7fba..bfe0a5bb5d 100644 --- a/indra/llui/lltextvalidate.cpp +++ b/indra/llui/lltextvalidate.cpp @@ -328,6 +328,15 @@ namespace LLTextValidate return rv; } + bool validateASCIINoLeadingSpace(const LLWString &str) + { + if (LLStringOps::isSpace(str[0])) + { + return FALSE; + } + return validateASCII(str); + } + // Used for multiline text stored on the server. // Example is landmark description in Places SP. bool validateASCIIWithNewLine(const LLWString &str) diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h index 5c830d7db3..e2b6c313d6 100644 --- a/indra/llui/lltextvalidate.h +++ b/indra/llui/lltextvalidate.h @@ -52,6 +52,7 @@ namespace LLTextValidate bool validateASCIIPrintableNoPipe(const LLWString &str); bool validateASCIIPrintableNoSpace(const LLWString &str); bool validateASCII(const LLWString &str); + bool validateASCIINoLeadingSpace(const LLWString &str); bool validateASCIIWithNewLine(const LLWString &str); } diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index aabc7ed2e4..f790d8e005 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -522,7 +522,7 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path) else { std::string part(ti->begin(), ti->end()); - context = context->findChildView(part, recurse); + context = context->findChildView(LLURI::unescape(part), recurse); recurse = false; } } diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index 56977c597b..84ea770a8d 100644 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -231,3 +231,13 @@ void LLUrlAction::blockObject(std::string url) executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + LLURI::escape(object_name)); } } + +void LLUrlAction::unblockObject(std::string url) +{ + std::string object_id = getObjectId(url); + std::string object_name = getObjectName(url); + if (LLUUID::validate(object_id)) + { + executeSLURL("secondlife:///app/agent/" + object_id + "/unblock/" + object_name); + } +} diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index 5497e28bb4..2d2a8dfef1 100644 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -83,6 +83,7 @@ public: static void addFriend(std::string url); static void removeFriend(std::string url); static void blockObject(std::string url); + static void unblockObject(std::string url); /// specify the callbacks to enable this class's functionality typedef boost::function<void (const std::string&)> url_callback_t; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 8f7cac1f61..e1d9b1a487 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -391,7 +391,27 @@ static void buildPathname(std::ostream& out, const LLView* view) buildPathname(out, view->getParent()); // Build pathname into ostream on the way back from recursion. - out << '/' << view->getName(); + out << '/'; + + // substitute all '/' in name with appropriate code + std::string name = view->getName(); + std::size_t found = name.find('/'); + std::size_t start = 0; + while (found != std::string::npos) + { + std::size_t sub_len = found - start; + if (sub_len > 0) + { + out << name.substr(start, sub_len); + } + out << "%2F"; + start = found + 1; + found = name.find('/', start); + } + if (start < name.size()) + { + out << name.substr(start, name.size() - start); + } } std::string LLView::getPathname() const @@ -588,6 +608,11 @@ void LLView::onVisibilityChange ( BOOL new_visibility ) BOOL log_visibility_change = LLViewerEventRecorder::instance().getLoggingStatus(); BOOST_FOREACH(LLView* viewp, mChildList) { + if (!viewp) + { + continue; + } + // only views that are themselves visible will have their overall visibility affected by their ancestors old_visibility=viewp->getVisible(); diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 5f4fb8f4a0..86a15f2ef2 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -531,6 +531,13 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd case LL_PATH_PER_ACCOUNT_CHAT_LOGS: prefix = getPerAccountChatLogsDir(); + if (prefix.empty()) + { + // potentially directory was not set yet + // intentionally return a blank string to the caller + LL_DEBUGS("LLDir") << "Conversation log directory is not yet set" << LL_ENDL; + return std::string(); + } break; case LL_PATH_LOGS: diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 0a30f4c807..a05ba8cbba 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -166,6 +166,8 @@ public: // Provide native key event data virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); } + // Get system UI size based on DPI (for 96 DPI UI size should be 1.0) + virtual F32 getSystemUISize() { return 1.0; } protected: LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); virtual ~LLWindow(); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 875ffe4cd4..2a39029eee 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -78,6 +78,31 @@ LPWSTR gIconResource = IDI_APPLICATION; LLW32MsgCallback gAsyncMsgCallback = NULL; +#ifndef DPI_ENUMS_DECLARED + +typedef enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +typedef enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; + +#endif + +typedef HRESULT(STDAPICALLTYPE *SetProcessDpiAwarenessType)(_In_ PROCESS_DPI_AWARENESS value); + +typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)( + _In_ HMONITOR hmonitor, + _In_ MONITOR_DPI_TYPE dpiType, + _Out_ UINT *dpiX, + _Out_ UINT *dpiY); + // // LLWindowWin32 // @@ -3878,6 +3903,46 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) return FALSE; } +F32 LLWindowWin32::getSystemUISize() +{ + float scale_value = 0; + HWND hWnd = (HWND)getPlatformWindow(); + HDC hdc = GetDC(hWnd); + HMONITOR hMonitor; + + HMODULE hShcore = LoadLibrary(L"shcore.dll"); + + if (hShcore != NULL) + { + SetProcessDpiAwarenessType pSPDA; + pSPDA = (SetProcessDpiAwarenessType)GetProcAddress(hShcore, "SetProcessDpiAwareness"); + GetDpiForMonitorType pGDFM; + pGDFM = (GetDpiForMonitorType)GetProcAddress(hShcore, "GetDpiForMonitor"); + if (pSPDA != NULL && pGDFM != NULL) + { + pSPDA(PROCESS_PER_MONITOR_DPI_AWARE); + POINT pt; + UINT dpix = 0, dpiy = 0; + HRESULT hr = E_FAIL; + + // Get the DPI for the main monitor, and set the scaling factor + pt.x = 1; + pt.y = 1; + hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST); + hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + scale_value = dpix / 96.0f; + } + } + else + { + LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL; + scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; + } + + ReleaseDC(hWnd, hdc); + return scale_value; +} + //static std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList() { diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 1a775eadaf..1386321912 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -110,6 +110,8 @@ public: /*virtual*/ void interruptLanguageTextInput(); /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + /*virtual*/ F32 getSystemUISize(); + LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); static std::vector<std::string> getDynamicFallbackFontList(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8d863631cf..dce0ea73cd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1315,13 +1315,10 @@ set(viewer_HEADER_FILES source_group("CMake Rules" FILES ViewerInstall.cmake) +#summary.json creation moved to viewer_manifest.py MAINT-6413 # the viewer_version.txt file created here is for passing to viewer_manifest and autobuild -# the summary.json file is created for the benefit of the TeamCity builds, where -# it is used to provide descriptive information to the build results page file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt" "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\n") -file(WRITE "${CMAKE_BINARY_DIR}/summary.json" - "{\"Type\":\"viewer\",\"Version\":\"${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\"}\n") set_source_files_properties( llversioninfo.cpp tests/llversioninfo_test.cpp diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 2cd6638042..a0d3dc0f99 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -37,7 +37,7 @@ tooltip_ref="Command_Build_Tooltip" execute_function="Build.Toggle" execute_parameters="build" - is_enabled_function="Build.Enabled" + is_enabled_function="Build.EnabledOrActive" is_enabled_parameters="build" is_running_function="Floater.IsOpen" is_running_parameters="build" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a8d42be2a1..c3d7d67c86 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3701,6 +3701,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>QueueInventoryFetchTimeout</key> + <map> + <key>Comment</key> + <string>Max time llcompilequeue will wait for inventory fetch to complete (in seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>300.0</real> + </map> <key>FindLandArea</key> <map> <key>Comment</key> @@ -10207,6 +10218,17 @@ <key>Value</key> <real>1.0</real> </map> + <key>RenderRiggedFactorMultiplier</key> + <map> + <key>Comment</key> + <string>Affects level of detail for worn rigged meshes</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>7.5</real> + </map> <key>RenderWater</key> <map> <key>Comment</key> @@ -11065,6 +11087,28 @@ <key>Value</key> <integer>1</integer> </map> + <key>FriendsListHideUsernames</key> + <map> + <key>Comment</key> + <string>Show both Display name and Username in Friend list</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>NearbyListHideUsernames</key> + <map> + <key>Comment</key> + <string>Show both Display name and Username in Nearby list</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>NearbyListShowMap</key> <map> <key>Comment</key> @@ -12759,6 +12803,17 @@ <key>Value</key> <real>1.0</real> </map> + <key>LastSystemUIScaleFactor</key> + <map> + <key>Comment</key> + <string>Size of system UI during last run. On Windows 100% (96 DPI) system setting is 1.0 UI size</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1.0</real> + </map> <key>UIScrollbarSize</key> <map> <key>Comment</key> @@ -13254,6 +13309,17 @@ <key>Value</key> <string>1</string> </map> + <key>UpdaterShowReleaseNotes</key> + <map> + <key>Comment</key> + <string>Enables displaying of the Release notes in a web floater after update.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>UploadBakedTexOld</key> <map> <key>Comment</key> diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index be8ea2bab9..e99b94f150 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -32,7 +32,7 @@ RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 -RenderAvatarMaxComplexity 1 80000 +RenderAvatarMaxComplexity 1 350000 RenderAvatarVP 1 1 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index ca6c00951d..801a622e93 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -32,7 +32,7 @@ RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 -RenderAvatarMaxComplexity 1 80000 +RenderAvatarMaxComplexity 1 350000 RenderAvatarVP 1 1 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index ea69b088f9..1f891ee4d7 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -32,7 +32,7 @@ RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 -RenderAvatarMaxComplexity 1 80000 +RenderAvatarMaxComplexity 1 350000 RenderAvatarVP 1 1 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 diff --git a/indra/newview/installers/windows/installer_template.nsi b/indra/newview/installers/windows/installer_template.nsi index b8677fd9e4..89317f2793 100644 --- a/indra/newview/installers/windows/installer_template.nsi +++ b/indra/newview/installers/windows/installer_template.nsi @@ -648,6 +648,7 @@ Function un.ProgramFiles %%DELETE_FILES%%
# Optional/obsolete files. Delete won't fail if they don't exist.
+Delete "$INSTDIR\autorun.bat"
Delete "$INSTDIR\dronesettings.ini"
Delete "$INSTDIR\message_template.msg"
Delete "$INSTDIR\newview.pdb"
@@ -679,6 +680,16 @@ FOLDERFOUND: NOFOLDER:
+MessageBox MB_YESNO $(DeleteRegistryKeysMB) IDYES DeleteKeys IDNO NoDelete
+
+DeleteKeys:
+ DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Classes\x-grid-location-info"
+ DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Classes\secondlife"
+ DeleteRegKey HKEY_CLASSES_ROOT "x-grid-location-info"
+ DeleteRegKey HKEY_CLASSES_ROOT "secondlife"
+
+NoDelete:
+
FunctionEnd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/indra/newview/installers/windows/lang_en-us.nsi b/indra/newview/installers/windows/lang_en-us.nsi Binary files differindex 343c312ddc..aa403a961c 100644 --- a/indra/newview/installers/windows/lang_en-us.nsi +++ b/indra/newview/installers/windows/lang_en-us.nsi diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index d933537d2e..d8b0787852 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3895,11 +3895,17 @@ void LLAgent::handleTeleportFinished() mIsMaturityRatingChangingDuringTeleport = false; } - // Init SLM Marketplace connection so we know which UI should be used for the user as a merchant - // Note: Eventually, all merchant will be migrated to the new SLM system and there will be no reason to show the old UI at all. - // Note: Some regions will not support the SLM cap for a while so we need to do that check for each teleport. - // *TODO : Suppress that line from here once the whole grid migrated to SLM and move it to idle_startup() (llstartup.cpp) - check_merchant_status(); + if (mRegionp) + { + if (mRegionp->capabilitiesReceived()) + { + onCapabilitiesReceivedAfterTeleport(); + } + else + { + mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::onCapabilitiesReceivedAfterTeleport)); + } + } } void LLAgent::handleTeleportFailed() @@ -3931,6 +3937,14 @@ void LLAgent::handleTeleportFailed() } } +/*static*/ +void LLAgent::onCapabilitiesReceivedAfterTeleport() +{ + + check_merchant_status(); +} + + void LLAgent::teleportRequest( const U64& region_handle, const LLVector3& pos_local, diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 3a533c2cba..d82ff7a67f 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -676,6 +676,8 @@ private: void handleTeleportFinished(); void handleTeleportFailed(); + static void onCapabilitiesReceivedAfterTeleport(); + //-------------------------------------------------------------------- // Teleport State //-------------------------------------------------------------------- diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index b76a66ab39..170e4063a1 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -62,23 +62,37 @@ using namespace LLAvatarAppearanceDefines; /////////////////////////////////////////////////////////////////////////////// -// Callback to wear and start editing an item that has just been created. -void wear_and_edit_cb(const LLUUID& inv_item) +void set_default_permissions(LLViewerInventoryItem* item) { - if (inv_item.isNull()) return; - - LLViewerInventoryItem* item = gInventory.getItem(inv_item); - if (!item) return; - - LLPermissions perm = item->getPermissions(); + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskNextOwner() != LLFloaterPerms::getNextOwnerPerms("Wearables") + || perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms("Wearables") + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms("Wearables")) + { perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); + item->setPermissions(perm); item->updateServer(FALSE); - gInventory.updateItem(item); - gInventory.notifyObservers(); + } +} + +// Callback to wear and start editing an item that has just been created. +void wear_and_edit_cb(const LLUUID& inv_item) +{ + if (inv_item.isNull()) return; + + LLViewerInventoryItem* item = gInventory.getItem(inv_item); + if (!item) return; + + set_default_permissions(item); + + // item was just created, update even if permissions did not changed + gInventory.updateItem(item); + gInventory.notifyObservers(); // Request editing the item after it gets worn. gAgentWearables.requestEditingWearable(inv_item); @@ -94,13 +108,8 @@ void wear_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("Wearables")); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Wearables")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Wearables")); - item->setPermissions(perm); + set_default_permissions(item); - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -253,6 +262,7 @@ void LLAgentWearables::AddWearableToAgentInventoryCallback::fire(const LLUUID& i { LLAppearanceMgr::instance().addCOFItemLink(inv_item, new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription); + editWearable(inv_item); } } @@ -423,7 +433,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type, // old_wearable may still be referred to by other inventory items. Revert // unsaved changes so other inventory items aren't affected by the changes // that were just saved. - old_wearable->revertValues(); + old_wearable->revertValuesWithoutUpdate(); } void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index) @@ -1364,6 +1374,30 @@ void LLAgentWearables::findAttachmentsAddRemoveInfo(LLInventoryModel::item_array // LL_INFOS() << "remove " << remove_count << " add " << add_count << LL_ENDL; } +std::vector<LLViewerObject*> LLAgentWearables::getTempAttachments() +{ + llvo_vec_t temp_attachs; + if (isAgentAvatarValid()) + { + for (LLVOAvatar::attachment_map_t::iterator iter = gAgentAvatarp->mAttachmentPoints.begin(); iter != gAgentAvatarp->mAttachmentPoints.end();) + { + LLVOAvatar::attachment_map_t::iterator curiter = iter++; + LLViewerJointAttachment* attachment = curiter->second; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject *objectp = (*attachment_iter); + if (objectp && objectp->isTempAttachment()) + { + temp_attachs.push_back(objectp); + } + } + } + } + return temp_attachs; +} + void LLAgentWearables::userRemoveMultipleAttachments(llvo_vec_t& objects_to_remove) { if (!isAgentAvatarValid()) return; diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 1004482020..b27698fd8f 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -185,6 +185,8 @@ public: static void userRemoveMultipleAttachments(llvo_vec_t& llvo_array); static void userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_item_array); + static llvo_vec_t getTempAttachments(); + //-------------------------------------------------------------------- // Signals //-------------------------------------------------------------------- diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 3e3d5c7456..648212177b 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -838,11 +838,11 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories) void AISUpdate::doUpdate() { - // Do version/descendent accounting. + // Do version/descendant accounting. for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin(); catit != mCatDescendentDeltas.end(); ++catit) { - LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL; + LL_DEBUGS("Inventory") << "descendant accounting for " << catit->first << LL_ENDL; const LLUUID cat_id(catit->first); // Don't account for update if we just created this category. @@ -859,13 +859,13 @@ void AISUpdate::doUpdate() continue; } - // If we have a known descendent count, set that now. + // If we have a known descendant count, set that now. LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); if (cat) { S32 descendent_delta = catit->second; S32 old_count = cat->getDescendentCount(); - LL_DEBUGS("Inventory") << "Updating descendent count for " + LL_DEBUGS("Inventory") << "Updating descendant count for " << cat->getName() << " " << cat_id << " with delta " << descendent_delta << " from " << old_count << " to " << (old_count+descendent_delta) << LL_ENDL; @@ -896,7 +896,7 @@ void AISUpdate::doUpdate() LLUUID category_id(update_it->first); LLPointer<LLViewerInventoryCategory> new_category = update_it->second; // Since this is a copy of the category *before* the accounting update, above, - // we need to transfer back the updated version/descendent count. + // we need to transfer back the updated version/descendant count. LLViewerInventoryCategory* curr_cat = gInventory.getCategory(new_category->getUUID()); if (!curr_cat) { @@ -961,7 +961,16 @@ void AISUpdate::doUpdate() { LL_WARNS() << "Possible version mismatch for category " << cat->getName() << ", viewer version " << cat->getVersion() - << " server version " << version << LL_ENDL; + << " AIS version " << version << " !!!Adjusting local version!!!" << LL_ENDL; + + // the AIS version should be considered the true version. Adjust + // our local category model to reflect this version number. Otherwise + // it becomes possible to get stuck with the viewer being out of + // sync with the inventory system. Under normal circumstances + // inventory COF is maintained on the viewer through calls to + // LLInventoryModel::accountForUpdate when a changing operation + // is performed. This occasionally gets out of sync however. + cat->setVersion(version); } } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index cc676550ab..4a4361e94b 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -60,6 +60,8 @@ #include "llcoros.h" #include "lleventcoro.h" +#include "llavatarpropertiesprocessor.h" + #if LL_MSVC // disable boost::lexical_cast warning #pragma warning (disable:4702) @@ -3359,15 +3361,9 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() { if (!mOutstandingAppearanceBakeRequest) { -#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE mRerequestAppearanceBake = false; LLCoprocedureManager::CoProcedure_t proc = boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this, _1); LLCoprocedureManager::instance().enqueueCoprocedure("AIS", "LLAppearanceMgr::serverAppearanceUpdateCoro", proc); -#else - LLCoros::instance().launch("serverAppearanceUpdateCoro", - boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this)); - -#endif } else { @@ -3375,17 +3371,8 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() } } -#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter) -#else -void LLAppearanceMgr::serverAppearanceUpdateCoro() -#endif { -#ifndef APPEARANCEBAKE_AS_IN_AIS_QUEUE - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter( - new LLCoreHttpUtil::HttpCoroutineAdapter("serverAppearanceUpdateCoro", LLCore::HttpRequest::DEFAULT_POLICY_ID)); -#endif - mRerequestAppearanceBake = false; if (!gAgent.getRegion()) { @@ -3493,10 +3480,15 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro() // on multiple machines. if (result.has("expected")) { - S32 expectedCofVersion = result["expected"].asInteger(); LL_WARNS("Avatar") << "Server expected " << expectedCofVersion << " as COF version" << LL_ENDL; + // Force an update texture request for ourself. The message will return + // through the UDP and be handled in LLVOAvatar::processAvatarAppearance + // this should ensure that we receive a new canonical COF from the sim + // host. Hopefully it will return before the timeout. + LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(gAgent.getID()); + bRetry = true; // Wait for a 1/2 second before trying again. Just to keep from asking too quickly. if (++retryCount > BAKE_RETRY_MAX_COUNT) @@ -3924,6 +3916,10 @@ void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) LL_DEBUGS("Avatar") << "setAttachmentInvLinkEnable => " << (int) val << LL_ENDL; mAttachmentInvLinkEnabled = val; } +boost::signals2::connection LLAppearanceMgr::setAttachmentsChangedCallback(attachments_changed_callback_t cb) +{ + return mAttachmentsChangeSignal.connect(cb); +} void dumpAttachmentSet(const std::set<LLUUID>& atts, const std::string& msg) { @@ -3950,6 +3946,8 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); LLAttachmentsMgr::instance().onAttachmentArrived(item_id); + + mAttachmentsChangeSignal(); } void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) @@ -3970,6 +3968,8 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) { //LL_INFOS() << "no link changes, inv link not enabled" << LL_ENDL; } + + mAttachmentsChangeSignal(); } BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index bf181cb4ad..07ae5fba86 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -225,14 +225,14 @@ public: void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; } std::string getAppearanceServiceURL() const; + typedef boost::function<void ()> attachments_changed_callback_t; + typedef boost::signals2::signal<void ()> attachments_changed_signal_t; + boost::signals2::connection setAttachmentsChangedCallback(attachments_changed_callback_t cb); + private: -#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE void serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter); -#else - void serverAppearanceUpdateCoro(); -#endif static void debugAppearanceUpdateCOF(const LLSD& content); @@ -272,6 +272,8 @@ private: LLTimer mInFlightTimer; static bool mActive; + attachments_changed_signal_t mAttachmentsChangeSignal; + std::auto_ptr<LLOutfitUnLockTimer> mUnlockOutfitTimer; // Set of temp attachment UUIDs that should be removed diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b6d02ea2f8..950692a788 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -587,6 +587,7 @@ static void settings_to_globals() LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor"); + LLVOVolume::sRiggedFactorMultiplier = gSavedSettings.getF32("RenderRiggedFactorMultiplier"); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor"); @@ -696,7 +697,8 @@ LLAppViewer::LLAppViewer() mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)), mFastTimerLogThread(NULL), mUpdater(new LLUpdaterService()), - mSettingsLocationList(NULL) + mSettingsLocationList(NULL), + mIsFirstRun(false) { if(NULL != sInstance) { @@ -1220,6 +1222,8 @@ bool LLAppViewer::init() boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + showReleaseNotesIfRequired(); + return true; } @@ -2483,7 +2487,10 @@ bool LLAppViewer::initConfiguration() if (gSavedSettings.getBOOL("FirstRunThisInstall")) { - // Note that the "FirstRunThisInstall" settings is currently unused. + // Set firstrun flag to indicate that some further init actiona should be taken + // like determining screen DPI value and so on + mIsFirstRun = true; + gSavedSettings.setBOOL("FirstRunThisInstall", FALSE); } @@ -3140,7 +3147,8 @@ bool LLAppViewer::initWindow() .min_width(gSavedSettings.getU32("MinWindowWidth")) .min_height(gSavedSettings.getU32("MinWindowHeight")) .fullscreen(gSavedSettings.getBOOL("FullScreen")) - .ignore_pixel_depth(ignorePixelDepth); + .ignore_pixel_depth(ignorePixelDepth) + .first_run(mIsFirstRun); gViewerWindow = new LLViewerWindow(window_params); @@ -3438,6 +3446,12 @@ std::string LLAppViewer::getViewerInfoString() const { support << '\n' << LLTrans::getString("AboutTraffic", args); } + + // SLT timestamp + LLSD substitution; + substitution["datetime"] = (S32)time(NULL);//(S32)time_corrected(); + support << "\n" << LLTrans::getString("AboutTime", substitution); + return support.str(); } @@ -5793,6 +5807,18 @@ void LLAppViewer::launchUpdater() // LLAppViewer::instance()->forceQuit(); } +/** +* Check if user is running a new version of the viewer. +* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. +*/ +void LLAppViewer::showReleaseNotesIfRequired() +{ + if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion && gSavedSettings.getBOOL("UpdaterShowReleaseNotes")) + { + LLSD info(getViewerInfo()); + LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); + } +} //virtual void LLAppViewer::setMasterSystemAudioMute(bool mute) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b5e674bd7b..d4af2440be 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -254,6 +254,8 @@ private: void sendLogoutRequest(); void disconnectViewer(); + + void showReleaseNotesIfRequired(); // *FIX: the app viewer class should be some sort of singleton, no? // Perhaps its child class is the singleton and this should be an abstract base. @@ -316,6 +318,7 @@ private: // llcorehttp library init/shutdown helper LLAppCoreHttp mAppCoreHttp; + bool mIsFirstRun; //--------------------------------------------- //*NOTE: Mani - legacy updater stuff // Still useable? diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 00bc8ebe87..a6e745448a 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -476,13 +476,63 @@ void LLAvatarActions::kick(const LLUUID& id) } // static +void LLAvatarActions::freezeAvatar(const LLUUID& id) +{ + std::string fullname; + gCacheName->getFullName(id, fullname); + LLSD payload; + payload["avatar_id"] = id; + + if (!fullname.empty()) + { + LLSD args; + args["AVATAR_NAME"] = fullname; + LLNotificationsUtil::add("FreezeAvatarFullname", args, payload, handleFreezeAvatar); + } + else + { + LLNotificationsUtil::add("FreezeAvatar", LLSD(), payload, handleFreezeAvatar); + } +} + +// static +void LLAvatarActions::ejectAvatar(const LLUUID& id, bool ban_enabled) +{ + std::string fullname; + gCacheName->getFullName(id, fullname); + LLSD payload; + payload["avatar_id"] = id; + payload["ban_enabled"] = ban_enabled; + LLSD args; + if (!fullname.empty()) + { + args["AVATAR_NAME"] = fullname; + } + + if (ban_enabled) + { + LLNotificationsUtil::add("EjectAvatarFullname", args, payload, handleEjectAvatar); + } + else + { + if (!fullname.empty()) + { + LLNotificationsUtil::add("EjectAvatarFullnameNoBan", args, payload, handleEjectAvatar); + } + else + { + LLNotificationsUtil::add("EjectAvatarNoBan", LLSD(), payload, handleEjectAvatar); + } + } +} + +// static void LLAvatarActions::freeze(const LLUUID& id) { LLSD payload; payload["avatar_id"] = id; LLNotifications::instance().add("FreezeUser", LLSD(), payload, handleFreeze); } - // static void LLAvatarActions::unfreeze(const LLUUID& id) { @@ -1133,10 +1183,77 @@ bool LLAvatarActions::handleKick(const LLSD& notification, const LLSD& response) } return false; } -bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response) + +bool LLAvatarActions::handleFreezeAvatar(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); + if (0 == option || 1 == option) + { + U32 flags = 0x0; + if (1 == option) + { + // unfreeze + flags |= 0x1; + } + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + LLMessageSystem* msg = gMessageSystem; + + msg->newMessage("FreezeUser"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("TargetID", avatar_id ); + msg->addU32("Flags", flags ); + gAgent.sendReliableMessage(); + } + return false; +} + +bool LLAvatarActions::handleEjectAvatar(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (2 == option) + { + return false; + } + LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); + bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean(); + + if (0 == option) + { + LLMessageSystem* msg = gMessageSystem; + U32 flags = 0x0; + msg->newMessage("EjectUser"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID() ); + msg->addUUID("SessionID", gAgent.getSessionID() ); + msg->nextBlock("Data"); + msg->addUUID("TargetID", avatar_id ); + msg->addU32("Flags", flags ); + gAgent.sendReliableMessage(); + } + else if (ban_enabled) + { + LLMessageSystem* msg = gMessageSystem; + + U32 flags = 0x1; + msg->newMessage("EjectUser"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID() ); + msg->addUUID("SessionID", gAgent.getSessionID() ); + msg->nextBlock("Data"); + msg->addUUID("TargetID", avatar_id ); + msg->addU32("Flags", flags ); + gAgent.sendReliableMessage(); + } + return false; +} + +bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); if (option == 0) { LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); @@ -1153,6 +1270,7 @@ bool LLAvatarActions::handleFreeze(const LLSD& notification, const LLSD& respons } return false; } + bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& response) { S32 option = LLNotification::getSelectedOption(notification, response); diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index bd0ac24e93..256d44d820 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -173,6 +173,9 @@ public: */ static void inviteToGroup(const LLUUID& id); + static void freezeAvatar(const LLUUID& id); + + static void ejectAvatar(const LLUUID& id, bool ban_enabled = false); /** * Kick avatar off grid */ @@ -242,6 +245,8 @@ private: static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); static bool handleRemove(const LLSD& notification, const LLSD& response); static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id); + static bool handleFreezeAvatar(const LLSD& notification, const LLSD& response); + static bool handleEjectAvatar(const LLSD& notification, const LLSD& response); static bool handleKick(const LLSD& notification, const LLSD& response); static bool handleFreeze(const LLSD& notification, const LLSD& response); static bool handleUnfreeze(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 8846d1317d..513f25e301 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -140,6 +140,7 @@ LLAvatarList::LLAvatarList(const Params& p) , mShowProfileBtn(p.show_profile_btn) , mShowSpeakingIndicator(p.show_speaking_indicator) , mShowPermissions(p.show_permissions_granted) +, mShowCompleteName(false) { setCommitOnSelectionChange(true); @@ -174,6 +175,11 @@ void LLAvatarList::setShowIcons(std::string param_name) mShowIcons = gSavedSettings.getBOOL(mIconParamName); } +std::string LLAvatarList::getAvatarName(LLAvatarName av_name) +{ + return mShowCompleteName? av_name.getCompleteName(false) : av_name.getDisplayName(); +} + // virtual void LLAvatarList::draw() { @@ -279,7 +285,7 @@ void LLAvatarList::refresh() LLAvatarName av_name; have_names &= LLAvatarNameCache::get(buddy_id, &av_name); - if (!have_filter || findInsensitive(av_name.getDisplayName(), mNameFilter)) + if (!have_filter || findInsensitive(getAvatarName(av_name), mNameFilter)) { if (nadded >= ADD_LIMIT) { @@ -297,7 +303,7 @@ void LLAvatarList::refresh() } else { - std::string display_name = av_name.getDisplayName(); + std::string display_name = getAvatarName(av_name); addNewItem(buddy_id, display_name.empty() ? waiting_str : display_name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); @@ -327,7 +333,7 @@ void LLAvatarList::refresh() const LLUUID& buddy_id = it->asUUID(); LLAvatarName av_name; have_names &= LLAvatarNameCache::get(buddy_id, &av_name); - if (!findInsensitive(av_name.getDisplayName(), mNameFilter)) + if (!findInsensitive(getAvatarName(av_name), mNameFilter)) { removeItemByUUID(buddy_id); modified = true; @@ -381,6 +387,7 @@ void LLAvatarList::updateAvatarNames() for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++) { LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it); + item->setShowCompleteName(mShowCompleteName); item->updateAvatarName(); } mNeedUpdateNames = false; @@ -400,7 +407,7 @@ bool LLAvatarList::filterHasMatches() // If name has not been loaded yet we consider it as a match. // When the name will be loaded the filter will be applied again(in refresh()). - if (have_name && !findInsensitive(av_name.getDisplayName(), mNameFilter)) + if (have_name && !findInsensitive(getAvatarName(av_name), mNameFilter)) { continue; } @@ -434,6 +441,7 @@ S32 LLAvatarList::notifyParent(const LLSD& info) void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); + item->setShowCompleteName(mShowCompleteName); // This sets the name as a side effect item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus); item->setOnline(mIgnoreOnlineStatus ? true : is_online); @@ -445,6 +453,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is item->showSpeakingIndicator(mShowSpeakingIndicator); item->setShowPermissions(mShowPermissions); + item->setDoubleClickCallback(boost::bind(&LLAvatarList::onItemDoubleClicked, this, _1, _2, _3, _4)); addItem(item, id, pos); diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 3542577ae3..1a672c279b 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -83,6 +83,7 @@ public: void setShowIcons(std::string param_name); bool getIconsVisible() const { return mShowIcons; } const std::string getIconParamName() const{return mIconParamName;} + std::string getAvatarName(LLAvatarName av_name); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -100,6 +101,8 @@ public: void addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name); void handleDisplayNamesOptionChanged(); + void setShowCompleteName(bool show) { mShowCompleteName = show;}; + protected: void refresh(); @@ -126,6 +129,7 @@ private: bool mShowProfileBtn; bool mShowSpeakingIndicator; bool mShowPermissions; + bool mShowCompleteName; LLTimer* mLITUpdateTimer; // last interaction time update timer std::string mIconParamName; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 3e6c817dd6..af3fac91bc 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -77,8 +77,10 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) mShowInfoBtn(true), mShowProfileBtn(true), mShowPermissions(false), + mShowCompleteName(false), mHovered(false), - mAvatarNameCacheConnection() + mAvatarNameCacheConnection(), + mGreyOutUsername("") { if (not_from_ui_factory) { @@ -399,14 +401,28 @@ void LLAvatarListItem::updateAvatarName() void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight) { - LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight); + if(mShowCompleteName && highlight.empty()) + { + LLTextUtil::textboxSetGreyedVal(mAvatarName, mAvatarNameStyle, name, mGreyOutUsername); + } + else + { + LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight); + } } void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name) { mAvatarNameCacheConnection.disconnect(); - setAvatarName(av_name.getDisplayName()); + mGreyOutUsername = ""; + std::string name_string = mShowCompleteName? av_name.getCompleteName(false) : av_name.getDisplayName(); + if(av_name.getCompleteName() != av_name.getUserName()) + { + mGreyOutUsername = "[ " + av_name.getUserName(true) + " ]"; + LLStringUtil::toLower(mGreyOutUsername); + } + setAvatarName(name_string); setAvatarToolTip(av_name.getUserName()); //requesting the list to resort diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 7ef35a746e..36d18114aa 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -106,6 +106,7 @@ public: void setShowPermissions(bool show) { mShowPermissions = show; }; void showLastInteractionTime(bool show); void setAvatarIconVisible(bool visible); + void setShowCompleteName(bool show) { mShowCompleteName = show;}; const LLUUID& getAvatarId() const; std::string getAvatarName() const; @@ -218,6 +219,9 @@ private: /// true when the mouse pointer is hovering over this item bool mHovered; + bool mShowCompleteName; + std::string mGreyOutUsername; + void fetchAvatarName(); boost::signals2::connection mAvatarNameCacheConnection; diff --git a/indra/newview/llavatarrendernotifier.cpp b/indra/newview/llavatarrendernotifier.cpp index a13e142e16..24934fdb73 100644 --- a/indra/newview/llavatarrendernotifier.cpp +++ b/indra/newview/llavatarrendernotifier.cpp @@ -63,7 +63,7 @@ mLatestAgentComplexity(0), mLatestOverLimitPct(0.0f), mShowOverLimitAgents(false), mNotifyOutfitLoading(false), -mLastCofVersion(-1), +mLastCofVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), mLastOutfitRezStatus(-1), mLastSkeletonSerialNum(-1) { @@ -207,8 +207,8 @@ void LLAvatarRenderNotifier::updateNotificationState() mLastSkeletonSerialNum = gAgentAvatarp->mLastSkeletonSerialNum; } else if (mLastCofVersion >= 0 - && (mLastCofVersion != gAgentAvatarp->mLastUpdateRequestCOFVersion - || mLastSkeletonSerialNum != gAgentAvatarp->mLastSkeletonSerialNum)) + && (mLastCofVersion != LLAppearanceMgr::instance().getCOFVersion() + || mLastSkeletonSerialNum != gAgentAvatarp->mLastSkeletonSerialNum)) { // version mismatch in comparison to previous outfit - outfit changed mNotifyOutfitLoading = true; diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 00fa6dd979..54c6c985d6 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -311,7 +311,8 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) } else if (mesg[0] == '/' && mesg[1] - && LLStringOps::isDigit(mesg[1])) + && (LLStringOps::isDigit(mesg[1]) + || (mesg[1] == '-' && mesg[2] && LLStringOps::isDigit(mesg[2])))) { // This a special "/20" speak on a channel S32 pos = 0; @@ -325,7 +326,7 @@ LLWString LLChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) channel_string.push_back(c); pos++; } - while(c && pos < 64 && LLStringOps::isDigit(c)); + while(c && pos < 64 && (LLStringOps::isDigit(c) || (pos == 1 && c == '-'))); // Move the pointer forward to the first non-whitespace char // Check isspace before looping, so we can handle "/33foo" diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 4b426081d0..5d2997688f 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -156,6 +156,10 @@ public: LLFloaterSidePanelContainer::showPanel("people", "panel_people", LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId())); } + else if (level == "unblock") + { + LLMuteList::getInstance()->remove(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); + } else if (level == "map") { std::string url = "secondlife://" + mObjectData["slurl"].asString(); @@ -169,6 +173,20 @@ public: } + bool onObjectIconContextMenuItemVisible(const LLSD& userdata) + { + std::string level = userdata.asString(); + if (level == "is_blocked") + { + return LLMuteList::getInstance()->isMuted(getAvatarId(), mFrom, LLMute::flagTextChat); + } + else if (level == "not_blocked") + { + return !LLMuteList::getInstance()->isMuted(getAvatarId(), mFrom, LLMute::flagTextChat); + } + return false; + } + void onAvatarIconContextMenuItemClicked(const LLSD& userdata) { std::string level = userdata.asString(); @@ -275,6 +293,7 @@ public: registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); + registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mPopupMenuHandleAvatar = menu->getHandle(); @@ -719,6 +738,8 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) editor_params.trusted_content = false; mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); mEditor->setIsFriendCallback(LLAvatarActions::isFriend); + mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0)); + } LLSD LLChatHistory::getValue() const diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 219bcf0eb0..7721e67290 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -62,6 +62,57 @@ #include "llviewerassetupload.h" #include "llcorehttputil.h" +namespace +{ + + const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue"); + + + class ObjectInventoryFetcher: public LLVOInventoryListener + { + public: + typedef boost::shared_ptr<ObjectInventoryFetcher> ptr_t; + + ObjectInventoryFetcher(LLEventPump &pump, LLViewerObject* object, void* user_data) : + mPump(pump), + LLVOInventoryListener() + { + registerVOInventoryListener(object, this); + } + + virtual void inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data); + + void fetchInventory() + { + requestVOInventory(); + } + + const LLInventoryObject::object_list_t & getInventoryList() const { return mInventoryList; } + + private: + LLInventoryObject::object_list_t mInventoryList; + LLEventPump & mPump; + }; + + class HandleScriptUserData + { + public: + HandleScriptUserData(const std::string &pumpname) : + mPumpname(pumpname) + { } + + const std::string &getPumpName() const { return mPumpname; } + + private: + std::string mPumpname; + }; + + +} + // *NOTE$: A minor specialization of LLScriptAssetUpload, it does not require a buffer // (and does not save a buffer to the vFS) and it finds the compile queue window and // displays a compiling message. @@ -149,47 +200,6 @@ BOOL LLFloaterScriptQueue::postBuild() return TRUE; } -// This is the callback method for the viewer object currently being -// worked on. -// NOT static, virtual! -void LLFloaterScriptQueue::inventoryChanged(LLViewerObject* viewer_object, - LLInventoryObject::object_list_t* inv, - S32, - void* q_id) -{ - LL_INFOS() << "LLFloaterScriptQueue::inventoryChanged() for object " - << viewer_object->getID() << LL_ENDL; - - //Remove this listener from the object since its - //listener callback is now being executed. - - //We remove the listener here because the function - //removeVOInventoryListener removes the listener from a ViewerObject - //which it internally stores. - - //If we call this further down in the function, calls to handleInventory - //and nextObject may update the internally stored viewer object causing - //the removal of the incorrect listener from an incorrect object. - - //Fixes SL-6119:Recompile scripts fails to complete - removeVOInventoryListener(); - - if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) ) - { - handleInventory(viewer_object, inv); - } - else - { - // something went wrong... - // note that we're not working on this one, and move onto the - // next object in the list. - LL_WARNS() << "No inventory for " << mCurrentObjectID - << LL_ENDL; - nextObject(); - } -} - - // static void LLFloaterScriptQueue::onCloseBtn(void* user_data) { @@ -197,9 +207,10 @@ void LLFloaterScriptQueue::onCloseBtn(void* user_data) self->closeFloater(); } -void LLFloaterScriptQueue::addObject(const LLUUID& id) +void LLFloaterScriptQueue::addObject(const LLUUID& id, std::string name) { - mObjectIDs.push_back(id); + ObjectData obj = { id, name }; + mObjectList.push_back(obj); } BOOL LLFloaterScriptQueue::start() @@ -208,7 +219,7 @@ BOOL LLFloaterScriptQueue::start() LLStringUtil::format_map_t args; args["[START]"] = mStartString; - args["[COUNT]"] = llformat ("%d", mObjectIDs.size()); + args["[COUNT]"] = llformat ("%d", mObjectList.size()); buffer = getString ("Starting", args); getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); @@ -216,74 +227,24 @@ BOOL LLFloaterScriptQueue::start() return startQueue(); } -BOOL LLFloaterScriptQueue::isDone() const +void LLFloaterScriptQueue::addProcessingMessage(const std::string &message, const LLSD &args) { - return (mCurrentObjectID.isNull() && (mObjectIDs.size() == 0)); -} + std::string buffer(LLTrans::getString(message, args)); -// go to the next object. If no objects left, it falls out silently -// and waits to be killed by the window being closed. -BOOL LLFloaterScriptQueue::nextObject() -{ - U32 count; - BOOL successful_start = FALSE; - do - { - count = mObjectIDs.size(); - LL_INFOS() << "LLFloaterScriptQueue::nextObject() - " << count - << " objects left to process." << LL_ENDL; - mCurrentObjectID.setNull(); - if(count > 0) - { - successful_start = popNext(); - } - LL_INFOS() << "LLFloaterScriptQueue::nextObject() " - << (successful_start ? "successful" : "unsuccessful") - << LL_ENDL; - } while((mObjectIDs.size() > 0) && !successful_start); - if(isDone() && !mDone) - { - mDone = true; - getChild<LLScrollListCtrl>("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM); - getChildView("close")->setEnabled(TRUE); - } - return successful_start; + getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); } -// returns true if the queue has started, otherwise false. This -// method pops the top object off of the queue. -BOOL LLFloaterScriptQueue::popNext() +void LLFloaterScriptQueue::addStringMessage(const std::string &message) { - // get the first element off of the container, and attempt to get - // the inventory. - BOOL rv = FALSE; - S32 count = mObjectIDs.size(); - if(mCurrentObjectID.isNull() && (count > 0)) - { - mCurrentObjectID = mObjectIDs.at(0); - LL_INFOS() << "LLFloaterScriptQueue::popNext() - mCurrentID: " - << mCurrentObjectID << LL_ENDL; - mObjectIDs.erase(mObjectIDs.begin()); - LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID); - if(obj) - { - LL_INFOS() << "LLFloaterScriptQueue::popNext() requesting inv for " - << mCurrentObjectID << LL_ENDL; - LLUUID* id = new LLUUID(getKey().asUUID()); - registerVOInventoryListener(obj,id); - requestVOInventory(); - rv = TRUE; - } - } - return rv; + getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM); } -BOOL LLFloaterScriptQueue::startQueue() + +BOOL LLFloaterScriptQueue::isDone() const { - return nextObject(); + return (mCurrentObjectID.isNull() && (mObjectList.size() == 0)); } - ///---------------------------------------------------------------------------- /// Class LLFloaterCompileQueue ///---------------------------------------------------------------------------- @@ -306,7 +267,7 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content ) { mExperienceIds.insert(it->asUUID()); } - nextObject(); +// nextObject(); } BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const @@ -314,188 +275,289 @@ BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const return mExperienceIds.find(id) != mExperienceIds.end(); } +// //Attempt to record this asset ID. If it can not be inserted into the set +// //then it has already been processed so return false. +// bool LLFloaterCompileQueue::checkAssetId(const LLUUID &assetId) +// { +// std::pair<uuid_list_t::iterator, bool> result = mAssetIds.insert(assetId); +// return result.second; +// } -void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, - LLInventoryObject::object_list_t* inv) +void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult) { - // find all of the lsl, leaving off duplicates. We'll remove - // all matching asset uuids on compilation success. + LLEventPumps::instance().post(pumpName, expresult); +} - typedef std::multimap<LLUUID, LLPointer<LLInventoryItem> > uuid_item_map; - uuid_item_map asset_item_map; +// *TODO: handleSCriptRetrieval is passed into the VFS via a legacy C function pointer +// future project would be to convert these to C++ callables (std::function<>) so that +// we can use bind and remove the userData parameter. +// +void LLFloaterCompileQueue::handleScriptRetrieval(LLVFS *vfs, const LLUUID& assetId, + LLAssetType::EType type, void* userData, S32 status, LLExtStat extStatus) +{ + LLSD result(LLSD::emptyMap()); - LLInventoryObject::object_list_t::const_iterator it = inv->begin(); - LLInventoryObject::object_list_t::const_iterator end = inv->end(); - for ( ; it != end; ++it) - { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) - { - LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); - // Check permissions before allowing the user to retrieve data. - if (item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) && - item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()) ) - { - LLPointer<LLViewerInventoryItem> script = new LLViewerInventoryItem(item); - mCurrentScripts.push_back(script); - asset_item_map.insert(std::make_pair(item->getAssetUUID(), item)); - } - } - } + result["asset_id"] = assetId; + if (status) + { + result["error"] = status; + + if (status == LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE) + { + result["message"] = LLTrans::getString("CompileQueueProblemDownloading") + (":"); + result["alert"] = LLTrans::getString("CompileQueueScriptNotFound"); + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + result["message"] = LLTrans::getString("CompileQueueInsufficientPermFor") + (":"); + result["alert"] = LLTrans::getString("CompileQueueInsufficientPermDownload"); + } + else + { + result["message"] = LLTrans::getString("CompileQueueUnknownFailure"); + } + } - if (asset_item_map.empty()) - { - // There are no scripts in this object. move on. - nextObject(); - } - else - { - // request all of the assets. - uuid_item_map::iterator iter; - for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++) - { - LLInventoryItem *itemp = iter->second; - LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(), - viewer_object->getID(), itemp); - - LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), - boost::bind(&LLFloaterCompileQueue::requestAsset, datap, _1)); - } - } -} + LLEventPumps::instance().post(((HandleScriptUserData *)userData)->getPumpName(), result); +} -void LLFloaterCompileQueue::requestAsset( LLScriptQueueData* datap, const LLSD& experience ) +/*static*/ +void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent) { - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", datap->mQueueID); - if(!queue) - { - delete datap; - return; - } - if(experience.has(LLExperienceCache::EXPERIENCE_ID)) - { - datap->mExperienceId=experience[LLExperienceCache::EXPERIENCE_ID].asUUID(); - if(!queue->hasExperience(datap->mExperienceId)) - { - std::string buffer = LLTrans::getString("CompileNoExperiencePerm", LLSD::emptyMap() - .with("SCRIPT", datap->mItem->getName()) - .with("EXPERIENCE", experience[LLExperienceCache::NAME].asString())); - - queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); - queue->removeItemByItemID(datap->mItem->getUUID()); - delete datap; - return; - } - } - //LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL; - gAssetStorage->getInvItemAsset(datap->mHost, - gAgent.getID(), - gAgent.getSessionID(), - datap->mItem->getPermissions().getOwner(), - datap->mTaskId, - datap->mItem->getUUID(), - datap->mItem->getAssetUUID(), - datap->mItem->getType(), - LLFloaterCompileQueue::scriptArrived, - (void*)datap); + LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", parent); + if (!queue) + return; + + queue->experienceIdsReceived(result["experience_ids"]); + + LLHandle<LLFloaterScriptQueue> hFloater(queue->getDerivedHandle<LLFloaterScriptQueue>()); + + fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript, + queue->getDerivedHandle<LLFloaterCompileQueue>(), _1, _2, _3); + + + LLCoros::instance().launch("ScriptQueueCompile", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + queue->mStartString, + hFloater, + queue->mObjectList, + fn)); + } -/*static*/ -void LLFloaterCompileQueue::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId) +bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater, + const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { + LLSD result; + LLFloaterCompileQueue *that = hfloater.get(); + bool monocompile = that->mMono; + F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout"); + + if (!that) + return false; - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(queueId)); - if (queue) + // Initial test to see if we can (or should) attempt to compile the script. + LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory); { - // Bytecode save completed - if (response["compiled"]) + + if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) || + !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID())) { - std::string message = std::string("Compilation of \"") + scriptName + std::string("\" succeeded"); + std::string buffer = "Skipping: " + item->getName() + "(Permissions)"; + that->addStringMessage(buffer); + return true; + } - queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM); - LL_INFOS() << message << LL_ENDL; +// if (!that->checkAssetId(item->getAssetUUID())) +// { +// std::string buffer = "Skipping: " + item->getName() + "(Repeat)"; +// that->addStringMessage(buffer); +// return true; +// } + } + that = NULL; + + // Attempt to retrieve the experience + LLUUID experienceId; + { + LLExperienceCache::instance().fetchAssociatedExperience(inventory->getParentUUID(), inventory->getUUID(), + boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1)); + + result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, + LLSD().with("timeout", LLSD::Boolean(true))); + + that = hfloater.get(); + if (!that) + { + return false; } - else + + if (result.has("timeout") && result["timeout"].asBoolean()) { - LLSD compile_errors = response["errors"]; - for (LLSD::array_const_iterator line = compile_errors.beginArray(); - line < compile_errors.endArray(); line++) - { - std::string str = line->asString(); - str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = that->getString("Timeout", args); + that->addStringMessage(buffer); + return true; + } - queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(str, ADD_BOTTOM); + if (result.has(LLExperienceCache::EXPERIENCE_ID)) + { + experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID(); + if (!that->hasExperience(experienceId)) + { + that->addProcessingMessage("CompileNoExperiencePerm", LLSD() + .with("SCRIPT", inventory->getName()) + .with("EXPERIENCE", result[LLExperienceCache::NAME].asString())); + return true; } - LL_INFOS() << response["errors"] << LL_ENDL; } } + that = NULL; + + { + HandleScriptUserData userData(pump.getName()); + + + // request the asset + gAssetStorage->getInvItemAsset(LLHost(), + gAgent.getID(), + gAgent.getSessionID(), + item->getPermissions().getOwner(), + object->getID(), + item->getUUID(), + item->getAssetUUID(), + item->getType(), + &LLFloaterCompileQueue::handleScriptRetrieval, + &userData); + + result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, + LLSD().with("timeout", LLSD::Boolean(true))); + } + + that = hfloater.get(); + if (!that) + { + return false; + } + + if (result.has("timeout")) + { + if (result.has("timeout") && result["timeout"].asBoolean()) + { + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = that->getString("Timeout", args); + that->addStringMessage(buffer); + return true; + } + } + + if (result.has("error")) + { + LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL; + std::string buffer = result["message"].asString() + " " + inventory->getName(); + that->addStringMessage(buffer); + + if (result.has("alert")) + { + LLSD args; + args["MESSAGE"] = result["alert"].asString(); + LLNotificationsUtil::add("SystemMessage", args); + } + return true; + } + + LLUUID assetId = result["asset_id"]; + that = NULL; + + + std::string url = object->getRegion()->getCapability("UpdateScriptTask"); + + + { + LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(), + inventory->getUUID(), + assetId, + monocompile ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, + true, + inventory->getName(), + LLUUID(), + experienceId, + boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _4))); + + LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); + } + + result = llcoro::suspendUntilEventOnWithTimeout(pump, fetch_timeout, LLSD().with("timeout", LLSD::Boolean(true))); + + that = hfloater.get(); + if (!that) + { + return false; + } + + if (result.has("timeout")) + { + if (result.has("timeout") && result["timeout"].asBoolean()) + { + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = that->getString("Timeout", args); + that->addStringMessage(buffer); + return true; + } + } + + // Bytecode save completed + if (result["compiled"]) + { + std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded"); + + that->addStringMessage(buffer); + LL_INFOS() << buffer << LL_ENDL; + } + else + { + LLSD compile_errors = result["errors"]; + std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:"); + that->addStringMessage(buffer); + for (LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); line++) + { + std::string str = line->asString(); + str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); + + that->addStringMessage(str); + } + LL_INFOS() << result["errors"] << LL_ENDL; + } + + return true; } -// This is the callback for when each script arrives -// static -void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) +bool LLFloaterCompileQueue::startQueue() { - LL_INFOS() << "LLFloaterCompileQueue::scriptArrived()" << LL_ENDL; - LLScriptQueueData* data = (LLScriptQueueData*)user_data; - if(!data) - { - return; - } - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", data->mQueueID); - - std::string buffer; - if(queue && (0 == status)) - { - LLViewerObject* object = gObjectList.findObject(data->mTaskId); - if (object) + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string lookup_url = region->getCapability("GetCreatorExperiences"); + if (!lookup_url.empty()) { - std::string url = object->getRegion()->getCapability("UpdateScriptTask"); - std::string scriptName = data->mItem->getName(); - - LLBufferedAssetUploadInfo::taskUploadFinish_f proc = boost::bind(&LLFloaterCompileQueue::finishLSLUpload, _1, _2, _3, _4, - scriptName, data->mQueueID); + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success = + boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID()); - LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(data->mTaskId, data->mItem->getUUID(), asset_id, - (queue->mMono) ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, - true, scriptName, data->mQueueID, data->mExperienceId, proc)); + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure = + boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID()); - LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, + success, failure); + return TRUE; } - } - else - { - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) - { - LLSD args; - args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound"); - LLNotificationsUtil::add("SystemMessage", args); - - buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mItem->getName(); - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - LLSD args; - args["MESSAGE"] = LLTrans::getString("CompileQueueInsufficientPermDownload"); - LLNotificationsUtil::add("SystemMessage", args); - - buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mItem->getName(); - } - else - { - buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mItem->getName(); - } - - LL_WARNS() << "Problem downloading script asset." << LL_ENDL; - if(queue) queue->removeItemByItemID(data->mItem->getUUID()); - } - if(queue && (buffer.size() > 0)) - { - queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); - } - delete data; + } + + return true; } @@ -514,40 +576,42 @@ LLFloaterResetQueue::~LLFloaterResetQueue() { } -void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv) +bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, + const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) +{ + LLFloaterScriptQueue *that = hfloater.get(); + if (that) + { + std::string buffer; + buffer = that->getString("Resetting") + (": ") + inventory->getName(); + that->addStringMessage(buffer); + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ScriptReset); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); + msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); + msg->sendReliable(object->getRegion()->getHost()); + + return true; +} + +bool LLFloaterResetQueue::startQueue() { - // find all of the lsl, leaving off duplicates. We'll remove - // all matching asset uuids on compilation success. + fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts, + getDerivedHandle<LLFloaterScriptQueue>(), _1, _2, _3); - LLInventoryObject::object_list_t::const_iterator it = inv->begin(); - LLInventoryObject::object_list_t::const_iterator end = inv->end(); - for ( ; it != end; ++it) - { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) - { - LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); - - if (object) - { - LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); - std::string buffer; - buffer = getString("Resetting") + (": ") + item->getName(); - getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ScriptReset); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, viewer_obj->getID()); - msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID()); - msg->sendReliable(object->getRegion()->getHost()); - } - } - } + LLCoros::instance().launch("ScriptResetQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + mStartString, + getDerivedHandle<LLFloaterScriptQueue>(), + mObjectList, + fn)); - nextObject(); + return true; } ///---------------------------------------------------------------------------- @@ -565,44 +629,46 @@ LLFloaterRunQueue::~LLFloaterRunQueue() { } -void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv) +bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, + const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { - // find all of the lsl, leaving off duplicates. We'll remove - // all matching asset uuids on compilation success. - LLInventoryObject::object_list_t::const_iterator it = inv->begin(); - LLInventoryObject::object_list_t::const_iterator end = inv->end(); - for ( ; it != end; ++it) - { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) - { - LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); - - if (object) - { - LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); - LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output"); - std::string buffer; - buffer = getString("Running") + (": ") + item->getName(); - list->addSimpleElement(buffer, ADD_BOTTOM); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetScriptRunning); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, viewer_obj->getID()); - msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID()); - msg->addBOOLFast(_PREHASH_Running, TRUE); - msg->sendReliable(object->getRegion()->getHost()); - } - } - } + LLFloaterScriptQueue *that = hfloater.get(); + if (that) + { + std::string buffer; + buffer = that->getString("Running") + (": ") + inventory->getName(); + that->addStringMessage(buffer); + } - nextObject(); + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetScriptRunning); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); + msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); + msg->addBOOLFast(_PREHASH_Running, TRUE); + msg->sendReliable(object->getRegion()->getHost()); + + return true; } +bool LLFloaterRunQueue::startQueue() +{ + LLHandle<LLFloaterScriptQueue> hFloater(getDerivedHandle<LLFloaterScriptQueue>()); + fnQueueAction_t fn = boost::bind(LLFloaterRunQueue::runObjectScripts, hFloater, _1, _2, _3); + + LLCoros::instance().launch("ScriptRunQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + mStartString, + hFloater, + mObjectList, + fn)); + + return true; +} + + ///---------------------------------------------------------------------------- /// Class LLFloaterNotRunQueue ///---------------------------------------------------------------------------- @@ -618,96 +684,171 @@ LLFloaterNotRunQueue::~LLFloaterNotRunQueue() { } -void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id) +bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, + const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump) { - LL_INFOS() << "LLFloaterCompileQueue::removeItemByAssetID()" << LL_ENDL; - for(S32 i = 0; i < mCurrentScripts.size(); ) - { - if(asset_id == mCurrentScripts.at(i)->getUUID()) - { - vector_replace_with_last(mCurrentScripts, mCurrentScripts.begin() + i); - } - else - { - ++i; - } - } - if(mCurrentScripts.empty()) - { - nextObject(); - } + LLFloaterScriptQueue *that = hfloater.get(); + if (that) + { + std::string buffer; + buffer = that->getString("NotRunning") + (": ") + inventory->getName(); + that->addStringMessage(buffer); + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetScriptRunning); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); + msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); + msg->addBOOLFast(_PREHASH_Running, FALSE); + msg->sendReliable(object->getRegion()->getHost()); + + return true; } -BOOL LLFloaterCompileQueue::startQueue() +bool LLFloaterNotRunQueue::startQueue() { - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - std::string lookup_url=region->getCapability("GetCreatorExperiences"); - if(!lookup_url.empty()) - { - LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success = - boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID()); + LLHandle<LLFloaterScriptQueue> hFloater(getDerivedHandle<LLFloaterScriptQueue>()); - LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure = - boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID()); + fnQueueAction_t fn = boost::bind(&LLFloaterNotRunQueue::stopObjectScripts, hFloater, _1, _2, _3); + LLCoros::instance().launch("ScriptQueueNotRun", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + mStartString, + hFloater, + mObjectList, + fn)); - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, - success, failure); - return TRUE; - } - } - return nextObject(); + return true; } -/*static*/ -void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent) +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- +void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data) { - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", parent); - if (!queue) - return; + mInventoryList.clear(); + mInventoryList.assign(inventory->begin(), inventory->end()); + + mPump.post(LLSD().with("changed", LLSD::Boolean(true))); - queue->experienceIdsReceived(result["experience_ids"]); } -void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv) +void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, LLHandle<LLFloaterScriptQueue> hfloater, + object_data_list_t objectList, fnQueueAction_t func) { - // find all of the lsl, leaving off duplicates. We'll remove - // all matching asset uuids on compilation success. - LLInventoryObject::object_list_t::const_iterator it = inv->begin(); - LLInventoryObject::object_list_t::const_iterator end = inv->end(); - for ( ; it != end; ++it) - { - if((*it)->getType() == LLAssetType::AT_LSL_TEXT) - { - LLViewerObject* object = gObjectList.findObject(viewer_obj->getID()); - - if (object) - { - LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); - LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output"); - std::string buffer; - buffer = getString("NotRunning") + (": ") +item->getName(); - list->addSimpleElement(buffer, ADD_BOTTOM); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetScriptRunning); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, viewer_obj->getID()); - msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID()); - msg->addBOOLFast(_PREHASH_Running, FALSE); - msg->sendReliable(object->getRegion()->getHost()); - } - } - } + LLCoros::set_consuming(true); + LLFloaterScriptQueue * floater(NULL); + LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true); + F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout"); + +// floater = hfloater.get(); +// floater->addProcessingMessage("Starting", +// LLSD() +// .with("[START]", action) +// .with("[COUNT]", LLSD::Integer(objectList.size()))); +// floater = NULL; + + for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj) + { + bool firstForObject = true; + LLUUID object_id = (*itObj).mObjectId; + LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL; - nextObject(); -} + LLPointer<LLViewerObject> obj = gObjectList.findObject(object_id); + LLInventoryObject::object_list_t inventory; + if (obj) + { + ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL)); -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- + fetcher->fetchInventory(); + + floater = hfloater.get(); + if (floater) + { + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = (*itObj).mObjectName; + floater->addStringMessage(floater->getString("LoadingObjInv", args)); + } + + LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout, + LLSD().with("timeout", LLSD::Boolean(true))); + + if (result.has("timeout") && result["timeout"].asBoolean()) + { + LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() << + ". Skipping to next object." << LL_ENDL; + + // floater could have been closed + floater = hfloater.get(); + if (floater) + { + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = (*itObj).mObjectName; + floater->addStringMessage(floater->getString("Timeout", args)); + } + + continue; + } + + inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end()); + } + else + { + LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id << + ". Skipping to next." << LL_ENDL; + continue; + } + + // TODO: Get the name of the object we are looking at here so that we can display it below. + //std::string objName = (dynamic_cast<LLInventoryObject *>(obj.get()))->getName(); + LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL; + + for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin(); + itInv != inventory.end(); ++itInv) + { + floater = hfloater.get(); + if (!floater) + { + LL_WARNS("SCRIPTQ") << "Script Queue floater closed! Canceling remaining ops" << LL_ENDL; + break; + } + + // note, we have a smart pointer to the obj above... but if we didn't we'd check that + // it still exists here. + + if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT)) + { + LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL; + if (firstForObject) + { + //floater->addStringMessage(objName + ":"); + firstForObject = false; + } + + if (!func(obj, (*itInv), maildrop)) + { + continue; + } + } + + llcoro::suspend(); + } + // Just test to be sure the floater is still present before calling the func + if (!hfloater.get()) + { + LL_WARNS("SCRIPTQ") << "Script Queue floater dismissed." << LL_ENDL; + break; + } + + } + + floater = hfloater.get(); + if (floater) + { + floater->addStringMessage("Done"); + floater->getChildView("close")->setEnabled(TRUE); + } +} diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h index 46bcb9746b..1b3d8f83a0 100644 --- a/indra/newview/llcompilequeue.h +++ b/indra/newview/llcompilequeue.h @@ -37,6 +37,8 @@ #include "llviewerinventory.h" +#include "llevents.h" + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFloaterScriptQueue // @@ -48,7 +50,7 @@ // scripts manipulated. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFloaterScriptQueue : public LLFloater, public LLVOInventoryListener +class LLFloaterScriptQueue : public LLFloater/*, public LLVOInventoryListener*/ { public: LLFloaterScriptQueue(const LLSD& key); @@ -59,34 +61,23 @@ public: void setMono(bool mono) { mMono = mono; } // addObject() accepts an object id. - void addObject(const LLUUID& id); + void addObject(const LLUUID& id, std::string name); // start() returns TRUE if the queue has started, otherwise FALSE. BOOL start(); -protected: - // This is the callback method for the viewer object currently - // being worked on. - /*virtual*/ void inventoryChanged(LLViewerObject* obj, - LLInventoryObject::object_list_t* inv, - S32 serial_num, - void* queue); - - // This is called by inventoryChanged - virtual void handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv) = 0; + void addProcessingMessage(const std::string &message, const LLSD &args); + void addStringMessage(const std::string &message); + std::string getStartString() const { return mStartString; } + +protected: static void onCloseBtn(void* user_data); // returns true if this is done BOOL isDone() const; - virtual BOOL startQueue(); - - // go to the next object. If no objects left, it falls out - // silently and waits to be killed by the deleteIfDone() callback. - BOOL nextObject(); - BOOL popNext(); + virtual bool startQueue() = 0; void setStartString(const std::string& s) { mStartString = s; } @@ -96,12 +87,23 @@ protected: LLButton* mCloseBtn; // Object Queue - std::vector<LLUUID> mObjectIDs; + struct ObjectData + { + LLUUID mObjectId; + std::string mObjectName; + }; + typedef std::vector<ObjectData> object_data_list_t; + + object_data_list_t mObjectList; LLUUID mCurrentObjectID; bool mDone; std::string mStartString; bool mMono; + + typedef boost::function<bool(const LLPointer<LLViewerObject> &, LLInventoryObject*, LLEventPump &)> fnQueueAction_t; + static void objectScriptProcessingQueueCoro(std::string action, LLHandle<LLFloaterScriptQueue> hfloater, object_data_list_t objectList, fnQueueAction_t func); + }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -122,8 +124,6 @@ class LLFloaterCompileQueue : public LLFloaterScriptQueue { friend class LLFloaterReg; public: - // remove any object in mScriptScripts with the matching uuid. - void removeItemByItemID(const LLUUID& item_id); void experienceIdsReceived( const LLSD& content ); BOOL hasExperience(const LLUUID& id)const; @@ -132,27 +132,17 @@ protected: LLFloaterCompileQueue(const LLSD& key); virtual ~LLFloaterCompileQueue(); - // This is called by inventoryChanged - virtual void handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv); - - static void requestAsset(struct LLScriptQueueData* datap, const LLSD& experience); + virtual bool startQueue(); + static bool processScript(LLHandle<LLFloaterCompileQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump); - static void finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId); - - // This is the callback for when each script arrives - static void scriptArrived(LLVFS *vfs, const LLUUID& asset_id, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status); - - virtual BOOL startQueue(); -protected: - LLViewerInventoryItem::item_array_t mCurrentScripts; + //bool checkAssetId(const LLUUID &assetId); + static void handleHTTPResponse(std::string pumpName, const LLSD &expresult); + static void handleScriptRetrieval(LLVFS *vfs, const LLUUID& assetId, LLAssetType::EType type, void* userData, S32 status, LLExtStat extStatus); private: static void processExperienceIdResults(LLSD result, LLUUID parent); - + //uuid_list_t mAssetIds; // list of asset IDs processed. uuid_list_t mExperienceIds; }; @@ -169,9 +159,9 @@ protected: LLFloaterResetQueue(const LLSD& key); virtual ~LLFloaterResetQueue(); - // This is called by inventoryChanged - virtual void handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv); + static bool resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump); + + virtual bool startQueue(); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -186,10 +176,10 @@ class LLFloaterRunQueue : public LLFloaterScriptQueue protected: LLFloaterRunQueue(const LLSD& key); virtual ~LLFloaterRunQueue(); - - // This is called by inventoryChanged - virtual void handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv); + + static bool runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump); + + virtual bool startQueue(); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -205,9 +195,9 @@ protected: LLFloaterNotRunQueue(const LLSD& key); virtual ~LLFloaterNotRunQueue(); - // This is called by inventoryChanged - virtual void handleInventory(LLViewerObject* viewer_obj, - LLInventoryObject::object_list_t* inv); + static bool stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater, const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump); + + virtual bool startQueue(); }; #endif // LL_LLCOMPILEQUEUE_H diff --git a/indra/newview/llconversationlog.cpp b/indra/newview/llconversationlog.cpp index 05c7e6caa5..4e69896b69 100644 --- a/indra/newview/llconversationlog.cpp +++ b/indra/newview/llconversationlog.cpp @@ -448,7 +448,12 @@ bool LLConversationLog::moveLog(const std::string &originDirectory, const std::s std::string LLConversationLog::getFileName() { std::string filename = "conversation"; - return gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename) + ".log"; + std::string log_address = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); + if (!log_address.empty()) + { + log_address += ".log"; + } + return log_address; } bool LLConversationLog::saveToFile(const std::string& filename) diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 33675bd261..b716a76543 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -62,28 +62,15 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : LLFacePool(POOL_TERRAIN), mTexturep(texturep) { - U32 format = GL_ALPHA8; - U32 int_format = GL_ALPHA; - // Hack! sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale"); sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); - mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", - FTT_LOCAL_FILE, - TRUE, LLGLTexture::BOOST_UI, - LLViewerTexture::FETCHED_TEXTURE, - format, int_format, - LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); + mAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD); //gGL.getTexUnit(0)->bind(mAlphaRampImagep.get()); mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); - m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", - FTT_LOCAL_FILE, - TRUE, LLGLTexture::BOOST_UI, - LLViewerTexture::FETCHED_TEXTURE, - format, int_format, - LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); + m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTexture(IMG_ALPHA_GRAD_2D); //gGL.getTexUnit(0)->bind(m2DAlphaRampImagep.get()); m2DAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 7178042b32..cc77b407ae 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -40,12 +40,14 @@ #include "llcorehttputil.h" #include "lleventfilter.h" +#include "boost/make_shared.hpp" + namespace LLEventPolling { namespace Details { - class LLEventPollImpl + class LLEventPollImpl: public boost::enable_shared_from_this<LLEventPollImpl> { public: LLEventPollImpl(const LLHost &sender); @@ -113,7 +115,7 @@ namespace Details { std::string coroname = LLCoros::instance().launch("LLEventPollImpl::eventPollCoro", - boost::bind(&LLEventPollImpl::eventPollCoro, this, url)); + boost::bind(&LLEventPollImpl::eventPollCoro, this->shared_from_this(), url)); LL_INFOS("LLEventPollImpl") << coroname << " with url '" << url << LL_ENDL; } } @@ -273,8 +275,7 @@ namespace Details LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender): mImpl() { - mImpl = boost::unique_ptr<LLEventPolling::Details::LLEventPollImpl> - (new LLEventPolling::Details::LLEventPollImpl(sender)); + mImpl = boost::make_shared<LLEventPolling::Details::LLEventPollImpl>(sender); mImpl->start(poll_url); } diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h index e2afd9226b..65766dbb2a 100644 --- a/indra/newview/lleventpoll.h +++ b/indra/newview/lleventpoll.h @@ -27,12 +27,6 @@ #ifndef LL_LLEVENTPOLL_H #define LL_LLEVENTPOLL_H -#include "boost/move/unique_ptr.hpp" - -namespace boost -{ - using ::boost::movelib::unique_ptr; // move unique_ptr into the boost namespace. -} class LLHost; @@ -57,7 +51,7 @@ public: private: - boost::unique_ptr<LLEventPolling::Details::LLEventPollImpl> mImpl; + boost::shared_ptr<LLEventPolling::Details::LLEventPollImpl> mImpl; }; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 7f1c981a3c..d4ba230feb 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -809,3 +809,62 @@ void LLFeatureManager::applyBaseMasks() maskFeatures("safe"); } } + +LLSD LLFeatureManager::getRecommendedSettingsMap() +{ + // Create the map and fill it with the hardware recommended settings. + // It's needed to create an initial Default graphics preset (MAINT-6435). + // The process is similar to the one LLFeatureManager::applyRecommendedSettings() does. + + LLSD map(LLSD::emptyMap()); + + loadGPUClass(); + U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); + LL_INFOS("RenderInit") << "Getting the map of recommended settings for level " << level << LL_ENDL; + + applyBaseMasks(); + std::string features(isValidGraphicsLevel(level) ? getNameForGraphicsLevel(level) : "Low"); + + maskFeatures(features); + + LLControlVariable* ctrl = gSavedSettings.getControl("RenderQualityPerformance"); // include the quality value for correct preset loading + map["RenderQualityPerformance"]["Value"] = (LLSD::Integer)level; + map["RenderQualityPerformance"]["Comment"] = ctrl->getComment();; + map["RenderQualityPerformance"]["Persist"] = 1; + map["RenderQualityPerformance"]["Type"] = LLControlGroup::typeEnumToString(ctrl->type()); + + + + for (feature_map_t::iterator mIt = mFeatures.begin(); mIt != mFeatures.end(); ++mIt) + { + LLControlVariable* ctrl = gSavedSettings.getControl(mIt->first); + if (ctrl == NULL) + { + LL_WARNS() << "AHHH! Control setting " << mIt->first << " does not exist!" << LL_ENDL; + continue; + } + + if (ctrl->isType(TYPE_BOOLEAN)) + { + map[mIt->first]["Value"] = (LLSD::Boolean)getRecommendedValue(mIt->first); + } + else if (ctrl->isType(TYPE_S32) || ctrl->isType(TYPE_U32)) + { + map[mIt->first]["Value"] = (LLSD::Integer)getRecommendedValue(mIt->first); + } + else if (ctrl->isType(TYPE_F32)) + { + map[mIt->first]["Value"] = (LLSD::Real)getRecommendedValue(mIt->first); + } + else + { + LL_WARNS() << "AHHH! Control variable is not a numeric type!" << LL_ENDL; + continue; + } + map[mIt->first]["Comment"] = ctrl->getComment();; + map[mIt->first]["Persist"] = 1; + map[mIt->first]["Type"] = LLControlGroup::typeEnumToString(ctrl->type()); + } + + return map; +} diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 12ea691b49..c3d87cea0b 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -157,7 +157,9 @@ public: // load the dynamic GPU/feature table from a website void fetchHTTPTables(); - + + LLSD getRecommendedSettingsMap(); + protected: bool loadGPUClass(); diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 7da65a9a7c..d842106146 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -528,7 +528,8 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command) LLInventoryItem* item = gInventory.getItem(*it); if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE) { - LLClipboard::instance().addToClipboard(item->getUUID(),LLAssetType::AT_GESTURE); + LLWString item_name = utf8str_to_wstring(item->getName()); + LLClipboard::instance().addToClipboard(item_name, 0, item_name.size()); } } } diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 7a989806a1..257b39a7dd 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -798,7 +798,8 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* } else if (mesg[0] == '/' && mesg[1] - && LLStringOps::isDigit(mesg[1])) + && (LLStringOps::isDigit(mesg[1]) + || (mesg[1] == '-' && mesg[2] && LLStringOps::isDigit(mesg[2])))) { // This a special "/20" speak on a channel S32 pos = 0; @@ -812,7 +813,7 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel_string.push_back(c); pos++; } - while(c && pos < 64 && LLStringOps::isDigit(c)); + while(c && pos < 64 && (LLStringOps::isDigit(c) || (pos==1 && c =='-'))); // Move the pointer forward to the first non-whitespace char // Check isspace before looping, so we can handle "/33foo" @@ -837,19 +838,36 @@ LLWString LLFloaterIMNearbyChat::stripChannelNumber(const LLWString &mesg, S32* void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ChatFromViewer); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ChatData); - msg->addStringFast(_PREHASH_Message, utf8_out_text); - msg->addU8Fast(_PREHASH_Type, type); - msg->addS32("Channel", channel); - - gAgent.sendReliableMessage(); - - add(LLStatViewer::CHAT_COUNT, 1); + LLMessageSystem* msg = gMessageSystem; + + if (channel >= 0) + { + msg->newMessageFast(_PREHASH_ChatFromViewer); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_ChatData); + msg->addStringFast(_PREHASH_Message, utf8_out_text); + msg->addU8Fast(_PREHASH_Type, type); + msg->addS32("Channel", channel); + + } + else + { + // Hack: ChatFromViewer doesn't allow negative channels + msg->newMessage("ScriptDialogReply"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgentID); + msg->addUUID("SessionID", gAgentSessionID); + msg->nextBlock("Data"); + msg->addUUID("ObjectID", gAgentID); + msg->addS32("ChatChannel", channel); + msg->addS32("ButtonIndex", 0); + msg->addString("ButtonLabel", utf8_out_text); + } + + gAgent.sendReliableMessage(); + add(LLStatViewer::CHAT_COUNT, 1); } class LLChatCommandHandler : public LLCommandHandler diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 1f85c5ac1b..9fd731ed56 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -601,12 +601,31 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, toast_msg = chat_msg.mText; } + bool chat_overlaps = false; + if(nearby_chat->getChatHistory()) + { + LLRect chat_rect = nearby_chat->getChatHistory()->calcScreenRect(); + for (std::list<LLView*>::const_iterator child_iter = gFloaterView->getChildList()->begin(); + child_iter != gFloaterView->getChildList()->end(); ++child_iter) + { + LLView *view = *child_iter; + const LLRect& rect = view->getRect(); + if(view->isInVisibleChain() && (rect.overlaps(chat_rect))) + { + if(!nearby_chat->getChatHistory()->hasAncestor(view)) + { + chat_overlaps = true; + } + break; + } + } + } //Don't show nearby toast, if conversation is visible and selected if ((nearby_chat->hasFocus()) || (LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()) || - ((im_box->getSelectedSession().isNull() && - ((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost()) - || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost()))))) + ((im_box->getSelectedSession().isNull() && !chat_overlaps && + ((LLFloater::isVisible(im_box) && !nearby_chat->isTornOff() && !im_box->isMinimized()) + || (LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()))))) { if(nearby_chat->isMessagePaneExpanded()) { diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 357b635594..2cd94c592a 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -1094,6 +1094,12 @@ void LLFloaterIMSessionTab::saveCollapsedState() gSavedPerAccountSettings.setBOOL("NearbyChatIsNotCollapsed", isMessagePaneExpanded()); } } + +LLView* LLFloaterIMSessionTab::getChatHistory() +{ + return mChatHistory; +} + BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) { BOOL handled = FALSE; diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e7b05a584b..1b4922fd73 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -103,6 +103,8 @@ public: void restoreFloater(); void saveCollapsedState(); + LLView* getChatHistory(); + protected: // callback for click on any items of the visual states menu diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 135bbb335e..4a5732aecf 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -42,6 +42,8 @@ #include "llfloaterperms.h" #include "llviewercontrol.h" #include "llviewermenufile.h" // upload_new_resource() +#include "llstatusbar.h" // can_afford_transaction() +#include "llnotificationsutil.h" #include "lluictrlfactory.h" #include "llstring.h" #include "lleconomy.h" @@ -161,12 +163,15 @@ void LLFloaterNameDesc::onBtnOK( ) LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). - void *nruserdata = NULL; - std::string display_name = LLStringUtil::null; - LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo( + if (can_afford_transaction(expected_upload_cost)) + { + void *nruserdata = NULL; + std::string display_name = LLStringUtil::null; + + LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo( mFilenameAndPath, - getChild<LLUICtrl>("name_form")->getValue().asString(), + getChild<LLUICtrl>("name_form")->getValue().asString(), getChild<LLUICtrl>("description_form")->getValue().asString(), 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, LLFloaterPerms::getNextOwnerPerms("Uploads"), @@ -174,7 +179,14 @@ void LLFloaterNameDesc::onBtnOK( ) LLFloaterPerms::getEveryonePerms("Uploads"), expected_upload_cost)); - upload_new_resource(uploadInfo, callback, nruserdata); + upload_new_resource(uploadInfo, callback, nruserdata); + } + else + { + LLSD args; + args["COST"] = llformat("%d", expected_upload_cost); + LLNotificationsUtil::add("ErrorTextureCannotAfford", args); + } closeFloater(false); } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 36bdcf4d89..20d8119606 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1411,7 +1411,7 @@ void LLAvatarComplexityControls::setIndirectMaxArc() else { // This is the inverse of the calculation in updateMaxComplexity - indirect_max_arc = (U32)((log(max_arc) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE) + MIN_INDIRECT_ARC_LIMIT; + indirect_max_arc = (U32)ll_round(((log(F32(max_arc)) - MIN_ARC_LOG) / ARC_LIMIT_MAP_SCALE)) + MIN_INDIRECT_ARC_LIMIT; } gSavedSettings.setU32("IndirectMaxComplexity", indirect_max_arc); } @@ -1930,7 +1930,7 @@ void LLAvatarComplexityControls::updateMax(LLSliderCtrl* slider, LLTextBox* valu { // if this is changed, the inverse calculation in setIndirectMaxArc // must be changed to match - max_arc = (U32)exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT))); + max_arc = (U32)ll_round(exp(MIN_ARC_LOG + (ARC_LIMIT_MAP_SCALE * (indirect_value - MIN_INDIRECT_ARC_LIMIT)))); } gSavedSettings.setU32("RenderAvatarMaxComplexity", (U32)max_arc); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4eacd728c3..843dbbf25e 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -412,6 +412,11 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->getChild<LLUICtrl>("object_bonus_spin")->setValue(LLSD(object_bonus_factor) ); panel->getChild<LLUICtrl>("access_combo")->setValue(LLSD(sim_access) ); + LLPanelRegionGeneralInfo* panel_general = LLFloaterRegionInfo::getPanelGeneral(); + if (panel) + { + panel_general->setObjBonusFactor(object_bonus_factor); + } // detect teen grid for maturity @@ -465,6 +470,16 @@ LLPanelEstateCovenant* LLFloaterRegionInfo::getPanelCovenant() } // static +LLPanelRegionGeneralInfo* LLFloaterRegionInfo::getPanelGeneral() +{ + LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); + if (!floater) return NULL; + LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels"); + LLPanelRegionGeneralInfo* panel = (LLPanelRegionGeneralInfo*)tab->getChild<LLPanel>("General"); + return panel; +} + +// static LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain() { LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info"); @@ -717,7 +732,42 @@ BOOL LLPanelRegionGeneralInfo::postBuild() childSetAction("im_btn", onClickMessage, this); // childSetAction("manage_telehub_btn", onClickManageTelehub, this); - return LLPanelRegionInfo::postBuild(); + LLUICtrl* apply_btn = findChild<LLUICtrl>("apply_btn"); + if (apply_btn) + { + apply_btn->setCommitCallback(boost::bind(&LLPanelRegionGeneralInfo::onBtnSet, this)); + } + + refresh(); + return TRUE; +} + +void LLPanelRegionGeneralInfo::onBtnSet() +{ + if(mObjBonusFactor == getChild<LLUICtrl>("object_bonus_spin")->getValue().asReal()) + { + if (sendUpdate()) + { + disableButton("apply_btn"); + } + } + else + { + LLNotificationsUtil::add("ChangeObjectBonusFactor", LLSD(), LLSD(), boost::bind(&LLPanelRegionGeneralInfo::onChangeObjectBonus, this, _1, _2)); + } +} + +bool LLPanelRegionGeneralInfo::onChangeObjectBonus(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + if (sendUpdate()) + { + disableButton("apply_btn"); + } + } + return false; } void LLPanelRegionGeneralInfo::onClickKick() diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index 46f2b42137..dbb0ad05e9 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -95,6 +95,7 @@ public: static LLPanelEstateCovenant* getPanelCovenant(); static LLPanelRegionTerrainInfo* getPanelRegionTerrain(); static LLPanelRegionExperiences* getPanelExperiences(); + static LLPanelRegionGeneralInfo* getPanelGeneral(); // from LLPanel virtual void refresh(); @@ -183,6 +184,9 @@ public: // LLPanel virtual BOOL postBuild(); + void onBtnSet(); + void setObjBonusFactor(F32 object_bonus_factor) {mObjBonusFactor = object_bonus_factor;} + protected: virtual BOOL sendUpdate(); void onClickKick(); @@ -191,6 +195,9 @@ protected: bool onKickAllCommit(const LLSD& notification, const LLSD& response); static void onClickMessage(void* userdata); bool onMessageCommit(const LLSD& notification, const LLSD& response); + bool onChangeObjectBonus(const LLSD& notification, const LLSD& response); + + F32 mObjBonusFactor; }; diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 7b8fc5b35b..eae16b9f03 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -660,6 +660,8 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild() { return FALSE; } + list->setCommitCallback(boost::bind(&LLPanelScriptLimitsRegionMemory::checkButtonsEnabled, this)); + checkButtonsEnabled(); //set all columns to resizable mode even if some columns will be empty for(S32 column = 0; column < list->getNumColumns(); column++) @@ -750,6 +752,14 @@ void LLPanelScriptLimitsRegionMemory::clearList() getChild<LLUICtrl>("parcels_listed")->setValue(LLSD(msg_empty_string)); mObjectListItems.clear(); + checkButtonsEnabled(); +} + +void LLPanelScriptLimitsRegionMemory::checkButtonsEnabled() +{ + LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list"); + getChild<LLButton>("highlight_btn")->setEnabled(list->getNumSelected() > 0); + getChild<LLButton>("return_btn")->setEnabled(list->getNumSelected() > 0); } // static diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h index e3cbbd185f..2ac3862b4f 100644 --- a/indra/newview/llfloaterscriptlimits.h +++ b/indra/newview/llfloaterscriptlimits.h @@ -113,6 +113,7 @@ public: void showBeacon(); void returnObjectsFromParcel(S32 local_id); void returnObjects(); + void checkButtonsEnabled(); private: void onNameCache(const LLUUID& id, diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 0cb37dabe7..b139e5daf5 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -257,7 +257,6 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) static std::string badgeOK("badge_ok.j2c"); static std::string badgeNote("badge_note.j2c"); static std::string badgeWarn("badge_warn.j2c"); - static std::string badgeError("badge_error.j2c"); std::string badgeName; switch (badge) @@ -266,7 +265,7 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) case BADGE_OK: badgeName = badgeOK; break; case BADGE_NOTE: badgeName = badgeNote; break; case BADGE_WARN: badgeName = badgeWarn; break; - case BADGE_ERROR: badgeName = badgeError; break; + case BADGE_ERROR: badgeName = badgeWarn; break; } getChild<LLUICtrl>(id)->setValue(badgeName); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index afec981d56..b906671c7f 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1418,6 +1418,20 @@ void LLFloaterSnapshot::postPanelSwitch() } // static +void LLFloaterSnapshot::inventorySaveFailed() +{ + LLFloaterSnapshot* instance = findInstance(); + if (!instance) + { + llassert(instance != NULL); + return; + } + + instance->impl.updateControls(instance); + instance->impl.setStatus(Impl::STATUS_FINISHED, false, "inventory"); +} + +// static LLPointer<LLImageFormatted> LLFloaterSnapshot::getImageData() { // FIXME: May not work for textures. diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 0bb9474bb5..eb3a94999b 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -61,6 +61,7 @@ public: static BOOL saveLocal(); static void postSave(); static void postPanelSwitch(); + static void inventorySaveFailed(); static LLPointer<LLImageFormatted> getImageData(); static const LLVector3d& getPosTakenGlobal(); static void setAgentEmail(const std::string& email); diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index ece3e10faa..c67feb8158 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -963,10 +963,10 @@ F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination, } -void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui) +void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui, BOOL dest_reached) { LLCtrlListInterface *list = mListSearchResults; - if (list) + if (list && (!dest_reached || (list->getItemCount() == 1))) { list->operateOnAll(LLCtrlListInterface::OP_DELETE); } diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 7ce8dae9a9..c5801c8819 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -94,7 +94,7 @@ public: // A z_attenuation of 0.0f collapses the distance into the X-Y plane F32 getDistanceToDestination(const LLVector3d& pos_global, F32 z_attenuation = 0.5f) const; - void clearLocationSelection(BOOL clear_ui = FALSE); + void clearLocationSelection(BOOL clear_ui = FALSE, BOOL dest_reached = FALSE); void clearAvatarSelection(BOOL clear_ui = FALSE); void clearLandmarkSelection(BOOL clear_ui = FALSE); diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index a9bf8a9a50..97cc7684e4 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -248,7 +248,7 @@ bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, gInventory.collectDescendentsIf (cat->getUUID(), cats, items, - LLInventoryModel::EXCLUDE_TRASH, + LLInventoryModel::INCLUDE_TRASH, giveable); S32 count = cats.size(); bool complete = true; @@ -499,7 +499,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, gInventory.collectDescendentsIf (cat->getUUID(), cats, items, - LLInventoryModel::EXCLUDE_TRASH, + LLInventoryModel::INCLUDE_TRASH, giveable); bool give_successful = true; diff --git a/indra/newview/llinspectremoteobject.cpp b/indra/newview/llinspectremoteobject.cpp index a12ec390af..b64df2bd47 100644 --- a/indra/newview/llinspectremoteobject.cpp +++ b/indra/newview/llinspectremoteobject.cpp @@ -181,7 +181,7 @@ void LLInspectRemoteObject::update() getChild<LLUICtrl>("map_btn")->setEnabled(! mSLurl.empty()); // disable the Block button if we don't have the object ID (will this ever happen?) - getChild<LLUICtrl>("block_btn")->setEnabled(! mObjectID.isNull()); + getChild<LLUICtrl>("block_btn")->setEnabled(!mObjectID.isNull() && !LLMuteList::getInstance()->isMuted(mObjectID)); } ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 26c9b40fb1..f4bf38f65d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -286,6 +286,16 @@ BOOL LLInvFVBridge::cutToClipboard() return FALSE; } +// virtual +bool LLInvFVBridge::isCutToClipboard() +{ + if (LLClipboard::instance().isCutMode()) + { + return LLClipboard::instance().isOnClipboard(mUUID); + } + return false; +} + // Callback for cutToClipboard if DAMA required... BOOL LLInvFVBridge::callback_cutToClipboard(const LLSD& notification, const LLSD& response) { @@ -307,9 +317,7 @@ BOOL LLInvFVBridge::perform_cutToClipboard() if (obj && isItemMovable() && isItemRemovable()) { LLClipboard::instance().setCutMode(true); - BOOL added_to_clipboard = LLClipboard::instance().addToClipboard(mUUID); - removeObject(&gInventory, mUUID); // Always perform the remove even if the object couldn't make it to the clipboard - return added_to_clipboard; + return LLClipboard::instance().addToClipboard(mUUID); } return FALSE; } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 9053c61171..df25e01688 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -116,6 +116,7 @@ public: virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard(); + virtual bool isCutToClipboard(); virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; virtual void pasteFromClipboard() {} diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 003bbcafed..e995c138b4 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -84,21 +84,18 @@ LLInventoryFilter::LLInventoryFilter(const Params& p) bool LLInventoryFilter::check(const LLFolderViewModelItem* item) { const LLFolderViewModelItemInventory* listener = dynamic_cast<const LLFolderViewModelItemInventory*>(item); - // Clipboard cut items are *always* filtered so we need this value upfront - const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. const BOOL is_folder = listener->getInventoryType() == LLInventoryType::IT_CATEGORY; if (is_folder && (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)) { - return passed_clipboard; + return true; } bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true); passed = passed && checkAgainstFilterType(listener); passed = passed && checkAgainstPermissions(listener); passed = passed && checkAgainstFilterLinks(listener); - passed = passed && passed_clipboard; return passed; } @@ -108,9 +105,8 @@ bool LLInventoryFilter::check(const LLInventoryItem* item) const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true); const bool passed_filtertype = checkAgainstFilterType(item); const bool passed_permissions = checkAgainstPermissions(item); - const bool passed_clipboard = checkAgainstClipboard(item->getUUID()); - return passed_filtertype && passed_permissions && passed_clipboard && passed_string; + return passed_filtertype && passed_permissions && passed_string; } bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const @@ -129,13 +125,10 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { - // Always check against the clipboard - const BOOL passed_clipboard = checkAgainstClipboard(folder_id); - // we're showing all folders, overriding filter if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) { - return passed_clipboard; + return true; } // when applying a filter, matching folders get their contents downloaded first @@ -201,7 +194,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const LLViewerInventoryItem* item = gInventory.getItem(folder_id); if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) { - return passed_clipboard; + return true; } if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) @@ -216,7 +209,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return false; } - return passed_clipboard; + return true; } bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInventory* listener) const diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index e3cb4d57ef..d8f019374e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -287,7 +287,11 @@ void update_marketplace_category(const LLUUID& cur_uuid, bool perform_consistenc LL_INFOS("SLM") << "Unlist and clear version folder as the version folder is not at the right place anymore!!" << LL_ENDL; LLMarketplaceData::instance().setVersionFolder(listing_uuid, LLUUID::null,1); } - else if (version_folder_uuid.notNull() && LLMarketplaceData::instance().getActivationState(version_folder_uuid) && (count_descendants_items(version_folder_uuid) == 0) && !LLMarketplaceData::instance().isUpdating(version_folder_uuid,version_depth)) + else if (version_folder_uuid.notNull() + && gInventory.isCategoryComplete(version_folder_uuid) + && LLMarketplaceData::instance().getActivationState(version_folder_uuid) + && (count_descendants_items(version_folder_uuid) == 0) + && !LLMarketplaceData::instance().isUpdating(version_folder_uuid,version_depth)) { LL_INFOS("SLM") << "Unlist as the version folder is empty of any item!!" << LL_ENDL; LLNotificationsUtil::add("AlertMerchantVersionFolderEmpty"); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9a33e210ff..5230e8dff9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -582,7 +582,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, // Add the category to the internal representation LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 cat->setDescendentCount(0); LLCategoryUpdate update(cat->getParentUUID(), 1); accountForUpdate(update); @@ -640,7 +640,7 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv result["parent_id"].asUUID(), (LLFolderType::EType)result["type"].asInteger(), result["name"].asString(), gAgent.getID()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL); + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 cat->setDescendentCount(0); LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); @@ -914,8 +914,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, category_id); if( item_array ) { + LLInventoryModel::LLCategoryUpdate update(category_id, 1); + gInventory.accountForUpdate(update); + // *FIX: bit of a hack to call update server from here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -956,9 +959,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask) item_array = get_ptr_in_map(mParentChildItemTree, parent_id); if(item_array) { + LLInventoryModel::LLCategoryUpdate update(parent_id, 1); + gInventory.accountForUpdate(update); // *FIX: bit of a hack to call update server from // here... - new_item->updateServer(TRUE); + new_item->updateParentOnServer(FALSE); item_array->push_back(new_item); } else @@ -1045,7 +1050,6 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 if(old_cat) { // We already have an old category, modify its values - U32 mask = LLInventoryObserver::NONE; LLUUID old_parent_id = old_cat->getParentUUID(); LLUUID new_parent_id = cat->getParentUUID(); if(old_parent_id != new_parent_id) @@ -1100,7 +1104,8 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 item_array_t* itemsp = new item_array_t; mParentChildCategoryTree[new_cat->getUUID()] = catsp; mParentChildItemTree[new_cat->getUUID()] = itemsp; - addChangedMask(LLInventoryObserver::ADD, cat->getUUID()); + mask |= LLInventoryObserver::ADD; + addChangedMask(mask, cat->getUUID()); } } diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 8d21fda8f9..53b2ca2b74 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -64,6 +64,9 @@ #include "llurllineeditorctrl.h" #include "llagentui.h" +#include "llmenuoptionpathfindingrebakenavmesh.h" +#include "llpathfindingmanager.h" + //============================================================================ /* * "ADD LANDMARK" BUTTON UPDATING LOGIC @@ -1194,6 +1197,18 @@ bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata) return false; } +void LLLocationInputCtrl::callbackRebakeRegion(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) // OK + { + if (LLPathfindingManager::getInstance() != NULL) + { + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh(); + } + } +} + void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon) { switch (icon) @@ -1211,6 +1226,16 @@ void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon) LLNotificationsUtil::add("NoBuild"); break; case PATHFINDING_DIRTY_ICON: + if (LLPathfindingManager::getInstance() != NULL) + { + LLMenuOptionPathfindingRebakeNavmesh *rebakeInstance = LLMenuOptionPathfindingRebakeNavmesh::getInstance(); + if (rebakeInstance && rebakeInstance->canRebakeRegion() && (rebakeInstance->getMode() == LLMenuOptionPathfindingRebakeNavmesh::kRebakeNavMesh_Available)) + { + LLNotificationsUtil::add("PathfindingDirtyRebake", LLSD(), LLSD(), + boost::bind(&LLLocationInputCtrl::callbackRebakeRegion, this, _1, _2)); + break; + } + } LLNotificationsUtil::add("PathfindingDirty"); break; case PATHFINDING_DISABLED_ICON: diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h index cd6fd24077..da71bab6c1 100644 --- a/indra/newview/lllocationinputctrl.h +++ b/indra/newview/lllocationinputctrl.h @@ -166,6 +166,7 @@ private: // callbacks bool onLocationContextMenuItemEnabled(const LLSD& userdata); void onLocationContextMenuItemClicked(const LLSD& userdata); + void callbackRebakeRegion(const LLSD& notification, const LLSD& response); void onParcelIconClick(EParcelIcon icon); void createNavMeshStatusListenerForCurrentRegion(); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 4116e38f11..485d4677b1 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -244,7 +244,10 @@ std::string LLLogChat::makeLogFileName(std::string filename) filename = cleanFileName(filename); filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_ACCOUNT_CHAT_LOGS, filename); - filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + if (!filename.empty()) + { + filename += '.' + LL_TRANSCRIPT_FILE_EXTENSION; + } return filename; } @@ -904,7 +907,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params std::string stuff = matches[IDX_STUFF]; boost::match_results<std::string::const_iterator> name_and_text; 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]; @@ -956,7 +959,6 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params im[LL_IM_FROM] = name; } - im[LL_IM_TEXT] = name_and_text[IDX_TEXT]; return true; //parsed name and message text, maybe have a timestamp too } diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h index 1fb05e047a..69881e8589 100644 --- a/indra/newview/llmanip.h +++ b/indra/newview/llmanip.h @@ -1,4 +1,4 @@ -/** +/** * @file llmanip.h * @brief LLManip class definition * @@ -37,7 +37,7 @@ class LLToolComposite; class LLVector3; class LLObjectSelection; -const S32 MIN_DIVISION_PIXEL_WIDTH = 9; +const S32 MIN_DIVISION_PIXEL_WIDTH = 3; class LLManip : public LLTool { diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b4259a456c..3975d3980b 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llmaniptranslate.cpp * @brief LLManipTranslate class implementation * @@ -548,12 +548,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) if (off_axis_magnitude > mSnapOffsetMeters) { mInSnapRegime = TRUE; - LLVector3 mouse_down_offset(mDragCursorStartGlobal - mDragSelectionStartGlobal); LLVector3 cursor_snap_agent = gAgent.getPosAgentFromGlobal(cursor_point_snap_line); - if (!gSavedSettings.getBOOL("SnapToMouseCursor")) - { - cursor_snap_agent -= mouse_down_offset; - } F32 cursor_grid_dist = (cursor_snap_agent - mGridOrigin) * axis_f; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 6cc7a0fc99..54f95520db 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -773,7 +773,9 @@ void LLMarketplaceData::getMerchantStatusCoro() std::string url = getSLMConnectURL("/merchant"); if (url.empty()) { - LL_INFOS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL; + LL_WARNS("Marketplace") << "No marketplace capability on Sim" << LL_ENDL; + setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_CONNECTION_FAILURE); + return; } LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 0aaed3e286..27b26efa51 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3906,8 +3906,8 @@ void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail) bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) { - LLSD mesh = mThread->getMeshHeader(mesh_id); - if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) + const LLSD* mesh = mThread->getMeshHeader(mesh_id); + if (mesh && mesh->has("physics_mesh") && (*mesh)["physics_mesh"].has("size") && ((*mesh)["physics_mesh"]["size"].asInteger() > 0)) { return true; } @@ -3921,27 +3921,26 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) return false; } -LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id) +const LLSD* LLMeshRepository::getMeshHeader(const LLUUID& mesh_id) { LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); return mThread->getMeshHeader(mesh_id); } -LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) +const LLSD* LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) { - static LLSD dummy_ret; if (mesh_id.notNull()) { LLMutexLock lock(mHeaderMutex); mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end()) + if (iter != mMeshHeader.end() && mMeshHeaderSize[mesh_id] > 0) { - return iter->second; + return &(iter->second); } } - return dummy_ret; + return NULL; } @@ -4034,6 +4033,13 @@ void LLMeshRepository::uploadError(LLSD& args) //static F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value) { + if (header.has("404") + || !header.has("lowest_lod") + || (header.has("version") && header["version"].asInteger() > MAX_MESH_VERSION)) + { + return 0.f; + } + F32 max_distance = 512.f; F32 dlowest = llmin(radius/0.03f, max_distance); @@ -4093,7 +4099,7 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32 } } - F32 max_area = 102932.f; //area of circle that encompasses region + F32 max_area = 102944.f; //area of circle that encompasses region (see MAINT-6559) F32 min_area = 1.f; F32 high_area = llmin(F_PI*dmid*dmid, max_area); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index d35c44397b..8a1166522f 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -305,7 +305,7 @@ public: bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); - LLSD& getMeshHeader(const LLUUID& mesh_id); + const LLSD* getMeshHeader(const LLUUID& mesh_id); void notifyLoadedMeshes(); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -506,7 +506,7 @@ public: bool meshRezEnabled(); - LLSD& getMeshHeader(const LLUUID& mesh_id); + const LLSD* getMeshHeader(const LLUUID& mesh_id); void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true, diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index b2164c1f21..d17f5494a0 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -199,7 +199,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group) mGroupNameEditor = panel_group->getChild<LLLineEditor>("group_name_editor"); - mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCII ); + mGroupNameEditor->setPrevalidate( LLTextValidate::validateASCIINoLeadingSpace ); } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 4229419fce..c779ba5cdd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -150,6 +150,7 @@ BOOL LLPanelMainInventory::postBuild() LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); if (recent_items_panel) { + // assign default values until we will be sure that we have setting to restore recent_items_panel->setSinceLogoff(TRUE); recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); @@ -181,6 +182,7 @@ BOOL LLPanelMainInventory::postBuild() LLParamSDParser parser; parser.readSD(recent_items, p); recent_items_panel->getFilter().fromParams(p); + recent_items_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::RECENTITEMS_SORT_ORDER)); } } @@ -372,7 +374,14 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata) } getActivePanel()->setSortOrder(sort_order_mask); - gSavedSettings.setU32("InventorySortOrder", sort_order_mask); + if ("Recent Items" == getActivePanel()->getName()) + { + gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask); + } + else + { + gSavedSettings.setU32("InventorySortOrder", sort_order_mask); + } } // static @@ -1143,6 +1152,15 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } } +void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) +{ + if(!new_visibility) + { + mMenuAdd->setVisible(FALSE); + getActivePanel()->getRootFolder()->finishRenamingItem(); + } +} + bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index 21f0ca0cae..290e2e5f47 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -72,6 +72,7 @@ public: std::string& tooltip_msg); /*virtual*/ void changed(U32); /*virtual*/ void draw(); + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); LLInventoryPanel* getPanel() { return mActivePanel; } LLInventoryPanel* getActivePanel() { return mActivePanel; } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 8331c152e2..8b9941c0ca 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1059,9 +1059,6 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) case LLAssetType::AT_BODYPART: applyListViewFilter(LVIT_BODYPART); break; - case LLAssetType::AT_GESTURE: - applyListViewFilter(LVIT_GESTURES); - break; case LLAssetType::AT_CLOTHING: default: applyListViewFilter(LVIT_CLOTHING); diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 841bb4337a..30870daf40 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -80,7 +80,6 @@ public: { LVIT_ALL = 0, LVIT_CLOTHING, - LVIT_GESTURES, LVIT_BODYPART, LVIT_ATTACHMENT, LVIT_SHAPE, diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 73b928f014..bc177abc57 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -611,9 +611,11 @@ BOOL LLPanelPeople::postBuild() mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online")); mOnlineFriendList->setShowIcons("FriendsListShowIcons"); mOnlineFriendList->showPermissions("FriendsListShowPermissions"); + mOnlineFriendList->setShowCompleteName(!gSavedSettings.getBOOL("FriendsListHideUsernames")); mAllFriendList->setNoItemsCommentText(getString("no_friends")); mAllFriendList->setShowIcons("FriendsListShowIcons"); mAllFriendList->showPermissions("FriendsListShowPermissions"); + mAllFriendList->setShowCompleteName(!gSavedSettings.getBOOL("FriendsListHideUsernames")); LLPanel* nearby_tab = getChild<LLPanel>(NEARBY_TAB_NAME); nearby_tab->setVisibleCallback(boost::bind(&Updater::setActive, mNearbyListUpdater, _2)); @@ -622,6 +624,7 @@ BOOL LLPanelPeople::postBuild() mNearbyList->setNoItemsMsg(getString("no_one_near")); mNearbyList->setNoFilteredItemsMsg(getString("no_one_filtered_near")); mNearbyList->setShowIcons("NearbyListShowIcons"); + mNearbyList->setShowCompleteName(!gSavedSettings.getBOOL("NearbyListHideUsernames")); mMiniMap = (LLNetMap*)getChildView("Net Map",true); mMiniMap->setToolTipMsg(gSavedSettings.getBOOL("DoubleClickTeleport") ? getString("AltMiniMapToolTipMsg") : getString("MiniMapToolTipMsg")); @@ -1342,6 +1345,16 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata) mAllFriendList->showPermissions(show_permissions); mOnlineFriendList->showPermissions(show_permissions); } + else if (chosen_item == "view_usernames") + { + bool hide_usernames = !gSavedSettings.getBOOL("FriendsListHideUsernames"); + gSavedSettings.setBOOL("FriendsListHideUsernames", hide_usernames); + + mAllFriendList->setShowCompleteName(!hide_usernames); + mAllFriendList->handleDisplayNamesOptionChanged(); + mOnlineFriendList->setShowCompleteName(!hide_usernames); + mOnlineFriendList->handleDisplayNamesOptionChanged(); + } } void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) @@ -1374,6 +1387,14 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) { setSortOrder(mNearbyList, E_SORT_BY_DISTANCE); } + else if (chosen_item == "view_usernames") + { + bool hide_usernames = !gSavedSettings.getBOOL("NearbyListHideUsernames"); + gSavedSettings.setBOOL("NearbyListHideUsernames", hide_usernames); + + mNearbyList->setShowCompleteName(!hide_usernames); + mNearbyList->handleDisplayNamesOptionChanged(); + } } bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index a5f59dbf4a..65769ff526 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -38,9 +38,14 @@ #include "llavataractions.h" #include "llcallingcard.h" // for LLAvatarTracker #include "lllogchat.h" +#include "llparcel.h" #include "llviewermenu.h" // for gMenuHolder #include "llconversationmodel.h" #include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llvoavatarself.h" +#include "roles_constants.h" namespace LLPanelPeopleMenus { @@ -77,9 +82,13 @@ LLContextMenu* PeopleContextMenu::createMenu() registrar.add("Avatar.InviteToGroup", boost::bind(&LLAvatarActions::inviteToGroup, id)); registrar.add("Avatar.TeleportRequest", boost::bind(&PeopleContextMenu::requestTeleport, this)); registrar.add("Avatar.Calllog", boost::bind(&LLAvatarActions::viewChatHistory, id)); + registrar.add("Avatar.Freeze", boost::bind(&LLAvatarActions::freezeAvatar, id)); + registrar.add("Avatar.Eject", boost::bind(&PeopleContextMenu::eject, this)); + enable_registrar.add("Avatar.EnableItem", boost::bind(&PeopleContextMenu::enableContextMenuItem, this, _2)); enable_registrar.add("Avatar.CheckItem", boost::bind(&PeopleContextMenu::checkContextMenuItem, this, _2)); + enable_registrar.add("Avatar.EnableFreezeEject", boost::bind(&PeopleContextMenu::enableFreezeEject, this, _2)); // create the context menu from the XUI menu = createFromFile("menu_people_nearby.xml"); @@ -258,6 +267,50 @@ bool PeopleContextMenu::checkContextMenuItem(const LLSD& userdata) return false; } +bool PeopleContextMenu::enableFreezeEject(const LLSD& userdata) +{ + if((gAgent.getID() == mUUIDs.front()) || (mUUIDs.size() != 1)) + { + return false; + } + + const LLUUID& id = mUUIDs.front(); + + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (id.notNull()) + { + LLViewerObject* object = gObjectList.findObject(id); + if (object) + { + if( !object->isAvatar() ) + { + object = NULL; + } + avatar = (LLVOAvatar*) object; + } + } + if (!avatar) return false; + + // Gods can always freeze + if (gAgent.isGodlike()) return true; + + // Estate owners / managers can freeze + // Parcel owners can also freeze + const LLVector3& pos = avatar->getPositionRegion(); + const LLVector3d& pos_global = avatar->getPositionGlobal(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos_global)->getParcel(); + LLViewerRegion* region = avatar->getRegion(); + if (!region) return false; + + bool new_value = region->isOwnedSelf(pos); + if (!new_value || region->isOwnedGroup(pos)) + { + new_value = LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_ADMIN); + } + return new_value; +} + void PeopleContextMenu::requestTeleport() { // boost::bind cannot recognize overloaded method LLAvatarActions::teleportRequest(), @@ -272,6 +325,39 @@ void PeopleContextMenu::offerTeleport() LLAvatarActions::offerTeleport(mUUIDs); } +void PeopleContextMenu::eject() +{ + if((gAgent.getID() == mUUIDs.front()) || (mUUIDs.size() != 1)) + { + return; + } + + const LLUUID& id = mUUIDs.front(); + + // Use avatar_id if available, otherwise default to right-click avatar + LLVOAvatar* avatar = NULL; + if (id.notNull()) + { + LLViewerObject* object = gObjectList.findObject(id); + if (object) + { + if( !object->isAvatar() ) + { + object = NULL; + } + avatar = (LLVOAvatar*) object; + } + } + if (!avatar) return; + LLSD payload; + payload["avatar_id"] = avatar->getID(); + std::string fullname = avatar->getFullname(); + + const LLVector3d& pos = avatar->getPositionGlobal(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->selectParcelAt(pos)->getParcel(); + LLAvatarActions::ejectAvatar(id ,LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED)); +} + void PeopleContextMenu::startConference() { uuid_vec_t uuids; @@ -320,6 +406,8 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags) items.push_back(std::string("share")); items.push_back(std::string("pay")); items.push_back(std::string("block_unblock")); + items.push_back(std::string("freeze")); + items.push_back(std::string("eject")); } hide_context_entries(menu, items, disabled_items); diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h index 9767bab89f..5ed20e0064 100644 --- a/indra/newview/llpanelpeoplemenus.h +++ b/indra/newview/llpanelpeoplemenus.h @@ -46,7 +46,9 @@ protected: private: bool enableContextMenuItem(const LLSD& userdata); bool checkContextMenuItem(const LLSD& userdata); + bool enableFreezeEject(const LLSD& userdata); void offerTeleport(); + void eject(); void startConference(); void requestTeleport(); }; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index e795e7eedb..184238c40c 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -176,6 +176,16 @@ public: return true; } + if (verb == "unblock") + { + if (params.size() > 2) + { + const std::string object_name = params[2].asString(); + LLMute mute(avatar_id, object_name, LLMute::OBJECT); + LLMuteList::getInstance()->remove(mute); + } + return true; + } return false; } }; diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index c55e230b5e..a2d1752c6a 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -34,6 +34,8 @@ #include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model #include "llpanelsnapshot.h" #include "llviewercontrol.h" // gSavedSettings +#include "llstatusbar.h" // can_afford_transaction() +#include "llnotificationsutil.h" /** * The panel provides UI for saving snapshot as an inventory texture. @@ -102,6 +104,17 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) void LLPanelSnapshotInventory::onSend() { - LLFloaterSnapshot::saveTexture(); - LLFloaterSnapshot::postSave(); + S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + if (can_afford_transaction(expected_upload_cost)) + { + LLFloaterSnapshot::saveTexture(); + LLFloaterSnapshot::postSave(); + } + else + { + LLSD args; + args["COST"] = llformat("%d", expected_upload_cost); + LLNotificationsUtil::add("ErrorPhotoCannotAfford", args); + LLFloaterSnapshot::inventorySaveFailed(); + } } diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index d86a8b4480..796372ba04 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -30,13 +30,19 @@ #include "lltoggleablemenu.h" +#include "llagent.h" +#include "llaccordionctrl.h" +#include "llaccordionctrltab.h" #include "llappearancemgr.h" #include "llfloatersidepanelcontainer.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llmenubutton.h" +#include "llscrolllistctrl.h" #include "llviewermenu.h" +#include "llviewerregion.h" #include "llwearableitemslist.h" #include "llsdserialize.h" #include "llclipboard.h" @@ -94,6 +100,7 @@ protected: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("Wearing.Edit", boost::bind(&edit_outfit)); + registrar.add("Wearing.ShowOriginal", boost::bind(show_item_original, mUUIDs.front())); registrar.add("Wearing.TakeOff", boost::bind(&LLAppearanceMgr::removeItemsFromAvatar, LLAppearanceMgr::getInstance(), mUUIDs)); registrar.add("Wearing.Detach", @@ -144,11 +151,48 @@ protected: menu->setItemVisible("take_off", allow_take_off); menu->setItemVisible("detach", allow_detach); menu->setItemVisible("edit_outfit_separator", allow_take_off || allow_detach); + menu->setItemVisible("show_original", mUUIDs.size() == 1); + menu->setItemVisible("edit_item", FALSE); } }; ////////////////////////////////////////////////////////////////////////// +class LLTempAttachmentsContextMenu : public LLListContextMenu +{ +public: + LLTempAttachmentsContextMenu(LLPanelWearing* panel_wearing) + : mPanelWearing(panel_wearing) + {} +protected: + /* virtual */ LLContextMenu* createMenu() + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + + registrar.add("Wearing.EditItem", boost::bind(&LLPanelWearing::onEditAttachment, mPanelWearing)); + registrar.add("Wearing.Detach", boost::bind(&LLPanelWearing::onRemoveAttachment, mPanelWearing)); + LLContextMenu* menu = createFromFile("menu_wearing_tab.xml"); + + updateMenuItemsVisibility(menu); + + return menu; + } + + void updateMenuItemsVisibility(LLContextMenu* menu) + { + menu->setItemVisible("take_off", FALSE); + menu->setItemVisible("detach", TRUE); + menu->setItemVisible("edit_outfit_separator", TRUE); + menu->setItemVisible("show_original", FALSE); + menu->setItemVisible("edit_item", TRUE); + menu->setItemVisible("edit", FALSE); + } + + LLPanelWearing* mPanelWearing; +}; + +////////////////////////////////////////////////////////////////////////// + std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null; static LLPanelInjector<LLPanelWearing> t_panel_wearing("panel_wearing"); @@ -157,30 +201,47 @@ LLPanelWearing::LLPanelWearing() : LLPanelAppearanceTab() , mCOFItemsList(NULL) , mIsInitialized(false) + , mAttachmentsChangedConnection() { mCategoriesObserver = new LLInventoryCategoriesObserver(); mGearMenu = new LLWearingGearMenu(this); mContextMenu = new LLWearingContextMenu(); + mAttachmentsMenu = new LLTempAttachmentsContextMenu(this); } LLPanelWearing::~LLPanelWearing() { delete mGearMenu; delete mContextMenu; + delete mAttachmentsMenu; if (gInventory.containsObserver(mCategoriesObserver)) { gInventory.removeObserver(mCategoriesObserver); } delete mCategoriesObserver; + + if (mAttachmentsChangedConnection.connected()) + { + mAttachmentsChangedConnection.disconnect(); + } } BOOL LLPanelWearing::postBuild() { + mAccordionCtrl = getChild<LLAccordionCtrl>("wearables_accordion"); + mWearablesTab = getChild<LLAccordionCtrlTab>("tab_wearables"); + mAttachmentsTab = getChild<LLAccordionCtrlTab>("tab_temp_attachments"); + mAttachmentsTab->setDropDownStateChangedCallback(boost::bind(&LLPanelWearing::onAccordionTabStateChanged, this)); + mCOFItemsList = getChild<LLWearableItemsList>("cof_items_list"); mCOFItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onWearableItemsListRightClick, this, _1, _2, _3)); + mTempItemsList = getChild<LLScrollListCtrl>("temp_attachments_list"); + mTempItemsList->setFgUnselectedColor(LLColor4::white); + mTempItemsList->setRightMouseDownCallback(boost::bind(&LLPanelWearing::onTempAttachmentsListRightClick, this, _1, _2, _3)); + LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn"); menu_gear_btn->setMenu(mGearMenu->getMenu()); @@ -221,6 +282,44 @@ void LLPanelWearing::onOpen(const LLSD& /*info*/) } } +void LLPanelWearing::draw() +{ + if (mUpdateTimer.getStarted() && (mUpdateTimer.getElapsedTimeF32() > 0.1)) + { + mUpdateTimer.stop(); + updateAttachmentsList(); + } + LLPanel::draw(); +} + +void LLPanelWearing::onAccordionTabStateChanged() +{ + if(mAttachmentsTab->isExpanded()) + { + startUpdateTimer(); + mAttachmentsChangedConnection = LLAppearanceMgr::instance().setAttachmentsChangedCallback(boost::bind(&LLPanelWearing::startUpdateTimer, this)); + } + else + { + if (mAttachmentsChangedConnection.connected()) + { + mAttachmentsChangedConnection.disconnect(); + } + } +} + +void LLPanelWearing::startUpdateTimer() +{ + if (!mUpdateTimer.getStarted()) + { + mUpdateTimer.start(); + } + else + { + mUpdateTimer.reset(); + } +} + // virtual void LLPanelWearing::setFilterSubString(const std::string& string) { @@ -249,6 +348,124 @@ bool LLPanelWearing::isActionEnabled(const LLSD& userdata) return false; } +void LLPanelWearing::updateAttachmentsList() +{ + std::vector<LLViewerObject*> attachs = LLAgentWearables::getTempAttachments(); + mTempItemsList->deleteAllItems(); + mAttachmentsMap.clear(); + if(!attachs.empty()) + { + if(!populateAttachmentsList()) + { + requestAttachmentDetails(); + } + } + else + { + std::string no_attachments = getString("no_attachments"); + LLSD row; + row["columns"][0]["column"] = "text"; + row["columns"][0]["value"] = no_attachments; + row["columns"][0]["font"] = "SansSerifBold"; + mTempItemsList->addElement(row); + } +} + +bool LLPanelWearing::populateAttachmentsList(bool update) +{ + bool populated = true; + if(mTempItemsList) + { + mTempItemsList->deleteAllItems(); + mAttachmentsMap.clear(); + std::vector<LLViewerObject*> attachs = LLAgentWearables::getTempAttachments(); + + std::string icon_name = LLInventoryIcon::getIconName(LLAssetType::AT_OBJECT, LLInventoryType::IT_OBJECT); + for (std::vector<LLViewerObject*>::iterator iter = attachs.begin(); + iter != attachs.end(); ++iter) + { + LLViewerObject *attachment = *iter; + LLSD row; + row["id"] = attachment->getID(); + row["columns"][0]["column"] = "icon"; + row["columns"][0]["type"] = "icon"; + row["columns"][0]["value"] = icon_name; + row["columns"][1]["column"] = "text"; + if(mObjectNames.count(attachment->getID()) && !mObjectNames[attachment->getID()].empty()) + { + row["columns"][1]["value"] = mObjectNames[attachment->getID()]; + } + else if(update) + { + row["columns"][1]["value"] = attachment->getID(); + populated = false; + } + else + { + row["columns"][1]["value"] = "Loading..."; + populated = false; + } + mTempItemsList->addElement(row); + mAttachmentsMap[attachment->getID()] = attachment; + } + } + return populated; +} + +void LLPanelWearing::requestAttachmentDetails() +{ + LLSD body; + std::string url = gAgent.getRegion()->getCapability("AttachmentResources"); + if (!url.empty()) + { + LLCoros::instance().launch("LLPanelWearing::getAttachmentLimitsCoro", + boost::bind(&LLPanelWearing::getAttachmentLimitsCoro, this, url)); + } +} + +void LLPanelWearing::getAttachmentLimitsCoro(std::string url) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL; + return; + } + + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + setAttachmentDetails(result); +} + + +void LLPanelWearing::setAttachmentDetails(LLSD content) +{ + mObjectNames.clear(); + S32 number_attachments = content["attachments"].size(); + for(int i = 0; i < number_attachments; i++) + { + S32 number_objects = content["attachments"][i]["objects"].size(); + for(int j = 0; j < number_objects; j++) + { + LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID(); + std::string name = content["attachments"][i]["objects"][j]["name"].asString(); + mObjectNames[task_id] = name; + } + } + if(!mObjectNames.empty()) + { + populateAttachmentsList(true); + } +} + boost::signals2::connection LLPanelWearing::setSelectionChangeCallback(commit_callback_t cb) { if (!mCOFItemsList) return boost::signals2::connection(); @@ -268,6 +485,20 @@ void LLPanelWearing::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) mContextMenu->show(ctrl, selected_uuids, x, y); } +void LLPanelWearing::onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) +{ + LLScrollListCtrl* list = dynamic_cast<LLScrollListCtrl*>(ctrl); + if (!list) return; + list->selectItemAt(x, y, MASK_NONE); + uuid_vec_t selected_uuids; + + if(list->getCurrentID().notNull()) + { + selected_uuids.push_back(list->getCurrentID()); + mAttachmentsMenu->show(ctrl, selected_uuids, x, y); + } +} + bool LLPanelWearing::hasItemSelected() { return mCOFItemsList->getSelectedItem() != NULL; @@ -278,6 +509,28 @@ void LLPanelWearing::getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const mCOFItemsList->getSelectedUUIDs(selected_uuids); } +void LLPanelWearing::onEditAttachment() +{ + LLScrollListItem* item = mTempItemsList->getFirstSelected(); + if (item) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); + handle_object_edit(); + } +} + +void LLPanelWearing::onRemoveAttachment() +{ + LLScrollListItem* item = mTempItemsList->getFirstSelected(); + if (item) + { + LLSelectMgr::getInstance()->deselectAll(); + LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); + LLSelectMgr::getInstance()->sendDropAttachment(); + } +} + void LLPanelWearing::copyToClipboard() { std::string text; diff --git a/indra/newview/llpanelwearing.h b/indra/newview/llpanelwearing.h index 9a212b3cca..c5cb79092a 100644 --- a/indra/newview/llpanelwearing.h +++ b/indra/newview/llpanelwearing.h @@ -31,9 +31,14 @@ // newview #include "llpanelappearancetab.h" +#include "llselectmgr.h" +#include "lltimer.h" +class LLAccordionCtrl; +class LLAccordionCtrlTab; class LLInventoryCategoriesObserver; class LLListContextMenu; +class LLScrollListCtrl; class LLWearableItemsList; class LLWearingGearMenu; @@ -52,6 +57,8 @@ public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + /*virtual*/ void onOpen(const LLSD& info); /*virtual*/ void setFilterSubString(const std::string& string); @@ -62,17 +69,43 @@ public: /*virtual*/ void copyToClipboard(); + void startUpdateTimer(); + void updateAttachmentsList(); + boost::signals2::connection setSelectionChangeCallback(commit_callback_t cb); bool hasItemSelected(); + bool populateAttachmentsList(bool update = false); + void onAccordionTabStateChanged(); + void setAttachmentDetails(LLSD content); + void requestAttachmentDetails(); + void onEditAttachment(); + void onRemoveAttachment(); + private: void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + void onTempAttachmentsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + + void getAttachmentLimitsCoro(std::string url); LLInventoryCategoriesObserver* mCategoriesObserver; LLWearableItemsList* mCOFItemsList; + LLScrollListCtrl* mTempItemsList; LLWearingGearMenu* mGearMenu; LLListContextMenu* mContextMenu; + LLListContextMenu* mAttachmentsMenu; + + LLAccordionCtrlTab* mWearablesTab; + LLAccordionCtrlTab* mAttachmentsTab; + LLAccordionCtrl* mAccordionCtrl; + + std::map<LLUUID, LLViewerObject*> mAttachmentsMap; + + std::map<LLUUID, std::string> mObjectNames; + + boost::signals2::connection mAttachmentsChangedConnection; + LLFrameTimer mUpdateTimer; bool mIsInitialized; }; diff --git a/indra/newview/llpathfindinglinksetlist.cpp b/indra/newview/llpathfindinglinksetlist.cpp index b886e46765..eb7b95552e 100644 --- a/indra/newview/llpathfindinglinksetlist.cpp +++ b/indra/newview/llpathfindinglinksetlist.cpp @@ -204,7 +204,10 @@ void LLPathfindingLinksetList::parseLinksetListData(const LLSD& pLinksetListData { const std::string& uuid(linksetDataIter->first); const LLSD& linksetData = linksetDataIter->second; - LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData)); - objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr)); + if(linksetData.size() != 0) + { + LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData)); + objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, linksetPtr)); + } } } diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index d95546f11d..836f63bffa 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -38,6 +38,7 @@ #include "llviewercontrol.h" #include "llfloaterpreference.h" #include "llfloaterreg.h" +#include "llfeaturemanager.h" LLPresetsManager::LLPresetsManager() { @@ -60,7 +61,7 @@ void LLPresetsManager::createMissingDefault() LL_INFOS() << "No default preset found -- creating one at " << default_file << LL_ENDL; // Write current graphic settings as the default - savePreset(PRESETS_GRAPHIC, PRESETS_DEFAULT); + savePreset(PRESETS_GRAPHIC, PRESETS_DEFAULT, true); } else { @@ -103,8 +104,7 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam if (found) { std::string path = gDirUtilp->add(dir, file); - std::string name = gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true); - + std::string name = LLURI::unescape(gDirUtilp->getBaseFileName(path, /*strip_exten = */ true)); LL_DEBUGS() << " Found preset '" << name << "'" << LL_ENDL; if (PRESETS_DEFAULT != name) @@ -134,7 +134,7 @@ void LLPresetsManager::loadPresetNamesFromDir(const std::string& dir, preset_nam presets = mPresetNames; } -bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string name) +bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string name, bool createDefault) { if (LLTrans::getString(PRESETS_DEFAULT) == name) { @@ -146,11 +146,10 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n if(PRESETS_GRAPHIC == subdirectory) { - gSavedSettings.setString("PresetGraphicActive", name); - LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences"); - if (instance) + if (instance && !createDefault) { + gSavedSettings.setString("PresetGraphicActive", name); instance->getControlNames(name_list); LL_DEBUGS() << "saving preset '" << name << "'; " << name_list.size() << " names" << LL_ENDL; name_list.push_back("PresetGraphicActive"); @@ -170,23 +169,36 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n LL_ERRS() << "Invalid presets directory '" << subdirectory << "'" << LL_ENDL; } - if (name_list.size() > 1) // if the active preset name is the only thing in the list, don't save the list + if (name_list.size() > 1 // if the active preset name is the only thing in the list, don't save the list + || (createDefault && name == PRESETS_DEFAULT && subdirectory == PRESETS_GRAPHIC)) // or create a default graphics preset from hw recommended settings { // make an empty llsd LLSD paramsData(LLSD::emptyMap()); - for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it) + if (createDefault) { - std::string ctrl_name = *it; - LLControlVariable* ctrl = gSavedSettings.getControl(ctrl_name).get(); - std::string comment = ctrl->getComment(); - std::string type = LLControlGroup::typeEnumToString(ctrl->type()); - LLSD value = ctrl->getValue(); - - paramsData[ctrl_name]["Comment"] = comment; - paramsData[ctrl_name]["Persist"] = 1; - paramsData[ctrl_name]["Type"] = type; - paramsData[ctrl_name]["Value"] = value; + paramsData = LLFeatureManager::getInstance()->getRecommendedSettingsMap(); + if (gSavedSettings.getU32("RenderAvatarMaxComplexity") == 0) + { + // use the recommended setting as an initial one (MAINT-6435) + gSavedSettings.setU32("RenderAvatarMaxComplexity", paramsData["RenderAvatarMaxComplexity"]["Value"].asInteger()); + } + } + else + { + for (std::vector<std::string>::iterator it = name_list.begin(); it != name_list.end(); ++it) + { + std::string ctrl_name = *it; + LLControlVariable* ctrl = gSavedSettings.getControl(ctrl_name).get(); + std::string comment = ctrl->getComment(); + std::string type = LLControlGroup::typeEnumToString(ctrl->type()); + LLSD value = ctrl->getValue(); + + paramsData[ctrl_name]["Comment"] = comment; + paramsData[ctrl_name]["Persist"] = 1; + paramsData[ctrl_name]["Type"] = type; + paramsData[ctrl_name]["Value"] = value; + } } std::string pathName(getPresetsDir(subdirectory) + gDirUtilp->getDirDelimiter() + LLURI::escape(name) + ".xml"); @@ -203,10 +215,12 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n LL_DEBUGS() << "saved preset '" << name << "'; " << paramsData.size() << " parameters" << LL_ENDL; - gSavedSettings.setString("PresetGraphicActive", name); - - // signal interested parties - triggerChangeSignal(); + if (!createDefault) + { + gSavedSettings.setString("PresetGraphicActive", name); + // signal interested parties + triggerChangeSignal(); + } } else { diff --git a/indra/newview/llpresetsmanager.h b/indra/newview/llpresetsmanager.h index ac4f0c010c..21f9885f27 100644 --- a/indra/newview/llpresetsmanager.h +++ b/indra/newview/llpresetsmanager.h @@ -56,7 +56,7 @@ public: static std::string getPresetsDir(const std::string& subdirectory); void setPresetNamesInComboBox(const std::string& subdirectory, LLComboBox* combo, EDefaultOptions default_option); void loadPresetNamesFromDir(const std::string& dir, preset_name_list_t& presets, EDefaultOptions default_option); - bool savePreset(const std::string& subdirectory, std::string name); + bool savePreset(const std::string& subdirectory, std::string name, bool createDefault = false); void loadPreset(const std::string& subdirectory, std::string name); bool deletePreset(const std::string& subdirectory, std::string name); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 20c43bc432..510d91839d 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -94,7 +94,8 @@ BOOL LLPreviewNotecard::postBuild() if (item) { getChild<LLUICtrl>("desc")->setValue(item->getDescription()); - getChildView("Delete")->setEnabled(true); + BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID()); + getChildView("Delete")->setEnabled(!source_library); } getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); @@ -219,6 +220,7 @@ void LLPreviewNotecard::loadAsset() BOOL is_owner = gAgent.allowOperation(PERM_OWNER, perm, GP_OBJECT_MANIPULATE); BOOL allow_copy = gAgent.allowOperation(PERM_COPY, perm, GP_OBJECT_MANIPULATE); BOOL allow_modify = canModify(mObjectUUID, item); + BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID()); if (allow_copy || gAgent.isGodlike()) { @@ -288,7 +290,7 @@ void LLPreviewNotecard::loadAsset() getChildView("lock")->setVisible( TRUE); } - if(allow_modify || is_owner) + if((allow_modify || is_owner) && !source_library) { getChildView("Delete")->setEnabled(TRUE); } @@ -435,6 +437,23 @@ void LLPreviewNotecard::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, } } +void LLPreviewNotecard::finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId) +{ + + LLSD floater_key; + floater_key["taskid"] = taskId; + floater_key["itemid"] = itemId; + LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance<LLPreviewNotecard>("preview_notecard", floater_key); + if (nc) + { + if (nc->hasEmbeddedInventory()) + { + gVFS->removeFile(newAssetId, LLAssetType::AT_NOTECARD); + } + nc->setAssetId(newAssetId); + nc->refreshFromInventory(); + } +} bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem) { @@ -483,7 +502,7 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem) else if (!mObjectUUID.isNull() && !task_url.empty()) { uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, - boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _3, LLUUID::null))); + boost::bind(&LLPreviewNotecard::finishTaskUpload, _1, _3, mObjectUUID))); url = task_url; } diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index ba571995f6..017c4485ba 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -96,6 +96,7 @@ protected: bool handleConfirmDeleteDialog(const LLSD& notification, const LLSD& response); static void finishInventoryUpload(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId); + static void finishTaskUpload(LLUUID itemId, LLUUID newAssetId, LLUUID taskId); protected: LLViewerTextEditor* mEditor; diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 2a2c51be40..645a77e42a 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -38,6 +38,7 @@ #include "llimagetga.h" #include "llimagepng.h" #include "llinventory.h" +#include "llinventorymodel.h" #include "llnotificationsutil.h" #include "llresmgr.h" #include "lltrans.h" @@ -120,18 +121,22 @@ BOOL LLPreviewTexture::postBuild() childSetAction("save_tex_btn", LLPreviewTexture::onSaveAsBtn, this); getChildView("save_tex_btn")->setVisible( true); getChildView("save_tex_btn")->setEnabled(canSaveAs()); - - if (!mCopyToInv) - { - const LLInventoryItem* item = getItem(); - - if (item) - { - childSetCommitCallback("desc", LLPreview::onText, this); - getChild<LLUICtrl>("desc")->setValue(item->getDescription()); - getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); - } - } + + const LLInventoryItem* item = getItem(); + if (item) + { + if (!mCopyToInv) + { + childSetCommitCallback("desc", LLPreview::onText, this); + getChild<LLUICtrl>("desc")->setValue(item->getDescription()); + getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); + } + BOOL source_library = mObjectUUID.isNull() && gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID()); + if (source_library) + { + getChildView("Discard")->setEnabled(false); + } + } // Fill in ratios list with common aspect ratio values mRatiosList.clear(); @@ -526,6 +531,15 @@ void LLPreviewTexture::loadAsset() // check that we can copy inworld items into inventory getChildView("Keep")->setEnabled(mIsCopyable); } + else + { + // check that we can remove item + BOOL source_library = gInventory.isObjectDescendentOf(mItemUUID, gInventory.getLibraryRootFolderID()); + if (source_library) + { + getChildView("Discard")->setEnabled(false); + } + } } LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus() diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 86135ee6e8..f07f0ed86c 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -383,7 +383,7 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) { - if (!mEditWearable || mEditWearable->getVisible() == visible) + if (!mEditWearable || ((mEditWearable->getWearable() == wearable) && mEditWearable->getVisible() == visible)) { // visibility isn't changing, hence nothing to do return; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 88fbd233b8..4e81d78455 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -687,6 +687,11 @@ bool idle_startup() gRememberPassword = gSavedSettings.getBOOL("RememberPassword"); show_connect_box = TRUE; } + + //setup map of datetime strings to codes and slt & local time offset from utc + // *TODO: Does this need to be here? + LLStringOps::setupDatetimeInfo(false); + // Go to the next startup state LLStartUp::setStartupState( STATE_BROWSER_INIT ); return FALSE; @@ -766,7 +771,11 @@ bool idle_startup() LL_DEBUGS("AppInit") << "FirstLoginThisInstall off" << LL_ENDL; } } - + display_startup(); + if (gViewerWindow->getSystemUIScaleFactorChanged()) + { + LLViewerWindow::showSystemUIScaleFactorChanged(); + } LLStartUp::setStartupState( STATE_LOGIN_WAIT ); // Wait for user input } else @@ -1139,9 +1148,6 @@ bool idle_startup() LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); } } - //setup map of datetime strings to codes and slt & local time offset from utc - // *TODO: Does this need to be here? - LLStringOps::setupDatetimeInfo (false); transition_back_to_login_panel(emsg.str()); show_connect_box = true; } @@ -3310,6 +3316,13 @@ bool process_login_success_response() { time_t now = time(NULL); gUTCOffset = (server_utc_time - now); + + // Print server timestamp + LLSD substitution; + substitution["datetime"] = (S32)server_utc_time; + std::string timeStr = "[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second, datetime, slt]"; + LLStringUtil::format(timeStr, substitution); + LL_INFOS("AppInit") << "Server SLT timestamp: " << timeStr << ". Server-viewer time offset before correction: " << gUTCOffset << "s" << LL_ENDL; } } diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 7020ac0c65..edde7c8076 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -202,6 +202,21 @@ void LLToast::hide() } } +/*virtual*/ +void LLToast::setFocus(BOOL b) +{ + if (b && !hasFocus() && mPanel) + { + LLModalDialog::setFocus(TRUE); + // mostly for buttons + mPanel->setFocus(TRUE); + } + else + { + LLModalDialog::setFocus(b); + } +} + void LLToast::onFocusLost() { if(mWrapperPanel && !isBackgroundVisible()) diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index f02d7c2a1a..cd92189012 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -150,6 +150,8 @@ public: // virtual void hide(); + /*virtual*/ void setFocus(BOOL b); + /*virtual*/ void onFocusLost(); /*virtual*/ void onFocusReceived(); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 98ed2f0fc4..e3a856be5c 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -103,7 +103,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); } // for the scriptdialog buttons we use fixed button size. This is a limit! - if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > BUTTON_WIDTH) + if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > (BUTTON_WIDTH-2*HPAD)) { p.rect.width = 1; p.auto_resize = true; @@ -160,7 +160,11 @@ void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair } LLButton* btn = it->second; LLRect btn_rect(btn->getRect()); - if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel + if (buttons.size() == 1) // for the one-button forms, center that button + { + left = (max_width - btn_rect.getWidth()) / 2; + } + else if (left + btn_rect.getWidth() > max_width)// whether there is still some place for button+h_pad in the mControlPanel { // looks like we need to add button to the next row left = 0; @@ -321,6 +325,7 @@ void LLToastNotifyPanel::init( LLRect rect, bool show_images ) mTextBox->setContentTrusted(is_content_trusted); mTextBox->setValue(mNotification->getMessage()); mTextBox->setIsFriendCallback(LLAvatarActions::isFriend); + mTextBox->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0)); // add buttons for a script notification if (mIsTip) diff --git a/indra/newview/lltoastscriptquestion.cpp b/indra/newview/lltoastscriptquestion.cpp index 91ba8c0247..7a3a1d8fd7 100644 --- a/indra/newview/lltoastscriptquestion.cpp +++ b/indra/newview/lltoastscriptquestion.cpp @@ -54,6 +54,19 @@ BOOL LLToastScriptQuestion::postBuild() return TRUE; } + +// virtual +void LLToastScriptQuestion::setFocus(BOOL b) +{ + LLToastPanel::setFocus(b); + // toast can fade out and disappear with focus ON, so reset to default anyway + LLButton* dfbutton = getDefaultButton(); + if (dfbutton && dfbutton->getVisible() && dfbutton->getEnabled()) + { + dfbutton->setFocus(b); + } +} + void LLToastScriptQuestion::snapToMessageHeight() { LLTextBox* mMessage = getChild<LLTextBox>("top_info_message"); @@ -118,6 +131,12 @@ void LLToastScriptQuestion::createButtons() button->setRect(rect); buttons_width += rect.getWidth() + LEFT_PAD; + + if (form_element.has("default") && form_element["default"].asBoolean()) + { + button->setFocus(TRUE); + setDefaultBtn(button); + } } } } diff --git a/indra/newview/lltoastscriptquestion.h b/indra/newview/lltoastscriptquestion.h index 3a557f60f6..a756f88415 100644 --- a/indra/newview/lltoastscriptquestion.h +++ b/indra/newview/lltoastscriptquestion.h @@ -39,6 +39,8 @@ public: virtual BOOL postBuild(); virtual ~LLToastScriptQuestion(){}; + /*virtual*/ void setFocus(BOOL b); + private: void snapToMessageHeight(); diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 2f8e464b71..b0e3b5bf89 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -83,6 +83,7 @@ LLToolMgr::LLToolMgr() // Not a panel, register these callbacks globally. LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); + LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.EnabledOrActive", boost::bind(&LLToolMgr::buildEnabledOrActive, this)); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2)); LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Marketplace.Enabled", boost::bind(&LLToolMgr::canAccessMarketplace, this)); LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Marketplace.Toggle", boost::bind(&LLToolMgr::toggleMarketplace, this, _2)); @@ -264,17 +265,21 @@ bool LLToolMgr::canEdit() return LLViewerParcelMgr::getInstance()->allowAgentBuild(); } +bool LLToolMgr::buildEnabledOrActive() +{ + return inEdit() || canEdit(); +} + void LLToolMgr::toggleBuildMode(const LLSD& sdname) { const std::string& param = sdname.asString(); + LLFloaterReg::toggleInstanceOrBringToFront("build"); if (param == "build" && !canEdit()) { return; } - LLFloaterReg::toggleInstanceOrBringToFront("build"); - bool build_visible = LLFloaterReg::instanceVisible("build"); if (build_visible) { diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index a3c1045aac..e5b45750d9 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -54,6 +54,7 @@ public: bool inEdit(); bool canEdit(); + bool buildEnabledOrActive(); bool canAccessMarketplace(); void toggleBuildMode(const LLSD& sdname); void toggleMarketplace(const LLSD& sdname); diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index f611d0503f..b015cde45d 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -183,7 +183,7 @@ void LLTracker::render3D() F32 dist = gFloaterWorldMap->getDistanceToDestination(pos_global, 0.5f); if (dist < DESTINATION_REACHED_RADIUS) { - instance()->stopTrackingLocation(); + instance()->stopTrackingLocation(FALSE,TRUE); } else { @@ -655,13 +655,13 @@ void LLTracker::stopTrackingLandmark(BOOL clear_ui) } -void LLTracker::stopTrackingLocation(BOOL clear_ui) +void LLTracker::stopTrackingLocation(BOOL clear_ui, BOOL dest_reached) { purgeBeaconText(); mTrackedLocationName.assign(""); mIsTrackingLocation = FALSE; mTrackedPositionGlobal.zeroVec(); - gFloaterWorldMap->clearLocationSelection(clear_ui); + gFloaterWorldMap->clearLocationSelection(clear_ui, dest_reached); mTrackingStatus = TRACKING_NOTHING; mTrackingLocationType = LOCATION_NOTHING; } diff --git a/indra/newview/lltracker.h b/indra/newview/lltracker.h index 218f3430a6..a1c5052c1b 100644 --- a/indra/newview/lltracker.h +++ b/indra/newview/lltracker.h @@ -116,7 +116,7 @@ protected: void stopTrackingAll(BOOL clear_ui = FALSE); void stopTrackingAvatar(BOOL clear_ui = FALSE); - void stopTrackingLocation(BOOL clear_ui = FALSE); + void stopTrackingLocation(BOOL clear_ui = FALSE, BOOL dest_reached = FALSE); void stopTrackingLandmark(BOOL clear_ui = FALSE); void drawMarker(const LLVector3d& pos_global, const LLColor4& color); diff --git a/indra/newview/llviewchildren.cpp b/indra/newview/llviewchildren.cpp index 5c5bbdc8f5..32b2f7e9f5 100644 --- a/indra/newview/llviewchildren.cpp +++ b/indra/newview/llviewchildren.cpp @@ -79,8 +79,9 @@ void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible) default: case BADGE_OK: child->setValue(std::string("badge_ok.j2c")); break; case BADGE_NOTE: child->setValue(std::string("badge_note.j2c")); break; - case BADGE_WARN: child->setValue(std::string("badge_warn.j2c")); break; - case BADGE_ERROR: child->setValue(std::string("badge_error.j2c")); break; + case BADGE_WARN: + case BADGE_ERROR: + child->setValue(std::string("badge_warn.j2c")); break; } } } diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index f0dafec240..497ff4d2bf 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -837,5 +837,12 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res } } + // Let the Snapshot floater know we have failed uploading. + LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); + if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_snapshot) + { + floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); + } + } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 16f40fb747..5e74e9f019 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -207,6 +207,12 @@ static bool handleVolumeLODChanged(const LLSD& newvalue) return true; } +static bool handleRiggedLODChanged(const LLSD& newvalue) +{ + LLVOVolume::sRiggedFactorMultiplier = (F32)newvalue.asReal(); + return true; +} + static bool handleAvatarLODChanged(const LLSD& newvalue) { LLVOAvatar::sLODFactor = (F32) newvalue.asReal(); @@ -619,6 +625,7 @@ void settings_setup_listeners() gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2)); + gSavedSettings.getControl("RenderRiggedFactorMultiplier")->getSignal()->connect(boost::bind(&handleRiggedLODChanged, _2)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2)); gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _2)); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d0813544f8..0bbe9fa2c2 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1007,6 +1007,22 @@ void activate_gesture_cb(const LLUUID& inv_item) LLGestureMgr::instance().activateGesture(inv_item); } +void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type) +{ + llassert(item); + LLPermissions perm = item->getPermissions(); + if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type) + || perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type)) + { + perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type)); + perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type)); + + item->setPermissions(perm); + + item->updateServer(FALSE); + } +} + void create_script_cb(const LLUUID& inv_item) { if (!inv_item.isNull()) @@ -1014,13 +1030,9 @@ void create_script_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts")); - - item->setPermissions(perm); + set_default_permissions(item, "Scripts"); - item->updateServer(FALSE); + // item was just created, update even if permissions did not changed gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -1036,13 +1048,8 @@ void create_gesture_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures")); + set_default_permissions(item, "Gestures"); - item->setPermissions(perm); - - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); @@ -1061,13 +1068,8 @@ void create_notecard_cb(const LLUUID& inv_item) LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (item) { - LLPermissions perm = item->getPermissions(); - perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards")); - perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards")); - - item->setPermissions(perm); + set_default_permissions(item, "Notecards"); - item->updateServer(FALSE); gInventory.updateItem(item); gInventory.notifyObservers(); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99a9ed1d75..46f03f9971 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -397,13 +397,15 @@ void set_merchant_SLM_menu() gToolBarView->enableCommand(command->id(), true); } -void check_merchant_status() +void check_merchant_status(bool force) { if (!gSavedSettings.getBOOL("InventoryOutboxDisplayBoth")) { - // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() - LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); - + if (force) + { + // Reset the SLM status: we actually want to check again, that's the point of calling check_merchant_status() + LLMarketplaceData::instance().setSLMStatus(MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED); + } // Hide SLM related menu item gMenuHolder->getChild<LLView>("MarketplaceListings")->setVisible(FALSE); @@ -6986,20 +6988,25 @@ class LLAvatarCall : public view_listener_t namespace { - struct QueueObjects : public LLSelectedObjectFunctor + struct QueueObjects : public LLSelectedNodeFunctor { BOOL scripted; BOOL modifiable; LLFloaterScriptQueue* mQueue; QueueObjects(LLFloaterScriptQueue* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {} - virtual bool apply(LLViewerObject* obj) + virtual bool apply(LLSelectNode* node) { + LLViewerObject* obj = node->getObject(); + if (!obj) + { + return true; + } scripted = obj->flagScripted(); modifiable = obj->permModify(); if( scripted && modifiable ) { - mQueue->addObject(obj->getID()); + mQueue->addObject(obj->getID(), node->mName); return false; } else @@ -7015,7 +7022,7 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& msg) QueueObjects func(q); LLSelectMgr *mgr = LLSelectMgr::getInstance(); LLObjectSelectionHandle selectHandle = mgr->getSelection(); - bool fail = selectHandle->applyToObjects(&func); + bool fail = selectHandle->applyToNodes(&func); if(fail) { if ( !func.scripted ) diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index b7bdf00157..a553bb79a2 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -83,7 +83,7 @@ BOOL enable_god_full(void* user_data); BOOL enable_god_liaison(void* user_data); BOOL enable_god_basic(void* user_data); void set_underclothes_menu_options(); -void check_merchant_status(); +void check_merchant_status(bool force = false); void exchange_callingcard(const LLUUID& dest_id); @@ -108,6 +108,7 @@ void handle_look_at_selection(const LLSD& param); void handle_zoom_to_object(LLUUID object_id); void handle_object_return(); void handle_object_delete(); +void handle_object_edit(); void handle_buy_land(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 92df3866f7..3925154c0f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1639,7 +1639,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); discard_agent_offer->startFetch(); - if (catp || (itemp && itemp->isFinished())) + if ((catp && gInventory.isCategoryComplete(mObjectID)) || (itemp && itemp->isFinished())) { discard_agent_offer->done(); } @@ -4719,7 +4719,9 @@ void process_sound_trigger(LLMessageSystem *msg, void **) { if (!gAudiop) { +#if !LL_LINUX LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +#endif return; } @@ -4781,7 +4783,9 @@ void process_preload_sound(LLMessageSystem *msg, void **user_data) { if (!gAudiop) { +#if !LL_LINUX LL_WARNS("AudioEngine") << "LLAudioEngine instance doesn't exist!" << LL_ENDL; +#endif return; } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 5edc3c9745..72a8595845 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -133,6 +133,7 @@ std::map<std::string, U32> LLViewerObject::sObjectDataMap; // JC 3/18/2003 const F32 PHYSICS_TIMESTEP = 1.f / 45.f; +const F64 INV_REQUEST_EXPIRE_TIME_SEC = 60.f; static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object"); @@ -245,7 +246,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mInventory(NULL), mInventorySerialNum(0), mRegionp( regionp ), - mInventoryPending(FALSE), + mInvRequestExpireTime(0.f), mInventoryDirty(FALSE), mDead(FALSE), mOrphaned(FALSE), @@ -1434,10 +1435,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, setChanged(MOVED | SILHOUETTE); } - else if (mText.notNull()) + else { - mText->markDead(); - mText = NULL; + if (mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + mHudText.clear(); } std::string media_url; @@ -1812,10 +1817,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, setChanged(TEXTURE); } - else if(mText.notNull()) + else { - mText->markDead(); - mText = NULL; + if (mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + mHudText.clear(); } std::string media_url; @@ -2832,6 +2841,15 @@ void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener) } } +BOOL LLViewerObject::isInventoryPending() +{ + if (mInvRequestExpireTime == 0.f || mInvRequestExpireTime < LLFrameTimer::getTotalSeconds()) + { + return FALSE; + } + return TRUE; +} + void LLViewerObject::clearInventoryListeners() { for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer()); @@ -2870,7 +2888,7 @@ void LLViewerObject::requestInventory() void LLViewerObject::fetchInventoryFromServer() { - if (!mInventoryPending) + if (mInvRequestExpireTime == 0.f || mInvRequestExpireTime < LLFrameTimer::getTotalSeconds()) { delete mInventory; LLMessageSystem* msg = gMessageSystem; @@ -2883,7 +2901,7 @@ void LLViewerObject::fetchInventoryFromServer() msg->sendReliable(mRegionp->getHost()); // this will get reset by dirtyInventory or doInventoryCallback - mInventoryPending = TRUE; + mInvRequestExpireTime = LLFrameTimer::getTotalSeconds() + INV_REQUEST_EXPIRE_TIME_SEC; } } @@ -3099,7 +3117,7 @@ void LLViewerObject::doInventoryCallback() mInventoryCallbacks.erase(curiter); } } - mInventoryPending = FALSE; + mInvRequestExpireTime = 0.f; } void LLViewerObject::removeInventory(const LLUUID& item_id) @@ -4990,8 +5008,26 @@ void LLViewerObject::initHudText() void LLViewerObject::restoreHudText() { - if(mText) + if (mHudText.empty()) + { + if (mText) + { + mText->markDead(); + mText = NULL; + } + } + else { + if (!mText) + { + initHudText(); + } + else + { + // Restore default values + mText->setZCompare(TRUE); + mText->setDoFade(TRUE); + } mText->setColor(mHudTextColor); mText->setString(mHudText); } diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index cb8acfdcf8..b95190c554 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -437,7 +437,7 @@ public: // viewer object has the inventory stored locally. void registerInventoryListener(LLVOInventoryListener* listener, void* user_data); void removeInventoryListener(LLVOInventoryListener* listener); - BOOL isInventoryPending() { return mInventoryPending; } + BOOL isInventoryPending(); void clearInventoryListeners(); bool hasInventoryListeners(); void requestInventory(); @@ -757,7 +757,7 @@ protected: S16 mInventorySerialNum; LLViewerRegion *mRegionp; // Region that this object belongs to. - BOOL mInventoryPending; + F64 mInvRequestExpireTime; BOOL mInventoryDirty; BOOL mDead; BOOL mOrphaned; // This is an orphaned child diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 023f1b92ba..86591ff4df 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -465,7 +465,7 @@ LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node) { LLVector4a tmp; tmp.splat(0.f); - mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = + mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] = mObjectExtents[0] = mObjectExtents[1] = tmp; mBounds[0] = node->getCenter(); diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index 7efa821bbf..814060f4f2 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -441,10 +441,20 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewer return NULL; } + F32 prev_max_age = pssp->mPartSysData.mMaxAge; + F32 prev_start_age = pssp->mPartSysData.mStartAge; if (!pssp->mPartSysData.unpackBlock(block_num)) { return NULL; } + else if (pssp->mPartSysData.mMaxAge + && (prev_max_age != pssp->mPartSysData.mMaxAge || prev_start_age != pssp->mPartSysData.mStartAge)) + { + // reusing existing pss, so reset time to allow particles to start again + pssp->mLastUpdateTime = 0.f; + pssp->mLastPartTime = 0.f; + } + if (pssp->mPartSysData.mTargetUUID.notNull()) { LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index cac2ed8585..899ab3a371 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -264,17 +264,18 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle) } S32 id = ++mHttpResponderID; - ++mSeedCapAttempts; LLSD capabilityNames = LLSD::emptyArray(); buildCapabilityNames(capabilityNames); LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url - << " (attempt #" << mSeedCapAttempts << ")" << LL_ENDL; + << " (attempt #" << mSeedCapAttempts + 1 << ")" << LL_ENDL; regionp = NULL; result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames); + ++mSeedCapAttempts; + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); if (!regionp) //region was removed { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index db4b555eca..178aa1e646 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1200,7 +1200,7 @@ void LLViewerFetchedTexture::loadFromFastCache() { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl mRawImage->scale(expected_width, expected_height); @@ -1875,7 +1875,8 @@ bool LLViewerFetchedTexture::updateFetch() static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2); static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3); - if(textures_decode_disabled) + if(textures_decode_disabled || + (gUseWireframe && mBoostLevel < LLGLTexture::BOOST_AVATAR_BAKED_SELF)) // don't fetch the surface textures in wireframe mode { return false; } @@ -1980,7 +1981,7 @@ bool LLViewerFetchedTexture::updateFetch() { S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENTIONS; S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENTIONS; - if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height) + if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) { // scale oversized icon, no need to give more work to gl mRawImage->scale(expected_width, expected_height); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 08f6143861..d7080051da 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -171,13 +171,27 @@ void LLViewerTextureList::doPreloadImages() mImagePreloads.insert(image); } image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, - 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903")); + 0, 0, IMG_TRANSPARENT); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - + image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + GL_ALPHA8, GL_ALPHA, IMG_ALPHA_GRAD); + if (image) + { + image->setAddressMode(LLTexUnit::TAM_CLAMP); + mImagePreloads.insert(image); + } + image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + GL_ALPHA8, GL_ALPHA, IMG_ALPHA_GRAD_2D); + if (image) + { + image->setAddressMode(LLTexUnit::TAM_CLAMP); + mImagePreloads.insert(image); + } + LLPointer<LLImageRaw> img_blak_square_tex(new LLImageRaw(2, 2, 3)); memset(img_blak_square_tex->getData(), 0, img_blak_square_tex->getDataSize()); LLPointer<LLViewerFetchedTexture> img_blak_square(new LLViewerFetchedTexture(img_blak_square_tex, FTT_DEFAULT, FALSE)); @@ -188,7 +202,7 @@ void LLViewerTextureList::doPreloadImages() static std::string get_texture_list_name() { - return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "texture_list_" + gSavedSettings.getString("LoginLocation") + ".xml"); + return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + ".xml"); } void LLViewerTextureList::doPrefetchImages() @@ -293,7 +307,7 @@ void LLViewerTextureList::shutdown() break; } - if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty()) + if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "").empty()) { std::string filename = get_texture_list_name(); llofstream file; diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 0f73515b5d..88eb13e7cd 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -451,7 +451,7 @@ void LLViewerWearable::copyDataFrom(const LLViewerWearable* src) // Probably reduntant, but ensure that the newly created wearable is not dirty by setting current value of params in new wearable // to be the same as the saved values (which were loaded from src at param->cloneParam(this)) - revertValues(); + revertValuesWithoutUpdate(); } void LLViewerWearable::setItemID(const LLUUID& item_id) @@ -471,6 +471,11 @@ void LLViewerWearable::revertValues() } } +void LLViewerWearable::revertValuesWithoutUpdate() +{ + LLWearable::revertValues(); +} + void LLViewerWearable::saveValues() { LLWearable::saveValues(); diff --git a/indra/newview/llviewerwearable.h b/indra/newview/llviewerwearable.h index 62cd5e21ad..cc99f6af2f 100644 --- a/indra/newview/llviewerwearable.h +++ b/indra/newview/llviewerwearable.h @@ -85,6 +85,8 @@ public: /*virtual*/ void revertValues(); /*virtual*/ void saveValues(); + void revertValuesWithoutUpdate(); + // Something happened that requires the wearable's label to be updated (e.g. worn/unworn). /*virtual*/void setUpdated() const; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c17c50fd88..f47a37fcda 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1655,7 +1655,8 @@ LLViewerWindow::LLViewerWindow(const Params& p) mResDirty(false), mStatesDirty(false), mCurrResolutionIndex(0), - mProgressView(NULL) + mProgressView(NULL), + mSystemUIScaleFactorChanged(false) { // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to // pass its value right now. Instead, pass it a nullary function that @@ -1743,6 +1744,16 @@ LLViewerWindow::LLViewerWindow(const Params& p) gSavedSettings.setS32("FullScreenHeight",scr.mY); } + + F32 system_scale_factor = mWindow->getSystemUISize(); + if (p.first_run || gSavedSettings.getF32("LastSystemUIScaleFactor") != system_scale_factor) + { + mSystemUIScaleFactorChanged = true; + gSavedSettings.setF32("LastSystemUIScaleFactor", system_scale_factor); + gSavedSettings.setF32("UIScaleFactor", system_scale_factor); + } + + // Get the real window rect the window was created with (since there are various OS-dependent reasons why // the size of a window or fullscreen context may have been adjusted slightly...) F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); @@ -1838,6 +1849,28 @@ LLViewerWindow::LLViewerWindow(const Params& p) mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); } +//static +void LLViewerWindow::showSystemUIScaleFactorChanged() +{ + LLNotificationsUtil::add("SystemUIScaleFactorChanged", LLSD(), LLSD(), onSystemUIScaleFactorChanged); +} + +//static +bool LLViewerWindow::onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if(option == 0) + { + LLFloaterReg::toggleInstanceOrBringToFront("preferences"); + LLFloater* pref_floater = LLFloaterReg::getInstance("preferences"); + LLTabContainer* tab_container = pref_floater->getChild<LLTabContainer>("pref core"); + tab_container->selectTabByName("advanced1"); + + } + return false; +} + + void LLViewerWindow::initGLDefaults() { gGL.setSceneBlendType(LLRender::BT_ALPHA); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ad06f00234..afe80358ca 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -155,7 +155,8 @@ public: min_width, min_height; Optional<bool> fullscreen, - ignore_pixel_depth; + ignore_pixel_depth, + first_run; Params(); }; @@ -418,6 +419,9 @@ public: void calcDisplayScale(); static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale); + bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; } + static void showSystemUIScaleFactorChanged(); + private: bool shouldShowToolTipFor(LLMouseHandler *mh); @@ -431,6 +435,7 @@ private: S32 getChatConsoleBottomPad(); // Vertical padding for child console rect, varied by bottom clutter LLRect getChatConsoleRect(); // Get optimal cosole rect. + static bool onSystemUIScaleFactorChanged(const LLSD& notification, const LLSD& response); private: LLWindow* mWindow; // graphical window object bool mActive; @@ -509,6 +514,7 @@ private: LLPointer<LLViewerObject> mDragHoveredObject; static LLTrace::SampleStatHandle<> sMouseVelocityStat; + bool mSystemUIScaleFactorChanged; // system UI scale factor changed from last run }; // diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index b9dd43f061..cdc7e20c2c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7313,7 +7313,6 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32 //----------------------------------------------------------------------------- void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { - static S32 largestSelfCOFSeen(LLViewerInventoryCategory::VERSION_UNKNOWN); LL_DEBUGS("Avatar") << "starts" << LL_ENDL; bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"); @@ -7348,43 +7347,34 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) return; } - S32 this_update_cof_version = contents.mCOFVersion; - S32 last_update_request_cof_version = mLastUpdateRequestCOFVersion; + S32 thisAppearanceVersion(contents.mCOFVersion); + if (isSelf()) + { // In the past this was considered to be the canonical COF version, + // that is no longer the case. The canonical version is maintained + // by the AIS code and should match the COF version there. Even so, + // we must prevent rolling this one backwards backwards or processing + // stale versions. - if( isSelf() ) - { - LL_DEBUGS("Avatar") << "this_update_cof_version " << this_update_cof_version - << " last_update_request_cof_version " << last_update_request_cof_version - << " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL; + S32 aisCOFVersion(LLAppearanceMgr::instance().getCOFVersion()); + + LL_DEBUGS("Avatar") << "handling self appearance message #" << thisAppearanceVersion << + " (highest seen #" << mLastUpdateReceivedCOFVersion << + ") (AISCOF=#" << aisCOFVersion << ")" << LL_ENDL; - if (largestSelfCOFSeen > this_update_cof_version) + if (mLastUpdateReceivedCOFVersion >= thisAppearanceVersion) { - LL_WARNS("Avatar") << "Already processed appearance for COF version " << - largestSelfCOFSeen << ", discarding appearance with COF " << this_update_cof_version << LL_ENDL; + LL_WARNS("Avatar") << "Stale appearance received #" << thisAppearanceVersion << + " attempt to roll back from #" << mLastUpdateReceivedCOFVersion << + "... dropping." << LL_ENDL; + return; + } + if (isEditingAppearance()) + { + LL_DEBUGS("Avatar") << "Editing appearance. Dropping appearance update." << LL_ENDL; return; } - largestSelfCOFSeen = this_update_cof_version; - - } - else - { - LL_DEBUGS("Avatar") << "appearance message received" << LL_ENDL; - } - - // Check for stale update. - if (isSelf() - && (this_update_cof_version < last_update_request_cof_version)) - { - LL_WARNS() << "Stale appearance update, wanted version " << last_update_request_cof_version - << ", got " << this_update_cof_version << LL_ENDL; - return; - } - if (isSelf() && isEditingAppearance()) - { - LL_DEBUGS("Avatar") << "ignoring appearance message while in appearance edit" << LL_ENDL; - return; - } + } // SUNSHINE CLEANUP - is this case OK now? S32 num_params = contents.mParamWeights.size(); @@ -7399,13 +7389,17 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } // No backsies zone - if we get here, the message should be valid and usable, will be processed. - LL_INFOS("Avatar") << "Processing appearance message version " << this_update_cof_version << LL_ENDL; + LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; - // Note: - // RequestAgentUpdateAppearanceResponder::onRequestRequested() - // assumes that cof version is only updated with server-bake - // appearance messages. - mLastUpdateReceivedCOFVersion = this_update_cof_version; + if (isSelf()) + { + // Note: + // locally the COF is maintained via LLInventoryModel::accountForUpdate + // which is called from various places. This should match the simhost's + // idea of what the COF version is. AIS however maintains its own version + // of the COF that should be considered canonical. + mLastUpdateReceivedCOFVersion = thisAppearanceVersion; + } if (applyParsedTEMessage(contents.mTEContents) > 0 && isChanged(TEXTURE)) { @@ -7528,7 +7522,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // Got an update for some other avatar // Ignore updates for self, because we have a more authoritative value in the preferences. setHoverOffset(contents.mHoverOffset); - LL_INFOS("Avatar") << avString() << "setting hover to " << contents.mHoverOffset[2] << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "setting hover to " << contents.mHoverOffset[2] << LL_ENDL; } if (!contents.mHoverOffsetWasSet && !isSelf()) @@ -8151,6 +8145,7 @@ U32 LLVOAvatar::getPartitionType() const //static void LLVOAvatar::updateImpostors() { + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; LLCharacter::sAllowInstancesChange = FALSE; for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 07427e0377..189ed54993 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -427,7 +427,7 @@ void LLVivoxVoiceClient::connectorCreate() void LLVivoxVoiceClient::connectorShutdown() { - if(!mConnectorEstablished) + if(mConnectorEstablished) { std::ostringstream stream; stream diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8f0b233f01..5fc571bf1d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -86,6 +86,7 @@ BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; +F32 LLVOVolume::sRiggedFactorMultiplier = 6.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; @@ -1213,18 +1214,18 @@ void LLVOVolume::sculpt() } } -S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) +S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor) { S32 cur_detail; if (LLPipeline::sDynamicLOD) { // We've got LOD in the profile, and in the twist. Use radius. - F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; + F32 tan_angle = (lod_factor*radius) / distance; cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); } else { - cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3); + cur_detail = llclamp((S32)(sqrtf(radius)*lod_factor*4.f), 0, 3); } return cur_detail; } @@ -1240,6 +1241,7 @@ BOOL LLVOVolume::calcLOD() F32 radius; F32 distance; + F32 lod_factor = LLVOVolume::sLODFactor; if (mDrawable->isState(LLDrawable::RIGGED)) { @@ -1251,22 +1253,27 @@ BOOL LLVOVolume::calcLOD() return FALSE; } + // Note: when changing, take note that a lot of rigged meshes have only one LOD. + lod_factor *= LLVOVolume::sRiggedFactorMultiplier; distance = avatar->mDrawable->mDistanceWRTCamera; - radius = avatar->getBinRadius(); + F32 avatar_radius = avatar->getBinRadius(); + F32 object_radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); + radius = object_radius * LLVOVolume::sRiggedFactorMultiplier; + radius = llmin(radius, avatar_radius); } else { distance = mDrawable->mDistanceWRTCamera; radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length(); } - + //hold onto unmodified distance for debugging //F32 debug_distance = distance; - + distance *= sDistanceFactor; - F32 rampDist = LLVOVolume::sLODFactor * 2; - + F32 rampDist = lod_factor * 2; + if (distance < rampDist) { // Boost LOD when you're REALLY close @@ -1279,7 +1286,8 @@ BOOL LLVOVolume::calcLOD() distance *= F_PI/3.f; cur_detail = computeLODDetail(ll_round(distance, 0.01f), - ll_round(radius, 0.01f)); + ll_round(radius, 0.01f), + lod_factor); if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && @@ -1753,7 +1761,10 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); compiled = TRUE; lodOrSculptChanged(drawable, compiled); - genBBoxes(FALSE); + if (!mLODChanged) + { + genBBoxes(FALSE); + } } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local else @@ -3627,8 +3638,9 @@ F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_v F32 radius = getScale().length()*0.5f; if (isMesh()) - { - LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID()); + { + const LLSD* header_ptr = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID()); + LLSD header = header_ptr ? *header_ptr : LLSD(); return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value); } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index a331908320..ca9917069b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -327,7 +327,7 @@ public: void clearRiggedVolume(); protected: - S32 computeLODDetail(F32 distance, F32 radius); + S32 computeLODDetail(F32 distance, F32 radius, F32 lod_factor); BOOL calcLOD(); LLFace* addFace(S32 face_index); void updateTEData(); @@ -379,6 +379,7 @@ private: public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop static F32 sLODFactor; // LOD scale factor + static F32 sRiggedFactorMultiplier; // Worn rigged LOD scale factor multiplier static F32 sDistanceFactor; // LOD distance factor static LLPointer<LLObjectMediaDataClient> sObjectMediaClient; diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index 066cb9a0ac..482a2a61e2 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -288,14 +288,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) { // set up the iterators - // keep cloud positions and coverage the same - /// TODO masking will do this later - F32 cloudPos1X = (F32) mParamValues["cloud_pos_density1"][0].asReal(); - F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal(); - F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal(); - F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal(); - F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal(); - LLSD srcVal; LLSD destVal; @@ -379,15 +371,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) setSunAngle((1 - weight) * srcSunAngle + weight * destSunAngle); setEastAngle((1 - weight) * srcEastAngle + weight * destEastAngle); - - // now setup the sun properly - - // reset those cloud positions - mParamValues["cloud_pos_density1"][0] = cloudPos1X; - mParamValues["cloud_pos_density1"][1] = cloudPos1Y; - mParamValues["cloud_pos_density2"][0] = cloudPos2X; - mParamValues["cloud_pos_density2"][1] = cloudPos2Y; - mParamValues["cloud_shadow"][0] = cloudCover; } void LLWLParamSet::updateCloudScrolling(void) diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index 97a9eb7f5f..cc3645131d 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -322,7 +322,7 @@ public: mBoundListener = LLEventPumps::instance(). obtain("mainloop"). - listen(LLEventPump::inventName(), boost::bind(&Poller::poll, this, _1)); + listen(LLEventPump::ANONYMOUS, boost::bind(&Poller::poll, this, _1)); LL_INFOS("LLXMLRPCListener") << mMethod << " request sent to " << mUri << LL_ENDL; } diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 72037a84b3..85f4ae587a 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -774,6 +774,9 @@ with the same filename but different name <texture name="default_land_picture.j2c" /> <texture name="default_profile_picture.j2c" /> <texture name="locked_image.j2c" /> + <texture name="badge_note.j2c" /> + <texture name="badge_warn.j2c" /> + <texture name="badge_ok.j2c" /> <texture name="materials_ui_x_24.png" /> <texture name="Progress_1" file_name="icons/Progress_1.png" preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml index f4aca7bb3d..0982683a7f 100644 --- a/indra/newview/skins/default/xui/en/floater_script_queue.xml +++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml @@ -29,6 +29,14 @@ name="NotRunning"> Not running </floater.string> + <floater.string + name="Timeout"> + Timeout: [OBJECT_NAME] + </floater.string> + <floater.string + name="LoadingObjInv"> + Loading inventory for: [OBJECT_NAME] + </floater.string> <button follows="right|bottom" height="24" diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index 170b7177fb..550af03683 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -10,8 +10,10 @@ <file>ArialUni.ttf</file> </os> <os name="Mac"> + <file>ヒラギノ角ゴシック W3.ttc</file> <file>ヒラギノ角ゴ Pro W3.otf</file> <file>ヒラギノ角ゴ ProN W3.otf</file> + <file>ヒラギノ明朝 ProN W3.ttc</file> <file>AppleGothic.dfont</file> <file>AppleGothic.ttf</file> <file>AppleSDGothicNeo-Regular.otf</file> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 419ec359a6..dcf2da52f1 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -140,13 +140,6 @@ function="Advanced.ShowDebugSettings" parameter="all" /> </menu_item_call> - <menu_item_call - label="UI/Color Settings" - name="UI/Color Settings"> - <menu_item_call.on_click - function="Advanced.ShowDebugSettings" - parameter="skin" /> - </menu_item_call> <menu_item_separator /> <menu_item_call label="XUI Preview Tool" diff --git a/indra/newview/skins/default/xui/en/menu_object_icon.xml b/indra/newview/skins/default/xui/en/menu_object_icon.xml index 2d4f1792c2..5137aea72a 100644 --- a/indra/newview/skins/default/xui/en/menu_object_icon.xml +++ b/indra/newview/skins/default/xui/en/menu_object_icon.xml @@ -23,6 +23,20 @@ <menu_item_call.on_click function="ObjectIcon.Action" parameter="block" /> + <menu_item_call.on_visible + function="ObjectIcon.Visible" + parameter="not_blocked" /> + </menu_item_call> + <menu_item_call + label="Unblock" + layout="topleft" + name="Unblock"> + <menu_item_call.on_click + function="ObjectIcon.Action" + parameter="unblock" /> + <menu_item_call.on_visible + function="ObjectIcon.Visible" + parameter="is_blocked" /> </menu_item_call> <menu_item_separator layout="topleft" /> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index 8790fde7c5..b5a4b87acd 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -40,6 +40,14 @@ function="CheckControl" parameter="FriendsListShowPermissions" /> </menu_item_check> + <menu_item_check name="view_usernames" label="Hide usernames"> + <menu_item_check.on_click + function="People.Friends.ViewSort.Action" + parameter="view_usernames" /> + <menu_item_check.on_check + function="CheckControl" + parameter="FriendsListHideUsernames" /> + </menu_item_check> <menu_item_check name="view_conversation" label="View Conversation Log..."> <menu_item_check.on_check function="Floater.Visible" diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index f12226ebeb..c1500d4e7c 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -143,4 +143,20 @@ function="Avatar.EnableItem" parameter="can_block" /> </menu_item_check> + <menu_item_call + label="Freeze" + name="freeze"> + <menu_item_call.on_click + function="Avatar.Freeze" /> + <menu_item_call.on_visible + function="Avatar.EnableFreezeEject"/> + </menu_item_call> + <menu_item_call + label="Eject" + name="eject"> + <menu_item_call.on_click + function="Avatar.Eject" /> + <menu_item_call.on_visible + function="Avatar.EnableFreezeEject"/> + </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml index da88ca9f4d..a9f6b8045d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -50,4 +50,12 @@ function="ToggleControl" parameter="NearbyListShowMap" /> </menu_item_check> + <menu_item_check name="view_usernames" label="Hide usernames"> + <menu_item_check.on_click + function="People.Nearby.ViewSort.Action" + parameter="view_usernames" /> + <menu_item_check.on_check + function="CheckControl" + parameter="NearbyListHideUsernames" /> + </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml index b9d003b841..41d40b389a 100644 --- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml +++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml @@ -16,6 +16,13 @@ <menu_item_call.on_click function="Url.Block" /> </menu_item_call> + <menu_item_call + label="Unblock" + layout="topleft" + name="unblock_object"> + <menu_item_call.on_click + function="Url.Unblock" /> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0a492fb37b..b189d1038f 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -806,7 +806,7 @@ <menu_item_check.on_click function="Build.Toggle" /> <menu_item_check.on_enable - function="Build.Enabled" /> + function="Build.EnabledOrActive" /> </menu_item_check> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml index 2d54e69601..75c1de24aa 100644 --- a/indra/newview/skins/default/xui/en/menu_wearing_tab.xml +++ b/indra/newview/skins/default/xui/en/menu_wearing_tab.xml @@ -27,4 +27,18 @@ <on_click function="Wearing.Edit" /> </menu_item_call> + <menu_item_call + label="Edit" + layout="topleft" + name="edit_item"> + <on_click + function="Wearing.EditItem" /> + </menu_item_call> + <menu_item_call + label="Show Original" + layout="topleft" + name="show_original"> + <on_click + function="Wearing.ShowOriginal" /> + </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 492d963653..54e90ac496 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -832,6 +832,13 @@ If you no longer wish to have these abilities granted to this role, disable them </notification> <notification + icon="notify.tga" + name="GroupBanUserOnBanlist" + type="notify"> +Some residents have not been sent an invite due to being banned from the group. + </notification> + + <notification icon="alertmodal.tga" name="AttachmentDrop" type="alertmodal"> @@ -1150,6 +1157,22 @@ Error encoding snapshot. <notification icon="alertmodal.tga" + name="ErrorPhotoCannotAfford" + type="alertmodal"> + You need L$[COST] to save a photo to your inventory. You may either buy L$ or save the photo to your computer instead. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" + name="ErrorTextureCannotAfford" + type="alertmodal"> + You need L$[COST] to save a texture to your inventory. You may either buy L$ or save the photo to your computer instead. + <tag>fail</tag> + </notification> + + <notification + icon="alertmodal.tga" name="ErrorUploadingPostcard" type="alertmodal"> There was a problem sending a snapshot due to the following reason: [REASON] @@ -3523,6 +3546,19 @@ Teleport all Residents in this region home? <notification icon="alertmodal.tga" + name="ChangeObjectBonusFactor" + type="alertmodal"> + Lowering the object bonus after builds have been established in a region may cause objects to be returned or deleted. Are you sure you want to change object bonus? + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm changing object bonus factor" + name="okcancelignore" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="EstateObjectReturn" type="alertmodal"> Are you sure you want to return objects owned by [USER_NAME]? @@ -3636,6 +3672,13 @@ Can't add estate owner to estate 'Banned Resident' list. <notification icon="alertmodal.tga" + name="ProblemAddingEstateManagerBanned" + type="alertmodal"> +Unable to add banned resident to estate manager list. + </notification> + + <notification + icon="alertmodal.tga" name="CanNotChangeAppearanceUntilLoaded" type="alertmodal"> Can't change appearance until clothing and shape are loaded. @@ -4030,6 +4073,18 @@ Do you want to open your Web browser to view this content? <notification icon="alertmodal.tga" + name="SystemUIScaleFactorChanged" + type="alertmodal"> +System UI size factor has changed since last run. Do you want to open UI size adjustment settings page? + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="WebLaunchJoinNow" type="alertmodal"> Go to your [http://secondlife.com/account/ Dashboard] to manage your account? @@ -4149,6 +4204,14 @@ Leave Group? </notification> <notification + icon="notify.tga" + name="GroupDepart" + type="notify"> +You have left the group '[group_name]'. + <tag>group</tag> + </notification> + + <notification icon="alertmodal.tga" name="OwnerCannotLeaveGroup" type="alertmodal"> @@ -4160,6 +4223,17 @@ Leave Group? </notification> <notification + icon="alertmodal.tga" + name="GroupDepartError" + type="alertmodal"> + Unable to leave group. + <tag>group</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification icon="alert.tga" name="ConfirmKick" type="alert"> @@ -5281,6 +5355,17 @@ There are too many prims selected. Please select [MAX_PRIM_COUNT] or fewer prim </notification> <notification + icon="alertmodal.tga" + name="TooManyScriptsSelected" + type="alertmodal"> +Too many scripts in the objects selected. Please select fewer objects and try again + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification icon="alertmodal.tga" name="ProblemImportingEstateCovenant" type="alertmodal"> @@ -5699,6 +5784,17 @@ Warning: The 'Pay object' click action has been set, but it will only <notification icon="alertmodal.tga" + name="PaymentBlockedButtonMismatch" + type="alertmodal"> + Payment stopped: the price paid does not match any of the pay buttons set for this object. + <tag>fail</tag> + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="OpenObjectCannotCopy" type="alertmodal"> There are no items in this object that you are allowed to copy. @@ -6872,6 +6968,15 @@ This area has building disabled. You can't build or rez objects here. </notification> <notification + icon="notify.tga" + name="AutopilotCanceled" + persist="true" + type="notify"> + <unique/> +Autopilot canceled + </notification> + + <notification icon="notify.tga" name="PathfindingDirty" persist="true" @@ -6881,6 +6986,19 @@ This area has building disabled. You can't build or rez objects here. </notification> <notification + icon="notify.tga" + name="PathfindingDirtyRebake" + persist="true" + type="notify"> + <unique/> + The region has pending pathfinding changes. If you have build rights, you may rebake the region by clicking on the “Rebake region” button. + <usetemplate + name="okbutton" + yestext="Rebake region" + /> + </notification> + + <notification icon="notify.tga" name="DynamicPathfindingDisabled" persist="true" @@ -8272,8 +8390,18 @@ Appearance has been saved to XML to [PATH] <notification icon="notifytip.tga" name="AppearanceToXMLFailed" type="notifytip"> Failed to save appearance to XML. + </notification> + + <notification icon="notifytip.tga" - name="PresetNotDeleted" + name="PresetNotSaved" + type="notifytip"> +Error saving preset [NAME]. + </notification> + + <notification + icon="notifytip.tga" + name="PresetNotDeleted" type="notifytip"> Error deleting preset [NAME]. </notification> @@ -8752,23 +8880,6 @@ Click and drag anywhere on the world to rotate your view </notification> <notification - name="PopupAttempt" - icon="Popup_Caution" - type="browser"> - A pop-up was prevented from opening. - <form name="form"> - <ignore name="ignore" - control="MediaEnablePopups" - invert_control="true" - text="Enable all pop-ups"/> - <button default="true" - index="0" - name="open" - text="Open pop-up window"/> - </form> - </notification> - - <notification icon="alertmodal.tga" name="SOCKS_NOT_PERMITTED" type="alertmodal"> @@ -9750,6 +9861,14 @@ Can't move object '[OBJECT_NAME]' to <notification icon="alertmodal.tga" + name="NoParcelPermsNoObject" + type="notify"> + <tag>fail</tag> +Copy failed because you lack access to that parcel. + </notification> + + <notification + icon="alertmodal.tga" name="CantMoveObjectRegionVersion" type="notify"> <tag>fail</tag> @@ -9785,6 +9904,17 @@ You don't have permission to modify that object <notification icon="alertmodal.tga" + name="TooMuchObjectInventorySelected" + type="alertmodal"> + <tag>fail</tag> + Too many objects with large inventory are selected. Please select fewer objects and try again. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="CantEnablePhysObjContributesToNav" type="notify"> <tag>fail</tag> @@ -9882,6 +10012,22 @@ Cannot save to object contents: This would modify the attachment permissions. <notification icon="alertmodal.tga" + name="AttachmentHasTooMuchInventory" + type="notify"> + <tag>fail</tag> +Your attachments contain too much inventory to add more. + </notification> + + <notification + icon="alertmodal.tga" + name="IllegalAttachment" + type="notify"> + <tag>fail</tag> +The attachment has requested a nonexistent point on the avatar. It has been attached to the chest instead. + </notification> + + <notification + icon="alertmodal.tga" name="TooManyScripts" type="notify"> <tag>fail</tag> @@ -10920,6 +11066,14 @@ Money transfers to objects are currently disabled in this region. <notification icon="alertmodal.tga" + name="DroppedMoneyTransferRequest" + type="notify"> + <tag>fail</tag> +Unable to make payment due to system load. + </notification> + + <notification + icon="alertmodal.tga" name="CantPayNoAgent" type="notify"> <tag>fail</tag> diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 183ae2e824..ded814bbeb 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -67,7 +67,7 @@ follows="left|top" height="32" left_pad="-11" - max_length_bytes="16" + max_length_chars="16" text_pad_left="8" name="password_edit" label="Password" diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml index d1416ece82..35b80c56ab 100644 --- a/indra/newview/skins/default/xui/en/panel_login_first.xml +++ b/indra/newview/skins/default/xui/en/panel_login_first.xml @@ -124,7 +124,7 @@ width="200" height="32" left="220" - max_length_bytes="16" + max_length_chars="16" name="password_edit" label="Password" text_pad_left="8" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml index d85b778db2..42a7974316 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml @@ -9,6 +9,26 @@ name="Wearing" top="0" width="312"> +<panel.string + name="no_attachments"> + No attachments worn. + </panel.string> + <accordion + fit_parent="true" + follows="all" + height="400" + layout="topleft" + left="0" + single_expansion="true" + top="0" + name="wearables_accordion" + background_visible="true" + bg_alpha_color="DkGray2" + width="309"> + <accordion_tab + layout="topleft" + name="tab_wearables" + title="Wearables"> <wearable_items_list follows="all" height="400" @@ -20,6 +40,27 @@ top="0" width="309" worn_indication_enabled="false" /> + </accordion_tab> + <accordion_tab + layout="topleft" + name="tab_temp_attachments" + title="Temporary attachments"> + <scroll_list + draw_heading="false" + left="3" + width="309" + height="400" + follows="all" + name="temp_attachments_list"> + <scroll_list.columns + name="icon" + width="15" /> + <scroll_list.columns + name="text" + width="210" /> + </scroll_list> + </accordion_tab> + </accordion> <panel background_visible="true" follows="bottom|left|right" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 3e96160834..4a5117adac 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -138,7 +138,7 @@ initial_value="1" layout="topleft" left_pad="0" - max_val="1.5" + max_val="2.0" min_val="0.75" name="ui_scale_slider" top_pad="-14" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 0b605cf6f7..c20f9b2c51 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -273,6 +273,18 @@ name="update_willing_to_test" width="400" top_pad="5"/> + <check_box + top_delta="4" + enabled="true" + follows="left|top" + height="14" + control_name="UpdaterShowReleaseNotes" + label="Show Release Notes after update" + left_delta="0" + mouse_opaque="true" + name="update_show_release_notes" + width="400" + top_pad="5"/> <text type="string" length="1" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index ae63546082..b19c6756bc 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -54,6 +54,7 @@ LLCEFLib/CEF Version: [LLCEFLIB_VERSION] Voice Server Version: [VOICE_VERSION] </string> <string name="AboutTraffic">Packets Lost: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%)</string> + <string name="AboutTime">[month, datetime, slt] [day, datetime, slt] [year, datetime, slt] [hour, datetime, slt]:[min, datetime, slt]:[second,datetime,slt]</string> <string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string> <string name="BuildConfiguration">Build Configuration</string> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 1c77cf805e..f3d89bb866 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -30,6 +30,7 @@ import sys import os.path import shutil import errno +import json import re import tarfile import time @@ -181,9 +182,16 @@ class ViewerManifest(LLManifest): self.path("*.tga") self.end_prefix("local_assets") - # Files in the newview/ directory + # File in the newview/ directory self.path("gpu_table.txt") - # The summary.json file gets left in the build directory by newview/CMakeLists.txt. + + #summary.json. Standard with exception handling is fine. If we can't open a new file for writing, we have worse problems + summary_dict = {"Type":"viewer","Version":'.'.join(self.args['version']),"Channel":self.channel_with_pkg_suffix()} + with open(os.path.join(os.pardir,'summary.json'), 'w') as summary_handle: + json.dump(summary_dict,summary_handle) + + #we likely no longer need the test, since we will throw an exception above, but belt and suspenders and we get the + #return code for free. if not self.path2basename(os.pardir, "summary.json"): print "No summary.json file" |