diff --git a/.hgtags b/.hgtags index dbf8ea63fd..c2f496d31b 100755 --- a/.hgtags +++ b/.hgtags @@ -577,3 +577,4 @@ ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release 7b6b020fd5ad9a8dc3670c5c92d1ca92e55fc485 5.1.4-release 2ea47f358b171178eb9a95503a1670d519c2886f 5.1.5-release 04538b8157c1f5cdacd9403f0a395452d4a93689 5.1.6-release +ac3b1332ad4f55b7182a8cbcc1254535a0069f75 5.1.7-release diff --git a/autobuild.xml b/autobuild.xml index 1ace4378a6..6502fcc882 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -3566,9 +3566,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 86f6708f393c162cd4f92426b0a3cde7 + f45c0a5e7b4601b355e163bf62f5718e url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15341/99062/viewer_manager-1.0.513570-darwin64-513570.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/20587/147509/viewer_manager-1.0.517052-darwin64-517052.tar.bz2 name darwin64 @@ -3602,9 +3602,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - c4dec51062ad78c09b11f7432aff4d1d + d2443caf062697430071d458a965f611 url - http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/17857/121832/viewer_manager-1.0.515286-windows-515286.tar.bz2 + http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/20588/147516/viewer_manager-1.0.517052-windows-517052.tar.bz2 name windows @@ -3615,7 +3615,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors source_type hg version - 1.0.515286 + 1.0.517052 vlc-bin @@ -3878,6 +3878,8 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors package_description + canonical_repo + https://bitbucket.org/lindenlab/viewer-release copyright Copyright (c) 2018, The Phoenix Firestorm Project, Inc. description diff --git a/doc/contributions.txt b/doc/contributions.txt index 85fb4f5c94..95870101b7 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -221,7 +221,6 @@ Ansariel Hiller STORM-2151 MAINT-6917 MAINT-8085 - STORM-2122 Aralara Rajal Arare Chantilly CHUIBUG-191 diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 2f75f9041a..cc21caca11 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -327,6 +327,7 @@ const U8 CLICK_ACTION_OPEN = 4; const U8 CLICK_ACTION_PLAY = 5; const U8 CLICK_ACTION_OPEN_MEDIA = 6; const U8 CLICK_ACTION_ZOOM = 7; +const U8 CLICK_ACTION_DISABLED = 8; // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 8768d1d90c..f2f1b1157c 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -35,6 +35,7 @@ // external library headers #include // other Linden headers +#include "lltimer.h" #include "llevents.h" #include "llerror.h" #include "stringize.h" @@ -280,6 +281,25 @@ void LLCoros::setStackSize(S32 stacksize) mStackSize = stacksize; } +void LLCoros::printActiveCoroutines() +{ + LL_INFOS("LLCoros") << "Number of active coroutines: " << (S32)mCoros.size() << LL_ENDL; + if (mCoros.size() > 0) + { + LL_INFOS("LLCoros") << "-------------- List of active coroutines ------------"; + CoroMap::iterator iter; + CoroMap::iterator end = mCoros.end(); + F64 time = LLTimer::getTotalSeconds(); + for (iter = mCoros.begin(); iter != end; iter++) + { + F64 life_time = time - iter->second->mCreationTime; + LL_CONT << LL_NEWLINE << "Name: " << iter->first << " life: " << life_time; + } + LL_CONT << LL_ENDL; + LL_INFOS("LLCoros") << "-----------------------------------------------------" << LL_ENDL; + } +} + #if LL_WINDOWS static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific @@ -379,7 +399,8 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name, mCoro(boost::bind(toplevel, _1, this, callable), stacksize), // don't consume events unless specifically directed mConsuming(false), - mSelf(0) + mSelf(0), + mCreationTime(LLTimer::getTotalSeconds()) { } @@ -388,7 +409,13 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl std::string name(generateDistinctName(prefix)); Current current; // pass the current value of Current as previous context - CoroData* newCoro = new CoroData(current, name, callable, mStackSize); + CoroData* newCoro = new(std::nothrow) CoroData(current, name, callable, mStackSize); + if (newCoro == NULL) + { + // Out of memory? + printActiveCoroutines(); + LL_ERRS("LLCoros") << "Failed to start coroutine: " << name << " Stacksize: " << mStackSize << " Total coroutines: " << mCoros.size() << LL_ENDL; + } // Store it in our pointer map mCoros.insert(name, newCoro); // also set it as current diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 884d6b159c..8fb27af6a4 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -151,6 +151,9 @@ public: /// for delayed initialization void setStackSize(S32 stacksize); + /// for delayed initialization + void printActiveCoroutines(); + /// get the current coro::self& for those who really really care static coro::self& get_self(); @@ -223,6 +226,7 @@ private: // function signature down to that point -- and of course through every // other caller of every such function. LLCoros::coro::self* mSelf; + F64 mCreationTime; // since epoch }; typedef boost::ptr_map CoroMap; CoroMap mCoros; diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp index 49d865cbfa..0b72b53186 100644 --- a/indra/llcorehttp/_httpservice.cpp +++ b/indra/llcorehttp/_httpservice.cpp @@ -95,10 +95,12 @@ HttpService::~HttpService() if (! mThread->timedJoin(250)) { // Failed to join, expect problems ahead so do a hard termination. - mThread->cancel(); + LL_WARNS(LOG_CORE) << "Destroying HttpService with running thread. Expect problems." << LL_NEWLINE + << "State: " << S32(sState) + << " Last policy: " << U32(mLastPolicy) + << LL_ENDL; - LL_WARNS(LOG_CORE) << "Destroying HttpService with running thread. Expect problems." - << LL_ENDL; + mThread->cancel(); } } } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index a72d4bb52f..f566eee563 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -193,7 +193,13 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) ret = (U8*) ll_aligned_malloc<64>(size); if (!ret) { - LL_ERRS() << "Failed to allocate for LLVBOPool buffer" << LL_ENDL; + LL_ERRS() << "Failed to allocate "<< size << " bytes for LLVBOPool buffer " << name <<"." << LL_NEWLINE + << "Free list size: " << mFreeList.size() // this happens if we are out of memory so a solution might be to clear some from freelist + << " Allocated Bytes: " << LLVertexBuffer::sAllocatedBytes + << " Allocated Index Bytes: " << LLVertexBuffer::sAllocatedIndexBytes + << " Pooled Bytes: " << sBytesPooled + << " Pooled Index Bytes: " << sIndexBytesPooled + << LL_ENDL; } } } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 639a5593dd..653acf2c34 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -209,7 +209,6 @@ set(viewer_SOURCE_FILES lggbeamscolors.cpp lggcontactsets.cpp lfsimfeaturehandler.cpp - llfloaterauction.cpp llfloaterdisplayname.cpp llpanelopenregionsettings.cpp llviewerdisplayname.cpp @@ -317,6 +316,7 @@ set(viewer_SOURCE_FILES llflickrconnect.cpp llfloaterabout.cpp llfloaterbvhpreview.cpp + llfloaterauction.cpp llfloaterautoreplacesettings.cpp llfloateravatar.cpp llfloateravatarpicker.cpp @@ -968,7 +968,6 @@ set(viewer_HEADER_FILES lggbeamscolors.h lggcontactsets.h lfsimfeaturehandler.h - llfloaterauction.h llfloaterdisplayname.h llviewerdisplayname.h # [Legacy Bake] @@ -1076,6 +1075,7 @@ set(viewer_HEADER_FILES llflickrconnect.h llfloaterabout.h llfloaterbvhpreview.h + llfloaterauction.h llfloaterautoreplacesettings.h llfloateravatar.h llfloateravatarpicker.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ddf4259bdb..a031d1f129 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5790,13 +5790,13 @@ FeatureManagerHTTPTable Comment - Base directory for HTTP feature/gpu table fetches + Deprecated Persist - 1 + 0 Type String Value - http://viewer-settings.firestormviewer.org + Backup 0 @@ -24703,17 +24703,6 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 - FSUseReadOfflineMsgsCap - - Comment - If enabled, use the ReadOfflineMsgsCap to request offline messages at login - Persist - 1 - Type - Boolean - Value - 0 - FSExperimentalRegionCrossingMovementFix Comment diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index df36dfc407..7c897bc670 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -1202,5 +1202,16 @@ Value 0 + FSRememberSnapshotPathSessions + + Comment + If enabled, remember the path and filename of snapshots between sessions. Default (true) + Persist + 1 + Type + Boolean + Value + 1 + diff --git a/indra/newview/daeexport.cpp b/indra/newview/daeexport.cpp index b024e875d1..7078c32daf 100644 --- a/indra/newview/daeexport.cpp +++ b/indra/newview/daeexport.cpp @@ -81,6 +81,7 @@ #include "lltrans.h" #include "llversioninfo.h" #include "llviewercontrol.h" +#include "llviewermenufile.h" #include "llviewernetwork.h" #include "llviewerregion.h" #include "llviewertexturelist.h" @@ -196,14 +197,14 @@ void ColladaExportFloater::updateUI() void ColladaExportFloater::onClickExport() { - LLFilePicker& file_picker = LLFilePicker::instance(); - if (!file_picker.getSaveFile(LLFilePicker::FFSAVE_COLLADA, LLDir::getScrubbedFileName(mObjectName + ".dae"))) - { - LL_INFOS() << "User closed the filepicker, aborting export!" << LL_ENDL; - return; - } - mFilename = file_picker.getFirstFile(); - + (new LLFilePickerReplyThread(boost::bind(&ColladaExportFloater::onExportFileSelected, this, _1), + LLFilePicker::FFSAVE_COLLADA, LLDir::getScrubbedFileName(mObjectName + ".dae")))->getFile(); +} + +void ColladaExportFloater::onExportFileSelected(const std::vector& filenames) +{ + mFilename = filenames[0]; + if (gSavedSettings.getBOOL("DAEExportTextures")) { saveTextures(); diff --git a/indra/newview/daeexport.h b/indra/newview/daeexport.h index 725f764aff..c0719468ad 100644 --- a/indra/newview/daeexport.h +++ b/indra/newview/daeexport.h @@ -131,6 +131,7 @@ private: void refresh(); void dirty(); void onClickExport(); + void onExportFileSelected(const std::vector& filenames); void onTextureExportCheck(); void onCommitTextureType(); void saveTextures(); diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp index 5fe68d3227..93d7526116 100644 --- a/indra/newview/fschathistory.cpp +++ b/indra/newview/fschathistory.cpp @@ -561,10 +561,24 @@ public: registrar_enable.add("ObjectIcon.Visible", boost::bind(&FSChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenuHandleAvatar = menu->getHandle(); + if (menu) + { + mPopupMenuHandleAvatar = menu->getHandle(); + } + else + { + LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; + } menu = LLUICtrlFactory::getInstance()->createFromFile("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenuHandleObject = menu->getHandle(); + if (menu) + { + mPopupMenuHandleObject = menu->getHandle(); + } + else + { + LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; + } setDoubleClickCallback(boost::bind(&FSChatHistoryHeader::showInspector, this)); @@ -671,6 +685,11 @@ public: } mUserNameFont = mNameStyleParams.font(); + if (!mUserNameTextBox) + { + mUserNameTextBox = getChild("user_name"); + mTimeBoxTextBox = getChild("time_box"); + } mUserNameTextBox->setReadOnlyColor(mNameStyleParams.readonly_color()); mUserNameTextBox->setColor(mNameStyleParams.color()); mUserNameTextBox->setFont(mUserNameFont); diff --git a/indra/newview/fsfloaterexport.cpp b/indra/newview/fsfloaterexport.cpp index 5c0ef654f3..e031979e3a 100644 --- a/indra/newview/fsfloaterexport.cpp +++ b/indra/newview/fsfloaterexport.cpp @@ -55,8 +55,9 @@ #include "llvfile.h" #include "llviewercontrol.h" #include "llviewerinventory.h" -#include "llviewerpartsource.h" +#include "llviewermenufile.h" #include "llviewernetwork.h" +#include "llviewerpartsource.h" #include "llviewerregion.h" #include "llviewertexturelist.h" #include "llvovolume.h" @@ -1082,14 +1083,14 @@ void FSFloaterObjectExport::updateUI() void FSFloaterObjectExport::onClickExport() { - LLFilePicker& file_picker = LLFilePicker::instance(); - if(!file_picker.getSaveFile(LLFilePicker::FFSAVE_EXPORT, LLDir::getScrubbedFileName(mObjectName + ".oxp"))) - { - LL_INFOS() << "User closed the filepicker, aborting export!" << LL_ENDL; - return; - } - mFilename = file_picker.getFirstFile(); - + (new LLFilePickerReplyThread(boost::bind(&FSFloaterObjectExport::onExportFileSelected, this, _1), + LLFilePicker::FFSAVE_EXPORT, LLDir::getScrubbedFileName(mObjectName + ".oxp")))->getFile(); +} + +void FSFloaterObjectExport::onExportFileSelected(const std::vector& filenames) +{ + mFilename = filenames[0]; + LLUIString title = getString("title_working"); title.setArg("[OBJECT]", mObjectName); setTitle(title); diff --git a/indra/newview/fsfloaterexport.h b/indra/newview/fsfloaterexport.h index c1db65229b..52e3813980 100644 --- a/indra/newview/fsfloaterexport.h +++ b/indra/newview/fsfloaterexport.h @@ -86,6 +86,7 @@ private: void addSelectedObjects(); void populateObjectList(); void onClickExport(); + void onExportFileSelected(const std::vector& filenames); void addTexturePreview(); S32 getNumExportableTextures(); void addObject(const LLViewerObject* prim, const std::string name); diff --git a/indra/newview/fsslurl.cpp b/indra/newview/fsslurl.cpp index 5307651f5b..a07f2700fa 100644 --- a/indra/newview/fsslurl.cpp +++ b/indra/newview/fsslurl.cpp @@ -325,15 +325,15 @@ LLSLURL::LLSLURL(const std::string& slurl) // (or its a slurl.com or maps.secondlife.com URL). std::string probe_grid; - std::string hyper = slurl_uri.hostNameAndPort(); - std::string hyper_trimmed = LLGridManager::getInstance()->trimHypergrid(hyper); - if (hyper != hyper_trimmed) + std::string hypergrid = slurl_uri.hostNameAndPort(); + std::string hyper_trimmed = LLGridManager::getInstance()->trimHypergrid(hypergrid); + if (hypergrid != hyper_trimmed) { mHypergrid = true; - path_array.insert(0,hyper); + path_array.insert(0, hypergrid); } - probe_grid = LLGridManager::getInstance()->getGridByProbing(hyper); + probe_grid = LLGridManager::getInstance()->getGridByProbing(hypergrid); if (probe_grid.empty()) { probe_grid = LLGridManager::getInstance()->getGridByProbing(slurl_uri.hostName()); @@ -479,8 +479,8 @@ LLSLURL::LLSLURL(const std::string& slurl) } // Create a slurl for the middle of the region -LLSLURL::LLSLURL(const std::string& grid, const std::string& region, bool hyper) -: mHypergrid(hyper) +LLSLURL::LLSLURL(const std::string& grid, const std::string& region, bool hypergrid) +: mHypergrid(hypergrid) { mGrid = grid; mRegion = region; @@ -490,8 +490,8 @@ LLSLURL::LLSLURL(const std::string& grid, const std::string& region, bool hyper) // create a slurl given the position. The position will be modded with the region // width handling global positions as well -LLSLURL::LLSLURL(const std::string& grid, const std::string& region, const LLVector3& position, bool hyper) -: mHypergrid(hyper) +LLSLURL::LLSLURL(const std::string& grid, const std::string& region, const LLVector3& position, bool hypergrid) +: mHypergrid(hypergrid) { mGrid = grid; mRegion = region; @@ -516,15 +516,15 @@ LLSLURL::LLSLURL(const std::string& grid, const std::string& region, const LLVec } // create a simstring -LLSLURL::LLSLURL(const std::string& region, const LLVector3& position, bool hyper) -: mHypergrid(hyper) +LLSLURL::LLSLURL(const std::string& region, const LLVector3& position, bool hypergrid) +: mHypergrid(hypergrid) { *this = LLSLURL(LLGridManager::getInstance()->getGrid(), region, position); } // create a slurl from a global position -LLSLURL::LLSLURL(const std::string& grid, const std::string& region, const LLVector3d& global_position, bool hyper) -: mHypergrid(hyper) +LLSLURL::LLSLURL(const std::string& grid, const std::string& region, const LLVector3d& global_position, bool hypergrid) +: mHypergrid(hypergrid) { // Aurora-sim var region teleports //*this = LLSLURL(grid, @@ -540,8 +540,8 @@ LLSLURL::LLSLURL(const std::string& grid, const std::string& region, const LLVec } // create a slurl from a global position -LLSLURL::LLSLURL(const std::string& region, const LLVector3d& global_position, bool hyper) -: mHypergrid(hyper) +LLSLURL::LLSLURL(const std::string& region, const LLVector3d& global_position, bool hypergrid) +: mHypergrid(hypergrid) { *this = LLSLURL(LLGridManager::getInstance()->getGrid(), region, global_position); } diff --git a/indra/newview/fsslurl.h b/indra/newview/fsslurl.h index ef19cda080..e01764190b 100644 --- a/indra/newview/fsslurl.h +++ b/indra/newview/fsslurl.h @@ -70,11 +70,11 @@ public: LLSLURL(): mType(INVALID) { } LLSLURL(const std::string& slurl); - LLSLURL(const std::string& grid, const std::string& region, bool hyper = false); - LLSLURL(const std::string& region, const LLVector3& position, bool hyper = false); - LLSLURL(const std::string& grid, const std::string& region, const LLVector3& position, bool hyper = false); - LLSLURL(const std::string& grid, const std::string& region, const LLVector3d& global_position, bool hyper = false); - LLSLURL(const std::string& region, const LLVector3d& global_position, bool hyper = false); + LLSLURL(const std::string& grid, const std::string& region, bool hypergrid = false); + LLSLURL(const std::string& region, const LLVector3& position, bool hypergrid = false); + LLSLURL(const std::string& grid, const std::string& region, const LLVector3& position, bool hypergrid = false); + LLSLURL(const std::string& grid, const std::string& region, const LLVector3d& global_position, bool hypergrid = false); + LLSLURL(const std::string& region, const LLVector3d& global_position, bool hypergrid = false); LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb); LLSLURL(const LLSD& path_array, bool from_app); diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 7300529823..927bf530a2 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -83,6 +83,8 @@ const F32 AVATAR_ZOOM_MIN_Y_FACTOR = 0.7f; const F32 AVATAR_ZOOM_MIN_Z_FACTOR = 1.15f; const F32 MAX_CAMERA_DISTANCE_FROM_AGENT = 50.f; +const F32 MAX_CAMERA_DISTANCE_FROM_OBJECT = 496.f; +const F32 CAMERA_FUDGE_FROM_OBJECT = 16.f; const F32 MAX_CAMERA_SMOOTH_DISTANCE = 50.0f; @@ -767,10 +769,7 @@ F32 LLAgentCamera::getCameraZoomFraction() else { F32 min_zoom; - const F32 DIST_FUDGE = 16.f; // meters - F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE, - MAX_CAMERA_DISTANCE_FROM_AGENT); + F32 max_zoom = getCameraMaxZoomDistance(); F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); if (mFocusObject.notNull()) @@ -816,23 +815,17 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction) else { F32 min_zoom = LAND_MIN_ZOOM; - const F32 DIST_FUDGE = 16.f; // meters - F32 max_zoom = llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE, - MAX_CAMERA_DISTANCE_FROM_AGENT); + F32 max_zoom = getCameraMaxZoomDistance(); if (mFocusObject.notNull()) { - if (mFocusObject.notNull()) + if (mFocusObject->isAvatar()) { - if (mFocusObject->isAvatar()) - { - min_zoom = AVATAR_MIN_ZOOM; - } - else - { - min_zoom = OBJECT_MIN_ZOOM; - } + min_zoom = AVATAR_MIN_ZOOM; + } + else + { + min_zoom = OBJECT_MIN_ZOOM; } } @@ -949,12 +942,7 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) new_distance = llmax(new_distance, min_zoom); } - // Don't zoom too far back - const F32 DIST_FUDGE = 16.f; // meters - // Freeing the camera movement some more... ok, a lot -KC - static LLCachedControl disable_constraints(gSavedSettings,"DisableCameraConstraints"); - F32 max_distance = disable_constraints ? INT_MAX : llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); + F32 max_distance = getCameraMaxZoomDistance(); max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154 @@ -1031,17 +1019,12 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters) new_distance = llmax(new_distance, min_zoom); } - // Don't zoom too far back - const F32 DIST_FUDGE = 16.f; // meters - // Freeing the camera movement some more... ok, a lot -KC - static LLCachedControl disable_constraints(gSavedSettings,"DisableCameraConstraints"); - F32 max_distance = disable_constraints ? INT_MAX : llmin(mDrawDistance - DIST_FUDGE, - LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); + F32 max_distance = getCameraMaxZoomDistance(); if (new_distance > max_distance) { // Unless camera is unlocked - if (!disable_constraints) + if (!gSavedSettings.getBOOL("DisableCameraConstraints")) { return; } @@ -2107,6 +2090,15 @@ LLVector3 LLAgentCamera::getCameraOffsetInitial() return convert_from_llsd(mCameraOffsetInitial[mCameraPreset]->get(), TYPE_VEC3, ""); } +F32 LLAgentCamera::getCameraMaxZoomDistance() +{ + // Ignore "DisableCameraConstraints", we don't want to be out of draw range when we focus onto objects or avatars + // Freeing the camera movement some more... ok, a lot -KC + static LLCachedControl disable_constraints(gSavedSettings,"DisableCameraConstraints"); + return disable_constraints ? INT_MAX : llmin(MAX_CAMERA_DISTANCE_FROM_OBJECT, + mDrawDistance - 1, // convenience, don't hit draw limit when focusing on something + LLWorld::getInstance()->getRegionWidthInMeters() - CAMERA_FUDGE_FROM_OBJECT); +} //----------------------------------------------------------------------------- // handleScrollWheel() diff --git a/indra/newview/llagentcamera.h b/indra/newview/llagentcamera.h index 98296e8a8a..5384db0b8f 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -117,6 +117,8 @@ public: private: /** Determines default camera offset depending on the current camera preset */ LLVector3 getCameraOffsetInitial(); + /** Determines maximum camera distance from target for mouselook, opposite to LAND_MIN_ZOOM */ + F32 getCameraMaxZoomDistance(); /** Camera preset in Third Person Mode */ ECameraPreset mCameraPreset; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 8ca2d331a3..df3120526e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -42,6 +42,7 @@ #include "llagentlanguage.h" #include "llagentui.h" #include "llagentwearables.h" +#include "lldirpicker.h" #include "llfloaterimcontainer.h" #include "llimprocessing.h" #include "llwindow.h" @@ -1275,6 +1276,8 @@ bool LLAppViewer::init() } } +// don't nag developers who need to run the executable directly +#if LL_RELEASE_FOR_DOWNLOAD // Disable VMP // MAINT-8305: If we're processing a SLURL, skip the launcher check. if (gSavedSettings.getString("CmdLineLoginLocation").empty() && !beingDebugged()) @@ -1293,6 +1296,7 @@ bool LLAppViewer::init() // } //} // +#endif #if LL_WINDOWS if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) @@ -1862,12 +1866,10 @@ bool LLAppViewer::doFrame() saveFinalSnapshot(); } - // Cut down wait on logout; Need to terminate voice here because we need gServicePump! if (LLVoiceClient::instanceExists()) { LLVoiceClient::getInstance()->terminate(); } - // delete gServicePump; @@ -1972,13 +1974,6 @@ bool LLAppViewer::cleanup() // Give any remaining SLPlugin instances a chance to exit cleanly. LLPluginProcessParent::shutdown(); - // Cut down wait on logout; Need to terminate voice earlier because we need gServicePump! - //if (LLVoiceClient::instanceExists()) - //{ - // LLVoiceClient::getInstance()->terminate(); - //} - // - disconnectViewer(); LL_INFOS() << "Viewer disconnected" << LL_ENDL; @@ -2143,6 +2138,8 @@ bool LLAppViewer::cleanup() // (Deleted observers should have already removed themselves) gInventory.cleanupInventory(); + LLCoros::getInstance()->printActiveCoroutines(); + LL_INFOS() << "Cleaning up Selections" << LL_ENDL; // Clean up selection managers after UI is destroyed, as UI may be observing them. @@ -2368,6 +2365,7 @@ bool LLAppViewer::cleanup() mAppCoreHttp.cleanup(); SUBSYSTEM_CLEANUP(LLFilePickerThread); + SUBSYSTEM_CLEANUP(LLDirPickerThread); //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl) delete sTextureCache; @@ -2538,6 +2536,7 @@ bool LLAppViewer::initThreads() gMeshRepo.init(); LLFilePickerThread::initClass(); + LLDirPickerThread::initClass(); // *FIX: no error handling here! return true; @@ -5439,7 +5438,7 @@ void LLAppViewer::idle() LLSmoothInterpolation::updateInterpolants(); LLMortician::updateClass(); LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify() - + LLDirPickerThread::clearDead(); F32 dt_raw = idle_timer.getElapsedTimeAndResetF32(); // Cap out-of-control frame times diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 663651ae0c..41aac017a1 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -541,10 +541,24 @@ public: registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenuHandleAvatar = menu->getHandle(); + if (menu) + { + mPopupMenuHandleAvatar = menu->getHandle(); + } + else + { + LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; + } menu = LLUICtrlFactory::getInstance()->createFromFile("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenuHandleObject = menu->getHandle(); + if (menu) + { + mPopupMenuHandleObject = menu->getHandle(); + } + else + { + LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; + } setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::showInspector, this)); @@ -636,7 +650,12 @@ public: } mUserNameFont = style_params.font(); - LLTextBox* user_name = getChild("user_name"); + if (!mUserNameTextBox) + { + mUserNameTextBox = getChild("user_name"); + mTimeBoxTextBox = getChild("time_box"); + } + LLTextBox* user_name = mUserNameTextBox; user_name->setReadOnlyColor(style_params.readonly_color()); user_name->setColor(style_params.color()); diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index 5c4f0f4d5d..b8e6e81ee6 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -77,6 +77,14 @@ LLDirPicker::LLDirPicker() : mFileName(NULL), mLocked(false) { + bi.hwndOwner = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = NULL; + bi.lpszTitle = NULL; + bi.ulFlags = BIF_USENEWUI; + bi.lpfn = NULL; + bi.lParam = NULL; + bi.iImage = 0; } LLDirPicker::~LLDirPicker() @@ -84,7 +92,7 @@ LLDirPicker::~LLDirPicker() // nothing } -BOOL LLDirPicker::getDir(std::string* filename) +BOOL LLDirPicker::getDir(std::string* filename, bool blocking) { if( mLocked ) { @@ -99,39 +107,39 @@ BOOL LLDirPicker::getDir(std::string* filename) BOOL success = FALSE; - // Modal, so pause agent - send_agent_pause(); + + if (blocking) + { + // Modal, so pause agent + send_agent_pause(); + } - BROWSEINFO bi; - memset(&bi, 0, sizeof(bi)); + bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); - bi.ulFlags = BIF_USENEWUI; - bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); - bi.lpszTitle = NULL; + ::OleInitialize(NULL); + LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi); - ::OleInitialize(NULL); + if(pIDL != NULL) + { + WCHAR buffer[_MAX_PATH] = {'\0'}; - LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi); + if(::SHGetPathFromIDList(pIDL, buffer) != 0) + { + // Set the string value. - if(pIDL != NULL) - { - WCHAR buffer[_MAX_PATH] = {'\0'}; + mDir = utf16str_to_utf8str(llutf16string(buffer)); + success = TRUE; + } + // free the item id list + CoTaskMemFree(pIDL); + } - if(::SHGetPathFromIDList(pIDL, buffer) != 0) - { - // Set the string value. + ::OleUninitialize(); - mDir = utf16str_to_utf8str(llutf16string(buffer)); - success = TRUE; - } - - // free the item id list - CoTaskMemFree(pIDL); - } - - ::OleUninitialize(); - - send_agent_resume(); + if (blocking) + { + send_agent_resume(); + } // Account for the fact that the app has been stalled. LLFrameTimer::updateFrameTime(); @@ -167,7 +175,7 @@ void LLDirPicker::reset() //static -BOOL LLDirPicker::getDir(std::string* filename) +BOOL LLDirPicker::getDir(std::string* filename, bool blocking) { LLFilePicker::ELoadFilter filter=LLFilePicker::FFLOAD_DIRECTORY; @@ -201,7 +209,7 @@ void LLDirPicker::reset() mFilePicker->reset(); } -BOOL LLDirPicker::getDir(std::string* filename) +BOOL LLDirPicker::getDir(std::string* filename, bool blocking) { reset(); @@ -256,7 +264,7 @@ void LLDirPicker::reset() { } -BOOL LLDirPicker::getDir(std::string* filename) +BOOL LLDirPicker::getDir(std::string* filename, bool blocking) { return FALSE; } @@ -267,3 +275,94 @@ std::string LLDirPicker::getDirName() } #endif + + +LLMutex* LLDirPickerThread::sMutex = NULL; +std::queue LLDirPickerThread::sDeadQ; + +void LLDirPickerThread::getFile() +{ +#if LL_WINDOWS + start(); +#else + run(); +#endif +} + +//virtual +void LLDirPickerThread::run() +{ +#if LL_WINDOWS + bool blocking = false; +#else + bool blocking = true; // modal +#endif + + LLDirPicker picker; + + if (picker.getDir(&mProposedName, blocking)) + { + mResponses.push_back(picker.getDirName()); + } + + { + LLMutexLock lock(sMutex); + sDeadQ.push(this); + } + +} + +//static +void LLDirPickerThread::initClass() +{ + sMutex = new LLMutex(); +} + +//static +void LLDirPickerThread::cleanupClass() +{ + clearDead(); + + delete sMutex; + sMutex = NULL; +} + +//static +void LLDirPickerThread::clearDead() +{ + if (!sDeadQ.empty()) + { + LLMutexLock lock(sMutex); + while (!sDeadQ.empty()) + { + LLDirPickerThread* thread = sDeadQ.front(); + thread->notify(thread->mResponses); + delete thread; + sDeadQ.pop(); + } + } +} + +LLDirPickerThread::LLDirPickerThread(const dir_picked_signal_t::slot_type& cb, const std::string &proposed_name) + : LLThread("dir picker"), + mFilePickedSignal(NULL) +{ + mFilePickedSignal = new dir_picked_signal_t(); + mFilePickedSignal->connect(cb); +} + +LLDirPickerThread::~LLDirPickerThread() +{ + delete mFilePickedSignal; +} + +void LLDirPickerThread::notify(const std::vector& filenames) +{ + if (!filenames.empty()) + { + if (mFilePickedSignal) + { + (*mFilePickedSignal)(filenames, mProposedName); + } + } +} diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h index 8656b23afd..c7dba12130 100644 --- a/indra/newview/lldirpicker.h +++ b/indra/newview/lldirpicker.h @@ -33,6 +33,13 @@ #include "stdtypes.h" +#include "llthread.h" +#include + +#if LL_WINDOWS +#include +#endif + #if LL_DARWIN // AssertMacros.h does bad things. @@ -53,7 +60,7 @@ public: // calling this before main() is undefined static LLDirPicker& instance( void ) { return sInstance; } - BOOL getDir(std::string* filename); + BOOL getDir(std::string* filename, bool blocking = true); std::string getDirName(); // clear any lists of buffers or whatever, and make sure the dir @@ -76,11 +83,15 @@ private: LLFilePicker *mFilePicker; #endif + std::string* mFileName; std::string mDir; bool mLocked; static LLDirPicker sInstance; +#if LL_WINDOWS + BROWSEINFO bi; +#endif public: // don't call these directly please. @@ -88,4 +99,33 @@ public: ~LLDirPicker(); }; +class LLDirPickerThread : public LLThread +{ +public: + + static std::queue sDeadQ; + static LLMutex* sMutex; + + static void initClass(); + static void cleanupClass(); + static void clearDead(); + + std::vector mResponses; + std::string mProposedName; + + typedef boost::signals2::signal& filenames, std::string proposed_name)> dir_picked_signal_t; + + LLDirPickerThread(const dir_picked_signal_t::slot_type& cb, const std::string &proposed_name); + ~LLDirPickerThread(); + + void getFile(); + + virtual void run(); + + virtual void notify(const std::vector& filenames); + +private: + dir_picked_signal_t* mFilePickedSignal; +}; + #endif diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 329d5f1b73..846edf8bae 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -333,6 +333,9 @@ void LLDrawPoolAlpha::render(S32 pass) gGL.diffuseColor4f(0, 0, 1, 1); pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + gGL.diffuseColor4f(0, 1, 0, 1); + pushBatches(LLRenderPass::PASS_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE); + if(shaders) { gHighlightProgram.unbind(); diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index beb270e711..bc44ccc162 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -67,13 +67,10 @@ #if LL_DARWIN const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_mac.%s.txt"; #elif LL_LINUX const char FEATURE_TABLE_FILENAME[] = "featuretable_linux.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_linux.%s.txt"; #else const char FEATURE_TABLE_FILENAME[] = "featuretable.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable.%s.txt"; #endif #if 0 // consuming code in #if 0 below @@ -278,33 +275,11 @@ bool LLFeatureManager::loadFeatureTables() app_path += gDirUtilp->getDirDelimiter(); std::string filename; - std::string http_filename; filename = FEATURE_TABLE_FILENAME; - http_filename = llformat(FEATURE_TABLE_VER_FILENAME, LLVersionInfo::getShortVersion().c_str()); // use getShortVersion instead of getVersion. app_path += filename; - // second table is downloaded with HTTP - note that this will only be used on the run _after_ it is downloaded - std::string http_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, http_filename); - - // use HTTP table if it exists - std::string path; - bool parse_ok = false; - if (gDirUtilp->fileExists(http_path)) - { - parse_ok = parseFeatureTable(http_path); - if (!parse_ok) - { - // the HTTP table failed to parse, so delete it - LLFile::remove(http_path); - LL_WARNS("RenderInit") << "Removed invalid feature table '" << http_path << "'" << LL_ENDL; - } - } - - if (!parse_ok) - { - parse_ok = parseFeatureTable(app_path); - } + bool parse_ok = parseFeatureTable(app_path); return parse_ok; } @@ -412,16 +387,22 @@ bool LLFeatureManager::loadGPUClass() if (!gSavedSettings.getBOOL("SkipBenchmark")) { //get memory bandwidth from benchmark - - // Allow to skip gpu_benchmark with -noprobe. - // This can make sense for some Intel GPUs which can take 15+ Minutes or crash during gpu_benchmark - - // F32 gbps = gpu_benchmark(); - F32 gbps = -1.0f; - if( !gSavedSettings.getBOOL( "NoHardwareProbe" ) ) - gbps = gpu_benchmark(); - - // + F32 gbps; + try + { + // Allow to skip gpu_benchmark with -noprobe. + // This can make sense for some Intel GPUs which can take 15+ Minutes or crash during gpu_benchmark + // gbps = gpu_benchmark(); + gbps = -1.0f; + if( !gSavedSettings.getBOOL( "NoHardwareProbe" ) ) + gbps = gpu_benchmark(); + // + } + catch (const std::exception& e) + { + gbps = -1.f; + LL_WARNS("RenderInit") << "GPU benchmark failed: " << e.what() << LL_ENDL; + } if (gbps < 0.f) { //couldn't bench, use GLVersion @@ -500,88 +481,6 @@ bool LLFeatureManager::loadGPUClass() return true; // indicates that a gpu value was established } -void LLFeatureManager::fetchFeatureTableCoro(std::string tableName) -{ - LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FeatureManagerHTTPTable", httpPolicy)); - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable"); - - // Re-enable feature table download -//#if LL_WINDOWS -// std::string os_string = LLOSInfo::instance().getOSStringSimple(); -// std::string filename; -// -// if (os_string.find("Microsoft Windows XP") == 0) -// { -// filename = llformat(tableName.c_str(), "_xp", LLVersionInfo::getVersion().c_str()); -// } -// else -// { -// filename = llformat(tableName.c_str(), "", LLVersionInfo::getVersion().c_str()); -// } -//#else -// const std::string filename = llformat(tableName.c_str(), LLVersionInfo::getVersion().c_str()); -//#endif - const std::string filename = llformat(tableName.c_str(), LLVersionInfo::getShortVersion().c_str()); - // - - std::string url = base + "/" + filename; - // testing url below - //url = "http://viewer-settings.secondlife.com/featuretable.2.1.1.208406.txt"; - const std::string path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); - - - // Re-enable feature table download - //LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL; - - //LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url); - time_t last_modified = 0; - llstat stat_data; - if(!LLFile::stat(path, &stat_data)) - { - last_modified = stat_data.st_mtime; - } - LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); - httpOpts->setWantHeaders(true); - httpOpts->setLastModified((long)last_modified); - LL_INFOS() << "LLFeatureManager fetching " << url << " with last modifed of " << last_modified << " into " << path << LL_ENDL; - LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts); - // - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - // Re-enable feature table download - //if (status) - if (status == LLCore::HttpStatus(HTTP_OK)) - // - { // There was a newer feature table on the server. We've grabbed it and now should write it. - // write to file - const LLSD::Binary &raw = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary(); - - LL_INFOS() << "writing feature table to " << path << LL_ENDL; - - S32 size = raw.size(); - if (size > 0) - { - // write to file - LLAPRFile out(path, LL_APR_WB); - out.write(raw.data(), size); - out.close(); - } - } -} - -// fetch table(s) from a website (S3) -void LLFeatureManager::fetchHTTPTables() -{ - LLCoros::instance().launch("LLFeatureManager::fetchFeatureTableCoro", - boost::bind(&LLFeatureManager::fetchFeatureTableCoro, this, FEATURE_TABLE_VER_FILENAME)); -} - void LLFeatureManager::cleanupFeatureTables() { std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer()); diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 54bd07329a..f77861a1a7 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -145,9 +145,6 @@ public: // in the skip list if true void applyFeatures(bool skipFeatures); - // load the dynamic GPU/feature table from a website - void fetchHTTPTables(); - LLSD getRecommendedSettingsMap(); protected: @@ -158,8 +155,6 @@ protected: void initBaseMask(); - void fetchFeatureTableCoro(std::string name); - std::map mMaskList; std::set mSkippedFeatures; BOOL mInited; diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 01a91f700f..268de7eba3 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -45,6 +45,7 @@ #include "llcombobox.h" #include "llfloaterreg.h" #include "llfloateravatarpicker.h" +#include "llfloaterauction.h" #include "llfloatergroups.h" #include "llfloaterscriptlimits.h" #include "llavataractions.h" @@ -78,7 +79,6 @@ #include "llpanelexperiencelisteditor.h" #include "llpanelexperiencepicker.h" #include "llexperiencecache.h" -#include "llweb.h" #include "llgroupactions.h" #include "llsdutil_math.h" @@ -567,7 +567,7 @@ void LLPanelLandGeneral::refresh() mBtnDeedToGroup->setEnabled(FALSE); mBtnSetGroup->setEnabled(FALSE); - mBtnStartAuction->setEnabled(LLGridManager::instance().isInSecondLife()); // Restore land auction floater for OpenSim + mBtnStartAuction->setEnabled(FALSE); mCheckDeedToGroup ->set(FALSE); mCheckDeedToGroup ->setEnabled(FALSE); @@ -667,7 +667,7 @@ void LLPanelLandGeneral::refresh() mTextClaimDate->setEnabled(FALSE); mTextGroup->setText(getString("none_text")); mTextGroup->setEnabled(FALSE); - mBtnStartAuction->setEnabled(LLGridManager::instance().isInSecondLife()); // Restore land auction floater for OpenSim + mBtnStartAuction->setEnabled(FALSE); } else { @@ -723,12 +723,10 @@ void LLPanelLandGeneral::refresh() mTextClaimDate->setText(claim_date_str); mTextClaimDate->setEnabled(is_leased); - // Restore land auction floater for OpenSim BOOL enable_auction = (gAgent.getGodLevel() >= GOD_LIAISON) && (owner_id == GOVERNOR_LINDEN_ID) && (parcel->getAuctionID() == 0); - mBtnStartAuction->setEnabled(enable_auction || LLGridManager::instance().isInSecondLife()); - // + mBtnStartAuction->setEnabled(enable_auction); } // Display options @@ -1082,32 +1080,20 @@ void LLPanelLandGeneral::onClickBuyPass(void* data) // static void LLPanelLandGeneral::onClickStartAuction(void* data) { - // Restore land auction floater for OpenSim - //std::string auction_url = "https://places.[GRID]/auctions/"; - //LLWeb::loadURLExternal(LLWeb::expandURLSubstitutions(auction_url, LLSD())); - if (LLGridManager::instance().isInSecondLife()) + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcelp = panelp->mParcel->getParcel(); + if(parcelp) { - std::string auction_url = "https://places.[GRID]/auctions/"; - LLWeb::loadURLExternal(LLWeb::expandURLSubstitutions(auction_url, LLSD())); - } - else - { - LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; - LLParcel* parcelp = panelp->mParcel->getParcel(); - if (parcelp) + if(parcelp->getForSale()) { - if (parcelp->getForSale()) - { - LLNotificationsUtil::add("CannotStartAuctionAlreadyForSale"); - } - else - { - //LLFloaterAuction::showInstance(); - LLFloaterReg::showInstance("auction"); - } + LLNotificationsUtil::add("CannotStartAuctionAlreadyForSale"); + } + else + { + //LLFloaterAuction::showInstance(); + LLFloaterReg::showInstance("auction"); } } - // } // static diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp index cc94ef71d9..9805d2d68b 100644 --- a/indra/newview/llfloaternotificationstabbed.cpp +++ b/indra/newview/llfloaternotificationstabbed.cpp @@ -412,7 +412,8 @@ void LLFloaterNotificationsTabbed::onStoreToast(LLPanel* info_panel, LLUUID id) p.notification_name = notify->getName(); p.transaction_id = payload["transaction_id"]; p.group_id = payload["group_id"]; - p.fee = payload["fee"]; + p.fee = payload["fee"]; + p.use_offline_cap = payload["use_offline_cap"].asInteger(); p.subject = payload["subject"].asString(); p.message = payload["message"].asString(); // Unscrew avatar icon for transaction messages diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 43dcab6a5c..3e0b0803e2 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1661,16 +1661,15 @@ void LLFloaterPreference::onClickSetCache() std::string proposed_name(cur_name); - LLDirPicker& picker = LLDirPicker::instance(); - if (! picker.getDir(&proposed_name ) ) - { - return; //Canceled! - } + (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeCachePath, this, _1, _2), proposed_name))->getFile(); +} - std::string dir_name = picker.getDirName(); - if (!dir_name.empty() && dir_name != cur_name) +void LLFloaterPreference::changeCachePath(const std::vector& filenames, std::string proposed_name) +{ + std::string dir_name = filenames[0]; + if (!dir_name.empty() && dir_name != proposed_name) { - std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name)); + std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name)); LLNotificationsUtil::add("CacheWillBeMoved"); gSavedSettings.setString("NewCacheLocation", dir_name); gSavedSettings.setString("NewCacheLocationTopFolder", new_top_folder); @@ -1722,14 +1721,13 @@ void LLFloaterPreference::onClickSetSoundCache() std::string cur_name(gSavedSettings.getString("FSSoundCacheLocation")); std::string proposed_name(cur_name); - LLDirPicker& picker = LLDirPicker::instance(); - if (! picker.getDir(&proposed_name ) ) - { - return; //Canceled! - } + (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeSoundCachePath, this, _1, _2), proposed_name))->getFile(); +} - std::string dir_name = picker.getDirName(); - if (!dir_name.empty() && dir_name != cur_name) +void LLFloaterPreference::changeSoundCachePath(const std::vector& filenames, std::string proposed_name) +{ + std::string dir_name = filenames[0]; + if (!dir_name.empty() && dir_name != proposed_name) { gSavedSettings.setString("FSSoundCacheLocation", dir_name); setSoundCacheLocation(dir_name); @@ -1831,19 +1829,17 @@ void LLFloaterPreference::onClickClearSpamList() void LLFloaterPreference::setPreprocInclude() { std::string cur_name(gSavedSettings.getString("_NACL_PreProcHDDIncludeLocation")); - std::string proposed_name(cur_name); - LLDirPicker& picker = LLDirPicker::instance(); - if (! picker.getDir(&proposed_name ) ) - { - return; //Canceled! - } + (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changePreprocIncludePath, this, _1, _2), proposed_name))->getFile(); +} - std::string dir_name = picker.getDirName(); - if (!dir_name.empty() && dir_name != cur_name) +void LLFloaterPreference::changePreprocIncludePath(const std::vector& filenames, std::string proposed_name) +{ + std::string dir_name = filenames[0]; + if (!dir_name.empty() && dir_name != proposed_name) { - std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name)); + std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name)); gSavedSettings.setString("_NACL_PreProcHDDIncludeLocation", dir_name); } } @@ -2848,25 +2844,21 @@ void LLFloaterPreference::onClickLogPath() std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath")); mPriorInstantMessageLogPath.clear(); - LLDirPicker& picker = LLDirPicker::instance(); - //Launches a directory picker and waits for feedback - if (!picker.getDir(&proposed_name ) ) - { - return; //Canceled! - } - //Gets the path from the directory picker - std::string dir_name = picker.getDirName(); - - //Path changed - if(proposed_name != dir_name) - { - gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); - mPriorInstantMessageLogPath = proposed_name; - - // enable/disable 'Delete transcripts button - updateDeleteTranscriptsButton(); + (new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeLogPath, this, _1, _2), proposed_name))->getFile(); } + +void LLFloaterPreference::changeLogPath(const std::vector& filenames, std::string proposed_name) +{ + //Path changed + if (proposed_name != filenames[0]) + { + gSavedPerAccountSettings.setString("InstantMessageLogPath", filenames[0]); + mPriorInstantMessageLogPath = proposed_name; + + // enable/disable 'Delete transcripts button + updateDeleteTranscriptsButton(); + } //[FIX FIRE-2765 : SJ] Enable Reset button when own Chatlogdirectory is set getChildView("reset_logpath")->setEnabled(TRUE); } @@ -4883,16 +4875,17 @@ BOOL FSPanelPreferenceBackup::postBuild() void FSPanelPreferenceBackup::onClickSetBackupSettingsPath() { std::string dir_name = gSavedSettings.getString("SettingsBackupPath"); - LLDirPicker& picker = LLDirPicker::instance(); - if (!picker.getDir(&dir_name)) - { - // canceled - return; - } + (new LLDirPickerThread(boost::bind(&FSPanelPreferenceBackup::changeBackupSettingsPath, this, _1, _2), dir_name))->getFile(); +} - dir_name = picker.getDirName(); - gSavedSettings.setString("SettingsBackupPath", dir_name); - getChild("settings_backup_path")->setValue(dir_name); +void FSPanelPreferenceBackup::changeBackupSettingsPath(const std::vector& filenames, std::string proposed_name) +{ + std::string dir_name = filenames[0]; + if (!dir_name.empty() && dir_name != proposed_name) + { + gSavedSettings.setString("SettingsBackupPath", dir_name); + getChild("settings_backup_path")->setValue(dir_name); + } } void FSPanelPreferenceBackup::onClickBackupSettings() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 0453925823..ec0f820ce0 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -171,6 +171,7 @@ public: // Sound cache void setSoundCacheLocation(const LLStringExplicit& location); void onClickSetSoundCache(); + void changeSoundCachePath(const std::vector& filenames, std::string proposed_name); void onClickBrowseSoundCache(); void onClickResetSoundCache(); // @@ -179,6 +180,7 @@ public: void onClickResetVoice(); void onClickSetCache(); + void changeCachePath(const std::vector& filenames, std::string proposed_name); void onClickBrowseCache(); void onClickBrowseCrashLogs(); void onClickBrowseChatLogDir(); @@ -195,11 +197,13 @@ public: // void onClickSetSounds(); // Handled centrally now void onClickPreviewUISound(const LLSD& ui_sound_id); // FIRE-8190: Preview function for "UI Sounds" Panel void setPreprocInclude(); + void changePreprocIncludePath(const std::vector& filenames, std::string proposed_name); void onClickEnablePopup(); void onClickDisablePopup(); void resetAllIgnored(); void setAllIgnored(); void onClickLogPath(); + void changeLogPath(const std::vector& filenames, std::string proposed_name); bool moveTranscriptsAndLog(); //[FIX FIRE-2765 : SJ] Making sure Reset button resets works void onClickResetLogPath(); @@ -472,6 +476,7 @@ public: protected: // Backup settings void onClickSetBackupSettingsPath(); + void changeBackupSettingsPath(const std::vector& filenames, std::string proposed_name); void onClickSelectAll(); void onClickDeselectAll(); void onClickBackupSettings(); diff --git a/indra/newview/llfloaterscriptedprefs.cpp b/indra/newview/llfloaterscriptedprefs.cpp index 300061696b..c7fc91a52e 100644 --- a/indra/newview/llfloaterscriptedprefs.cpp +++ b/indra/newview/llfloaterscriptedprefs.cpp @@ -91,17 +91,15 @@ void LLFloaterScriptEdPrefs::getUIColor(LLUICtrl* ctrl, const LLSD& param) void LLFloaterScriptEdPrefs::setPreprocInclude() { std::string cur_name(gSavedSettings.getString("_NACL_PreProcHDDIncludeLocation")); - std::string proposed_name(cur_name); - - LLDirPicker& picker = LLDirPicker::instance(); - if (!picker.getDir(&proposed_name )) - { - return; //Canceled! - } - - std::string dir_name = picker.getDirName(); - if (!dir_name.empty() && dir_name != cur_name) + + (new LLDirPickerThread(boost::bind(&LLFloaterScriptEdPrefs::changePreprocIncludePath, this, _1, _2), proposed_name))->getFile(); +} + +void LLFloaterScriptEdPrefs::changePreprocIncludePath(const std::vector& filenames, std::string proposed_name) +{ + std::string dir_name = filenames[0]; + if (!dir_name.empty() && dir_name != proposed_name) { std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name)); gSavedSettings.setString("_NACL_PreProcHDDIncludeLocation", dir_name); diff --git a/indra/newview/llfloaterscriptedprefs.h b/indra/newview/llfloaterscriptedprefs.h index 8c1a7e0643..87f545caba 100644 --- a/indra/newview/llfloaterscriptedprefs.h +++ b/indra/newview/llfloaterscriptedprefs.h @@ -47,6 +47,7 @@ private: // Port old FS script prefs void setPreprocInclude(); + void changePreprocIncludePath(const std::vector& filenames, std::string proposed_name); LLScriptEditor* mEditor; }; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index eaae58ae38..711afc506a 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1495,30 +1495,15 @@ void LLFloaterSnapshot::saveTexture() previewp->saveTexture(); } -// Threaded filepickers -//BOOL LLFloaterSnapshot::saveLocal() -void LLFloaterSnapshot::saveLocal(boost::function callback) -// +void LLFloaterSnapshot::saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { LL_DEBUGS() << "saveLocal" << LL_ENDL; LLSnapshotLivePreview* previewp = getPreviewView(); - if (!previewp) + llassert(previewp != NULL); + if (previewp) { - llassert(previewp != NULL); - // Threaded filepickers - //return FALSE; - if (callback) - { - callback(false); - } - return; - // + previewp->saveLocal(success_cb, failure_cb); } - - // Threaded filepickers - //return previewp->saveLocal(); - previewp->saveLocal(callback); - // } void LLFloaterSnapshotBase::postSave() diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index fc99e8b7f7..802f8b51f4 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -159,10 +159,9 @@ public: static LLFloaterSnapshot* getInstance(); static LLFloaterSnapshot* findInstance(); /*virtual*/ void saveTexture(); - // Threaded filepickers - //BOOL saveLocal(); - void saveLocal(boost::function callback); - // + + typedef boost::signals2::signal snapshot_saved_signal_t; + void saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); static void setAgentEmail(const std::string& email); BOOL isWaitingState(); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index ff411782fe..b7015a5a7b 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -1106,15 +1106,6 @@ private: //----------------------------------------------------------------------------- F32 gpu_benchmark() { -#if LL_WINDOWS - if (gGLManager.mIsIntel - && std::string::npos != LLOSInfo::instance().getOSStringSimple().find("Microsoft Windows 8")) // or 8.1 - { // don't run benchmark on Windows 8/8.1 based PCs with Intel GPU (MAINT-8197) - LL_WARNS() << "Skipping gpu_benchmark() for Intel graphics on Windows 8." << LL_ENDL; - return -1.f; - } -#endif - if (!gGLManager.mHasShaderObjects || !gGLManager.mHasTimerQuery) { // don't bother benchmarking the fixed function // or venerable drivers which don't support accurate timing anyway diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 865cfa3a96..aedf31f2cf 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1284,10 +1284,11 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, LLSD payload; payload["transaction_id"] = session_id; - payload["group_id"] = from_id; + payload["group_id"] = from_group ? from_id : aux_id; payload["name"] = name; payload["message"] = message; payload["fee"] = membership_fee; + payload["use_offline_cap"] = session_id.isNull() && (offline == IM_OFFLINE); LLSD args; args["MESSAGE"] = message; @@ -2118,8 +2119,12 @@ void LLIMProcessing::requestOfflineMessages() // Auto-accepted inventory items may require the avatar object // to build a correct name. Likewise, inventory offers from // muted avatars require the mute list to properly mute. - if (cap_url.empty() || !gSavedSettings.getBOOL("FSUseReadOfflineMsgsCap")) + if (cap_url.empty() + || gAgent.getRegionCapability("AcceptFriendship").empty() + || gAgent.getRegionCapability("AcceptGroupInvite").empty()) { + // Offline messages capability provides no session/transaction ids for message AcceptFriendship and IM_GROUP_INVITATION to work + // So make sure we have the caps before using it. requestOfflineMessagesLegacy(); } else @@ -2220,7 +2225,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) message_data["to_agent_id"].asUUID(), IM_OFFLINE, (EInstantMessage)message_data["dialog"].asInteger(), - LLUUID::null, // session id, fix this for friendship offers to work + LLUUID::null, // session id, since there is none we can only use frienship/group invite caps message_data["timestamp"].asInteger(), message_data["from_agent_name"].asString(), message_data["message"].asString(), diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp index 66ad5c0b7b..99c6ffcba1 100644 --- a/indra/newview/llnotificationlistitem.cpp +++ b/indra/newview/llnotificationlistitem.cpp @@ -324,38 +324,15 @@ void LLGroupInviteNotificationListItem::onClickJoinBtn() return; } - if(mParams.fee > 0) - { - LLSD args; - args["COST"] = llformat("%d", mParams.fee); - // Set the fee for next time to 0, so that we don't keep - // asking about a fee. - LLSD next_payload; - next_payload["group_id"]= mParams.group_id; - next_payload["transaction_id"]= mParams.transaction_id; - next_payload["fee"] = 0; - LLNotificationsUtil::add("JoinGroupCanAfford", args, next_payload); - } - else - { - send_improved_im(mParams.group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_ACCEPT, - mParams.transaction_id); - } + send_join_group_response(mParams.group_id, mParams.transaction_id, true, mParams.fee, mParams.use_offline_cap); + LLNotificationListItem::onClickCloseBtn(); } void LLGroupInviteNotificationListItem::onClickDeclineBtn() { - send_improved_im(mParams.group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_DECLINE, - mParams.transaction_id); + send_join_group_response(mParams.group_id, mParams.transaction_id, false, mParams.fee, mParams.use_offline_cap); + LLNotificationListItem::onClickCloseBtn(); } diff --git a/indra/newview/llnotificationlistitem.h b/indra/newview/llnotificationlistitem.h index d2d90b35e3..cfcd90f782 100644 --- a/indra/newview/llnotificationlistitem.h +++ b/indra/newview/llnotificationlistitem.h @@ -60,6 +60,7 @@ public: // std::string sender; S32 fee; + U8 use_offline_cap; LLDate time_stamp; LLDate received_time; LLSD inventory_offer; diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index f9a794ab0d..ca089eb5ab 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1180,72 +1180,72 @@ void LLOutfitGallery::refreshTextures(const LLUUID& category_id) void LLOutfitGallery::uploadPhoto(LLUUID outfit_id) { - outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); - if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull()) - { - return; - } + outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id); + if (outfit_it == mOutfitMap.end() || outfit_it->first.isNull()) + { + return; + } + (new LLFilePickerReplyThread(boost::bind(&LLOutfitGallery::uploadOutfitImage, this, _1, outfit_id), LLFilePicker::FFLOAD_IMAGE, false))->getFile(); +} - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) +void LLOutfitGallery::uploadOutfitImage(const std::vector& filenames, LLUUID outfit_id) +{ + std::string filename = filenames[0]; + LLLocalBitmap* unit = new LLLocalBitmap(filename); + if (unit->getValid()) { - std::string filename = picker.getFirstFile(); - LLLocalBitmap* unit = new LLLocalBitmap(filename); - if (unit->getValid()) + std::string exten = gDirUtilp->getExtension(filename); + U32 codec = LLImageBase::getCodecFromExtension(exten); + + LLImageDimensionsInfo image_info; + std::string image_load_error; + if (!image_info.load(filename, codec)) { - std::string exten = gDirUtilp->getExtension(filename); - U32 codec = LLImageBase::getCodecFromExtension(exten); - - LLImageDimensionsInfo image_info; - std::string image_load_error; - if (!image_info.load(filename, codec)) - { - image_load_error = image_info.getLastError(); - } - - S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; - S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; - - if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) - { - LLStringUtil::format_map_t args; - args["WIDTH"] = llformat("%d", max_width); - args["HEIGHT"] = llformat("%d", max_height); - - image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args); - } - - if (!image_load_error.empty()) - { - LLSD subst; - subst["REASON"] = image_load_error; - LLNotificationsUtil::add("OutfitPhotoLoadError", subst); - return; - } - - S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). - void *nruserdata = NULL; - nruserdata = (void *)&outfit_id; - - LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id); - if (!outfit_cat) return; - updateSnapshotFolderObserver(); - checkRemovePhoto(outfit_id); - std::string upload_pending_name = outfit_id.asString(); - std::string upload_pending_desc = ""; - LLAssetStorage::LLStoreAssetCallback callback = NULL; - LLUUID photo_id = upload_new_resource(filename, // file - upload_pending_name, - upload_pending_desc, - 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms("Uploads"), - LLFloaterPerms::getGroupPerms("Uploads"), - LLFloaterPerms::getEveryonePerms("Uploads"), - upload_pending_name, callback, expected_upload_cost, nruserdata); - mOutfitLinkPending = outfit_id; + image_load_error = image_info.getLastError(); } - delete unit; + + S32 max_width = MAX_OUTFIT_PHOTO_WIDTH; + S32 max_height = MAX_OUTFIT_PHOTO_HEIGHT; + + if ((image_info.getWidth() > max_width) || (image_info.getHeight() > max_height)) + { + LLStringUtil::format_map_t args; + args["WIDTH"] = llformat("%d", max_width); + args["HEIGHT"] = llformat("%d", max_height); + + image_load_error = LLTrans::getString("outfit_photo_load_dimensions_error", args); + } + + if (!image_load_error.empty()) + { + LLSD subst; + subst["REASON"] = image_load_error; + LLNotificationsUtil::add("OutfitPhotoLoadError", subst); + return; + } + + S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). + void *nruserdata = NULL; + nruserdata = (void *)&outfit_id; + + LLViewerInventoryCategory *outfit_cat = gInventory.getCategory(outfit_id); + if (!outfit_cat) return; + updateSnapshotFolderObserver(); + checkRemovePhoto(outfit_id); + std::string upload_pending_name = outfit_id.asString(); + std::string upload_pending_desc = ""; + LLAssetStorage::LLStoreAssetCallback callback = NULL; + LLUUID photo_id = upload_new_resource(filename, // file + upload_pending_name, + upload_pending_desc, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms("Uploads"), + LLFloaterPerms::getGroupPerms("Uploads"), + LLFloaterPerms::getEveryonePerms("Uploads"), + upload_pending_name, callback, expected_upload_cost, nruserdata); + mOutfitLinkPending = outfit_id; } + delete unit; } void LLOutfitGallery::linkPhotoToOutfit(LLUUID photo_id, LLUUID outfit_id) diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 383924a7d6..6dd8a6298f 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -130,6 +130,7 @@ protected: private: void loadPhotos(); void uploadPhoto(LLUUID outfit_id); + void uploadOutfitImage(const std::vector& filenames, LLUUID outfit_id); void updateSnapshotFolderObserver(); LLUUID getPhotoAssetId(const LLUUID& outfit_id); LLUUID getDefaultPhoto(); diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 781802d035..90ec357386 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -206,6 +206,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, // change z sort of clickable text to be behind buttons sendChildToBack(getChildView("forgot_password_text")); + sendChildToBack(getChildView("sign_up_text")); LLComboBox* favorites_combo = getChild("start_location_combo"); updateLocationSelectorsVisibility(); // separate so that it can be called from preferences @@ -273,6 +274,9 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLTextBox* forgot_password_text = getChild("forgot_password_text"); forgot_password_text->setClickedCallback(onClickForgotPassword, NULL); + LLTextBox* sign_up_text = getChild("sign_up_text"); + sign_up_text->setClickedCallback(onClickSignUp, NULL); + // get the web browser control LLMediaCtrl* web_browser = getChild("login_html"); web_browser->addObserver(this); @@ -923,6 +927,15 @@ void LLPanelLogin::onClickForgotPassword(void*) } } +//static +void LLPanelLogin::onClickSignUp(void*) +{ + if (sInstance) + { + LLWeb::loadURLExternal(sInstance->getString("sign_up_url")); + } +} + // static void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data) { diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 97fc6f22de..61ec0b4250 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -101,6 +101,7 @@ private: static void onClickNewAccount(void*); static void onClickVersion(void*); static void onClickForgotPassword(void*); + static void onClickSignUp(void*); static void onPassKey(LLLineEditor* caller, void* user_data); static void updateServerCombo(); diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index 67739648e9..ad92a3eaaa 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -1244,12 +1244,12 @@ void LLPanelNearByMedia::onClickSelectedMediaMute() F32 volume = impl->getVolume(); if(volume > 0.0) { - impl->setVolume(0.0); + impl->setMute(true); } else if (mVolumeSlider->getValueF32() == 0.0) { - impl->setVolume(1.0); - mVolumeSlider->setValue(1.0); + impl->setMute(false); + mVolumeSlider->setValue(impl->getVolume()); } else { diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index ed09970f0f..e439eefe07 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -134,6 +134,10 @@ U8 string_value_to_click_action(std::string p_value) { return CLICK_ACTION_ZOOM; } + if (p_value == "None") + { + return CLICK_ACTION_DISABLED; + } return CLICK_ACTION_TOUCH; } @@ -160,6 +164,9 @@ std::string click_action_to_string_value( U8 action) case CLICK_ACTION_ZOOM: return "Zoom"; break; + case CLICK_ACTION_DISABLED: + return "None"; + break; } } @@ -1430,34 +1437,45 @@ void LLPanelPermissions::setAllSaleInfo() LLSaleInfo new_sale_info(sale_type, price); LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(new_sale_info); - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - return object->getClickAction() == CLICK_ACTION_BUY - || object->getClickAction() == CLICK_ACTION_TOUCH; - } - } check_actions; + // Note: won't work right if a root and non-root are both single-selected (here and other places). + BOOL is_perm_modify = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsModify()) + || LLSelectMgr::getInstance()->selectGetModify(); + BOOL is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) + || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced(); - // Selection should only contain objects that are of target - // action already or of action we are aiming to remove. - bool default_actions = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&check_actions); - - if (default_actions && old_sale_info.isForSale() != new_sale_info.isForSale()) + if (is_perm_modify && is_nonpermanent_enforced) { - // FIRE-5273: Change default click action to buy only for modifiable objects - //U8 new_click_action = new_sale_info.isForSale() ? CLICK_ACTION_BUY : CLICK_ACTION_TOUCH; struct f : public LLSelectedObjectFunctor { virtual bool apply(LLViewerObject* object) { - return object->permModify(); + return object->getClickAction() == CLICK_ACTION_BUY + || object->getClickAction() == CLICK_ACTION_TOUCH; } - } modify_checks; - bool allow_modify = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&modify_checks); - U8 new_click_action = (new_sale_info.isForSale() && allow_modify) ? CLICK_ACTION_BUY : CLICK_ACTION_TOUCH; - // - LLSelectMgr::getInstance()->selectionSetClickAction(new_click_action); + } check_actions; + + // Selection should only contain objects that are of target + // action already or of action we are aiming to remove. + bool default_actions = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&check_actions); + + if (default_actions && old_sale_info.isForSale() != new_sale_info.isForSale()) + { + // FIRE-5273: Change default click action to buy only for modifiable objects + //U8 new_click_action = new_sale_info.isForSale() ? CLICK_ACTION_BUY : CLICK_ACTION_TOUCH; + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + return object->permModify(); + } + } modify_checks; + bool allow_modify = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&modify_checks); + U8 new_click_action = (new_sale_info.isForSale() && allow_modify) ? CLICK_ACTION_BUY : CLICK_ACTION_TOUCH; + // + LLSelectMgr::getInstance()->selectionSetClickAction(new_click_action); + } } showMarkForSale(FALSE); diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 4bb7e711ba..c2cc4d26a1 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -63,14 +63,14 @@ private: /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); /*virtual*/ void updateControls(const LLSD& info); - // Threaded filepickers - void saveLocalCallback(bool success); - S32 mLocalFormat; void onFormatComboCommit(LLUICtrl* ctrl); void onQualitySliderCommit(LLUICtrl* ctrl); void onSaveFlyoutCommit(LLUICtrl* ctrl); + + void onLocalSaved(); + void onLocalCanceled(); }; static LLPanelInjector panel_class("llpanelsnapshotlocal"); @@ -185,22 +185,22 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl) LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); floater->notify(LLSD().with("set-working", true)); - // Threaded filepickers - //BOOL saved = floater->saveLocal(); - //if (saved) - //{ - // LLFloaterSnapshot::postSave(); - // floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); - //} - //else - //{ - // cancel(); - // floater->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local"))); - //} - floater->saveLocal(boost::bind(&LLPanelSnapshotLocal::saveLocalCallback, this, _1)); - // + floater->saveLocal((boost::bind(&LLPanelSnapshotLocal::onLocalSaved, this)), (boost::bind(&LLPanelSnapshotLocal::onLocalCanceled, this))); } +void LLPanelSnapshotLocal::onLocalSaved() +{ + mSnapshotFloater->postSave(); + LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); +} + +void LLPanelSnapshotLocal::onLocalCanceled() +{ + //cancel(); // Don't go back to selection + LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local"))); +} + + // Store settings at logout LLPanelSnapshotLocal::~LLPanelSnapshotLocal() { @@ -208,24 +208,6 @@ LLPanelSnapshotLocal::~LLPanelSnapshotLocal() gSavedSettings.setS32("LastSnapshotToDiskWidth", getTypedPreviewWidth()); gSavedSettings.setS32("LastSnapshotToDiskHeight", getTypedPreviewHeight()); } -// - -// Threaded filepickers -void LLPanelSnapshotLocal::saveLocalCallback(bool success) -{ - LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance(); - - if (success) - { - mSnapshotFloater->postSave(); - floater->notify(LLSD().with("set-finished", LLSD().with("ok", true).with("msg", "local"))); - } - else - { - LLNotificationsUtil::add("CannotSaveSnapshot"); - floater->notify(LLSD().with("set-ready", true)); - } -} LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType() { diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 907782f1a1..38794293e2 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -2463,14 +2463,22 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset buffer[file_length] = 0; preview->mScriptEd->setScriptText(LLStringExplicit(&buffer[0]), TRUE); preview->mScriptEd->mEditor->makePristine(); + + std::string script_name = DEFAULT_SCRIPT_NAME; LLInventoryItem* item = gInventory.getItem(*item_uuid); BOOL is_modifiable = FALSE; - if(item - && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), - GP_OBJECT_MANIPULATE)) + if (item) { - is_modifiable = TRUE; + if (!item->getName().empty()) + { + script_name = item->getName(); + } + if (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) + { + is_modifiable = TRUE; + } } + preview->mScriptEd->setScriptName(script_name); preview->mScriptEd->setEnableEditing(is_modifiable); preview->mAssetStatus = PREVIEW_ASSET_LOADED; diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 4226316ad4..a0a8143912 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -1159,6 +1159,8 @@ static U8 string_value_to_click_action(std::string p_value) return CLICK_ACTION_OPEN; if (p_value == "Zoom") return CLICK_ACTION_ZOOM; + if (p_value == "None") + return CLICK_ACTION_DISABLED; return CLICK_ACTION_TOUCH; } diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index de2c6cdc52..deff615eaa 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -70,6 +70,7 @@ S32 BORDER_WIDTH = 6; const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512 std::set LLSnapshotLivePreview::sList; +LLPointer LLSnapshotLivePreview::sSaveLocalImage = NULL; LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p) : LLView(p), @@ -135,6 +136,7 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview() // gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); sList.erase(this); + sSaveLocalImage = NULL; } void LLSnapshotLivePreview::setMaxImageSize(S32 size) @@ -1193,77 +1195,19 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) mDataSize = 0; } -// Threaded filepickers -//BOOL LLSnapshotLivePreview::saveLocal() -//{ -// // Update mFormattedImage if necessary -// getFormattedImage(); -// -// // Save the formatted image -// BOOL success = saveLocal(mFormattedImage); -// -// if(success) -// { -// gViewerWindow->playSnapshotAnimAndSound(); -// } -// 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) +void LLSnapshotLivePreview::saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - // Update mFormattedImage if necessary - getFormattedImage(); - - // Save the formatted image - gViewerWindow->saveImageNumbered(mFormattedImage, false, boost::bind(&LLSnapshotLivePreview::saveLocalCallback, this, _1, callback)); + // Update mFormattedImage if necessary + getFormattedImage(); + + // Save the formatted image + saveLocal(mFormattedImage, success_cb, failure_cb); } -void LLSnapshotLivePreview::saveLocalCallback(bool success, boost::function callback) +//Check if failed due to insufficient memory +void LLSnapshotLivePreview::saveLocal(LLPointer image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - if(success) - { - gViewerWindow->playSnapshotAnimAndSound(); - } + sSaveLocalImage = image; - if (callback) - { - callback(success); - } + gViewerWindow->saveImageNumbered(sSaveLocalImage, FALSE, success_cb, failure_cb); } -// diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 10d21102e3..54b71af20c 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -40,8 +40,9 @@ class LLSnapshotLivePreview : public LLView { LOG_CLASS(LLSnapshotLivePreview); public: + typedef boost::signals2::signal snapshot_saved_signal_t; - //static BOOL saveLocal(LLPointer); // Threaded filepickers + static void saveLocal(LLPointer image, const snapshot_saved_signal_t::slot_type& success_cb = snapshot_saved_signal_t(), const snapshot_saved_signal_t::slot_type& failure_cb = snapshot_saved_signal_t()); struct Params : public LLInitParam::Block { Params() @@ -104,11 +105,7 @@ public: std::string getFilter() const { return mFilterName; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); void saveTexture(BOOL outfit_snapshot = FALSE, std::string name = ""); - // Threaded filepickers - //BOOL saveLocal(); - void saveLocal(boost::function callback); - void saveLocalCallback(bool success, boost::function callback); - // + void saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); LLPointer getFormattedImage(); LLPointer getEncodedImage(); @@ -184,7 +181,9 @@ private: LLQuaternion mCameraRot; BOOL mSnapshotActive; LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType; - std::string mFilterName; + std::string mFilterName; + + static LLPointer sSaveLocalImage; public: static std::set sList; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 05004681c1..11b62ba755 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -294,6 +294,7 @@ static bool mLoginStatePastUI = false; const S32 DEFAULT_MAX_AGENT_GROUPS = 42; const S32 ALLOWED_MAX_AGENT_GROUPS = 500; +const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds boost::scoped_ptr LLStartUp::sStateWatcher(new LLEventStream("StartupState")); boost::scoped_ptr LLStartUp::sListener(new LLStartupListener()); @@ -697,9 +698,6 @@ bool idle_startup() gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion()); gSavedSettings.setString("LastGPUString", thisGPU); - // Re-enable feature table download - LLFeatureManager::getInstance()->fetchHTTPTables(); - std::string xml_file = LLUI::locateSkin("xui_version.xml"); LLXMLNodePtr root; bool xml_ok = false; @@ -1468,6 +1466,14 @@ bool idle_startup() gSavedPerAccountSettings.setString("InstantMessageLogPath", gDirUtilp->getChatLogsDir()); } // + + // FIRE-22853 Make snapshots to disk not remember path and filename if the user doesnt want them to. + if (!gSavedPerAccountSettings.getBOOL("FSRememberSnapshotPathSessions")) + { + gSavedPerAccountSettings.setString("SnapshotBaseDir", gSavedPerAccountSettings.getControl("SnapshotBaseDir")->getDefault().asString()); + gSavedPerAccountSettings.setString("SnapshotBaseName", gSavedPerAccountSettings.getControl("SnapshotBaseName")->getDefault().asString()); + } + // // Seperate user directories per grid on OS build #ifdef OPENSIM gDirUtilp->setPerAccountChatLogsDir(userid, gridlabel); @@ -2333,6 +2339,13 @@ bool idle_startup() LLStartUp::setStartupState( STATE_INVENTORY_SEND ); } display_startup(); + + if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) + { + LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + reset_login(); + } return FALSE; } diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index d579fd66aa..68181e96cc 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -615,7 +615,7 @@ bool LLTextureCacheRemoteWorker::doWrite() if(idx >= 0) { // write to the fast cache. - if(!mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel)) + if(!mCache->writeToFastCache(mID, idx, mRawImage, mRawDiscardLevel)) { LL_WARNS() << "writeToFastCache failed" << LL_ENDL; mDataSize = -1; // failed @@ -2036,8 +2036,48 @@ LLPointer LLTextureCache::readFromFastCache(const LLUUID& id, S32& d return raw; } +#if LL_WINDOWS + +static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific + +U32 exception_dupe_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +{ + if (code == STATUS_MSC_EXCEPTION) + { + // C++ exception, go on + return EXCEPTION_CONTINUE_SEARCH; + } + else + { + // handle it + return EXCEPTION_EXECUTE_HANDLER; + } +} + +//due to unwinding +void dupe(LLPointer &raw) +{ + raw = raw->duplicate(); +} + +void logExceptionDupplicate(LLPointer &raw) +{ + __try + { + dupe(raw); + } + __except (exception_dupe_filter(GetExceptionCode(), GetExceptionInformation())) + { + // convert to C++ styled exception + char integer_string[32]; + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + throw std::exception(integer_string); + } +} +#endif + //return the fast cache location -bool LLTextureCache::writeToFastCache(S32 id, LLPointer raw, S32 discardlevel) +bool LLTextureCache::writeToFastCache(LLUUID image_id, S32 id, LLPointer raw, S32 discardlevel) { //rescale image if needed if (raw.isNull() || raw->isBufferInvalid() || !raw->getData()) @@ -2065,7 +2105,31 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer raw, S32 dis if(w * h *c > 0) //valid { //make a duplicate to keep the original raw image untouched. - raw = raw->duplicate(); + + try + { +#if LL_WINDOWS + // Temporary diagnostics for scale/duplicate crash + logExceptionDupplicate(raw); +#else + raw = raw->duplicate(); +#endif + } + catch (...) + { + removeFromCache(image_id); + LL_ERRS() << "Failed to cache image: " << image_id + << " local id: " << id + << " Exception: " << boost::current_exception_diagnostic_information() + << " Image new width: " << w + << " Image new height: " << h + << " Image new components: " << c + << " Image discard difference: " << i + << LL_ENDL; + + return false; + } + if (raw->isBufferInvalid()) { LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL; diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index f1628451b8..34e43eeedf 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -179,7 +179,7 @@ private: void openFastCache(bool first_time = false); void closeFastCache(bool forced = false); - bool writeToFastCache(S32 id, LLPointer raw, S32 discardlevel); + bool writeToFastCache(LLUUID image_id, S32 cache_id, LLPointer raw, S32 discardlevel); private: // Internal diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 777c46c62b..b474e40ff7 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -271,7 +271,7 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary() addEntry(DAD_CLOTHING, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_OBJECT, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dRezAttachmentFromInv, &LLToolDragAndDrop::dad3dGiveInventoryObject, &LLToolDragAndDrop::dad3dRezObjectOnObject, &LLToolDragAndDrop::dad3dRezObjectOnLand)); addEntry(DAD_NOTECARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); - addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory, &LLToolDragAndDrop::dad3dUpdateInventoryCategory, &LLToolDragAndDrop::dad3dNULL)); + addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory, &LLToolDragAndDrop::dad3dRezCategoryOnObject, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL)); @@ -2421,6 +2421,21 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( return rv; } + +EAcceptance LLToolDragAndDrop::dad3dRezCategoryOnObject( + LLViewerObject* obj, S32 face, MASK mask, BOOL drop) +{ + if ((mask & MASK_CONTROL)) + { + return dad3dUpdateInventoryCategory(obj, face, mask, drop); + } + else + { + return ACCEPT_NO; + } +} + + BOOL LLToolDragAndDrop::dadUpdateInventoryCategory(LLViewerObject* obj, BOOL drop) { diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 2d99de2244..24a712029c 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -162,6 +162,8 @@ protected: MASK mask, BOOL drop); EAcceptance dad3dRezObjectOnObject(LLViewerObject* obj, S32 face, MASK mask, BOOL drop); + EAcceptance dad3dRezCategoryOnObject(LLViewerObject* obj, S32 face, + MASK mask, BOOL drop); EAcceptance dad3dRezScript(LLViewerObject* obj, S32 face, MASK mask, BOOL drop); EAcceptance dad3dTextureObject(LLViewerObject* obj, S32 face, diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 7f9ead3477..f0a1eaec0b 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -325,6 +325,8 @@ BOOL LLToolPie::handleLeftClickPick() } } return TRUE; + case CLICK_ACTION_DISABLED: + return TRUE; default: // nothing break; @@ -509,6 +511,8 @@ ECursorType LLToolPie::cursorFromObject(LLViewerObject* object) case CLICK_ACTION_OPEN_MEDIA: cursor = cursor_from_parcel_media(click_action); break; + case CLICK_ACTION_DISABLED: + break; default: break; } @@ -574,6 +578,8 @@ void LLToolPie::selectionPropertiesReceived() case CLICK_ACTION_OPEN: LLFloaterReg::showInstance("openobject"); break; + case CLICK_ACTION_DISABLED: + break; default: break; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 1c5bdfce5c..3911d2f778 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -34,6 +34,7 @@ #include "llcompilequeue.h" #include "llfasttimerview.h" #include "llfloaterabout.h" +#include "llfloaterauction.h" #include "llfloaterautoreplacesettings.h" #include "llfloateravatar.h" #include "llfloateravatarpicker.h" @@ -200,7 +201,6 @@ #include "fspanelclassified.h" #include "lggbeamcolormapfloater.h" #include "lggbeammapfloater.h" -#include "llfloaterauction.h" #include "llfloaterdisplayname.h" #include "llfloaterscriptrecover.h" #include "llfloatersearchreplace.h" @@ -241,6 +241,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("avatar", "floater_avatar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); // [FS Persisted Avatar Render Settings] @@ -453,7 +454,6 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("animation_explorer", "floater_animation_explorer.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("animation_overrider", "floater_ao.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("area_search", "floater_fs_area_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); - LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("export_collada", "floater_export_collada.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("delete_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("floater_profile", "floater_profile_view.xml",&LLFloaterReg::build); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index eb48919db3..38e60dc567 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1583,6 +1583,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mNavigateServerRequest(false), mMediaSourceFailed(false), mRequestedVolume(1.0f), + mPreviousVolume(1.0f), mIsMuted(false), mNeedsMuteCheck(false), mPreviousMediaState(MEDIA_NONE), @@ -2126,6 +2127,20 @@ void LLViewerMediaImpl::setVolume(F32 volume) updateVolume(); } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setMute(bool mute) +{ + if (mute) + { + mPreviousVolume = mRequestedVolume; + setVolume(0.0); + } + else + { + setVolume(mPreviousVolume); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index c52960dfcf..e2e758befb 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -216,6 +216,7 @@ public: void skipBack(F32 step_scale); void skipForward(F32 step_scale); void setVolume(F32 volume); + void setMute(bool mute); void updateVolume(); F32 getVolume(); void focus(bool focus); @@ -448,6 +449,7 @@ private: bool mNavigateServerRequest; bool mMediaSourceFailed; F32 mRequestedVolume; + F32 mPreviousVolume; bool mIsMuted; bool mNeedsMuteCheck; int mPreviousMediaState; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 79c03d15a5..eb234d8f06 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -138,6 +138,7 @@ #include "llpathfindingmanager.h" #include "llstartup.h" #include "boost/unordered_map.hpp" +#include #include "llcleanup.h" // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "fsavatarrenderpersistence.h" @@ -4548,12 +4549,19 @@ class LLSelfSitDown : public view_listener_t } }; + + +bool show_sitdown_self() +{ + return isAgentAvatarValid() && !gAgentAvatarp->isSitting(); +} + bool enable_sitdown_self() { // [RLVa:KB] - Checked: 2010-08-28 (RLVa-1.2.1a) | Added: RLVa-1.2.1a - return isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying() && !gRlvHandler.hasBehaviour(RLV_BHVR_SIT); + return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying() && !gRlvHandler.hasBehaviour(RLV_BHVR_SIT); // [/RLVa:KB] -// return isAgentAvatarValid() && !gAgentAvatarp->isSitting() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying(); +// return show_sitdown_self() && !gAgentAvatarp->isEditingAppearance() && !gAgent.getFlying(); } // Force sit -KC @@ -10254,11 +10262,15 @@ void handle_report_bug(const LLSD& param) LLStringUtil::format_map_t replace; // FIRE-14001: JIRA report is being cut off when using Help -> Report Bug - //replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getViewerInfoString(true)); + //std::string environment = LLAppViewer::instance()->getViewerInfoString(true); + //boost::regex regex; + //regex.assign(""); + //std::string stripped_env = boost::regex_replace(environment, regex, ""); + + //replace["[ENVIRONMENT]"] = LLURI::escape(stripped_env); LLSD sysinfo = FSData::getSystemInfo(); replace["[ENVIRONMENT]"] = LLURI::escape(sysinfo["Part1"].asString().substr(1) + sysinfo["Part2"].asString().substr(1)); // - LLSLURL location_url; LLAgentUI::buildSLURL(location_url); replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString()); @@ -11613,7 +11625,8 @@ void initialize_menus() view_listener_t::addMenu(new LLSelfStandUp(), "Self.StandUp"); enable.add("Self.EnableStandUp", boost::bind(&enable_standup_self)); view_listener_t::addMenu(new LLSelfSitDown(), "Self.SitDown"); - enable.add("Self.EnableSitDown", boost::bind(&enable_sitdown_self)); + enable.add("Self.EnableSitDown", boost::bind(&enable_sitdown_self)); + enable.add("Self.ShowSitDown", boost::bind(&show_sitdown_self)); view_listener_t::addMenu(new FSSelfForceSit(), "Self.ForceSit"); //KC enable.add("Self.EnableForceSit", boost::bind(&enable_forcesit_self)); //KC view_listener_t::addMenu(new FSSelfCheckForceSit(), "Self.getForceSit"); //KC diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index ef1e0cf42c..677becb77f 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -209,38 +209,55 @@ void LLFilePickerThread::clearDead() } } -LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple) +LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb) : LLFilePickerThread(filter, get_multiple), mLoadFilter(filter), mSaveFilter(LLFilePicker::FFSAVE_ALL), - mFilePickedSignal(NULL) + mFilePickedSignal(NULL), + mFailureSignal(NULL) { mFilePickedSignal = new file_picked_signal_t(); mFilePickedSignal->connect(cb); + + mFailureSignal = new file_picked_signal_t(); + mFailureSignal->connect(failure_cb); } -LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name) +LLFilePickerReplyThread::LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb) : LLFilePickerThread(filter, proposed_name), mLoadFilter(LLFilePicker::FFLOAD_ALL), mSaveFilter(filter), - mFilePickedSignal(NULL) + mFilePickedSignal(NULL), + mFailureSignal(NULL) { mFilePickedSignal = new file_picked_signal_t(); mFilePickedSignal->connect(cb); + + mFailureSignal = new file_picked_signal_t(); + mFailureSignal->connect(failure_cb); } LLFilePickerReplyThread::~LLFilePickerReplyThread() { delete mFilePickedSignal; + delete mFailureSignal; } void LLFilePickerReplyThread::notify(const std::vector& filenames) { - if (filenames.empty()) return; - - if (mFilePickedSignal) + if (filenames.empty()) { - (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); + if (mFailureSignal) + { + (*mFailureSignal)(filenames, mLoadFilter, mSaveFilter); + } + } + else + { + if (mFilePickedSignal) + { + (*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); + } } } @@ -597,18 +614,6 @@ class LLFileCloseAllWindows : public view_listener_t } }; -// Threaded filepickers -LLPointer sFormattedSnapshotImage = NULL; -void take_snapshot_to_disk_callback(bool success) -{ - sFormattedSnapshotImage = NULL; - if (success) - { - gViewerWindow->playSnapshotAnimAndSound(); - } -} -// - class LLFileTakeSnapshotToDisk : public view_listener_t { bool handleEvent(const LLSD& userdata) @@ -632,49 +637,26 @@ class LLFileTakeSnapshotToDisk : public view_listener_t gSavedSettings.getBOOL("RenderUIInSnapshot"), FALSE)) { - // Threaded filepickers - //gViewerWindow->playSnapshotAnimAndSound(); - //LLPointer formatted; - //LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); - //switch (fmt) - //{ - //case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: - // formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); - // break; - //default: - // LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; - //case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: - // formatted = new LLImagePNG; - // break; - //case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: - // formatted = new LLImageBMP; - // break; - //} - //formatted->enableOverSize() ; - //formatted->encode(raw, 0); - //formatted->disableOverSize() ; - //LLSnapshotLivePreview::saveLocal(formatted); - + LLPointer formatted; LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat"); switch (fmt) { case LLSnapshotModel::SNAPSHOT_FORMAT_JPEG: - sFormattedSnapshotImage = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); + formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality")); break; default: LL_WARNS() << "Unknown local snapshot format: " << fmt << LL_ENDL; case LLSnapshotModel::SNAPSHOT_FORMAT_PNG: - sFormattedSnapshotImage = new LLImagePNG; + formatted = new LLImagePNG; break; case LLSnapshotModel::SNAPSHOT_FORMAT_BMP: - sFormattedSnapshotImage = new LLImageBMP; + formatted = new LLImageBMP; break; } - sFormattedSnapshotImage->enableOverSize() ; - sFormattedSnapshotImage->encode(raw, 0); - sFormattedSnapshotImage->disableOverSize() ; - gViewerWindow->saveImageNumbered(sFormattedSnapshotImage, false, boost::bind(&take_snapshot_to_disk_callback, _1)); - // + formatted->enableOverSize() ; + formatted->encode(raw, 0); + formatted->disableOverSize() ; + LLSnapshotLivePreview::saveLocal(formatted); } return true; } diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 4f62a912e9..d9a84dbd26 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -114,8 +114,8 @@ public: typedef boost::signals2::signal& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)> file_picked_signal_t; - LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple); - LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name); + LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ELoadFilter filter, bool get_multiple, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); + LLFilePickerReplyThread(const file_picked_signal_t::slot_type& cb, LLFilePicker::ESaveFilter filter, const std::string &proposed_name, const file_picked_signal_t::slot_type& failure_cb = file_picked_signal_t()); ~LLFilePickerReplyThread(); virtual void notify(const std::vector& filenames); @@ -124,6 +124,7 @@ private: LLFilePicker::ELoadFilter mLoadFilter; LLFilePicker::ESaveFilter mSaveFilter; file_picked_signal_t* mFilePickedSignal; + file_picked_signal_t* mFailureSignal; }; #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d8173dc131..51010762f6 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -185,6 +185,98 @@ const U8 AU_FLAGS_NONE = 0x00; const U8 AU_FLAGS_HIDETITLE = 0x01; const U8 AU_FLAGS_CLIENT_AUTOPILOT = 0x02; +void accept_friendship_coro(std::string url, LLSD notification) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + if (url.empty()) + { + LL_WARNS("Friendship") << "Empty capability!" << LL_ENDL; + return; + } + + LLSD payload = notification["payload"]; + url += "?from=" + payload["from_id"].asString(); + url += "&agent_name=\"" + LLURI::escape(gAgentAvatarp->getFullname()) + "\""; + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("Friendship") << "HTTP status, " << status.toTerseString() << + ". friendship offer accept failed." << LL_ENDL; + } + else + { + if (!result.has("success") || result["success"].asBoolean() == false) + { + LL_WARNS("Friendship") << "Server failed to process accepted friendship. " << httpResults << LL_ENDL; + } + else + { + LL_DEBUGS("Friendship") << "Adding friend to list" << httpResults << LL_ENDL; + // add friend to recent people list + LLRecentPeople::instance().add(payload["from_id"]); + + LLNotificationsUtil::add("FriendshipAcceptedByMe", + notification["substitutions"], payload); + } + } +} + +void decline_friendship_coro(std::string url, LLSD notification, S32 option) +{ + if (url.empty()) + { + LL_WARNS("Friendship") << "Empty capability!" << LL_ENDL; + return; + } + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD payload = notification["payload"]; + url += "?from=" + payload["from_id"].asString(); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("Friendship") << "HTTP status, " << status.toTerseString() << + ". friendship offer decline failed." << LL_ENDL; + } + else + { + if (!result.has("success") || result["success"].asBoolean() == false) + { + LL_WARNS("Friendship") << "Server failed to process declined friendship. " << httpResults << LL_ENDL; + } + else + { + LL_DEBUGS("Friendship") << "Friendship declined" << httpResults << LL_ENDL; + if (option == 1) + { + LLNotificationsUtil::add("FriendshipDeclinedByMe", + notification["substitutions"], payload); + } + else if (option == 2) + { + // start IM session + LLAvatarActions::startIM(payload["from_id"].asUUID()); + } + } + } +} + bool friendship_offer_callback(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -195,9 +287,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) // this will be skipped if the user offering friendship is blocked if (notification_ptr) { - // add friend to recent people list - LLRecentPeople::instance().add(payload["from_id"]); - switch(option) { case 0: @@ -208,46 +297,79 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) const LLUUID fid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD); // This will also trigger an onlinenotification if the user is online - msg->newMessageFast(_PREHASH_AcceptFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->nextBlockFast(_PREHASH_FolderData); - msg->addUUIDFast(_PREHASH_FolderID, fid); - msg->sendReliable(LLHost(payload["sender"].asString())); + std::string url = gAgent.getRegionCapability("AcceptFriendship"); + LL_DEBUGS("Friendship") << "Cap string: " << url << LL_ENDL; + if (!url.empty() && payload.has("online") && payload["online"].asBoolean() == false) + { + LL_DEBUGS("Friendship") << "Accepting friendship via capability" << LL_ENDL; + LLCoros::instance().launch("LLMessageSystem::acceptFriendshipOffer", + boost::bind(accept_friendship_coro, url, notification)); + } + else if (payload.has("session_id") && payload["session_id"].asUUID().notNull()) + { + LL_DEBUGS("Friendship") << "Accepting friendship via viewer message" << LL_ENDL; + msg->newMessageFast(_PREHASH_AcceptFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->nextBlockFast(_PREHASH_FolderData); + msg->addUUIDFast(_PREHASH_FolderID, fid); + msg->sendReliable(LLHost(payload["sender"].asString())); - LLSD payload = notification["payload"]; - LLNotificationsUtil::add("FriendshipAcceptedByMe", - notification["substitutions"], payload); + // add friend to recent people list + LLRecentPeople::instance().add(payload["from_id"]); + LLNotificationsUtil::add("FriendshipAcceptedByMe", + notification["substitutions"], payload); + } + else + { + LL_WARNS("Friendship") << "Failed to accept friendship offer, neither capability nor transaction id are accessible" << LL_ENDL; + } break; } case 1: // Decline - { - LLSD payload = notification["payload"]; - LLNotificationsUtil::add("FriendshipDeclinedByMe", - notification["substitutions"], payload); - } // fall-through case 2: // Send IM - decline and start IM session { // decline // We no longer notify other viewers, but we DO still send - // the rejection to the simulator to delete the pending userop. - msg->newMessageFast(_PREHASH_DeclineFriendship); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_TransactionBlock); - msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); - msg->sendReliable(LLHost(payload["sender"].asString())); + // the rejection to the simulator to delete the pending userop. + std::string url = gAgent.getRegionCapability("DeclineFriendship"); + LL_DEBUGS("Friendship") << "Cap string: " << url << LL_ENDL; + if (!url.empty() && payload.has("online") && payload["online"].asBoolean() == false) + { + LL_DEBUGS("Friendship") << "Declining friendship via capability" << LL_ENDL; + LLCoros::instance().launch("LLMessageSystem::declineFriendshipOffer", + boost::bind(decline_friendship_coro, url, notification, option)); + } + else if (payload.has("session_id") && payload["session_id"].asUUID().notNull()) + { + LL_DEBUGS("Friendship") << "Declining friendship via viewer message" << LL_ENDL; + msg->newMessageFast(_PREHASH_DeclineFriendship); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_TransactionBlock); + msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]); + msg->sendReliable(LLHost(payload["sender"].asString())); - // start IM session - if(2 == option) - { - LLAvatarActions::startIM(payload["from_id"].asUUID()); - } + if (option == 1) // due to fall-through + { + LLNotificationsUtil::add("FriendshipDeclinedByMe", + notification["substitutions"], payload); + } + else if (option == 2) + { + // start IM session + LLAvatarActions::startIM(payload["from_id"].asUUID()); + } + } + else + { + LL_WARNS("Friendship") << "Failed to decline friendship offer, neither capability nor transaction id are accessible" << LL_ENDL; + } } default: // close button probably, possibly timed out @@ -653,6 +775,119 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain) static LLSD sSavedGroupInvite; static LLSD sSavedResponse; +void response_group_invitation_coro(std::string url, LLUUID group_id, bool notify_and_update) +{ + if (url.empty()) + { + LL_WARNS("GroupInvite") << "Empty capability!" << LL_ENDL; + return; + } + + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD payload; + payload["group"] = group_id; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, payload); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("GroupInvite") << "HTTP status, " << status.toTerseString() << + ". Group " << group_id << " invitation response processing failed." << LL_ENDL; + } + else + { + if (!result.has("success") || result["success"].asBoolean() == false) + { + LL_WARNS("GroupInvite") << "Server failed to process group " << group_id << " invitation response. " << httpResults << LL_ENDL; + } + else + { + LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL; + if (notify_and_update) + { + LLNotificationsUtil::add("JoinGroupSuccess"); + gAgent.sendAgentDataUpdateRequest(); + + LLGroupMgr::getInstance()->clearGroupData(group_id); + // refresh the floater for this group, if any. + LLGroupActions::refresh(group_id); + } + } + } +} + +void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accept_invite, S32 fee, bool use_offline_cap, LLSD &payload) +{ + if (accept_invite && fee > 0) + { + // If there is a fee to join this group, make + // sure the user is sure they want to join. + LLSD args; + args["COST"] = llformat("%d", fee); + // Set the fee for next time to 0, so that we don't keep + // asking about a fee. + LLSD next_payload = payload; + next_payload["fee"] = 0; + LLNotificationsUtil::add("JoinGroupCanAfford", + args, + next_payload); + } + else if (use_offline_cap) + { + std::string url; + if (accept_invite) + { + url = gAgent.getRegionCapability("AcceptGroupInvite"); + } + else + { + url = gAgent.getRegionCapability("DeclineGroupInvite"); + } + + if (!url.empty()) + { + LLCoros::instance().launch("LLMessageSystem::acceptGroupInvitation", + boost::bind(response_group_invitation_coro, url, group_id, accept_invite)); + } + else + { + // if sim has no this cap, we can do nothing - regular request will fail + LL_WARNS("GroupInvite") << "No capability, can't reply to offline invitation!" << LL_ENDL; + } + } + else + { + EInstantMessage type = accept_invite ? IM_GROUP_INVITATION_ACCEPT : IM_GROUP_INVITATION_DECLINE; + + send_improved_im(group_id, + std::string("name"), + std::string("message"), + IM_ONLINE, + type, + transaction_id); + } +} + +void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accept_invite, S32 fee, bool use_offline_cap) +{ + LLSD payload; + if (accept_invite) + { + payload["group_id"] = group_id; + payload["transaction_id"] = transaction_id; + payload["fee"] = fee; + payload["use_offline_cap"] = use_offline_cap; + } + send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, payload); +} + bool join_group_response(const LLSD& notification, const LLSD& response) { // A bit of variable saving and restoring is used to deal with the case where your group list is full and you @@ -691,6 +926,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) std::string name = notification_adjusted["payload"]["name"].asString(); std::string message = notification_adjusted["payload"]["message"].asString(); S32 fee = notification_adjusted["payload"]["fee"].asInteger(); + U8 use_offline_cap = notification_adjusted["payload"]["use_offline_cap"].asInteger(); if (option == 2 && !group_id.isNull()) { @@ -735,42 +971,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) return false; } } - - if (accept_invite) - { - // If there is a fee to join this group, make - // sure the user is sure they want to join. - if (fee > 0) - { - LLSD args; - args["COST"] = llformat("%d", fee); - // Set the fee for next time to 0, so that we don't keep - // asking about a fee. - LLSD next_payload = notification_adjusted["payload"]; - next_payload["fee"] = 0; - LLNotificationsUtil::add("JoinGroupCanAfford", - args, - next_payload); - } - else - { - send_improved_im(group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_ACCEPT, - transaction_id); - } - } - else - { - send_improved_im(group_id, - std::string("name"), - std::string("message"), - IM_ONLINE, - IM_GROUP_INVITATION_DECLINE, - transaction_id); - } + send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, notification_adjusted["payload"]); sSavedGroupInvite[id] = LLSD::emptyMap(); sSavedResponse[id] = LLSD::emptyMap(); @@ -1804,7 +2005,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& //don't spam them if they are getting flooded if (check_offer_throttle(mFromName, true)) { - log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + log_message = "" + chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString("."); LLSD args; args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessageTip", args); @@ -2079,7 +2280,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const //don't spam them if they are getting flooded if (check_offer_throttle(mFromName, true)) { - log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + log_message = "" + chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString("."); LLSD args; args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessageTip", args); @@ -2163,6 +2364,23 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const return false; } +std::string LLOfferInfo::getSanitizedDescription() +{ + // currently we get description from server as: 'Object' ( Location ) + // object name shouldn't be shown as a hyperlink + std::string description = mDesc; + + std::size_t start = mDesc.find_first_of("'"); + std::size_t end = mDesc.find_last_of("'"); + if ((start != std::string::npos) && (end != std::string::npos)) + { + description.insert(start, ""); + description.insert(end + 8, ""); + } + return description; +} + + void LLOfferInfo::initRespondFunctionMap() { if(mRespondFunctions.empty()) @@ -4035,6 +4253,110 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) } +// sounds can arrive before objects, store them for a short time +// Note: this is a workaround for MAINT-4743, real fix would be to make +// server send sound along with object update that creates (rezes) the object +class PostponedSoundData +{ +public: + PostponedSoundData() : + mExpirationTime(0) + {} + PostponedSoundData(const LLUUID &object_id, const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const U8 flags); + bool hasExpired() { return LLFrameTimer::getTotalSeconds() > mExpirationTime; } + + LLUUID mObjectId; + LLUUID mSoundId; + LLUUID mOwnerId; + F32 mGain; + U8 mFlags; + static const F64 MAXIMUM_PLAY_DELAY; + +private: + F64 mExpirationTime; //seconds since epoch +}; +const F64 PostponedSoundData::MAXIMUM_PLAY_DELAY = 15.0; +static F64 postponed_sounds_update_expiration = 0.0; +static std::map postponed_sounds; + +void set_attached_sound(LLViewerObject *objectp, const LLUUID &object_id, const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const U8 flags) +{ + if (LLMuteList::getInstance()->isMuted(object_id)) return; + + if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; + + // Don't play sounds from a region with maturity above current agent maturity + LLVector3d pos = objectp->getPositionGlobal(); + if (!gAgent.canAccessMaturityAtGlobal(pos)) + { + return; + } + + objectp->setAttachedSound(sound_id, owner_id, gain, flags); +} + +PostponedSoundData::PostponedSoundData(const LLUUID &object_id, const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const U8 flags) + : + mObjectId(object_id), + mSoundId(sound_id), + mOwnerId(owner_id), + mGain(gain), + mFlags(flags), + mExpirationTime(LLFrameTimer::getTotalSeconds() + MAXIMUM_PLAY_DELAY) +{ +} + +// static +void update_attached_sounds() +{ + if (postponed_sounds.empty()) + { + return; + } + + std::map::iterator iter = postponed_sounds.begin(); + std::map::iterator end = postponed_sounds.end(); + while (iter != end) + { + std::map::iterator cur_iter = iter++; + PostponedSoundData* data = &cur_iter->second; + if (data->hasExpired()) + { + postponed_sounds.erase(cur_iter); + } + else + { + LLViewerObject *objectp = gObjectList.findObject(data->mObjectId); + if (objectp) + { + set_attached_sound(objectp, data->mObjectId, data->mSoundId, data->mOwnerId, data->mGain, data->mFlags); + postponed_sounds.erase(cur_iter); + } + } + } + postponed_sounds_update_expiration = LLFrameTimer::getTotalSeconds() + 2 * PostponedSoundData::MAXIMUM_PLAY_DELAY; +} + +//static +void clear_expired_postponed_sounds() +{ + if (postponed_sounds_update_expiration > LLFrameTimer::getTotalSeconds()) + { + return; + } + std::map::iterator iter = postponed_sounds.begin(); + std::map::iterator end = postponed_sounds.end(); + while (iter != end) + { + std::map::iterator cur_iter = iter++; + PostponedSoundData* data = &cur_iter->second; + if (data->hasExpired()) + { + postponed_sounds.erase(cur_iter); + } + } + postponed_sounds_update_expiration = LLFrameTimer::getTotalSeconds() + 2 * PostponedSoundData::MAXIMUM_PLAY_DELAY; +} // *TODO: Remove this dependency, or figure out a better way to handle // this hack. @@ -4053,7 +4375,12 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data) } // Update the object... + S32 old_num_objects = gObjectList.mNumNewObjects; gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL); + if (old_num_objects != gObjectList.mNumNewObjects) + { + update_attached_sounds(); + } } void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data) @@ -4069,7 +4396,12 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data } // Update the object... + S32 old_num_objects = gObjectList.mNumNewObjects; gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED); + if (old_num_objects != gObjectList.mNumNewObjects) + { + update_attached_sounds(); + } } void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) @@ -4100,7 +4432,12 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ gObjectData += (U32Bytes)mesgsys->getReceiveSize(); } + S32 old_num_objects = gObjectList.mNumNewObjects; gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); + if (old_num_objects != gObjectList.mNumNewObjects) + { + update_attached_sounds(); + } } static LLTrace::BlockTimerStatHandle FTM_PROCESS_OBJECTS("Process Kill Objects"); @@ -4457,27 +4794,27 @@ void process_attached_sound(LLMessageSystem *msg, void **user_data) msg->getU8Fast(_PREHASH_DataBlock, _PREHASH_Flags, flags); LLViewerObject *objectp = gObjectList.findObject(object_id); - if (!objectp) + if (objectp) { - // we don't know about this object, just bail - return; + set_attached_sound(objectp, object_id, sound_id, owner_id, gain, flags); } - - if (LLMuteList::getInstance()->isMuted(object_id)) return; - - if (LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagObjectSounds)) return; - - // Don't play sounds from a region with maturity above current agent maturity - LLVector3d pos = objectp->getPositionGlobal(); - if( !gAgent.canAccessMaturityAtGlobal(pos) ) + else if (sound_id.notNull()) { - return; + // we don't know about this object yet, probably it has yet to arrive + // std::map for dupplicate prevention. + postponed_sounds[object_id] = (PostponedSoundData(object_id, sound_id, owner_id, gain, flags)); + clear_expired_postponed_sounds(); + } + else + { + std::map::iterator iter = postponed_sounds.find(object_id); + if (iter != postponed_sounds.end()) + { + postponed_sounds.erase(iter); + } } - - objectp->setAttachedSound(sound_id, owner_id, gain, flags); } - void process_attached_sound_gain_change(LLMessageSystem *mesgsys, void **user_data) { F32 gain = 0; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 4531dfe984..a4a0546511 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -74,6 +74,11 @@ enum InventoryOfferResponse BOOL can_afford_transaction(S32 cost); void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE, S32 trx_type = TRANS_GIFT, const std::string& desc = LLStringUtil::null); +void send_join_group_response(LLUUID group_id, + LLUUID transaction_id, + bool accept_invite, + S32 fee, + bool use_offline_cap); void process_logout_reply(LLMessageSystem* msg, void**); void process_layer_data(LLMessageSystem *mesgsys, void **user_data); @@ -279,6 +284,7 @@ public: private: void initRespondFunctionMap(); + std::string getSanitizedDescription(); typedef boost::function respond_function_t; typedef std::map respond_function_map_t; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 19de35f95c..03957885bb 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1990,7 +1990,10 @@ void LLViewerRegion::updateNetStats() mLastPacketsLost = mPacketsLost; mPacketsIn = cdp->getPacketsIn(); + // FIRE-17071: UDP network data measuring is wrong + //mBitsIn = 8 * cdp->getBytesIn(); mBitsIn = cdp->getBytesIn(); + // mPacketsOut = cdp->getPacketsOut(); mPacketsLost = cdp->getPacketsLost(); mPingDelay = cdp->getPingDelay(); @@ -3039,6 +3042,8 @@ void LLViewerRegion::unpackRegionHandshake() void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) { capabilityNames.append("AbuseCategories"); + //capabilityNames.append("AcceptFriendship"); + capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("AgentPreferences"); capabilityNames.append("AgentState"); capabilityNames.append("AttachmentResources"); @@ -3048,6 +3053,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ChatSessionRequest"); capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("CreateInventoryCategory"); + //capabilityNames.append("DeclineFriendship"); + capabilityNames.append("DeclineGroupInvite"); // ReadOfflineMsgs recieved messages only!!! capabilityNames.append("DispatchRegionInfo"); capabilityNames.append("DirectDelivery"); capabilityNames.append("EnvironmentSettings"); @@ -3111,7 +3118,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); capabilityNames.append("ProvisionVoiceAccountRequest"); - capabilityNames.append("ReadOfflineMsgs"); + capabilityNames.append("ReadOfflineMsgs"); // Only use with AcceptGroupInvite AcceptFriendship capabilityNames.append("RemoteParcelRequest"); capabilityNames.append("RenderMaterials"); capabilityNames.append("RequestTextureDownload"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 70eede8707..b010f7e69d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -200,6 +200,7 @@ #include "llviewerdisplay.h" #include "llspatialpartition.h" #include "llviewerjoystick.h" +#include "llviewermenufile.h" // LLFilePickerReplyThread #include "llviewernetwork.h" #include "llpostprocess.h" // [FS communication UI] @@ -293,38 +294,6 @@ static LLCachedControl sSnapshotDir(LLCachedControl(gS LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity"); -// Threaded filepickers -class FSSnapshotSaveFilePicker : public LLFilePickerThread -{ -public: - FSSnapshotSaveFilePicker(LLFilePicker::ESaveFilter filter, const std::string& default_name, boost::function notify_slot) - : LLFilePickerThread(filter, default_name) - { - mSignal.connect(notify_slot); - } - - virtual void notify(const std::vector& filenames) - { - if (!filenames.empty()) - { - mSignal(filenames[0]); - } - else - { - mSignal(std::string()); - } - } - - static void open(LLFilePicker::ESaveFilter filter, const std::string& default_name, boost::function notify_slot) - { - (new FSSnapshotSaveFilePicker(filter, default_name, notify_slot))->getFile(); - } - -protected: - boost::signals2::signal mSignal; -}; -// - class RecordToChatConsoleRecorder : public LLError::Recorder { public: @@ -5569,204 +5538,141 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d return FALSE; } -// 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) +// Saves an image to the harddrive as "SnapshotX" where X >= 1. +void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - if (snapshot_dir.empty() || !LLFile::isdir(snapshot_dir)) + if (!image) { - if (callback) - { - callback(false); - } + LL_WARNS() << "No image to save" << LL_ENDL; + return; + } + std::string extension("." + image->getExtension()); + LLImageFormatted* formatted_image = image; + // Get a base file location if needed. + if (force_picker || !isSnapshotLocSet()) + { + std::string proposed_name(sSnapshotBaseName); + + // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. + LLFilePicker::ESaveFilter pick_type; + + if (extension == ".j2c") + pick_type = LLFilePicker::FFSAVE_J2C; + else if (extension == ".bmp") + pick_type = LLFilePicker::FFSAVE_BMP; + else if (extension == ".jpg") + pick_type = LLFilePicker::FFSAVE_JPEG; + else if (extension == ".png") + pick_type = LLFilePicker::FFSAVE_PNG; + else if (extension == ".tga") + pick_type = LLFilePicker::FFSAVE_TGA; + else + pick_type = LLFilePicker::FFSAVE_ALL; + + (new LLFilePickerReplyThread(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, + boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)))->getFile(); + } + else + { + saveImageLocal(formatted_image, success_cb, failure_cb); + } +} + +void LLViewerWindow::onDirectorySelected(const std::vector& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) +{ + // Copy the directory + file name + std::string filepath = filenames[0]; + + gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); + gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); + saveImageLocal(image, success_cb, failure_cb); +} + +void LLViewerWindow::onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb) +{ + failure_cb(); +} + + +void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) +{ + std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); + if (lastSnapshotDir.empty()) + { + failure_cb(); return; } // 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)); + boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); #else - boost::filesystem::space_info b_space = boost::filesystem::space(snapshot_dir); + boost::filesystem::path b_path(lastSnapshotDir); #endif - if (b_space.free < image->getDataSize()) + if (!boost::filesystem::is_directory(b_path)) { - if (callback) - { - callback(false); - } + LLSD args; + args["PATH"] = lastSnapshotDir; + LLNotificationsUtil::add("SnapshotToLocalDirNotExist", args); + resetSnapshotLoc(); + failure_cb(); return; } + boost::filesystem::space_info b_space = boost::filesystem::space(b_path); + if (b_space.free < image->getDataSize()) + { + LLSD args; + args["PATH"] = lastSnapshotDir; + std::string needM_bytes_string; + LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (image->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); + + failure_cb(); + } + // Look for an unused file name + BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); std::string filepath; S32 i = 1; S32 err = 0; - + std::string extension("." + image->getExtension()); do { - filepath = snapshot_dir; + filepath = sSnapshotDir; filepath += gDirUtilp->getDirDelimiter(); - filepath += base_name; - filepath += llformat("_%.3d",i); + filepath += sSnapshotBaseName; + + if (is_snapshot_name_loc_set) + { + filepath += llformat("_%.3d",i); + } + filepath += extension; llstat stat_info; err = LLFile::stat( filepath, &stat_info ); i++; } - while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). + while( -1 != err // Search until the file is not found (i.e., stat() gives an error). + && is_snapshot_name_loc_set); // Or stop if we are rewriting. LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; - - if (gSavedSettings.getBOOL("FSLogSnapshotsToLocal")) + if (image->save(filepath)) { - LLStringUtil::format_map_t args; - args["FILENAME"] = filepath; - report_to_nearby_chat(LLTrans::getString("SnapshotSavedToDisk", args)); + playSnapshotAnimAndSound(); + success_cb(); } - - bool success = image->save(filepath); - if (callback) - { - callback(success); - } -} - -void LLViewerWindow::saveImageCallback(const std::string& filename, LLImageFormatted* image, const std::string& extension, boost::function callback) -{ - if (!filename.empty()) - { - gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filename, true)); - gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filename)); - - do_save_image(image, sSnapshotDir, sSnapshotBaseName, extension, callback); - return; - } - - if (callback) - { - callback(false); - } -} -// - -// Saves an image to the harddrive as "SnapshotX" where X >= 1. -// Threaded filepickers -//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; - // Threaded filepickers - //return FALSE; - if (callback) - { - callback(false); - return; - } - // - } - - LLFilePicker::ESaveFilter pick_type; - std::string extension("." + image->getExtension()); - if (extension == ".j2c") - pick_type = LLFilePicker::FFSAVE_J2C; - else if (extension == ".bmp") - pick_type = LLFilePicker::FFSAVE_BMP; - else if (extension == ".jpg") - pick_type = LLFilePicker::FFSAVE_JPEG; - else if (extension == ".png") - pick_type = LLFilePicker::FFSAVE_PNG; - else if (extension == ".tga") - pick_type = LLFilePicker::FFSAVE_TGA; else - pick_type = LLFilePicker::FFSAVE_ALL; // ??? - - // Threaded filepickers - //BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); - - //// Get a base file location if needed. - //if (force_picker || !isSnapshotLocSet()) - //{ - // std::string proposed_name( sSnapshotBaseName ); - - // // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. - - // // pick a directory in which to save - // LLFilePicker& picker = LLFilePicker::instance(); - // if (!picker.getSaveFile(pick_type, proposed_name)) - // { - // // Clicked cancel - // return FALSE; - // } - - // // Copy the directory + file name - // std::string filepath = picker.getFirstFile(); - - // gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); - // gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); - //} - - //std::string snapshot_dir = sSnapshotDir; - //if(snapshot_dir.empty()) - //{ - // return FALSE; - //} - -// 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()) -// { -// insufficient_memory = TRUE; -// return FALSE; -// } - //// Look for an unused file name - //std::string filepath; - //S32 i = 1; - //S32 err = 0; - - //do - //{ - // filepath = sSnapshotDir; - // filepath += gDirUtilp->getDirDelimiter(); - // filepath += sSnapshotBaseName; - - // if (is_snapshot_name_loc_set) - // { - // filepath += llformat("_%.3d",i); - // } - - // filepath += extension; - - // llstat stat_info; - // err = LLFile::stat( filepath, &stat_info ); - // i++; - //} - //while( -1 != err // Search until the file is not found (i.e., stat() gives an error). - // && is_snapshot_name_loc_set); // Or stop if we are rewriting. - - //LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; - //return image->save(filepath); - - // Get a base file location if needed. - if (force_picker || !isSnapshotLocSet() || !LLFile::isdir(sSnapshotDir())) { - std::string proposed_name( sSnapshotBaseName ); - - FSSnapshotSaveFilePicker::open(pick_type, proposed_name, boost::bind(&LLViewerWindow::saveImageCallback, this, _1, image, extension, callback)); - return; + failure_cb(); } - - do_save_image(image, sSnapshotDir, sSnapshotBaseName, extension, callback); - // } void LLViewerWindow::resetSnapshotLoc() diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 5f973e832b..60e567db60 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -353,11 +353,13 @@ public: BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, LLSnapshotModel::ESnapshotLayerType type); BOOL isSnapshotLocSet() const; void resetSnapshotLoc() const; - // Threaded filepickers - 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); - // + + typedef boost::signals2::signal snapshot_saved_signal_t; + + void saveImageNumbered(LLImageFormatted *image, BOOL force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void onDirectorySelected(const std::vector& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb); + void onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb); // Reset the directory where snapshots are saved. // Client will open directory picker on next snapshot save. diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index be1f082159..eafbf83841 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -593,12 +593,10 @@ void LLVivoxVoiceClient::connectorShutdown() writeString(stream.str()); } - // Cut down wait on logout else { mShutdownComplete = true; } - // } void LLVivoxVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID) @@ -1169,17 +1167,26 @@ bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait) retval = result.has("connector"); } else - { // If we are not doing a corowait then we must sleep until the connector has responded + { + mRelogRequested = false; //stop the control coro + // If we are not doing a corowait then we must sleep until the connector has responded // otherwise we may very well close the socket too early. #if LL_WINDOWS - int count = 0; - while (!mShutdownComplete && 10 > count++) - { // Rider: This comes out to a max wait time of 10 seconds. - // The situation that brings us here is a call from ::terminate() - // and so the viewer is attempting to go away. Don't slow it down - // longer than this. + if (!mShutdownComplete) + { + // The situation that brings us here is a call from ::terminate() + // At this point message system is already down so we can't wait for + // the message, yet we need to receive "connector shutdown response". + // Either wait a bit and emulate it or check gMessageSystem for specific message _sleep(1000); // Cut down wait on logout + //if (mConnected) + //{ + // mConnected = false; + // LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false))); + // LLEventPumps::instance().post("vivoxClientPump", vivoxevent); + //} + //mShutdownComplete = true; // Need to check messages on the service pump for the connector shutdown response // which sets mShutdownComplete to true! while (gMessageSystem->checkAllMessages(gFrameCount, gServicePump)) @@ -3405,7 +3412,7 @@ void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string & } mConnected = false; - mShutdownComplete = true; // Cut down wait on logout + mShutdownComplete = true; LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false))); @@ -6378,6 +6385,7 @@ void LLVivoxVoiceClient::expireVoiceFonts() LLSD args; args["URL"] = LLTrans::getString("voice_morphing_url"); + args["PREMIUM_URL"] = LLTrans::getString("premium_voice_morphing_url"); // Give a notification if any voice fonts have expired. if (have_expired) diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 9ac17ecc6a..472598e306 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -275,6 +275,12 @@ bool LLWeb::useExternalBrowser(const std::string &url) boost::match_results matches; return !(boost::regex_search(uri_string, matches, pattern)); } + else + { + boost::regex pattern = boost::regex("^mailto:", boost::regex::perl | boost::regex::icase); + boost::match_results matches; + return boost::regex_search(url, matches, pattern); + } return false; #endif } diff --git a/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml index 65a7e255f9..1361366bd5 100644 --- a/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml @@ -31,7 +31,7 @@ Niedrig - + Hardware @@ -56,6 +56,9 @@ (Neustart erforderlich) + + Netz + Niedrig @@ -72,6 +75,9 @@ Niedrig + + Shader + @@ -111,5 +117,6 @@