diff options
author | AndreyL ProductEngine <alihatskiy@productengine.com> | 2016-08-04 21:11:32 +0300 |
---|---|---|
committer | AndreyL ProductEngine <alihatskiy@productengine.com> | 2016-08-04 21:11:32 +0300 |
commit | 6de863132756ffdf3778721ec9dd0f3a15bf464a (patch) | |
tree | 6bc5a3c515fe92cb785b7eaf9b6860e7e7110b61 /indra | |
parent | 2339e759fc2d6f36a4b9425022a22a747ec55dad (diff) | |
parent | ce3658455230cf392f45cc99f44a737ee59f13bd (diff) |
Merged in lindenlab/viewer-lynx
Diffstat (limited to 'indra')
113 files changed, 1797 insertions, 691 deletions
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/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/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..1f9869fadc 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). @@ -2262,7 +2263,7 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent) for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { LLView* viewp = *child_it; - LLFloater* floaterp = (LLFloater*)viewp; + LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp); if (floaterp->isDependent()) { // dependents are moved with their "dependee" @@ -2319,8 +2320,11 @@ void LLFloaterView::restoreAll() // make sure all subwindows aren't minimized for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { - LLFloater* floaterp = (LLFloater*)*child_it; - floaterp->setMinimized(FALSE); + LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it); + 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); @@ -2591,7 +2600,7 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) ++child_it) //loop floaters { // Examine minimized children. - LLFloater* floater = (LLFloater*)((LLView*)*child_it); + LLFloater* floater = dynamic_cast<LLFloater*>(*child_it); if(floater->isMinimized()) { LLRect r = floater->getRect(); @@ -2644,7 +2653,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting) continue; } - LLFloater* floaterp = (LLFloater*)viewp; + LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp); // Attempt to close floater. This will cause the "do you want to save" // dialogs to appear. @@ -2710,8 +2719,7 @@ BOOL LLFloaterView::allChildrenClosed() // by setting themselves invisible) for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it) { - LLView* viewp = *it; - LLFloater* floaterp = (LLFloater*)viewp; + LLFloater* floaterp = dynamic_cast<LLFloater*>(*it); if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable()) { @@ -2947,7 +2955,7 @@ void LLFloaterView::syncFloaterTabOrder() // otherwise, make sure the focused floater is in the front of the child list for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) { - LLFloater* floaterp = (LLFloater*)*child_it; + LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it); if (gFocusMgr.childHasKeyboardFocus(floaterp)) { bringToFront(floaterp, FALSE); @@ -2969,7 +2977,7 @@ LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const if (parentp == this) { - return (LLFloater*)viewp; + return dynamic_cast<LLFloater*>(viewp); } return NULL; 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..8166ef6a07 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1629,9 +1629,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..5eb5ca4f82 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -972,6 +972,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/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/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..62c3f401bf 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -588,6 +588,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/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..6ccf89eabe 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> @@ -11065,6 +11076,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> 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/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..a1d9786321 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) diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index bf181cb4ad..7069da7352 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -228,11 +228,7 @@ public: private: -#ifdef APPEARANCEBAKE_AS_IN_AIS_QUEUE void serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter); -#else - void serverAppearanceUpdateCoro(); -#endif static void debugAppearanceUpdateCOF(const LLSD& content); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b6d02ea2f8..6bc1f67e32 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3438,6 +3438,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(); } 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/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/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/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/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/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/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/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/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..639641d1c2 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -904,7 +904,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 +956,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/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 0aaed3e286..54f8fb93d0 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -3935,7 +3935,7 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) { 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; } @@ -3956,10 +3956,11 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3 S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod) { - if (mThread) + if (mThread && mesh_id.notNull()) { + LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end()) + if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) { LLSD& header = iter->second; @@ -4031,9 +4032,30 @@ void LLMeshRepository::uploadError(LLSD& args) mUploadErrorQ.push(args); } +F32 LLMeshRepository::getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value) +{ + if (mThread && mesh_id.notNull()) + { + LLMutexLock lock(mThread->mHeaderMutex); + LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); + if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + { + return getStreamingCost(iter->second, radius, bytes, bytes_visible, lod, unscaled_value); + } + } + return 0.f; +} + //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); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index d35c44397b..a762042597 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -475,6 +475,7 @@ public: static LLDeadmanTimer sQuiescentTimer; // Time-to-complete-mesh-downloads after significant events + F32 getStreamingCost(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL); static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL); LLMeshRepository(); 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/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..d0353259a5 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -94,6 +94,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,6 +145,7 @@ 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); } }; diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index d95546f11d..9957039f72 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 { @@ -134,7 +135,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 +147,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 +170,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) + { + 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 { - 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; + 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 +216,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..ba9845ef04 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); } 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/llstartup.cpp b/indra/newview/llstartup.cpp index 88fbd233b8..a2c8e7772e 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; @@ -1139,9 +1144,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 +3312,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/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/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 99a9ed1d75..f5b06fbd19 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6986,20 +6986,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 +7020,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/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..ed719ae418 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -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; } 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/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..e69a8d1d1d 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3627,10 +3627,8 @@ 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()); - - return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value); + { + return gMeshRepo.getStreamingCost(getVolume()->getParams().getSculptID(), radius, bytes, visible_bytes, mLOD, unscaled_value); } else { 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..5d05ecf127 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -12,6 +12,7 @@ <os name="Mac"> <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..44b2727671 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,11 @@ <on_click function="Wearing.Edit" /> </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..dfde38bc5f 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1150,6 +1150,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 +3539,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]? @@ -6881,6 +6910,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 +8314,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="PresetNotSaved" + type="notifytip"> +Error saving preset [NAME]. + </notification> + + <notification icon="notifytip.tga" - name="PresetNotDeleted" + name="PresetNotDeleted" type="notifytip"> Error deleting preset [NAME]. </notification> 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_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/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" |