diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5d86a6415..6c29e3fd2 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -105,6 +105,7 @@ set(llcommon_HEADER_FILES CMakeLists.txt aiframetimer.h + airecursive.h aithreadid.h aithreadsafe.h bitpack.h diff --git a/indra/llcommon/airecursive.h b/indra/llcommon/airecursive.h new file mode 100644 index 000000000..0b22535a8 --- /dev/null +++ b/indra/llcommon/airecursive.h @@ -0,0 +1,58 @@ +/** + * @file airecursive.h + * @brief Declaration of AIRecursive. + * + * Copyright (c) 2013, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 05/01/2013 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AI_RECURSIVE +#define AI_RECURSIVE + +// Exception safe class to detect recursive calls. +// +// A unique, static bool must be passed (thread local if the function is +// called by more than one thread). +// +// Example usage: +// +// void f() +// { +// static bool recursive; +// if (recursive) return; +// AIRecursive dummy(flag); +// ... +// } + +class AIRecursive { + private: + bool& mFlag; + + public: + AIRecursive(bool& flag) : mFlag(flag) { mFlag = true; } + ~AIRecursive() { mFlag = false; } +}; + +#endif // AI_RECURSIVE diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index a9f56afff..eff95d83f 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -111,10 +111,10 @@ template struct AIAccess; template struct AISTAccessConst; template struct AISTAccess; +// This helper class is needed because offsetof is only allowed on POD types. template -class AIThreadSafeBits +struct AIThreadSafeBitsPOD { -private: // AIThreadSafe is a wrapper around an instance of T. // Because T might not have a default constructor, it is constructed // 'in place', with placement new, in the memory reserved here. @@ -122,7 +122,11 @@ private: // Make sure that the memory that T will be placed in is properly // aligned by using an array of long's. long mMemory[(sizeof(T) + sizeof(long) - 1) / sizeof(long)]; +}; +template +class AIThreadSafeBits : private AIThreadSafeBitsPOD +{ public: // The wrapped objects are constructed in-place with placement new *outside* // of this object (by AITHREADSAFE macro(s) or derived classes). @@ -130,20 +134,20 @@ public: ~AIThreadSafeBits() { ptr()->~T(); } // Only for use by AITHREADSAFE, see below. - void* memory() const { return const_cast(&mMemory[0]); } + void* memory() const { return const_cast(&AIThreadSafeBitsPOD::mMemory[0]); } // Cast a T* back to AIThreadSafeBits. This is the inverse of memory(). template static AIThreadSafeBits* wrapper_cast(T2* ptr) - { return reinterpret_cast*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); } + { return static_cast*>(reinterpret_cast*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBitsPOD, mMemory[0]))); } template static AIThreadSafeBits const* wrapper_cast(T2 const* ptr) - { return reinterpret_cast const*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); } + { return static_cast const*>(reinterpret_cast const*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBitsPOD, mMemory[0]))); } protected: // Accessors. - T const* ptr() const { return reinterpret_cast(mMemory); } - T* ptr() { return reinterpret_cast(mMemory); } + T const* ptr() const { return reinterpret_cast(AIThreadSafeBitsPOD::mMemory); } + T* ptr() { return reinterpret_cast(AIThreadSafeBitsPOD::mMemory); } }; /** diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 278f781ae..36f64bace 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -124,6 +124,25 @@ const int LL_ERR_PRICE_MISMATCH = -23018; #define llverify(func) do {if (func) {}} while(0) #endif +// This can be used for function parameters that are only used by llassert. +// The ellipsis is needed in case the parameter contains comma's (ie, as part of the type, +// or trailing comma). The first version can be used as first (or only) parameter of a function, +// or as parameter in the middle when adding a trailing comma, while the second version can be +// used as last parameter. +// +// Example usage: +// +// void foo(ASSERT_ONLY(int x)); +// void foo(x, ASSERT_ONLY(int y,) int z); +// void foo(x/*,*/ ASSERT_ONLY_COMMA(int y)); // The optional /*,*/ makes it just a bit better readable. +#ifdef SHOW_ASSERT +#define ASSERT_ONLY(type_param,...) type_param,##__VA_ARGS__ +#define ASSERT_ONLY_COMMA(type_param,...) , type_param,##__VA_ARGS__ +#else +#define ASSERT_ONLY(type_param,...) +#define ASSERT_ONLY_COMMA(type_param,...) +#endif + // handy compile-time assert - enforce those template parameters! #define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */ //XXX: used in two places in llcommon/llskipmap.h diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 3dc3bd3e2..83fac388b 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -290,7 +290,7 @@ enum refresh_t { class CurlSocketInfo { public: - CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj); + CurlSocketInfo(MultiHandle& multi_handle, ASSERT_ONLY(CURL* easy,) curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj); ~CurlSocketInfo(); void set_action(int action); @@ -300,7 +300,6 @@ class CurlSocketInfo private: MultiHandle& mMultiHandle; - CURL const* mEasy; curl_socket_t mSocketFd; int mAction; bool mDead; @@ -669,12 +668,10 @@ class MergeIterator private: PollSet* mReadPollSet; PollSet* mWritePollSet; - int readIndx; - int writeIndx; }; MergeIterator::MergeIterator(PollSet* readPollSet, PollSet* writePollSet) : - mReadPollSet(readPollSet), mWritePollSet(writePollSet), readIndx(0), writeIndx(0) + mReadPollSet(readPollSet), mWritePollSet(writePollSet) { mReadPollSet->reset(); mWritePollSet->reset(); @@ -766,8 +763,8 @@ std::ostream& operator<<(std::ostream& os, DebugFdSet const& s) } #endif -CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, CURL* easy, curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) : - mMultiHandle(multi_handle), mEasy(easy), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj) +CurlSocketInfo::CurlSocketInfo(MultiHandle& multi_handle, ASSERT_ONLY(CURL* easy,) curl_socket_t s, int action, ThreadSafeBufferedCurlEasyRequest* lockobj) : + mMultiHandle(multi_handle), mSocketFd(s), mAction(CURL_POLL_NONE), mDead(false), mEasyRequest(lockobj) { llassert(*AICurlEasyRequest_wat(*mEasyRequest) == easy); mMultiHandle.assign(s, this); diff --git a/indra/llmessage/aihttpheaders.cpp b/indra/llmessage/aihttpheaders.cpp index f019e05ac..dc9c7b5bf 100644 --- a/indra/llmessage/aihttpheaders.cpp +++ b/indra/llmessage/aihttpheaders.cpp @@ -174,7 +174,7 @@ bool AIHTTPReceivedHeaders::equal(std::string const& key1, std::string const& ke } for (std::string::const_iterator i1 = key1.begin(), i2 = key2.begin(); i1 != key1.end(); ++i1, ++i2) { - if ((*i1 ^ *i2) & 0xdf != 0) + if (((*i1 ^ *i2) & 0xdf) != 0) { return false; } diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 25370f739..1cbb52dab 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -57,6 +57,7 @@ #include "lltabcontainer.h" #include "v2math.h" #include "llfasttimer.h" +#include "airecursive.h" const S32 MINIMIZED_WIDTH = 160; const S32 CLOSE_BOX_FROM_TOP = 1; @@ -1988,9 +1989,16 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF return new_rect; } - void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus) { + // Stop recursive call sequence + // LLFloaterView::bringToFront calls + // LLFloater::setFocus calls + // LLFloater::setFrontmost calls this again. + static bool recursive; + if (recursive) { return; } + AIRecursive enter(recursive); + // *TODO: make this respect floater's mAutoFocus value, instead of // using parameter if (child->getHost()) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e947e1cdc..e78617636 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14660,17 +14660,6 @@ This should be as low as possible, but too low may break functionality Value 0 - UseFreezeTime - - Comment - Freeze time when taking snapshots. - Persist - 0 - Type - Boolean - Value - 0 - UseInventoryLinks Comment diff --git a/indra/newview/llfloaterfeed.cpp b/indra/newview/llfloaterfeed.cpp index 7b39b13e3..0fb31467e 100644 --- a/indra/newview/llfloaterfeed.cpp +++ b/indra/newview/llfloaterfeed.cpp @@ -42,6 +42,7 @@ #include "llviewertexture.h" #include "llviewerwindow.h" #include "llwebprofile.h" +#include "lluploaddialog.h" #include @@ -135,8 +136,7 @@ void LLFloaterFeed::draw(void) void LLFloaterFeed::onClickCancel() { - // Return false on cancel, to enable the upload button again. - LLFloaterSnapshot::saveFeedDone(false, mSnapshotIndex); + // Cancel is the same as just closing the floater. close(false); } @@ -152,23 +152,17 @@ void LLFloaterFeed::onClickPost() { static LLCachedControl add_location("SnapshotFeedAddLocation"); const std::string caption = childGetValue("caption").asString(); - LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::saveFeedDone, _1, mPNGImage)); + LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::saveFeedDone, _1, mSnapshotIndex)); + LLFloaterSnapshot::saveStart(mSnapshotIndex); LLWebProfile::uploadImage(mPNGImage, caption, add_location); // give user feedback of the event gViewerWindow->playSnapshotAnimAndSound(); + LLUploadDialog::modalUploadDialog(getString("upload_message")); // don't destroy the window until the upload is done // this way we keep the information in the form setVisible(FALSE); - - // remove any dependency on snapshot floater - // so we outlive it during the upload. - LLFloater* dependee = getDependee(); - if (dependee) - { - dependee->removeDependentFloater(this); - } } else { diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index 132bc5d73..6c05f60a5 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -223,7 +223,6 @@ void LLFloaterPostcard::onClickCancel(void* data) if (data) { LLFloaterPostcard *self = (LLFloaterPostcard *)data; - LLFloaterSnapshot::savePostcardDone(false, self->mSnapshotIndex); self->close(false); } } @@ -410,6 +409,7 @@ void LLFloaterPostcard::sendPostcard() LLVFile::writeFile(mJPEGImage->getData(), mJPEGImage->getDataSize(), gVFS, mAssetID, LLAssetType::AT_IMAGE_JPEG); // upload the image + LLFloaterSnapshot::saveStart(mSnapshotIndex); std::string url = gAgent.getRegion()->getCapability("SendPostcard"); if(!url.empty()) { @@ -436,11 +436,4 @@ void LLFloaterPostcard::sendPostcard() // don't destroy the window until the upload is done // this way we keep the information in the form setVisible(FALSE); - - // also remove any dependency on another floater - // so that we can be sure to outlive it while we - // need to. - LLFloater* dependee = getDependee(); - if (dependee) - dependee->removeDependentFloater(this); } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 6dcf63a74..00701a11b 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -181,12 +181,10 @@ public: LLFloaterFeed* getCaptionAndSaveFeed(); LLFloaterPostcard* savePostcard(); void saveTexture(); - void saveTextureDone(bool success, int index); static void saveTextureDone(LLUUID const& asset_id, void* user_data, S32 status, LLExtStat ext_status); void saveLocal(); - void saveLocalDone(bool success, int index); - void saveFeedDone(bool success, int index); - void savePostcardDone(bool success, int index); + void saveStart(int index); + void saveDone(ESnapshotType type, bool success, int index); void close(LLFloaterSnapshot* view); void doCloseAfterSave(); @@ -265,16 +263,93 @@ private: BOOL mSnapshotActive; LLViewerWindow::ESnapshotType mSnapshotBufferType; - bool mCallbackHappened; - bool mSaveSuccessful; + int mOutstandingCallbacks; + int mSaveFailures; LLFloaterSnapshot* mCloseCalled; - int mSnapshotIndex; + static int sSnapshotIndex; public: static std::set sList; LLFrameTimer mFormattedDelayTimer; }; +///---------------------------------------------------------------------------- +/// Class LLFloaterSnapshot::Impl +///---------------------------------------------------------------------------- +class LLFloaterSnapshot::Impl +{ +public: + Impl() + : mAvatarPauseHandles(), + mLastToolset(NULL) + { + } + ~Impl() + { + //unpause avatars + mAvatarPauseHandles.clear(); + mQualityMouseUpConnection.disconnect(); + } + static void onClickKeep(void* data); + static void onCommitSave(LLUICtrl* ctrl, void* data); + static void onClickNewSnapshot(void* data); + static void onClickFreezeTime(void* data); + static void onClickAutoSnap(LLUICtrl *ctrl, void* data); + static void onClickTemporaryImage(LLUICtrl *ctrl, void* data); + //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); + static void onClickLess(void* data) ; + static void onClickMore(void* data) ; + static void onClickUICheck(LLUICtrl *ctrl, void* data); + static void onClickHUDCheck(LLUICtrl *ctrl, void* data); + static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); + static void onCommitQuality(LLUICtrl* ctrl, void* data); + static void onCommitFeedResolution(LLUICtrl* ctrl, void* data); + static void onCommitPostcardResolution(LLUICtrl* ctrl, void* data); + static void onCommitTextureResolution(LLUICtrl* ctrl, void* data); + static void onCommitLocalResolution(LLUICtrl* ctrl, void* data); + static void onCommitFeedAspect(LLUICtrl* ctrl, void* data); + static void onCommitPostcardAspect(LLUICtrl* ctrl, void* data); + static void onCommitTextureAspect(LLUICtrl* ctrl, void* data); + static void onCommitLocalAspect(LLUICtrl* ctrl, void* data); + static void updateResolution(LLUICtrl* ctrl, void* data, bool update_controls = true); + static void updateAspect(LLUICtrl* ctrl, void* data, bool update_controls = true); + static void onCommitFreezeTime(LLUICtrl* ctrl, void* data); + static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); + static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); + static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); + static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); + static void onCommitCustomAspect(LLUICtrl *ctrl, void* data); + static void onQualityMouseUp(void* data); + + static LLSnapshotLivePreview* getPreviewView(void); + static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls = true); + static void setAspect(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true); + static void updateControls(LLFloaterSnapshot* floater, bool delayed_formatted = false); + static void resetFeedAndPostcardAspect(LLFloaterSnapshot* floater); + static void updateLayout(LLFloaterSnapshot* floater); + static void freezeTime(bool on); + + static LLHandle sPreviewHandle; + +private: + static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); + static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater); + static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); + static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); + +public: + std::vector mAvatarPauseHandles; + + LLToolset* mLastToolset; + boost::signals2::connection mQualityMouseUpConnection; +}; + +//---------------------------------------------------------------------------- +// LLSnapshotLivePreview + +//static +int LLSnapshotLivePreview::sSnapshotIndex; + void LLSnapshotLivePreview::setSnapshotBufferType(LLFloaterSnapshot* floater, LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; @@ -332,8 +407,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : mCameraRot(LLViewerCamera::getInstance()->getQuaternion()), mSnapshotActive(FALSE), mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR), - mCloseCalled(NULL), - mSnapshotIndex(0) + mCloseCalled(NULL) { DoutEntering(dc::notice, "LLSnapshotLivePreview() [" << (void*)this << "]"); setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); @@ -357,10 +431,9 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : LLSnapshotLivePreview::~LLSnapshotLivePreview() { DoutEntering(dc::notice, "~LLSnapshotLivePreview() [" << (void*)this << "]"); - // delete images - mRawSnapshot = NULL; - mFormattedImage = NULL; sList.erase(this); + // Stop callbacks from using this object. + ++sSnapshotIndex; } void LLSnapshotLivePreview::setMaxImageSize(S32 size) @@ -831,7 +904,19 @@ BOOL LLSnapshotLivePreview::onIdle(LLSnapshotLivePreview* previewp) // Grab the raw image and encode it into desired format. Dout(dc::notice, "LLSnapshotLivePreview::onIdle: Actually making a new snapshot!"); - previewp->mSnapshotIndex++; + + // This should never happen, but well. If it's true then that means that the + // snapshot floater is disabled. Incrementing sSnapshotIndex will cause the + // callbacks to be ignored, so we better make sure that the floater is enabled. + if (previewp->mCloseCalled) + { + previewp->mCloseCalled->setEnabled(TRUE); + } + previewp->sSnapshotIndex++; + Dout(dc::notice, "sSnapshotIndex is now " << previewp->sSnapshotIndex << "; mOutstandingCallbacks reset to 0."); + previewp->mOutstandingCallbacks = 0; // There are no outstanding callbacks for THIS snapshot. + previewp->mSaveFailures = 0; // There were no upload failures (or attempts for that matter) for this snapshot. + previewp->mFormattedImage = NULL; previewp->mFormattedUpToDate = false; previewp->mUsedBy = 0; // This snapshot wasn't used yet. @@ -1225,15 +1310,16 @@ LLFloaterFeed* LLSnapshotLivePreview::getCaptionAndSaveFeed() return NULL; } - mCallbackHappened = false; - mSaveSuccessful = false; + ++mOutstandingCallbacks; + mSaveFailures = 0; addUsedBy(SNAPSHOT_FEED); + Dout(dc::notice, "LLSnapshotLivePreview::getCaptionAndSaveFeed: sSnapshotIndex = " << sSnapshotIndex << "; mOutstandingCallbacks = " << mOutstandingCallbacks << "."); if (mFullScreenPreviewTexture.isNull()) { // This should never happen! llwarns << "The snapshot image has not been generated!" << llendl; - saveFeedDone(false, mSnapshotIndex); + saveDone(SNAPSHOT_FEED, false, sSnapshotIndex); return NULL; } @@ -1246,11 +1332,11 @@ LLFloaterFeed* LLSnapshotLivePreview::getCaptionAndSaveFeed() if (!png) { llwarns << "Formatted image not a PNG" << llendl; - saveFeedDone(false, mSnapshotIndex); + saveDone(SNAPSHOT_FEED, false, sSnapshotIndex); return NULL; } - LLFloaterFeed* floater = LLFloaterFeed::showFromSnapshot(png, mFullScreenPreviewTexture, image_scale, mSnapshotIndex); + LLFloaterFeed* floater = LLFloaterFeed::showFromSnapshot(png, mFullScreenPreviewTexture, image_scale, sSnapshotIndex); return floater; } @@ -1262,15 +1348,16 @@ LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() return NULL; } - mCallbackHappened = false; - mSaveSuccessful = false; + ++mOutstandingCallbacks; + mSaveFailures = 0; addUsedBy(SNAPSHOT_POSTCARD); + Dout(dc::notice, "LLSnapshotLivePreview::savePostcard: sSnapshotIndex = " << sSnapshotIndex << "; mOutstandingCallbacks = " << mOutstandingCallbacks << "."); if(mFullScreenPreviewTexture.isNull()) { //this should never happen!! llwarns << "The snapshot image has not been generated!" << llendl ; - savePostcardDone(false, mSnapshotIndex); + saveDone(SNAPSHOT_POSTCARD, false, sSnapshotIndex); return NULL ; } @@ -1285,10 +1372,10 @@ LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() if(!jpg) { llwarns << "Formatted image not a JPEG" << llendl; - savePostcardDone(false, mSnapshotIndex); + saveDone(SNAPSHOT_POSTCARD, false, sSnapshotIndex); return NULL; } - LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mFullScreenPreviewTexture, image_scale, mPosTakenGlobal, mSnapshotIndex); + LLFloaterPostcard* floater = LLFloaterPostcard::showFromSnapshot(jpg, mFullScreenPreviewTexture, image_scale, mPosTakenGlobal, sSnapshotIndex); return floater; } @@ -1307,9 +1394,11 @@ void LLSnapshotLivePreview::saveTexture() return; } - mCallbackHappened = false; - mSaveSuccessful = false; + ++mOutstandingCallbacks; + mSaveFailures = 0; addUsedBy(SNAPSHOT_TEXTURE); + Dout(dc::notice, "LLSnapshotLivePreview::saveTexture: sSnapshotIndex = " << sSnapshotIndex << "; mOutstandingCallbacks = " << mOutstandingCallbacks << "."); + saveStart(sSnapshotIndex); // gen a new uuid for this asset LLTransactionID tid; @@ -1333,7 +1422,7 @@ void LLSnapshotLivePreview::saveTexture() LLFloaterPerms::getGroupPerms(), // that is more permissive than other uploads LLFloaterPerms::getEveryonePerms(), "Snapshot : " + pos_string, - callback, expected_upload_cost, new saveTextureUserData(this, mSnapshotIndex)); + callback, expected_upload_cost, new saveTextureUserData(this, sSnapshotIndex)); gViewerWindow->playSnapshotAnimAndSound(); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); @@ -1346,17 +1435,20 @@ void LLSnapshotLivePreview::saveLocal() return; } - mCallbackHappened = false; - mSaveSuccessful = false; + ++mOutstandingCallbacks; + mSaveFailures = 0; addUsedBy(SNAPSHOT_LOCAL); + Dout(dc::notice, "LLSnapshotLivePreview::saveLocal: sSnapshotIndex = " << sSnapshotIndex << "; mOutstandingCallbacks = " << mOutstandingCallbacks << "."); + saveStart(sSnapshotIndex); - gViewerWindow->saveImageNumbered(mFormattedImage, mSnapshotIndex); // This calls saveLocalDone() immediately, or later. + gViewerWindow->saveImageNumbered(mFormattedImage, sSnapshotIndex); // This calls saveDone() immediately, or later. } void LLSnapshotLivePreview::close(LLFloaterSnapshot* view) { + DoutEntering(dc::notice, "LLSnapshotLivePreview::close(" << (void*)view << ") [mOutstandingCallbacks = " << mOutstandingCallbacks << "]"); mCloseCalled = view; - if (mCallbackHappened) + if (!mOutstandingCallbacks) { doCloseAfterSave(); } @@ -1366,79 +1458,51 @@ void LLSnapshotLivePreview::close(LLFloaterSnapshot* view) } } -void LLSnapshotLivePreview::saveFeedDone(bool success, int index) +void LLSnapshotLivePreview::saveStart(int index) { - if (mSnapshotIndex != index) + if (index == sSnapshotIndex && gSavedSettings.getBOOL("CloseSnapshotOnKeep") && gSavedSettings.getBOOL("FreezeTime")) { - // The snapshot was already replaced, so this callback has nothing to do with us anymore. - if (!success) - { - llwarns << "Permanent failure to upload snapshot" << llendl; - } - return; - } + // Turn off Freeze Time if we're going to close the floater + // anyway at the *start* of an upload/save attempt. + // + // The disadvantage is that if the upload fails then we lost the Frozen Scene. + // The user can still retry to upload or save the snapshot using the same size + // (or smaller) to disk. + // + // The advantage is that if for some reason the upload takes a long time, then + // the user can immediately continue with using the viewer instead of ending + // up with a frozen (haha) interface. - mCallbackHappened = true; - mSaveSuccessful = success; - if (!success) - { - // Enable Upload button. - delUsedBy(SNAPSHOT_FEED); - LLFloaterSnapshot::updateControls(); - } - if (mCloseCalled) - { - doCloseAfterSave(); + LLFloaterSnapshot::Impl::freezeTime(false); } } -void LLSnapshotLivePreview::savePostcardDone(bool success, int index) +void LLSnapshotLivePreview::saveDone(ESnapshotType type, bool success, int index) { - if (mSnapshotIndex != index) + DoutEntering(dc::notice, "LLSnapshotLivePreview::saveDone(" << type << ", " << success << ", " << index << ")"); + + if (sSnapshotIndex != index) { + Dout(dc::notice, "sSnapshotIndex (" << sSnapshotIndex << ") != index (" << index << ")"); + // The snapshot was already replaced, so this callback has nothing to do with us anymore. if (!success) { - llwarns << "Permanent failure to email snapshot" << llendl; + llwarns << "Permanent failure to upload or save snapshot" << llendl; } return; } - mCallbackHappened = true; - mSaveSuccessful = success; + --mOutstandingCallbacks; + Dout(dc::notice, "sSnapshotIndex = " << sSnapshotIndex << "; mOutstandingCallbacks = " << mOutstandingCallbacks << "."); if (!success) { + ++mSaveFailures; // Enable Upload button. - delUsedBy(SNAPSHOT_POSTCARD); + delUsedBy(type); LLFloaterSnapshot::updateControls(); } - if (mCloseCalled) - { - doCloseAfterSave(); - } -} - -void LLSnapshotLivePreview::saveTextureDone(bool success, int index) -{ - if (mSnapshotIndex != index) - { - // The snapshot was already replaced, so this callback has nothing to do with us anymore. - if (!success) - { - llwarns << "Permanent failure to upload texture" << llendl; - } - return; - } - - mCallbackHappened = true; - mSaveSuccessful = success; - if (!success) - { - // Enable Upload button. - delUsedBy(LLSnapshotLivePreview::SNAPSHOT_TEXTURE); - LLFloaterSnapshot::updateControls(); - } - if (mCloseCalled) + if (!mOutstandingCallbacks) { doCloseAfterSave(); } @@ -1455,39 +1519,17 @@ void LLSnapshotLivePreview::saveTextureDone(LLUUID const& asset_id, void* user_d LLNotificationsUtil::add("UploadSnapshotFail", args); } saveTextureUserData* data = (saveTextureUserData*)user_data; - data->mSelf->saveTextureDone(success, data->mSnapshotIndex); + data->mSelf->saveDone(SNAPSHOT_TEXTURE, success, data->mSnapshotIndex); delete data; } -void LLSnapshotLivePreview::saveLocalDone(bool success, int index) -{ - if (mSnapshotIndex != index) - { - // The snapshot was already replaced, so this callback has nothing to do with us anymore. - if (!success) - { - llwarns << "Permanent failure to save snapshot." << llendl; - } - return; - } - - mCallbackHappened = true; - mSaveSuccessful = success; - if (!success) - { - // Enable Save button. - delUsedBy(SNAPSHOT_LOCAL); - LLFloaterSnapshot::updateControls(); - } - if (mCloseCalled) - { - doCloseAfterSave(); - } -} - void LLSnapshotLivePreview::doCloseAfterSave() { - if (mSaveSuccessful) + if (!mCloseCalled) + { + return; + } + if (!mSaveFailures && gSavedSettings.getBOOL("CloseSnapshotOnKeep")) { // Relinquish image memory. mFormattedImage = NULL; @@ -1503,82 +1545,14 @@ void LLSnapshotLivePreview::doCloseAfterSave() } } -///---------------------------------------------------------------------------- -/// Class LLFloaterSnapshot::Impl -///---------------------------------------------------------------------------- - -class LLFloaterSnapshot::Impl -{ -public: - Impl() - : mAvatarPauseHandles(), - mLastToolset(NULL) - { - } - ~Impl() - { - //unpause avatars - mAvatarPauseHandles.clear(); - mQualityMouseUpConnection.disconnect(); - } - static void onClickKeep(void* data); - static void onCommitSave(LLUICtrl* ctrl, void* data); - static void onClickNewSnapshot(void* data); - static void onClickFreezeTime(void* data); - static void onClickAutoSnap(LLUICtrl *ctrl, void* data); - static void onClickTemporaryImage(LLUICtrl *ctrl, void* data); - //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); - static void onClickLess(void* data) ; - static void onClickMore(void* data) ; - static void onClickUICheck(LLUICtrl *ctrl, void* data); - static void onClickHUDCheck(LLUICtrl *ctrl, void* data); - static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); - static void onCommitQuality(LLUICtrl* ctrl, void* data); - static void onCommitFeedResolution(LLUICtrl* ctrl, void* data); - static void onCommitPostcardResolution(LLUICtrl* ctrl, void* data); - static void onCommitTextureResolution(LLUICtrl* ctrl, void* data); - static void onCommitLocalResolution(LLUICtrl* ctrl, void* data); - static void onCommitFeedAspect(LLUICtrl* ctrl, void* data); - static void onCommitPostcardAspect(LLUICtrl* ctrl, void* data); - static void onCommitTextureAspect(LLUICtrl* ctrl, void* data); - static void onCommitLocalAspect(LLUICtrl* ctrl, void* data); - static void updateResolution(LLUICtrl* ctrl, void* data, bool update_controls = true); - static void updateAspect(LLUICtrl* ctrl, void* data, bool update_controls = true); - static void onCommitFreezeTime(LLUICtrl* ctrl, void* data); - static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); - static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); - static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); - static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); - static void onCommitCustomAspect(LLUICtrl *ctrl, void* data); - static void onQualityMouseUp(void* data); - - static LLSnapshotLivePreview* getPreviewView(LLFloaterSnapshot *floater); - static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname, bool visible, bool update_controls = true); - static void setAspect(LLFloaterSnapshot* floater, const std::string& comboname, bool update_controls = true); - static void updateControls(LLFloaterSnapshot* floater, bool delayed_formatted = false); - static void resetFeedAndPostcardAspect(LLFloaterSnapshot* floater); - static void updateLayout(LLFloaterSnapshot* floater); - - static LLHandle sPreviewHandle; - -private: - static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); - static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater); - static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); - static void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); - -public: - std::vector mAvatarPauseHandles; - - LLToolset* mLastToolset; - boost::signals2::connection mQualityMouseUpConnection; -}; +//---------------------------------------------------------------------------- +// LLFloaterSnapshot::Impl // static LLHandle LLFloaterSnapshot::Impl::sPreviewHandle; // static -LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot *floater) +LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(void) { LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)sPreviewHandle.get(); return previewp; @@ -1646,11 +1620,8 @@ void LLFloaterSnapshot::Impl::resetFeedAndPostcardAspect(LLFloaterSnapshot* floa //static void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) { - LLSnapshotLivePreview* previewp = getPreviewView(floaterp); - - S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong() ; - - if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution + S32 delta_height = 0; + if (!gSavedSettings.getBOOL("AdvanceSnapshot")) { floaterp->getChild("feed_size_combo")->setCurrentByIndex(2); // 500x375 gSavedSettings.setS32("SnapshotFeedLastResolution", 2); @@ -1671,15 +1642,20 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) gSavedSettings.setS32("SnapshotLocalLastAspect", 0); updateControls(floaterp); - } - if (gSavedSettings.getBOOL("UseFreezeTime")) + delta_height = floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong(); + } + floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); +} + +//static +void LLFloaterSnapshot::Impl::freezeTime(bool on) +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + if (on) { // stop all mouse events at fullscreen preview layer - floaterp->getParent()->setMouseOpaque(TRUE); - - // shrink to smaller layout - floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); + sInstance->getParent()->setMouseOpaque(TRUE); // can see and interact with fullscreen preview now if (previewp) @@ -1706,8 +1682,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) } else // turning off freeze frame mode { - floaterp->getParent()->setMouseOpaque(FALSE); - floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); + sInstance->getParent()->setMouseOpaque(FALSE); if (previewp) { previewp->setVisible(FALSE); @@ -1781,7 +1756,7 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater, bool de floater->childSetVisible("local_size_combo", FALSE); floater->childSetVisible("local_aspect_combo", FALSE); - LLSnapshotLivePreview* previewp = getPreviewView(floater); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { previewp->setSnapshotType(shot_type); @@ -1910,8 +1885,7 @@ void LLFloaterSnapshot::Impl::onCommitFeedResolution(LLUICtrl* ctrl, void* data) { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotFeedLastResolution", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_FEED); @@ -1924,8 +1898,7 @@ void LLFloaterSnapshot::Impl::onCommitPostcardResolution(LLUICtrl* ctrl, void* d { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotPostcardLastResolution", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_POSTCARD); @@ -1938,8 +1911,7 @@ void LLFloaterSnapshot::Impl::onCommitTextureResolution(LLUICtrl* ctrl, void* da { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotTextureLastResolution", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_TEXTURE); @@ -1952,8 +1924,7 @@ void LLFloaterSnapshot::Impl::onCommitLocalResolution(LLUICtrl* ctrl, void* data { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotLocalLastResolution", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_LOCAL); @@ -1966,8 +1937,7 @@ void LLFloaterSnapshot::Impl::onCommitFeedAspect(LLUICtrl* ctrl, void* data) { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotFeedLastAspect", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_FEED); @@ -1980,8 +1950,7 @@ void LLFloaterSnapshot::Impl::onCommitPostcardAspect(LLUICtrl* ctrl, void* data) { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotPostcardLastAspect", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_POSTCARD); @@ -1994,8 +1963,7 @@ void LLFloaterSnapshot::Impl::onCommitTextureAspect(LLUICtrl* ctrl, void* data) { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotTextureLastAspect", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_TEXTURE); @@ -2008,8 +1976,7 @@ void LLFloaterSnapshot::Impl::onCommitLocalAspect(LLUICtrl* ctrl, void* data) { LLComboBox* combobox = (LLComboBox*)ctrl; gSavedSettings.setS32("SnapshotLocalLastAspect", combobox->getCurrentIndex()); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp && previewp->isUsed()) { previewp->addManualOverride(LLSnapshotLivePreview::SNAPSHOT_LOCAL); @@ -2027,67 +1994,79 @@ void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) onClickKeep(data); } +//static +void LLFloaterSnapshot::saveStart(int index) +{ + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(); + if (previewp) + { + previewp->saveStart(index); + } +} + // Called from LLViewerWindow::saveImageNumbered, LLViewerWindow::saveImageNumbered_continued1 and LLViewerWindow::saveImageNumbered_continued2. //static void LLFloaterSnapshot::saveLocalDone(bool success, int index) { - LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(); if (previewp) { - previewp->saveLocalDone(success, index); + previewp->saveDone(LLSnapshotLivePreview::SNAPSHOT_LOCAL, success, index); } } //static void LLFloaterSnapshot::saveFeedDone(bool success, int index) { - LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(); if (previewp) { - previewp->saveFeedDone(success, index); + previewp->saveDone(LLSnapshotLivePreview::SNAPSHOT_FEED, success, index); } } //static void LLFloaterSnapshot::savePostcardDone(bool success, int index) { - LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(sInstance); + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(); if (previewp) { - previewp->savePostcardDone(success, index); + previewp->saveDone(LLSnapshotLivePreview::SNAPSHOT_POSTCARD, success, index); } } // static void LLFloaterSnapshot::Impl::onClickKeep(void* data) { - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLFloaterSnapshot* floater = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_FEED) { LLFloaterFeed* floater = previewp->getCaptionAndSaveFeed(); - // If still in snapshot mode, put feed floater in snapshot floaterview - // and link it to snapshot floater. - if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + if (floater) { - gFloaterView->removeChild(floater); + // Make sure that the new floater is in front of gSnapshotFloaterView. + // So that the structure is: + // "root" --> + // "Snapshot Floater View" --> + // "floater_snapshot_profile" + // "Snapshot" floater + // ["snapshot_live_preview"] + // and "floater_snapshot_profile" (floater) is a child of "Snapshot Floater View" (gSnapshotFloaterView), + // and therefore in front of "snapshot_live_preview", if it exists. gSnapshotFloaterView->addChild(floater); - view->addDependentFloater(floater, FALSE); } } else if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) { LLFloaterPostcard* floater = previewp->savePostcard(); - // if still in snapshot mode, put postcard floater in snapshot floaterview - // and link it to snapshot floater - if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + if (floater) { - gFloaterView->removeChild(floater); + // Same as above, but for the "Postcard" floater. gSnapshotFloaterView->addChild(floater); - view->addDependentFloater(floater, FALSE); } } else if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) @@ -2101,37 +2080,34 @@ void LLFloaterSnapshot::Impl::onClickKeep(void* data) if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) { - previewp->close(view); + previewp->close(floater); } else { checkAutoSnapshot(previewp); } - updateControls(view); + updateControls(floater); } } // static void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data) { - LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); - if (previewp && view) + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) { previewp->updateSnapshot(TRUE); } } // static -void LLFloaterSnapshot::Impl::onClickFreezeTime(void* data) +void LLFloaterSnapshot::Impl::onClickFreezeTime(void*) { - LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; - LLSnapshotLivePreview* previewp = getPreviewView(view); - if (previewp && view) + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) { - gSavedSettings.setBOOL("UseFreezeTime", TRUE); - updateLayout(view); + freezeTime(true); } } @@ -2141,11 +2117,11 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; gSavedSettings.setBOOL( "AutoSnapshot", check->get() ); - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) + LLFloaterSnapshot* floater = (LLFloaterSnapshot*)data; + if (floater) { - checkAutoSnapshot(getPreviewView(view)); - updateControls(view); + checkAutoSnapshot(getPreviewView()); + updateControls(floater); } } @@ -2170,9 +2146,9 @@ void LLFloaterSnapshot::Impl::onClickMore(void* data) view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong()); updateControls(view) ; updateLayout(view) ; - if(getPreviewView(view)) + if (getPreviewView()) { - getPreviewView(view)->setThumbnailImageSize() ; + getPreviewView()->setThumbnailImageSize() ; } } } @@ -2187,9 +2163,9 @@ void LLFloaterSnapshot::Impl::onClickLess(void* data) view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort()); updateControls(view) ; updateLayout(view) ; - if(getPreviewView(view)) + if (getPreviewView()) { - getPreviewView(view)->setThumbnailImageSize() ; + getPreviewView()->setThumbnailImageSize(); } } } @@ -2203,7 +2179,7 @@ void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - checkAutoSnapshot(getPreviewView(view), TRUE); + checkAutoSnapshot(getPreviewView(), TRUE); updateControls(view); } } @@ -2217,7 +2193,7 @@ void LLFloaterSnapshot::Impl::onClickHUDCheck(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - checkAutoSnapshot(getPreviewView(view), TRUE); + checkAutoSnapshot(getPreviewView(), TRUE); updateControls(view); } } @@ -2236,15 +2212,11 @@ void LLFloaterSnapshot::Impl::onCommitQuality(LLUICtrl* ctrl, void* data) LLSliderCtrl* slider = (LLSliderCtrl*)ctrl; S32 quality_val = llfloor((F32)slider->getValue().asReal()); - LLFloaterSnapshot* view = (LLFloaterSnapshot *)data; - if (view) + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) { - LLSnapshotLivePreview* previewp = getPreviewView(view); - if (previewp) - { - previewp->setSnapshotQuality(quality_val); - checkAutoSnapshot(previewp, TRUE); - } + previewp->setSnapshotQuality(quality_val); + checkAutoSnapshot(previewp, TRUE); } } @@ -2317,7 +2289,7 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, bool S32 new_width = 0; S32 new_height = 0; F32 new_aspect = 0; - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); #if 0 // Broken -- not doing this for now. LLSnapshotLivePreview::ESnapshotType shot_type = (LLSnapshotLivePreview::ESnapshotType)gSavedSettings.getS32("LastSnapshotType"); @@ -2595,7 +2567,7 @@ void LLFloaterSnapshot::Impl::updateAspect(LLUICtrl* ctrl, void* data, bool upda return; } - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); view->getChild("feed_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFeedLastAspect")); view->getChild("postcard_aspect_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastAspect")); @@ -2742,7 +2714,7 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat S32 w = llround(view->childGetValue("snapshot_width").asReal(), 1.0); S32 h = llround(view->childGetValue("snapshot_height").asReal(), 1.0); - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { S32 curw,curh; @@ -2799,7 +2771,7 @@ void LLFloaterSnapshot::Impl::onCommitCustomAspect(LLUICtrl *ctrl, void* data) { F32 a = view->childGetValue("aspect_ratio").asReal(); - LLSnapshotLivePreview* previewp = getPreviewView(view); + LLSnapshotLivePreview* previewp = getPreviewView(); if (previewp) { F32 cura = previewp->getAspect(); @@ -2912,18 +2884,21 @@ BOOL LLFloaterSnapshot::postBuild() // create preview window LLRect full_screen_rect = sInstance->getRootView()->getRect(); LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(full_screen_rect); - sInstance->getRootView()->removeChild(gSnapshotFloaterView); - // make sure preview is below snapshot floater - sInstance->getRootView()->addChild(previewp); - sInstance->getRootView()->addChild(gSnapshotFloaterView); + // Make sure preview is below snapshot floater. + // "root" --> (first child is hit first): + // "Snapshot Floater View" + // "snapshot_live_preview" + // ... + sInstance->getRootView()->addChild(previewp); // Note that addChild is actually 'moveChild'. + sInstance->getRootView()->addChild(gSnapshotFloaterView); // The last added child becomes the first child; the one up front. - gSavedSettings.setBOOL("UseFreezeTime", gSavedSettings.getBOOL("SnapshotOpenFreezeTime")); gSavedSettings.setBOOL("TemporaryUpload",FALSE); childSetValue("temp_check",FALSE); Impl::sPreviewHandle = previewp->getHandle(); impl.updateControls(this); + impl.freezeTime(gSavedSettings.getBOOL("SnapshotOpenFreezeTime")); return TRUE; } @@ -2936,7 +2911,7 @@ LLRect LLFloaterSnapshot::getThumbnailAreaRect() void LLFloaterSnapshot::draw() { - LLSnapshotLivePreview* previewp = impl.getPreviewView(this); + LLSnapshotLivePreview* previewp = impl.getPreviewView(); if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock())) { @@ -2977,8 +2952,7 @@ void LLFloaterSnapshot::onClose(bool app_quitting) // Set invisible so it doesn't eat tooltips. JC gSnapshotFloaterView->setVisible(FALSE); gSavedSettings.setBOOL("SnapshotBtnState", FALSE); - gSavedSettings.setBOOL("UseFreezeTime", FALSE); - impl.updateLayout(this); + impl.freezeTime(false); destroy(); } @@ -2988,9 +2962,17 @@ void LLFloaterSnapshot::show(void*) if (!sInstance) { sInstance = new LLFloaterSnapshot(); - LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_snapshot.xml", NULL, FALSE); - //move snapshot floater to special purpose snapshotfloaterview - gFloaterView->removeChild(sInstance); + LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_snapshot.xml", NULL, FALSE); // "Snapshot" floater. + // Make snapshot floater a child of (full screen) gSnapshotFloaterView. + // So that the structure is: + // "root" --> + // "Snapshot Floater View" --> + // "Snapshot" floater + // ["floater_snapshot_profile"] + // ["Postcard"] + // ["snapshot_live_preview"] + // and the "Snapshot" floater (sInstance) is a child of "Snapshot Floater View" (gSnapshotFloaterView), + // and therefore in front of "snapshot_live_preview", if it exists. gSnapshotFloaterView->addChild(sInstance); sInstance->impl.updateLayout(sInstance); @@ -3047,28 +3029,26 @@ BOOL LLFloaterSnapshot::handleKeyHere(KEY key, MASK mask) // However, if we're showing the fullscreen frozen preview, drop out of it; // otherwise leave Freeze Time (so the next ESC press DOES defocus // the floater and only the fourth will finally reset the cam). - LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this); + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(); if (previewp && previewp->getShowFreezeFrameSnapshot()) { previewp->showFreezeFrameSnapshot(false); } else { - gSavedSettings.setBOOL("UseFreezeTime", FALSE); - impl.updateLayout(this); + impl.freezeTime(false); } return TRUE; } else if (key == 'Q' && mask == MASK_CONTROL) { // Allow users to quit with ctrl-Q. - LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(this); + LLSnapshotLivePreview* previewp = LLFloaterSnapshot::Impl::getPreviewView(); if (previewp && previewp->getShowFreezeFrameSnapshot()) { previewp->showFreezeFrameSnapshot(false); } - gSavedSettings.setBOOL("UseFreezeTime", FALSE); - impl.updateLayout(this); + impl.freezeTime(false); gFocusMgr.removeKeyboardFocusWithoutCallback(gFocusMgr.getKeyboardFocus()); return FALSE; } diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index a2ad6f385..3b4f79ced 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -72,6 +72,7 @@ public: static S32 getUIWinHeightShort() {return sUIWinHeightShort ;} static S32 getUIWinWidth() {return sUIWinWidth ;} + static void saveStart(int index); static void saveLocalDone(bool success, int index); static void saveFeedDone(bool success, int index); static void savePostcardDone(bool success, int index); @@ -79,8 +80,9 @@ public: static void updateControls(); static void resetFeedAndPostcardAspect(); -private: class Impl; + +private: Impl& impl; static LLFloaterSnapshot* sInstance; diff --git a/indra/newview/skins/default/xui/en-us/floater_snapshot_feed.xml b/indra/newview/skins/default/xui/en-us/floater_snapshot_feed.xml index 6322c447d..50bc3ae12 100644 --- a/indra/newview/skins/default/xui/en-us/floater_snapshot_feed.xml +++ b/indra/newview/skins/default/xui/en-us/floater_snapshot_feed.xml @@ -46,4 +46,7 @@ name="post_btn" bottom_delta="0" width="100"/> + + "Uploading..." +