diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2018-06-26 09:45:14 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2018-06-26 09:45:14 -0400 | 
| commit | f4a772b2b8e70eb3ef3b734a7d3e1623e3f1be15 (patch) | |
| tree | cc1759aeb34319f3af32085a7fc778fca7eda92d | |
| parent | 020757ff0170aa894c56cd719d46413c9e99fde6 (diff) | |
| parent | 9db683c13e67575bd347cf8a795f1a4ee148c4ea (diff) | |
DRTVWR-453: Update from MAINT (viewer-lynx).
58 files changed, 1699 insertions, 461 deletions
| diff --git a/doc/contributions.txt b/doc/contributions.txt index 039d00cbbf..90bbb1c2c6 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -220,7 +220,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 fda84aa5a8..a00a82aff0 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -323,6 +323,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 c5ba23f68c..3165ce0743 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -35,6 +35,7 @@  // external library headers  #include <boost/bind.hpp>  // other Linden headers +#include "lltimer.h"  #include "llevents.h"  #include "llerror.h"  #include "stringize.h" @@ -280,6 +281,22 @@ void LLCoros::setStackSize(S32 stacksize)      mStackSize = stacksize;  } +void LLCoros::printActiveCoroutines() +{ +    LL_INFOS("LLCoros") << "Number of active coroutines: " << (S32)mCoros.size() << LL_ENDL; +    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 @@ -375,7 +392,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())  {  } @@ -384,7 +402,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<std::string, CoroData> CoroMap;      CoroMap mCoros; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index f31a054139..29de79dc64 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -249,23 +249,13 @@ namespace LLError  	{  #ifdef __GNUC__  		// GCC: type_info::name() returns a mangled class name,st demangle - -		static size_t abi_name_len = 100; -		static char* abi_name_buf = (char*)malloc(abi_name_len); -			// warning: above is voodoo inferred from the GCC manual, -			// do NOT change - -		int status; -			// We don't use status, and shouldn't have to pass apointer to it -			// but gcc 3.3 libstc++'s implementation of demangling is broken -			// and fails without. -			 -		char* name = abi::__cxa_demangle(mangled, -										abi_name_buf, &abi_name_len, &status); -			// this call can realloc the abi_name_buf pointer (!) - -		return name ? name : mangled; - +        // passing nullptr, 0 forces allocation of a unique buffer we can free +        // fixing MAINT-8724 on OSX 10.14 +		int status = -1; +		char* name = abi::__cxa_demangle(mangled, nullptr, 0, &status); +        std::string result(name ? name : mangled); +        free(name); +        return result;  #elif LL_WINDOWS  		// DevStudio: type_info::name() includes the text "class " at the start 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 e3e605d040..1312f6afda 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -192,7 +192,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/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 212e27477b..ed65b1e45f 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -2784,7 +2784,6 @@ void LLScrollListCtrl::onClickColumn(void *userdata)  	}  	// if this column is the primary sort key, reverse the direction -	sort_column_t cur_sort_column;  	if (!parent->mSortColumns.empty() && parent->mSortColumns.back().first == column_index)  	{  		ascending = !parent->mSortColumns.back().second; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b7a860aae0..2fc722d4c3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -201,6 +201,7 @@ set(viewer_SOURCE_FILES      llflickrconnect.cpp      llfloaterabout.cpp      llfloaterbvhpreview.cpp +    llfloaterauction.cpp      llfloaterautoreplacesettings.cpp      llfloateravatar.cpp      llfloateravatarpicker.cpp @@ -822,6 +823,7 @@ set(viewer_HEADER_FILES      llflickrconnect.h      llfloaterabout.h      llfloaterbvhpreview.h +    llfloaterauction.h      llfloaterautoreplacesettings.h      llfloateravatar.h      llfloateravatarpicker.h @@ -2055,7 +2057,12 @@ if (DARWIN)    # These all get set with PROPERTIES    set(product "Second Life")    # this is the setting for the Python wrapper, see SL-322 and WRAPPER line in Info-SecondLife.plist -  set(MACOSX_WRAPPER_EXECUTABLE_NAME "SL_Launcher") +  if (PACKAGE) +      set(MACOSX_WRAPPER_EXECUTABLE_NAME "SL_Launcher") +  else (PACKAGE) +      # force the name of the actual executable to allow running it within Xcode for debugging +      set(MACOSX_WRAPPER_EXECUTABLE_NAME "../Resources/Second Life Viewer.app/Contents/MacOS/Second Life") +  endif (PACKAGE)    set(MACOSX_BUNDLE_INFO_STRING "Second Life Viewer")    set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns")    set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer") diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f0782e0bf7..a01435626f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3703,13 +3703,13 @@  	<key>FeatureManagerHTTPTable</key>        <map>          <key>Comment</key> -        <string>Base directory for HTTP feature/gpu table fetches</string> +        <string>Deprecated</string>          <key>Persist</key> -        <integer>1</integer> +        <integer>0</integer>          <key>Type</key>          <string>String</string>          <key>Value</key> -        <string>http://viewer-settings.secondlife.com</string> +        <string></string>      </map>      <key>FPSLogFrequency</key>          <map> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 5b9f1b9d4f..92a3026096 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -76,6 +76,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; @@ -738,10 +740,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()) @@ -787,23 +786,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;  			}  		} @@ -909,10 +902,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 -	F32 max_distance = 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 @@ -978,10 +968,7 @@ 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 -		F32 max_distance = llmin(mDrawDistance - DIST_FUDGE,  -								 LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); +		F32 max_distance = getCameraMaxZoomDistance();  		if (new_distance > max_distance)  		{ @@ -1946,6 +1933,13 @@ LLVector3 LLAgentCamera::getCameraOffsetInitial()  	return convert_from_llsd<LLVector3>(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 +    return 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 ab793ff316..d087de1e2f 100644 --- a/indra/newview/llagentcamera.h +++ b/indra/newview/llagentcamera.h @@ -112,6 +112,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 f705084bdb..acec68f393 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" @@ -1082,6 +1083,8 @@ bool LLAppViewer::init()  		}  	} +// don't nag developers who need to run the executable directly +#if LL_RELEASE_FOR_DOWNLOAD  	// MAINT-8305: If we're processing a SLURL, skip the launcher check.  	if (gSavedSettings.getString("CmdLineLoginLocation").empty())  	{ @@ -1098,6 +1101,7 @@ bool LLAppViewer::init()  			LLNotificationsUtil::add("RunLauncher");  		}  	} +#endif  #if LL_WINDOWS  	if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) @@ -1794,6 +1798,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. @@ -1980,6 +1986,7 @@ bool LLAppViewer::cleanup()  	mAppCoreHttp.cleanup();  	SUBSYSTEM_CLEANUP(LLFilePickerThread); +	SUBSYSTEM_CLEANUP(LLDirPickerThread);  	//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)  	delete sTextureCache; @@ -2150,6 +2157,7 @@ bool LLAppViewer::initThreads()  	gMeshRepo.init();  	LLFilePickerThread::initClass(); +	LLDirPickerThread::initClass();  	// *FIX: no error handling here!  	return true; @@ -4584,7 +4592,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 97a71a8802..1099d4bc09 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -528,10 +528,24 @@ public:  		registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));  		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -		mPopupMenuHandleAvatar = menu->getHandle(); +		if (menu) +		{ +			mPopupMenuHandleAvatar = menu->getHandle(); +		} +		else +		{ +			LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; +		}  		menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("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)); @@ -619,7 +633,12 @@ public:  		}    		mUserNameFont = style_params.font(); -		LLTextBox* user_name = getChild<LLTextBox>("user_name"); +		if (!mUserNameTextBox) +		{ +			mUserNameTextBox = getChild<LLTextBox>("user_name"); +			mTimeBoxTextBox = getChild<LLTextBox>("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..5443afe60c 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(); - -   BROWSEINFO bi; -   memset(&bi, 0, sizeof(bi)); - -   bi.ulFlags   = BIF_USENEWUI; -   bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); -   bi.lpszTitle = NULL; - -   ::OleInitialize(NULL); +	 +	if (blocking) +	{ +		// Modal, so pause agent +		send_agent_pause(); +	} -   LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi); +	bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow(); -   if(pIDL != NULL) -   { -      WCHAR buffer[_MAX_PATH] = {'\0'}; +	::OleInitialize(NULL); +	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; -      } +		if(::SHGetPathFromIDList(pIDL, buffer) != 0) +		{ +			// Set the string value. -      // free the item id list -      CoTaskMemFree(pIDL); -   } +			mDir = utf16str_to_utf8str(llutf16string(buffer)); +			success = TRUE; +		} +		// free the item id list +		CoTaskMemFree(pIDL); +	} -   ::OleUninitialize(); +	::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*> 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(NULL); +} + +//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<std::string>& 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 <queue> + +#if LL_WINDOWS +#include <shlobj.h> +#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<LLDirPickerThread*> sDeadQ; +	static LLMutex* sMutex; + +	static void initClass(); +	static void cleanupClass(); +	static void clearDead(); + +	std::vector<std::string> mResponses; +	std::string mProposedName; + +	typedef boost::signals2::signal<void(const std::vector<std::string>& 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<std::string>& filenames); + +private: +	dir_picked_signal_t*		mFilePickedSignal; +}; +  #endif diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index b0d48abb14..0873300cd2 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -328,6 +328,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 bc96ee00f7..487496df9a 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -62,13 +62,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 @@ -273,33 +270,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::getVersion().c_str());  	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;  } @@ -407,7 +382,16 @@ bool LLFeatureManager::loadGPUClass()  	if (!gSavedSettings.getBOOL("SkipBenchmark"))  	{  		//get memory bandwidth from benchmark -		F32 gbps = gpu_benchmark(); +		F32 gbps; +		try +		{ +			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 @@ -486,70 +470,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"); - - -#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 - -    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); - - -    LL_INFOS() << "LLFeatureManager fetching " << url << " into " << path << LL_ENDL; - -    LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url); - -    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; -    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - -    if (status) -    {   // 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<std::string, LLFeatureList *> mMaskList;  	std::set<std::string> mSkippedFeatures;  	BOOL		mInited; diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp new file mode 100644 index 0000000000..56619e818a --- /dev/null +++ b/indra/newview/llfloaterauction.cpp @@ -0,0 +1,552 @@ +/**  + * @file llfloaterauction.cpp + * @author James Cook, Ian Wilkes + * @brief Implementation of the auction floater. + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterauction.h" + +#include "llgl.h" +#include "llimagej2c.h" +#include "llimagetga.h" +#include "llparcel.h" +#include "llvfile.h" +#include "llvfs.h" +#include "llwindow.h" +#include "message.h" + +#include "llagent.h" +#include "llassetstorage.h" +#include "llcombobox.h" +#include "llestateinfomodel.h" +#include "llmimetypes.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llsavedsettingsglue.h" +#include "llviewertexturelist.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" +#include "llviewerdisplay.h" +#include "llviewercontrol.h" +#include "llui.h" +#include "llrender.h" +#include "llsdutil.h" +#include "llsdutil_math.h" +#include "lltrans.h" +#include "llcorehttputil.h" + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +void auction_j2c_upload_done(const LLUUID& asset_id, +							   void* user_data, S32 status, LLExtStat ext_status); +void auction_tga_upload_done(const LLUUID& asset_id, +							   void* user_data, S32 status, LLExtStat ext_status); + +///---------------------------------------------------------------------------- +/// Class llfloaterauction +///---------------------------------------------------------------------------- + +// Default constructor +LLFloaterAuction::LLFloaterAuction(const LLSD& key) +  : LLFloater(key), +	mParcelID(-1) +{ +	mCommitCallbackRegistrar.add("ClickSnapshot",	boost::bind(&LLFloaterAuction::onClickSnapshot, this)); +	mCommitCallbackRegistrar.add("ClickSellToAnyone",		boost::bind(&LLFloaterAuction::onClickSellToAnyone, this)); +	mCommitCallbackRegistrar.add("ClickStartAuction",		boost::bind(&LLFloaterAuction::onClickStartAuction, this)); +	mCommitCallbackRegistrar.add("ClickResetParcel",		boost::bind(&LLFloaterAuction::onClickResetParcel, this)); +} + +// Destroys the object +LLFloaterAuction::~LLFloaterAuction() +{ +} + +BOOL LLFloaterAuction::postBuild() +{ +	return TRUE; +} + +void LLFloaterAuction::onOpen(const LLSD& key) +{ +	initialize(); +} + +void LLFloaterAuction::initialize() +{ +	mParcelUpdateCapUrl.clear(); + +	mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection(); +	LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); +	LLParcel* parcelp = mParcelp->getParcel(); +	if(parcelp && region && !parcelp->getForSale()) +	{ +		mParcelHost = region->getHost(); +		mParcelID = parcelp->getLocalID(); +		mParcelUpdateCapUrl = region->getCapability("ParcelPropertiesUpdate"); + +		getChild<LLUICtrl>("parcel_text")->setValue(parcelp->getName()); +		getChildView("snapshot_btn")->setEnabled(TRUE); +		getChildView("reset_parcel_btn")->setEnabled(TRUE); +		getChildView("start_auction_btn")->setEnabled(TRUE); + +		U32 estate_id = LLEstateInfoModel::instance().getID(); +		// Only enable "Sell to Anyone" on Teen grid or if we don't know the ID yet +		getChildView("sell_to_anyone_btn")->setEnabled(estate_id == ESTATE_TEEN || estate_id == 0); +	} +	else +	{ +		mParcelHost.invalidate(); +		if(parcelp && parcelp->getForSale()) +		{ +			getChild<LLUICtrl>("parcel_text")->setValue(getString("already for sale")); +		} +		else +		{ +			getChild<LLUICtrl>("parcel_text")->setValue(LLStringUtil::null); +		} +		mParcelID = -1; +		getChildView("snapshot_btn")->setEnabled(false); +		getChildView("reset_parcel_btn")->setEnabled(false); +		getChildView("sell_to_anyone_btn")->setEnabled(false); +		getChildView("start_auction_btn")->setEnabled(false); +	} + +	mImageID.setNull(); +	mImage = NULL; +} + +void LLFloaterAuction::draw() +{ +	LLFloater::draw(); + +	if(!isMinimized() && mImage.notNull())  +	{ +		LLView* snapshot_icon = findChildView("snapshot_icon"); +		if (snapshot_icon) +		{ +			LLRect rect = snapshot_icon->getRect(); +			{ +				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +				gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f)); +				rect.stretch(-1); +			} +			{ +				LLGLSUIDefault gls_ui; +				gGL.color3f(1.f, 1.f, 1.f); +				gl_draw_scaled_image(rect.mLeft, +									 rect.mBottom, +									 rect.getWidth(), +									 rect.getHeight(), +									 mImage); +			} +		} +	} +} + + +// static +void LLFloaterAuction::onClickSnapshot(void* data) +{ +	LLFloaterAuction* self = (LLFloaterAuction*)(data); + +	LLPointer<LLImageRaw> raw = new LLImageRaw; + +	gForceRenderLandFence = self->getChild<LLUICtrl>("fence_check")->getValue().asBoolean(); +	BOOL success = gViewerWindow->rawSnapshot(raw, +											  gViewerWindow->getWindowWidthScaled(), +											  gViewerWindow->getWindowHeightScaled(), +											  TRUE, FALSE, +											  FALSE, FALSE); +	gForceRenderLandFence = FALSE; + +	if (success) +	{ +		self->mTransactionID.generate(); +		self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + +		if(!gSavedSettings.getBOOL("QuietSnapshotsToDisk")) +		{ +			gViewerWindow->playSnapshotAnimAndSound(); +		} +		LL_INFOS() << "Writing TGA..." << LL_ENDL; + +		LLPointer<LLImageTGA> tga = new LLImageTGA; +		tga->encode(raw); +		LLVFile::writeFile(tga->getData(), tga->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_IMAGE_TGA); +		 +		raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT); + +		LL_INFOS() << "Writing J2C..." << LL_ENDL; + +		LLPointer<LLImageJ2C> j2c = new LLImageJ2C; +		j2c->encode(raw, 0.0f); +		LLVFile::writeFile(j2c->getData(), j2c->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_TEXTURE); + +		self->mImage = LLViewerTextureManager::getLocalTexture((LLImageRaw*)raw, FALSE); +		gGL.getTexUnit(0)->bind(self->mImage); +		self->mImage->setAddressMode(LLTexUnit::TAM_CLAMP); +	} +	else +	{ +		LL_WARNS() << "Unable to take snapshot" << LL_ENDL; +	} +} + +// static +void LLFloaterAuction::onClickStartAuction(void* data) +{ +	LLFloaterAuction* self = (LLFloaterAuction*)(data); + +	if(self->mImageID.notNull()) +	{ +		LLSD parcel_name = self->getChild<LLUICtrl>("parcel_text")->getValue(); + +	// create the asset +		std::string* name = new std::string(parcel_name.asString()); +		gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_TGA, +									&auction_tga_upload_done, +									(void*)name, +									FALSE); +		self->getWindow()->incBusyCount(); + +		std::string* j2c_name = new std::string(parcel_name.asString()); +		gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_TEXTURE, +								   &auction_j2c_upload_done, +								   (void*)j2c_name, +								   FALSE); +		self->getWindow()->incBusyCount(); + +		LLNotificationsUtil::add("UploadingAuctionSnapshot"); + +	} +	LLMessageSystem* msg = gMessageSystem; + +	msg->newMessage("ViewerStartAuction"); + +	msg->nextBlock("AgentData"); +	msg->addUUID("AgentID", gAgent.getID()); +	msg->addUUID("SessionID", gAgent.getSessionID()); +	msg->nextBlock("ParcelData"); +	msg->addS32("LocalID", self->mParcelID); +	msg->addUUID("SnapshotID", self->mImageID); +	msg->sendReliable(self->mParcelHost); + +	// clean up floater, and get out +	self->cleanupAndClose(); +} + + +void LLFloaterAuction::cleanupAndClose() +{ +	mImageID.setNull(); +	mImage = NULL; +	mParcelID = -1; +	mParcelHost.invalidate(); +	closeFloater(); +} + + + +// static glue +void LLFloaterAuction::onClickResetParcel(void* data) +{ +	LLFloaterAuction* self = (LLFloaterAuction*)(data); +	if (self) +	{ +		self->doResetParcel(); +	} +} + + +// Reset all the values for the parcel in preparation for a sale +void LLFloaterAuction::doResetParcel() +{ +	LLParcel* parcelp = mParcelp->getParcel(); +	LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + +	if (parcelp +		&& region +		&& !mParcelUpdateCapUrl.empty()) +	{ +		LLSD body; +		std::string empty; + +		// request new properties update from simulator +		U32 message_flags = 0x01; +		body["flags"] = ll_sd_from_U32(message_flags); + +		// Set all the default parcel properties for auction +		body["local_id"] = parcelp->getLocalID(); + +		U32 parcel_flags = PF_ALLOW_LANDMARK | +						   PF_ALLOW_FLY	| +						   PF_CREATE_GROUP_OBJECTS | +						   PF_ALLOW_ALL_OBJECT_ENTRY | +						   PF_ALLOW_GROUP_OBJECT_ENTRY | +						   PF_ALLOW_GROUP_SCRIPTS | +						   PF_RESTRICT_PUSHOBJECT | +						   PF_SOUND_LOCAL | +						   PF_ALLOW_VOICE_CHAT | +						   PF_USE_ESTATE_VOICE_CHAN; + +		body["parcel_flags"] = ll_sd_from_U32(parcel_flags); +		 +		// Build a parcel name like "Ahern (128,128) PG 4032m" +		std::ostringstream parcel_name; +		LLVector3 center_point( parcelp->getCenterpoint() ); +		center_point.snap(0);		// Get rid of fractions +		parcel_name << region->getName()  +					<< " (" +					<< (S32) center_point.mV[VX] +					<< "," +					<< (S32) center_point.mV[VY]						 +					<< ") " +					<< region->getSimAccessString() +					<< " " +					<< parcelp->getArea() +					<< "m"; + +		std::string new_name(parcel_name.str().c_str()); +		body["name"] = new_name; +		getChild<LLUICtrl>("parcel_text")->setValue(new_name);	// Set name in dialog as well, since it won't get updated otherwise + +		body["sale_price"] = (S32) 0; +		body["description"] = empty; +		body["music_url"] = empty; +		body["media_url"] = empty; +		body["media_desc"] = empty; +		body["media_type"] = LLMIMETypes::getDefaultMimeType(); +		body["media_width"] = (S32) 0; +		body["media_height"] = (S32) 0; +		body["auto_scale"] = (S32) 0; +		body["media_loop"] = (S32) 0; +		body["obscure_media"] = (S32) 0; // OBSOLETE - no longer used +		body["obscure_music"] = (S32) 0; // OBSOLETE - no longer used +		body["media_id"] = LLUUID::null; +		body["group_id"] = MAINTENANCE_GROUP_ID;	// Use maintenance group +		body["pass_price"] = (S32) 10;		// Defaults to $10 +		body["pass_hours"] = 0.0f; +		body["category"] = (U8) LLParcel::C_NONE; +		body["auth_buyer_id"] = LLUUID::null; +		body["snapshot_id"] = LLUUID::null; +		body["user_location"] = ll_sd_from_vector3( LLVector3::zero ); +		body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero ); +		body["landing_type"] = (U8) LLParcel::L_DIRECT; + +		LL_INFOS() << "Sending parcel update to reset for auction via capability to: " +			<< mParcelUpdateCapUrl << LL_ENDL; + +        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(mParcelUpdateCapUrl, body, +            "Parcel reset for auction", +            "Parcel not set for auction."); + +		// Send a message to clear the object return time +		LLMessageSystem *msg = gMessageSystem; +		msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime); +		msg->nextBlockFast(_PREHASH_AgentData); +		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +		msg->nextBlockFast(_PREHASH_ParcelData); +		msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID()); +		msg->addS32Fast(_PREHASH_OtherCleanTime, 5);			// 5 minute object auto-return + +		msg->sendReliable(region->getHost()); + +		// Clear the access lists +		clearParcelAccessList(parcelp, region, AL_ACCESS); +		clearParcelAccessList(parcelp, region, AL_BAN); +		clearParcelAccessList(parcelp, region, AL_ALLOW_EXPERIENCE); +		clearParcelAccessList(parcelp, region, AL_BLOCK_EXPERIENCE); +	} +} + + + +void LLFloaterAuction::clearParcelAccessList(LLParcel* parcel, LLViewerRegion* region, U32 list) +{ +	if (!region || !parcel) return; + +	LLUUID transactionUUID; +	transactionUUID.generate(); + +	LLMessageSystem* msg = gMessageSystem; + +	msg->newMessageFast(_PREHASH_ParcelAccessListUpdate); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); +	msg->nextBlockFast(_PREHASH_Data); +	msg->addU32Fast(_PREHASH_Flags, list); +	msg->addS32(_PREHASH_LocalID, parcel->getLocalID() ); +	msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID); +	msg->addS32Fast(_PREHASH_SequenceID, 1);			// sequence_id +	msg->addS32Fast(_PREHASH_Sections, 0);				// num_sections + +	// pack an empty block since there will be no data +	msg->nextBlockFast(_PREHASH_List); +	msg->addUUIDFast(_PREHASH_ID,  LLUUID::null ); +	msg->addS32Fast(_PREHASH_Time, 0 ); +	msg->addU32Fast(_PREHASH_Flags,	0 ); + +	msg->sendReliable( region->getHost() ); +} + + + +// static - 'Sell to Anyone' clicked, throw up a confirmation dialog +void LLFloaterAuction::onClickSellToAnyone(void* data) +{ +	LLFloaterAuction* self = (LLFloaterAuction*)(data); +	if (self) +	{ +		LLParcel* parcelp = self->mParcelp->getParcel(); + +		// Do a confirmation +		S32 sale_price = parcelp->getArea();	// Selling for L$1 per meter +		S32 area = parcelp->getArea(); + +		LLSD args; +		args["LAND_SIZE"] = llformat("%d", area); +		args["SALE_PRICE"] = llformat("%d", sale_price); +		args["NAME"] = LLTrans::getString("Anyone"); + +		LLNotification::Params params("ConfirmLandSaleChange");	// Re-use existing dialog +		params.substitutions(args) +			.functor.function(boost::bind(&LLFloaterAuction::onSellToAnyoneConfirmed, self, _1, _2)); + +		params.name("ConfirmLandSaleToAnyoneChange"); +		 +		// ask away +		LLNotifications::instance().add(params); +	} +} + + +// Sell confirmation clicked +bool LLFloaterAuction::onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response)	 +{ +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	if (option == 0) +	{ +		doSellToAnyone(); +	} + +	return false; +} + + + +// Reset all the values for the parcel in preparation for a sale +void LLFloaterAuction::doSellToAnyone() +{ +	LLParcel* parcelp = mParcelp->getParcel(); +	LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + +	if (parcelp +		&& region +		&& !mParcelUpdateCapUrl.empty()) +	{ +		LLSD body; +		std::string empty; + +		// request new properties update from simulator +		U32 message_flags = 0x01; +		body["flags"] = ll_sd_from_U32(message_flags); + +		// Set all the default parcel properties for auction +		body["local_id"] = parcelp->getLocalID(); + +		// Set 'for sale' flag +		U32 parcel_flags = parcelp->getParcelFlags() | PF_FOR_SALE; +		// Ensure objects not included +		parcel_flags &= ~PF_FOR_SALE_OBJECTS; +		body["parcel_flags"] = ll_sd_from_U32(parcel_flags); +		 +		body["sale_price"] = parcelp->getArea();	// Sell for L$1 per square meter +		body["auth_buyer_id"] = LLUUID::null;		// To anyone + +		LL_INFOS() << "Sending parcel update to sell to anyone for L$1 via capability to: " +			<< mParcelUpdateCapUrl << LL_ENDL; + +        LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(mParcelUpdateCapUrl, body, +            "Parcel set as sell to everyone.", +            "Parcel sell to everyone failed."); + +		// clean up floater, and get out +		cleanupAndClose(); +	} +} + + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- + +void auction_tga_upload_done(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) +{ +	std::string* name = (std::string*)(user_data); +	LL_INFOS() << "Upload of asset '" << *name << "' " << asset_id +			<< " returned " << status << LL_ENDL; +	delete name; + +	gViewerWindow->getWindow()->decBusyCount(); + +	if (0 == status) +	{ +		LLNotificationsUtil::add("UploadWebSnapshotDone"); +	} +	else +	{ +		LLSD args; +		args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); +		LLNotificationsUtil::add("UploadAuctionSnapshotFail", args); +	} +} + +void auction_j2c_upload_done(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed) +{ +	std::string* name = (std::string*)(user_data); +	LL_INFOS() << "Upload of asset '" << *name << "' " << asset_id +			<< " returned " << status << LL_ENDL; +	delete name; + +	gViewerWindow->getWindow()->decBusyCount(); + +	if (0 == status) +	{ +		LLNotificationsUtil::add("UploadSnapshotDone"); +	} +	else +	{ +		LLSD args; +		args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); +		LLNotificationsUtil::add("UploadAuctionSnapshotFail", args); +	} +} diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h new file mode 100644 index 0000000000..c83a11ba8b --- /dev/null +++ b/indra/newview/llfloaterauction.h @@ -0,0 +1,86 @@ +/**  + * @file llfloaterauction.h + * @author James Cook, Ian Wilkes + * @brief llfloaterauction class header file + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERAUCTION_H +#define LL_LLFLOATERAUCTION_H + +#include "llfloater.h" +#include "lluuid.h" +#include "llpointer.h" +#include "llviewertexture.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterAuction +// +// Class which holds the functionality to start auctions. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLParcelSelection; +class LLParcel; +class LLViewerRegion; + +class LLFloaterAuction : public LLFloater +{ +	friend class LLFloaterReg; +public: +	// LLFloater interface +	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ void draw(); + +private: +	 +	LLFloaterAuction(const LLSD& key); +	~LLFloaterAuction(); +	 +	void initialize(); + +	static void onClickSnapshot(void* data); +	static void onClickResetParcel(void* data); +	static void onClickSellToAnyone(void* data);		// Sell to anyone clicked +	bool onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response);	// Sell confirmation clicked +	static void onClickStartAuction(void* data); + +	/*virtual*/ BOOL postBuild(); + +	void doResetParcel(); +	void doSellToAnyone(); +	void clearParcelAccessList( LLParcel* parcel, LLViewerRegion* region, U32 list); +	void cleanupAndClose(); + +private: + +	LLTransactionID mTransactionID; +	LLAssetID mImageID; +	LLPointer<LLViewerTexture> mImage; +	LLSafeHandle<LLParcelSelection> mParcelp; +	S32 mParcelID; +	LLHost mParcelHost; + +	std::string mParcelUpdateCapUrl;	// "ParcelPropertiesUpdate" capability +}; + + +#endif // LL_LLFLOATERAUCTION_H diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 596b04c31c..88b3fb7b96 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" @@ -542,6 +542,7 @@ void LLPanelLandGeneral::refresh()  	mBtnDeedToGroup->setEnabled(FALSE);  	mBtnSetGroup->setEnabled(FALSE); +	mBtnStartAuction->setEnabled(FALSE);  	mCheckDeedToGroup	->set(FALSE);  	mCheckDeedToGroup	->setEnabled(FALSE); @@ -639,6 +640,7 @@ void LLPanelLandGeneral::refresh()  			mTextClaimDate->setEnabled(FALSE);  			mTextGroup->setText(getString("none_text"));  			mTextGroup->setEnabled(FALSE); +			mBtnStartAuction->setEnabled(FALSE);  		}  		else  		{ @@ -690,6 +692,11 @@ void LLPanelLandGeneral::refresh()  			LLStringUtil::format (claim_date_str, substitution);  			mTextClaimDate->setText(claim_date_str);  			mTextClaimDate->setEnabled(is_leased); + +			BOOL enable_auction = (gAgent.getGodLevel() >= GOD_LIAISON) +								  && (owner_id == GOVERNOR_LINDEN_ID) +								  && (parcel->getAuctionID() == 0); +			mBtnStartAuction->setEnabled(enable_auction);  		}  		// Display options @@ -1017,8 +1024,20 @@ void LLPanelLandGeneral::onClickBuyPass(void* data)  // static  void LLPanelLandGeneral::onClickStartAuction(void* data)  { -	std::string auction_url = "https://places.[GRID]/auctions/"; -	LLWeb::loadURLExternal(LLWeb::expandURLSubstitutions(auction_url, LLSD())); +	LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; +	LLParcel* parcelp = panelp->mParcel->getParcel(); +	if(parcelp) +	{ +		if(parcelp->getForSale()) +		{ +			LLNotificationsUtil::add("CannotStartAuctionAlreadyForSale"); +		} +		else +		{ +			//LLFloaterAuction::showInstance(); +			LLFloaterReg::showInstance("auction"); +		} +	}  }  // static diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 9d723bdd9d..4ce35643b1 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -1096,16 +1096,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<std::string>& 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); @@ -1744,25 +1743,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(); +	(new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeLogPath, this, _1, _2), proposed_name))->getFile(); +} +void LLFloaterPreference::changeLogPath(const std::vector<std::string>& filenames, std::string proposed_name) +{  	//Path changed -	if(proposed_name != dir_name) +	if (proposed_name != filenames[0])  	{ -	gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name); +		gSavedPerAccountSettings.setString("InstantMessageLogPath", filenames[0]);  		mPriorInstantMessageLogPath = proposed_name; -	 -	// enable/disable 'Delete transcripts button -	updateDeleteTranscriptsButton(); -} + +		// enable/disable 'Delete transcripts button +		updateDeleteTranscriptsButton(); +	}  }  bool LLFloaterPreference::moveTranscriptsAndLog() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 0cd7bac20f..8339a18296 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -133,6 +133,7 @@ public:  	void setCacheLocation(const LLStringExplicit& location);  	void onClickSetCache(); +	void changeCachePath(const std::vector<std::string>& filenames, std::string proposed_name);  	void onClickResetCache();  	void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);  	void onSelectSkin(); @@ -145,6 +146,7 @@ public:  	void resetAllIgnored();  	void setAllIgnored();  	void onClickLogPath(); +	void changeLogPath(const std::vector<std::string>& filenames, std::string proposed_name);  	bool moveTranscriptsAndLog();  	void enableHistory();  	void setPersonalInfo(const std::string& visibility, bool im_via_email, bool is_verified_email); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 156b2ba7b1..c08aaf3f50 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1309,17 +1309,15 @@ void LLFloaterSnapshot::saveTexture()  	previewp->saveTexture();  } -BOOL LLFloaterSnapshot::saveLocal() +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); -		return FALSE; +		previewp->saveLocal(success_cb, failure_cb);  	} - -	return previewp->saveLocal();  }  void LLFloaterSnapshotBase::postSave() diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 698273ac90..bcba14d63d 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -156,7 +156,9 @@ public:  	static LLFloaterSnapshot* getInstance();  	static LLFloaterSnapshot* findInstance();  	/*virtual*/ void saveTexture(); -	BOOL saveLocal(); + +	typedef boost::signals2::signal<void(void)> 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 4b0b10dd5a..a9b15fc8b6 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -966,15 +966,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/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index dc3b153da2..a90a29a731 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1166,72 +1166,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<std::string>& 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); +            image_load_error = image_info.getLastError(); +        } -            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; -            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); -            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); +        } -                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; +        } -            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; -            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; -    } +        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<std::string>& 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 ef5ce155b1..142dea83e2 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -204,6 +204,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<LLComboBox>("start_location_combo");  	updateLocationSelectorsVisibility(); // separate so that it can be called from preferences @@ -271,6 +272,9 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,  	LLTextBox* forgot_password_text = getChild<LLTextBox>("forgot_password_text");  	forgot_password_text->setClickedCallback(onClickForgotPassword, NULL); +	LLTextBox* sign_up_text = getChild<LLTextBox>("sign_up_text"); +	sign_up_text->setClickedCallback(onClickSignUp, NULL); +  	// get the web browser control  	LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");  	web_browser->addObserver(this); @@ -921,6 +925,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 852195b304..c633582d89 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -99,6 +99,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/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index a7c53a7050..fc44ce340c 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -100,6 +100,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;  } @@ -126,6 +130,9 @@ std::string click_action_to_string_value( U8 action)  		case CLICK_ACTION_ZOOM:  			return "Zoom";  			break; +		case CLICK_ACTION_DISABLED: +			return "None"; +			break;  	}  } diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 77378f8092..e7fced92a7 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -65,6 +65,9 @@ private:  	void onFormatComboCommit(LLUICtrl* ctrl);  	void onQualitySliderCommit(LLUICtrl* ctrl);  	void onSaveFlyoutCommit(LLUICtrl* ctrl); + +	void onLocalSaved(); +	void onLocalCanceled();  };  static LLPanelInjector<LLPanelSnapshotLocal> panel_class("llpanelsnapshotlocal"); @@ -164,19 +167,22 @@ void LLPanelSnapshotLocal::onSaveFlyoutCommit(LLUICtrl* ctrl)  	LLFloaterSnapshot* floater = LLFloaterSnapshot::getInstance();  	floater->notify(LLSD().with("set-working", true)); -	BOOL saved = floater->saveLocal(); -	if (saved) -	{ -		mSnapshotFloater->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::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(); +	LLFloaterSnapshot::getInstance()->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "local")));  } +  LLSnapshotModel::ESnapshotType LLPanelSnapshotLocal::getSnapshotType()  {  	return LLSnapshotModel::SNAPSHOT_LOCAL; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index d4eecaffce..9431914ba3 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1741,14 +1741,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 f73722521a..f03c7abc4d 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -1130,6 +1130,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 ee8b2d79c0..d0cff1464b 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*> LLSnapshotLivePreview::sList; +LLPointer<LLImageFormatted> LLSnapshotLivePreview::sSaveLocalImage = NULL;  LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Params& p)   	:	LLView(p), @@ -131,6 +132,7 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview()  	// 	gIdleCallbacks.deleteFunction( &LLSnapshotLivePreview::onIdle, (void*)this );  	sList.erase(this); +	sSaveLocalImage = NULL;  }  void LLSnapshotLivePreview::setMaxImageSize(S32 size)  @@ -1065,53 +1067,19 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)  	mDataSize = 0;  } -BOOL LLSnapshotLivePreview::saveLocal() +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 -	BOOL success = saveLocal(mFormattedImage); - -	if(success) -	{ -		gViewerWindow->playSnapshotAnimAndSound(); -	} -	return success; +	saveLocal(mFormattedImage, success_cb, failure_cb);  }  //Check if failed due to insufficient memory -BOOL LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> mFormattedImage) +void LLSnapshotLivePreview::saveLocal(LLPointer<LLImageFormatted> image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb)  { -	BOOL insufficient_memory; -	BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage, FALSE, insufficient_memory); +	sSaveLocalImage = image; -	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; +	gViewerWindow->saveImageNumbered(sSaveLocalImage, FALSE, success_cb, failure_cb);  } diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 4ea8d25a5a..683cd016d8 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<void(void)> snapshot_saved_signal_t; -	static BOOL saveLocal(LLPointer<LLImageFormatted>); +	static void saveLocal(LLPointer<LLImageFormatted> 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, LLView::Params>  	{  		Params() @@ -101,7 +102,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 = ""); -	BOOL saveLocal(); +	void saveLocal(const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb);  	LLPointer<LLImageFormatted>	getFormattedImage();  	LLPointer<LLImageRaw>		getEncodedImage(); @@ -170,7 +171,9 @@ private:  	LLQuaternion				mCameraRot;  	BOOL						mSnapshotActive;  	LLSnapshotModel::ESnapshotLayerType mSnapshotBufferType; -    std::string                 mFilterName; +	std::string					mFilterName; + +	static LLPointer<LLImageFormatted> sSaveLocalImage;  public:  	static std::set<LLSnapshotLivePreview*> sList; diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 2a0d961952..dd5dce3279 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -2027,13 +2027,15 @@ bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 dis  		if(w * h *c > 0) //valid  		{  			//make a duplicate to keep the original raw image untouched. -			raw = raw->scaled(w, h); +			raw = raw->duplicate();  			if (raw->isBufferInvalid())  			{  				LL_WARNS() << "Invalid image duplicate buffer" << LL_ENDL;  				return false;  			} +			raw->scale(w, h); +  			discardlevel += i ;  		}  	} diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 9fb53dc9ab..0f38cca56f 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -263,7 +263,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)); @@ -2335,6 +2335,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 f473000657..6a8843cb44 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -300,6 +300,8 @@ BOOL LLToolPie::handleLeftClickPick()  				}  			}  			return TRUE;			 +		case CLICK_ACTION_DISABLED: +			return TRUE;  		default:  			// nothing  			break; @@ -463,6 +465,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;  	} @@ -528,6 +532,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 55317bdaf5..0ebacddd9b 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" @@ -193,6 +194,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("about_land", "floater_about_land.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLand>);  	LLFloaterReg::add("appearance", "floater_my_appearance.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSidePanelContainer>);  	LLFloaterReg::add("associate_listing", "floater_associate_listing.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAssociateListing>); +	LLFloaterReg::add("auction", "floater_auction.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAuction>);  	LLFloaterReg::add("avatar", "floater_avatar.xml",  (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatar>);  	LLFloaterReg::add("avatar_picker", "floater_avatar_picker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarPicker>);  	LLFloaterReg::add("avatar_render_settings", "floater_avatar_render_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAvatarRenderSettings>); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index dc05d98228..cf1c442ce9 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -203,38 +203,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<std::string>& filenames)  { -	if (filenames.empty()) return; - -	if (mFilePickedSignal) +	if (filenames.empty()) +	{ +		if (mFailureSignal) +		{ +			(*mFailureSignal)(filenames, mLoadFilter, mSaveFilter); +		} +	} +	else  	{ -		(*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); +		if (mFilePickedSignal) +		{ +			(*mFilePickedSignal)(filenames, mLoadFilter, mSaveFilter); +		}  	}  } @@ -592,7 +609,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t  									   gSavedSettings.getBOOL("RenderUIInSnapshot"),  									   FALSE))  		{ -			gViewerWindow->playSnapshotAnimAndSound();  			LLPointer<LLImageFormatted> formatted;              LLSnapshotModel::ESnapshotFormat fmt = (LLSnapshotModel::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");  			switch (fmt) diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 15bbdd1e2d..35f86f606b 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -113,8 +113,8 @@ public:  	typedef boost::signals2::signal<void(const std::vector<std::string>& 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<std::string>& filenames); @@ -123,6 +123,7 @@ private:  	LLFilePicker::ELoadFilter	mLoadFilter;  	LLFilePicker::ESaveFilter	mSaveFilter;  	file_picked_signal_t*		mFilePickedSignal; +	file_picked_signal_t*		mFailureSignal;  }; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 0f326efe09..6cba7dd70c 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -153,6 +153,96 @@ 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() << "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() << "HTTP status, " << status.toTerseString() << +            ". friendship offer accept failed." << LL_ENDL; +    } +    else +    { +        if (!result.has("success") || result["success"].asBoolean() == false) +        { +            LL_WARNS() << "Server failed to process accepted friendship. " << httpResults << LL_ENDL; +        } +        else +        { +            // 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) +{ +    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() << "Empty capability!" << LL_ENDL; +        return; +    } + +    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() << "HTTP status, " << status.toTerseString() << +            ". friendship offer decline failed." << LL_ENDL; +    } +    else +    { +        if (!result.has("success") || result["success"].asBoolean() == false) +        { +            LL_WARNS() << "Server failed to process declined friendship. " << httpResults << LL_ENDL; +        } +        else +        { +            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); @@ -163,9 +253,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: @@ -176,46 +263,73 @@ 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())); - -		    LLSD payload = notification["payload"]; -		    LLNotificationsUtil::add("FriendshipAcceptedByMe", -				    notification["substitutions"], payload); +            std::string url = gAgent.getRegionCapability("AcceptFriendship"); +            if (!url.empty()) +            { +                LLCoros::instance().launch("LLMessageSystem::acceptFriendshipOffer", +                    boost::bind(accept_friendship_coro, url, notification)); +            } +            else if (payload.has("session_id") && payload["session_id"].asUUID().notNull()) +            { +                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())); + +                // add friend to recent people list +                LLRecentPeople::instance().add(payload["from_id"]); +                LLNotificationsUtil::add("FriendshipAcceptedByMe", +                    notification["substitutions"], payload); +            } +            else +            { +                LL_WARNS() << "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())); - -			    // start IM session -			    if(2 == option) -			    { -				    LLAvatarActions::startIM(payload["from_id"].asUUID()); -			    } +                // the rejection to the simulator to delete the pending userop. +                std::string url = gAgent.getRegionCapability("DeclineFriendship"); +                if (!url.empty()) +                { +                    LLCoros::instance().launch("LLMessageSystem::declineFriendshipOffer", +                        boost::bind(decline_friendship_coro, url, notification, option)); +                } +                else if (payload.has("session_id") && payload["session_id"].asUUID().notNull()) +                { +                    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())); + +                    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() << "Failed to decline friendship offer, neither capability nor transaction id are accessible" << LL_ENDL; +                }  	    }  	    default:  		    // close button probably, possibly timed out @@ -3258,6 +3372,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<LLUUID, PostponedSoundData> 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<LLUUID, PostponedSoundData>::iterator iter = postponed_sounds.begin(); +    std::map<LLUUID, PostponedSoundData>::iterator end = postponed_sounds.end(); +    while (iter != end) +    { +        std::map<LLUUID, PostponedSoundData>::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<LLUUID, PostponedSoundData>::iterator iter = postponed_sounds.begin(); +    std::map<LLUUID, PostponedSoundData>::iterator end = postponed_sounds.end(); +    while (iter != end) +    { +        std::map<LLUUID, PostponedSoundData>::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. @@ -3276,7 +3494,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) @@ -3292,7 +3515,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) @@ -3323,7 +3551,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"); @@ -3545,28 +3778,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<LLUUID, PostponedSoundData>::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/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 6937d064f9..9f6d606a22 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -63,7 +63,7 @@ const std::string  GRID_LOGIN_IDENTIFIER_TYPES = "login_identifier_types";  const std::string GRID_SLURL_BASE = "slurl_base";  const std::string GRID_APP_SLURL_BASE = "app_slurl_base"; -const std::string DEFAULT_LOGIN_PAGE = "http://viewer-login.agni.lindenlab.com/"; +const std::string DEFAULT_LOGIN_PAGE = "https://viewer-splash.secondlife.com/";  const std::string MAIN_GRID_LOGIN_URI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi"; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index feaafad2e1..832dcc2dd8 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1877,7 +1877,7 @@ void LLViewerRegion::updateNetStats()  	mLastPacketsLost =	mPacketsLost;  	mPacketsIn =				cdp->getPacketsIn(); -	mBitsIn =					cdp->getBytesIn(); +	mBitsIn =					8 * cdp->getBytesIn();  	mPacketsOut =				cdp->getPacketsOut();  	mPacketsLost =				cdp->getPacketsLost();  	mPingDelay =				cdp->getPingDelay(); @@ -2817,6 +2817,7 @@ void LLViewerRegion::unpackRegionHandshake()  void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  {  	capabilityNames.append("AbuseCategories"); +	capabilityNames.append("AcceptFriendship");  	capabilityNames.append("AgentPreferences");  	capabilityNames.append("AgentState");  	capabilityNames.append("AttachmentResources"); @@ -2826,6 +2827,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("ChatSessionRequest");  	capabilityNames.append("CopyInventoryFromNotecard");  	capabilityNames.append("CreateInventoryCategory"); +	capabilityNames.append("DeclineFriendship");  	capabilityNames.append("DispatchRegionInfo");  	capabilityNames.append("DirectDelivery");  	capabilityNames.append("EnvironmentSettings"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f394d6913f..cef19c9c2d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -193,6 +193,7 @@  #include "llviewerdisplay.h"  #include "llspatialpartition.h"  #include "llviewerjoystick.h" +#include "llviewermenufile.h" // LLFilePickerReplyThread  #include "llviewernetwork.h"  #include "llpostprocess.h"  #include "llfloaterimnearbychat.h" @@ -4365,77 +4366,110 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d  }  // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory) +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)  { -	insufficient_memory = FALSE; -  	if (!image)  	{  		LL_WARNS() << "No image to save" << LL_ENDL; -		return 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; // ??? -	 -	BOOL is_snapshot_name_loc_set = isSnapshotLocSet(); - +	LLImageFormatted* formatted_image = image;  	// Get a base file location if needed.  	if (force_picker || !isSnapshotLocSet())  	{ -		std::string proposed_name( sSnapshotBaseName ); +		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; -		// pick a directory in which to save -		LLFilePicker& picker = LLFilePicker::instance(); -		if (!picker.getSaveFile(pick_type, proposed_name)) -		{ -			// Clicked cancel -			return FALSE; -		} +		(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<std::string>& 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]; -		// Copy the directory + file name -		std::string filepath = picker.getFirstFile(); +	gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); +	gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); +	saveImageLocal(image, success_cb, failure_cb); +} -		gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); -		gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); -	} +void LLViewerWindow::onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb) +{ +	failure_cb(); +} -	std::string snapshot_dir = sSnapshotDir; -	if(snapshot_dir.empty()) + +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())  	{ -		return FALSE; +		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 (!boost::filesystem::is_directory(b_path)) +	{ +		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())  	{ -		insufficient_memory = TRUE; -		return FALSE; +		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 = sSnapshotDir; @@ -4457,7 +4491,15 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image, BOOL force_picke  			&& is_snapshot_name_loc_set); // Or stop if we are rewriting.  	LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; -	return image->save(filepath); +	if (image->save(filepath)) +	{ +		playSnapshotAnimAndSound(); +		success_cb(); +	} +	else +	{ +		failure_cb(); +	}  }  void LLViewerWindow::resetSnapshotLoc() diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index c01921641c..d8d420e6be 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -352,7 +352,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; -	BOOL			saveImageNumbered(LLImageFormatted *image, BOOL force_picker, BOOL& insufficient_memory); + +	typedef boost::signals2::signal<void(void)> 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<std::string>& 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 da4b6a5008..6a3242b43f 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -6193,6 +6193,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/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index cf843a07a6..535af317d9 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -502,7 +502,7 @@               name="Buy Land..."               width="130" />  			<button -             enabled="true" +             enabled="false"               follows="left|top"               height="23"               label="Linden Sale" diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml new file mode 100644 index 0000000000..9c6d114c4c --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_auction.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + height="412" + layout="topleft" + min_height="412" + min_width="420" + name="floater_auction" + help_topic="floater_auction" + title="START LINDEN LAND SALE" + width="420"> +    <floater.string +     name="already for sale"> +        You cannot auction parcels which are already for sale. +    </floater.string> +    <icon +     bottom="280" +     follows="left|right|top|bottom" +     layout="topleft" +     left="4" +     name="snapshot_icon" +     right="-4" +     top="24" /> +    <text +     follows="left|right|bottom" +     height="16" +     layout="topleft" +     left_delta="0" +     name="parcel_text" +     top_pad="12" +     width="400" /> +    <check_box +     control_name="AuctionShowFence"  +     follows="left|bottom" +     height="16" +     initial_value="true" +     label="Include yellow selection fence" +     layout="topleft" +     left_delta="0" +     name="fence_check" +     top_pad="12" +     width="199" /> +    <button +     follows="left|bottom" +     height="20" +     label="Snapshot" +     label_selected="Snapshot" +     layout="topleft" +     left_delta="0" +     name="snapshot_btn" +     top_pad="4" +     width="150"> +      <button.commit_callback +         function="ClickSnapshot" /> +    </button> +    <button +     follows="left|bottom" +     height="20" +     label="Sell to Anyone" +     label_selected="Sell to Anyone" +     layout="topleft" +     left_delta="0" +     name="sell_to_anyone_btn" +     top_pad="4" +     width="150"> +      <button.commit_callback +         function="ClickSellToAnyone" /> +    </button> +    <button +     follows="left|bottom" +     height="20" +     label="Clear Settings" +     label_selected="Clear Settings" +     layout="topleft" +     left_delta="0" +     name="reset_parcel_btn" +     top_pad="4" +     width="150"> +      <button.commit_callback +         function="ClickResetParcel" /> +    </button> +    <button +     follows="left|bottom" +     height="20" +     label="Start Auction" +     label_selected="Start Auction" +     layout="topleft" +     left_pad="4" +     name="start_auction_btn" +     top_delta="0" +     width="150"> +      <button.commit_callback +          function="ClickStartAuction" /> +    </button> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index ed3cc26851..bdcf3648fa 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1115,6 +1115,10 @@                   label="Zoom"                   name="Zoom"                   value="Zoom" /> +                <combo_box.item +                 label="None" +                 name="None" +                 value="None" />              </combo_box>              <check_box               height="23" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 7f9dc0c41f..6b164c660a 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -8102,6 +8102,8 @@ Failed to connect to [VOICE_CHANNEL_NAME], please try again later.  You will now      <unique/>      One or more of your subscribed Voice Morphs has expired.  [[URL] Click here] to renew your subscription. + +If you are a Premium Member, [[PREMIUM_URL] click here] to receive your voice morphing perk.    <tag>fail</tag>    <tag>voice</tag>    </notification> @@ -8115,6 +8117,8 @@ One or more of your subscribed Voice Morphs has expired.      <unique/>  The active Voice Morph has expired, your normal voice settings have been applied.  [[URL] Click here] to renew your subscription. + +If you are a Premium Member, [[PREMIUM_URL] click here] to receive your voice morphing perk.      <tag>fail</tag>      <tag>voice</tag>    </notification> @@ -8128,6 +8132,8 @@ The active Voice Morph has expired, your normal voice settings have been applied      <unique/>      One or more of your Voice Morphs will expire in less than [INTERVAL] days.  [[URL] Click here] to renew your subscription. + +If you are a Premium Member, [[PREMIUM_URL] click here] to receive your voice morphing perk.    <tag>fail</tag>      <tag>voice</tag>    </notification> @@ -8260,6 +8266,11 @@ Failed to save appearance to XML.  Failed to save snapshot to [PATH]: Disk is full. [NEED_MEMORY]KB is required but only [FREE_MEMORY]KB is free.    </notification> +  <notification icon="notifytip.tga" +    name="SnapshotToLocalDirNotExist" type="notifytip"> +Failed to save snapshot to [PATH]: Directory does not exist. +  </notification> +    <notification      icon="notifytip.tga"      name="PresetNotSaved" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 3a34bcbe21..7759d4fdb2 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -12,6 +12,10 @@      name="forgot_password_url">      http://secondlife.com/account/request.php    </panel.string> +  <panel.string +    name="sign_up_url"> +    https://join.secondlife.com/ +  </panel.string>    <layout_stack    follows="left|right|top"    height="172" @@ -149,7 +153,18 @@      label="Select grid"          layout="topleft"      name="server_combo" -    width="149" />	 +    width="149" /> +  <text +    follows="left|top" +    font="SansSerifMedium" +    text_color="EmphasisColor" +    height="16" +    name="sign_up_text" +    left="778" +    bottom_delta="-10" +    width="200"> +    Sign up +  </text>     </layout_panel>    <layout_panel        height="172" diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml index 35b80c56ab..213f9a6b0c 100644 --- a/indra/newview/skins/default/xui/en/panel_login_first.xml +++ b/indra/newview/skins/default/xui/en/panel_login_first.xml @@ -12,6 +12,10 @@      name="forgot_password_url">      http://secondlife.com/account/request.php    </panel.string> +  <panel.string +    name="sign_up_url"> +    https://join.secondlife.com/ +  </panel.string>    <layout_stack      follows="left|right|top|bottom"      width="1024" @@ -168,6 +172,17 @@              width="200">              Forgotten password            </text> +          <text +            follows="left|top" +            font="SansSerifLarge" +            text_color="EmphasisColor" +            height="16" +            name="sign_up_text" +            left="432" +            top="34" +            width="200"> +            Sign up +          </text>          </layout_panel>          <layout_panel            height="100" diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index b84dce222f..efedb9559e 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -292,10 +292,14 @@                   label="Open"                   name="Open"                   value="Open" /> -       <combo_box.item -          label="Zoom" -          name="Zoom" -          value="Zoom" /> +                <combo_box.item +                 label="Zoom" +                 name="Zoom" +                 value="Zoom" /> +                <combo_box.item +                 label="None" +                 name="None" +                 value="None" />              </combo_box>  	 <panel           border="false" diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index 3dd327591e..d1dddf8e7e 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -236,7 +236,7 @@ namespace tut  					  std::string("https://secondlife.com/helpers/"));  		ensure_equals("Agni login page",  					  LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"), -					  std::string("http://viewer-login.agni.lindenlab.com/")); +					  std::string("https://viewer-splash.secondlife.com/"));  		ensure("Agni is a system grid",  			   LLGridManager::getInstance()->isSystemGrid("util.agni.lindenlab.com")); @@ -261,7 +261,7 @@ namespace tut  					  std::string("http://aditi-secondlife.webdev.lindenlab.com/helpers/"));  		ensure_equals("Aditi login page",  					  LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"), -					  std::string("http://viewer-login.agni.lindenlab.com/")); +					  std::string("https://viewer-splash.secondlife.com/"));  		ensure("Aditi is a system grid",  			   LLGridManager::getInstance()->isSystemGrid("util.aditi.lindenlab.com"));  	} @@ -309,7 +309,7 @@ namespace tut  					  std::string("https://secondlife.com/helpers/"));  		ensure_equals("Agni login page",  					  LLGridManager::getInstance()->getLoginPage("util.agni.lindenlab.com"), -					  std::string("http://viewer-login.agni.lindenlab.com/")); +					  std::string("https://viewer-splash.secondlife.com/"));  		ensure("Agni is a system grid",  			   LLGridManager::getInstance()->isSystemGrid("util.agni.lindenlab.com")); @@ -333,7 +333,7 @@ namespace tut  					  std::string("http://aditi-secondlife.webdev.lindenlab.com/helpers/"));  		ensure_equals("Aditi login page",  					  LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"), -					  std::string("http://viewer-login.agni.lindenlab.com/")); +					  std::string("https://viewer-splash.secondlife.com/"));  		ensure("Aditi is a system grid",  			   LLGridManager::getInstance()->isSystemGrid("util.aditi.lindenlab.com")); @@ -422,7 +422,7 @@ namespace tut  					  std::string("https://secondlife.com/helpers/"));  		ensure_equals("getLoginPage",  					  LLGridManager::getInstance()->getLoginPage(), -					  std::string("http://viewer-login.agni.lindenlab.com/")); +					  std::string("https://viewer-splash.secondlife.com/"));  		ensure_equals("update url base for Agni", // relies on agni being the default  					  std::string("https://update.secondlife.com/update"),  					  LLGridManager::getInstance()->getUpdateServiceURL()); | 
