diff --git a/.hgtags b/.hgtags index 11deee1042..5685192b0c 100755 --- a/.hgtags +++ b/.hgtags @@ -565,3 +565,4 @@ cea1632c002c065985ebea15eeeb4aac90f50545 5.0.2-release 022709ef76a331cac1ba6ef1a6da8a5e9ef63f5a 5.0.4-release b4d76b5590fdf8bab72c64442353753a527cbc44 5.0.5-release 3e5035dfd8af49bd4c0009f0a76ef46a15991a45 5.0.6-release +abcab37e1b29414ab8c03af9ca2ab489d809788a 5.0.7-release diff --git a/doc/contributions.txt b/doc/contributions.txt index 38124bd1e6..8b54217e68 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -828,6 +828,8 @@ Kitty Barnett MAINT-6153 MAINT-6154 MAINT-6568 + STORM-2149 + MAINT-7581 Kolor Fall Komiko Okamoto Korvel Noh diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index d8185aa693..184fbab57f 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -129,6 +129,7 @@ LLMotion *LLMotionRegistry::createMotion( const LLUUID &id ) //----------------------------------------------------------------------------- LLMotionController::LLMotionController() : mTimeFactor(sCurrentTimeFactor), + mUpdateFactor(1.f), // Fix impostered animation speed based on a fix by Henri Beauchamp mCharacter(NULL), mAnimTime(0.f), mPrevTimerElapsed(0.f), @@ -825,7 +826,10 @@ void LLMotionController::updateMotions(bool force_update) // Update timing info for this time step. if (!mPaused) { - F32 update_time = mAnimTime + delta_time * mTimeFactor; + // Fix impostered animation speed based on a fix by Henri Beauchamp + //F32 update_time = mAnimTime + delta_time * mTimeFactor; + F32 update_time = mAnimTime + delta_time * mTimeFactor * mUpdateFactor; + // if (use_quantum) { F32 time_interval = fmodf(update_time, mTimeStep); diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 72de331694..d449c3649c 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -154,6 +154,9 @@ public: void setTimeFactor(F32 time_factor); F32 getTimeFactor() const { return mTimeFactor; } + // Fix impostered animation speed based on a fix by Henri Beauchamp + void setUpdateFactor(F32 update_factor) { mUpdateFactor = update_factor; } + motion_list_t& getActiveMotions() { return mActiveMotions; } void incMotionCounts(S32& num_motions, S32& num_loading_motions, S32& num_loaded_motions, S32& num_active_motions, S32& num_deprecated_motions); @@ -191,6 +194,7 @@ protected: protected: F32 mTimeFactor; // 1.f for normal speed static F32 sCurrentTimeFactor; // Value to use for initialization + F32 mUpdateFactor; // Fix impostered animation speed based on a fix by Henri Beauchamp static LLMotionRegistry sRegistry; LLPoseBlender mPoseBlender; diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h index 79c89d6c92..690ebbecd8 100644 --- a/indra/llcorehttp/_httpinternal.h +++ b/indra/llcorehttp/_httpinternal.h @@ -127,9 +127,12 @@ const int HTTP_TRACE_MAX = HTTP_TRACE_CURL_BODIES; // We want to span a few windows to allow transport to slow // after onset of the throttles and then recover without a final // failure. Other systems may need other constants. -const int HTTP_RETRY_COUNT_DEFAULT = 8; +const int HTTP_RETRY_COUNT_DEFAULT = 5; const int HTTP_RETRY_COUNT_MIN = 0; const int HTTP_RETRY_COUNT_MAX = 100; +const HttpTime HTTP_RETRY_BACKOFF_MIN_DEFAULT = 1E6L; // 1 sec +const HttpTime HTTP_RETRY_BACKOFF_MAX_DEFAULT = 5E6L; // 5 sec +const HttpTime HTTP_RETRY_BACKOFF_MAX = 20E6L; // 20 sec const int HTTP_REDIRECTS_DEFAULT = 10; diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 140d01ce9b..db05a9f41d 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -142,6 +142,8 @@ HttpOpRequest::HttpOpRequest() mPolicy503Retries(0), mPolicyRetryAt(HttpTime(0)), mPolicyRetryLimit(HTTP_RETRY_COUNT_DEFAULT), + mPolicyMinRetryBackoff(HttpTime(HTTP_RETRY_BACKOFF_MIN_DEFAULT)), + mPolicyMaxRetryBackoff(HttpTime(HTTP_RETRY_BACKOFF_MAX_DEFAULT)), mCallbackSSLVerify(NULL) { // *NOTE: As members are added, retry initialization/cleanup @@ -438,6 +440,9 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id, mPolicyRetryLimit = options->getRetries(); mPolicyRetryLimit = llclamp(mPolicyRetryLimit, HTTP_RETRY_COUNT_MIN, HTTP_RETRY_COUNT_MAX); mTracing = (std::max)(mTracing, llclamp(options->getTrace(), HTTP_TRACE_MIN, HTTP_TRACE_MAX)); + + mPolicyMinRetryBackoff = llclamp(options->getMinBackoff(), HttpTime(0), HTTP_RETRY_BACKOFF_MAX); + mPolicyMaxRetryBackoff = llclamp(options->getMaxBackoff(), mPolicyMinRetryBackoff, HTTP_RETRY_BACKOFF_MAX); } } diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index 0595db043d..79ae489839 100644 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -233,6 +233,8 @@ public: int mPolicy503Retries; HttpTime mPolicyRetryAt; int mPolicyRetryLimit; + HttpTime mPolicyMinRetryBackoff; // initial delay between retries (mcs) + HttpTime mPolicyMaxRetryBackoff; }; // end class HttpOpRequest diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp index a302db8b46..885f0ed61d 100644 --- a/indra/llcorehttp/_httppolicy.cpp +++ b/indra/llcorehttp/_httppolicy.cpp @@ -152,20 +152,16 @@ void HttpPolicy::addOp(const HttpOpRequest::ptr_t &op) void HttpPolicy::retryOp(const HttpOpRequest::ptr_t &op) { - static const HttpTime retry_deltas[] = - { - 250000, // 1st retry in 0.25 S, etc... - 500000, - 1000000, - 2000000, - 5000000 // ... to every 5.0 S. - }; - static const int delta_max(int(LL_ARRAY_SIZE(retry_deltas)) - 1); static const HttpStatus error_503(503); const HttpTime now(totalTime()); const int policy_class(op->mReqPolicy); - HttpTime delta(retry_deltas[llclamp(op->mPolicyRetries, 0, delta_max)]); + + HttpTime delta_min = op->mPolicyMinRetryBackoff; + HttpTime delta_max = op->mPolicyMaxRetryBackoff; + // mPolicyRetries limited to 100 + U32 delta_factor = op->mPolicyRetries <= 10 ? 1 << op->mPolicyRetries : 1024; + HttpTime delta = llmin(delta_min * delta_factor, delta_max); bool external_delta(false); if (op->mReplyRetryAfter > 0 && op->mReplyRetryAfter < 30) diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp index aab447f2dd..df5aa52fa9 100644 --- a/indra/llcorehttp/httpoptions.cpp +++ b/indra/llcorehttp/httpoptions.cpp @@ -39,6 +39,8 @@ HttpOptions::HttpOptions() : mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT), mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT), mRetries(HTTP_RETRY_COUNT_DEFAULT), + mMinRetryBackoff(HTTP_RETRY_BACKOFF_MIN_DEFAULT), + mMaxRetryBackoff(HTTP_RETRY_BACKOFF_MAX_DEFAULT), mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT), mFollowRedirects(true), mVerifyPeer(false), @@ -81,6 +83,16 @@ void HttpOptions::setRetries(unsigned int retries) mRetries = retries; } +void HttpOptions::setMinBackoff(HttpTime delay) +{ + mMinRetryBackoff = delay; +} + +void HttpOptions::setMaxBackoff(HttpTime delay) +{ + mMaxRetryBackoff = delay; +} + void HttpOptions::setUseRetryAfter(bool use_retry) { mUseRetryAfter = use_retry; diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h index 510eaa45bb..8a6de61b04 100644 --- a/indra/llcorehttp/httpoptions.h +++ b/indra/llcorehttp/httpoptions.h @@ -101,13 +101,31 @@ public: /// Sets the number of retries on an LLCore::HTTPRequest before the /// request fails. - // Default: 8 + // Default: 5 void setRetries(unsigned int retries); unsigned int getRetries() const { return mRetries; } + /// Sets minimal delay before request retries. In microseconds. + /// HttpPolicy will increase delay from min to max with each retry + // Default: 1 000 000 mcs + void setMinBackoff(HttpTime delay); + HttpTime getMinBackoff() const + { + return mMinRetryBackoff; + } + + /// Sets maximum delay before request retries. In microseconds. + /// HttpPolicy will increase delay from min to max with each retry + // Default: 5 000 000 mcs + void setMaxBackoff(HttpTime delay); + HttpTime getMaxBackoff() const + { + return mMaxRetryBackoff; + } + // Default: true void setUseRetryAfter(bool use_retry); bool getUseRetryAfter() const @@ -166,6 +184,8 @@ protected: unsigned int mTimeout; unsigned int mTransferTimeout; unsigned int mRetries; + HttpTime mMinRetryBackoff; + HttpTime mMaxRetryBackoff; bool mUseRetryAfter; bool mFollowRedirects; bool mVerifyPeer; diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index b2fa0ed315..eb70b78a36 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -112,10 +112,10 @@ void LLPngWrapper::readDataCallback(png_structp png_ptr, png_bytep dest, png_siz void LLPngWrapper::writeDataCallback(png_structp png_ptr, png_bytep src, png_size_t length) { PngDataInfo *dataInfo = (PngDataInfo *) png_get_io_ptr(png_ptr); - if (dataInfo->mOffset + length > dataInfo->mDataSize) - { - png_error(png_ptr, "Data write error. Requested data size exceeds available data size."); - return; + if (dataInfo->mOffset + length > dataInfo->mDataSize) + { + png_error(png_ptr, "Data write error. Requested data size exceeds available data size."); + return; } U8 *dest = &dataInfo->mData[dataInfo->mOffset]; memcpy(dest, src, length); diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index c0ae04536a..9189fe1d06 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1319,7 +1319,7 @@ void LLVertexBuffer::createGLIndices(U32 size) void LLVertexBuffer::destroyGLBuffer() { - if (mGLBuffer) + if (mGLBuffer || mMappedData) { if (mMappedDataUsingVBOs) { @@ -1339,7 +1339,7 @@ void LLVertexBuffer::destroyGLBuffer() void LLVertexBuffer::destroyGLIndices() { - if (mGLIndices) + if (mGLIndices || mMappedIndexData) { if (mMappedIndexDataUsingVBOs) { diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 05735f1bfc..90bb25b6ef 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -102,6 +102,18 @@ void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) void LLCloseAllFoldersFunctor::doItem(LLFolderViewItem* item) { } +//--------------------------------------------------------------------------- + +void LLAllDescendentsPassedFilter::doFolder(LLFolderViewFolder* folder) +{ + mAllDescendentsPassedFilter &= (folder) && (folder->passedFilter()) && (folder->descendantsPassedFilter()); +} + +void LLAllDescendentsPassedFilter::doItem(LLFolderViewItem* item) +{ + mAllDescendentsPassedFilter &= (item) && (item->passedFilter()); +} + ///---------------------------------------------------------------------------- /// Class LLFolderViewScrollContainer ///---------------------------------------------------------------------------- diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index c166c97d87..60a29e6d69 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -409,6 +409,18 @@ public: virtual void doItem(LLFolderViewItem* item); }; +class LLAllDescendentsPassedFilter : public LLFolderViewFunctor +{ +public: + LLAllDescendentsPassedFilter() : mAllDescendentsPassedFilter(true) {} + /*virtual*/ ~LLAllDescendentsPassedFilter() {} + /*virtual*/ void doFolder(LLFolderViewFolder* folder); + /*virtual*/ void doItem(LLFolderViewItem* item); + bool allDescendentsPassedFilter() const { return mAllDescendentsPassedFilter; } +protected: + bool mAllDescendentsPassedFilter; +}; + // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; const U32 FIRST_SELECTED_ITEM = 0x2; diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index ae48df7c6b..92ab2ed10e 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -1277,6 +1277,11 @@ BOOL LLFolderViewFolder::needsArrange() return mLastArrangeGeneration < getRoot()->getArrangeGeneration(); } +bool LLFolderViewFolder::descendantsPassedFilter(S32 filter_generation) +{ + return getViewModelItem()->descendantsPassedFilter(filter_generation); +} + // Passes selection information on to children and record selection // information if necessary. BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL openitem, diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 62d21f1dd2..a6f23cab5e 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3353,6 +3353,7 @@ BOOL LLMenuBarGL::handleAcceleratorKey(KEY key, MASK mask) if (getHighlightedItem()) { clearHoverItem(); + LLMenuGL::setKeyboardMode(FALSE); } else { @@ -3799,10 +3800,10 @@ BOOL LLMenuHolderGL::hideMenus() { return FALSE; } + LLMenuGL::setKeyboardMode(FALSE); BOOL menu_visible = hasVisibleMenu(); if (menu_visible) { - LLMenuGL::setKeyboardMode(FALSE); // clicked off of menu, hide them all for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 5764a4e26f..598fd70c71 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -67,7 +67,8 @@ LLNotificationForm::FormIgnore::FormIgnore() : text("text"), control("control"), invert_control("invert_control", false), - save_option("save_option", false) + save_option("save_option", false), + session_only("session_only", false) {} LLNotificationForm::FormButton::FormButton() @@ -126,6 +127,7 @@ bool handleIgnoredNotification(const LLSD& payload) switch(form->getIgnoreType()) { case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE: + case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY: response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON); break; case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE: @@ -198,7 +200,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica if (!p.ignore.save_option) { - mIgnore = IGNORE_WITH_DEFAULT_RESPONSE; + mIgnore = p.ignore.session_only ? IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY : IGNORE_WITH_DEFAULT_RESPONSE; } else { @@ -427,6 +429,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par mLogToChat(p.log_to_chat), mLogToIM(p.log_to_im), mShowToast(p.show_toast), + mFadeToast(p.fade_toast), mSoundName("") { if (p.sound.isProvided() && LLUI::sSettingGroups["config"] @@ -950,6 +953,11 @@ bool LLNotification::canShowToast() const return mTemplatep->mShowToast; } +bool LLNotification::canFadeToast() const +{ + return mTemplatep->mFadeToast; +} + bool LLNotification::hasFormElements() const { return mTemplatep->mForm->getNumElements() != 0; @@ -1801,6 +1809,18 @@ bool LLNotifications::getIgnoreAllNotifications() { return mIgnoreAllNotifications; } + +void LLNotifications::setIgnored(const std::string& name, bool ignored) +{ + LLNotificationTemplatePtr templatep = getTemplate(name); + templatep->mForm->setIgnored(ignored); +} + +bool LLNotifications::getIgnored(const std::string& name) +{ + LLNotificationTemplatePtr templatep = getTemplate(name); + return (mIgnoreAllNotifications) || ( (templatep->mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO) && (templatep->mForm->getIgnored()) ); +} bool LLNotifications::isVisibleByRules(LLNotificationPtr n) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 7ec574caeb..02036e4ff6 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -180,6 +180,7 @@ public: Optional save_option; Optional control; Optional invert_control; + Optional session_only; FormIgnore(); }; @@ -234,7 +235,8 @@ public: typedef enum e_ignore_type { IGNORE_NO, - IGNORE_WITH_DEFAULT_RESPONSE, + IGNORE_WITH_DEFAULT_RESPONSE, + IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY, IGNORE_WITH_LAST_RESPONSE, IGNORE_SHOW_AGAIN } EIgnoreType; @@ -564,6 +566,7 @@ public: bool canLogToChat() const; bool canLogToIM() const; bool canShowToast() const; + bool canFadeToast() const; bool hasFormElements() const; void playSound(); @@ -969,6 +972,9 @@ public: void setIgnoreAllNotifications(bool ignore); bool getIgnoreAllNotifications(); + void setIgnored(const std::string& name, bool ignored); + bool getIgnored(const std::string& name); + bool isVisibleByRules(LLNotificationPtr pNotification); private: diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index bed29254d8..20cbc89ede 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -177,6 +177,7 @@ struct LLNotificationTemplate Optional persist, log_to_im, show_toast, + fade_toast, log_to_chat, force_urls_external; Optional functor, @@ -199,6 +200,7 @@ struct LLNotificationTemplate Params() : name("name"), persist("persist", false), + fade_toast("fade_toast", true), log_to_im("log_to_im", false), show_toast("show_toast", true), log_to_chat("log_to_chat", true), @@ -316,6 +318,7 @@ struct LLNotificationTemplate bool mLogToChat; bool mLogToIM; bool mShowToast; + bool mFadeToast; }; #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 08c3d8fb94..31490766a0 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -428,6 +428,21 @@ S32 LLScrollListCtrl::getItemCount() const return mItemList.size(); } +BOOL LLScrollListCtrl::hasSelectedItem() const +{ + item_list::iterator iter; + for (iter = mItemList.begin(); iter < mItemList.end(); ) + { + LLScrollListItem* itemp = *iter; + if (itemp && itemp->getSelected()) + { + return TRUE; + } + iter++; + } + return FALSE; +} + // virtual LLScrolListInterface function (was deleteAllItems) void LLScrollListCtrl::clearRows() { diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index c156038282..0726a1d7c5 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -206,6 +206,8 @@ public: virtual BOOL isSelected(const LLSD& value) const; + BOOL hasSelectedItem() const; + BOOL handleClick(S32 x, S32 y, MASK mask); BOOL selectFirstItem(); BOOL selectNthItem( S32 index ); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 194262d405..c4b92e95c1 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -135,6 +135,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); mEditor = LLUICtrlFactory::create (params); mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this )); + mEditor->setFocusLostCallback( boost::bind(&LLSpinCtrl::onEditorLostFocus, _1, this )); if (p.allow_digits_only) { mEditor->setPrevalidateInput(LLTextValidate::validateNonNegativeS32NoSpace); @@ -276,6 +277,31 @@ void LLSpinCtrl::onEditorGainFocus( LLFocusableElement* caller, void *userdata ) self->onFocusReceived(); } +// static +void LLSpinCtrl::onEditorLostFocus( LLFocusableElement* caller, void *userdata ) +{ + LLSpinCtrl* self = (LLSpinCtrl*) userdata; + llassert( caller == self->mEditor ); + + self->onFocusLost(); + + std::string text = self->mEditor->getText(); + + LLLocale locale(LLLocale::USER_LOCALE); + F32 val = (F32)atof(text.c_str()); + + F32 saved_val = self->getValueF32(); + if (saved_val != val && !self->mEditor->isDirty()) + { + // Editor was focused when value update arrived, string + // in editor is different from one in spin control. + // Since editor is not dirty, it won't commit, so either + // attempt to commit value from editor or revert to a more + // recent value from spin control + self->updateEditor(); + } +} + void LLSpinCtrl::setValue(const LLSD& value ) { F32 v = (F32)value.asReal(); diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h index fa46c1ccbc..e43e426532 100644 --- a/indra/llui/llspinctrl.h +++ b/indra/llui/llspinctrl.h @@ -98,6 +98,7 @@ public: void onEditorCommit(const LLSD& data); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); + static void onEditorLostFocus(LLFocusableElement* caller, void *userdata); static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); void onUpBtn(const LLSD& data); diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 16fb1ec11b..380a97d825 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -108,8 +108,13 @@ LLDir::~LLDir() std::vector LLDir::getFilesInDir(const std::string &dirname) { //Returns a vector of fullpath filenames. - - boost::filesystem::path p (dirname); + +#ifdef LL_WINDOWS // or BOOST_WINDOWS_API + boost::filesystem::path p(utf8str_to_utf16str(dirname)); +#else + boost::filesystem::path p(dirname); +#endif + std::vector v; if (exists(p)) @@ -199,7 +204,12 @@ U32 LLDir::deleteDirAndContents(const std::string& dir_name) try { - boost::filesystem::path dir_path(dir_name); +#ifdef LL_WINDOWS // or BOOST_WINDOWS_API + boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name)); +#else + boost::filesystem::path dir_path(dir_name); +#endif + if (boost::filesystem::exists (dir_path)) { if (!boost::filesystem::is_empty (dir_path)) diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp index f56ad6346a..3eb64e69d9 100644 --- a/indra/llvfs/lldiriterator.cpp +++ b/indra/llvfs/lldiriterator.cpp @@ -51,16 +51,11 @@ private: LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) : mIsValid(false) { - // Unicode path on Windows need some extra handling - - // fs::path dir_path(dirname); -#ifdef LL_WINDOWS - fs::path dir_path( utf8str_to_utf16str(dirname) ); +#ifdef LL_WINDOWS // or BOOST_WINDOWS_API + fs::path dir_path(utf8str_to_utf16str(dirname)); #else fs::path dir_path(dirname); -#endif - - // +#endif bool is_dir = false; diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index f05d768ebe..135fed5272 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -35,6 +35,7 @@ #undef INITGUID #include +#include #include @@ -206,6 +207,160 @@ HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam ) return E_FAIL; } +//Getting the version of graphics controller driver via WMI +std::string LLDXHardware::getDriverVersionWMI() +{ + std::string mDriverVersion; + HRESULT hrCoInitialize = S_OK; + HRESULT hres; + hrCoInitialize = CoInitialize(0); + IWbemLocator *pLoc = NULL; + + hres = CoCreateInstance( + CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID *)&pLoc); + + if (FAILED(hres)) + { + LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hres << LL_ENDL; + return std::string(); // Program has failed. + } + + IWbemServices *pSvc = NULL; + + // Connect to the root\cimv2 namespace with + // the current user and obtain pointer pSvc + // to make IWbemServices calls. + hres = pLoc->ConnectServer( + _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace + NULL, // User name. NULL = current user + NULL, // User password. NULL = current + 0, // Locale. NULL indicates current + NULL, // Security flags. + 0, // Authority (e.g. Kerberos) + 0, // Context object + &pSvc // pointer to IWbemServices proxy + ); + + if (FAILED(hres)) + { + LL_WARNS("AppInit") << "Could not connect. Error code = 0x" << hres << LL_ENDL; + pLoc->Release(); + CoUninitialize(); + return std::string(); // Program has failed. + } + + LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL; + + // Set security levels on the proxy ------------------------- + hres = CoSetProxyBlanket( + pSvc, // Indicates the proxy to set + RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx + RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx + NULL, // Server principal name + RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx + RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx + NULL, // client identity + EOAC_NONE // proxy capabilities + ); + + if (FAILED(hres)) + { + LL_WARNS("AppInit") << "Could not set proxy blanket. Error code = 0x" << hres << LL_ENDL; + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return std::string(); // Program has failed. + } + IEnumWbemClassObject* pEnumerator = NULL; + + // Get the data from the query + ULONG uReturn = 0; + hres = pSvc->ExecQuery( + bstr_t("WQL"), + bstr_t("SELECT * FROM Win32_VideoController"), //Consider using Availability to filter out disabled controllers + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, + &pEnumerator); + + if (FAILED(hres)) + { + LL_WARNS("AppInit") << "Query for operating system name failed." << " Error code = 0x" << hres << LL_ENDL; + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return std::string(); // Program has failed. + } + + while (pEnumerator) + { + IWbemClassObject *pclsObj = NULL; + HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, + &pclsObj, &uReturn); + + if (0 == uReturn) + { + break; // If quantity less then 1. + } + + VARIANT vtProp; + + // Get the value of the Name property + hr = pclsObj->Get(L"DriverVersion", 0, &vtProp, 0, 0); + + if (FAILED(hr)) + { + LL_WARNS("AppInit") << "Query for name property failed." << " Error code = 0x" << hr << LL_ENDL; + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return std::string(); // Program has failed. + } + + // use characters in the returned driver version + BSTR driverVersion(vtProp.bstrVal); + + //convert BSTR to std::string + std::wstring ws(driverVersion, SysStringLen(driverVersion)); + std::string str(ws.begin(), ws.end()); + LL_INFOS("AppInit") << " DriverVersion : " << str << LL_ENDL; + + if (mDriverVersion.empty()) + { + mDriverVersion = str; + } + else if (mDriverVersion != str) + { + LL_WARNS("DriverVersion") << "Different versions of drivers. Version of second driver : " << str << LL_ENDL; + } + + VariantClear(&vtProp); + pclsObj->Release(); + } + + // Cleanup + // ======== + if (pSvc) + { + pSvc->Release(); + } + if (pLoc) + { + pLoc->Release(); + } + if (pEnumerator) + { + pEnumerator->Release(); + } + if (SUCCEEDED(hrCoInitialize)) + { + CoUninitialize(); + } + return mDriverVersion; +} + void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize) { HRESULT hr; diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h index 066227819d..17c60ce124 100644 --- a/indra/llwindow/lldxhardware.h +++ b/indra/llwindow/lldxhardware.h @@ -91,6 +91,8 @@ public: BOOL getInfo(BOOL vram_only, bool disable_wmi); // + std::string getDriverVersionWMI(); + S32 getVRAM() const { return mVRAM; } LLSD getDisplayInfo(); diff --git a/indra/lscript/README b/indra/lscript/README deleted file mode 100644 index 816ddebdbe..0000000000 --- a/indra/lscript/README +++ /dev/null @@ -1,34 +0,0 @@ -We no longer use lscript in Firestorm. legacy LSO compilation is no longer used in -Second Life or OpenSim, and this removes the dependency on Bison for building along -with continued compatibility problems with the build system (OSX 10.8, Opensuse 12.3, etc) - -This directory is not used as of Rev 34229. - --- -Cinder - -Please enjoy this ascii-art. - - ____ - \%%%%%%;. - \%%%%%%%%;.. - .\. (%%%%%%%%%%%%;. - .;%%%;. %%%%%%%%%%%%%%%%%;. - %%%%%%%%; %%%%%%%%%%%%%%%%%%%%%;. - %%%%%%%%%)__(%%%%%%%%%%%%%%%%%%%%%%%%;. - ;%%%%%% /%%%%%\ %%%%%%%%%%%%%%%%%%%%%%%; - \%% /%/'''\%%%\ %%%%%%%%%%%%%%%%%%%%%%%; - '%%%%%%%\. \%%|/%%%%%%%%%%%%%%%%%%%%%%; %% - .;%%%%%%%%%%\|%%%%%%%%%%%%%%%%%%%%%%%%%% %%% - (%CCC%%%%CCC%\%%%%%%%%%%%%%%%%%%%%%%%%%/ %%%% - %% !/ \%%%%%%%%%%%%%%%%%%%%%%/ %%%%%% - .% %%% \%%%%%%%%%%%%%/'%%%%%%%%% - .__\\/__. .%%% o o %%%% %%%%%%%%%%%/'%%%%%%%%%%% - \.;%%%%%%%%%;.'%% %%%% ,%%%%%%%%%%%%%%%%%%%%%%% - %%%%%%%%%%%%%%%/ %___.!. /%%%% ,%%%%%%%% \%%%%%%%%%%%%% - \%% %%% %%/ %%%%%%\ /%%%% ,%%%%%%%%% |%%%%%%%%%%%%% -/%% %%% %% %%%%%%%)?**&%%%% ,%%%%%%%%%%; |%%%%%%%%%%%%% - %% %%% %% %%%%%%%%%%%%%/ ,%%%%%%%%%%%/ /%%%%%%%%%%%%%% -/%%% %%%%% %%% %%%%%%%;/',;/%%%%%%%%%;;../%%%%%%%%%%%%%%%%% - %%%%%%/'''\%%%%%% ='''\\ \%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //'' ''\\ diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 69321b5280..8671064cc0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7811,12 +7811,12 @@ Type F32 Value - 10.0 + 40.0 LoginSRVPump Comment - Name of the message pump that handles SRV request + Name of the message pump that handles SRV request (deprecated) Persist 0 Type diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp index 8d5c27f3c2..8c7bc09820 100644 --- a/indra/newview/fschathistory.cpp +++ b/indra/newview/fschathistory.cpp @@ -40,18 +40,20 @@ #include "llpanel.h" #include "lluictrlfactory.h" #include "llscrollcontainer.h" -#include "llavatariconctrl.h" -#include "llcallingcard.h" //for LLAvatarTracker +#include "llagent.h" #include "llagentdata.h" #include "llavataractions.h" +#include "llavatariconctrl.h" +#include "llcallingcard.h" //for LLAvatarTracker +#include "llgroupactions.h" +#include "llgroupmgr.h" +#include "llspeakers.h" //for LLIMSpeakerMgr #include "lltrans.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" -#include "llmutelist.h" #include "llstylemap.h" #include "llslurl.h" #include "lllayoutstack.h" -#include "llagent.h" #include "llnotificationsutil.h" #include "lltoastnotifypanel.h" #include "lltooltip.h" @@ -202,6 +204,161 @@ public: return false; } + void banGroupMember(const LLUUID& participant_uuid) + { + LLUUID group_uuid = mSessionID; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if (!gdatap) + { + // Not a group + return; + } + + gdatap->banMemberById(participant_uuid); + } + + bool canBanInGroup() + { + LLUUID group_uuid = mSessionID; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if (!gdatap) + { + // Not a group + return false; + } + + if (gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) + && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS)) + { + return true; + } + + return false; + } + + bool canBanGroupMember(const LLUUID& participant_uuid) + { + LLUUID group_uuid = mSessionID; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if (!gdatap) + { + // Not a group + return false; + } + + if (gdatap->mPendingBanRequest) + { + return false; + } + + if (gAgentID == getAvatarId()) + { + //Don't ban self + return false; + } + + if (gdatap->isRoleMemberDataComplete()) + { + if (gdatap->mMembers.size()) + { + LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(participant_uuid); + if (mi != gdatap->mMembers.end()) + { + LLGroupMemberData* member_data = (*mi).second; + // Is the member an owner? + if (member_data && member_data->isInRole(gdatap->mOwnerRole)) + { + return false; + } + + if (gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) + && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS)) + { + return true; + } + } + } + } + + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(participant_uuid).get(); + + if (speakerp + && gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) + && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS)) + { + return true; + } + } + + return false; + } + + bool isGroupModerator() + { + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (!speaker_mgr) + { + LL_WARNS() << "Speaker manager is missing" << LL_ENDL; + return false; + } + + // Is session a group call/chat? + if(gAgent.isInGroup(mSessionID)) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(gAgentID).get(); + + // Is agent a moderator? + return speakerp && speakerp->mIsModerator; + } + + return false; + } + + bool canModerate(const std::string& userdata) + { + // only group moderators can perform actions related to this "enable callback" + if (!isGroupModerator() || gAgentID == getAvatarId()) + { + return false; + } + + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (!speaker_mgr) + { + return false; + } + + LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get(); + if (!speakerp) + { + return false; + } + + bool voice_channel = speakerp->isInVoiceChannel(); + + if ("can_moderate_voice" == userdata) + { + return voice_channel; + } + else if ("can_mute" == userdata) + { + return voice_channel && (speakerp->mStatus != LLSpeaker::STATUS_MUTED); + } + else if ("can_unmute" == userdata) + { + return speakerp->mStatus == LLSpeaker::STATUS_MUTED; + } + else if ("can_allow_text_chat" == userdata) + { + return true; + } + + return false; + } + void onAvatarIconContextMenuItemClicked(const LLSD& userdata) { std::string level = userdata.asString(); @@ -280,11 +437,36 @@ public: } else if(level == "block_unblock") { - mute(getAvatarId(), LLMute::flagVoiceChat); + LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagVoiceChat); } else if(level == "mute_unmute") { - mute(getAvatarId(), LLMute::flagTextChat); + LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagTextChat); + } + else if(level == "toggle_allow_text_chat") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + speaker_mgr->toggleAllowTextChat(getAvatarId()); + } + else if(level == "group_mute") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->moderateVoiceParticipant(getAvatarId(), false); + } + } + else if(level == "group_unmute") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->moderateVoiceParticipant(getAvatarId(), true); + } + } + else if(level == "ban_member") + { + banGroupMember(getAvatarId()); } } @@ -300,24 +482,69 @@ public: { return LLMuteList::getInstance()->isMuted(getAvatarId(), LLMute::flagTextChat); } + else if (level == "is_allowed_text_chat") + { + if (gAgent.isInGroup(mSessionID)) + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + const LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()); + + if (NULL != speakerp) + { + return !speakerp->mModeratorMutedText; + } + } + return false; + } return false; } - void mute(const LLUUID& participant_id, U32 flags) + bool onAvatarIconContextMenuItemEnabled(const LLSD& userdata) { - BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags); - LLAvatarName av_name; - LLAvatarNameCache::get(participant_id, &av_name); - LLMute mute(participant_id, av_name.getUserName(), LLMute::AGENT); + std::string level = userdata.asString(); - if (!is_muted) + if (level == "can_allow_text_chat" || level == "can_mute" || level == "can_unmute") { - LLMuteList::getInstance()->add(mute, flags); + return canModerate(userdata); } - else + else if (level == "can_ban_member") { - LLMuteList::getInstance()->remove(mute, flags); + return canBanGroupMember(getAvatarId()); } + return false; + } + + bool onAvatarIconContextMenuItemVisible(const LLSD& userdata) + { + std::string level = userdata.asString(); + + if (level == "show_mute") + { + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get(); + if (speakerp) + { + return speakerp->isInVoiceChannel() && speakerp->mStatus != LLSpeaker::STATUS_MUTED; + } + } + return false; + } + else if (level == "show_unmute") + { + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get(); + if (speakerp) + { + return speakerp->mStatus == LLSpeaker::STATUS_MUTED; + } + } + return false; + } + return false; } BOOL postBuild() @@ -327,6 +554,8 @@ public: registrar.add("AvatarIcon.Action", boost::bind(&FSChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); registrar_enable.add("AvatarIcon.Check", boost::bind(&FSChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); + registrar_enable.add("AvatarIcon.Enable", boost::bind(&FSChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); + registrar_enable.add("AvatarIcon.Visible", boost::bind(&FSChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); registrar.add("ObjectIcon.Action", boost::bind(&FSChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); registrar_enable.add("ObjectIcon.Visible", boost::bind(&FSChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); @@ -691,9 +920,14 @@ protected: if(menu) { bool is_friend = LLAvatarActions::isFriend(mAvatarID); + bool is_group_session = gAgent.isInGroup(mSessionID); menu->setItemEnabled("Add Friend", !is_friend); menu->setItemEnabled("Remove Friend", is_friend); + menu->setItemVisible("Moderator Options Separator", is_group_session && isGroupModerator()); + menu->setItemVisible("Moderator Options", is_group_session && isGroupModerator()); + menu->setItemVisible("Group Ban Separator", is_group_session && canBanInGroup()); + menu->setItemVisible("BanMember", is_group_session && canBanInGroup()); if(gAgentID == mAvatarID) { diff --git a/indra/newview/installers/windows/lang_pt-br.nsi b/indra/newview/installers/windows/lang_pt-br.nsi index 8280bfb396..5d157acfc3 100644 Binary files a/indra/newview/installers/windows/lang_pt-br.nsi and b/indra/newview/installers/windows/lang_pt-br.nsi differ diff --git a/indra/newview/installers/windows/lang_ru.nsi b/indra/newview/installers/windows/lang_ru.nsi index de2ea7a0fa..4520327b3a 100644 Binary files a/indra/newview/installers/windows/lang_ru.nsi and b/indra/newview/installers/windows/lang_ru.nsi differ diff --git a/indra/newview/installers/windows/lang_tr.nsi b/indra/newview/installers/windows/lang_tr.nsi index 16b075d409..76730babc6 100644 Binary files a/indra/newview/installers/windows/lang_tr.nsi and b/indra/newview/installers/windows/lang_tr.nsi differ diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi index 80a5ff1382..022236a9c5 100644 Binary files a/indra/newview/installers/windows/lang_zh.nsi and b/indra/newview/installers/windows/lang_zh.nsi differ diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index fca287e2ec..1b95a32a58 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -399,6 +399,40 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { status = LLCore::HttpStatus(HTTP_INTERNAL_ERROR, "Malformed response contents"); } + else if (status.getType() == 410) //GONE + { + // Item does not exist or was already deleted from server. + // parent folder is out of sync + if (type == REMOVECATEGORY) + { + LLViewerInventoryCategory *cat = gInventory.getCategory(targetId); + if (cat) + { + LL_WARNS("Inventory") << "Purge failed for '" << cat->getName() + << "' local version:" << cat->getVersion() + << " since folder no longer exists at server. Descendent count: server == " << cat->getDescendentCount() + << ", viewer == " << cat->getViewerDescendentCount() + << LL_ENDL; + gInventory.fetchDescendentsOf(cat->getParentUUID()); + // Note: don't delete folder here - contained items will be deparented (or deleted) + // and since we are clearly out of sync we can't be sure we won't get rid of something we need. + // For example folder could have been moved or renamed with items intact, let it fetch first. + } + } + else if (type == REMOVEITEM) + { + LLViewerInventoryItem *item = gInventory.getItem(targetId); + if (item) + { + LL_WARNS("Inventory") << "Purge failed for '" << item->getName() + << "' since item no longer exists at server." << LL_ENDL; + gInventory.fetchDescendentsOf(item->getParentUUID()); + // since item not on the server and exists at viewer, so it needs an update at the least, + // so delete it, in worst case item will be refetched with new params. + gInventory.onObjectDeletedFromServer(targetId); + } + } + } LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL; LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; } @@ -1000,7 +1034,16 @@ void AISUpdate::doUpdate() // 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); + if (version != LLViewerInventoryCategory::VERSION_UNKNOWN) + { + cat->setVersion(version); + } + else + { + // We do not account for update if version is UNKNOWN, so we shouldn't rise version + // either or viewer will get stuck on descendants count -1, try to refetch folder instead + cat->fetch(); + } } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5f8cb3cafd..797c495936 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3772,10 +3772,19 @@ LLSD LLAppViewer::getViewerInfo() const info["GRAPHICS_CARD"] = (const char*)(glGetString(GL_RENDERER)); #if LL_WINDOWS - LLSD driver_info = gDXHardware.getDisplayInfo(); - if (driver_info.has("DriverVersion")) + std::string drvinfo = gDXHardware.getDriverVersionWMI(); + if (!drvinfo.empty()) { - info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"]; + info["GRAPHICS_DRIVER_VERSION"] = drvinfo; + } + else + { + LL_WARNS("Driver version")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL; + LLSD driver_info = gDXHardware.getDisplayInfo(); + if (driver_info.has("DriverVersion")) + { + info["GRAPHICS_DRIVER_VERSION"] = driver_info["DriverVersion"]; + } } #endif diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 009df1d75c..729c889d33 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -1243,7 +1243,7 @@ void LLAvatarActions::toggleBlock(const LLUUID& id) } // static -void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +void LLAvatarActions::toggleMute(const LLUUID& id, U32 flags) { LLAvatarName av_name; LLAvatarNameCache::get(id, &av_name); @@ -1254,14 +1254,20 @@ void LLAvatarActions::toggleMuteVoice(const LLUUID& id) LLMute mute(id, av_name.getUserName(), LLMute::AGENT); if (!is_muted) { - mute_list->add(mute, LLMute::flagVoiceChat); + mute_list->add(mute, flags); } else { - mute_list->remove(mute, LLMute::flagVoiceChat); + mute_list->remove(mute, flags); } } +// static +void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +{ + toggleMute(id, LLMute::flagVoiceChat); +} + // static bool LLAvatarActions::canOfferTeleport(const LLUUID& id) { diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 7b995fc65c..22cee1d53e 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -140,6 +140,11 @@ public: */ static void toggleBlock(const LLUUID& id); + /** + * Mute/unmute avatar. + */ + static void toggleMute(const LLUUID& id, U32 flags); + /** * Block/unblock the avatar voice. */ diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 034aaf4526..ceb90084cc 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -40,10 +40,14 @@ #include "llpanel.h" #include "lluictrlfactory.h" #include "llscrollcontainer.h" -#include "llavatariconctrl.h" -#include "llcallingcard.h" //for LLAvatarTracker +#include "llagent.h" #include "llagentdata.h" #include "llavataractions.h" +#include "llavatariconctrl.h" +#include "llcallingcard.h" //for LLAvatarTracker +#include "llgroupactions.h" +#include "llgroupmgr.h" +#include "llspeakers.h" //for LLIMSpeakerMgr #include "lltrans.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" @@ -51,7 +55,6 @@ #include "llstylemap.h" #include "llslurl.h" #include "lllayoutstack.h" -#include "llagent.h" #include "llnotificationsutil.h" #include "lltoastnotifypanel.h" #include "lltooltip.h" @@ -63,7 +66,6 @@ #include "llurlaction.h" #include "llviewercontrol.h" #include "llviewerobjectlist.h" -#include "llmutelist.h" // [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) #include "rlvcommon.h" // [/RLVa:KB] @@ -200,6 +202,161 @@ public: return false; } + void banGroupMember(const LLUUID& participant_uuid) + { + LLUUID group_uuid = mSessionID; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if (!gdatap) + { + // Not a group + return; + } + + gdatap->banMemberById(participant_uuid); + } + + bool canBanInGroup() + { + LLUUID group_uuid = mSessionID; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if (!gdatap) + { + // Not a group + return false; + } + + if (gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) + && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS)) + { + return true; + } + + return false; + } + + bool canBanGroupMember(const LLUUID& participant_uuid) + { + LLUUID group_uuid = mSessionID; + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if (!gdatap) + { + // Not a group + return false; + } + + if (gdatap->mPendingBanRequest) + { + return false; + } + + if (gAgentID == getAvatarId()) + { + //Don't ban self + return false; + } + + if (gdatap->isRoleMemberDataComplete()) + { + if (gdatap->mMembers.size()) + { + LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(participant_uuid); + if (mi != gdatap->mMembers.end()) + { + LLGroupMemberData* member_data = (*mi).second; + // Is the member an owner? + if (member_data && member_data->isInRole(gdatap->mOwnerRole)) + { + return false; + } + + if (gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) + && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS)) + { + return true; + } + } + } + } + + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(participant_uuid).get(); + + if (speakerp + && gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) + && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS)) + { + return true; + } + } + + return false; + } + + bool isGroupModerator() + { + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (!speaker_mgr) + { + LL_WARNS() << "Speaker manager is missing" << LL_ENDL; + return false; + } + + // Is session a group call/chat? + if(gAgent.isInGroup(mSessionID)) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(gAgentID).get(); + + // Is agent a moderator? + return speakerp && speakerp->mIsModerator; + } + + return false; + } + + bool canModerate(const std::string& userdata) + { + // only group moderators can perform actions related to this "enable callback" + if (!isGroupModerator() || gAgentID == getAvatarId()) + { + return false; + } + + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (!speaker_mgr) + { + return false; + } + + LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get(); + if (!speakerp) + { + return false; + } + + bool voice_channel = speakerp->isInVoiceChannel(); + + if ("can_moderate_voice" == userdata) + { + return voice_channel; + } + else if ("can_mute" == userdata) + { + return voice_channel && (speakerp->mStatus != LLSpeaker::STATUS_MUTED); + } + else if ("can_unmute" == userdata) + { + return speakerp->mStatus == LLSpeaker::STATUS_MUTED; + } + else if ("can_allow_text_chat" == userdata) + { + return true; + } + + return false; + } + void onAvatarIconContextMenuItemClicked(const LLSD& userdata) { std::string level = userdata.asString(); @@ -258,11 +415,36 @@ public: } else if(level == "block_unblock") { - mute(getAvatarId(), LLMute::flagVoiceChat); + LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagVoiceChat); } else if(level == "mute_unmute") { - mute(getAvatarId(), LLMute::flagTextChat); + LLAvatarActions::toggleMute(getAvatarId(), LLMute::flagTextChat); + } + else if(level == "toggle_allow_text_chat") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + speaker_mgr->toggleAllowTextChat(getAvatarId()); + } + else if(level == "group_mute") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->moderateVoiceParticipant(getAvatarId(), false); + } + } + else if(level == "group_unmute") + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + speaker_mgr->moderateVoiceParticipant(getAvatarId(), true); + } + } + else if(level == "ban_member") + { + banGroupMember(getAvatarId()); } } @@ -278,24 +460,71 @@ public: { return LLMuteList::getInstance()->isMuted(getAvatarId(), LLMute::flagTextChat); } + else if (level == "is_allowed_text_chat") + { + if (gAgent.isInGroup(mSessionID)) + { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if(speaker_mgr) + { + const LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()); + if (NULL != speakerp) + { + return !speakerp->mModeratorMutedText; + } + } + } + return false; + } return false; } - void mute(const LLUUID& participant_id, U32 flags) + bool onAvatarIconContextMenuItemEnabled(const LLSD& userdata) { - BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags); - LLAvatarName av_name; - LLAvatarNameCache::get(participant_id, &av_name); - LLMute mute(participant_id, av_name.getUserName(), LLMute::AGENT); + std::string level = userdata.asString(); - if (!is_muted) + if (level == "can_allow_text_chat" || level == "can_mute" || level == "can_unmute") { - LLMuteList::getInstance()->add(mute, flags); + return canModerate(userdata); } - else + else if (level == "can_ban_member") { - LLMuteList::getInstance()->remove(mute, flags); + return canBanGroupMember(getAvatarId()); } + return false; + } + + bool onAvatarIconContextMenuItemVisible(const LLSD& userdata) + { + std::string level = userdata.asString(); + + if (level == "show_mute") + { + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get(); + if (speakerp) + { + return speakerp->isInVoiceChannel() && speakerp->mStatus != LLSpeaker::STATUS_MUTED; + } + } + return false; + } + else if (level == "show_unmute") + { + LLSpeakerMgr * speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) + { + LLSpeaker * speakerp = speaker_mgr->findSpeaker(getAvatarId()).get(); + if (speakerp) + { + return speakerp->mStatus == LLSpeaker::STATUS_MUTED; + } + } + return false; + } + return false; } BOOL postBuild() @@ -305,6 +534,8 @@ public: registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); + registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); + registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); @@ -613,9 +844,14 @@ protected: if(menu) { bool is_friend = LLAvatarActions::isFriend(mAvatarID); + bool is_group_session = gAgent.isInGroup(mSessionID); menu->setItemEnabled("Add Friend", !is_friend); menu->setItemEnabled("Remove Friend", is_friend); + menu->setItemVisible("Moderator Options Separator", is_group_session && isGroupModerator()); + menu->setItemVisible("Moderator Options", is_group_session && isGroupModerator()); + menu->setItemVisible("Group Ban Separator", is_group_session && canBanInGroup()); + menu->setItemVisible("BanMember", is_group_session && canBanInGroup()); if(gAgentID == mAvatarID) { diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 7e9f9e0de5..0b938b79e2 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1151,11 +1151,11 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec } else if ("block_unblock" == command) { - toggleMute(userID, LLMute::flagVoiceChat); + LLAvatarActions::toggleMute(userID, LLMute::flagVoiceChat); } else if ("mute_unmute" == command) { - toggleMute(userID, LLMute::flagTextChat); + LLAvatarActions::toggleMute(userID, LLMute::flagTextChat); } else if ("selected" == command || "mute_all" == command || "unmute_all" == command) { @@ -2097,24 +2097,6 @@ void LLFloaterIMContainer::toggleAllowTextChat(const LLUUID& participant_uuid) } } -void LLFloaterIMContainer::toggleMute(const LLUUID& participant_id, U32 flags) -{ - BOOL is_muted = LLMuteList::getInstance()->isMuted(participant_id, flags); - - LLAvatarName av_name; - LLAvatarNameCache::get(participant_id, &av_name); - LLMute mute(participant_id, av_name.getUserName(), LLMute::AGENT); - - if (!is_muted) - { - LLMuteList::getInstance()->add(mute, flags); - } - else - { - LLMuteList::getInstance()->remove(mute, flags); - } -} - void LLFloaterIMContainer::openNearbyChat() { // If there's only one conversation in the container and that conversation is the nearby chat diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 6b62ff2af5..4a0afaadc9 100644 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -178,7 +178,6 @@ private: void moderateVoiceAllParticipants(bool unmute); void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); void toggleAllowTextChat(const LLUUID& participant_uuid); - void toggleMute(const LLUUID& participant_id, U32 flags); void banSelectedMember(const LLUUID& participant_uuid); void openNearbyChat(); bool isParticipantListExpanded(); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 548ed49df7..2ab1b33b65 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -97,6 +97,10 @@ static LLChatTypeTrigger sChatTypeTriggers[] = { { "/shout" , CHAT_TYPE_SHOUT} }; +bool cb_do_nothing() +{ + return false; +} LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd) : LLFloaterIMSessionTab(LLSD(LLUUID::null)), @@ -107,6 +111,12 @@ LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd) mIsP2PChat = false; mIsNearbyChat = true; mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); + + // Required by LLFloaterIMSessionTab::mGearBtn + // But nearby floater has no 'per agent' menu items, + mEnableCallbackRegistrar.add("Avatar.EnableGearItem", boost::bind(&cb_do_nothing)); + mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&cb_do_nothing)); + mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&cb_do_nothing)); } //static diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 3d52f44e39..492d64102e 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -48,6 +48,10 @@ const F32 REFRESH_INTERVAL = 1.0f; +void cb_group_do_nothing() +{ +} + LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) : LLTransientDockableFloater(NULL, false, session_id), mIsP2PChat(false), @@ -84,6 +88,7 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLFloaterIMSessionTab::checkContextMenuItem, this, _2)); mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); + mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp index 3f80d6f1a4..10cce3bd22 100644 --- a/indra/newview/llfloaterlinkreplace.cpp +++ b/indra/newview/llfloaterlinkreplace.cpp @@ -41,16 +41,13 @@ LLFloaterLinkReplace::LLFloaterLinkReplace(const LLSD& key) mRemainingItems(0), mSourceUUID(LLUUID::null), mTargetUUID(LLUUID::null), - mInstance(NULL), mBatchSize(gSavedSettings.getU32("LinkReplaceBatchSize")) { mEventTimer.stop(); - mInstance = this; } LLFloaterLinkReplace::~LLFloaterLinkReplace() { - mInstance = NULL; } BOOL LLFloaterLinkReplace::postBuild() @@ -180,11 +177,9 @@ void LLFloaterLinkReplace::onStartClicked() } } -void LLFloaterLinkReplace::linkCreatedCallback(const LLUUID& old_item_id, - const LLUUID& target_item_id, - bool needs_wearable_ordering_update, - bool needs_description_update, - const LLUUID& outfit_folder_id) +// static +void LLFloaterLinkReplace::linkCreatedCallback(LLHandle floater_handle, const LLUUID& old_item_id, const LLUUID& target_item_id, + bool needs_wearable_ordering_update, bool needs_description_update, const LLUUID& outfit_folder_id) { LL_DEBUGS() << "Inventory link replace:" << LL_NEWLINE << " - old_item_id = " << old_item_id.asString() << LL_NEWLINE @@ -239,20 +234,21 @@ void LLFloaterLinkReplace::linkCreatedCallback(const LLUUID& old_item_id, outfit_update_folder = outfit_folder_id; } - LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::itemRemovedCallback, this, outfit_update_folder)); + LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::itemRemovedCallback, floater_handle, outfit_update_folder)); remove_inventory_object(old_item_id, cb); } -void LLFloaterLinkReplace::itemRemovedCallback(const LLUUID& outfit_folder_id) +// static +void LLFloaterLinkReplace::itemRemovedCallback(LLHandle floater_handle, const LLUUID& outfit_folder_id) { if (outfit_folder_id.notNull()) { LLAppearanceMgr::getInstance()->updateClothingOrderingInfo(outfit_folder_id); } - if (mInstance) + if (!floater_handle.isDead()) { - decreaseOpenItemCount(); + floater_handle.get()->decreaseOpenItemCount(); } } @@ -324,7 +320,7 @@ void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items) LLInventoryObject::const_object_list_t obj_array; obj_array.push_back(LLConstPointer(target_item)); LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(&LLFloaterLinkReplace::linkCreatedCallback, - this, + getDerivedHandle(), source_item->getUUID(), target_item->getUUID(), needs_wearable_ordering_update, diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h index 377dd1d450..dd5c301206 100644 --- a/indra/newview/llfloaterlinkreplace.h +++ b/indra/newview/llfloaterlinkreplace.h @@ -98,12 +98,9 @@ private: void updateFoundLinks(); void processBatch(LLInventoryModel::item_array_t items); - void linkCreatedCallback(const LLUUID& old_item_id, - const LLUUID& target_item_id, - bool needs_wearable_ordering_update, - bool needs_description_update, - const LLUUID& outfit_folder_id); - void itemRemovedCallback(const LLUUID& outfit_folder_id); + static void linkCreatedCallback(LLHandle floater_handle, const LLUUID& old_item_id, const LLUUID& target_item_id, + bool needs_wearable_ordering_update, bool needs_description_update, const LLUUID& outfit_folder_id); + static void itemRemovedCallback(LLHandle floater_handle, const LLUUID& outfit_folder_id); void onSourceItemDrop(const LLUUID& source_item_id); void onTargetItemDrop(const LLUUID& target_item_id); @@ -120,8 +117,6 @@ private: U32 mBatchSize; LLInventoryModel::item_array_t mRemainingInventoryItems; - - LLFloaterLinkReplace* mInstance; }; #endif // LL_FLOATERLINKREPLACE_H diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 5f0587a286..21df769d0c 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -112,24 +112,16 @@ BOOL LLFloaterScriptLimits::postBuild() } // contruct the panels - std::string land_url = gAgent.getRegion()->getCapability("LandResources"); - if (!land_url.empty()) - { - LLPanelScriptLimitsRegionMemory* panel_memory; - panel_memory = new LLPanelScriptLimitsRegionMemory; - mInfoPanels.push_back(panel_memory); - panel_memory->buildFromFile( "panel_script_limits_region_memory.xml"); - mTab->addTabPanel(panel_memory); - } - - std::string attachment_url = gAgent.getRegion()->getCapability("AttachmentResources"); - if (!attachment_url.empty()) - { - LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment; - mInfoPanels.push_back(panel_attachments); - panel_attachments->buildFromFile("panel_script_limits_my_avatar.xml"); - mTab->addTabPanel(panel_attachments); - } + LLPanelScriptLimitsRegionMemory* panel_memory = new LLPanelScriptLimitsRegionMemory; + mInfoPanels.push_back(panel_memory); + panel_memory->buildFromFile( "panel_script_limits_region_memory.xml"); + mTab->addTabPanel(panel_memory); + + LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment; + mInfoPanels.push_back(panel_attachments); + panel_attachments->buildFromFile("panel_script_limits_my_avatar.xml"); + mTab->addTabPanel(panel_attachments); + if(mInfoPanels.size() > 0) { @@ -195,6 +187,8 @@ LLPanelScriptLimitsRegionMemory::~LLPanelScriptLimitsRegionMemory() BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources() { + if (!gAgent.getRegion()) return FALSE; + LLSD body; std::string url = gAgent.getRegion()->getCapability("LandResources"); if (!url.empty()) @@ -718,10 +712,9 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain() LLParcel* parcel = instance->getCurrentSelectedParcel(); LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - LLUUID current_region_id = gAgent.getRegion()->getRegionID(); - if ((region) && (parcel)) { + LLUUID current_region_id = gAgent.getRegion()->getRegionID(); LLVector3 parcel_center = parcel->getCenterpoint(); region_id = region->getRegionID(); @@ -982,6 +975,8 @@ void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata) BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails() { + if (!gAgent.getRegion()) return FALSE; + LLSD body; std::string url = gAgent.getRegion()->getCapability("AttachmentResources"); if (!url.empty()) diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 021edbecb6..1ce9b0c15e 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -837,20 +837,20 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) // HACK - highlight buttons for next click mRadioGroupMove->setVisible(move_visible); - if (!gGrabBtnSpin && - !gGrabBtnVertical && - !(mask == MASK_VERTICAL) && - !(mask == MASK_SPIN) ) + if (!(gGrabBtnSpin || + gGrabBtnVertical || + (mask == MASK_VERTICAL) || + (mask == MASK_SPIN))) { mRadioGroupMove->setValue("radio move"); } - else if (gGrabBtnVertical || - (mask == MASK_VERTICAL) ) + else if ((mask == MASK_VERTICAL) || + (gGrabBtnVertical && (mask != MASK_SPIN))) { mRadioGroupMove->setValue("radio lift"); } - else if (gGrabBtnSpin || - (mask == MASK_SPIN) ) + else if ((mask == MASK_SPIN) || + (gGrabBtnSpin && (mask != MASK_VERTICAL))) { mRadioGroupMove->setValue("radio spin"); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8752e50a80..e3d66205f7 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4210,8 +4210,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items LLInventoryModel::cat_array_t* cat_array; LLInventoryModel::item_array_t* item_array; gInventory.getDirectDescendentsOf(mUUID, cat_array, item_array); + LLViewerInventoryCategory *trash = getCategory(); // Enable Empty menu item only when there is something to act upon. - if ((0 == cat_array->size() && 0 == item_array->size()) || is_recent_panel) + // Also don't enable menu if folder isn't fully fetched + if ((0 == cat_array->size() && 0 == item_array->size()) + || is_recent_panel + || !trash + || trash->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN + || trash->getDescendentCount() == LLViewerInventoryCategory::VERSION_UNKNOWN) { disabled_items.push_back(std::string("Empty Trash")); } @@ -4400,8 +4406,6 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& LLFolderType::EType type = category->getPreferredType(); const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); // BAP change once we're no longer treating regular categories as ensembles. - const bool is_ensemble = (type == LLFolderType::FT_NONE || - LLFolderType::lookupIsEnsembleType(type)); const bool is_agent_inventory = isAgentInventory(); // [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.4) const bool is_outfit = (type == LLFolderType::FT_OUTFIT); @@ -4437,41 +4441,34 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& checkFolderForContentsOfType(model, is_object) || checkFolderForContentsOfType(model, is_gesture) ) { - // FIRE-21246 re-enable context menus for remove from COF on system folders and reinstate wearables separator + // Only enable add/replace outfit for non-system folders. + if (!is_system_folder) + { + // FIRE-3302: "Add to Current Outfit" missing for inventory outfit folder + items.push_back(std::string("Add To Outfit")); + + // Adding an outfit onto another (versus replacing) doesn't make sense. + if (type != LLFolderType::FT_OUTFIT) + { + // FIRE-3302: "Add to Current Outfit" missing for inventory outfit folder + //items.push_back(std::string("Add To Outfit")); + // Patch: ReplaceWornItemsOnly + items.push_back(std::string("Wear Items")); + // + } + + items.push_back(std::string("Replace Outfit")); + } if (is_agent_inventory) { items.push_back(std::string("Folder Wearables Separator")); - // Only enable add/replace outfit for non-system folders. - if (!is_system_folder) - { - // FIRE-3302: "Add to Current Outfit" missing for inventory outfit folder - items.push_back(std::string("Add To Outfit")); - - // Adding an outfit onto another (versus replacing) doesn't make sense. - if (type != LLFolderType::FT_OUTFIT) - { - // FIRE-3302: "Add to Current Outfit" missing for inventory outfit folder - //items.push_back(std::string("Add To Outfit")); - // Patch: ReplaceWornItemsOnly - items.push_back(std::string("Wear Items")); - // - } - - items.push_back(std::string("Replace Outfit")); - } - - if (is_ensemble) - { - items.push_back(std::string("Wear As Ensemble")); - } items.push_back(std::string("Remove From Outfit")); if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) { - disabled_items.push_back(std::string("Remove From Outfit")); + disabled_items.push_back(std::string("Remove From Outfit")); } } - // (change also outdents the next 3 if blocks with no fucntional impact) -// if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) + //if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) // [SL:KB] - Patch: Appearance-Misc | Checked: 2010-11-24 (Catznip-2.4) if ( ((is_outfit) && (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID))) || ((!is_outfit) && (gAgentWearables.isCOFChangeInProgress())) ) @@ -4491,6 +4488,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& disabled_items.push_back(std::string("Add To Outfit")); } items.push_back(std::string("Outfit Separator")); + } } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 7d54ff1c89..7ec6bee909 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2427,9 +2427,33 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { - LLSD args; - args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle())); + static bool sDisplayedAtSession = false; + + LLAllDescendentsPassedFilter f; + for (std::set::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it) + { + if (LLFolderViewFolder* folder = dynamic_cast(*it)) + { + folder->applyFunctorRecursively(f); + } + } + // Fall through to the generic confirmation if the user choose to ignore the specialized one + if ( (!f.allDescendentsPassedFilter()) && (!LLNotifications::instance().getIgnored("DeleteFilteredItems")) ) + { + LLNotificationsUtil::add("DeleteFilteredItems", LLSD(), LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle())); + } + else + { + if (!sDisplayedAtSession) // ask for the confirmation at least once per session + { + LLNotifications::instance().setIgnored("DeleteItems", false); + sDisplayedAtSession = true; + } + + LLSD args; + args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle())); + } // Note: marketplace listings will be updated in the callback if delete confirmed return; } diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index a4166174bf..e852431d01 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -480,6 +480,8 @@ struct LLInventoryAction static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle root); static void removeItemFromDND(LLFolderView* root); + static const int sConfirmOnDeleteItemsNumber; + private: static void buildMarketplaceFolders(LLFolderView* root); static void updateMarketplaceFolders(); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index efc0d240aa..71c0a1fe1f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -42,6 +42,7 @@ #include "bufferstream.h" #include "llcorehttputil.h" #include "llviewermenu.h" +#include "llviewernetwork.h" // History (may be apocryphal) // @@ -554,7 +555,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch() // OnIdle it will be called anyway due to Add flag for processed item. // It seems like in some cases we are updaiting on fail (no flag), // but is there anything to update? - gInventory.notifyObservers(); + // FIRE-21376: Inventory not loading properly on OpenSim + //gInventory.notifyObservers(); + if (LLGridManager::getInstance()->isInSecondLife()) + { + gInventory.notifyObservers(); + } + // } if ((mFetchCount > max_concurrent_fetches) || @@ -873,6 +880,12 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res titem->setParent(lost_uuid); titem->updateParentOnServer(FALSE); gInventory.updateItem(titem); + // FIRE-21376: Inventory not loading properly on OpenSim + if (!LLGridManager::getInstance()->isInSecondLife()) + { + gInventory.notifyObservers(); + } + // } } } @@ -945,6 +958,13 @@ void BGFolderHttpHandler::processData(LLSD & content, LLCore::HttpResponse * res { fetcher->setAllFoldersFetched(); } + + // FIRE-21376: Inventory not loading properly on OpenSim + if (!LLGridManager::getInstance()->isInSecondLife()) + { + gInventory.notifyObservers(); + } + // } @@ -987,6 +1007,13 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http fetcher->setAllFoldersFetched(); } } + + // FIRE-21376: Inventory not loading properly on OpenSim + if (!LLGridManager::getInstance()->isInSecondLife()) + { + gInventory.notifyObservers(); + } + // } @@ -1024,6 +1051,13 @@ void BGFolderHttpHandler::processFailure(const char * const reason, LLCore::Http fetcher->setAllFoldersFetched(); } } + + // FIRE-21376: Inventory not loading properly on OpenSim + if (!LLGridManager::getInstance()->isInSecondLife()) + { + gInventory.notifyObservers(); + } + // } diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 4016b89554..59d569e69b 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -384,6 +384,11 @@ void LLInventoryFetchDescendentsObserver::startFetch() if (!cat) continue; if (!isCategoryComplete(cat)) { + // CHECK IT: isCategoryComplete() checks both version and descendant count but + // fetch() only works for Unknown version and doesn't care about descentants, + // as result fetch won't start and folder will potentially get stuck as + // incomplete in observer. + // Likely either both should use only version or both should check descendants. cat->fetch(); //blindly fetch it without seeing if anything else is fetching it. mIncomplete.push_back(*it); //Add to list of things being downloaded for this observer. } diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index a8c47d450c..b384257fb7 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -61,6 +61,8 @@ #include #include +const S32 LOGIN_MAX_RETRIES = 3; + class LLLoginInstance::Disposable { public: virtual ~Disposable() {} @@ -228,13 +230,16 @@ void LLLoginInstance::constructAuthParams(LLPointer user_credentia request_params["host_id"] = gSavedSettings.getString("HostID"); request_params["extended_errors"] = true; // request message_id and message_args + // Specify desired timeout/retry options + LLSD http_params; + http_params["timeout"] = gSavedSettings.getF32("LoginSRVTimeout"); + http_params["retries"] = LOGIN_MAX_RETRIES; + mRequestData.clear(); mRequestData["method"] = "login_to_simulator"; mRequestData["params"] = request_params; mRequestData["options"] = requested_options; - - mRequestData["cfg_srv_timeout"] = gSavedSettings.getF32("LoginSRVTimeout"); - mRequestData["cfg_srv_pump"] = gSavedSettings.getString("LoginSRVPump"); + mRequestData["http_params"] = http_params; } bool LLLoginInstance::handleLoginEvent(const LLSD& event) diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 46c5b381e3..d7f568be9e 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -177,6 +177,8 @@ public: virtual bool wantsKeyUpKeyDown() const; virtual bool wantsReturnKey() const; + virtual BOOL acceptsTextInput() const {return TRUE;} + protected: void convertInputCoords(S32& x, S32& y); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 0ef21bccfc..3dbc4f1581 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1669,7 +1669,12 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) LLMeshRepository::sCacheBytesRead += size; ++LLMeshRepository::sCacheReads; file.seek(offset); - U8* buffer = new U8[size]; + U8* buffer = new(std::nothrow) U8[size]; + if (!buffer) + { + LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh LOD" << LL_ENDL; + return false; + } file.read(buffer, size); //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written) diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 5e166c5712..ea97456528 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -327,6 +327,8 @@ public: */ static std::string getSubstitutionName(const LLNotificationPtr& notification); + static std::string getSubstitutionOriginalName(const LLNotificationPtr& notification); + /** * Adds notification panel to the IM floater. */ diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index ece4281d04..7d7102ecf3 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -325,6 +325,20 @@ std::string LLHandlerUtil::getSubstitutionName(const LLNotificationPtr& notifica return res; } +// static +std::string LLHandlerUtil::getSubstitutionOriginalName(const LLNotificationPtr& notification) +{ + if(notification->getSubstitutions().has("ORIGINAL_NAME")) + { + std::string name = notification->getSubstitutions()["ORIGINAL_NAME"]; + if(!name.empty()) + { + return name; + } + } + return LLHandlerUtil::getSubstitutionName(notification); +} + // static void LLHandlerUtil::addNotifPanelToIM(const LLNotificationPtr& notification) { diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index a0e764fc37..58cf7cc624 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -155,6 +155,7 @@ bool LLOfferHandler::processNotification(const LLNotificationPtr& notification) // we not save offer notifications to the syswell floater that should be added to the IM floater p.can_be_stored = !add_notif_to_im; p.force_show = notification->getOfferFromAgent(); + p.can_fade = notification->canFadeToast(); LLScreenChannel* channel = dynamic_cast(mChannel.get()); if(channel) diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 7acb2f9e90..fef0631fa6 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -77,6 +77,7 @@ void LLScriptHandler::addToastWithNotification(const LLNotificationPtr& notifica p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + p.can_fade = notification->canFadeToast(); if(gAgent.isDoNotDisturb()) { p.force_show = notification->getName() == "SystemMessage" diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index b77266ce5f..4415b60632 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -89,8 +89,8 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) } std::string session_name = notification->getPayload()["SESSION_NAME"]; - const std::string name = notification->getSubstitutions()["NAME"]; - const LLUUID agent_id = notification->getSubstitutions()["AGENT-ID"]; // [FIRE-3522 : SJ] + const std::string name = LLHandlerUtil::getSubstitutionOriginalName(notification); + const LLUUID agent_id = notification->getSubstitutions()["AGENT-ID"]; // [FIRE-3522 : SJ] if (session_name.empty()) { diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 13ec81515e..c25fd656da 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -347,7 +347,7 @@ void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item) mItemPanels.pop_back(); } -LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name) +LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name, LLUUID outfit_id) { LLOutfitGalleryItem::Params giparams; LLOutfitGalleryItem* gitem = LLUICtrlFactory::create(giparams); @@ -356,6 +356,7 @@ LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name) gitem->setFollowsLeft(); gitem->setFollowsTop(); gitem->setOutfitName(name); + gitem->setUUID(outfit_id); return gitem; } @@ -514,7 +515,7 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id) if (!cat) return; std::string name = cat->getName(); - LLOutfitGalleryItem* item = buildGalleryItem(name); + LLOutfitGalleryItem* item = buildGalleryItem(name, cat_id); mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item)); item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this, _1, _2, _3, cat_id)); @@ -664,7 +665,8 @@ LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p) mSelected(false), mWorn(false), mDefaultImage(true), - mOutfitName("") + mOutfitName(""), + mUUID(LLUUID()) { buildFromFile("panel_outfit_gallery_item.xml"); } @@ -748,23 +750,20 @@ BOOL LLOutfitGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLUICtrl::handleRightMouseDown(x, y, mask); } -BOOL LLOutfitGallery::handleDoubleClick(S32 x, S32 y, MASK mask) +BOOL LLOutfitGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) { LLTabContainer* appearence_tabs = LLPanelOutfitsInventory::findInstance()->getChild("appearance_tabs"); - LLPanel* panel = NULL; - LLAccordionCtrl* accordion = NULL; - if (appearence_tabs != NULL) + if (appearence_tabs && (mUUID != LLUUID())) { appearence_tabs->selectTabByName("outfitslist_tab"); - panel = appearence_tabs->getCurrentPanel(); - if (panel != NULL) + LLPanel* panel = appearence_tabs->getCurrentPanel(); + if (panel) { - accordion = panel->getChild("outfits_accordion"); + LLAccordionCtrl* accordion = panel->getChild("outfits_accordion"); LLOutfitsList* outfit_list = dynamic_cast(panel); if (accordion != NULL && outfit_list != NULL) { - LLUUID item_id = getSelectedOutfitUUID(); - outfit_list->setSelectedOutfitByUUID(item_id); + outfit_list->setSelectedOutfitByUUID(mUUID); LLAccordionCtrlTab* tab = accordion->getSelectedTab(); tab->showAndFocusHeader(); return TRUE; @@ -772,7 +771,7 @@ BOOL LLOutfitGallery::handleDoubleClick(S32 x, S32 y, MASK mask) } } - return LLUICtrl::handleDoubleClick(x, y, mask); + return LLPanel::handleDoubleClick(x, y, mask); } void LLOutfitGalleryItem::setImageAssetId(LLUUID image_asset_id) diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 37e75f1109..2566247072 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -115,8 +115,6 @@ public: void onBeforeOutfitSnapshotSave(); void onAfterOutfitSnapshotSave(); - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); - protected: /*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id); /*virtual*/ void onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid); @@ -150,7 +148,7 @@ private: void updateRowsIfNeeded(); void updateGalleryWidth(); - LLOutfitGalleryItem* buildGalleryItem(std::string name); + LLOutfitGalleryItem* buildGalleryItem(std::string name, LLUUID outfit_id); void onTextureSelectionChanged(LLInventoryItem* itemp); @@ -258,6 +256,7 @@ public: /*virtual*/ void draw(); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); void setDefaultImage(); void setImageAssetId(LLUUID asset_id); @@ -265,6 +264,7 @@ public: void setOutfitName(std::string name); void setOutfitWorn(bool value); void setSelected(bool value); + void setUUID(LLUUID outfit_id) {mUUID = outfit_id;} std::string getItemName() {return mOutfitName;} bool isDefaultImage() {return mDefaultImage;} @@ -274,6 +274,7 @@ public: private: LLPointer mTexturep; + LLUUID mUUID; LLUUID mImageAssetId; LLTextBox* mOutfitNameText; LLTextBox* mOutfitWornText; diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 8241254457..2ca590a4ba 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -219,19 +219,21 @@ void LLPanelClassifiedInfo::onOpen(const LLSD& key) LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(getClassifiedId()); gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough); - // While we're at it let's get the stats from the new table if that - // capability exists. - std::string url = gAgent.getRegion()->getCapability("SearchStatRequest"); - if (!url.empty()) + if (gAgent.getRegion()) { - LL_INFOS() << "Classified stat request via capability" << LL_ENDL; - LLSD body; - LLUUID classifiedId = getClassifiedId(); - body["classified_id"] = classifiedId; - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, - boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1)); + // While we're at it let's get the stats from the new table if that + // capability exists. + std::string url = gAgent.getRegion()->getCapability("SearchStatRequest"); + if (!url.empty()) + { + LL_INFOS() << "Classified stat request via capability" << LL_ENDL; + LLSD body; + LLUUID classifiedId = getClassifiedId(); + body["classified_id"] = classifiedId; + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, + boost::bind(&LLPanelClassifiedInfo::handleSearchStatResponse, classifiedId, _1)); + } } - // Update classified click stats. // *TODO: Should we do this when opening not from search? sendClickMessage("profile"); @@ -559,21 +561,24 @@ void LLPanelClassifiedInfo::sendClickMessage( const LLVector3d& global_pos, const std::string& sim_name) { - // You're allowed to click on your own ads to reassure yourself - // that the system is working. - LLSD body; - body["type"] = type; - body["from_search"] = from_search; - body["classified_id"] = classified_id; - body["parcel_id"] = parcel_id; - body["dest_pos_global"] = global_pos.getValue(); - body["region_name"] = sim_name; + if (gAgent.getRegion()) + { + // You're allowed to click on your own ads to reassure yourself + // that the system is working. + LLSD body; + body["type"] = type; + body["from_search"] = from_search; + body["classified_id"] = classified_id; + body["parcel_id"] = parcel_id; + body["dest_pos_global"] = global_pos.getValue(); + body["region_name"] = sim_name; - std::string url = gAgent.getRegion()->getCapability("SearchStatTracking"); - LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL; - LL_INFOS() << "body: [" << body << "]" << LL_ENDL; - LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, - "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent."); + std::string url = gAgent.getRegion()->getCapability("SearchStatTracking"); + LL_INFOS() << "Sending click msg via capability (url=" << url << ")" << LL_ENDL; + LL_INFOS() << "body: [" << body << "]" << LL_ENDL; + LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body, + "SearchStatTracking Click report sent.", "SearchStatTracking Click report NOT sent."); + } } void LLPanelClassifiedInfo::sendClickMessage(const std::string& type) diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index ee34197cdc..1eb13ad491 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -172,6 +172,8 @@ public: virtual void setupCtrls (LLPanel* parent) {}; + virtual void onFilterChanged() { } + protected: LLUUID mGroupID; BOOL mAllowEdit; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index d6f1402c56..4cd66c9f40 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -516,6 +516,7 @@ void LLPanelGroupSubTab::setSearchFilter(const std::string& filter) mSearchFilter = filter; LLStringUtil::toLower(mSearchFilter); update(GC_ALL); + onFilterChanged(); } void LLPanelGroupSubTab::activate() @@ -2578,12 +2579,7 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLUICtrl* ctrl, bool force) ////////////////////////////////////////////////////////////////////////// - LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.find(role_id); - U64 current_role_powers = GP_NO_POWERS; - if (rit != gdatap->mRoles.end()) - { - current_role_powers = ((*rit).second->getRoleData().mRolePowers); - } + U64 current_role_powers = gdatap->getRolePowers(role_id); if(isEnablingAbility) { @@ -2886,6 +2882,16 @@ void LLPanelGroupActionsSubTab::activate() LLPanelGroupSubTab::activate(); update(GC_ALL); + mActionDescription->clear(); + mActionList->deselectAllItems(); + mActionList->deleteAllItems(); + buildActionsList(mActionList, + GP_ALL_POWERS, + GP_ALL_POWERS, + NULL, + FALSE, + TRUE, + FALSE); } void LLPanelGroupActionsSubTab::deactivate() @@ -2914,19 +2920,31 @@ void LLPanelGroupActionsSubTab::update(LLGroupChange gc) if (mGroupID.isNull()) return; - mActionList->deselectAllItems(); mActionMembers->deleteAllItems(); mActionRoles->deleteAllItems(); - mActionDescription->clear(); + if(mActionList->hasSelectedItem()) + { + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if (gdatap && gdatap->isMemberDataComplete() && gdatap->isRoleDataComplete()) + { + handleActionSelect(); + } + } +} + +void LLPanelGroupActionsSubTab::onFilterChanged() +{ + mActionDescription->clear(); + mActionList->deselectAllItems(); mActionList->deleteAllItems(); buildActionsList(mActionList, - GP_ALL_POWERS, - GP_ALL_POWERS, - NULL, - FALSE, - TRUE, - FALSE); + GP_ALL_POWERS, + GP_ALL_POWERS, + NULL, + FALSE, + TRUE, + FALSE); } void LLPanelGroupActionsSubTab::handleActionSelect() diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 0e37ef874b..2107e2d9e1 100644 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -322,6 +322,7 @@ public: virtual bool needsApply(std::string& mesg); virtual bool apply(std::string& mesg); virtual void update(LLGroupChange gc); + virtual void onFilterChanged(); void handleActionSelect(); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 99c608ad9b..8e1fd9e30c 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1564,28 +1564,6 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) } LLFloaterReg::showInstance("linkreplace", params); } - - // Inventory Links Replace - if (command_name == "replace_links") - { - LLSD params; - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (current_item) - { - LLInvFVBridge* bridge = (LLInvFVBridge*)current_item->getViewModelItem(); - - if (bridge) - { - LLInventoryObject* obj = bridge->getInventoryObject(); - if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getActualType() != LLAssetType::AT_LINK_FOLDER) - { - params = LLSD(obj->getUUID()); - } - } - } - LLFloaterReg::showInstance("fs_linkreplace", params); - } - // } void LLPanelMainInventory::onVisibilityChange( BOOL new_visibility ) @@ -1704,13 +1682,13 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); - return children != LLInventoryModel::CHILDREN_NO; + return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); } if (command_name == "empty_lostnfound") { const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); - return children != LLInventoryModel::CHILDREN_NO; + return children != LLInventoryModel::CHILDREN_NO && gInventory.isCategoryComplete(trash_id); } return TRUE; diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 31f3f5623d..4bb7e711ba 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -194,6 +194,7 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl) //} //else //{ + // cancel(); // floater->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local"))); //} floater->saveLocal(boost::bind(&LLPanelSnapshotLocal::saveLocalCallback, this, _1)); diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp index 5e430286ac..b66d9b336f 100644 --- a/indra/newview/llpanelsnapshotpostcard.cpp +++ b/indra/newview/llpanelsnapshotpostcard.cpp @@ -202,6 +202,8 @@ void LLPanelSnapshotPostcard::sendPostcardFinished(LLSD result) void LLPanelSnapshotPostcard::sendPostcard() { + if (!gAgent.getRegion()) return; + // upload the image std::string url = gAgent.getRegion()->getCapability("SendPostcard"); if (!url.empty()) diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index 55cb7d616b..471e1c24f3 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -62,7 +62,7 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) + if (!isItemRemovable() || (gInventory.getCategory(mUUID) && !gInventory.isCategoryComplete(mUUID))) { disabled_items.push_back(std::string("Purge Item")); } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 9d4a798e61..c784bd10f2 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2322,6 +2322,7 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/) mScriptEd->sync(); } + if (!gAgent.getRegion()) return; const LLInventoryItem *inv_item = getItem(); // save it out to asset server std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgent"); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index d35d4e3ebb..de2c6cdc52 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -45,6 +45,7 @@ #include "llimagepng.h" #include "lllandmarkactions.h" #include "lllocalcliprect.h" +#include "llresmgr.h" #include "llnotificationsutil.h" #include "llslurl.h" #include "llsnapshotlivepreview.h" @@ -56,6 +57,7 @@ #include "llvfs.h" #include "llwindow.h" #include "llworld.h" +#include const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -1198,7 +1200,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) // getFormattedImage(); // // // Save the formatted image -// BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); +// BOOL success = saveLocal(mFormattedImage); // // if(success) // { @@ -1206,6 +1208,42 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) // } // return success; //} +// +////Check if failed due to insufficient memory +//BOOL LLSnapshotLivePreview::saveLocal(LLPointer mFormattedImage) +//{ +// BOOL insufficient_memory; +// BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, FALSE, insufficient_memory); +// +// if (insufficient_memory) +// { +// std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); +// +//#ifdef LL_WINDOWS +// boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); +//#else +// boost::filesystem::path b_path(lastSnapshotDir); +//#endif +// boost::filesystem::space_info b_space = boost::filesystem::space(b_path); +// if (b_space.free < mFormattedImage->getDataSize()) +// { +// LLSD args; +// args["PATH"] = lastSnapshotDir; +// +// std::string needM_bytes_string; +// LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (mFormattedImage->getDataSize()) >> 10); +// args["NEED_MEMORY"] = needM_bytes_string; +// +// std::string freeM_bytes_string; +// LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); +// args["FREE_MEMORY"] = freeM_bytes_string; +// +// LLNotificationsUtil::add("SnapshotToComputerFailed", args); +// return false; +// } +// } +// return success; +//} void LLSnapshotLivePreview::saveLocal(boost::function callback) { diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 29e5841f91..10d21102e3 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -41,6 +41,7 @@ class LLSnapshotLivePreview : public LLView LOG_CLASS(LLSnapshotLivePreview); public: + //static BOOL saveLocal(LLPointer); // Threaded filepickers struct Params : public LLInitParam::Block { Params() diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 27633ab64e..f44daacd5a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -3065,13 +3065,15 @@ void login_callback(S32 option, void *userdata) */ void show_release_notes_if_required() { - if (LLVersionInfo::getChannelAndVersion() != gLastRunVersion + static bool release_notes_shown = false; + if (!release_notes_shown && (LLVersionInfo::getChannelAndVersion() != gLastRunVersion) && LLVersionInfo::getViewerMaturity() != LLVersionInfo::TEST_VIEWER // don't show Release Notes for the test builds && gSavedSettings.getBOOL("UpdaterShowReleaseNotes") && !gSavedSettings.getBOOL("FirstLoginThisInstall")) { LLSD info(LLAppViewer::instance()->getViewerInfo()); LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); + release_notes_shown = true; } } diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 73cddd60cf..e1b2fa670d 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -46,6 +46,8 @@ #include "lltransientfloatermgr.h" #include "llviewercontrol.h" // for gSavedSettings +#include + const S32 MAX_ALLOWED_MSG_WIDTH = 400; const F32 DEFAULT_BUTTON_DELAY = 0.5f; @@ -365,6 +367,10 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal { setCheckBox(LLNotifications::instance().getGlobalString("skipnexttime"), ignore_label); } + if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE_SESSION_ONLY) + { + setCheckBox(LLNotifications::instance().getGlobalString("skipnexttimesessiononly"), ignore_label); + } else if (form->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE) { setCheckBox(LLNotifications::instance().getGlobalString("alwayschoose"), ignore_label); @@ -399,15 +405,18 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std:: const LLFontGL* font = mCheck->getFont(); const S32 LINE_HEIGHT = font->getLineHeight(); + + std::vector lines; + boost::split(lines, check_title, boost::is_any_of("\n")); // Extend dialog for "check next time" S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD; - S32 check_width = S32(font->getWidth(check_title) + 0.99f) + 16; + S32 check_width = S32(font->getWidth(lines[0]) + 0.99f) + 16; // use width of the first line max_msg_width = llmax(max_msg_width, check_width); S32 dialog_width = max_msg_width + 2 * HPAD; S32 dialog_height = LLToastPanel::getRect().getHeight(); - dialog_height += LINE_HEIGHT; + dialog_height += LINE_HEIGHT * lines.size(); dialog_height += LINE_HEIGHT / 2; LLToastPanel::reshape( dialog_width, dialog_height, FALSE ); @@ -416,7 +425,7 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std:: // set check_box's attributes LLRect check_rect; - mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT)); + mCheck->setRect(check_rect.setOriginAndSize(msg_x, VPAD+BTN_HEIGHT+LINE_HEIGHT/2, max_msg_width, LINE_HEIGHT*lines.size())); mCheck->setLabel(check_title); mCheck->setCommitCallback(boost::bind(&LLToastAlertPanel::onClickIgnore, this, _1)); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 922fd817ef..a9432c56fc 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1472,13 +1472,20 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, // accessor that looks at permissions, copyability, and names of // inventory items to determine if a drop would be ok. -EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item) +EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item, EDragAndDropType type) { // check the basics if (!item || !obj) return ACCEPT_NO; // HACK: downcast LLViewerInventoryItem* vitem = (LLViewerInventoryItem*)item; - if (!vitem->isFinished()) return ACCEPT_NO; + if (!vitem->isFinished() && (type != DAD_CATEGORY)) + { + // Note: for DAD_CATEGORY we assume that folder version check passed and folder + // is complete, meaning that items inside are up to date. + // (isFinished() == false) at the moment shows that item was loaded from cache. + // Library or agent inventory only. + return ACCEPT_NO; + } if (vitem->getIsLinkType()) return ACCEPT_NO; // No giving away links // deny attempts to drop from an object onto itself. This is to @@ -2382,7 +2389,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( (*item_iter) = item; } */ - rv = willObjectAcceptInventory(root_object, item); + rv = willObjectAcceptInventory(root_object, item, DAD_CATEGORY); if (rv < ACCEPT_YES_COPY_SINGLE) { LL_DEBUGS() << "Object will not accept " << item->getUUID() << LL_ENDL; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 766046785b..2d99de2244 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -224,7 +224,7 @@ protected: // accessor that looks at permissions, copyability, and names of // inventory items to determine if a drop would be ok. - static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item); + static EAcceptance willObjectAcceptInventory(LLViewerObject* obj, LLInventoryItem* item, EDragAndDropType type = DAD_NONE); public: // helper functions diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index f41b5d27b7..d8aa49ab07 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -499,39 +499,53 @@ void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask) return; } + //-------------------------------------------------- + // Determine target mode + //-------------------------------------------------- + bool vertical_dragging = false; + bool spin_grabbing = false; + if ((mask == MASK_VERTICAL) + || (gGrabBtnVertical && (mask != MASK_SPIN))) + { + vertical_dragging = TRUE; + } + else if ((mask == MASK_SPIN) + || (gGrabBtnSpin && (mask != MASK_VERTICAL))) + { + spin_grabbing = TRUE; + } + //-------------------------------------------------- // Toggle spinning //-------------------------------------------------- - if (mSpinGrabbing && !(mask == MASK_SPIN) && !gGrabBtnSpin) + if (mSpinGrabbing && !spin_grabbing) { - // user released ALT key, stop spinning + // user released or switched mask key(s), stop spinning stopSpin(); } - else if (!mSpinGrabbing && (mask == MASK_SPIN) ) + else if (!mSpinGrabbing && spin_grabbing) { - // user pressed ALT key, start spinning + // user pressed mask key(s), start spinning startSpin(); } + mSpinGrabbing = spin_grabbing; //-------------------------------------------------- // Toggle vertical dragging //-------------------------------------------------- - if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical) + if (mVerticalDragging && !vertical_dragging) { // ...switch to horizontal dragging - mVerticalDragging = FALSE; - mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp); mDragStartFromCamera = mDragStartPointGlobal - gAgentCamera.getCameraPositionGlobal(); } - else if (!mVerticalDragging && (mask == MASK_VERTICAL) ) + else if (!mVerticalDragging && vertical_dragging) { // ...switch to vertical dragging - mVerticalDragging = TRUE; - mDragStartPointGlobal = gViewerWindow->clickPointInWorldGlobal(x, y, objectp); mDragStartFromCamera = mDragStartPointGlobal - gAgentCamera.getCameraPositionGlobal(); } + mVerticalDragging = vertical_dragging; const F32 RADIANS_PER_PIXEL_X = 0.01f; const F32 RADIANS_PER_PIXEL_Y = 0.01f; @@ -782,12 +796,13 @@ void LLToolGrabBase::handleHoverNonPhysical(S32 x, S32 y, MASK mask) //-------------------------------------------------- // Toggle vertical dragging //-------------------------------------------------- - if (mVerticalDragging && !(mask == MASK_VERTICAL) && !gGrabBtnVertical) + if (!(mask == MASK_VERTICAL) && !gGrabBtnVertical) { mVerticalDragging = FALSE; } - else if (!mVerticalDragging && (mask == MASK_VERTICAL) ) + else if ((gGrabBtnVertical && (mask != MASK_SPIN)) + || (mask == MASK_VERTICAL)) { mVerticalDragging = TRUE; } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 5caa6e9c41..4c4c84370e 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1695,6 +1695,10 @@ void remove_inventory_category( LLPointer obj = gInventory.getCategory(cat_id); if(obj) { + if (!gInventory.isCategoryComplete(cat_id)) + { + LL_WARNS() << "Removing (purging) incomplete category " << obj->getName() << LL_ENDL; + } if(LLFolderType::lookupIsProtectedType(obj->getPreferredType())) { LLNotificationsUtil::add("CannotRemoveProtectedCategories"); @@ -1809,6 +1813,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer cb) { if (AISAPI::isAvailable()) { + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + LL_WARNS() << "Purging not fetched folder: " << cat->getName() << LL_ENDL; + } AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t(); AISAPI::PurgeDescendents(id, cr); } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index eb14320246..bd7dafd9f5 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -863,7 +863,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t //formatted->enableOverSize() ; //formatted->encode(raw, 0); //formatted->disableOverSize() ; - //gViewerWindow->saveImageNumbered(formatted); + //LLSnapshotLivePreview::saveLocal(formatted); LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); switch (fmt) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8064fb3306..b68ec83d86 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -3579,11 +3579,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_INVENTORY_ACCEPTED: { // args["NAME"] = LLSLURL("agent", from_id, "completename").getSLURLString();; +// args["ORIGINAL_NAME"] = original_name; // [RLVa:KB] - Checked: RLVa-1.2.2 // Only anonymize the name if the agent is nearby, there isn't an open IM session to them and their profile isn't open bool fRlvCanShowName = (!RlvActions::isRlvEnabled()) || (RlvActions::canShowName(RlvActions::SNC_DEFAULT, from_id)) || (!RlvUtil::isNearbyAgent(from_id)) || (RlvUIEnabler::hasOpenProfile(from_id)) || (RlvUIEnabler::hasOpenIM(from_id)); args["NAME"] = LLSLURL("agent", from_id, (fRlvCanShowName) ? "completename" : "rlvanonym").getSLURLString();; + args["ORIGINAL_NAME"] = fRlvCanShowName ? original_name : RlvStrings::getAnonym(original_name); // [/RLVa:KB] LLSD payload; payload["from_id"] = from_id; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 16418ecd93..5a961d0cb6 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1356,9 +1356,11 @@ void LLViewerObjectList::clearDebugText() void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { + bool new_dead_object = true; if (mDeadObjects.find(objectp->mID) != mDeadObjects.end()) { LL_INFOS() << "Object " << objectp->mID << " already on dead list!" << LL_ENDL; + new_dead_object = false; } else { @@ -1395,7 +1397,10 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) // Also, not cleaned up removeDrawable(objectp->mDrawable); - mNumDeadObjects++; + if(new_dead_object) + { + mNumDeadObjects++; + } } static LLTrace::BlockTimerStatHandle FTM_REMOVE_DRAWABLE("Remove Drawable"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 614292aa75..61e11d3e2d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -4853,6 +4854,21 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d // Threaded filepickers void do_save_image(LLImageFormatted* image, const std::string& snapshot_dir, const std::string& base_name, const std::string& extension, boost::function callback) { +// Check if there is enough free space to save snapshot +#ifdef LL_WINDOWS + boost::filesystem::space_info b_space = boost::filesystem::space(utf8str_to_utf16str(snapshot_dir)); +#else + boost::filesystem::space_info b_space = boost::filesystem::space(snapshot_dir); +#endif + if (b_space.free < image->getDataSize()) + { + if (callback) + { + callback(false); + } + return; + } + // Look for an unused file name std::string filepath; S32 i = 1; @@ -4908,10 +4924,13 @@ void LLViewerWindow::saveImageCallback(const std::string& filename, LLImageForma // Saves an image to the harddrive as "SnapshotX" where X >= 1. // Threaded filepickers -//BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker) +//BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory) void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker, boost::function callback) // { + // Threaded filepickers + //insufficient_memory = FALSE; + if (!image) { LL_WARNS() << "No image to save" << LL_ENDL; @@ -4963,6 +4982,17 @@ void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picke // LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath); //} +// Check if there is enough free space to save snapshot +//#ifdef LL_WINDOWS +// boost::filesystem::space_info b_space = boost::filesystem::space(utf8str_to_utf16str(sSnapshotDir)); +//#else +// boost::filesystem::space_info b_space = boost::filesystem::space(sSnapshotDir); +//#endif +// if (b_space.free < image->getDataSize()) +// { +// insufficient_memory = TRUE; +// return FALSE; +// } //// Look for an unused file name //std::string filepath; //S32 i = 1; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 867f49abc5..94c0c9ce27 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -354,7 +354,7 @@ public: BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } void resetSnapshotLoc() const { sSnapshotDir.clear(); } // Threaded filepickers - //BOOL saveImageNumbered(LLImageFormatted *image, bool force_picker = false); + BOOL saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory); void saveImageNumbered(LLImageFormatted *image, bool force_picker = false, boost::function callback = NULL); void saveImageCallback(const std::string& filename, LLImageFormatted* image, const std::string& extension, boost::function callback); // @@ -427,6 +427,7 @@ public: bool getSystemUIScaleFactorChanged() { return mSystemUIScaleFactorChanged; } static void showSystemUIScaleFactorChanged(); + static std::string getLastSnapshotDir() { return sSnapshotDir; } private: bool shouldShowToolTipFor(LLMouseHandler *mh); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index eaad4ab4ae..ffacfbbdae 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4050,11 +4050,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // don't early out for your own avatar, as we rely on your animations playing reliably // for example, the "turn around" animation when entering customize avatar needs to trigger // even when your avatar is offscreen - if (!visible && !isSelf()) - { - updateMotions(LLCharacter::HIDDEN_UPDATE); - return FALSE; - } + // Fix impostered animation speed based on a fix by Henri Beauchamp + //if (!visible && !isSelf()) + //{ + // updateMotions(LLCharacter::HIDDEN_UPDATE); + // return FALSE; + //} + // // Optionally disable the usage of timesteps, testing if this affects performance or // creates animation issues - FIRE-3657 @@ -4074,6 +4076,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) removeAnimationData("Walk Speed"); } mMotionController.setTimeStep(time_step); + mMotionController.setUpdateFactor(mUpdatePeriod); // Fix impostered animation speed based on a fix by Henri Beauchamp // LL_INFOS() << "Setting timestep to " << time_quantum * pixel_area_scale << LL_ENDL; } // Optionally disable the usage of timesteps, testing if this affects performance or @@ -4081,9 +4084,18 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) else { mMotionController.setTimeStep(0.0f); + mMotionController.setUpdateFactor(mUpdatePeriod); // Fix impostered animation speed based on a fix by Henri Beauchamp } // + // Fix impostered animation speed based on a fix by Henri Beauchamp + if (!visible && !isSelf()) + { + updateMotions(LLCharacter::HIDDEN_UPDATE); + return FALSE; + } + // + if (getParent() && !mIsSitting) { sitOnObject((LLViewerObject*)getParent()); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index b84ed40e40..d7ad69ff38 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2785,7 +2785,9 @@ bool LLVOAvatarSelf::updateAvatarRezMetrics(bool force_send) { const F32 AV_METRICS_INTERVAL_QA = 30.0; F32 send_period = 300.0; - if (gSavedSettings.getBOOL("QAModeMetrics")) + + static LLCachedControl qa_mode_metrics(gSavedSettings,"QAModeMetrics"); + if (qa_mode_metrics) { send_period = AV_METRICS_INTERVAL_QA; } diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp index cc3645131d..99070d5bee 100644 --- a/indra/newview/llxmlrpclistener.cpp +++ b/indra/newview/llxmlrpclistener.cpp @@ -312,7 +312,7 @@ public: } XMLRPC_RequestSetData(request, xparams); - mTransaction.reset(new LLXMLRPCTransaction(mUri, request)); + mTransaction.reset(new LLXMLRPCTransaction(mUri, request, true, command.has("http_params")? LLSD(command["http_params"]) : LLSD())); mPreviousStatus = mTransaction->status(NULL); // Free the XMLRPC_REQUEST object and the attached data values. diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index f8b38669b6..0c8495a6e4 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -208,7 +208,7 @@ public: std::string mCertStore; LLPointer mErrorCert; - Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip); + Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams); Impl(const std::string& uri, const std::string& method, LLXMLRPCValue params, bool useGzip); ~Impl(); @@ -219,7 +219,7 @@ public: void setHttpStatus(const LLCore::HttpStatus &status); private: - void init(XMLRPC_REQUEST request, bool useGzip); + void init(XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams); }; LLXMLRPCTransaction::Handler::Handler(LLCore::HttpRequest::ptr_t &request, @@ -315,13 +315,13 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle, //========================================================================= LLXMLRPCTransaction::Impl::Impl(const std::string& uri, - XMLRPC_REQUEST request, bool useGzip) + XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams) : mHttpRequest(), mStatus(LLXMLRPCTransaction::StatusNotStarted), mURI(uri), mResponse(0) { - init(request, useGzip); + init(request, useGzip, httpParams); } @@ -337,7 +337,7 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri, XMLRPC_RequestSetRequestType(request, xmlrpc_request_call); XMLRPC_RequestSetData(request, params.getValue()); - init(request, useGzip); + init(request, useGzip, LLSD()); // DEV-28398: without this XMLRPC_RequestFree() call, it looks as though // the 'request' object is simply leaked. It's less clear to me whether we // should also ask to free request value data (second param 1), since the @@ -345,7 +345,7 @@ LLXMLRPCTransaction::Impl::Impl(const std::string& uri, XMLRPC_RequestFree(request, 1); } -void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) +void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams) { LLCore::HttpOptions::ptr_t httpOpts; LLCore::HttpHeaders::ptr_t httpHeaders; @@ -359,7 +359,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()); - httpOpts->setTimeout(40L); + // delay between repeats will start from 5 sec and grow to 20 sec with each repeat + httpOpts->setMinBackoff(5E6L); + httpOpts->setMaxBackoff(20E6L); + + httpOpts->setTimeout(httpParams.has("timeout") ? httpParams["timeout"].asInteger() : 40L); + if (httpParams.has("retries")) + { + httpOpts->setRetries(httpParams["retries"].asInteger()); + } bool vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert"); mCertStore = gSavedSettings.getString("CertStore"); @@ -526,8 +534,8 @@ void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status) LLXMLRPCTransaction::LLXMLRPCTransaction( - const std::string& uri, XMLRPC_REQUEST request, bool useGzip) -: impl(* new Impl(uri, request, useGzip)) + const std::string& uri, XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams) +: impl(* new Impl(uri, request, useGzip, httpParams)) { } diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h index 3a1c9c82b7..7a9bc991f7 100644 --- a/indra/newview/llxmlrpctransaction.h +++ b/indra/newview/llxmlrpctransaction.h @@ -85,7 +85,7 @@ class LLXMLRPCTransaction { public: LLXMLRPCTransaction(const std::string& uri, - XMLRPC_REQUEST request, bool useGzip = true); + XMLRPC_REQUEST request, bool useGzip = true, const LLSD& httpParams = LLSD()); // does not take ownership of the request object // request can be freed as soon as the transaction is constructed diff --git a/indra/newview/skins/default/xui/de/floater_tos.xml b/indra/newview/skins/default/xui/de/floater_tos.xml index 5dbff878f3..9f8a494684 100644 --- a/indra/newview/skins/default/xui/de/floater_tos.xml +++ b/indra/newview/skins/default/xui/de/floater_tos.xml @@ -6,13 +6,16 @@ data:text/html,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody text=%22000000%22%3E%3Ch2%3E Wird geladen %3Ca%20target%3D%22_external%22%20href%3D%22http%3A//secondlife.com/app/tos/%22%3EServicebedingungen%3C/a%3E...%3C/h2%3E %3C/body%3E %3C/html%3E -