diff options
Diffstat (limited to 'indra')
57 files changed, 1699 insertions, 460 deletions
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()); |