diff options
371 files changed, 5339 insertions, 2194 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index aaf884f0e9..e1ea531caf 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -204,6 +204,14 @@ Ansariel Hiller MAINT-6636 MAINT-6744 MAINT-6752 + MAINT-6773 + MAINT-6906 + MAINT-6911 + STORM-2140 + MAINT-6912 + MAINT-6929 + STORM-2141 + MAINT-6953 Aralara Rajal Arare Chantilly CHUIBUG-191 @@ -1253,6 +1261,7 @@ Shyotl Kuhr MAINT-1138 MAINT-2334 MAINT-6913 + STORM-2143 Siana Gearz STORM-960 STORM-1088 @@ -1287,6 +1296,7 @@ Sovereign Engineer STORM-2107 MAINT-6218 MAINT-6913 + STORM-2143 SpacedOut Frye VWR-34 VWR-45 diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 3d27b4a5b5..f4dba16a94 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -42,6 +42,7 @@ #include "lldiriterator.h" #include "v4coloru.h" #include "llsdserialize.h" +#include "llcleanup.h" // system libraries #include <iostream> @@ -634,7 +635,7 @@ int main(int argc, char** argv) } // Cleanup and exit - LLImage::cleanupClass(); + SUBSYSTEM_CLEANUP(LLImage); if (fast_timer_log_thread) { fast_timer_log_thread->shutdown(); diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 8a1d2c4707..d6223bb4d2 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -127,8 +127,7 @@ class LLAvatarAppearanceDictionary : public LLSingleton<LLAvatarAppearanceDictio //-------------------------------------------------------------------- // Constructors and Destructors //-------------------------------------------------------------------- -public: - LLAvatarAppearanceDictionary(); + LLSINGLETON(LLAvatarAppearanceDictionary); virtual ~LLAvatarAppearanceDictionary(); private: void createAssociations(); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 959d6e499a..9318b23fd1 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -293,9 +293,9 @@ protected: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLTexLayerStaticImageList : public LLSingleton<LLTexLayerStaticImageList> { -public: - LLTexLayerStaticImageList(); + LLSINGLETON(LLTexLayerStaticImageList); ~LLTexLayerStaticImageList(); +public: LLGLTexture* getTexture(const std::string& file_name, BOOL is_mask); LLImageTGA* getImageTGA(const std::string& file_name); void deleteCachedImages(); diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp index 87109a5906..207e0c4011 100644 --- a/indra/llappearance/llwearabletype.cpp +++ b/indra/llappearance/llwearabletype.cpp @@ -71,8 +71,7 @@ struct WearableEntry : public LLDictionaryEntry class LLWearableDictionary : public LLSingleton<LLWearableDictionary>, public LLDictionary<LLWearableType::EType, WearableEntry> { -public: - LLWearableDictionary(); + LLSINGLETON(LLWearableDictionary); }; LLWearableDictionary::LLWearableDictionary() diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5bce2b8809..3493f80556 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -41,8 +41,10 @@ set(llcommon_SOURCE_FILES llbitpack.cpp llcallbacklist.cpp llcallstack.cpp + llcleanup.cpp llcommon.cpp llcommonutils.cpp + llcoro_get_id.cpp llcoros.cpp llcrc.cpp llcriticaldamp.cpp @@ -67,7 +69,9 @@ set(llcommon_SOURCE_FILES llformat.cpp llframetimer.cpp llheartbeat.cpp + llheteromap.cpp llinitparam.cpp + llinitdestroyclass.cpp llinstancetracker.cpp llleap.cpp llleaplistener.cpp @@ -138,8 +142,10 @@ set(llcommon_HEADER_FILES llboost.h llcallbacklist.h llcallstack.h + llcleanup.h llcommon.h llcommonutils.h + llcoro_get_id.h llcoros.h llcrc.h llcriticaldamp.h @@ -171,7 +177,9 @@ set(llcommon_HEADER_FILES llhandle.h llhash.h llheartbeat.h + llheteromap.h llindexedvector.h + llinitdestroyclass.h llinitparam.h llinstancetracker.h llkeythrottle.h @@ -188,6 +196,7 @@ set(llcommon_HEADER_FILES llmortician.h llnametable.h llpointer.h + llpounceable.h llpredicate.h llpreprocessor.h llpriqueuemap.h @@ -333,6 +342,8 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llpounceable "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llheteromap "" "${test_libs}") ## llexception_test.cpp isn't a regression test, and doesn't need to be run ## every build. It's to help a developer make implementation choices about diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index eb0699ad41..2c76f29020 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -48,6 +48,7 @@ #include "lleventtimer.h" #include "google_breakpad/exception_handler.h" #include "stringize.h" +#include "llcleanup.h" // // Signal handling @@ -177,7 +178,7 @@ LLApp::~LLApp() if(mExceptionHandler != 0) delete mExceptionHandler; - LLCommon::cleanupClass(); + SUBSYSTEM_CLEANUP(LLCommon); } // static diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5ae2df3994..4304db36be 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -63,8 +63,7 @@ struct AssetEntry : public LLDictionaryEntry class LLAssetDictionary : public LLSingleton<LLAssetDictionary>, public LLDictionary<LLAssetType::EType, AssetEntry> { -public: - LLAssetDictionary(); + LLSINGLETON(LLAssetDictionary); }; LLAssetDictionary::LLAssetDictionary() diff --git a/indra/llcommon/llcleanup.cpp b/indra/llcommon/llcleanup.cpp new file mode 100644 index 0000000000..c5283507bf --- /dev/null +++ b/indra/llcommon/llcleanup.cpp @@ -0,0 +1,29 @@ +/** + * @file llcleanup.cpp + * @author Nat Goodspeed + * @date 2016-08-30 + * @brief Implementation for llcleanup. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llcleanup.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" +#include "llerrorcontrol.h" + +void log_subsystem_cleanup(const char* file, int line, const char* function, + const char* classname) +{ + LL_INFOS("Cleanup") << LLError::abbreviateFile(file) << "(" << line << "): " + << "calling " << classname << "::cleanupClass() in " + << function << LL_ENDL; +} diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h new file mode 100644 index 0000000000..a319171b5f --- /dev/null +++ b/indra/llcommon/llcleanup.h @@ -0,0 +1,33 @@ +/** + * @file llcleanup.h + * @author Nat Goodspeed + * @date 2015-05-20 + * @brief Mechanism for cleaning up subsystem resources + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCLEANUP_H) +#define LL_LLCLEANUP_H + +#include <boost/current_function.hpp> + +// Instead of directly calling SomeClass::cleanupClass(), use +// SUBSYSTEM_CLEANUP(SomeClass); +// This logs the call as well as performing it. That gives us a baseline +// subsystem shutdown order against which to compare subsequent dynamic +// shutdown schemes. +#define SUBSYSTEM_CLEANUP(CLASSNAME) \ + do { \ + log_subsystem_cleanup(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, #CLASSNAME); \ + CLASSNAME::cleanupClass(); \ + } while (0) +// Use ancient do { ... } while (0) macro trick to permit a block of +// statements with the same syntax as a single statement. + +void log_subsystem_cleanup(const char* file, int line, const char* function, + const char* classname); + +#endif /* ! defined(LL_LLCLEANUP_H) */ diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 19642b0982..439ff4e628 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -31,6 +31,7 @@ #include "llthread.h" #include "lltrace.h" #include "lltracethreadrecorder.h" +#include "llcleanup.h" //static BOOL LLCommon::sAprInitialized = FALSE; @@ -63,11 +64,11 @@ void LLCommon::cleanupClass() sMasterThreadRecorder = NULL; LLTrace::set_master_thread_recorder(NULL); LLThreadSafeRefCount::cleanupThreadSafeRefCount(); - LLTimer::cleanupClass(); + SUBSYSTEM_CLEANUP(LLTimer); if (sAprInitialized) { ll_cleanup_apr(); sAprInitialized = FALSE; } - LLMemory::cleanupClass(); + SUBSYSTEM_CLEANUP(LLMemory); } diff --git a/indra/llcommon/llcoro_get_id.cpp b/indra/llcommon/llcoro_get_id.cpp new file mode 100644 index 0000000000..24ed1fe0c9 --- /dev/null +++ b/indra/llcommon/llcoro_get_id.cpp @@ -0,0 +1,32 @@ +/** + * @file llcoro_get_id.cpp + * @author Nat Goodspeed + * @date 2016-09-03 + * @brief Implementation for llcoro_get_id. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llcoro_get_id.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llcoros.h" + +namespace llcoro +{ + +id get_id() +{ + // An instance of Current can convert to LLCoros::CoroData*, which can + // implicitly convert to void*, which is an llcoro::id. + return LLCoros::Current(); +} + +} // llcoro diff --git a/indra/llcommon/llcoro_get_id.h b/indra/llcommon/llcoro_get_id.h new file mode 100644 index 0000000000..4c1dca6f19 --- /dev/null +++ b/indra/llcommon/llcoro_get_id.h @@ -0,0 +1,30 @@ +/** + * @file llcoro_get_id.h + * @author Nat Goodspeed + * @date 2016-09-03 + * @brief Supplement the functionality in llcoro.h. + * + * This is broken out as a separate header file to resolve + * circularity: LLCoros isa LLSingleton, yet LLSingleton machinery + * requires llcoro::get_id(). + * + * Be very suspicious of anyone else #including this header. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCORO_GET_ID_H) +#define LL_LLCORO_GET_ID_H + +namespace llcoro +{ + +/// Get an opaque, distinct token for the running coroutine (or main). +typedef void* id; +id get_id(); + +} // llcoro + +#endif /* ! defined(LL_LLCORO_GET_ID_H) */ diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 8e516d8beb..3ffce4810a 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -40,32 +40,79 @@ #include "stringize.h" #include "llexception.h" -// do nothing, when we need nothing done +namespace { +void no_op() {} +} // anonymous namespace + +// Do nothing, when we need nothing done. This is a static member of LLCoros +// because CoroData is a private nested class. void LLCoros::no_cleanup(CoroData*) {} // CoroData for the currently-running coroutine. Use a thread_specific_ptr // because each thread potentially has its own distinct pool of coroutines. -// This thread_specific_ptr does NOT own the CoroData object! That's owned by -// LLCoros::mCoros. It merely identifies it. For this reason we instantiate -// it with a no-op cleanup function. -boost::thread_specific_ptr<LLCoros::CoroData> -LLCoros::sCurrentCoro(LLCoros::no_cleanup); +LLCoros::Current::Current() +{ + // Use a function-static instance so this thread_specific_ptr is + // instantiated on demand. Since we happen to know it's consumed by + // LLSingleton, this is likely to happen before the runtime has finished + // initializing module-static data. For the same reason, we can't package + // this pointer in an LLSingleton. + + // This thread_specific_ptr does NOT own the CoroData object! That's owned + // by LLCoros::mCoros. It merely identifies it. For this reason we + // instantiate it with a no-op cleanup function. + static boost::thread_specific_ptr<LLCoros::CoroData> sCurrent(LLCoros::no_cleanup); + + // If this is the first time we're accessing sCurrent for the running + // thread, its get() will be NULL. This could be a problem, in that + // llcoro::get_id() would return the same (NULL) token value for the "main + // coroutine" in every thread, whereas what we really want is a distinct + // value for every distinct stack in the process. So if get() is NULL, + // give it a heap CoroData: this ensures that llcoro::get_id() will return + // distinct values. + // This tactic is "leaky": sCurrent explicitly does not destroy any + // CoroData to which it points, and we do NOT enter these "main coroutine" + // CoroData instances in the LLCoros::mCoros map. They are dummy entries, + // and they will leak at process shutdown: one CoroData per thread. + if (! sCurrent.get()) + { + // It's tempting to provide a distinct name for each thread's "main + // coroutine." But as getName() has always returned the empty string + // to mean "not in a coroutine," empty string should suffice here -- + // and truthfully the additional (thread-safe!) machinery to ensure + // uniqueness just doesn't feel worth the trouble. + // We use a no-op callable and a minimal stack size because, although + // CoroData's constructor in fact initializes its mCoro with a + // coroutine with that stack size, no one ever actually enters it by + // calling mCoro(). + sCurrent.reset(new CoroData(0, // no prev + "", // not a named coroutine + no_op, // no-op callable + 1024)); // stacksize moot + } + + mCurrent = &sCurrent; +} //static LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller) { - CoroData* current = sCurrentCoro.get(); - if (! current) - { - LL_ERRS("LLCoros") << "Calling " << caller << " from non-coroutine context!" << LL_ENDL; - } + CoroData* current = Current(); + // With the dummy CoroData set in LLCoros::Current::Current(), this + // pointer should never be NULL. + llassert_always(current); return *current; } //static LLCoros::coro::self& LLCoros::get_self() { - return *get_CoroData("get_self()").mSelf; + CoroData& current = get_CoroData("get_self()"); + if (! current.mSelf) + { + LL_ERRS("LLCoros") << "Calling get_self() from non-coroutine context!" << LL_ENDL; + } + return *current.mSelf; } //static @@ -80,20 +127,23 @@ bool LLCoros::get_consuming() return get_CoroData("get_consuming()").mConsuming; } -llcoro::Suspending::Suspending(): - mSuspended(LLCoros::sCurrentCoro.get()) +llcoro::Suspending::Suspending() { - // Revert mCurrentCoro to the value it had at the moment we last switched + LLCoros::Current current; + // Remember currently-running coroutine: we're about to suspend it. + mSuspended = current; + // Revert Current to the value it had at the moment we last switched // into this coroutine. - LLCoros::sCurrentCoro.reset(mSuspended->mPrev); + current.reset(mSuspended->mPrev); } llcoro::Suspending::~Suspending() { + LLCoros::Current current; // Okay, we're back, update our mPrev - mSuspended->mPrev = LLCoros::sCurrentCoro.get(); - // and reinstate our sCurrentCoro. - LLCoros::sCurrentCoro.reset(mSuspended); + mSuspended->mPrev = current; + // and reinstate our Current. + current.reset(mSuspended); } LLCoros::LLCoros(): @@ -213,13 +263,7 @@ bool LLCoros::kill(const std::string& name) std::string LLCoros::getName() const { - CoroData* current = sCurrentCoro.get(); - if (! current) - { - // not in a coroutine - return ""; - } - return current->mName; + return Current()->mName; } void LLCoros::setStackSize(S32 stacksize) @@ -229,8 +273,8 @@ void LLCoros::setStackSize(S32 stacksize) } // Top-level wrapper around caller's coroutine callable. This function accepts -// the coroutine library's implicit coro::self& parameter and sets sCurrentSelf -// but does not pass it down to the caller's callable. +// the coroutine library's implicit coro::self& parameter and saves it, but +// does not pass it down to the caller's callable. void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& callable) { // capture the 'self' param in CoroData @@ -254,8 +298,8 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName)); } // This cleanup isn't perfectly symmetrical with the way we initially set - // data->mPrev, but this is our last chance to reset mCurrentCoro. - sCurrentCoro.reset(data->mPrev); + // data->mPrev, but this is our last chance to reset Current. + Current().reset(data->mPrev); } /***************************************************************************** @@ -278,7 +322,7 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name, mPrev(prev), mName(name), // Wrap the caller's callable in our toplevel() function so we can manage - // sCurrentCoro appropriately at startup and shutdown of each coroutine. + // Current appropriately at startup and shutdown of each coroutine. mCoro(boost::bind(toplevel, _1, this, callable), stacksize), // don't consume events unless specifically directed mConsuming(false), @@ -289,13 +333,13 @@ LLCoros::CoroData::CoroData(CoroData* prev, const std::string& name, std::string LLCoros::launch(const std::string& prefix, const callable_t& callable) { std::string name(generateDistinctName(prefix)); - // pass the current value of sCurrentCoro as previous context - CoroData* newCoro = new CoroData(sCurrentCoro.get(), name, - callable, mStackSize); + Current current; + // pass the current value of Current as previous context + CoroData* newCoro = new CoroData(current, name, callable, mStackSize); // Store it in our pointer map mCoros.insert(name, newCoro); // also set it as current - sCurrentCoro.reset(newCoro); + current.reset(newCoro); /* Run the coroutine until its first wait, then return here */ (newCoro->mCoro)(std::nothrow); return name; diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 39316ed0e6..bbe2d22af4 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -35,8 +35,10 @@ #include <boost/ptr_container/ptr_map.hpp> #include <boost/function.hpp> #include <boost/thread/tss.hpp> +#include <boost/noncopyable.hpp> #include <string> #include <stdexcept> +#include "llcoro_get_id.h" // for friend declaration // forward-declare helper class namespace llcoro @@ -83,6 +85,7 @@ class Suspending; */ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros> { + LLSINGLETON(LLCoros); public: /// Canonical boost::dcoroutines::coroutine signature we use typedef boost::dcoroutines::coroutine<void()> coro; @@ -173,9 +176,8 @@ public: class Future; private: - LLCoros(); - friend class LLSingleton<LLCoros>; friend class llcoro::Suspending; + friend llcoro::id llcoro::get_id(); std::string generateDistinctName(const std::string& prefix) const; bool cleanup(const LLSD&); struct CoroData; @@ -222,8 +224,22 @@ private: typedef boost::ptr_map<std::string, CoroData> CoroMap; CoroMap mCoros; - // identify the current coroutine's CoroData - static boost::thread_specific_ptr<LLCoros::CoroData> sCurrentCoro; + // Identify the current coroutine's CoroData. Use a little helper class so + // a caller can either use a temporary instance, or instantiate a named + // variable and access it multiple times. + class Current + { + public: + Current(); + + operator LLCoros::CoroData*() { return get(); } + LLCoros::CoroData* operator->() { return get(); } + LLCoros::CoroData* get() { return mCurrent->get(); } + void reset(LLCoros::CoroData* ptr) { mCurrent->reset(ptr); } + + private: + boost::thread_specific_ptr<LLCoros::CoroData>* mCurrent; + }; }; namespace llcoro @@ -231,7 +247,7 @@ namespace llcoro /// Instantiate one of these in a block surrounding any leaf point when /// control literally switches away from this coroutine. -class Suspending +class Suspending: boost::noncopyable { public: Suspending(); diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 7887a942e9..e6407ecf22 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -239,6 +239,14 @@ namespace { std::string className(const std::type_info& type) { + return LLError::Log::demangle(type.name()); + } +} // anonymous + +namespace LLError +{ + std::string Log::demangle(const char* mangled) + { #ifdef __GNUC__ // GCC: type_info::name() returns a mangled class name,st demangle @@ -252,31 +260,34 @@ namespace // but gcc 3.3 libstc++'s implementation of demangling is broken // and fails without. - char* name = abi::__cxa_demangle(type.name(), + 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 : type.name(); + return name ? name : mangled; #elif LL_WINDOWS // DevStudio: type_info::name() includes the text "class " at the start static const std::string class_prefix = "class "; - - std::string name = type.name(); - std::string::size_type p = name.find(class_prefix); - if (p == std::string::npos) + std::string name = mangled; + if (0 != name.compare(0, class_prefix.length(), class_prefix)) { + LL_DEBUGS() << "Did not see '" << class_prefix << "' prefix on '" + << name << "'" << LL_ENDL; return name; } - return name.substr(p + class_prefix.size()); + return name.substr(class_prefix.length()); -#else - return type.name(); +#else + return mangled; #endif } +} // LLError +namespace +{ std::string functionName(const std::string& preprocessor_name) { #if LL_WINDOWS @@ -363,9 +374,8 @@ namespace class Globals : public LLSingleton<Globals> { + LLSINGLETON(Globals); public: - Globals(); - std::ostringstream messageStream; bool messageStreamInUse; @@ -438,11 +448,10 @@ namespace LLError class Settings : public LLSingleton<Settings> { + LLSINGLETON(Settings); public: - Settings(); - SettingsConfigPtr getSettingsConfig(); - + void reset(); SettingsStoragePtr saveAndReset(); void restore(SettingsStoragePtr pSettingsStorage); @@ -450,7 +459,7 @@ namespace LLError private: SettingsConfigPtr mSettingsConfig; }; - + SettingsConfig::SettingsConfig() : LLRefCount(), mPrintLocation(false), @@ -475,8 +484,7 @@ namespace LLError mRecorders.clear(); } - Settings::Settings() - : LLSingleton<Settings>(), + Settings::Settings(): mSettingsConfig(new SettingsConfig()) { } @@ -485,26 +493,31 @@ namespace LLError { return mSettingsConfig; } - + void Settings::reset() { Globals::getInstance()->invalidateCallSites(); mSettingsConfig = new SettingsConfig(); } - + SettingsStoragePtr Settings::saveAndReset() { SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); reset(); return oldSettingsConfig; } - + void Settings::restore(SettingsStoragePtr pSettingsStorage) { Globals::getInstance()->invalidateCallSites(); SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); mSettingsConfig = newSettingsConfig; } + + bool is_available() + { + return Settings::instanceExists() && Globals::instanceExists(); + } } namespace LLError diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 3573b3f44e..ceb1fd2c5f 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -190,6 +190,7 @@ namespace LLError static std::ostringstream* out(); static void flush(std::ostringstream* out, char* message); static void flush(std::ostringstream*, const CallSite&); + static std::string demangle(const char* mangled); }; struct LL_COMMON_API CallSite diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 56ac52e5de..56e84f7172 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -189,6 +189,11 @@ namespace LLError LL_COMMON_API std::string abbreviateFile(const std::string& filePath); LL_COMMON_API int shouldLogCallCount(); + + // Check whether Globals exists. This should only be used by LLSingleton + // infrastructure to avoid trying to log when our internal LLSingleton is + // unavailable -- circularity ensues. + LL_COMMON_API bool is_available(); }; #endif // LL_LLERRORCONTROL_H diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index a3b9ec02e0..7cff7dfd45 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -229,7 +229,7 @@ class LLEventPump; */ class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps> { - friend class LLSingleton<LLEventPumps>; + LLSINGLETON(LLEventPumps); public: /** * Find or create an LLEventPump instance with a specific name. We return @@ -272,7 +272,6 @@ private: void unregister(const LLEventPump&); private: - LLEventPumps(); ~LLEventPumps(); testable: diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 873a7bce25..7b559861bb 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -239,7 +239,7 @@ int LLFile::close(LLFILE * file) } -int LLFile::remove(const std::string& filename) +int LLFile::remove(const std::string& filename, int supress_error) { #if LL_WINDOWS std::string utf8filename = filename; @@ -248,7 +248,7 @@ int LLFile::remove(const std::string& filename) #else int rc = ::remove(filename.c_str()); #endif - return warnif("remove", filename, rc); + return warnif("remove", filename, rc, supress_error); } int LLFile::rename(const std::string& filename, const std::string& newname) diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 3e25228aeb..d8f84daf2b 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -72,7 +72,7 @@ public: static int mkdir(const std::string& filename, int perms = 0700); static int rmdir(const std::string& filename); - static int remove(const std::string& filename); + static int remove(const std::string& filename, int supress_error = 0); static int rename(const std::string& filename,const std::string& newname); static bool copy(const std::string from, const std::string to); diff --git a/indra/llcommon/llheteromap.cpp b/indra/llcommon/llheteromap.cpp new file mode 100644 index 0000000000..7c19196e0c --- /dev/null +++ b/indra/llcommon/llheteromap.cpp @@ -0,0 +1,32 @@ +/** + * @file llheteromap.cpp + * @author Nat Goodspeed + * @date 2016-10-12 + * @brief Implementation for llheteromap. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llheteromap.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +LLHeteroMap::~LLHeteroMap() +{ + // For each entry in our map, we must call its deleter, which is the only + // record we have of its original type. + for (TypeMap::iterator mi(mMap.begin()), me(mMap.end()); mi != me; ++mi) + { + // mi->second is the std::pair; mi->second.first is the void*; + // mi->second.second points to the deleter function + (mi->second.second)(mi->second.first); + mi->second.first = NULL; + } +} diff --git a/indra/llcommon/llheteromap.h b/indra/llcommon/llheteromap.h new file mode 100644 index 0000000000..9d6f303d08 --- /dev/null +++ b/indra/llcommon/llheteromap.h @@ -0,0 +1,95 @@ +/** + * @file llheteromap.h + * @author Nat Goodspeed + * @date 2016-10-12 + * @brief Map capable of storing objects of diverse types, looked up by type. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLHETEROMAP_H) +#define LL_LLHETEROMAP_H + +#include <typeinfo> +#include <utility> // std::pair +#include <map> + +/** + * LLHeteroMap addresses an odd requirement. Usually when you want to put + * objects of different classes into a runtime collection of any kind, you + * derive them all from a common base class and store pointers to that common + * base class. + * + * LLInitParam::BaseBlock uses disturbing raw-pointer arithmetic to find data + * members in its subclasses. It seems that no BaseBlock subclass can be + * stored in a polymorphic class of any kind: the presence of a vtbl pointer + * in the layout silently throws off the reinterpret_cast arithmetic. Bad + * Things result. (Many thanks to Nicky D for this analysis!) + * + * LLHeteroMap collects objects WITHOUT a common base class, retrieves them by + * object type and destroys them when the LLHeteroMap is destroyed. + */ +class LLHeteroMap +{ +public: + ~LLHeteroMap(); + + /// find or create + template <class T> + T& obtain() + { + // Look up map entry by typeid(T). We don't simply use mMap[typeid(T)] + // because that requires default-constructing T on every lookup. For + // some kinds of T, that could be expensive. + TypeMap::iterator found = mMap.find(&typeid(T)); + if (found == mMap.end()) + { + // Didn't find typeid(T). Create an entry. Because we're storing + // only a void* in the map, discarding type information, make sure + // we capture that type information in our deleter. + void* ptr = new T(); + void (*dlfn)(void*) = &deleter<T>; + std::pair<TypeMap::iterator, bool> inserted = + mMap.insert(TypeMap::value_type(&typeid(T), + TypeMap::mapped_type(ptr, dlfn))); + // Okay, now that we have an entry, claim we found it. + found = inserted.first; + } + // found->second is the std::pair; second.first is the void* + // pointer to the object in question. Cast it to correct type and + // dereference it. + return *(static_cast<T*>(found->second.first)); + } + +private: + template <class T> + static + void deleter(void* p) + { + delete static_cast<T*>(p); + } + + // Comparing two std::type_info* values is tricky, because the standard + // does not guarantee that there will be only one type_info instance for a + // given type. In other words, &typeid(A) in one part of the program may + // not always equal &typeid(A) in some other part. Use special comparator. + struct type_info_ptr_comp + { + bool operator()(const std::type_info* lhs, const std::type_info* rhs) + { + return lhs->before(*rhs); + } + }; + + // What we actually store is a map from std::type_info (permitting lookup + // by object type) to a void* pointer to the object PLUS its deleter. + typedef std::map< + const std::type_info*, std::pair<void*, void (*)(void*)>, + type_info_ptr_comp> + TypeMap; + TypeMap mMap; +}; + +#endif /* ! defined(LL_LLHETEROMAP_H) */ diff --git a/indra/llcommon/llinitdestroyclass.cpp b/indra/llcommon/llinitdestroyclass.cpp new file mode 100644 index 0000000000..e6382a7924 --- /dev/null +++ b/indra/llcommon/llinitdestroyclass.cpp @@ -0,0 +1,30 @@ +/** + * @file llinitdestroyclass.cpp + * @author Nat Goodspeed + * @date 2016-08-30 + * @brief Implementation for llinitdestroyclass. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinitdestroyclass.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" + +void LLCallbackRegistry::fireCallbacks() const +{ + for (FuncList::const_iterator fi = mCallbacks.begin(), fe = mCallbacks.end(); + fi != fe; ++fi) + { + LL_INFOS("LLInitDestroyClass") << "calling " << fi->first << "()" << LL_ENDL; + fi->second(); + } +} diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h new file mode 100644 index 0000000000..5f979614fe --- /dev/null +++ b/indra/llcommon/llinitdestroyclass.h @@ -0,0 +1,175 @@ +/** + * @file llinitdestroyclass.h + * @author Nat Goodspeed + * @date 2015-05-27 + * @brief LLInitClass / LLDestroyClass mechanism + * + * The LLInitClass template, extracted from llui.h, ensures that control will + * reach a static initClass() method. LLDestroyClass does the same for a + * static destroyClass() method. + * + * The distinguishing characteristics of these templates are: + * + * - All LLInitClass<T>::initClass() methods are triggered by an explicit call + * to LLInitClassList::instance().fireCallbacks(). Presumably this call + * happens sometime after all static objects in the program have been + * initialized. In other words, each LLInitClass<T>::initClass() method + * should be able to make some assumptions about global program state. + * + * - Similarly, LLDestroyClass<T>::destroyClass() methods are triggered by + * LLDestroyClassList::instance().fireCallbacks(). Again, presumably this + * happens at a well-defined moment in the program's shutdown sequence. + * + * - The initClass() calls happen in an unspecified sequence. You may not rely + * on the relative ordering of LLInitClass<T>::initClass() versus another + * LLInitClass<U>::initClass() method. If you need such a guarantee, use + * LLSingleton instead and make the dependency explicit. + * + * - Similarly, LLDestroyClass<T>::destroyClass() may happen either before or + * after LLDestroyClass<U>::destroyClass(). You cannot rely on that order. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLINITDESTROYCLASS_H) +#define LL_LLINITDESTROYCLASS_H + +#include "llsingleton.h" +#include <boost/function.hpp> +#include <typeinfo> +#include <vector> +#include <utility> // std::pair + +/** + * LLCallbackRegistry is an implementation detail base class for + * LLInitClassList and LLDestroyClassList. It accumulates the initClass() or + * destroyClass() callbacks for registered classes. + */ +class LLCallbackRegistry +{ +public: + typedef boost::function<void()> func_t; + + void registerCallback(const std::string& name, const func_t& func) + { + mCallbacks.push_back(FuncList::value_type(name, func)); + } + + void fireCallbacks() const; + +private: + // Arguably this should be a boost::signals2::signal, which is, after all, + // a sequence of callables. We manage it by hand so we can log a name for + // each registered function we call. + typedef std::vector< std::pair<std::string, func_t> > FuncList; + FuncList mCallbacks; +}; + +/** + * LLInitClassList is the LLCallbackRegistry for LLInitClass. It stores the + * registered initClass() methods. It must be an LLSingleton because + * LLInitClass registers its initClass() method at static construction time + * (before main()), requiring LLInitClassList to be fully constructed on + * demand regardless of module initialization order. + */ +class LLInitClassList : + public LLCallbackRegistry, + public LLSingleton<LLInitClassList> +{ + LLSINGLETON_EMPTY_CTOR(LLInitClassList); +}; + +/** + * LLDestroyClassList is the LLCallbackRegistry for LLDestroyClass. It stores + * the registered destroyClass() methods. It must be an LLSingleton because + * LLDestroyClass registers its destroyClass() method at static construction + * time (before main()), requiring LLDestroyClassList to be fully constructed + * on demand regardless of module initialization order. + */ +class LLDestroyClassList : + public LLCallbackRegistry, + public LLSingleton<LLDestroyClassList> +{ + LLSINGLETON_EMPTY_CTOR(LLDestroyClassList); +}; + +/** + * LLRegisterWith is an implementation detail for LLInitClass and + * LLDestroyClass. It is intended to be used as a static class member whose + * constructor registers the specified callback with the LLMumbleClassList + * singleton registry specified as the template argument. + */ +template<typename T> +class LLRegisterWith +{ +public: + LLRegisterWith(const std::string& name, const LLCallbackRegistry::func_t& func) + { + T::instance().registerCallback(name, func); + } + + // this avoids a MSVC bug where non-referenced static members are "optimized" away + // even if their constructors have side effects + S32 reference() + { + S32 dummy; + dummy = 0; + return dummy; + } +}; + +/** + * Derive MyClass from LLInitClass<MyClass> (the Curiously Recurring Template + * Pattern) to ensure that the static method MyClass::initClass() will be + * called (along with all other LLInitClass<T> subclass initClass() methods) + * when someone calls LLInitClassList::instance().fireCallbacks(). This gives + * the application specific control over the timing of all such + * initializations, without having to insert calls for every such class into + * generic application code. + */ +template<typename T> +class LLInitClass +{ +public: + LLInitClass() { sRegister.reference(); } + + // When this static member is initialized, the subclass initClass() method + // is registered on LLInitClassList. See sRegister definition below. + static LLRegisterWith<LLInitClassList> sRegister; +}; + +/** + * Derive MyClass from LLDestroyClass<MyClass> (the Curiously Recurring + * Template Pattern) to ensure that the static method MyClass::destroyClass() + * will be called (along with other LLDestroyClass<T> subclass destroyClass() + * methods) when someone calls LLDestroyClassList::instance().fireCallbacks(). + * This gives the application specific control over the timing of all such + * cleanup calls, without having to insert calls for every such class into + * generic application code. + */ +template<typename T> +class LLDestroyClass +{ +public: + LLDestroyClass() { sRegister.reference(); } + + // When this static member is initialized, the subclass destroyClass() + // method is registered on LLInitClassList. See sRegister definition + // below. + static LLRegisterWith<LLDestroyClassList> sRegister; +}; + +// Here's where LLInitClass<T> specifies the subclass initClass() method. +template <typename T> +LLRegisterWith<LLInitClassList> +LLInitClass<T>::sRegister(std::string(typeid(T).name()) + "::initClass", + &T::initClass); +// Here's where LLDestroyClass<T> specifies the subclass destroyClass() method. +template <typename T> +LLRegisterWith<LLDestroyClassList> +LLDestroyClass<T>::sRegister(std::string(typeid(T).name()) + "::destroyClass", + &T::destroyClass); + +#endif /* ! defined(LL_LLINITDESTROYCLASS_H) */ diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index aa2f4eb289..1d104cf55d 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -193,7 +193,12 @@ namespace LLInitParam { if (!silent) { - p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str())); + std::string file_name = p.getCurrentFileName(); + if(!file_name.empty()) + { + file_name = "in file: " + file_name; + } + p.parserWarning(llformat("Failed to parse parameter \"%s\" %s", p.getCurrentElementName().c_str(), file_name.c_str())); } return false; } diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index c65b05f610..f1f4226c40 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -551,6 +551,7 @@ namespace LLInitParam } virtual std::string getCurrentElementName() = 0; + virtual std::string getCurrentFileName() = 0; virtual void parserWarning(const std::string& message); virtual void parserError(const std::string& message); void setParseSilently(bool silent) { mParseSilently = silent; } diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 1fc821d9a9..16fc365da1 100644 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -40,7 +40,7 @@ LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ; /*static*/ -void LLMetricPerformanceTesterBasic::cleanClass() +void LLMetricPerformanceTesterBasic::cleanupClass() { for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter) { diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h index 1a18cdf36f..e6b46be1cf 100644 --- a/indra/llcommon/llmetricperformancetester.h +++ b/indra/llcommon/llmetricperformancetester.h @@ -156,7 +156,7 @@ public: /** * @brief Delete all testers and reset the tester map */ - static void cleanClass() ; + static void cleanupClass() ; private: // Add a tester to the map. Returns false if adding fails. diff --git a/indra/llcommon/llpounceable.h b/indra/llcommon/llpounceable.h new file mode 100644 index 0000000000..0421ce966a --- /dev/null +++ b/indra/llcommon/llpounceable.h @@ -0,0 +1,216 @@ +/** + * @file llpounceable.h + * @author Nat Goodspeed + * @date 2015-05-22 + * @brief LLPounceable is tangentially related to a future: it's a holder for + * a value that may or may not exist yet. Unlike a future, though, + * LLPounceable freely allows reading the held value. (If the held + * type T does not have a distinguished "empty" value, consider using + * LLPounceable<boost::optional<T>>.) + * + * LLPounceable::callWhenReady() is this template's claim to fame. It + * allows its caller to "pounce" on the held value as soon as it + * becomes non-empty. Call callWhenReady() with any C++ callable + * accepting T. If the held value is already non-empty, callWhenReady() + * will immediately call the callable with the held value. If the held + * value is empty, though, callWhenReady() will enqueue the callable + * for later. As soon as LLPounceable is assigned a non-empty held + * value, it will flush the queue of deferred callables. + * + * Consider a global LLMessageSystem* gMessageSystem. Message system + * initialization happens at a very specific point during viewer + * initialization. Other subsystems want to register callbacks on the + * LLMessageSystem instance as soon as it's initialized, but their own + * initialization may precede that. If we define gMessageSystem to be + * an LLPounceable<LLMessageSystem*>, a subsystem can use + * callWhenReady() to either register immediately (if gMessageSystem + * is already up and runnning) or register as soon as gMessageSystem + * is set with a new, initialized instance. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLPOUNCEABLE_H) +#define LL_LLPOUNCEABLE_H + +#include "llsingleton.h" +#include <boost/noncopyable.hpp> +#include <boost/call_traits.hpp> +#include <boost/type_traits/remove_pointer.hpp> +#include <boost/utility/value_init.hpp> +#include <boost/unordered_map.hpp> +#include <boost/signals2/signal.hpp> + +// Forward declare the user template, since we want to be able to point to it +// in some of its implementation classes. +template <typename T, class TAG> +class LLPounceable; + +template <typename T, typename TAG> +struct LLPounceableTraits +{ + // Our "queue" is a signal object with correct signature. + typedef boost::signals2::signal<void (typename boost::call_traits<T>::param_type)> signal_t; + // Call callWhenReady() with any callable accepting T. + typedef typename signal_t::slot_type func_t; + // owner pointer type + typedef LLPounceable<T, TAG>* owner_ptr; +}; + +// Tag types distinguish the two different implementations of LLPounceable's +// queue. +struct LLPounceableQueue {}; +struct LLPounceableStatic {}; + +// generic LLPounceableQueueImpl deliberately omitted: only the above tags are +// legal +template <typename T, class TAG> +class LLPounceableQueueImpl; + +// The implementation selected by LLPounceableStatic uses an LLSingleton +// because we can't count on a data member queue being initialized at the time +// we start getting callWhenReady() calls. This is that LLSingleton. +template <typename T> +class LLPounceableQueueSingleton: + public LLSingleton<LLPounceableQueueSingleton<T> > +{ + LLSINGLETON_EMPTY_CTOR(LLPounceableQueueSingleton); + + typedef LLPounceableTraits<T, LLPounceableStatic> traits; + typedef typename traits::owner_ptr owner_ptr; + typedef typename traits::signal_t signal_t; + + // For a given held type T, every LLPounceable<T, LLPounceableStatic> + // instance will call on the SAME LLPounceableQueueSingleton instance -- + // given how class statics work. We must keep a separate queue for each + // LLPounceable instance. Use a hash map for that. + typedef boost::unordered_map<owner_ptr, signal_t> map_t; + +public: + // Disambiguate queues belonging to different LLPounceables. + signal_t& get(owner_ptr owner) + { + // operator[] has find-or-create semantics -- just what we want! + return mMap[owner]; + } + +private: + map_t mMap; +}; + +// LLPounceableQueueImpl that uses the above LLSingleton +template <typename T> +class LLPounceableQueueImpl<T, LLPounceableStatic> +{ +public: + typedef LLPounceableTraits<T, LLPounceableStatic> traits; + typedef typename traits::owner_ptr owner_ptr; + typedef typename traits::signal_t signal_t; + + signal_t& get(owner_ptr owner) const + { + // this Impl contains nothing; it delegates to the Singleton + return LLPounceableQueueSingleton<T>::instance().get(owner); + } +}; + +// The implementation selected by LLPounceableQueue directly contains the +// queue of interest, suitable for an LLPounceable we can trust to be fully +// initialized when it starts getting callWhenReady() calls. +template <typename T> +class LLPounceableQueueImpl<T, LLPounceableQueue> +{ +public: + typedef LLPounceableTraits<T, LLPounceableQueue> traits; + typedef typename traits::owner_ptr owner_ptr; + typedef typename traits::signal_t signal_t; + + signal_t& get(owner_ptr) + { + return mQueue; + } + +private: + signal_t mQueue; +}; + +// LLPounceable<T> is for an LLPounceable instance on the heap or the stack. +// LLPounceable<T, LLPounceableStatic> is for a static LLPounceable instance. +template <typename T, class TAG=LLPounceableQueue> +class LLPounceable: public boost::noncopyable +{ +private: + typedef LLPounceableTraits<T, TAG> traits; + typedef typename traits::owner_ptr owner_ptr; + typedef typename traits::signal_t signal_t; + +public: + typedef typename traits::func_t func_t; + + // By default, both the initial value and the distinguished empty value + // are a default-constructed T instance. However you can explicitly + // specify each. + LLPounceable(typename boost::call_traits<T>::value_type init =boost::value_initialized<T>(), + typename boost::call_traits<T>::param_type empty=boost::value_initialized<T>()): + mHeld(init), + mEmpty(empty) + {} + + // make read access to mHeld as cheap and transparent as possible + operator T () const { return mHeld; } + typename boost::remove_pointer<T>::type operator*() const { return *mHeld; } + typename boost::call_traits<T>::value_type operator->() const { return mHeld; } + // uncomment 'explicit' as soon as we allow C++11 compilation + /*explicit*/ operator bool() const { return bool(mHeld); } + bool operator!() const { return ! mHeld; } + + // support both assignment (dumb ptr idiom) and reset() (smart ptr) + void operator=(typename boost::call_traits<T>::param_type value) + { + reset(value); + } + + void reset(typename boost::call_traits<T>::param_type value) + { + mHeld = value; + // If this new value is non-empty, flush anything pending in the queue. + if (mHeld != mEmpty) + { + signal_t& signal(get_signal()); + signal(mHeld); + signal.disconnect_all_slots(); + } + } + + // our claim to fame + void callWhenReady(const func_t& func) + { + if (mHeld != mEmpty) + { + // If the held value is already non-empty, immediately call func() + func(mHeld); + } + else + { + // Held value still empty, queue func() for later. By default, + // connect() enqueues slots in FIFO order. + get_signal().connect(func); + } + } + +private: + signal_t& get_signal() { return mQueue.get(this); } + + // Store both the current and the empty value. + // MAYBE: Might be useful to delegate to LLPounceableTraits the meaning of + // testing for "empty." For some types we want operator!(); for others we + // want to compare to a distinguished value. + typename boost::call_traits<T>::value_type mHeld, mEmpty; + // This might either contain the queue (LLPounceableQueue) or delegate to + // an LLSingleton (LLPounceableStatic). + LLPounceableQueueImpl<T, TAG> mQueue; +}; + +#endif /* ! defined(LL_LLPOUNCEABLE_H) */ diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index 29950c108d..750fe9fdc8 100644 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -247,7 +247,10 @@ class LLRegistrySingleton : public LLRegistry<KEY, VALUE, COMPARATOR>, public LLSingleton<DERIVED_TYPE> { - friend class LLSingleton<DERIVED_TYPE>; + // This LLRegistrySingleton doesn't use LLSINGLETON(LLRegistrySingleton) + // because the concrete class is actually DERIVED_TYPE, not + // LLRegistrySingleton. So each concrete subclass needs + // LLSINGLETON(whatever) -- not this intermediate base class. public: typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t; typedef const KEY& ref_const_key_t; @@ -269,7 +272,7 @@ public: ~ScopedRegistrar() { - if (!singleton_t::destroyed()) + if (singleton_t::instanceExists()) { popScope(); } diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h index 09f1bdf1e3..93910b70ae 100644 --- a/indra/llcommon/llsdparam.h +++ b/indra/llcommon/llsdparam.h @@ -66,6 +66,7 @@ public: } /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ std::string getCurrentFileName(){ return LLStringUtil::null; } private: void writeSDImpl(LLSD& sd, diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index d49ff0feb5..81ba8631c6 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -1200,6 +1200,7 @@ bool LLSDBinaryParser::parseString( read(istr, (char*)&value_nbo, sizeof(U32)); /*Flawfinder: ignore*/ S32 size = (S32)ntohl(value_nbo); if(mCheckLimits && (size > mMaxBytesLeft)) return false; + if(size < 0) return false; std::vector<char> buf; if(size) { diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 9b49e52377..9025e53bb2 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -25,7 +25,445 @@ */ #include "linden_common.h" - #include "llsingleton.h" +#include "llerror.h" +#include "llerrorcontrol.h" // LLError::is_available() +#include "lldependencies.h" +#include "llcoro_get_id.h" +#include <boost/foreach.hpp> +#include <boost/unordered_map.hpp> +#include <algorithm> +#include <iostream> // std::cerr in dire emergency +#include <sstream> +#include <stdexcept> + +namespace { +void log(LLError::ELevel level, + const char* p1, const char* p2, const char* p3, const char* p4); + +void logdebugs(const char* p1="", const char* p2="", const char* p3="", const char* p4=""); + +bool oktolog(); +} // anonymous namespace + +// Our master list of all LLSingletons is itself an LLSingleton. We used to +// store it in a function-local static, but that could get destroyed before +// the last of the LLSingletons -- and ~LLSingletonBase() definitely wants to +// remove itself from the master list. Since the whole point of this master +// list is to help track inter-LLSingleton dependencies, and since we have +// this implicit dependency from every LLSingleton to the master list, make it +// an LLSingleton. +class LLSingletonBase::MasterList: + public LLSingleton<LLSingletonBase::MasterList> +{ + LLSINGLETON_EMPTY_CTOR(MasterList); + +public: + // No need to make this private with accessors; nobody outside this source + // file can see it. + + // This is the master list of all instantiated LLSingletons (save the + // MasterList itself) in arbitrary order. You MUST call dep_sort() before + // traversing this list. + LLSingletonBase::list_t mMaster; + + // We need to maintain a stack of LLSingletons currently being + // initialized, either in the constructor or in initSingleton(). However, + // managing that as a stack depends on having a DISTINCT 'initializing' + // stack for every C++ stack in the process! And we have a distinct C++ + // stack for every running coroutine. It would be interesting and cool to + // implement a generic coroutine-local-storage mechanism and use that + // here. The trouble is that LLCoros is itself an LLSingleton, so + // depending on LLCoros functionality could dig us into infinite + // recursion. (Moreover, when we reimplement LLCoros on top of + // Boost.Fiber, that library already provides fiber_specific_ptr -- so + // it's not worth a great deal of time and energy implementing a generic + // equivalent on top of boost::dcoroutine, which is on its way out.) + // Instead, use a map of llcoro::id to select the appropriate + // coro-specific 'initializing' stack. llcoro::get_id() is carefully + // implemented to avoid requiring LLCoros. + typedef boost::unordered_map<llcoro::id, LLSingletonBase::list_t> InitializingMap; + InitializingMap mInitializing; + + // non-static method, cf. LLSingletonBase::get_initializing() + list_t& get_initializing_() + { + // map::operator[] has find-or-create semantics, exactly what we need + // here. It returns a reference to the selected mapped_type instance. + return mInitializing[llcoro::get_id()]; + } + + void cleanup_initializing_() + { + InitializingMap::iterator found = mInitializing.find(llcoro::get_id()); + if (found != mInitializing.end()) + { + mInitializing.erase(found); + } + } +}; + +//static +LLSingletonBase::list_t& LLSingletonBase::get_master() +{ + return LLSingletonBase::MasterList::instance().mMaster; +} + +void LLSingletonBase::add_master() +{ + // As each new LLSingleton is constructed, add to the master list. + get_master().push_back(this); +} + +void LLSingletonBase::remove_master() +{ + // When an LLSingleton is destroyed, remove from master list. + // add_master() used to capture the iterator to the newly-added list item + // so we could directly erase() it from the master list. Unfortunately + // that runs afoul of destruction-dependency order problems. So search the + // master list, and remove this item IF FOUND. We have few enough + // LLSingletons, and they are so rarely destroyed (once per run), that the + // cost of a linear search should not be an issue. + get_master().remove(this); +} + +//static +LLSingletonBase::list_t& LLSingletonBase::get_initializing() +{ + return LLSingletonBase::MasterList::instance().get_initializing_(); +} + +//static +LLSingletonBase::list_t& LLSingletonBase::get_initializing_from(MasterList* master) +{ + return master->get_initializing_(); +} + +LLSingletonBase::~LLSingletonBase() {} + +void LLSingletonBase::push_initializing(const char* name) +{ + // log BEFORE pushing so logging singletons don't cry circularity + log_initializing("Pushing", name); + get_initializing().push_back(this); +} + +void LLSingletonBase::pop_initializing() +{ + list_t& list(get_initializing()); + + if (list.empty()) + { + logerrs("Underflow in stack of currently-initializing LLSingletons at ", + demangle(typeid(*this).name()).c_str(), "::getInstance()"); + } + + // Now we know list.back() exists: capture it + LLSingletonBase* back(list.back()); + // and pop it + list.pop_back(); + + // The viewer launches an open-ended number of coroutines. While we don't + // expect most of them to initialize LLSingleton instances, our present + // get_initializing() logic could lead to an open-ended number of map + // entries. So every time we pop the stack back to empty, delete the entry + // entirely. + if (list.empty()) + { + MasterList::instance().cleanup_initializing_(); + } + + // Now validate the newly-popped LLSingleton. + if (back != this) + { + logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ", + demangle(typeid(*this).name()).c_str(), "::getInstance() trying to pop ", + demangle(typeid(*back).name()).c_str()); + } + + // log AFTER popping so logging singletons don't cry circularity + log_initializing("Popping", typeid(*back).name()); +} + +//static +void LLSingletonBase::log_initializing(const char* verb, const char* name) +{ + if (oktolog()) + { + LL_DEBUGS("LLSingleton") << verb << ' ' << demangle(name) << ';'; + list_t& list(get_initializing()); + for (list_t::const_reverse_iterator ri(list.rbegin()), rend(list.rend()); + ri != rend; ++ri) + { + LLSingletonBase* sb(*ri); + LL_CONT << ' ' << demangle(typeid(*sb).name()); + } + LL_ENDL; + } +} + +void LLSingletonBase::capture_dependency(list_t& initializing, EInitState initState) +{ + // Did this getInstance() call come from another LLSingleton, or from + // vanilla application code? Note that although this is a nontrivial + // method, the vast majority of its calls arrive here with initializing + // empty(). + if (! initializing.empty()) + { + // getInstance() is being called by some other LLSingleton. But -- is + // this a circularity? That is, does 'this' already appear in the + // initializing stack? + // For what it's worth, normally 'initializing' should contain very + // few elements. + list_t::const_iterator found = + std::find(initializing.begin(), initializing.end(), this); + if (found != initializing.end()) + { + // Report the circularity. Requiring the coder to dig through the + // logic to diagnose exactly how we got here is less than helpful. + std::ostringstream out; + for ( ; found != initializing.end(); ++found) + { + // 'found' is an iterator; *found is an LLSingletonBase*; **found + // is the actual LLSingletonBase instance. + LLSingletonBase* foundp(*found); + out << demangle(typeid(*foundp).name()) << " -> "; + } + // We promise to capture dependencies from both the constructor + // and the initSingleton() method, so an LLSingleton's instance + // pointer is on the initializing list during both. Now that we've + // detected circularity, though, we must distinguish the two. If + // the recursive call is from the constructor, we CAN'T honor it: + // otherwise we'd be returning a pointer to a partially- + // constructed object! But from initSingleton() is okay: that + // method exists specifically to support circularity. + // Decide which log helper to call based on initState. They have + // identical signatures. + ((initState == CONSTRUCTING)? logerrs : logwarns) + ("LLSingleton circularity: ", out.str().c_str(), + demangle(typeid(*this).name()).c_str(), ""); + } + else + { + // Here 'this' is NOT already in the 'initializing' stack. Great! + // Record the dependency. + // initializing.back() is the LLSingletonBase* currently being + // initialized. Store 'this' in its mDepends set. + LLSingletonBase* current(initializing.back()); + if (current->mDepends.insert(this).second) + { + // only log the FIRST time we hit this dependency! + logdebugs(demangle(typeid(*current).name()).c_str(), + " depends on ", demangle(typeid(*this).name()).c_str()); + } + } + } +} + +//static +LLSingletonBase::vec_t LLSingletonBase::dep_sort() +{ + // While it would theoretically be possible to maintain a static + // SingletonDeps through the life of the program, dynamically adding and + // removing LLSingletons as they are created and destroyed, in practice + // it's less messy to construct it on demand. The overhead of doing so + // should happen basically twice: once for cleanupAll(), once for + // deleteAll(). + typedef LLDependencies<LLSingletonBase*> SingletonDeps; + SingletonDeps sdeps; + list_t& master(get_master()); + BOOST_FOREACH(LLSingletonBase* sp, master) + { + // Build the SingletonDeps structure by adding, for each + // LLSingletonBase* sp in the master list, sp itself. It has no + // associated value type in our SingletonDeps, hence the 0. We don't + // record the LLSingletons it must follow; rather, we record the ones + // it must precede. Copy its mDepends to a KeyList to express that. + sdeps.add(sp, 0, + SingletonDeps::KeyList(), + SingletonDeps::KeyList(sp->mDepends.begin(), sp->mDepends.end())); + } + vec_t ret; + ret.reserve(master.size()); + // We should be able to effect this with a transform_iterator that + // extracts just the first (key) element from each sorted_iterator, then + // uses vec_t's range constructor... but frankly this is more + // straightforward, as long as we remember the above reserve() call! + BOOST_FOREACH(SingletonDeps::sorted_iterator::value_type pair, sdeps.sort()) + { + ret.push_back(pair.first); + } + // The master list is not itself pushed onto the master list. Add it as + // the very last entry -- it is the LLSingleton on which ALL others + // depend! -- so our caller will process it. + ret.push_back(MasterList::getInstance()); + return ret; +} + +//static +void LLSingletonBase::cleanupAll() +{ + // It's essential to traverse these in dependency order. + BOOST_FOREACH(LLSingletonBase* sp, dep_sort()) + { + // Call cleanupSingleton() only if we haven't already done so for this + // instance. + if (! sp->mCleaned) + { + sp->mCleaned = true; + + logdebugs("calling ", + demangle(typeid(*sp).name()).c_str(), "::cleanupSingleton()"); + try + { + sp->cleanupSingleton(); + } + catch (const std::exception& e) + { + logwarns("Exception in ", demangle(typeid(*sp).name()).c_str(), + "::cleanupSingleton(): ", e.what()); + } + catch (...) + { + logwarns("Unknown exception in ", demangle(typeid(*sp).name()).c_str(), + "::cleanupSingleton()"); + } + } + } +} + +//static +void LLSingletonBase::deleteAll() +{ + // It's essential to traverse these in dependency order. + BOOST_FOREACH(LLSingletonBase* sp, dep_sort()) + { + // Capture the class name first: in case of exception, don't count on + // being able to extract it later. + const std::string name = demangle(typeid(*sp).name()); + try + { + // Call static method through instance function pointer. + if (! sp->mDeleteSingleton) + { + // This Should Not Happen... but carry on. + logwarns(name.c_str(), "::mDeleteSingleton not initialized!"); + } + else + { + // properly initialized: call it. + logdebugs("calling ", name.c_str(), "::deleteSingleton()"); + // From this point on, DO NOT DEREFERENCE sp! + sp->mDeleteSingleton(); + } + } + catch (const std::exception& e) + { + logwarns("Exception in ", name.c_str(), "::deleteSingleton(): ", e.what()); + } + catch (...) + { + logwarns("Unknown exception in ", name.c_str(), "::deleteSingleton()"); + } + } +} + +/*------------------------ Final cleanup management ------------------------*/ +class LLSingletonBase::MasterRefcount +{ +public: + // store a POD int so it will be statically initialized to 0 + int refcount; +}; +static LLSingletonBase::MasterRefcount sMasterRefcount; + +LLSingletonBase::ref_ptr_t LLSingletonBase::get_master_refcount() +{ + // Calling this method constructs a new ref_ptr_t, which implicitly calls + // intrusive_ptr_add_ref(MasterRefcount*). + return &sMasterRefcount; +} + +void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount* mrc) +{ + // Count outstanding SingletonLifetimeManager instances. + ++mrc->refcount; +} + +void intrusive_ptr_release(LLSingletonBase::MasterRefcount* mrc) +{ + // Notice when each SingletonLifetimeManager instance is destroyed. + if (! --mrc->refcount) + { + // The last instance was destroyed. Time to kill any remaining + // LLSingletons -- but in dependency order. + LLSingletonBase::deleteAll(); + } +} + +/*---------------------------- Logging helpers -----------------------------*/ +namespace { +bool oktolog() +{ + // See comments in log() below. + return sMasterRefcount.refcount && LLError::is_available(); +} + +void log(LLError::ELevel level, + const char* p1, const char* p2, const char* p3, const char* p4) +{ + // Check whether we're in the implicit final LLSingletonBase::deleteAll() + // call. We've carefully arranged for deleteAll() to be called when the + // last SingletonLifetimeManager instance is destroyed -- in other words, + // when the last translation unit containing an LLSingleton instance + // cleans up static data. That could happen after std::cerr is destroyed! + // The is_available() test below ensures that we'll stop logging once + // LLError has been cleaned up. If we had a similar portable test for + // std::cerr, this would be a good place to use it. As we do not, just + // don't log anything during implicit final deleteAll(). Detect that by + // the master refcount having gone to zero. + if (sMasterRefcount.refcount == 0) + return; + + // Check LLError::is_available() because some of LLError's infrastructure + // is itself an LLSingleton. If that LLSingleton has not yet been + // initialized, trying to log will engage LLSingleton machinery... and + // around and around we go. + if (LLError::is_available()) + { + LL_VLOGS(level, "LLSingleton") << p1 << p2 << p3 << p4 << LL_ENDL; + } + else + { + // Caller may be a test program, or something else whose stderr is + // visible to the user. + std::cerr << p1 << p2 << p3 << p4 << std::endl; + } +} + +void logdebugs(const char* p1, const char* p2, const char* p3, const char* p4) +{ + log(LLError::LEVEL_DEBUG, p1, p2, p3, p4); +} +} // anonymous namespace + +//static +void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, const char* p4) +{ + log(LLError::LEVEL_WARN, p1, p2, p3, p4); +} + +//static +void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4) +{ + log(LLError::LEVEL_ERROR, p1, p2, p3, p4); + // The other important side effect of LL_ERRS() is + // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG) + LLError::crashAndLoop(std::string()); +} +std::string LLSingletonBase::demangle(const char* mangled) +{ + return LLError::Log::demangle(mangled); +} diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 6e6291a165..1b915dfd6e 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -25,188 +25,495 @@ #ifndef LLSINGLETON_H #define LLSINGLETON_H -#include "llerror.h" // *TODO: eliminate this - -#include <typeinfo> #include <boost/noncopyable.hpp> +#include <boost/unordered_set.hpp> +#include <boost/intrusive_ptr.hpp> +#include <list> +#include <vector> +#include <typeinfo> + +class LLSingletonBase: private boost::noncopyable +{ +public: + class MasterList; + class MasterRefcount; + typedef boost::intrusive_ptr<MasterRefcount> ref_ptr_t; + +private: + // All existing LLSingleton instances are tracked in this master list. + typedef std::list<LLSingletonBase*> list_t; + static list_t& get_master(); + // This, on the other hand, is a stack whose top indicates the LLSingleton + // currently being initialized. + static list_t& get_initializing(); + static list_t& get_initializing_from(MasterList*); + // Produce a vector<LLSingletonBase*> of master list, in dependency order. + typedef std::vector<LLSingletonBase*> vec_t; + static vec_t dep_sort(); + + bool mCleaned; // cleanupSingleton() has been called + // we directly depend on these other LLSingletons + typedef boost::unordered_set<LLSingletonBase*> set_t; + set_t mDepends; + +protected: + typedef enum e_init_state + { + UNINITIALIZED = 0, // must be default-initialized state + CONSTRUCTING, + INITIALIZING, + INITIALIZED, + DELETED + } EInitState; + + // Define tag<T> to pass to our template constructor. You can't explicitly + // invoke a template constructor with ordinary template syntax: + // http://stackoverflow.com/a/3960925/5533635 + template <typename T> + struct tag + { + typedef T type; + }; + + // Base-class constructor should only be invoked by the DERIVED_TYPE + // constructor, which passes tag<DERIVED_TYPE> for various purposes. + template <typename DERIVED_TYPE> + LLSingletonBase(tag<DERIVED_TYPE>); + virtual ~LLSingletonBase(); + + // Every new LLSingleton should be added to/removed from the master list + void add_master(); + void remove_master(); + // with a little help from our friends. + template <class T> friend struct LLSingleton_manage_master; + + // Maintain a stack of the LLSingleton subclass instance currently being + // initialized. We use this to notice direct dependencies: we want to know + // if A requires B. We deduce a dependency if while initializing A, + // control reaches B::getInstance(). + // We want &A to be at the top of that stack during both A::A() and + // A::initSingleton(), since a call to B::getInstance() might occur during + // either. + // Unfortunately the desired timespan does not correspond neatly with a + // single C++ scope, else we'd use RAII to track it. But we do know that + // LLSingletonBase's constructor definitely runs just before + // LLSingleton's, which runs just before the specific subclass's. + void push_initializing(const char*); + // LLSingleton is, and must remain, the only caller to initSingleton(). + // That being the case, we control exactly when it happens -- and we can + // pop the stack immediately thereafter. + void pop_initializing(); +private: + // logging + static void log_initializing(const char* verb, const char* name); +protected: + // If a given call to B::getInstance() happens during either A::A() or + // A::initSingleton(), record that A directly depends on B. + void capture_dependency(list_t& initializing, EInitState); + + // delegate LL_ERRS() logging to llsingleton.cpp + static void logerrs(const char* p1, const char* p2="", + const char* p3="", const char* p4=""); + // delegate LL_WARNS() logging to llsingleton.cpp + static void logwarns(const char* p1, const char* p2="", + const char* p3="", const char* p4=""); + static std::string demangle(const char* mangled); + + // obtain canonical ref_ptr_t + static ref_ptr_t get_master_refcount(); + + // Default methods in case subclass doesn't declare them. + virtual void initSingleton() {} + virtual void cleanupSingleton() {} + + // deleteSingleton() isn't -- and shouldn't be -- a virtual method. It's a + // class static. However, given only Foo*, deleteAll() does need to be + // able to reach Foo::deleteSingleton(). Make LLSingleton (which declares + // deleteSingleton()) store a pointer here. Since we know it's a static + // class method, a classic-C function pointer will do. + void (*mDeleteSingleton)(); + +public: + /** + * Call this to call the cleanupSingleton() method for every LLSingleton + * constructed since the start of the last cleanupAll() call. (Any + * LLSingleton constructed DURING a cleanupAll() call won't be cleaned up + * until the next cleanupAll() call.) cleanupSingleton() neither deletes + * nor destroys its LLSingleton; therefore it's safe to include logic that + * might take significant realtime or even throw an exception. + * + * The most important property of cleanupAll() is that cleanupSingleton() + * methods are called in dependency order, leaf classes last. Thus, given + * two LLSingleton subclasses A and B, if A's dependency on B is properly + * expressed as a B::getInstance() or B::instance() call during either + * A::A() or A::initSingleton(), B will be cleaned up after A. + * + * If a cleanupSingleton() method throws an exception, the exception is + * logged, but cleanupAll() attempts to continue calling the rest of the + * cleanupSingleton() methods. + */ + static void cleanupAll(); + /** + * Call this to call the deleteSingleton() method for every LLSingleton + * constructed since the start of the last deleteAll() call. (Any + * LLSingleton constructed DURING a deleteAll() call won't be cleaned up + * until the next deleteAll() call.) deleteSingleton() deletes and + * destroys its LLSingleton. Any cleanup logic that might take significant + * realtime -- or throw an exception -- must not be placed in your + * LLSingleton's destructor, but rather in its cleanupSingleton() method. + * + * The most important property of deleteAll() is that deleteSingleton() + * methods are called in dependency order, leaf classes last. Thus, given + * two LLSingleton subclasses A and B, if A's dependency on B is properly + * expressed as a B::getInstance() or B::instance() call during either + * A::A() or A::initSingleton(), B will be cleaned up after A. + * + * If a deleteSingleton() method throws an exception, the exception is + * logged, but deleteAll() attempts to continue calling the rest of the + * deleteSingleton() methods. + */ + static void deleteAll(); +}; + +// support ref_ptr_t +void intrusive_ptr_add_ref(LLSingletonBase::MasterRefcount*); +void intrusive_ptr_release(LLSingletonBase::MasterRefcount*); -// LLSingleton implements the getInstance() method part of the Singleton -// pattern. It can't make the derived class constructors protected, though, so -// you have to do that yourself. -// -// There are two ways to use LLSingleton. The first way is to inherit from it -// while using the typename that you'd like to be static as the template -// parameter, like so: -// -// class Foo: public LLSingleton<Foo>{}; -// -// Foo& instance = Foo::instance(); -// -// The second way is to use the singleton class directly, without inheritance: -// -// typedef LLSingleton<Foo> FooSingleton; -// -// Foo& instance = FooSingleton::instance(); -// -// In this case, the class being managed as a singleton needs to provide an -// initSingleton() method since the LLSingleton virtual method won't be -// available -// -// As currently written, it is not thread-safe. +// Most of the time, we want LLSingleton_manage_master() to forward its +// methods to real LLSingletonBase methods. +template <class T> +struct LLSingleton_manage_master +{ + void add(LLSingletonBase* sb) { sb->add_master(); } + void remove(LLSingletonBase* sb) { sb->remove_master(); } + void push_initializing(LLSingletonBase* sb) { sb->push_initializing(typeid(T).name()); } + void pop_initializing (LLSingletonBase* sb) { sb->pop_initializing(); } + LLSingletonBase::list_t& get_initializing(T*) { return LLSingletonBase::get_initializing(); } +}; +// But for the specific case of LLSingletonBase::MasterList, don't. +template <> +struct LLSingleton_manage_master<LLSingletonBase::MasterList> +{ + void add(LLSingletonBase*) {} + void remove(LLSingletonBase*) {} + void push_initializing(LLSingletonBase*) {} + void pop_initializing (LLSingletonBase*) {} + LLSingletonBase::list_t& get_initializing(LLSingletonBase::MasterList* instance) + { + return LLSingletonBase::get_initializing_from(instance); + } +}; + +// Now we can implement LLSingletonBase's template constructor. template <typename DERIVED_TYPE> -class LLSingleton : private boost::noncopyable +LLSingletonBase::LLSingletonBase(tag<DERIVED_TYPE>): + mCleaned(false), + mDeleteSingleton(NULL) +{ + // Make this the currently-initializing LLSingleton. + LLSingleton_manage_master<DERIVED_TYPE>().push_initializing(this); +} + +/** + * LLSingleton implements the getInstance() method part of the Singleton + * pattern. It can't make the derived class constructors protected, though, so + * you have to do that yourself. + * + * Derive your class from LLSingleton, passing your subclass name as + * LLSingleton's template parameter, like so: + * + * class Foo: public LLSingleton<Foo> + * { + * // use this macro at start of every LLSingleton subclass + * LLSINGLETON(Foo); + * public: + * // ... + * }; + * + * Foo& instance = Foo::instance(); + * + * LLSingleton recognizes a couple special methods in your derived class. + * + * If you override LLSingleton<T>::initSingleton(), your method will be called + * immediately after the instance is constructed. This is useful for breaking + * circular dependencies: if you find that your LLSingleton subclass + * constructor references other LLSingleton subclass instances in a chain + * leading back to yours, move the instance reference from your constructor to + * your initSingleton() method. + * + * If you override LLSingleton<T>::cleanupSingleton(), your method will be + * called if someone calls LLSingletonBase::cleanupAll(). The significant part + * of this promise is that cleanupAll() will call individual + * cleanupSingleton() methods in reverse dependency order. + * + * That is, consider LLSingleton subclasses C, B and A. A depends on B, which + * in turn depends on C. These dependencies are expressed as calls to + * B::instance() or B::getInstance(), and C::instance() or C::getInstance(). + * It shouldn't matter whether these calls appear in A::A() or + * A::initSingleton(), likewise B::B() or B::initSingleton(). + * + * We promise that if you later call LLSingletonBase::cleanupAll(): + * 1. A::cleanupSingleton() will be called before + * 2. B::cleanupSingleton(), which will be called before + * 3. C::cleanupSingleton(). + * Put differently, if your LLSingleton subclass constructor or + * initSingleton() method explicitly depends on some other LLSingleton + * subclass, you may continue to rely on that other subclass in your + * cleanupSingleton() method. + * + * We introduce a special cleanupSingleton() method because cleanupSingleton() + * operations can involve nontrivial realtime, or might throw an exception. A + * destructor should do neither! + * + * If your cleanupSingleton() method throws an exception, we log that + * exception but proceed with the remaining cleanupSingleton() calls. + * + * Similarly, if at some point you call LLSingletonBase::deleteAll(), all + * remaining LLSingleton instances will be destroyed in dependency order. (Or + * call MySubclass::deleteSingleton() to specifically destroy the canonical + * MySubclass instance.) + * + * As currently written, LLSingleton is not thread-safe. + */ +template <typename DERIVED_TYPE> +class LLSingleton : public LLSingletonBase { - private: - typedef enum e_init_state - { - UNINITIALIZED, - CONSTRUCTING, - INITIALIZING, - INITIALIZED, - DELETED - } EInitState; - static DERIVED_TYPE* constructSingleton() { return new DERIVED_TYPE(); } - - // stores pointer to singleton instance - struct SingletonLifetimeManager - { - SingletonLifetimeManager() - { - construct(); - } - - static void construct() - { - sData.mInitState = CONSTRUCTING; - sData.mInstance = constructSingleton(); - sData.mInitState = INITIALIZING; - } - - ~SingletonLifetimeManager() - { - if (sData.mInitState != DELETED) - { - deleteSingleton(); - } - } - }; - + + // We know of no way to instruct the compiler that every subclass + // constructor MUST be private. However, we can make the LLSINGLETON() + // macro both declare a private constructor and provide the required + // friend declaration. How can we ensure that every subclass uses + // LLSINGLETON()? By making that macro provide a definition for this pure + // virtual method. If you get "can't instantiate class due to missing pure + // virtual method" for this method, then add LLSINGLETON(yourclass) in the + // subclass body. + virtual void you_must_use_LLSINGLETON_macro() = 0; + + // stores pointer to singleton instance + struct SingletonLifetimeManager + { + SingletonLifetimeManager(): + mMasterRefcount(LLSingletonBase::get_master_refcount()) + { + construct(); + } + + static void construct() + { + sData.mInitState = CONSTRUCTING; + sData.mInstance = constructSingleton(); + sData.mInitState = INITIALIZING; + } + + ~SingletonLifetimeManager() + { + // The dependencies between LLSingletons, and the arbitrary order + // of static-object destruction, mean that we DO NOT WANT this + // destructor to delete this LLSingleton. This destructor will run + // without regard to any other LLSingleton whose cleanup might + // depend on its existence. What we really want is to count the + // runtime's attempts to cleanup LLSingleton static data -- and on + // the very last one, call LLSingletonBase::deleteAll(). That + // method will properly honor cross-LLSingleton dependencies. This + // is why we store an intrusive_ptr to a MasterRefcount: our + // ref_ptr_t member counts SingletonLifetimeManager instances. + // Once the runtime destroys the last of these, THEN we can delete + // every remaining LLSingleton. + } + + LLSingletonBase::ref_ptr_t mMasterRefcount; + }; + +protected: + // Pass DERIVED_TYPE explicitly to LLSingletonBase's constructor because, + // until our subclass constructor completes, *this isn't yet a + // full-fledged DERIVED_TYPE. + LLSingleton(): LLSingletonBase(LLSingletonBase::tag<DERIVED_TYPE>()) + { + // populate base-class function pointer with the static + // deleteSingleton() function for this particular specialization + mDeleteSingleton = &deleteSingleton; + + // add this new instance to the master list + LLSingleton_manage_master<DERIVED_TYPE>().add(this); + } + public: - virtual ~LLSingleton() - { - sData.mInstance = NULL; - sData.mInitState = DELETED; - } - - /** - * @brief Immediately delete the singleton. - * - * A subsequent call to LLProxy::getInstance() will construct a new - * instance of the class. - * - * LLSingletons are normally destroyed after main() has exited and the C++ - * runtime is cleaning up statically-constructed objects. Some classes - * derived from LLSingleton have objects that are part of a runtime system - * that is terminated before main() exits. Calling the destructor of those - * objects after the termination of their respective systems can cause - * crashes and other problems during termination of the project. Using this - * method to destroy the singleton early can prevent these crashes. - * - * An example where this is needed is for a LLSingleton that has an APR - * object as a member that makes APR calls on destruction. The APR system is - * shut down explicitly before main() exits. This causes a crash on exit. - * Using this method before the call to apr_terminate() and NOT calling - * getInstance() again will prevent the crash. - */ - static void deleteSingleton() - { - delete sData.mInstance; - sData.mInstance = NULL; - sData.mInitState = DELETED; - } - - - static DERIVED_TYPE* getInstance() - { - static SingletonLifetimeManager sLifeTimeMgr; - - switch (sData.mInitState) - { - case UNINITIALIZED: - // should never be uninitialized at this point - llassert(false); - return NULL; - case CONSTRUCTING: - LL_ERRS() << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << LL_ENDL; - return NULL; - case INITIALIZING: - // go ahead and flag ourselves as initialized so we can be reentrant during initialization - sData.mInitState = INITIALIZED; - // initialize singleton after constructing it so that it can reference other singletons which in turn depend on it, - // thus breaking cyclic dependencies - sData.mInstance->initSingleton(); - return sData.mInstance; - case INITIALIZED: - return sData.mInstance; - case DELETED: - LL_WARNS() << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << LL_ENDL; - SingletonLifetimeManager::construct(); - // same as first time construction - sData.mInitState = INITIALIZED; - sData.mInstance->initSingleton(); - return sData.mInstance; - } - - return NULL; - } - - static DERIVED_TYPE* getIfExists() - { - return sData.mInstance; - } - - // Reference version of getInstance() - // Preferred over getInstance() as it disallows checking for NULL - static DERIVED_TYPE& instance() - { - return *getInstance(); - } - - // Has this singleton been created uet? - // Use this to avoid accessing singletons before the can safely be constructed - static bool instanceExists() - { - return sData.mInitState == INITIALIZED; - } - - // Has this singleton already been deleted? - // Use this to avoid accessing singletons from a static object's destructor - static bool destroyed() - { - return sData.mInitState == DELETED; - } + virtual ~LLSingleton() + { + // remove this instance from the master list + LLSingleton_manage_master<DERIVED_TYPE>().remove(this); + sData.mInstance = NULL; + sData.mInitState = DELETED; + } -private: + /** + * @brief Immediately delete the singleton. + * + * A subsequent call to LLProxy::getInstance() will construct a new + * instance of the class. + * + * Without an explicit call to LLSingletonBase::deleteAll(), LLSingletons + * are implicitly destroyed after main() has exited and the C++ runtime is + * cleaning up statically-constructed objects. Some classes derived from + * LLSingleton have objects that are part of a runtime system that is + * terminated before main() exits. Calling the destructor of those objects + * after the termination of their respective systems can cause crashes and + * other problems during termination of the project. Using this method to + * destroy the singleton early can prevent these crashes. + * + * An example where this is needed is for a LLSingleton that has an APR + * object as a member that makes APR calls on destruction. The APR system is + * shut down explicitly before main() exits. This causes a crash on exit. + * Using this method before the call to apr_terminate() and NOT calling + * getInstance() again will prevent the crash. + */ + static void deleteSingleton() + { + delete sData.mInstance; + sData.mInstance = NULL; + sData.mInitState = DELETED; + } + + static DERIVED_TYPE* getInstance() + { + static SingletonLifetimeManager sLifeTimeMgr; - virtual void initSingleton() {} + switch (sData.mInitState) + { + case UNINITIALIZED: + // should never be uninitialized at this point + logerrs("Uninitialized singleton ", + demangle(typeid(DERIVED_TYPE).name()).c_str()); + return NULL; - struct SingletonData - { - // explicitly has a default constructor so that member variables are zero initialized in BSS - // and only changed by singleton logic, not constructor running during startup - EInitState mInitState; - DERIVED_TYPE* mInstance; - }; - static SingletonData sData; + case CONSTRUCTING: + logerrs("Tried to access singleton ", + demangle(typeid(DERIVED_TYPE).name()).c_str(), + " from singleton constructor!"); + return NULL; + + case INITIALIZING: + // go ahead and flag ourselves as initialized so we can be + // reentrant during initialization + sData.mInitState = INITIALIZED; + // initialize singleton after constructing it so that it can + // reference other singletons which in turn depend on it, thus + // breaking cyclic dependencies + sData.mInstance->initSingleton(); + // pop this off stack of initializing singletons + LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance); + break; + + case INITIALIZED: + break; + + case DELETED: + logwarns("Trying to access deleted singleton ", + demangle(typeid(DERIVED_TYPE).name()).c_str(), + " -- creating new instance"); + SingletonLifetimeManager::construct(); + // same as first time construction + sData.mInitState = INITIALIZED; + sData.mInstance->initSingleton(); + // pop this off stack of initializing singletons + LLSingleton_manage_master<DERIVED_TYPE>().pop_initializing(sData.mInstance); + break; + } + + // By this point, if DERIVED_TYPE was pushed onto the initializing + // stack, it has been popped off. So the top of that stack, if any, is + // an LLSingleton that directly depends on DERIVED_TYPE. If this call + // came from another LLSingleton, rather than from vanilla application + // code, record the dependency. + sData.mInstance->capture_dependency( + LLSingleton_manage_master<DERIVED_TYPE>().get_initializing(sData.mInstance), + sData.mInitState); + return sData.mInstance; + } + + // Reference version of getInstance() + // Preferred over getInstance() as it disallows checking for NULL + static DERIVED_TYPE& instance() + { + return *getInstance(); + } + + // Has this singleton been created yet? + // Use this to avoid accessing singletons before they can safely be constructed. + static bool instanceExists() + { + return sData.mInitState == INITIALIZED; + } + +private: + struct SingletonData + { + // explicitly has a default constructor so that member variables are zero initialized in BSS + // and only changed by singleton logic, not constructor running during startup + EInitState mInitState; + DERIVED_TYPE* mInstance; + }; + static SingletonData sData; }; template<typename T> typename LLSingleton<T>::SingletonData LLSingleton<T>::sData; +/** + * Use LLSINGLETON(Foo); at the start of an LLSingleton<Foo> subclass body + * when you want to declare an out-of-line constructor: + * + * @code + * class Foo: public LLSingleton<Foo> + * { + * // use this macro at start of every LLSingleton subclass + * LLSINGLETON(Foo); + * public: + * // ... + * }; + * // ... + * [inline] + * Foo::Foo() { ... } + * @endcode + * + * Unfortunately, this mechanism does not permit you to define even a simple + * (but nontrivial) constructor within the class body. If it's literally + * trivial, use LLSINGLETON_EMPTY_CTOR(); if not, use LLSINGLETON() and define + * the constructor outside the class body. If you must define it in a header + * file, use 'inline' (unless it's a template class) to avoid duplicate-symbol + * errors at link time. + */ +#define LLSINGLETON(DERIVED_CLASS) \ +private: \ + /* implement LLSingleton pure virtual method whose sole purpose */ \ + /* is to remind people to use this macro */ \ + virtual void you_must_use_LLSINGLETON_macro() {} \ + friend class LLSingleton<DERIVED_CLASS>; \ + DERIVED_CLASS() + +/** + * Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo> + * subclass body when the constructor is trivial: + * + * @code + * class Foo: public LLSingleton<Foo> + * { + * // use this macro at start of every LLSingleton subclass + * LLSINGLETON_EMPTY_CTOR(Foo); + * public: + * // ... + * }; + * @endcode + */ +#define LLSINGLETON_EMPTY_CTOR(DERIVED_CLASS) \ + /* LLSINGLETON() is carefully implemented to permit exactly this */ \ + LLSINGLETON(DERIVED_CLASS) {} + #endif diff --git a/indra/llcommon/tests/llheteromap_test.cpp b/indra/llcommon/tests/llheteromap_test.cpp new file mode 100644 index 0000000000..686bffb878 --- /dev/null +++ b/indra/llcommon/tests/llheteromap_test.cpp @@ -0,0 +1,163 @@ +/** + * @file llheteromap_test.cpp + * @author Nat Goodspeed + * @date 2016-10-12 + * @brief Test for llheteromap. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llheteromap.h" +// STL headers +#include <set> +// std headers +// external library headers + +// (pacify clang) +std::ostream& operator<<(std::ostream& out, const std::set<std::string>& strset); +// other Linden headers +#include "../test/lltut.h" + +static std::string clog; +static std::set<std::string> dlog; + +// want to be able to use ensure_equals() on a set<string> +std::ostream& operator<<(std::ostream& out, const std::set<std::string>& strset) +{ + out << '{'; + const char* delim = ""; + for (std::set<std::string>::const_iterator si(strset.begin()), se(strset.end()); + si != se; ++si) + { + out << delim << '"' << *si << '"'; + delim = ", "; + } + out << '}'; + return out; +} + +// unrelated test classes +struct Chalk +{ + int dummy; + std::string name; + + Chalk(): + dummy(0) + { + clog.append("a"); + } + + ~Chalk() + { + dlog.insert("a"); + } + +private: + Chalk(const Chalk&); // no implementation +}; + +struct Cheese +{ + std::string name; + + Cheese() + { + clog.append("e"); + } + + ~Cheese() + { + dlog.insert("e"); + } + +private: + Cheese(const Cheese&); // no implementation +}; + +struct Chowdah +{ + char displace[17]; + std::string name; + + Chowdah() + { + displace[0] = '\0'; + clog.append("o"); + } + + ~Chowdah() + { + dlog.insert("o"); + } + +private: + Chowdah(const Chowdah&); // no implementation +}; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llheteromap_data + { + llheteromap_data() + { + clog.erase(); + dlog.clear(); + } + }; + typedef test_group<llheteromap_data> llheteromap_group; + typedef llheteromap_group::object object; + llheteromap_group llheteromapgrp("llheteromap"); + + template<> template<> + void object::test<1>() + { + set_test_name("create, get, delete"); + + { + LLHeteroMap map; + + { + // create each instance + Chalk& chalk = map.obtain<Chalk>(); + chalk.name = "Chalk"; + + Cheese& cheese = map.obtain<Cheese>(); + cheese.name = "Cheese"; + + Chowdah& chowdah = map.obtain<Chowdah>(); + chowdah.name = "Chowdah"; + } // refs go out of scope + + { + // verify each instance + Chalk& chalk = map.obtain<Chalk>(); + ensure_equals(chalk.name, "Chalk"); + + Cheese& cheese = map.obtain<Cheese>(); + ensure_equals(cheese.name, "Cheese"); + + Chowdah& chowdah = map.obtain<Chowdah>(); + ensure_equals(chowdah.name, "Chowdah"); + } + } // destroy map + + // Chalk, Cheese and Chowdah should have been created in specific order + ensure_equals(clog, "aeo"); + + // We don't care what order they're destroyed in, as long as each is + // appropriately destroyed. + std::set<std::string> dtorset; + for (const char* cp = "aeo"; *cp; ++cp) + dtorset.insert(std::string(1, *cp)); + ensure_equals(dlog, dtorset); + } +} // namespace tut diff --git a/indra/llcommon/tests/llpounceable_test.cpp b/indra/llcommon/tests/llpounceable_test.cpp new file mode 100644 index 0000000000..2f4915ce11 --- /dev/null +++ b/indra/llcommon/tests/llpounceable_test.cpp @@ -0,0 +1,230 @@ +/** + * @file llpounceable_test.cpp + * @author Nat Goodspeed + * @date 2015-05-22 + * @brief Test for llpounceable. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llpounceable.h" +// STL headers +// std headers +// external library headers +#include <boost/bind.hpp> +// other Linden headers +#include "../test/lltut.h" + +/*----------------------------- string testing -----------------------------*/ +void append(std::string* dest, const std::string& src) +{ + dest->append(src); +} + +/*-------------------------- Data-struct testing ---------------------------*/ +struct Data +{ + Data(const std::string& data): + mData(data) + {} + const std::string mData; +}; + +void setter(Data** dest, Data* ptr) +{ + *dest = ptr; +} + +static Data* static_check = 0; + +// Set up an extern pointer to an LLPounceableStatic so the linker will fill +// in the forward reference from below, before runtime. +extern LLPounceable<Data*, LLPounceableStatic> gForward; + +struct EnqueueCall +{ + EnqueueCall() + { + // Intentionally use a forward reference to an LLPounceableStatic that + // we believe is NOT YET CONSTRUCTED. This models the scenario in + // which a constructor in another translation unit runs before + // constructors in this one. We very specifically want callWhenReady() + // to work even in that case: we need the LLPounceableQueueImpl to be + // initialized even if the LLPounceable itself is not. + gForward.callWhenReady(boost::bind(setter, &static_check, _1)); + } +} nqcall; +// When this declaration is processed, we should enqueue the +// setter(&static_check, _1) call for when gForward is set non-NULL. Needless +// to remark, we want this call not to crash. + +// Now declare gForward. Its constructor should not run until after nqcall's. +LLPounceable<Data*, LLPounceableStatic> gForward; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llpounceable_data + { + }; + typedef test_group<llpounceable_data> llpounceable_group; + typedef llpounceable_group::object object; + llpounceable_group llpounceablegrp("llpounceable"); + + template<> template<> + void object::test<1>() + { + set_test_name("LLPounceableStatic out-of-order test"); + // LLPounceable<T, LLPounceableStatic>::callWhenReady() must work even + // before LLPounceable's constructor runs. That's the whole point of + // implementing it with an LLSingleton queue. This models (say) + // LLPounceableStatic<LLMessageSystem*, LLPounceableStatic>. + ensure("static_check should still be null", ! static_check); + Data myData("test<1>"); + gForward = &myData; // should run setter + ensure_equals("static_check should be &myData", static_check, &myData); + } + + template<> template<> + void object::test<2>() + { + set_test_name("LLPounceableQueue different queues"); + // We expect that LLPounceable<T, LLPounceableQueue> should have + // different queues because that specialization stores the queue + // directly in the LLPounceable instance. + Data *aptr = 0, *bptr = 0; + LLPounceable<Data*> a, b; + a.callWhenReady(boost::bind(setter, &aptr, _1)); + b.callWhenReady(boost::bind(setter, &bptr, _1)); + ensure("aptr should be null", ! aptr); + ensure("bptr should be null", ! bptr); + Data adata("a"), bdata("b"); + a = &adata; + ensure_equals("aptr should be &adata", aptr, &adata); + // but we haven't yet set b + ensure("bptr should still be null", !bptr); + b = &bdata; + ensure_equals("bptr should be &bdata", bptr, &bdata); + } + + template<> template<> + void object::test<3>() + { + set_test_name("LLPounceableStatic different queues"); + // LLPounceable<T, LLPounceableStatic> should also have a distinct + // queue for each instance, but that engages an additional map lookup + // because there's only one LLSingleton for each T. + Data *aptr = 0, *bptr = 0; + LLPounceable<Data*, LLPounceableStatic> a, b; + a.callWhenReady(boost::bind(setter, &aptr, _1)); + b.callWhenReady(boost::bind(setter, &bptr, _1)); + ensure("aptr should be null", ! aptr); + ensure("bptr should be null", ! bptr); + Data adata("a"), bdata("b"); + a = &adata; + ensure_equals("aptr should be &adata", aptr, &adata); + // but we haven't yet set b + ensure("bptr should still be null", !bptr); + b = &bdata; + ensure_equals("bptr should be &bdata", bptr, &bdata); + } + + template<> template<> + void object::test<4>() + { + set_test_name("LLPounceable<T> looks like T"); + // We want LLPounceable<T, TAG> to be drop-in replaceable for a plain + // T for read constructs. In particular, it should behave like a dumb + // pointer -- and with zero abstraction cost for such usage. + Data* aptr = 0; + Data a("a"); + // should be able to initialize a pounceable (when its constructor + // runs) + LLPounceable<Data*> pounceable(&a); + // should be able to pass LLPounceable<T> to function accepting T + setter(&aptr, pounceable); + ensure_equals("aptr should be &a", aptr, &a); + // should be able to dereference with * + ensure_equals("deref with *", (*pounceable).mData, "a"); + // should be able to dereference with -> + ensure_equals("deref with ->", pounceable->mData, "a"); + // bool operations + ensure("test with operator bool()", pounceable); + ensure("test with operator !()", ! (! pounceable)); + } + + template<> template<> + void object::test<5>() + { + set_test_name("Multiple callWhenReady() queue items"); + Data *p1 = 0, *p2 = 0, *p3 = 0; + Data a("a"); + LLPounceable<Data*> pounceable; + // queue up a couple setter() calls for later + pounceable.callWhenReady(boost::bind(setter, &p1, _1)); + pounceable.callWhenReady(boost::bind(setter, &p2, _1)); + // should still be pending + ensure("p1 should be null", !p1); + ensure("p2 should be null", !p2); + ensure("p3 should be null", !p3); + pounceable = 0; + // assigning a new empty value shouldn't flush the queue + ensure("p1 should still be null", !p1); + ensure("p2 should still be null", !p2); + ensure("p3 should still be null", !p3); + // using whichever syntax + pounceable.reset(0); + // try to make ensure messages distinct... tough to pin down which + // ensure() failed if multiple ensure() calls in the same test<n> have + // the same message! + ensure("p1 should again be null", !p1); + ensure("p2 should again be null", !p2); + ensure("p3 should again be null", !p3); + pounceable.reset(&a); // should flush queue + ensure_equals("p1 should be &a", p1, &a); + ensure_equals("p2 should be &a", p2, &a); + ensure("p3 still not set", !p3); + // immediate call + pounceable.callWhenReady(boost::bind(setter, &p3, _1)); + ensure_equals("p3 should be &a", p3, &a); + } + + template<> template<> + void object::test<6>() + { + set_test_name("queue order"); + std::string data; + LLPounceable<std::string*> pounceable; + pounceable.callWhenReady(boost::bind(append, _1, "a")); + pounceable.callWhenReady(boost::bind(append, _1, "b")); + pounceable.callWhenReady(boost::bind(append, _1, "c")); + pounceable = &data; + ensure_equals("callWhenReady() must preserve chronological order", + data, "abc"); + + std::string data2; + pounceable = NULL; + pounceable.callWhenReady(boost::bind(append, _1, "d")); + pounceable.callWhenReady(boost::bind(append, _1, "e")); + pounceable.callWhenReady(boost::bind(append, _1, "f")); + pounceable = &data2; + ensure_equals("LLPounceable must reset queue when fired", + data2, "def"); + } + + template<> template<> + void object::test<7>() + { + set_test_name("compile-fail test, uncomment to check"); + // The following declaration should fail: only LLPounceableQueue and + // LLPounceableStatic should work as tags. +// LLPounceable<Data*, int> pounceable; + } +} // namespace tut diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index 385289aefe..56886bc73f 100644 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -30,47 +30,172 @@ #include "llsingleton.h" #include "../test/lltut.h" + +// Capture execution sequence by appending to log string. +std::string sLog; + +#define DECLARE_CLASS(CLS) \ +struct CLS: public LLSingleton<CLS> \ +{ \ + LLSINGLETON(CLS); \ + ~CLS(); \ +public: \ + static enum dep_flag { \ + DEP_NONE, /* no dependency */ \ + DEP_CTOR, /* dependency in ctor */ \ + DEP_INIT /* dependency in initSingleton */ \ + } sDepFlag; \ + \ + void initSingleton(); \ + void cleanupSingleton(); \ +}; \ + \ +CLS::dep_flag CLS::sDepFlag = DEP_NONE + +DECLARE_CLASS(A); +DECLARE_CLASS(B); + +#define DEFINE_MEMBERS(CLS, OTHER) \ +CLS::CLS() \ +{ \ + sLog.append(#CLS); \ + if (sDepFlag == DEP_CTOR) \ + { \ + (void)OTHER::instance(); \ + } \ +} \ + \ +void CLS::initSingleton() \ +{ \ + sLog.append("i" #CLS); \ + if (sDepFlag == DEP_INIT) \ + { \ + (void)OTHER::instance(); \ + } \ +} \ + \ +void CLS::cleanupSingleton() \ +{ \ + sLog.append("x" #CLS); \ +} \ + \ +CLS::~CLS() \ +{ \ + sLog.append("~" #CLS); \ +} + +DEFINE_MEMBERS(A, B) +DEFINE_MEMBERS(B, A) + namespace tut { - struct singleton - { - // We need a class created with the LLSingleton template to test with. - class LLSingletonTest: public LLSingleton<LLSingletonTest> - { - - }; - }; - - typedef test_group<singleton> singleton_t; - typedef singleton_t::object singleton_object_t; - tut::singleton_t tut_singleton("LLSingleton"); - - template<> template<> - void singleton_object_t::test<1>() - { - - } - template<> template<> - void singleton_object_t::test<2>() - { - LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); - ensure(singleton_test); - } - template<> template<> - void singleton_object_t::test<3>() - { - //Construct the instance - LLSingletonTest::getInstance(); - ensure(LLSingletonTest::instanceExists()); - - //Delete the instance - LLSingletonTest::deleteSingleton(); - ensure(LLSingletonTest::destroyed()); - ensure(!LLSingletonTest::instanceExists()); - - //Construct it again. - LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); - ensure(singleton_test); - ensure(LLSingletonTest::instanceExists()); - } + struct singleton + { + // We need a class created with the LLSingleton template to test with. + class LLSingletonTest: public LLSingleton<LLSingletonTest> + { + LLSINGLETON_EMPTY_CTOR(LLSingletonTest); + }; + }; + + typedef test_group<singleton> singleton_t; + typedef singleton_t::object singleton_object_t; + tut::singleton_t tut_singleton("LLSingleton"); + + template<> template<> + void singleton_object_t::test<1>() + { + + } + template<> template<> + void singleton_object_t::test<2>() + { + LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); + ensure(singleton_test); + } + + template<> template<> + void singleton_object_t::test<3>() + { + //Construct the instance + LLSingletonTest::getInstance(); + ensure(LLSingletonTest::instanceExists()); + + //Delete the instance + LLSingletonTest::deleteSingleton(); + ensure(!LLSingletonTest::instanceExists()); + + //Construct it again. + LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); + ensure(singleton_test); + ensure(LLSingletonTest::instanceExists()); + } + +#define TESTS(CLS, OTHER, N0, N1, N2, N3) \ + template<> template<> \ + void singleton_object_t::test<N0>() \ + { \ + set_test_name("just " #CLS); \ + CLS::sDepFlag = CLS::DEP_NONE; \ + OTHER::sDepFlag = OTHER::DEP_NONE; \ + sLog.clear(); \ + \ + (void)CLS::instance(); \ + ensure_equals(sLog, #CLS "i" #CLS); \ + LLSingletonBase::cleanupAll(); \ + ensure_equals(sLog, #CLS "i" #CLS "x" #CLS); \ + LLSingletonBase::deleteAll(); \ + ensure_equals(sLog, #CLS "i" #CLS "x" #CLS "~" #CLS); \ + } \ + \ + template<> template<> \ + void singleton_object_t::test<N1>() \ + { \ + set_test_name(#CLS " ctor depends " #OTHER); \ + CLS::sDepFlag = CLS::DEP_CTOR; \ + OTHER::sDepFlag = OTHER::DEP_NONE; \ + sLog.clear(); \ + \ + (void)CLS::instance(); \ + ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS); \ + LLSingletonBase::cleanupAll(); \ + ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER); \ + LLSingletonBase::deleteAll(); \ + ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ + } \ + \ + template<> template<> \ + void singleton_object_t::test<N2>() \ + { \ + set_test_name(#CLS " init depends " #OTHER); \ + CLS::sDepFlag = CLS::DEP_INIT; \ + OTHER::sDepFlag = OTHER::DEP_NONE; \ + sLog.clear(); \ + \ + (void)CLS::instance(); \ + ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER); \ + LLSingletonBase::cleanupAll(); \ + ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \ + LLSingletonBase::deleteAll(); \ + ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ + } \ + \ + template<> template<> \ + void singleton_object_t::test<N3>() \ + { \ + set_test_name(#CLS " circular init"); \ + CLS::sDepFlag = CLS::DEP_INIT; \ + OTHER::sDepFlag = OTHER::DEP_CTOR; \ + sLog.clear(); \ + \ + (void)CLS::instance(); \ + ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER); \ + LLSingletonBase::cleanupAll(); \ + ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \ + LLSingletonBase::deleteAll(); \ + ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ + } + + TESTS(A, B, 4, 5, 6, 7) + TESTS(B, A, 8, 9, 10, 11) } diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 0bb0348d26..b03ee6eeda 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -93,6 +93,7 @@ target_link_libraries( ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} ${BOOST_THREAD_LIBRARY} + ${BOOST_SYSTEM_LIBRARY} ) # tests @@ -129,8 +130,8 @@ if (LL_TESTS) ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} - ${BOOST_SYSTEM_LIBRARY} ${BOOST_THREAD_LIBRARY} + ${BOOST_SYSTEM_LIBRARY} ) # If http_proxy is in the current environment (e.g. to fetch s3-proxy @@ -197,8 +198,8 @@ endif (DARWIN) ${CURL_LIBRARIES} ${OPENSSL_LIBRARIES} ${CRYPTO_LIBRARIES} - ${BOOST_SYSTEM_LIBRARY} ${BOOST_THREAD_LIBRARY} + ${BOOST_SYSTEM_LIBRARY} ) add_executable(http_texture_load diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index db57869a1b..07cc0e4625 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -568,7 +568,17 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service) // Use the viewer-based thread-safe API which has a // fast/safe check for proxy enable. Would like to // encapsulate this someway... - LLProxy::getInstance()->applyProxySettings(mCurlHandle); + if (LLProxy::instanceExists()) + { + // Make sure proxy won't be initialized from here, + // it might conflict with LLStartUp::startLLProxy() + LLProxy::getInstance()->applyProxySettings(mCurlHandle); + } + else + { + LL_WARNS() << "Proxy is not initialized!" << LL_ENDL; + } + } else if (gpolicy.mHttpProxy.size()) { diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp index bef762f5ce..a310fc0508 100644..100755 --- a/indra/llcorehttp/tests/llcorehttp_test.cpp +++ b/indra/llcorehttp/tests/llcorehttp_test.cpp @@ -46,6 +46,7 @@ #include "test_httprequestqueue.hpp" #include "llproxy.h" +#include "llcleanup.h" unsigned long ssl_thread_id_callback(void); void ssl_locking_callback(int mode, int type, const char * file, int line); @@ -101,7 +102,7 @@ void init_curl() void term_curl() { - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); CRYPTO_set_locking_callback(NULL); for (int i(0); i < ssl_mutex_count; ++i) diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp index 463e55dd7e..6cd7960ecd 100644 --- a/indra/llcorehttp/tests/test_httprequest.hpp +++ b/indra/llcorehttp/tests/test_httprequest.hpp @@ -729,7 +729,7 @@ void HttpRequestTestObjectType::test<7>() #if 0 // defined(WIN32) // Can't do this on any platform anymore, the LL logging system holds // on to memory and produces what looks like memory leaks... - + // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal()); ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); #endif @@ -1459,21 +1459,21 @@ void HttpRequestTestObjectType::test<14>() // references to it after completion of this method. // Create before memory record as the string copy will bump numbers. TestHandler2 handler(this, "handler"); - LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor); - std::string url_base(get_base_url() + "/sleep/"); // path to a 30-second sleep - + LLCore::HttpHandler::ptr_t handlerp(&handler, NoOpDeletor); + std::string url_base(get_base_url() + "/sleep/"); // path to a 30-second sleep + // record the total amount of dynamically allocated memory mMemTotal = GetMemTotal(); mHandlerCalls = 0; HttpRequest * req = NULL; HttpOptions::ptr_t opts; - + try { - // Get singletons created + // Get singletons created HttpRequest::createService(); - + // Start threading early so that thread memory is invariant // over the test. HttpRequest::startThread(); @@ -1482,10 +1482,10 @@ void HttpRequestTestObjectType::test<14>() req = new HttpRequest(); ensure("Memory allocated on construction", mMemTotal < GetMemTotal()); - opts = HttpOptions::ptr_t(new HttpOptions); - opts->setRetries(0); // Don't retry + opts = HttpOptions::ptr_t(new HttpOptions); + opts->setRetries(0); // Don't retry opts->setTimeout(2); - + // Issue a GET that sleeps mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT); HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID, @@ -1494,8 +1494,8 @@ void HttpRequestTestObjectType::test<14>() 0, 0, opts, - HttpHeaders::ptr_t(), - handlerp); + HttpHeaders::ptr_t(), + handlerp); ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID); // Run the notification pump. @@ -1513,7 +1513,7 @@ void HttpRequestTestObjectType::test<14>() mStatus = HttpStatus(); handle = req->requestStopThread(handlerp); ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID); - + // Run the notification pump again count = 0; limit = LOOP_COUNT_LONG; @@ -1535,30 +1535,29 @@ void HttpRequestTestObjectType::test<14>() ensure("Thread actually stopped running", HttpService::isStopped()); // release options - opts.reset(); - + opts.reset(); + // release the request object delete req; req = NULL; // Shut down service HttpRequest::destroyService(); - + ensure("Two handler calls on the way out", 2 == mHandlerCalls); -#if defined(WIN32) - // Can only do this memory test on Windows. On other platforms, - // the LL logging system holds on to memory and produces what looks - // like memory leaks... - - // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal()); +#if 0 // defined(WIN32) + // Can't do this on any platform anymore, the LL logging system holds + // on to memory and produces what looks like memory leaks... + + // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal()); ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); #endif } catch (...) { stop_thread(req); - opts.reset(); + opts.reset(); delete req; HttpRequest::destroyService(); throw; @@ -3065,12 +3064,11 @@ void HttpRequestTestObjectType::test<22>() // Shut down service HttpRequest::destroyService(); - -#if defined(WIN32) - // Can only do this memory test on Windows. On other platforms, - // the LL logging system holds on to memory and produces what looks - // like memory leaks... - + +#if 0 // defined(WIN32) + // Can't do this on any platform anymore, the LL logging system holds + // on to memory and produces what looks like memory leaks... + // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal()); ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); #endif @@ -3195,12 +3193,11 @@ void HttpRequestTestObjectType::test<23>() // Shut down service HttpRequest::destroyService(); - -#if defined(WIN32) - // Can only do this memory test on Windows. On other platforms, - // the LL logging system holds on to memory and produces what looks - // like memory leaks... - + +#if 0 // defined(WIN32) + // Can't do this on any platform anymore, the LL logging system holds + // on to memory and produces what looks like memory leaks... + // printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal()); ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal()); #endif diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py index 6c5f37d407..493143641b 100755 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py @@ -34,16 +34,19 @@ import sys import time import select import getopt -from threading import Thread try: from cStringIO import StringIO except ImportError: from StringIO import StringIO from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from SocketServer import ThreadingMixIn from llbase.fastest_elementtree import parse as xml_parse from llbase import llsd + +# we're in llcorehttp/tests ; testrunner.py is found in llmessage/tests +sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, + "llmessage", "tests")) + from testrunner import freeport, run, debug, VERBOSE class TestHTTPRequestHandler(BaseHTTPRequestHandler): @@ -269,7 +272,7 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler): # Suppress error output as well pass -class Server(ThreadingMixIn, HTTPServer): +class Server(HTTPServer): # This pernicious flag is on by default in HTTPServer. But proper # operation of freeport() absolutely depends on it being off. allow_reuse_address = False @@ -293,22 +296,26 @@ if __name__ == "__main__": if option == "-V" or option == "--valgrind": do_valgrind = True - # Instantiate a Server(TestHTTPRequestHandler) on the first free port - # in the specified port range. Doing this inline is better than in a - # daemon thread: if it blows up here, we'll get a traceback. If it blew up - # in some other thread, the traceback would get eaten and we'd run the - # subject test program anyway. - httpd, port = freeport(xrange(8000, 8020), - lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler)) + # function to make a server with specified port + make_server = lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler) + + if not sys.platform.startswith("win"): + # Instantiate a Server(TestHTTPRequestHandler) on a port chosen by the + # runtime. + httpd = make_server(0) + else: + # "Then there's Windows" + # Instantiate a Server(TestHTTPRequestHandler) on the first free port + # in the specified port range. + httpd, port = freeport(xrange(8000, 8020), make_server) # Pass the selected port number to the subject test program via the # environment. We don't want to impose requirements on the test program's # command-line parsing -- and anyway, for C++ integration tests, that's # performed in TUT code rather than our own. - os.environ["LL_TEST_PORT"] = str(port) - debug("$LL_TEST_PORT = %s", port) + os.environ["LL_TEST_PORT"] = str(httpd.server_port) + debug("$LL_TEST_PORT = %s", httpd.server_port) if do_valgrind: args = ["valgrind", "--log-file=./valgrind.log"] + args path_search = True - sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), use_path=path_search, *args)) - + sys.exit(run(server_inst=httpd, use_path=path_search, *args)) diff --git a/indra/llcorehttp/tests/testrunner.py b/indra/llcorehttp/tests/testrunner.py deleted file mode 100755 index 9a2de71142..0000000000 --- a/indra/llcorehttp/tests/testrunner.py +++ /dev/null @@ -1,265 +0,0 @@ -#!/usr/bin/env python -"""\ -@file testrunner.py -@author Nat Goodspeed -@date 2009-03-20 -@brief Utilities for writing wrapper scripts for ADD_COMM_BUILD_TEST unit tests - -$LicenseInfo:firstyear=2009&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$ -""" - -from __future__ import with_statement - -import os -import sys -import re -import errno -import socket - -VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "0") # default to quiet -# Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if -# that construct actually turns on verbosity... -VERBOSE = not re.match(r"(0|off|false|quiet)$", VERBOSE, re.IGNORECASE) - -if VERBOSE: - def debug(fmt, *args): - print fmt % args - sys.stdout.flush() -else: - debug = lambda *args: None - -def freeport(portlist, expr): - """ - Find a free server port to use. Specifically, evaluate 'expr' (a - callable(port)) until it stops raising EADDRINUSE exception. - - Pass: - - portlist: an iterable (e.g. xrange()) of ports to try. If you exhaust the - range, freeport() lets the socket.error exception propagate. If you want - unbounded, you could pass itertools.count(baseport), though of course in - practice the ceiling is 2^16-1 anyway. But it seems prudent to constrain - the range much more sharply: if we're iterating an absurd number of times, - probably something else is wrong. - - expr: a callable accepting a port number, specifically one of the items - from portlist. If calling that callable raises socket.error with - EADDRINUSE, freeport() retrieves the next item from portlist and retries. - - Returns: (expr(port), port) - - port: the value from portlist for which expr(port) succeeded - - Raises: - - Any exception raised by expr(port) other than EADDRINUSE. - - socket.error if, for every item from portlist, expr(port) raises - socket.error. The exception you see is the one from the last item in - portlist. - - StopIteration if portlist is completely empty. - - Example: - - class Server(HTTPServer): - # If you use BaseHTTPServer.HTTPServer, turning off this flag is - # essential for proper operation of freeport()! - allow_reuse_address = False - # ... - server, port = freeport(xrange(8000, 8010), - lambda port: Server(("localhost", port), - MyRequestHandler)) - # pass 'port' to client code - # call server.serve_forever() - """ - try: - # If portlist is completely empty, let StopIteration propagate: that's an - # error because we can't return meaningful values. We have no 'port', - # therefore no 'expr(port)'. - portiter = iter(portlist) - port = portiter.next() - - while True: - try: - # If this value of port works, return as promised. - value = expr(port) - - except socket.error, err: - # Anything other than 'Address already in use', propagate - if err.args[0] != errno.EADDRINUSE: - raise - - # Here we want the next port from portiter. But on StopIteration, - # we want to raise the original exception rather than - # StopIteration. So save the original exc_info(). - type, value, tb = sys.exc_info() - try: - try: - port = portiter.next() - except StopIteration: - raise type, value, tb - finally: - # Clean up local traceback, see docs for sys.exc_info() - del tb - - else: - debug("freeport() returning %s on port %s", value, port) - return value, port - - # Recap of the control flow above: - # If expr(port) doesn't raise, return as promised. - # If expr(port) raises anything but EADDRINUSE, propagate that - # exception. - # If portiter.next() raises StopIteration -- that is, if the port - # value we just passed to expr(port) was the last available -- reraise - # the EADDRINUSE exception. - # If we've actually arrived at this point, portiter.next() delivered a - # new port value. Loop back to pass that to expr(port). - - except Exception, err: - debug("*** freeport() raising %s: %s", err.__class__.__name__, err) - raise - -def run(*args, **kwds): - """All positional arguments collectively form a command line, executed as - a synchronous child process. - In addition, pass server=new_thread_instance as an explicit keyword (to - differentiate it from an additional command-line argument). - new_thread_instance should be an instantiated but not yet started Thread - subclass instance, e.g.: - run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd")) - """ - # If there's no server= keyword arg, don't start a server thread: simply - # run a child process. - try: - thread = kwds.pop("server") - except KeyError: - pass - else: - # Start server thread. Note that this and all other comm server - # threads should be daemon threads: we'll let them run "forever," - # confident that the whole process will terminate when the main thread - # terminates, which will be when the child process terminates. - thread.setDaemon(True) - thread.start() - # choice of os.spawnv(): - # - [v vs. l] pass a list of args vs. individual arguments, - # - [no p] don't use the PATH because we specifically want to invoke the - # executable passed as our first arg, - # - [no e] child should inherit this process's environment. - debug("Running %s...", " ".join(args)) - if kwds.get("use_path", False): - rc = os.spawnvp(os.P_WAIT, args[0], args) - else: - rc = os.spawnv(os.P_WAIT, args[0], args) - debug("%s returned %s", args[0], rc) - return rc - -# **************************************************************************** -# test code -- manual at this point, see SWAT-564 -# **************************************************************************** -def test_freeport(): - # ------------------------------- Helpers -------------------------------- - from contextlib import contextmanager - # helper Context Manager for expecting an exception - # with exc(SomeError): - # raise SomeError() - # raises AssertionError otherwise. - @contextmanager - def exc(exception_class, *args): - try: - yield - except exception_class, err: - for i, expected_arg in enumerate(args): - assert expected_arg == err.args[i], \ - "Raised %s, but args[%s] is %r instead of %r" % \ - (err.__class__.__name__, i, err.args[i], expected_arg) - print "Caught expected exception %s(%s)" % \ - (err.__class__.__name__, ', '.join(repr(arg) for arg in err.args)) - else: - assert False, "Failed to raise " + exception_class.__class__.__name__ - - # helper to raise specified exception - def raiser(exception): - raise exception - - # the usual - def assert_equals(a, b): - assert a == b, "%r != %r" % (a, b) - - # ------------------------ Sanity check the above ------------------------ - class SomeError(Exception): pass - # Without extra args, accept any err.args value - with exc(SomeError): - raiser(SomeError("abc")) - # With extra args, accept only the specified value - with exc(SomeError, "abc"): - raiser(SomeError("abc")) - with exc(AssertionError): - with exc(SomeError, "abc"): - raiser(SomeError("def")) - with exc(AssertionError): - with exc(socket.error, errno.EADDRINUSE): - raiser(socket.error(errno.ECONNREFUSED, 'Connection refused')) - - # ----------- freeport() without engaging socket functionality ----------- - # If portlist is empty, freeport() raises StopIteration. - with exc(StopIteration): - freeport([], None) - - assert_equals(freeport([17], str), ("17", 17)) - - # This is the magic exception that should prompt us to retry - inuse = socket.error(errno.EADDRINUSE, 'Address already in use') - # Get the iterator to our ports list so we can check later if we've used all - ports = iter(xrange(5)) - with exc(socket.error, errno.EADDRINUSE): - freeport(ports, lambda port: raiser(inuse)) - # did we entirely exhaust 'ports'? - with exc(StopIteration): - ports.next() - - ports = iter(xrange(2)) - # Any exception but EADDRINUSE should quit immediately - with exc(SomeError): - freeport(ports, lambda port: raiser(SomeError())) - assert_equals(ports.next(), 1) - - # ----------- freeport() with platform-dependent socket stuff ------------ - # This is what we should've had unit tests to begin with (see CHOP-661). - def newbind(port): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.bind(('127.0.0.1', port)) - return sock - - bound0, port0 = freeport(xrange(7777, 7780), newbind) - assert_equals(port0, 7777) - bound1, port1 = freeport(xrange(7777, 7780), newbind) - assert_equals(port1, 7778) - bound2, port2 = freeport(xrange(7777, 7780), newbind) - assert_equals(port2, 7779) - with exc(socket.error, errno.EADDRINUSE): - bound3, port3 = freeport(xrange(7777, 7780), newbind) - -if __name__ == "__main__": - test_freeport() diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index dfb344c908..dca49be051 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -45,6 +45,7 @@ #include "llhttpsdhandler.h" #include "httpcommon.h" #include "httpresponse.h" +#include "llcleanup.h" #include <curl/curl.h> #include <openssl/crypto.h> @@ -623,7 +624,7 @@ void LLCrashLogger::commonCleanup() { term_curl(); LLError::logToFile(""); //close crashreport.log - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); } void LLCrashLogger::init_curl() diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index f71607096c..a07ea14621 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -705,18 +705,21 @@ void LLImageBase::deleteData() // virtual U8* LLImageBase::allocateData(S32 size) { + //make this function thread-safe. + static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16; //256 MB + mBadBufferAllocation = false; + if (size < 0) { size = mWidth * mHeight * mComponents; if (size <= 0) { - LL_ERRS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL; + LL_WARNS() << llformat("LLImageBase::allocateData called with bad dimensions: %dx%dx%d",mWidth,mHeight,(S32)mComponents) << LL_ENDL; + mBadBufferAllocation = true; } - } - - //make this function thread-safe. - static const U32 MAX_BUFFER_SIZE = 4096 * 4096 * 16 ; //256 MB - if (size < 1 || size > MAX_BUFFER_SIZE) + } + + if (!mBadBufferAllocation && (size < 1 || size > MAX_BUFFER_SIZE)) { LL_INFOS() << "width: " << mWidth << " height: " << mHeight << " components: " << mComponents << LL_ENDL ; if(mAllowOverSize) @@ -725,25 +728,31 @@ U8* LLImageBase::allocateData(S32 size) } else { - LL_ERRS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL; + LL_WARNS() << "LLImageBase::allocateData: bad size: " << size << LL_ENDL; + mBadBufferAllocation = true; } } - if (!mData || size != mDataSize) + + if (!mBadBufferAllocation && (!mData || size != mDataSize)) { deleteData(); // virtual - mBadBufferAllocation = false ; mData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); if (!mData) { LL_WARNS() << "Failed to allocate image data size [" << size << "]" << LL_ENDL; - size = 0 ; - mWidth = mHeight = 0 ; - mBadBufferAllocation = true ; + mBadBufferAllocation = true; } - mDataSize = size; - claimMem(mDataSize); } + if (mBadBufferAllocation) + { + size = 0; + mWidth = mHeight = 0; + mData = NULL; + } + mDataSize = size; + claimMem(mDataSize); + return mData; } @@ -791,7 +800,7 @@ U8* LLImageBase::getData() return mData; } -bool LLImageBase::isBufferInvalid() +bool LLImageBase::isBufferInvalid() const { return mBadBufferAllocation || mData == NULL ; } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 9cc7431a9c..d0bd4a2aef 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -141,7 +141,7 @@ public: const U8 *getData() const ; U8 *getData() ; - bool isBufferInvalid() ; + bool isBufferInvalid() const; void setSize(S32 width, S32 height, S32 ncomponents); U8* allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 size = -1); // setSize() + allocateData() diff --git a/indra/llinventory/lleconomy.cpp b/indra/llinventory/lleconomy.cpp index e10402196f..2a023d8c24 100644 --- a/indra/llinventory/lleconomy.cpp +++ b/indra/llinventory/lleconomy.cpp @@ -31,7 +31,7 @@ #include "v3math.h" -LLGlobalEconomy::LLGlobalEconomy() +LLBaseEconomy::LLBaseEconomy() : mObjectCount( -1 ), mObjectCapacity( -1 ), mPriceObjectClaim( -1 ), @@ -45,15 +45,15 @@ LLGlobalEconomy::LLGlobalEconomy() mPriceGroupCreate( -1 ) { } -LLGlobalEconomy::~LLGlobalEconomy() +LLBaseEconomy::~LLBaseEconomy() { } -void LLGlobalEconomy::addObserver(LLEconomyObserver* observer) +void LLBaseEconomy::addObserver(LLEconomyObserver* observer) { mObservers.push_back(observer); } -void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer) +void LLBaseEconomy::removeObserver(LLEconomyObserver* observer) { std::list<LLEconomyObserver*>::iterator it = std::find(mObservers.begin(), mObservers.end(), observer); @@ -63,7 +63,7 @@ void LLGlobalEconomy::removeObserver(LLEconomyObserver* observer) } } -void LLGlobalEconomy::notifyObservers() +void LLBaseEconomy::notifyObservers() { for (std::list<LLEconomyObserver*>::iterator it = mObservers.begin(); it != mObservers.end(); @@ -74,7 +74,7 @@ void LLGlobalEconomy::notifyObservers() } // static -void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data) +void LLBaseEconomy::processEconomyData(LLMessageSystem *msg, LLBaseEconomy* econ_data) { S32 i; F32 f; @@ -117,7 +117,7 @@ void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data->notifyObservers(); } -S32 LLGlobalEconomy::calculateTeleportCost(F32 distance) const +S32 LLBaseEconomy::calculateTeleportCost(F32 distance) const { S32 min_cost = getTeleportMinPrice(); F32 exponent = getTeleportPriceExponent(); @@ -135,13 +135,13 @@ S32 LLGlobalEconomy::calculateTeleportCost(F32 distance) const return cost; } -S32 LLGlobalEconomy::calculateLightRent(const LLVector3& object_size) const +S32 LLBaseEconomy::calculateLightRent(const LLVector3& object_size) const { F32 intensity_mod = llmax(object_size.magVec(), 1.f); return (S32)(intensity_mod * getPriceRentLight()); } -void LLGlobalEconomy::print() +void LLBaseEconomy::print() { LL_INFOS() << "Global Economy Settings: " << LL_ENDL; LL_INFOS() << "Object Capacity: " << mObjectCapacity << LL_ENDL; @@ -159,8 +159,7 @@ void LLGlobalEconomy::print() } LLRegionEconomy::LLRegionEconomy() -: LLGlobalEconomy(), - mPriceObjectRent( -1.f ), +: mPriceObjectRent( -1.f ), mPriceObjectScaleFactor( -1.f ), mEnergyEfficiency( -1.f ), mBasePriceParcelClaimDefault(-1), @@ -187,7 +186,7 @@ void LLRegionEconomy::processEconomyData(LLMessageSystem *msg, void** user_data) LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; - LLGlobalEconomy::processEconomyData(msg, this_ptr); + LLBaseEconomy::processEconomyData(msg, this_ptr); msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelClaim, i); this_ptr->setBasePriceParcelClaimDefault(i); @@ -252,7 +251,7 @@ S32 LLRegionEconomy::getPriceParcelRent() const void LLRegionEconomy::print() { - this->LLGlobalEconomy::print(); + this->LLBaseEconomy::print(); LL_INFOS() << "Region Economy Settings: " << LL_ENDL; LL_INFOS() << "Land (square meters): " << mAreaTotal << LL_ENDL; diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index 47fcf688a2..cdfde171c1 100644 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -42,18 +42,11 @@ public: virtual void onEconomyDataChange() = 0; }; -class LLGlobalEconomy +class LLBaseEconomy { public: - LLGlobalEconomy(); - virtual ~LLGlobalEconomy(); - - // This class defines its singleton internally as a typedef instead of inheriting from - // LLSingleton like most others because the LLRegionEconomy sub-class might also - // become a singleton and this pattern will more easily disambiguate them. - typedef LLSingleton<LLGlobalEconomy> Singleton; - - void initSingleton() { } + LLBaseEconomy(); + virtual ~LLBaseEconomy(); virtual void print(); @@ -61,7 +54,7 @@ public: void removeObserver(LLEconomyObserver* observer); void notifyObservers(); - static void processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data); + static void processEconomyData(LLMessageSystem *msg, LLBaseEconomy* econ_data); S32 calculateTeleportCost(F32 distance) const; S32 calculateLightRent(const LLVector3& object_size) const; @@ -108,8 +101,12 @@ private: std::list<LLEconomyObserver*> mObservers; }; +class LLGlobalEconomy: public LLSingleton<LLGlobalEconomy>, public LLBaseEconomy +{ + LLSINGLETON_EMPTY_CTOR(LLGlobalEconomy); +}; -class LLRegionEconomy : public LLGlobalEconomy +class LLRegionEconomy : public LLBaseEconomy { public: LLRegionEconomy(); diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 86aca77de8..b0daf639fa 100644 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -51,8 +51,7 @@ struct FolderEntry : public LLDictionaryEntry class LLFolderDictionary : public LLSingleton<LLFolderDictionary>, public LLDictionary<LLFolderType::EType, FolderEntry> { -public: - LLFolderDictionary(); + LLSINGLETON(LLFolderDictionary); protected: virtual LLFolderType::EType notFound() const { diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 8807b36117..d1e6807f52 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -63,8 +63,7 @@ struct InventoryEntry : public LLDictionaryEntry class LLInventoryDictionary : public LLSingleton<LLInventoryDictionary>, public LLDictionary<LLInventoryType::EType, InventoryEntry> { -public: - LLInventoryDictionary(); + LLSINGLETON(LLInventoryDictionary); }; LLInventoryDictionary::LLInventoryDictionary() diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 93b9f22b25..692284e04b 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -254,6 +254,11 @@ inline int round_int(double x) } #endif // BOGUS_ROUND +inline F64 ll_round(const F64 val) +{ + return F64(floor(val + 0.5f)); +} + inline F32 ll_round( F32 val, F32 nearest ) { return F32(floor(val * (1.0f / nearest) + 0.5f)) * nearest; diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h index 497367b80c..7d0e83180c 100644 --- a/indra/llmessage/llcoproceduremanager.h +++ b/indra/llmessage/llcoproceduremanager.h @@ -37,7 +37,8 @@ class LLCoprocedurePool; class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > { - friend class LLSingleton < LLCoprocedureManager > ; + LLSINGLETON(LLCoprocedureManager); + virtual ~LLCoprocedureManager(); public: typedef boost::function<U32(const std::string &)> SettingQuery_t; @@ -45,9 +46,6 @@ public: typedef boost::function<void(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t; - LLCoprocedureManager(); - virtual ~LLCoprocedureManager(); - /// Places the coprocedure on the queue for processing. /// /// @param name Is used for debugging and should identify this coroutine. diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 1002b33f80..8ee7080d38 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -43,7 +43,7 @@ class LLUUID; class LLExperienceCache: public LLSingleton < LLExperienceCache > { - friend class LLSingleton < LLExperienceCache > ; + LLSINGLETON(LLExperienceCache); public: typedef boost::function<std::string(const std::string &)> CapabilityQuery_t; @@ -103,7 +103,6 @@ public: static const int PROPERTY_SUSPENDED; // 1 << 7 private: - LLExperienceCache(); virtual ~LLExperienceCache(); virtual void initSingleton(); diff --git a/indra/llmessage/llproxy.h b/indra/llmessage/llproxy.h index bd23dd39de..688dff7c83 100644 --- a/indra/llmessage/llproxy.h +++ b/indra/llmessage/llproxy.h @@ -218,14 +218,14 @@ enum LLSocks5AuthType */ class LLProxy: public LLSingleton<LLProxy> { - LOG_CLASS(LLProxy); -public: /*########################################################################################### METHODS THAT DO NOT LOCK mProxyMutex! ###########################################################################################*/ // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only. - LLProxy(); + LLSINGLETON(LLProxy); + LOG_CLASS(LLProxy); +public: // Static check for enabled status for UDP packets. Call from main thread only. static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; } @@ -239,9 +239,11 @@ public: /*########################################################################################### METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED! ###########################################################################################*/ +private: // Destructor, closes open connections. Do not call directly, use cleanupClass(). ~LLProxy(); +public: // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be // destroyed before the call to apr_terminate. Call from main thread only. static void cleanupClass(); diff --git a/indra/llmessage/llxfer_file.cpp b/indra/llmessage/llxfer_file.cpp index 257a13f277..8e2ed890e7 100644 --- a/indra/llmessage/llxfer_file.cpp +++ b/indra/llmessage/llxfer_file.cpp @@ -98,12 +98,12 @@ void LLXfer_File::cleanup () mFp = NULL; } - LLFile::remove(mTempFilename); + LLFile::remove(mTempFilename, ENOENT); if (mDeleteLocalOnCompletion) { LL_DEBUGS() << "Removing file: " << mLocalFilename << LL_ENDL; - LLFile::remove(mLocalFilename); + LLFile::remove(mLocalFilename, ENOENT); } else { @@ -321,7 +321,7 @@ S32 LLXfer_File::processEOF() mCallbackResult = flushval; } - LLFile::remove(mLocalFilename); + LLFile::remove(mLocalFilename, ENOENT); if (!mCallbackResult) { diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index 272dbbc785..2ceb64ce8f 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -444,7 +444,7 @@ U64 LLXferManager::requestFile(const std::string& local_filename, && (remote_filename.substr(remote_filename.length()-4) == ".tmp") && gDirUtilp->fileExists(local_filename)) { - LLFile::remove(local_filename); + LLFile::remove(local_filename, ENOENT); } xfer_id = getNextID(); ((LLXfer_File *)xferp)->initializeRequest( diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 290b67feb3..6ef4025ab1 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -76,6 +76,7 @@ #include "v4math.h" #include "lltransfertargetvfile.h" #include "llcorehttputil.h" +#include "llpounceable.h" // Constants //const char* MESSAGE_LOG_FILENAME = "message.log"; @@ -1724,7 +1725,9 @@ std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg) return s; } -LLMessageSystem *gMessageSystem = NULL; +// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.) +// callback registrations for when gMessageSystem is first assigned +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem; // update appropriate ping info void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/) @@ -2641,7 +2644,7 @@ void end_messaging_system(bool print_summary) LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL; } - delete gMessageSystem; + delete static_cast<LLMessageSystem*>(gMessageSystem); gMessageSystem = NULL; } } diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 133db620e6..f6c5d9e228 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -60,6 +60,7 @@ #include "llstoredmessage.h" #include "boost/function.hpp" +#include "llpounceable.h" const U32 MESSAGE_MAX_STRINGS_LENGTH = 64; const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; @@ -68,10 +69,10 @@ const S32 MESSAGE_MAX_PER_FRAME = 400; class LLMessageStringTable : public LLSingleton<LLMessageStringTable> { -public: - LLMessageStringTable(); + LLSINGLETON(LLMessageStringTable); ~LLMessageStringTable(); +public: char *getString(const char *str); U32 mUsed; @@ -832,7 +833,7 @@ private: // external hook into messaging system -extern LLMessageSystem *gMessageSystem; +extern LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem; // Must specific overall system version, which is used to determine // if a patch is available in the message template checksum verification. diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index a32bfa59ce..9356a14f1f 100644 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -42,6 +42,7 @@ #include "lliosocket.h" #include "stringize.h" +#include "llcleanup.h" namespace tut { @@ -66,7 +67,7 @@ namespace tut ~HTTPClientTestData() { delete mClientPump; - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); apr_pool_destroy(mPool); } diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp index 3b04530c1a..e20f61b73f 100644 --- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp +++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp @@ -31,11 +31,12 @@ #include "llhost.h" #include "message.h" #include "llsd.h" +#include "llpounceable.h" #include "llhost.cpp" // Needed for copy operator #include "net.cpp" // Needed by LLHost. -LLMessageSystem * gMessageSystem = NULL; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem; // sensor test doubles bool gClearRecvWasCalled = false; diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp index 55748ad27e..41f982a7e2 100644 --- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp +++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -33,8 +33,9 @@ #include "message.h" #include "llmessageconfig.h" #include "llhttpnode_stub.cpp" +#include "llpounceable.h" -LLMessageSystem* gMessageSystem = NULL; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem; LLMessageConfig::SenderTrust LLMessageConfig::getSenderTrustedness(const std::string& msg_name) diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 5eb739393f..5986524342 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -44,7 +44,7 @@ // init time. Use the lazy, on-demand initialization we get from LLSingleton. class NetworkIO: public LLSingleton<NetworkIO> { -public: + LLSINGLETON(NetworkIO); NetworkIO(): mServicePump(NULL), mDone(false) @@ -69,6 +69,7 @@ public: boost::bind(&NetworkIO::done, this, _1)); } +public: bool pump(F32 timeout=10) { // Reset the done flag so we don't pop out prematurely diff --git a/indra/llmessage/tests/test_llsdmessage_peer.py b/indra/llmessage/tests/test_llsdmessage_peer.py index bac18fa374..9cd2959ea1 100755 --- a/indra/llmessage/tests/test_llsdmessage_peer.py +++ b/indra/llmessage/tests/test_llsdmessage_peer.py @@ -31,7 +31,6 @@ $/LicenseInfo$ import os import sys -from threading import Thread from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler from llbase.fastest_elementtree import parse as xml_parse @@ -155,17 +154,23 @@ class Server(HTTPServer): allow_reuse_address = False if __name__ == "__main__": - # Instantiate a Server(TestHTTPRequestHandler) on the first free port - # in the specified port range. Doing this inline is better than in a - # daemon thread: if it blows up here, we'll get a traceback. If it blew up - # in some other thread, the traceback would get eaten and we'd run the - # subject test program anyway. - httpd, port = freeport(xrange(8000, 8020), - lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler)) + # function to make a server with specified port + make_server = lambda port: Server(('127.0.0.1', port), TestHTTPRequestHandler) + + if not sys.platform.startswith("win"): + # Instantiate a Server(TestHTTPRequestHandler) on a port chosen by the + # runtime. + httpd = make_server(0) + else: + # "Then there's Windows" + # Instantiate a Server(TestHTTPRequestHandler) on the first free port + # in the specified port range. + httpd, port = freeport(xrange(8000, 8020), make_server) + # Pass the selected port number to the subject test program via the # environment. We don't want to impose requirements on the test program's # command-line parsing -- and anyway, for C++ integration tests, that's # performed in TUT code rather than our own. - os.environ["PORT"] = str(port) - debug("$PORT = %s", port) - sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), *sys.argv[1:])) + os.environ["PORT"] = str(httpd.server_port) + debug("$PORT = %s", httpd.server_port) + sys.exit(run(server_inst=httpd, *sys.argv[1:])) diff --git a/indra/llmessage/tests/testrunner.py b/indra/llmessage/tests/testrunner.py index 5b9beb359b..c25945067e 100755 --- a/indra/llmessage/tests/testrunner.py +++ b/indra/llmessage/tests/testrunner.py @@ -27,13 +27,12 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA $/LicenseInfo$ """ -from __future__ import with_statement - import os import sys import re import errno import socket +import subprocess VERBOSE = os.environ.get("INTEGRATION_TEST_VERBOSE", "0") # default to quiet # Support usage such as INTEGRATION_TEST_VERBOSE=off -- distressing to user if @@ -47,6 +46,9 @@ if VERBOSE: else: debug = lambda *args: None +class Error(Exception): + pass + def freeport(portlist, expr): """ Find a free server port to use. Specifically, evaluate 'expr' (a @@ -141,34 +143,73 @@ def freeport(portlist, expr): raise def run(*args, **kwds): - """All positional arguments collectively form a command line, executed as - a synchronous child process. - In addition, pass server=new_thread_instance as an explicit keyword (to - differentiate it from an additional command-line argument). - new_thread_instance should be an instantiated but not yet started Thread - subclass instance, e.g.: - run("python", "-c", 'print "Hello, world!"', server=TestHTTPServer(name="httpd")) """ - # If there's no server= keyword arg, don't start a server thread: simply - # run a child process. + Run a specified command as a synchronous child process, optionally + launching a server Thread during the run. + + All positional arguments collectively form a command line. The first + positional argument names the program file to execute. + + Returns the termination code of the child process. + + In addition, you may pass keyword-only arguments: + + use_path=True: allow a simple filename as command and search PATH for that + filename. (This argument is retained for backwards compatibility but is + now the default behavior.) + + server_inst: an instance of a subclass of SocketServer.BaseServer. + + When you pass server_inst, run() calls its handle_request() method in a + loop until the child process terminates. + """ + # server= keyword arg is discontinued try: thread = kwds.pop("server") except KeyError: pass else: - # Start server thread. Note that this and all other comm server - # threads should be daemon threads: we'll let them run "forever," - # confident that the whole process will terminate when the main thread - # terminates, which will be when the child process terminates. - thread.setDaemon(True) - thread.start() - # choice of os.spawnv(): - # - [v vs. l] pass a list of args vs. individual arguments, - # - [no p] don't use the PATH because we specifically want to invoke the - # executable passed as our first arg, - # - [no e] child should inherit this process's environment. + raise Error("Obsolete call to testrunner.run(): pass server_inst=, not server=") + debug("Running %s...", " ".join(args)) - rc = os.spawnv(os.P_WAIT, args[0], args) + + try: + server_inst = kwds.pop("server_inst") + except KeyError: + # Without server_inst, this is very simple: just run child process. + rc = subprocess.call(args) + else: + # We're being asked to run a local server while the child process + # runs. We used to launch a daemon thread calling + # server_inst.serve_forever(), then eventually call sys.exit() with + # the daemon thread still running -- but in recent versions of Python + # 2, even when you call sys.exit(0), apparently killing the thread + # causes the Python runtime to force the process termination code + # nonzero. So now we avoid the extra thread altogether. + + # SocketServer.BaseServer.handle_request() honors a 'timeout' + # attribute, if it's set to something other than None. + # We pick 0.5 seconds because that's the default poll timeout for + # BaseServer.serve_forever(), which is what we used to use. + server_inst.timeout = 0.5 + + child = subprocess.Popen(args) + while child.poll() is None: + # Setting server_inst.timeout is what keeps this handle_request() + # call from blocking "forever." Interestingly, looping over + # handle_request() with a timeout is very like the implementation + # of serve_forever(). We just check a different flag to break out. + # It might be interesting if handle_request() returned an + # indication of whether it in fact handled a request or timed out. + # Oddly, it doesn't. We could discover that by overriding + # handle_timeout(), whose default implementation does nothing -- + # but in fact we really don't care. All that matters is that we + # regularly poll both the child process and the server socket. + server_inst.handle_request() + # We don't bother to capture the rc returned by child.poll() because + # poll() is already defined to capture that in its returncode attr. + rc = child.returncode + debug("%s returned %s", args[0], rc) return rc diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index d73bdd7693..4f500adefc 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -855,6 +855,8 @@ struct ModelSort bool LLDAELoader::OpenFile(const std::string& filename) { + setLoadState( READING_FILE ); + //no suitable slm exists, load from the .dae file DAE dae; domCOLLADA* dom; @@ -1001,6 +1003,11 @@ bool LLDAELoader::OpenFile(const std::string& filename) std::sort(mModelList.begin(), mModelList.end(), ModelSort()); + if (!mNoNormalize) + { + LLModel::normalizeModels(mModelList); + } + model_list::iterator model_iter = mModelList.begin(); while (model_iter != mModelList.end()) { @@ -2429,8 +2436,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo // ret->sortVolumeFacesByMaterialName(); - bool normalized = false; - int submodelID = 0; // remove all faces that definitely won't fit into one model and submodel limit @@ -2445,12 +2450,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo { // Insure we do this once with the whole gang and not per-model // - if (!normalized && !mNoNormalize) - { - normalized = true; - ret->normalizeVolumeFaces(); - } - ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder); if (!mNoOptimize) diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index db6d00bc2c..0c313e460e 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -178,6 +178,165 @@ void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remain } } +// Shrink group of models to fit +// on a 1x1x1 cube centered at the origin. +void LLModel::normalizeModels(std::vector<LLPointer<LLModel > > model_list) +{ + std::vector<LLPointer<LLModel > >::iterator iter = model_list.begin(); + + LLVector4a min, max; + while (iter != model_list.end() && (*iter)->mVolumeFaces.empty()) + { + iter++; + } + if (iter == model_list.end()) + { + // no models with faces + return; + } + + min = (*iter)->mVolumeFaces[0].mExtents[0]; + max = (*iter)->mVolumeFaces[0].mExtents[1]; + + // Treat models as a group - each model out of 1x1x1 cube + // needs scaling and will affect whole group scale + while (iter != model_list.end()) + { + LLPointer<LLModel> model = *iter++; + + if (model.notNull() && !model->mVolumeFaces.empty()) + { + // For all of the volume faces + // in the model, loop over + // them and see what the extents + // of the volume along each axis. + + for (U32 i = 0; i < model->mVolumeFaces.size(); ++i) + { + LLVolumeFace& face = model->mVolumeFaces[i]; + + update_min_max(min, max, face.mExtents[0]); + update_min_max(min, max, face.mExtents[1]); + + if (face.mTexCoords) + { + LLVector2& min_tc = face.mTexCoordExtents[0]; + LLVector2& max_tc = face.mTexCoordExtents[1]; + + min_tc = face.mTexCoords[0]; + max_tc = face.mTexCoords[0]; + + for (U32 j = 1; j < face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, face.mTexCoords[j]); + } + } + else + { + face.mTexCoordExtents[0].set(0, 0); + face.mTexCoordExtents[1].set(1, 1); + } + } + } + } + + // Now that we have the extents of the model + // we can compute the offset needed to center + // the model at the origin. + + // Compute center of the model + // and make it negative to get translation + // needed to center at origin. + LLVector4a trans; + trans.setAdd(min, max); + trans.mul(-0.5f); + + // Compute the total size along all + // axes of the model. + LLVector4a size; + size.setSub(max, min); + + // Prevent division by zero. + F32 x = size[0]; + F32 y = size[1]; + F32 z = size[2]; + F32 w = size[3]; + if (fabs(x) < F_APPROXIMATELY_ZERO) + { + x = 1.0; + } + if (fabs(y) < F_APPROXIMATELY_ZERO) + { + y = 1.0; + } + if (fabs(z) < F_APPROXIMATELY_ZERO) + { + z = 1.0; + } + size.set(x, y, z, w); + + // Compute scale as reciprocal of size + LLVector4a scale; + scale.splat(1.f); + scale.div(size); + + LLVector4a inv_scale(1.f); + inv_scale.div(scale); + + iter = model_list.begin(); + // apply fixed scale and trans to all models as a single group + while (iter != model_list.end()) + { + LLPointer<LLModel> model = *iter++; + + if (model.isNull() || model->mVolumeFaces.empty()) + { + continue; + } + + for (U32 i = 0; i < model->mVolumeFaces.size(); ++i) + { + LLVolumeFace& face = model->mVolumeFaces[i]; + + // We shrink the extents so + // that they fall within + // the unit cube. + face.mExtents[0].add(trans); + face.mExtents[0].mul(scale); + + face.mExtents[1].add(trans); + face.mExtents[1].mul(scale); + + // For all the positions, we scale + // the positions to fit within the unit cube. + LLVector4a* pos = (LLVector4a*)face.mPositions; + LLVector4a* norm = (LLVector4a*)face.mNormals; + + for (U32 j = 0; j < face.mNumVertices; ++j) + { + pos[j].add(trans); + pos[j].mul(scale); + if (norm && !norm[j].equals3(LLVector4a::getZero())) + { + norm[j].mul(inv_scale); + norm[j].normalize3(); + } + } + } + + // mNormalizedScale is the scale at which + // we would need to multiply the model + // by to get the original size of the + // model instead of the normalized size. + LLVector4a normalized_scale; + normalized_scale.splat(1.f); + normalized_scale.div(scale); + model->mNormalizedScale.set(normalized_scale.getF32ptr()); + model->mNormalizedTranslation.set(trans.getF32ptr()); + model->mNormalizedTranslation *= -1.f; + } +} + // Shrink the model to fit // on a 1x1x1 cube centered at the origin. // The positions and extents diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 097558ef67..755fac9c87 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -176,6 +176,7 @@ public: void addFace(const LLVolumeFace& face); void sortVolumeFacesByMaterialName(); + static void normalizeModels(std::vector<LLPointer<LLModel > > model_list); void normalizeVolumeFaces(); void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); void optimizeVolumeFaces(); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 81a5537f78..20cba68f84 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1267,6 +1267,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S llassert(gGLManager.mInited); stop_glerror(); + if (!imageraw || imageraw->isBufferInvalid()) + { + LL_WARNS() << "Trying to create a texture from invalid image data" << LL_ENDL; + return FALSE; + } + if (discard_level < 0) { llassert(mCurrentDiscardLevel >= 0); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 69420dd0bb..3e7c69611d 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -267,7 +267,14 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) } else { - LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + if (texture) + { + LL_DEBUGS() << "NULL LLTexUnit::bind GL image" << LL_ENDL; + } + else + { + LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + } return false; } } @@ -286,7 +293,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) if(!texture) { - LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL; return false; } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 0fae600a90..31dffdd545 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -448,7 +448,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) else { - GLenum array[] = + static const GLenum array[] = { GL_VERTEX_ARRAY, GL_NORMAL_ARRAY, @@ -456,7 +456,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) GL_COLOR_ARRAY, }; - GLenum mask[] = + static const GLenum mask[] = { MAP_VERTEX, MAP_NORMAL, diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 53720a6044..f8ef5289db 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -361,6 +361,7 @@ LLAccordionCtrlTab::LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&p) { mStoredOpenCloseState = false; mWasStateStored = false; + mSkipChangesOnNotifyParent = false; mDropdownBGColor = LLColor4::white; LLAccordionCtrlTabHeader::Params headerParams; @@ -691,7 +692,7 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info) mExpandedHeight = height; - if(isExpanded()) + if(isExpanded() && !mSkipChangesOnNotifyParent) { LLRect panel_rect = getRect(); panel_rect.setLeftTopAndSize( panel_rect.mLeft, panel_rect.mTop, panel_rect.getWidth(), height); diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 7a78700e0f..0263bce4be 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -195,6 +195,8 @@ public: void setFitPanel( bool fit ) { mFitPanel = true; } bool getFitParent() const { return mFitPanel; } + void setIgnoreResizeNotification(bool ignore) { mSkipChangesOnNotifyParent = ignore;} + protected: void adjustContainerPanel (const LLRect& child_rect); void adjustContainerPanel (); @@ -235,6 +237,7 @@ private: bool mStoredOpenCloseState; bool mWasStateStored; + bool mSkipChangesOnNotifyParent; bool mSelectionEnabled; diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h index 58d80e2687..a668ac1ac6 100644 --- a/indra/llui/llclipboard.h +++ b/indra/llui/llclipboard.h @@ -48,10 +48,10 @@ class LLClipboard : public LLSingleton<LLClipboard> { -public: - LLClipboard(); + LLSINGLETON(LLClipboard); ~LLClipboard(); +public: // Clears the clipboard void reset(); // Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state) diff --git a/indra/llui/llcommandmanager.h b/indra/llui/llcommandmanager.h index f2f2145953..8cec5e2b24 100644 --- a/indra/llui/llcommandmanager.h +++ b/indra/llui/llcommandmanager.h @@ -173,6 +173,9 @@ private: class LLCommandManager : public LLSingleton<LLCommandManager> { + LLSINGLETON(LLCommandManager); + ~LLCommandManager(); + public: struct Params : public LLInitParam::Block<Params> { @@ -184,9 +187,6 @@ public: } }; - LLCommandManager(); - ~LLCommandManager(); - U32 commandCount() const; LLCommand * getCommand(U32 commandIndex); LLCommand * getCommand(const LLCommandId& commandId); diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index ac92b19977..99267d978a 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -35,7 +35,9 @@ class LLScrollContainer; struct ContainerViewRegistry : public LLChildRegistry<ContainerViewRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(ContainerViewRegistry); +}; class LLContainerView : public LLView { diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 299f5e42d4..5e00bf7f45 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -105,6 +105,81 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null* return true; } +bool LLFlatListView::addItemPairs(pairs_list_t panel_list, bool rearrange /*= true*/) +{ + if (!mItemComparator) + { + LL_WARNS_ONCE() << "No comparator specified for inserting FlatListView items." << LL_ENDL; + return false; + } + if (panel_list.size() == 0) + { + return false; + } + + // presort list so that it will be easier to sort elements into mItemPairs + panel_list.sort(ComparatorAdaptor(*mItemComparator)); + + pairs_const_iterator_t new_pair_it = panel_list.begin(); + item_pair_t* new_pair = *new_pair_it; + pairs_iterator_t pair_it = mItemPairs.begin(); + item_pair_t* item_pair = *pair_it; + + // sort panel_list into mItemPars + while (new_pair_it != panel_list.end() && pair_it != mItemPairs.end()) + { + if (!new_pair->first || new_pair->first->getParent() == mItemsPanel) + { + // iterator already used or we are reusing existing panel + new_pair_it++; + new_pair = *new_pair_it; + } + else if (mItemComparator->compare(new_pair->first, item_pair->first)) + { + LLPanel* panel = new_pair->first; + + mItemPairs.insert(pair_it, new_pair); + mItemsPanel->addChild(panel); + + //_4 is for MASK + panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4)); + panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4)); + // Children don't accept the focus + panel->setTabStop(false); + } + else + { + pair_it++; + item_pair = *pair_it; + } + } + + // Add what is left of panel_list into the end of mItemPairs. + for (; new_pair_it != panel_list.end(); ++new_pair_it) + { + item_pair_t* item_pair = *new_pair_it; + LLPanel *panel = item_pair->first; + if (panel && panel->getParent() != mItemsPanel) + { + mItemPairs.push_back(item_pair); + mItemsPanel->addChild(panel); + + //_4 is for MASK + panel->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, item_pair, _4)); + panel->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, item_pair, _4)); + // Children don't accept the focus + panel->setTabStop(false); + } + } + + if (rearrange) + { + rearrangeItems(); + notifyParentItemsRectChanged(); + } + return true; +} + bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add, const LLSD& value /*= LLUUID::null*/) { @@ -1289,6 +1364,28 @@ void LLFlatListViewEx::setFilterSubString(const std::string& filter_str) } } +void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) +{ + if (!item) return; + + // 0 signifies that filter is matched, + // i.e. we don't hide items that don't support 'match_filter' action, separators etc. + if (0 == item->notify(action)) + { + mHasMatchedItems = true; + item->setVisible(true); + } + else + { + // TODO: implement (re)storing of current selection. + if (!mForceShowingUnmatchedItems) + { + selectItem(item, false); + } + item->setVisible(mForceShowingUnmatchedItems); + } +} + void LLFlatListViewEx::filterItems() { typedef std::vector <LLPanel*> item_panel_list_t; @@ -1309,22 +1406,7 @@ void LLFlatListViewEx::filterItems() iter != iter_end; ++iter) { LLPanel* pItem = (*iter); - // 0 signifies that filter is matched, - // i.e. we don't hide items that don't support 'match_filter' action, separators etc. - if (0 == pItem->notify(action)) - { - mHasMatchedItems = true; - pItem->setVisible(true); - } - else - { - // TODO: implement (re)storing of current selection. - if(!mForceShowingUnmatchedItems) - { - selectItem(pItem, false); - } - pItem->setVisible(mForceShowingUnmatchedItems); - } + updateItemVisibility(pItem, action); } sort(); diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index 92bf429031..230ea200d8 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -351,6 +351,8 @@ protected: virtual bool removeItemPair(item_pair_t* item_pair, bool rearrange); + bool addItemPairs(pairs_list_t panel_list, bool rearrange = true); + /** * Notify parent about changed size of internal controls with "size_changes" action * @@ -480,6 +482,7 @@ public: * Sets up new filter string and filters the list. */ void setFilterSubString(const std::string& filter_str); + std::string getFilterSubString() { return mFilterSubString; } /** * Filters the list, rearranges and notifies parent about shape changes. @@ -503,6 +506,14 @@ protected: */ void updateNoItemsMessage(const std::string& filter_string); + /** + * Applies visibility acording to action and LLFlatListView settings. + * + * @param item - item we are changing + * @param item - action - parameters to determin visibility from + */ + void updateItemVisibility(LLPanel* item, const LLSD &action); + private: std::string mNoFilteredItemsMsg; std::string mNoItemsMsg; diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index f5364f4863..e43974bc52 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -53,14 +53,8 @@ template <typename FUNCTOR_TYPE> class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> > { - friend class LLSingleton<LLFunctorRegistry>; + LLSINGLETON(LLFunctorRegistry); LOG_CLASS(LLFunctorRegistry); -private: - LLFunctorRegistry() : LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") - { - mMap[LOGFUNCTOR] = log_functor; - mMap[DONOTHING] = do_nothing; - } public: typedef FUNCTOR_TYPE ResponseFunctor; @@ -125,6 +119,14 @@ private: }; template <typename FUNCTOR_TYPE> +LLFunctorRegistry<FUNCTOR_TYPE>::LLFunctorRegistry() : + LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing") +{ + mMap[LOGFUNCTOR] = log_functor; + mMap[DONOTHING] = do_nothing; +} + +template <typename FUNCTOR_TYPE> class LLFunctorRegistration { public: diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index a245ebe1b9..f772dbc6b4 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -40,7 +40,9 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack> public: struct LayoutStackRegistry : public LLChildRegistry<LayoutStackRegistry> - {}; + { + LLSINGLETON_EMPTY_CTOR(LayoutStackRegistry); + }; struct Params : public LLInitParam::Block<Params, LLView::Params> { diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index c89e1dac1d..becb45fa79 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -163,6 +163,9 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) { llassert( mMaxLengthBytes > 0 ); + LLUICtrl::setEnabled(TRUE); + setEnabled(p.enabled); + mScrollTimer.reset(); mTripleClickTimer.reset(); setText(p.default_text()); @@ -218,6 +221,13 @@ LLLineEditor::~LLLineEditor() gFocusMgr.releaseFocusIfNeeded( this ); } +void LLLineEditor::initFromParams(const LLLineEditor::Params& params) +{ + LLUICtrl::initFromParams(params); + LLUICtrl::setEnabled(TRUE); + setEnabled(params.enabled); +} + void LLLineEditor::onFocusReceived() { gEditMenuHandler = this; diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index ccbd305a16..88468503df 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -108,6 +108,9 @@ public: Params(); }; + + void initFromParams(const LLLineEditor::Params& params); + protected: LLLineEditor(const Params&); friend class LLUICtrlFactory; diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 628dedb906..c7f7f6848c 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -347,7 +347,9 @@ private: // child widget registry struct MenuRegistry : public LLChildRegistry<MenuRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(MenuRegistry); +}; class LLMenuGL diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 354add0b82..024332ee65 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -884,9 +884,9 @@ class LLNotifications : public LLSingleton<LLNotifications>, public LLNotificationChannelBase { + LLSINGLETON(LLNotifications); LOG_CLASS(LLNotifications); - friend class LLSingleton<LLNotifications>; public: // Needed to clear up RefCounted things prior to actual destruction @@ -966,8 +966,6 @@ public: bool isVisibleByRules(LLNotificationPtr pNotification); private: - // we're a singleton, so we don't have a public constructor - LLNotifications(); /*virtual*/ void initSingleton(); void loadPersistentNotifications(); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index c2185f24de..b8f47ef6ba 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -268,8 +268,9 @@ typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc; class LLRegisterPanelClass : public LLSingleton< LLRegisterPanelClass > { + LLSINGLETON_EMPTY_CTOR(LLRegisterPanelClass); public: - // reigister with either the provided builder, or the generic templated builder + // register with either the provided builder, or the generic templated builder void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func) { mPanelClassesNames[tag] = func; diff --git a/indra/llui/llresmgr.h b/indra/llui/llresmgr.h index a652dcd2c0..b19d8d40b8 100644 --- a/indra/llui/llresmgr.h +++ b/indra/llui/llresmgr.h @@ -42,9 +42,9 @@ enum LLLOCALE_ID class LLResMgr : public LLSingleton<LLResMgr> { -public: - LLResMgr(); + LLSINGLETON(LLResMgr); +public: void setLocale( LLLOCALE_ID locale_id ); LLLOCALE_ID getLocale() const { return mLocale; } diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index f64cf43a8e..c4c4d0a136 100644 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -48,7 +48,9 @@ class LLUICtrlFactory; *****************************************************************************/ struct ScrollContainerRegistry : public LLChildRegistry<ScrollContainerRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(ScrollContainerRegistry); +}; class LLScrollContainer : public LLUICtrl { diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index 4ab80195ea..acac589e43 100644 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -29,16 +29,15 @@ #include "llsingleton.h" #include "llui.h" +#include "llinitdestroyclass.h" #include <boost/signals2.hpp> class Hunspell; class LLSpellChecker : public LLSingleton<LLSpellChecker>, public LLInitClass<LLSpellChecker> { - friend class LLSingleton<LLSpellChecker>; + LLSINGLETON(LLSpellChecker); friend class LLInitClass<LLSpellChecker>; -protected: - LLSpellChecker(); ~LLSpellChecker(); public: diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 8b1ba406c8..d49e216898 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -153,7 +153,7 @@ F32 clamp_precision(F32 value, S32 decimal_precision) for (S32 i = 0; i < decimal_precision; i++) clamped_value *= 10.0; - clamped_value = ll_round((F32)clamped_value); + clamped_value = ll_round(clamped_value); for (S32 i = 0; i < decimal_precision; i++) clamped_value /= 10.0; diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index bc78d3b5fd..af4db7d7ea 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -35,7 +35,9 @@ class LLStatBar; // widget registrars struct StatViewRegistry : public LLChildRegistry<StatViewRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(StatViewRegistry); +}; class LLStatView : public LLContainerView { diff --git a/indra/llui/lltextparser.h b/indra/llui/lltextparser.h index 400aeeb8be..3d71e40452 100644 --- a/indra/llui/lltextparser.h +++ b/indra/llui/lltextparser.h @@ -37,14 +37,14 @@ class LLColor4; class LLTextParser : public LLSingleton<LLTextParser> { + LLSINGLETON(LLTextParser); + public: typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType; typedef enum e_highlight_type { PART, ALL } EHighlightType; typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition; typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction; - LLTextParser(); - LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0); bool parseFullLineHighlights(const std::string &text, LLColor4 *color); diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index fad127fc4c..0b1fbe5367 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -129,9 +129,10 @@ public: class LLToolTipMgr : public LLSingleton<LLToolTipMgr> { + LLSINGLETON(LLToolTipMgr); LOG_CLASS(LLToolTipMgr); + public: - LLToolTipMgr(); void show(const LLToolTip::Params& params); void show(const std::string& message); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index f790d8e005..770f13c1c3 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -60,6 +60,7 @@ #include "llflyoutbutton.h" #include "llsearcheditor.h" #include "lltoolbar.h" +#include "llcleanup.h" // for XUIParse #include "llquaternion.h" @@ -208,7 +209,7 @@ void LLUI::initClass(const settings_map_t& settings, void LLUI::cleanupClass() { - LLRender2D::cleanupClass(); + SUBSYSTEM_CLEANUP(LLRender2D); } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c727f75c4f..d7151dbee9 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -344,95 +344,6 @@ private: // Moved LLLocalClipRect to lllocalcliprect.h -class LLCallbackRegistry -{ -public: - typedef boost::signals2::signal<void()> callback_signal_t; - - void registerCallback(const callback_signal_t::slot_type& slot) - { - mCallbacks.connect(slot); - } - - void fireCallbacks() - { - mCallbacks(); - } - -private: - callback_signal_t mCallbacks; -}; - -class LLInitClassList : - public LLCallbackRegistry, - public LLSingleton<LLInitClassList> -{ - friend class LLSingleton<LLInitClassList>; -private: - LLInitClassList() {} -}; - -class LLDestroyClassList : - public LLCallbackRegistry, - public LLSingleton<LLDestroyClassList> -{ - friend class LLSingleton<LLDestroyClassList>; -private: - LLDestroyClassList() {} -}; - -template<typename T> -class LLRegisterWith -{ -public: - LLRegisterWith(boost::function<void ()> func) - { - T::instance().registerCallback(func); - } - - // this avoids a MSVC bug where non-referenced static members are "optimized" away - // even if their constructors have side effects - S32 reference() - { - S32 dummy; - dummy = 0; - return dummy; - } -}; - -template<typename T> -class LLInitClass -{ -public: - LLInitClass() { sRegister.reference(); } - - static LLRegisterWith<LLInitClassList> sRegister; -private: - - static void initClass() - { - LL_ERRS() << "No static initClass() method defined for " << typeid(T).name() << LL_ENDL; - } -}; - -template<typename T> -class LLDestroyClass -{ -public: - LLDestroyClass() { sRegister.reference(); } - - static LLRegisterWith<LLDestroyClassList> sRegister; -private: - - static void destroyClass() - { - LL_ERRS() << "No static destroyClass() method defined for " << typeid(T).name() << LL_ENDL; - } -}; - -template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass); -template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass); - // useful parameter blocks struct TimeIntervalParam : public LLInitParam::ChoiceBlock<TimeIntervalParam> { diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h index 6a7a681d57..44472070cc 100644 --- a/indra/llui/lluicolortable.h +++ b/indra/llui/lluicolortable.h @@ -38,7 +38,8 @@ class LLUIColor; class LLUIColorTable : public LLSingleton<LLUIColorTable> { -LOG_CLASS(LLUIColorTable); + LLSINGLETON_EMPTY_CTOR(LLUIColorTable); + LOG_CLASS(LLUIColorTable); // consider using sorted vector, can be much faster typedef std::map<std::string, LLUIColor> string_color_map_t; diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index 99553ee0d2..550bee5c70 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -258,18 +258,25 @@ public: class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter> { + LLSINGLETON_EMPTY_CTOR(LLTextInputFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const { return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl *>(view)->acceptsTextInput(), TRUE); } }; - + template <typename F, typename DERIVED> class CallbackRegistry : public LLRegistrySingleton<std::string, F, DERIVED > {}; - class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{}; + class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry> + { + LLSINGLETON_EMPTY_CTOR(CommitCallbackRegistry); + }; // the enable callback registry is also used for visiblity callbacks - class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{}; + class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry> + { + LLSINGLETON_EMPTY_CTOR(EnableCallbackRegistry); + }; protected: diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 4cc7da1267..fdefae01b1 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -92,15 +92,27 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa { std::string filename = gDirUtilp->add("widgets", widget_tag + ".xml"); LLXMLNodePtr root_node; + std::vector<std::string> search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, filename); - // Here we're looking for the "en" version, the default-language version - // of the file, rather than the localized version. - std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, filename); - if (!full_filename.empty()) + if (search_paths.empty()) { - LLUICtrlFactory::instance().pushFileName(full_filename); - LLSimpleXUIParser parser; - parser.readXUI(full_filename, block); + return; + } + + // "en" version, the default-language version of the file. + std::string base_filename = search_paths.front(); + if (!base_filename.empty()) + { + LLUICtrlFactory::instance().pushFileName(base_filename); + + if (!LLXMLNode::getLayeredXMLNode(root_node, search_paths)) + { + LL_WARNS() << "Couldn't parse widget from: " << base_filename << LL_ENDL; + return; + } + LLXUIParser parser; + parser.readXUI(root_node, block, base_filename); LLUICtrlFactory::instance().popFileName(); } } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 3ce39c947f..03d946f1b7 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -33,6 +33,8 @@ #include "llxuiparser.h" #include "llstl.h" #include "lldir.h" +#include "llsingleton.h" +#include "llheteromap.h" class LLView; @@ -57,22 +59,24 @@ protected: class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry> { -protected: - LLDefaultChildRegistry(){} - friend class LLSingleton<LLDefaultChildRegistry>; + LLSINGLETON_EMPTY_CTOR(LLDefaultChildRegistry); }; // lookup widget name by type class LLWidgetNameRegistry : public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(LLWidgetNameRegistry); +}; // lookup function for generating empty param block by widget type // this is used for schema generation //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)(); //class LLDefaultParamBlockRegistry //: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry> -//{}; +//{ +// LLSINGLETON(LLDefaultParamBlockRegistry); +//}; extern LLTrace::BlockTimerStatHandle FTM_WIDGET_SETUP; extern LLTrace::BlockTimerStatHandle FTM_WIDGET_CONSTRUCTION; @@ -85,31 +89,15 @@ extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getIn class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory> { -private: - friend class LLSingleton<LLUICtrlFactory>; - LLUICtrlFactory(); + LLSINGLETON(LLUICtrlFactory); ~LLUICtrlFactory(); // only partial specialization allowed in inner classes, so use extra dummy parameter template <typename PARAM_BLOCK, int DUMMY> - class ParamDefaults : public LLSingleton<ParamDefaults<PARAM_BLOCK, DUMMY> > + class ParamDefaults { public: - ParamDefaults() - { - // look up template file for this param block... - const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); - if (param_block_tag) - { // ...and if it exists, back fill values using the most specific template first - PARAM_BLOCK params; - LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params); - mPrototype.fillFrom(params); - } - // recursively fill from base class param block - ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get()); - - } - + ParamDefaults(); const PARAM_BLOCK& get() { return mPrototype; } private: @@ -118,9 +106,10 @@ private: // base case for recursion, there are NO base classes of LLInitParam::BaseBlock template<int DUMMY> - class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> > + class ParamDefaults<LLInitParam::BaseBlock, DUMMY> { public: + ParamDefaults(); const LLInitParam::BaseBlock& get() { return mBaseBlock; } private: LLInitParam::BaseBlock mBaseBlock; @@ -132,7 +121,7 @@ public: template<typename T> static const typename T::Params& getDefaultParams() { - return ParamDefaults<typename T::Params, 0>::instance().get(); + return instance().mParamDefaultsMap.obtain< ParamDefaults<typename T::Params, 0> >().get(); } // Does what you want for LLFloaters and LLPanels @@ -147,7 +136,8 @@ public: template<typename T> static T* create(typename T::Params& params, LLView* parent = NULL) { - params.fillFrom(ParamDefaults<typename T::Params, 0>::instance().get()); + params.fillFrom(instance().mParamDefaultsMap.obtain< + ParamDefaults<typename T::Params, 0> >().get()); T* widget = createWidgetImpl<T>(params, parent); if (widget) @@ -295,8 +285,40 @@ private: class LLPanel* mDummyPanel; std::vector<std::string> mFileNames; + + // store ParamDefaults specializations + // Each ParamDefaults specialization used to be an LLSingleton in its own + // right. But the 2016 changes to the LLSingleton mechanism, making + // LLSingleton instances polymorphic, are incompatible with current + // LLInitParam::BaseBlock functionality. (Thanks NickyD for spotting + // that!) Moreover, instances of the private nested ParamDefaults template + // aren't global resources -- which is what LLSingleton is designed for. + // This is simply a cache looked up by type. Its lifespan is tied to + // LLUICtrlFactory. Use LLHeteroMap for this cache. + LLHeteroMap mParamDefaultsMap; }; +template <typename PARAM_BLOCK, int DUMMY> +LLUICtrlFactory::ParamDefaults<PARAM_BLOCK, DUMMY>::ParamDefaults() +{ + // look up template file for this param block... + const std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK)); + if (param_block_tag) + { // ...and if it exists, back fill values using the most specific template first + PARAM_BLOCK params; + LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, params); + mPrototype.fillFrom(params); + } + // recursively fill from base class param block + ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom( + LLUICtrlFactory::instance().mParamDefaultsMap.obtain< + ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY> >().get()); + +} + +template <int DUMMY> +LLUICtrlFactory::ParamDefaults<LLInitParam::BaseBlock, DUMMY>::ParamDefaults() {} + // this is here to make gcc happy with reference to LLUICtrlFactory template<typename DERIVED> template<typename T> diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 27a2456deb..b5a31f5118 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1377,7 +1377,7 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url) LLUrlEntryEmail::LLUrlEntryEmail() : LLUrlEntryBase() { - mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,6}", + mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,63}", boost::regex::perl | boost::regex::icase); mMenuName = "menu_url_email.xml"; mTooltip = LLTrans::getString("TooltipEmail"); diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h index 24c3a2b513..efafe543ab 100644 --- a/indra/llui/llurlregistry.h +++ b/indra/llui/llurlregistry.h @@ -62,9 +62,9 @@ void LLUrlRegistryNullCallback(const std::string &url, /// class LLUrlRegistry : public LLSingleton<LLUrlRegistry> { -public: + LLSINGLETON(LLUrlRegistry); ~LLUrlRegistry(); - +public: /// add a new Url handler to the registry (will be freed on destruction) /// optionally force it to the front of the list, making it take /// priority over other regular expression matches for URLs @@ -89,9 +89,6 @@ public: bool isUrl(const LLWString &text); private: - LLUrlRegistry(); - friend class LLSingleton<LLUrlRegistry>; - std::vector<LLUrlEntryBase *> mUrlEntry; LLUrlEntryBase* mUrlEntryTrusted; LLUrlEntryBase* mUrlEntryIcon; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 9604e5ce10..89ad8138d8 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1912,6 +1912,7 @@ private: class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder> { + LLSINGLETON_EMPTY_CTOR(SortByTabOrder); /*virtual*/ void sort(LLView * parent, LLView::child_list_t &children) const { children.sort(CompareByTabOrder(parent->getTabOrder(), parent->getDefaultTabGroup())); @@ -1935,6 +1936,7 @@ const LLViewQuery & LLView::getTabOrderQuery() // This class is only used internally by getFocusRootsQuery below. class LLFocusRootsFilter : public LLQueryFilter, public LLSingleton<LLFocusRootsFilter> { + LLSINGLETON_EMPTY_CTOR(LLFocusRootsFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const { return filterResult_t(view->isCtrl() && view->isFocusRoot(), !view->isFocusRoot()); diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h index 375efcc3de..d1059d55de 100644 --- a/indra/llui/llviewereventrecorder.h +++ b/indra/llui/llviewereventrecorder.h @@ -44,13 +44,10 @@ class LLViewerEventRecorder : public LLSingleton<LLViewerEventRecorder> { - - public: - - LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton + LLSINGLETON(LLViewerEventRecorder); ~LLViewerEventRecorder(); - + public: void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y, std::string mName); void setMouseLocalCoords(S32 x,S32 y); void setMouseGlobalCoords(S32 x,S32 y); diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h index 9044c4ff29..21bb1be26f 100644 --- a/indra/llui/llviewquery.h +++ b/indra/llui/llviewquery.h @@ -54,31 +54,37 @@ public: class LLLeavesFilter : public LLQueryFilter, public LLSingleton<LLLeavesFilter> { + LLSINGLETON_EMPTY_CTOR(LLLeavesFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; }; class LLRootsFilter : public LLQueryFilter, public LLSingleton<LLRootsFilter> { + LLSINGLETON_EMPTY_CTOR(LLRootsFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; }; class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter> { + LLSINGLETON_EMPTY_CTOR(LLVisibleFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; }; class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter> { + LLSINGLETON_EMPTY_CTOR(LLEnabledFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; }; class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter> { + LLSINGLETON_EMPTY_CTOR(LLTabStopFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; }; class LLCtrlFilter : public LLQueryFilter, public LLSingleton<LLCtrlFilter> { + LLSINGLETON_EMPTY_CTOR(LLCtrlFilter); /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const; }; diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index ad2a39cab7..eb0eac8194 100644 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -41,7 +41,9 @@ class LLView; // lookup widget type by name class LLWidgetTypeRegistry : public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(LLWidgetTypeRegistry); +}; // global static instance for registering all widget types @@ -51,7 +53,9 @@ typedef LLRegistry<std::string, LLWidgetCreatorFunc> widget_registry_t; class LLChildRegistryRegistry : public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry> -{}; +{ + LLSINGLETON_EMPTY_CTOR(LLChildRegistryRegistry); +}; class LLXSDWriter : public LLInitParam::Parser { @@ -60,7 +64,7 @@ public: void writeXSD(const std::string& name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace); /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } - + /*virtual*/ std::string getCurrentFileName() { return LLStringUtil::null; } LLXSDWriter(); ~LLXSDWriter(); @@ -98,6 +102,7 @@ public: typedef LLInitParam::Parser::name_stack_t name_stack_t; /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ std::string getCurrentFileName() { return mCurFileName; } /*virtual*/ void parserWarning(const std::string& message); /*virtual*/ void parserError(const std::string& message); @@ -200,6 +205,7 @@ public: virtual ~LLSimpleXUIParser(); /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ std::string getCurrentFileName() { return mCurFileName; } /*virtual*/ void parserWarning(const std::string& message); /*virtual*/ void parserError(const std::string& message); diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index f01178c374..338be1808d 100644..100755 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -31,6 +31,7 @@ #include "llcachename.h" #include "lluuid.h" #include "message.h" +#include "llpounceable.h" #include <string> @@ -165,7 +166,7 @@ LLFontGL* LLFontGL::getFontDefault() char const* const _PREHASH_AgentData = (char *)"AgentData"; char const* const _PREHASH_AgentID = (char *)"AgentID"; -LLMessageSystem* gMessageSystem = NULL; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem; // // Stub implementation for LLMessageSystem diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp index 1cc0e819db..db0eac7031 100644 --- a/indra/llvfs/llvfs.cpp +++ b/indra/llvfs/llvfs.cpp @@ -2114,6 +2114,17 @@ void LLVFS::dumpFiles() LL_INFOS() << "Extracted " << files_extracted << " files out of " << mFileBlocks.size() << LL_ENDL; } +time_t LLVFS::creationTime() +{ + llstat data_file_stat; + int errors = LLFile::stat(mDataFilename, &data_file_stat); + if (0 == errors) + { + return data_file_stat.st_ctime; + } + return 0; +} + //============================================================================ // protected //============================================================================ diff --git a/indra/llvfs/llvfs.h b/indra/llvfs/llvfs.h index 39f31a221b..dca5ff4ad5 100644 --- a/indra/llvfs/llvfs.h +++ b/indra/llvfs/llvfs.h @@ -127,6 +127,7 @@ public: void dumpStatistics(); void listFiles(); void dumpFiles(); + time_t creationTime(); protected: void removeFileBlock(LLVFSFileBlock *fileblock); diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index 474953d3a4..7e90ade423 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -175,9 +175,9 @@ BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window) return FALSE; } -void LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) +BOOL LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) { - + return FALSE; } void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg) diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index de789a71d9..47d5a18858 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -65,7 +65,7 @@ public: virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data); virtual BOOL handleTimerEvent(LLWindow *window); virtual BOOL handleDeviceChange(LLWindow *window); - virtual void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); + virtual BOOL handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); enum DragNDropAction { DNDA_START_TRACKING = 0,// Start tracking an incoming drag diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 4086db8e52..321792eb14 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -2623,19 +2623,21 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ case WM_DPICHANGED: { LPRECT lprc_new_scale; - F32 new_scale = LOWORD(w_param) / USER_DEFAULT_SCREEN_DPI; + F32 new_scale = F32(LOWORD(w_param)) / F32(USER_DEFAULT_SCREEN_DPI); lprc_new_scale = (LPRECT)l_param; S32 new_width = lprc_new_scale->right - lprc_new_scale->left; S32 new_height = lprc_new_scale->bottom - lprc_new_scale->top; - window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height); - SetWindowPos(h_wnd, - HWND_TOP, - lprc_new_scale->left, - lprc_new_scale->top, - new_width, - new_height, - SWP_NOZORDER | SWP_NOACTIVATE); - return 0; + if (window_imp->mCallbacks->handleDPIChanged(window_imp, new_scale, new_width, new_height)) + { + SetWindowPos(h_wnd, + HWND_TOP, + lprc_new_scale->left, + lprc_new_scale->top, + new_width, + new_height, + SWP_NOZORDER | SWP_NOACTIVATE); + } + return 0; } case WM_SETFOCUS: @@ -3982,7 +3984,7 @@ F32 LLWindowWin32::getSystemUISize() hr = pGDFM(hMonitor, MDT_EFFECTIVE_DPI, &dpix, &dpiy); if (hr == S_OK) { - scale_value = dpix / USER_DEFAULT_SCREEN_DPI; + scale_value = F32(dpix) / F32(USER_DEFAULT_SCREEN_DPI); } else { @@ -4001,7 +4003,7 @@ F32 LLWindowWin32::getSystemUISize() else { LL_WARNS() << "Could not load shcore.dll library (included by <ShellScalingAPI.h> from Win 8.1 SDK). Using legacy DPI awareness API of Win XP/7" << LL_ENDL; - scale_value = GetDeviceCaps(hdc, LOGPIXELSX) / USER_DEFAULT_SCREEN_DPI; + scale_value = F32(GetDeviceCaps(hdc, LOGPIXELSX)) / F32(USER_DEFAULT_SCREEN_DPI); } ReleaseDC(hWnd, hdc); diff --git a/indra/media_plugins/cef/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp index 0cfb810906..c9ea3ed597 100644 --- a/indra/media_plugins/cef/windows_volume_catcher.cpp +++ b/indra/media_plugins/cef/windows_volume_catcher.cpp @@ -31,17 +31,16 @@ #include "llsingleton.h" class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> { -friend LLSingleton<VolumeCatcherImpl>; + LLSINGLETON(VolumeCatcherImpl); + // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. + ~VolumeCatcherImpl(); + public: void setVolume(F32 volume); void setPan(F32 pan); private: - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - VolumeCatcherImpl(); - ~VolumeCatcherImpl(); - typedef void (WINAPI *set_volume_func_t)(F32); typedef void (WINAPI *set_mute_func_t)(bool); diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index 0bd323eb58..ebcdde2960 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -84,6 +84,7 @@ private: float mCurTime; float mDuration; + EStatus mVlcStatus; }; //////////////////////////////////////////////////////////////////////////////// @@ -111,6 +112,7 @@ MediaPluginBase(host_send_func, host_user_data) mURL = std::string(); + mVlcStatus = STATUS_NONE; setStatus(STATUS_NONE); } @@ -209,28 +211,28 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) switch (event->type) { case libvlc_MediaPlayerOpening: - parent->setStatus(STATUS_LOADING); + parent->mVlcStatus = STATUS_LOADING; break; case libvlc_MediaPlayerPlaying: parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f; - parent->setStatus(STATUS_PLAYING); + parent->mVlcStatus = STATUS_PLAYING; break; case libvlc_MediaPlayerPaused: - parent->setStatus(STATUS_PAUSED); + parent->mVlcStatus = STATUS_PAUSED; break; case libvlc_MediaPlayerStopped: - parent->setStatus(STATUS_DONE); + parent->mVlcStatus = STATUS_DONE; break; case libvlc_MediaPlayerEndReached: - parent->setStatus(STATUS_DONE); + parent->mVlcStatus = STATUS_DONE; break; case libvlc_MediaPlayerEncounteredError: - parent->setStatus(STATUS_ERROR); + parent->mVlcStatus = STATUS_ERROR; break; case libvlc_MediaPlayerTimeChanged: @@ -446,6 +448,7 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) } else if (message_name == "idle") { + setStatus(mVlcStatus); } else if (message_name == "cleanup") { @@ -567,7 +570,7 @@ void MediaPluginLibVLC::receiveMessage(const char* message_string) { if (mLibVLCMediaPlayer) { - libvlc_media_player_pause(mLibVLCMediaPlayer); + libvlc_media_player_set_pause(mLibVLCMediaPlayer, 1); } } else if (message_name == "seek") diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index d6d7d2c563..9ac1c3520d 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -248,7 +248,6 @@ set(viewer_SOURCE_FILES llfloaterimsession.cpp llfloaterimcontainer.cpp llfloaterinspect.cpp - llfloaterinventory.cpp llfloaterjoystick.cpp llfloaterlagmeter.cpp llfloaterland.cpp @@ -262,7 +261,8 @@ set(viewer_SOURCE_FILES llfloatermodeluploadbase.cpp llfloaternamedesc.cpp llfloaternotificationsconsole.cpp - llfloaternotificationstabbed.cpp + llfloaternotificationstabbed.cpp + llfloateroutfitphotopreview.cpp llfloateroutfitsnapshot.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp @@ -867,7 +867,6 @@ set(viewer_HEADER_FILES llfloaterimsession.h llfloaterimcontainer.h llfloaterinspect.h - llfloaterinventory.h llfloaterjoystick.h llfloaterlagmeter.h llfloaterland.h @@ -881,7 +880,8 @@ set(viewer_HEADER_FILES llfloatermodeluploadbase.h llfloaternamedesc.h llfloaternotificationsconsole.h - llfloaternotificationstabbed.h + llfloaternotificationstabbed.h + llfloateroutfitphotopreview.h llfloateroutfitsnapshot.h llfloaterobjectweights.h llfloateropenobject.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index a0d3dc0f99..9bc0a7c701 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -282,4 +282,14 @@ is_running_function="Floater.IsOpen" is_running_parameters="camera" /> + <command name="reporter" + available_in_toybox="true" + icon="Command_Report_Abuse_Icon" + label_ref="Command_Report_Abuse_Label" + tooltip_ref="Command_Report_Abuse_Tooltip" + execute_function="Floater.ToggleOrBringToFront" + execute_parameters="reporter" + is_running_function="Floater.IsOpen" + is_running_parameters="reporter" + /> </commands> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6621b9e269..9f37c3487e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5263,6 +5263,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>LastAppearanceTab</key> + <map> + <key>Comment</key> + <string>Last selected tab in appearance floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>LastMediaSettingsTab</key> <map> <key>Comment</key> @@ -6629,6 +6640,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>MuteListLimit</key> + <map> + <key>Comment</key> + <string>Maximum number of entries in the mute list</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>1000</integer> + </map> <key>MyOutfitsAutofill</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index fd6b1b5b3f..eee13fb28e 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -242,6 +242,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>PreviousScreenshotForReport</key> + <map> + <key>Comment</key> + <string>Use Previous Screenshot for Abuse report</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <!-- Settings below are for back compatibility only. They are not used in current viewer anymore. But they can't be removed to avoid influence on previous versions of the viewer in case of settings are not used or default value @@ -251,7 +262,7 @@ <key>LogChat</key> <map> <key>Comment</key> - <string>Log Chat</string> + <string>Obsolete - this setting is no longer used and has no effect.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -262,7 +273,7 @@ <key>LogChatIM</key> <map> <key>Comment</key> - <string>Log Incoming Instant Messages with Chat</string> + <string>Obsolete - this setting is no longer used and has no effect.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -273,7 +284,7 @@ <key>LogChatTimestamp</key> <map> <key>Comment</key> - <string>Log Timestamp of Chat</string> + <string>Obsolete - this setting is no longer used and has no effect.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -281,6 +292,7 @@ <key>Value</key> <integer>0</integer> </map> + <!-- End of back compatibility settings --> <key>TranslatingEnabled</key> <map> <key>Comment</key> @@ -336,6 +348,5 @@ <key>Value</key> <integer>1</integer> </map> - <!-- End of back compatibility settings --> </map> </llsd> diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl index b9ddbc8e1c..8918182853 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl @@ -43,12 +43,12 @@ void default_lighting() { vec4 color = texture2D(diffuseMap,vary_texcoord0.xy); + color *= vertex_color; + if (color.a < minimum_alpha) { discard; } - - color.rgb *= vertex_color.rgb; color.rgb = atmosLighting(color.rgb); diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index f251ceffd4..55e1d19f05 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -58,9 +58,9 @@ protected: //=============================================================================== class LLAccountingCostManager : public LLSingleton<LLAccountingCostManager> { + LLSINGLETON(LLAccountingCostManager); + public: - //Ctor - LLAccountingCostManager(); //Store an object that will be eventually fetched void addObject( const LLUUID& objectID ); //Request quotas for object list diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 66e2d6fa6a..cfb09d329b 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3191,7 +3191,7 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global) } BOOL LLAgent::leftButtonGrabbed() const -{ +{ const BOOL camera_mouse_look = gAgentCamera.cameraMouselook(); return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0) @@ -3199,13 +3199,6 @@ BOOL LLAgent::leftButtonGrabbed() const || (camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0); } -BOOL LLAgent::leftButtonBlocked() const -{ - const BOOL camera_mouse_look = gAgentCamera.cameraMouselook(); - return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0) - || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0); -} - BOOL LLAgent::rotateGrabbed() const { return (mControlsTakenCount[CONTROL_YAW_POS_INDEX] > 0) @@ -3663,14 +3656,7 @@ BOOL LLAgent::anyControlGrabbed() const BOOL LLAgent::isControlGrabbed(S32 control_index) const { - if (gAgent.mControlsTakenCount[control_index] > 0) - return TRUE; - return gAgent.mControlsTakenPassedOnCount[control_index] > 0; -} - -BOOL LLAgent::isControlBlocked(S32 control_index) const -{ - return mControlsTakenCount[control_index] > 0; + return mControlsTakenCount[control_index] > 0; } void LLAgent::forceReleaseControls() diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index d82ff7a67f..b5da5e9062 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -444,8 +444,7 @@ private: // Grab //-------------------------------------------------------------------- public: - BOOL leftButtonGrabbed() const; - BOOL leftButtonBlocked() const; + BOOL leftButtonGrabbed() const; BOOL rotateGrabbed() const; BOOL forwardGrabbed() const; BOOL backwardGrabbed() const; @@ -462,9 +461,8 @@ public: BOOL controlFlagsDirty() const; void enableControlFlagReset(); void resetControlFlags(); - BOOL anyControlGrabbed() const; // True if a script has taken over any control - BOOL isControlGrabbed(S32 control_index) const; // True if a script has taken over a control - BOOL isControlBlocked(S32 control_index) const; // Control should be ignored or won't be passed + BOOL anyControlGrabbed() const; // True iff a script has taken over a control + BOOL isControlGrabbed(S32 control_index) const; // Send message to simulator to force grabbed controls to be // released, in case of a poorly written script. void forceReleaseControls(); diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h index abf7027ed2..f981e08ff7 100644 --- a/indra/newview/llagentpicksinfo.h +++ b/indra/newview/llagentpicksinfo.h @@ -36,14 +36,12 @@ struct LLAvatarPicks; */ class LLAgentPicksInfo : public LLSingleton<LLAgentPicksInfo> { + LLSINGLETON(LLAgentPicksInfo); + virtual ~LLAgentPicksInfo(); + class LLAgentPicksObserver; public: - - LLAgentPicksInfo(); - - virtual ~LLAgentPicksInfo(); - /** * Requests number of picks from server. * diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index b27698fd8f..2710262910 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -38,6 +38,7 @@ #include "llviewerinventory.h" #include "llavatarappearancedefines.h" #include "llwearabledata.h" +#include "llinitdestroyclass.h" class LLInventoryItem; class LLVOAvatarSelf; diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index be8877328d..8188c6c3f9 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -58,7 +58,7 @@ frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(oneFrame) userInfo:nil repeats:YES]; } else { - handleQuit(); + exit(0); } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil]; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4d6d7a9d89..fc4be98fbd 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3410,9 +3410,21 @@ LLSD LLAppearanceMgr::dumpCOF() const return result; } +// static +void LLAppearanceMgr::onIdle(void *) +{ + LLAppearanceMgr* mgr = LLAppearanceMgr::getInstance(); + if (mgr->mRerequestAppearanceBake) + { + mgr->requestServerAppearanceUpdate(); + } +} + void LLAppearanceMgr::requestServerAppearanceUpdate() { - if (!mOutstandingAppearanceBakeRequest) + // Workaround: we shouldn't request update from server prior to uploading all attachments, but it is + // complicated to check for pending attachment uploads, so we are just waiting for uploads to complete + if (!mOutstandingAppearanceBakeRequest && gAssetStorage->getNumPendingUploads() == 0) { mRerequestAppearanceBake = false; LLCoprocedureManager::CoProcedure_t proc = boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this, _1); @@ -3420,13 +3432,14 @@ void LLAppearanceMgr::requestServerAppearanceUpdate() } else { + // Shedule update mRerequestAppearanceBake = true; } } void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter) { - mRerequestAppearanceBake = false; + BoolSetter outstanding(mOutstandingAppearanceBakeRequest); if (!gAgent.getRegion()) { LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL; @@ -3458,8 +3471,6 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd bool bRetry; do { - BoolSetter outstanding(mOutstandingAppearanceBakeRequest); - // If we have already received an update for this or higher cof version, // put a warning in the log and cancel the request. S32 cofVersion = getCOFVersion(); @@ -3571,12 +3582,6 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd } } while (bRetry); - - if (mRerequestAppearanceBake) - { // A bake request came in while this one was still outstanding. - // Requeue ourself for a later request. - requestServerAppearanceUpdate(); - } } /*static*/ @@ -3942,7 +3947,6 @@ LLAppearanceMgr::LLAppearanceMgr(): mAttachmentInvLinkEnabled(false), mOutfitIsDirty(false), mOutfitLocked(false), - mInFlightCounter(0), mInFlightTimer(), mIsInUpdateAppearanceFromCOF(false), mOutstandingAppearanceBakeRequest(false), @@ -3957,6 +3961,7 @@ LLAppearanceMgr::LLAppearanceMgr(): "OutfitOperationsTimeout"))); gIdleCallbacks.addFunction(&LLAttachmentsMgr::onIdle, NULL); + gIdleCallbacks.addFunction(&LLAppearanceMgr::onIdle, NULL); //sheduling appearance update requests } LLAppearanceMgr::~LLAppearanceMgr() diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f0d3f80f59..166c663feb 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -42,9 +42,10 @@ class LLOutfitUnLockTimer; class LLAppearanceMgr: public LLSingleton<LLAppearanceMgr> { + LLSINGLETON(LLAppearanceMgr); + ~LLAppearanceMgr(); LOG_CLASS(LLAppearanceMgr); - friend class LLSingleton<LLAppearanceMgr>; friend class LLOutfitUnLockTimer; public: @@ -224,6 +225,7 @@ public: bool isInUpdateAppearanceFromCOF() { return mIsInUpdateAppearanceFromCOF; } + static void onIdle(void *); void requestServerAppearanceUpdate(); void setAppearanceServiceURL(const std::string& url) { mAppearanceServiceURL = url; } @@ -234,17 +236,12 @@ public: boost::signals2::connection setAttachmentsChangedCallback(attachments_changed_callback_t cb); - private: void serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter); static void debugAppearanceUpdateCOF(const LLSD& content); std::string mAppearanceServiceURL; - -protected: - LLAppearanceMgr(); - ~LLAppearanceMgr(); private: @@ -272,7 +269,6 @@ private: * to avoid unsynchronized outfit state or performing duplicate operations. */ bool mOutfitLocked; - S32 mInFlightCounter; LLTimer mInFlightTimer; static bool mActive; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a0ebae119e..d0c7d0b72e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -209,7 +209,7 @@ #include "llfloaterreg.h" #include "llfloateroutfitsnapshot.h" #include "llfloatersnapshot.h" -#include "llfloaterinventory.h" +#include "llsidepanelinventory.h" // includes for idle() idleShutdown() #include "llviewercontrol.h" @@ -234,6 +234,7 @@ #include "llsecapi.h" #include "llmachineid.h" #include "llmainlooprepeater.h" +#include "llcleanup.h" #include "llcoproceduremanager.h" #include "llviewereventrecorder.h" @@ -388,6 +389,7 @@ const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; */ class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList> { + LLSINGLETON_EMPTY_CTOR(LLDeferredTaskList); LOG_CLASS(LLDeferredTaskList); friend class LLAppViewer; @@ -738,7 +740,7 @@ LLAppViewer::LLAppViewer() LLAppViewer::~LLAppViewer() { delete mSettingsLocationList; - LLViewerEventRecorder::instance().~LLViewerEventRecorder(); + LLViewerEventRecorder::deleteSingleton(); LLLoginInstance::instance().setUpdaterService(0); @@ -1747,7 +1749,7 @@ bool LLAppViewer::cleanup() gTransferManager.cleanup(); #endif - LLLocalBitmapMgr::cleanupClass(); + SUBSYSTEM_CLEANUP(LLLocalBitmapMgr); // Note: this is where gWorldMap used to be deleted. @@ -1856,11 +1858,11 @@ bool LLAppViewer::cleanup() LLViewerObject::cleanupVOClasses(); - LLAvatarAppearance::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarAppearance); - LLAvatarAppearance::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarAppearance); - LLPostProcess::cleanupClass(); + SUBSYSTEM_CLEANUP(LLPostProcess); LLTracker::cleanupInstance(); @@ -1886,12 +1888,12 @@ bool LLAppViewer::cleanup() //end_messaging_system(); - LLFollowCamMgr::cleanupClass(); - //LLVolumeMgr::cleanupClass(); + SUBSYSTEM_CLEANUP(LLFollowCamMgr); + //SUBSYSTEM_CLEANUP(LLVolumeMgr); LLPrimitive::cleanupVolumeManager(); - LLWorldMapView::cleanupClass(); - LLFolderViewItem::cleanupClass(); - LLUI::cleanupClass(); + SUBSYSTEM_CLEANUP(LLWorldMapView); + SUBSYSTEM_CLEANUP(LLFolderViewItem); + SUBSYSTEM_CLEANUP(LLUI); // // Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles). @@ -1900,7 +1902,7 @@ bool LLAppViewer::cleanup() // LL_INFOS() << "Cleaning up VFS" << LL_ENDL; - LLVFile::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVFile); LL_INFOS() << "Saving Data" << LL_ENDL; @@ -2003,9 +2005,9 @@ bool LLAppViewer::cleanup() // Non-LLCurl libcurl library mAppCoreHttp.cleanup(); - LLFilePickerThread::cleanupClass(); + SUBSYSTEM_CLEANUP(LLFilePickerThread); - //MUST happen AFTER LLCurl::cleanupClass + //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl) delete sTextureCache; sTextureCache = NULL; delete sTextureFetch; @@ -2029,22 +2031,22 @@ bool LLAppViewer::cleanup() gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name)); } - LLMetricPerformanceTesterBasic::cleanClass() ; + SUBSYSTEM_CLEANUP(LLMetricPerformanceTesterBasic) ; LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL; //Note: - //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() + //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao - LLViewerMedia::cleanupClass(); - LLViewerParcelMedia::cleanupClass(); + SUBSYSTEM_CLEANUP(LLViewerMedia); + SUBSYSTEM_CLEANUP(LLViewerParcelMedia); gTextureList.shutdown(); // shutdown again in case a callback added something LLUIImageList::getInstance()->cleanUp(); // This should eventually be done in LLAppViewer - LLImage::cleanupClass(); - LLVFSThread::cleanupClass(); - LLLFSThread::cleanupClass(); + SUBSYSTEM_CLEANUP(LLImage); + SUBSYSTEM_CLEANUP(LLVFSThread); + SUBSYSTEM_CLEANUP(LLLFSThread); #ifndef LL_RELEASE_FOR_DOWNLOAD LL_INFOS() << "Auditing VFS" << LL_ENDL; @@ -2087,10 +2089,10 @@ bool LLAppViewer::cleanup() LL_INFOS() << "File launched." << LL_ENDL; } LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); LLCore::LLHttp::cleanup(); - LLWearableType::cleanupClass(); + SUBSYSTEM_CLEANUP(LLWearableType); LLMainLoopRepeater::instance().stop(); @@ -2102,10 +2104,34 @@ bool LLAppViewer::cleanup() LLError::LLCallStacks::cleanup(); removeMarkerFiles(); - - LL_INFOS() << "Goodbye!" << LL_ENDL; - removeDumpDir(); + // It's not at first obvious where, in this long sequence, generic cleanup + // calls OUGHT to go. So let's say this: as we migrate cleanup from + // explicit hand-placed calls into the generic mechanism, eventually + // all cleanup will get subsumed into the generic calls. So the calls you + // still see above are calls that MUST happen before the generic cleanup + // kicks in. + + // This calls every remaining LLSingleton's cleanupSingleton() method. + // This method should perform any cleanup that might take significant + // realtime, or might throw an exception. + LLSingletonBase::cleanupAll(); + + // This calls every remaining LLSingleton's deleteSingleton() method. + // No class destructor should perform any cleanup that might take + // significant realtime, or throw an exception. + // LLSingleton machinery includes a last-gasp implicit deleteAll() call, + // so this explicit call shouldn't strictly be necessary. However, by the + // time the runtime engages that implicit call, it may already have + // destroyed things like std::cerr -- so the implicit deleteAll() refrains + // from logging anything. Since both cleanupAll() and deleteAll() call + // their respective cleanup methods in computed dependency order, it's + // probably useful to be able to log that order. + LLSingletonBase::deleteAll(); + + LL_INFOS() << "Goodbye!" << LL_ENDL; + + removeDumpDir(); // return 0; return true; @@ -3330,6 +3356,26 @@ LLSD LLAppViewer::getViewerInfo() const info["OPENGL_VERSION"] = (const char*)(glGetString(GL_VERSION)); + // Settings + + LLRect window_rect = gViewerWindow->getWindowRectRaw(); + info["WINDOW_WIDTH"] = window_rect.getWidth(); + info["WINDOW_HEIGHT"] = window_rect.getHeight(); + info["FONT_SIZE_ADJUSTMENT"] = gSavedSettings.getF32("FontScreenDPI"); + info["UI_SCALE"] = gSavedSettings.getF32("UIScaleFactor"); + info["DRAW_DISTANCE"] = gSavedSettings.getF32("RenderFarClip"); + info["NET_BANDWITH"] = gSavedSettings.getF32("ThrottleBandwidthKBPS"); + info["LOD_FACTOR"] = gSavedSettings.getF32("RenderVolumeLODFactor"); + info["RENDER_QUALITY"] = (F32)gSavedSettings.getU32("RenderQualityPerformance"); + info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled"; + info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory"); + + LLSD substitution; + substitution["datetime"] = (S32)(gVFS ? gVFS->creationTime() : 0); + info["VFS_TIME"] = LLTrans::getString("AboutTime", substitution); + + // Libraries + info["J2C_VERSION"] = LLImageJ2C::getEngineInfo(); bool want_fullname = true; info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD(); @@ -3449,7 +3495,9 @@ std::string LLAppViewer::getViewerInfoString() const { support << "\n" << LLTrans::getString("AboutDriver", args); } - support << "\n" << LLTrans::getString("AboutLibs", args); + support << "\n" << LLTrans::getString("AboutOGL", args); + support << "\n\n" << LLTrans::getString("AboutSettings", args); + support << "\n\n" << LLTrans::getString("AboutLibs", args); if (info.has("COMPILER")) { support << "\n" << LLTrans::getString("AboutCompiler", args); @@ -5500,12 +5548,15 @@ void LLAppViewer::disconnectViewer() } saveNameCache(); - LLExperienceCache *expCache = LLExperienceCache::getIfExists(); - if (expCache) - expCache->cleanup(); + if (LLExperienceCache::instanceExists()) + { + // TODO: LLExperienceCache::cleanup() logic should be moved to + // cleanupSingleton(). + LLExperienceCache::instance().cleanup(); + } // close inventory interface, close all windows - LLFloaterInventory::cleanup(); + LLSidepanelInventory::cleanup(); gAgentWearables.cleanup(); gAgentCamera.cleanup(); diff --git a/indra/newview/llattachmentsmgr.h b/indra/newview/llattachmentsmgr.h index bb7d35edbc..a4ef762e8b 100644 --- a/indra/newview/llattachmentsmgr.h +++ b/indra/newview/llattachmentsmgr.h @@ -62,6 +62,9 @@ class LLViewerInventoryItem; //-------------------------------------------------------------------------------- class LLAttachmentsMgr: public LLSingleton<LLAttachmentsMgr> { + LLSINGLETON(LLAttachmentsMgr); + virtual ~LLAttachmentsMgr(); + public: // Stores info for attachments that will be requested during idle. struct AttachmentsInfo @@ -72,9 +75,6 @@ public: }; typedef std::deque<AttachmentsInfo> attachments_vec_t; - LLAttachmentsMgr(); - virtual ~LLAttachmentsMgr(); - void addAttachmentRequest(const LLUUID& item_id, const U8 attachment_pt, const BOOL add); diff --git a/indra/newview/llautoreplace.h b/indra/newview/llautoreplace.h index 9eecc2d981..23cc313646 100644 --- a/indra/newview/llautoreplace.h +++ b/indra/newview/llautoreplace.h @@ -191,6 +191,7 @@ class LLAutoReplaceSettings */ class LLAutoReplace : public LLSingleton<LLAutoReplace> { + LLSINGLETON(LLAutoReplace); public: /// Callback that provides the hook for use in text entry methods void autoreplaceCallback(S32& replacement_start, S32& replacement_length, LLWString& replacement_string, S32& cursor_pos, const LLWString& input_text); @@ -202,8 +203,6 @@ public: void setSettings(const LLAutoReplaceSettings& settings); private: - friend class LLSingleton<LLAutoReplace>; - LLAutoReplace(); /*virtual*/ void initSingleton(); LLAutoReplaceSettings mSettings; ///< configuration information diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 7b8c630837..36e95c07f4 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -689,6 +689,8 @@ namespace action_give_inventory struct LLShareInfo : public LLSingleton<LLShareInfo> { + LLSINGLETON_EMPTY_CTOR(LLShareInfo); + public: std::vector<LLAvatarName> mAvatarNames; uuid_vec_t mAvatarUuids; }; diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h index 5b5720f4ac..a1dacd1a27 100644 --- a/indra/newview/llavatariconctrl.h +++ b/indra/newview/llavatariconctrl.h @@ -37,6 +37,8 @@ class LLAvatarName; class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache> { + LLSINGLETON(LLAvatarIconIDCache); + public: struct LLAvatarIconIDCacheItem { @@ -46,10 +48,6 @@ public: bool expired(); }; - LLAvatarIconIDCache() - : mFilename("avatar_icons_cache.txt") - {} - void load (); void save (); @@ -64,6 +62,11 @@ protected: std::map<LLUUID,LLAvatarIconIDCacheItem> mCache;//we cache only LLUID and time }; +inline +LLAvatarIconIDCache::LLAvatarIconIDCache() + : mFilename("avatar_icons_cache.txt") +{} + namespace LLAvatarIconCtrlEnums { enum ESymbolPos diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 1dcd2c9b90..d5c5c75c69 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -187,13 +187,12 @@ public: class LLAvatarPropertiesProcessor : public LLSingleton<LLAvatarPropertiesProcessor> { -public: - - LLAvatarPropertiesProcessor(); + LLSINGLETON(LLAvatarPropertiesProcessor); virtual ~LLAvatarPropertiesProcessor(); +public: void addObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer); - + void removeObserver(const LLUUID& avatar_id, LLAvatarPropertiesObserver* observer); // Request various types of avatar data. Duplicate requests will be diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h index 870ef4f394..6b5fa7bc35 100644 --- a/indra/newview/llavatarrenderinfoaccountant.h +++ b/indra/newview/llavatarrenderinfoaccountant.h @@ -38,13 +38,13 @@ class LLViewerRegion; // that is sent to or fetched from regions. class LLAvatarRenderInfoAccountant : public LLSingleton<LLAvatarRenderInfoAccountant> { + LLSINGLETON(LLAvatarRenderInfoAccountant); + ~LLAvatarRenderInfoAccountant(); + private: LOG_CLASS(LLAvatarRenderInfoAccountant); public: - LLAvatarRenderInfoAccountant(); - ~LLAvatarRenderInfoAccountant(); - void sendRenderInfoToRegion(LLViewerRegion * regionp); void getRenderInfoFromRegion(LLViewerRegion * regionp); diff --git a/indra/newview/llavatarrendernotifier.h b/indra/newview/llavatarrendernotifier.h index a169baef40..ec17b3d9e6 100644 --- a/indra/newview/llavatarrendernotifier.h +++ b/indra/newview/llavatarrendernotifier.h @@ -67,9 +67,9 @@ typedef std::list<LLHUDComplexity> hud_complexity_list_t; // reported that user's agent is too 'heavy' for their settings class LLAvatarRenderNotifier : public LLSingleton<LLAvatarRenderNotifier> { -public: - LLAvatarRenderNotifier(); + LLSINGLETON(LLAvatarRenderNotifier); +public: void displayNotification(bool show_over_limit); bool isNotificationVisible(); @@ -114,10 +114,10 @@ private: // Class to notify user about heavy set of HUD class LLHUDRenderNotifier : public LLSingleton<LLHUDRenderNotifier> { -public: - LLHUDRenderNotifier(); + LLSINGLETON(LLHUDRenderNotifier); ~LLHUDRenderNotifier(); +public: void updateNotificationHUD(hud_complexity_list_t complexity); bool isNotificationVisible(); diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index a5de8a5327..8b9d0dda8b 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -43,6 +43,9 @@ namespace LLNotificationsUI */ class LLChannelManager : public LLSingleton<LLChannelManager> { + LLSINGLETON(LLChannelManager); + virtual ~LLChannelManager(); + public: @@ -65,9 +68,6 @@ public: } }; - LLChannelManager(); - virtual ~LLChannelManager(); - // On LoginCompleted - show StartUp toast void onLoginCompleted(); // removes a channel intended for the startup toast and allows other channels to show their toasts diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index cfc62c07b6..f5721fb348 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -240,6 +240,32 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification) } } + S32 chars_in_line = mMsgText->getRect().getWidth() / messageFont->getWidth("c"); + S32 max_lines = notification["available_height"].asInteger() / (mMsgText->getTextPixelHeight() + 4); + S32 new_line_chars = std::count(messageText.begin(), messageText.end(), '\n'); + S32 lines_count = (messageText.size() - new_line_chars) / chars_in_line + new_line_chars + 1; + + //Remove excessive chars if message is not fit in available height. MAINT-6891 + if(lines_count > max_lines) + { + while(lines_count > max_lines) + { + std::size_t nl_pos = messageText.rfind('\n'); + if (nl_pos != std::string::npos) + { + nl_pos = nl_pos > messageText.length() - chars_in_line? nl_pos : messageText.length() - chars_in_line; + messageText.erase(messageText.begin() + nl_pos, messageText.end()); + } + else + { + messageText.erase(messageText.end() - chars_in_line, messageText.end()); + } + new_line_chars = std::count(messageText.begin(), messageText.end(), '\n'); + lines_count = (messageText.size() - new_line_chars) / chars_in_line + new_line_chars; + } + messageText += " ..."; + } + //append text { LLStyle::Params style_params; diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp index 254e3f61a8..c4f959bfa9 100644 --- a/indra/newview/llchicletbar.cpp +++ b/indra/newview/llchicletbar.cpp @@ -38,7 +38,7 @@ namespace const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; } -LLChicletBar::LLChicletBar(const LLSD&) +LLChicletBar::LLChicletBar() : mChicletPanel(NULL), mToolbarStack(NULL) { diff --git a/indra/newview/llchicletbar.h b/indra/newview/llchicletbar.h index 956c82cb77..6c521dc1d5 100644 --- a/indra/newview/llchicletbar.h +++ b/indra/newview/llchicletbar.h @@ -38,8 +38,9 @@ class LLChicletBar : public LLSingleton<LLChicletBar> , public LLPanel { + LLSINGLETON(LLChicletBar); LOG_CLASS(LLChicletBar); - friend class LLSingleton<LLChicletBar>; + public: BOOL postBuild(); @@ -82,8 +83,6 @@ private: void fitWithTopInfoBar(); protected: - LLChicletBar(const LLSD& key = LLSD()); - LLChicletPanel* mChicletPanel; LLLayoutStack* mToolbarStack; }; diff --git a/indra/newview/llconversationlog.h b/indra/newview/llconversationlog.h index 62f08144b9..035cbcb945 100644 --- a/indra/newview/llconversationlog.h +++ b/indra/newview/llconversationlog.h @@ -109,7 +109,7 @@ private: class LLConversationLog : public LLSingleton<LLConversationLog>, LLIMSessionObserver { - friend class LLSingleton<LLConversationLog>; + LLSINGLETON(LLConversationLog); public: void removeConversation(const LLConversation& conversation); @@ -157,7 +157,6 @@ public: private: - LLConversationLog(); virtual ~LLConversationLog() { if (mAvatarNameCacheConnection.connected()) diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b18e543f0a..15a8aacd37 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -303,7 +303,7 @@ BOOL LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); LLUUID session_id = item? item->getUUID() : LLUUID(); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); - if(!session_floater->hasFocus()) + if(session_floater && !session_floater->hasFocus()) { session_floater->setFocus(true); } @@ -458,6 +458,11 @@ void LLConversationViewSession::refresh() } } } + + if (mSpeakingIndicator) + { + mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel); + } requestArrange(); // Do the regular upstream refresh LLFolderViewFolder::refresh(); diff --git a/indra/newview/lldaycyclemanager.h b/indra/newview/lldaycyclemanager.h index 3d2144960d..04db9d5dac 100644 --- a/indra/newview/lldaycyclemanager.h +++ b/indra/newview/lldaycyclemanager.h @@ -40,6 +40,7 @@ */ class LLDayCycleManager : public LLSingleton<LLDayCycleManager> { + LLSINGLETON_EMPTY_CTOR(LLDayCycleManager); LOG_CLASS(LLDayCycleManager); public: @@ -66,7 +67,6 @@ public: boost::signals2::connection setModifyCallback(const modify_signal_t::slot_type& cb); private: - friend class LLSingleton<LLDayCycleManager>; /*virtual*/ void initSingleton(); void loadAllPresets(); diff --git a/indra/newview/lldeferredsounds.h b/indra/newview/lldeferredsounds.h index bf1eb62957..33f02b3521 100644 --- a/indra/newview/lldeferredsounds.h +++ b/indra/newview/lldeferredsounds.h @@ -33,7 +33,7 @@ struct SoundData; class LLDeferredSounds : public LLSingleton<LLDeferredSounds> { -private: + LLSINGLETON_EMPTY_CTOR(LLDeferredSounds); std::vector<SoundData> soundVector; public: //Add sounds to be played once progress bar is hidden (such as after teleport or loading screen) diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 7836e2cb94..7d2712eec7 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -69,8 +69,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick() } LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() - : LLSingleton<LLDoNotDisturbNotificationStorage>() - , LLNotificationStorage("") + : LLNotificationStorage("") , mDirty(false) { nameToPayloadParameterMap[toastName] = "SESSION_ID"; diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h index 6e68b0d1be..e6cb7835e3 100644 --- a/indra/newview/lldonotdisturbnotificationstorage.h +++ b/indra/newview/lldonotdisturbnotificationstorage.h @@ -47,14 +47,14 @@ public: class LLDoNotDisturbNotificationStorage : public LLSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage { + LLSINGLETON(LLDoNotDisturbNotificationStorage); + ~LLDoNotDisturbNotificationStorage(); + LOG_CLASS(LLDoNotDisturbNotificationStorage); public: static const char * toastName; static const char * offerName; - LLDoNotDisturbNotificationStorage(); - ~LLDoNotDisturbNotificationStorage(); - void initialize(); bool getDirty(); void resetDirty(); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 84ead0bdde..60056ac21d 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -401,7 +401,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass) if ((params.mVertexBuffer->getTypeMask() & mask) != mask) { //FIXME! - LL_WARNS() << "Missing required components, skipping render batch." << LL_ENDL; + LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask + << " present: " << (params.mVertexBuffer->getTypeMask() & mask) + << ". Skipping render batch." << LL_ENDL; continue; } diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp index a626ad1bff..b97e483fd9 100644 --- a/indra/newview/llenvmanager.cpp +++ b/indra/newview/llenvmanager.cpp @@ -609,10 +609,15 @@ bool LLEnvManagerNew::useRegionSky() return true; } - // *TODO: Support fixed sky from region. - - // Otherwise apply region day cycle. + // Otherwise apply region day cycle/skies. LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL; + + // *TODO: Support fixed sky from region. Just do sky reset for now. + if (region_settings.getSkyMap().size() == 1) + { + // Region is set to fixed sky. Reset. + useSkyParams(region_settings.getSkyMap().beginMap()->second); + } return useDayCycleParams( region_settings.getWLDayCycle(), LLEnvKey::SCOPE_REGION, diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h index c7877303fc..6a0a267f4e 100644 --- a/indra/newview/llenvmanager.h +++ b/indra/newview/llenvmanager.h @@ -162,14 +162,13 @@ public: */ class LLEnvManagerNew : public LLSingleton<LLEnvManagerNew> { + LLSINGLETON(LLEnvManagerNew); LOG_CLASS(LLEnvManagerNew); public: typedef boost::signals2::signal<void()> prefs_change_signal_t; typedef boost::signals2::signal<void()> region_settings_change_signal_t; typedef boost::signals2::signal<void(bool)> region_settings_applied_signal_t; - LLEnvManagerNew(); - // getters to access user env. preferences bool getUseRegionSettings() const; bool getUseDayCycle() const; @@ -231,7 +230,6 @@ public: void onRegionSettingsApplyResponse(bool ok); private: - friend class LLSingleton<LLEnvManagerNew>; /*virtual*/ void initSingleton(); void loadUserPrefs(); diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h index fcfbd1ce7d..e7a6a2a725 100644 --- a/indra/newview/llestateinfomodel.h +++ b/indra/newview/llestateinfomodel.h @@ -38,6 +38,7 @@ class LLMessageSystem; */ class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel> { + LLSINGLETON(LLEstateInfoModel); LOG_CLASS(LLEstateInfoModel); public: @@ -73,11 +74,8 @@ public: protected: typedef std::vector<std::string> strings_t; - friend class LLSingleton<LLEstateInfoModel>; friend class LLDispatchEstateUpdateInfo; - LLEstateInfoModel(); - /// refresh model with data from the incoming server message void update(const strings_t& strings); diff --git a/indra/newview/llexperiencelog.h b/indra/newview/llexperiencelog.h index ac227db336..09e0cd8821 100644 --- a/indra/newview/llexperiencelog.h +++ b/indra/newview/llexperiencelog.h @@ -33,6 +33,7 @@ class LLExperienceLog : public LLSingleton<LLExperienceLog> { + LLSINGLETON(LLExperienceLog); public: typedef boost::signals2::signal<void(LLSD&)> callback_signal_t; @@ -62,7 +63,6 @@ public: void setEventsToSave(LLSD new_events){mEventsToSave = new_events; } bool isNotExpired(std::string& date); protected: - LLExperienceLog(); void handleExperienceMessage(LLSD& message); @@ -81,7 +81,6 @@ protected: bool mNotifyNewEvent; friend class LLExperienceLogDispatchHandler; - friend class LLSingleton<LLExperienceLog>; }; diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h index 2a2cdb5499..7fd4070f54 100644 --- a/indra/newview/llfacebookconnect.h +++ b/indra/newview/llfacebookconnect.h @@ -43,6 +43,8 @@ class LLEventPump; */ class LLFacebookConnect : public LLSingleton<LLFacebookConnect> { + LLSINGLETON(LLFacebookConnect); + ~LLFacebookConnect() {}; LOG_CLASS(LLFacebookConnect); public: enum EConnectionState @@ -86,10 +88,7 @@ public: void openFacebookWeb(std::string url); private: - friend class LLSingleton<LLFacebookConnect>; - LLFacebookConnect(); - ~LLFacebookConnect() {}; std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false); EConnectionState mConnectionState; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index d1e77f57e2..a69b3b7dc7 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -238,7 +238,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) { return TRUE; } - else if (mHoverBarIndex == -1) + else if (mHoverBarIndex < 0) { mHoverBarIndex = 0; } @@ -260,7 +260,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) { hover_bar = &bar; if (bar.mTimeBlock->getTreeNode().mCollapsed) - { + { // stop on first collapsed BlockTimerStatHandle, since we can't select any children break; } diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 2115f77cf3..cac32c7f2a 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -34,6 +34,7 @@ #include "llinventoryobserver.h" #include "llinventorymodel.h" #include "llviewerinventory.h" +#include "llinitdestroyclass.h" class LLMenuItemCallGL; class LLToggleableMenu; @@ -173,6 +174,7 @@ private: class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage> , public LLDestroyClass<LLFavoritesOrderStorage> { + LLSINGLETON(LLFavoritesOrderStorage); LOG_CLASS(LLFavoritesOrderStorage); public: /** @@ -221,10 +223,6 @@ public: std::map<LLUUID,std::string> mFavoriteNames; private: - friend class LLSingleton<LLFavoritesOrderStorage>; - LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); } - ~LLFavoritesOrderStorage() {} - /** * Removes sort indexes for items which are not in Favorites bar for now. */ @@ -274,4 +272,10 @@ private: }; }; + +inline +LLFavoritesOrderStorage::LLFavoritesOrderStorage() : + mIsDirty(false), mUpdateRequired(false) +{ load(); } + #endif // LL_LLFAVORITESBARCTRL_H diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index c3d87cea0b..54bd07329a 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -97,20 +97,10 @@ protected: class LLFeatureManager : public LLFeatureList, public LLSingleton<LLFeatureManager> { -public: - LLFeatureManager() - : LLFeatureList("default"), - - mInited(FALSE), - mTableVersion(0), - mSafe(FALSE), - mGPUClass(GPU_CLASS_UNKNOWN), - mExpectedGLVersion(0.f), - mGPUSupported(FALSE) - { - } + LLSINGLETON(LLFeatureManager); ~LLFeatureManager() {cleanupFeatureTables();} +public: // initialize this by loading feature table and gpu table void init(); @@ -181,5 +171,17 @@ protected: BOOL mGPUSupported; }; +inline +LLFeatureManager::LLFeatureManager() +: LLFeatureList("default"), + + mInited(FALSE), + mTableVersion(0), + mSafe(FALSE), + mGPUClass(GPU_CLASS_UNKNOWN), + mExpectedGLVersion(0.f), + mGPUSupported(FALSE) +{ +} #endif // LL_LLFEATUREMANAGER_H diff --git a/indra/newview/llfilteredwearablelist.cpp b/indra/newview/llfilteredwearablelist.cpp index a29ccf2b6d..f2af9b5300 100644 --- a/indra/newview/llfilteredwearablelist.cpp +++ b/indra/newview/llfilteredwearablelist.cpp @@ -93,4 +93,9 @@ void LLFilteredWearableListManager::populateList() mWearableList->refreshList(item_array); } +void LLFilteredWearableListManager::holdProgress() +{ + mWearableList->setForceRefresh(false); +} + // EOF diff --git a/indra/newview/llfilteredwearablelist.h b/indra/newview/llfilteredwearablelist.h index c21458ca98..f44ab1466f 100644 --- a/indra/newview/llfilteredwearablelist.h +++ b/indra/newview/llfilteredwearablelist.h @@ -56,6 +56,11 @@ public: */ void populateList(); + /** + * Drop operation + */ + void holdProgress(); + private: LLInventoryItemsList* mWearableList; LLInventoryCollectFunctor* mCollector; diff --git a/indra/newview/llflickrconnect.h b/indra/newview/llflickrconnect.h index 0155804da0..43cadca708 100644 --- a/indra/newview/llflickrconnect.h +++ b/indra/newview/llflickrconnect.h @@ -43,6 +43,8 @@ class LLEventPump; */ class LLFlickrConnect : public LLSingleton<LLFlickrConnect> { + LLSINGLETON(LLFlickrConnect); + ~LLFlickrConnect() {}; LOG_CLASS(LLFlickrConnect); public: enum EConnectionState @@ -80,10 +82,7 @@ public: void openFlickrWeb(std::string url); private: - friend class LLSingleton<LLFlickrConnect>; - LLFlickrConnect(); - ~LLFlickrConnect() {}; std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false); EConnectionState mConnectionState; diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index aa7bfbfdb7..c394eb815b 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -502,37 +502,39 @@ void LLFloaterAvatarPicker::find() url.reserve(128); // avoid a memory allocation or two LLViewerRegion* region = gAgent.getRegion(); - url = region->getCapability("AvatarPickerSearch"); - // Prefer use of capabilities to search on both SLID and display name - if (!url.empty()) + if(region) { - // capability urls don't end in '/', but we need one to parse - // query parameters correctly - if (url.size() > 0 && url[url.size()-1] != '/') + url = region->getCapability("AvatarPickerSearch"); + // Prefer use of capabilities to search on both SLID and display name + if (!url.empty()) { - url += "/"; - } - url += "?page_size=100&names="; - std::replace(text.begin(), text.end(), '.', ' '); - url += LLURI::escape(text); - LL_INFOS() << "avatar picker " << url << LL_ENDL; + // capability urls don't end in '/', but we need one to parse + // query parameters correctly + if (url.size() > 0 && url[url.size()-1] != '/') + { + url += "/"; + } + url += "?page_size=100&names="; + std::replace(text.begin(), text.end(), '.', ' '); + url += LLURI::escape(text); + LL_INFOS() << "avatar picker " << url << LL_ENDL; - LLCoros::instance().launch("LLFloaterAvatarPicker::findCoro", - boost::bind(&LLFloaterAvatarPicker::findCoro, url, mQueryID, getKey().asString())); - } - else - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("AvatarPickerRequest"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->addUUID("QueryID", mQueryID); // not used right now - msg->nextBlock("Data"); - msg->addString("Name", text); - gAgent.sendReliableMessage(); + LLCoros::instance().launch("LLFloaterAvatarPicker::findCoro", + boost::bind(&LLFloaterAvatarPicker::findCoro, url, mQueryID, getKey().asString())); + } + else + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("AvatarPickerRequest"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID", gAgent.getID()); + msg->addUUID("SessionID", gAgent.getSessionID()); + msg->addUUID("QueryID", mQueryID); // not used right now + msg->nextBlock("Data"); + msg->addString("Name", text); + gAgent.sendReliableMessage(); + } } - getChild<LLScrollListCtrl>("SearchResults")->deleteAllItems(); getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching")); diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index b32ac860aa..4607b4ac41 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -44,7 +44,6 @@ #include "llinventorymodel.h" // for gInventory #include "llfirstuse.h" #include "llfloaterreg.h" -#include "llfloaterinventory.h" // for LLInventoryIcon::getIcon #include "llnotificationsutil.h" #include "llselectmgr.h" #include "llscrolllistctrl.h" diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index d33a138e94..5f606ec326 100644 --- a/indra/newview/llfloaterbvhpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1004,7 +1004,7 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata) { std::string name = floaterp->getChild<LLUICtrl>("name_form")->getValue().asString(); std::string desc = floaterp->getChild<LLUICtrl>("description_form")->getValue().asString(); - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); LLResourceUploadInfo::ptr_t assetUpdloadInfo(new LLResourceUploadInfo( floaterp->mTransactionID, LLAssetType::AT_ANIMATION, diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 15b67b905d..7039e48e74 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -101,7 +101,7 @@ LLFloaterIMContainer::~LLFloaterIMContainer() gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed()); gSavedPerAccountSettings.setBOOL("ConversationsParticipantListCollapsed", !isParticipantListExpanded()); - if (!LLSingleton<LLIMMgr>::destroyed()) + if (LLIMMgr::instanceExists()) { LLIMMgr::getInstance()->removeSessionObserver(this); } diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 9fd731ed56..4cd91c53d8 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -285,6 +285,14 @@ void LLFloaterIMNearbyChatScreenChannel::addChat(LLSD& chat) if(mStopProcessing) return; + if (mFloaterSnapRegion == NULL) + { + mFloaterSnapRegion = gViewerWindow->getRootView()->getChildView("floater_snap_region"); + } + LLRect channel_rect; + mFloaterSnapRegion->localRectToOtherView(mFloaterSnapRegion->getLocalRect(), &channel_rect, gFloaterView); + chat["available_height"] = channel_rect.getHeight() - channel_rect.mBottom - gSavedSettings.getS32("ToastGap") - 110;; + /* find last toast and check ID */ @@ -380,7 +388,7 @@ void LLFloaterIMNearbyChatScreenChannel::arrangeToasts() setFollows(FOLLOWS_ALL); } - LLRect toast_rect; + LLRect toast_rect; updateRect(); LLRect channel_rect; diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp deleted file mode 100644 index 9b9b90e521..0000000000 --- a/indra/newview/llfloaterinventory.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @file llfloaterinventory.cpp - * @brief Implementation of the inventory view and associated stuff. - * - * $LicenseInfo:firstyear=2001&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 "llfloaterinventory.h" - -#include "llagentcamera.h" -//#include "llfirstuse.h" -#include "llfloaterreg.h" -#include "llinventorymodel.h" -#include "llpanelmaininventory.h" -#include "llresmgr.h" -#include "llviewerfoldertype.h" -#include "lltransientfloatermgr.h" - -///---------------------------------------------------------------------------- -/// LLFloaterInventory -///---------------------------------------------------------------------------- - -LLFloaterInventory::LLFloaterInventory(const LLSD& key) - : LLFloater(key) -{ - LLTransientFloaterMgr::getInstance()->addControlView(this); -} - -LLFloaterInventory::~LLFloaterInventory() -{ - LLTransientFloaterMgr::getInstance()->removeControlView(this); -} - -BOOL LLFloaterInventory::postBuild() -{ - mPanelMainInventory = findChild<LLPanelMainInventory>("Inventory Panel"); - return TRUE; -} - -LLInventoryPanel* LLFloaterInventory::getPanel() -{ - if (mPanelMainInventory) - return mPanelMainInventory->getPanel(); - return NULL; -} - -// static -LLFloaterInventory* LLFloaterInventory::showAgentInventory() -{ - // Hack to generate semi-unique key for each inventory floater. - static S32 instance_num = 0; - instance_num = (instance_num + 1) % S32_MAX; - - LLFloaterInventory* iv = NULL; - if (!gAgentCamera.cameraMouselook()) - { - iv = LLFloaterReg::showTypedInstance<LLFloaterInventory>("inventory", LLSD(instance_num)); - } - return iv; -} - -// static -void LLFloaterInventory::cleanup() -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();) - { - LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter++); - if (iv) - { - iv->destroy(); - } - } -} - -void LLFloaterInventory::onOpen(const LLSD& key) -{ - //LLFirstUse::useInventory(); -} - -void LLFloaterInventory::onClose(bool app_quitting) -{ - LLFloater::onClose(app_quitting); - if (mKey.asInteger() > 1) - { - destroy(); - } -} diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h deleted file mode 100644 index 823c4903b4..0000000000 --- a/indra/newview/llfloaterinventory.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file llfloaterinventory.h - * @brief LLFloaterInventory, LLInventoryFolder, and LLInventoryItem - * class definition - * - * $LicenseInfo:firstyear=2001&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_LLFLOATERINVENTORY_H -#define LL_LLFLOATERINVENTORY_H - -#include "llfloater.h" -#include "llfoldertype.h" - -class LLInventoryPanel; -class LLPanelMainInventory; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFloaterInventory -// -// This deals with the buttons and views used to navigate as -// well as controlling the behavior of the overall object. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFloaterInventory : public LLFloater -{ -public: - LLFloaterInventory(const LLSD& key); - ~LLFloaterInventory(); - - BOOL postBuild(); - - // This method makes sure that an inventory view exists, is - // visible, and has focus. The view chosen is returned. - static LLFloaterInventory* showAgentInventory(); - - // Final cleanup, destroy all open inventory views. - static void cleanup(); - - // Inherited functionality - /*virtual*/ void onOpen(const LLSD& key); - /*virtual*/ void onClose(bool app_quitting); - - LLInventoryPanel* getPanel(); - LLPanelMainInventory* getMainInventoryPanel() { return mPanelMainInventory;} -private: - LLPanelMainInventory* mPanelMainInventory; -}; - -#endif // LL_LLFLOATERINVENTORY_H - - - diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 7aae48cf5d..c654817849 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1197,6 +1197,7 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL) , mLodsQuery() +, mLodsWithParsingError() , mPelvisZOffset( 0.0f ) , mLegacyRigValid( false ) , mRigValidJointUpload( false ) @@ -1780,8 +1781,8 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable // this is the initial file picking. Close the whole floater // if we don't have a base model to show for high LOD. mFMP->closeFloater(false); - mLoading = false; } + mLoading = false; return; } @@ -1938,9 +1939,16 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) { mLoading = false ; mModelLoader = NULL; + mLodsWithParsingError.push_back(loaded_lod); return ; } + mLodsWithParsingError.erase(std::remove(mLodsWithParsingError.begin(), mLodsWithParsingError.end(), loaded_lod), mLodsWithParsingError.end()); + if(mLodsWithParsingError.empty()) + { + mFMP->childEnable( "calculate_btn" ); + } + // Copy determinations about rig so UI will reflect them // setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload()); @@ -2162,7 +2170,11 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) if (!mBaseModel.empty()) { const std::string& model_name = mBaseModel[0]->getName(); - mFMP->getChild<LLUICtrl>("description_form")->setValue(model_name); + LLLineEditor* description_form = mFMP->getChild<LLLineEditor>("description_form"); + if (description_form->getText().empty()) + { + description_form->setText(model_name); + } } } refresh(); @@ -2687,17 +2699,7 @@ void LLModelPreview::updateStatusMessages() setLoadState( LLModelLoader::ERROR_MATERIALS ); mFMP->childDisable( "calculate_btn" ); } - - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) ) - { - setLoadState( LLModelLoader::ERROR_MATERIALS ); - mFMP->childDisable( "calculate_btn" ); - } - - if (lod_model) + else { //for each model in the lod S32 cur_tris = 0; @@ -3630,7 +3632,7 @@ BOOL LLModelPreview::render() } } - if (has_skin_weights) + if (has_skin_weights && lodsReady()) { //model has skin weights, enable view options for skin weights and joint positions if (fmp && isLegacyRigValid() ) { @@ -4555,4 +4557,12 @@ void LLFloaterModelPreview::setPermissonsErrorStatus(S32 status, const std::stri LLNotificationsUtil::add("MeshUploadPermError"); } +bool LLFloaterModelPreview::isModelLoading() +{ + if(mModelPreview) + { + return mModelPreview->mLoading; + } + return false; +} diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index a7a5c1b33a..0b2b7db2b6 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -115,6 +115,8 @@ public: void enableViewOption(const std::string& option); void disableViewOption(const std::string& option); + bool isModelLoading(); + // shows warning message if agent has no permissions to upload model /*virtual*/ void onPermissionsReceived(const LLSD& result); @@ -304,6 +306,7 @@ public: static bool sIgnoreLoadedCallback; std::vector<S32> mLodsQuery; + std::vector<S32> mLodsWithParsingError; protected: diff --git a/indra/newview/llfloatermodeluploadbase.cpp b/indra/newview/llfloatermodeluploadbase.cpp index 0fe97fd610..7cdfd56d9a 100644 --- a/indra/newview/llfloatermodeluploadbase.cpp +++ b/indra/newview/llfloatermodeluploadbase.cpp @@ -80,6 +80,7 @@ void LLFloaterModelUploadBase::requestAgentUploadPermissionsCoro(std::string url if (!observer) { LL_WARNS("MeshUploadFlag") << "Unable to get observer after call to '" << url << "' aborting." << LL_ENDL; + return; } if (!status) diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 4a5732aecf..c9a689281e 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -123,7 +123,7 @@ BOOL LLFloaterNameDesc::postBuild() // Cancel button getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnCancel, this)); - getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() )); + getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload() )); setDefaultBtn("ok_btn"); @@ -162,7 +162,7 @@ void LLFloaterNameDesc::onBtnOK( ) getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::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). + 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). if (can_afford_transaction(expected_upload_cost)) { diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp index feaeef4ad0..ed1ad4426f 100644 --- a/indra/newview/llfloaterobjectweights.cpp +++ b/indra/newview/llfloaterobjectweights.cpp @@ -145,6 +145,14 @@ void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel) { S32 rezzed_prims = parcel->getSimWidePrimCount(); S32 total_capacity = parcel->getSimWideMaxPrimCapacity(); + // Can't have more than region max tasks, regardless of parcel + // object bonus factor. + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + if (region) + { + S32 max_tasks_per_region = (S32)region->getMaxTasks(); + total_capacity = llmin(total_capacity, max_tasks_per_region); + } mRezzedOnLand->setText(llformat("%d", rezzed_prims)); mRemainingCapacity->setText(llformat("%d", total_capacity - rezzed_prims)); diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index ef746d308d..2a1749bd42 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -39,7 +39,6 @@ #include "lltextbox.h" #include "llinventorybridge.h" -#include "llfloaterinventory.h" #include "llinventorymodel.h" #include "llinventorypanel.h" #include "llpanelobjectinventory.h" diff --git a/indra/newview/llfloateroutfitphotopreview.cpp b/indra/newview/llfloateroutfitphotopreview.cpp new file mode 100644 index 0000000000..6c39db730c --- /dev/null +++ b/indra/newview/llfloateroutfitphotopreview.cpp @@ -0,0 +1,289 @@ +/** + * @file llfloateroutfitphotopreview.cpp + * @brief LLFloaterOutfitPhotoPreview class implementation + * + * $LicenseInfo:firstyear=2002&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 "llwindow.h" + +#include "llfloateroutfitphotopreview.h" + +#include "llagent.h" +#include "llappearancemgr.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "llfilepicker.h" +#include "llfloaterreg.h" +#include "llimagetga.h" +#include "llimagepng.h" +#include "llinventory.h" +#include "llinventorymodel.h" +#include "llnotificationsutil.h" +#include "llresmgr.h" +#include "lltrans.h" +#include "lltextbox.h" +#include "lltextureview.h" +#include "llui.h" +#include "llviewerinventory.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" +#include "lllineeditor.h" + +const S32 MAX_OUTFIT_PHOTO_WIDTH = 256; +const S32 MAX_OUTFIT_PHOTO_HEIGHT = 256; + +const S32 CLIENT_RECT_VPAD = 4; + +LLFloaterOutfitPhotoPreview::LLFloaterOutfitPhotoPreview(const LLSD& key) + : LLPreview(key), + mUpdateDimensions(TRUE), + mImage(NULL), + mOutfitID(LLUUID()), + mImageOldBoostLevel(LLGLTexture::BOOST_NONE), + mExceedLimits(FALSE) +{ + updateImageID(); +} + +LLFloaterOutfitPhotoPreview::~LLFloaterOutfitPhotoPreview() +{ + LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ; + + if (mImage.notNull()) + { + mImage->setBoostLevel(mImageOldBoostLevel); + mImage = NULL; + } +} + +// virtual +BOOL LLFloaterOutfitPhotoPreview::postBuild() +{ + getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterOutfitPhotoPreview::onOkBtn, this)); + getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloaterOutfitPhotoPreview::onCancelBtn, this)); + + return LLPreview::postBuild(); +} + +void LLFloaterOutfitPhotoPreview::draw() +{ + updateDimensions(); + + LLPreview::draw(); + + if (!isMinimized()) + { + LLGLSUIDefault gls_ui; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + const LLRect& border = mClientRect; + LLRect interior = mClientRect; + interior.stretch( -PREVIEW_BORDER_WIDTH ); + + // ...border + gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f)); + gl_rect_2d_checkerboard( interior ); + + if ( mImage.notNull() ) + { + // Draw the texture + gGL.diffuseColor3f( 1.f, 1.f, 1.f ); + gl_draw_scaled_image(interior.mLeft, + interior.mBottom, + interior.getWidth(), + interior.getHeight(), + mImage); + + // Pump the texture priority + F32 pixel_area = (F32)(interior.getWidth() * interior.getHeight() ); + mImage->addTextureStats( pixel_area ); + + S32 int_width = interior.getWidth(); + S32 int_height = interior.getHeight(); + mImage->setKnownDrawSize(int_width, int_height); + } + } + +} + +// virtual +void LLFloaterOutfitPhotoPreview::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + LLPreview::reshape(width, height, called_from_parent); + + LLRect dim_rect(getChildView("dimensions")->getRect()); + + S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE; + + S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD; + + LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0); + client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); + client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ; + + S32 client_width = client_rect.getWidth(); + S32 client_height = client_width; + + if(client_height > client_rect.getHeight()) + { + client_height = client_rect.getHeight(); + client_width = client_height; + } + mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height); + +} + + +void LLFloaterOutfitPhotoPreview::updateDimensions() +{ + if (!mImage) + { + return; + } + if ((mImage->getFullWidth() * mImage->getFullHeight()) == 0) + { + return; + } + + if (mAssetStatus != PREVIEW_ASSET_LOADED) + { + mAssetStatus = PREVIEW_ASSET_LOADED; + mUpdateDimensions = TRUE; + } + + getChild<LLUICtrl>("dimensions")->setTextArg("[WIDTH]", llformat("%d", mImage->getFullWidth())); + getChild<LLUICtrl>("dimensions")->setTextArg("[HEIGHT]", llformat("%d", mImage->getFullHeight())); + + if ((mImage->getFullWidth() <= MAX_OUTFIT_PHOTO_WIDTH) && (mImage->getFullHeight() <= MAX_OUTFIT_PHOTO_HEIGHT)) + { + getChild<LLButton>("ok_btn")->setEnabled(TRUE); + mExceedLimits = FALSE; + } + else + { + mExceedLimits = TRUE; + LLStringUtil::format_map_t args; + args["MAX_WIDTH"] = llformat("%d", MAX_OUTFIT_PHOTO_WIDTH); + args["MAX_HEIGHT"] = llformat("%d", MAX_OUTFIT_PHOTO_HEIGHT); + std::string label = getString("exceed_limits", args); + getChild<LLUICtrl>("notification")->setValue(label); + getChild<LLUICtrl>("notification")->setColor(LLColor4::yellow); + getChild<LLButton>("ok_btn")->setEnabled(FALSE); + } + + if (mUpdateDimensions) + { + mUpdateDimensions = FALSE; + + reshape(getRect().getWidth(), getRect().getHeight()); + gFloaterView->adjustToFitScreen(this, FALSE); + } +} + +void LLFloaterOutfitPhotoPreview::loadAsset() +{ + if (mImage.notNull()) + { + mImage->setBoostLevel(mImageOldBoostLevel); + } + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mImageOldBoostLevel = mImage->getBoostLevel(); + mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); + mImage->forceToSaveRawImage(0) ; + mAssetStatus = PREVIEW_ASSET_LOADING; + mUpdateDimensions = TRUE; + updateDimensions(); +} + +LLPreview::EAssetStatus LLFloaterOutfitPhotoPreview::getAssetStatus() +{ + if (mImage.notNull() && (mImage->getFullWidth() * mImage->getFullHeight() > 0)) + { + mAssetStatus = PREVIEW_ASSET_LOADED; + } + return mAssetStatus; +} + +void LLFloaterOutfitPhotoPreview::updateImageID() +{ + const LLViewerInventoryItem *item = static_cast<const LLViewerInventoryItem*>(getItem()); + if(item) + { + mImageID = item->getAssetUUID(); + LLPermissions perm(item->getPermissions()); + } + else + { + mImageID = mItemUUID; + } + +} + +/* virtual */ +void LLFloaterOutfitPhotoPreview::setObjectID(const LLUUID& object_id) +{ + mObjectUUID = object_id; + + const LLUUID old_image_id = mImageID; + + updateImageID(); + if (mImageID != old_image_id) + { + mAssetStatus = PREVIEW_ASSET_UNLOADED; + loadAsset(); + } + refreshFromItem(); +} + +void LLFloaterOutfitPhotoPreview::setOutfitID(const LLUUID& outfit_id) +{ + mOutfitID = outfit_id; + LLViewerInventoryCategory* outfit_folder = gInventory.getCategory(mOutfitID); + if(outfit_folder && !mExceedLimits) + { + getChild<LLUICtrl>("notification")->setValue( getString("photo_confirmation")); + getChild<LLUICtrl>("notification")->setTextArg("[OUTFIT]", outfit_folder->getName()); + getChild<LLUICtrl>("notification")->setColor(LLColor4::white); + } + +} + +void LLFloaterOutfitPhotoPreview::onOkBtn() +{ + if(mOutfitID.notNull() && getItem()) + { + LLAppearanceMgr::instance().removeOutfitPhoto(mOutfitID); + LLPointer<LLInventoryCallback> cb = NULL; + link_inventory_object(mOutfitID, LLConstPointer<LLInventoryObject>(getItem()), cb); + } + closeFloater(); +} + +void LLFloaterOutfitPhotoPreview::onCancelBtn() +{ + closeFloater(); +} diff --git a/indra/newview/llfloateroutfitphotopreview.h b/indra/newview/llfloateroutfitphotopreview.h new file mode 100644 index 0000000000..a1e7b58abe --- /dev/null +++ b/indra/newview/llfloateroutfitphotopreview.h @@ -0,0 +1,77 @@ +/** + * @file llfloateroutfitphotopreview.h + * @brief LLFloaterOutfitPhotoPreview class definition + * + * $LicenseInfo:firstyear=2002&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_LLFLOATEROUTFITPHOTOPREVIEW_H +#define LL_LLFLOATEROUTFITPHOTOPREVIEW_H + +#include "llpreview.h" +#include "llbutton.h" +#include "llframetimer.h" +#include "llviewertexture.h" + +class LLComboBox; +class LLImageRaw; + +class LLFloaterOutfitPhotoPreview : public LLPreview +{ +public: + LLFloaterOutfitPhotoPreview(const LLSD& key); + ~LLFloaterOutfitPhotoPreview(); + + virtual void draw(); + + virtual void loadAsset(); + virtual EAssetStatus getAssetStatus(); + + virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + /*virtual*/ void setObjectID(const LLUUID& object_id); + + void setOutfitID(const LLUUID& outfit_id); + void onOkBtn(); + void onCancelBtn(); + +protected: + void init(); + /* virtual */ BOOL postBuild(); + +private: + void updateImageID(); // set what image is being uploaded. + void updateDimensions(); + LLUUID mImageID; + LLUUID mOutfitID; + LLPointer<LLViewerFetchedTexture> mImage; + S32 mImageOldBoostLevel; + + // This is stored off in a member variable, because the save-as + // button and drag and drop functionality need to know. + BOOL mUpdateDimensions; + + BOOL mExceedLimits; + + LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; +}; +#endif // LL_LLFLOATEROUTFITPHOTOPREVIEW_H diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index dfe462c8d1..87973c2286 100644 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -284,7 +284,6 @@ void LLFloaterPay::processPayPriceReply(LLMessageSystem* msg, void **userdata) self->mQuickPayButton[i]->setLabelUnselected(button_str); self->mQuickPayButton[i]->setVisible(TRUE); self->mQuickPayInfo[i]->mAmount = pay_button; - self->getChildView("fastpay text")->setVisible(TRUE); if ( pay_button > max_pay_amount ) { @@ -412,7 +411,6 @@ void LLFloaterPay::payDirectly(money_callback callback, floater->getChildView("pay btn")->setVisible(TRUE); floater->getChildView("amount text")->setVisible(TRUE); - floater->getChildView("fastpay text")->setVisible(TRUE); for(S32 i=0;i<MAX_PAY_BUTTONS;++i) { floater->mQuickPayButton[i]->setVisible(TRUE); @@ -594,7 +592,8 @@ void LLFloaterPay::give(S32 amount) else { // just transfer the L$ - mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, LLStringUtil::null); + std::string paymentMessage(getChild<LLLineEditor>("payment_message")->getValue().asString()); + mCallback(mTargetUUID, gAgent.getRegion(), amount, mTargetIsGroup, TRANS_GIFT, (paymentMessage.empty() ? LLStringUtil::null : paymentMessage)); // check if the payee needs to be unmuted LLMuteList::getInstance()->autoRemove(mTargetUUID, LLMuteList::AR_MONEY); diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index b0b2770c6e..2281ea1496 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -183,6 +183,11 @@ void LLFloaterPermsDefault::sendInitialPerms() void LLFloaterPermsDefault::updateCap() { + if (!gAgent.getRegion()) + { + LL_WARNS("Avatar") << "Region not set, cannot request capability update" << LL_ENDL; + return; + } std::string object_url = gAgent.getRegion()->getCapability("AgentPreferences"); if(!object_url.empty()) diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index a6ce0ba678..790e2b3ad1 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -37,6 +37,7 @@ #include "llcachename.h" #include "llcheckboxctrl.h" #include "llfontgl.h" +#include "llimagebmp.h" #include "llimagej2c.h" #include "llinventory.h" #include "llnotificationsutil.h" @@ -76,6 +77,7 @@ #include "llselectmgr.h" #include "llversioninfo.h" #include "lluictrlfactory.h" +#include "llviewercontrol.h" #include "llviewernetwork.h" #include "llagentui.h" @@ -86,6 +88,7 @@ #include "llcorehttputil.h" #include "llviewerassetupload.h" +const std::string SCREEN_PREV_FILENAME = "screen_report_last.bmp"; //========================================================================= //----------------------------------------------------------------------------- @@ -181,11 +184,6 @@ BOOL LLFloaterReporter::postBuild() } setPosBox(pos); - // Take a screenshot, but don't draw this floater. - setVisible(FALSE); - takeScreenshot(); - setVisible(TRUE); - // Default text to be blank getChild<LLUICtrl>("object_name")->setValue(LLStringUtil::null); getChild<LLUICtrl>("owner_name")->setValue(LLStringUtil::null); @@ -769,18 +767,24 @@ void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url } } -void LLFloaterReporter::takeScreenshot() +void LLFloaterReporter::takeScreenshot(bool use_prev_screenshot) { - const S32 IMAGE_WIDTH = 1024; - const S32 IMAGE_HEIGHT = 768; - - LLPointer<LLImageRaw> raw = new LLImageRaw; - if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE)) + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", TRUE); + if(!use_prev_screenshot) { - LL_WARNS() << "Unable to take screenshot" << LL_ENDL; - return; + std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME); + LLPointer<LLImageBMP> bmp_image = new LLImageBMP; + if(bmp_image->encode(mImageRaw, 0.0f)) + { + bmp_image->save(screenshot_filename); + } + } + else + { + mImageRaw = mPrevImageRaw; } - LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(raw); + + LLPointer<LLImageJ2C> upload_data = LLViewerTextureList::convertToUploadFile(mImageRaw); // create a resource data mResourceDatap->mInventoryType = LLInventoryType::IT_NONE; @@ -812,7 +816,7 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer<LLViewerFetchedTexture> image_in_list = LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid); - image_in_list->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER); + image_in_list->createGLTexture(0, mImageRaw, 0, TRUE, LLGLTexture::OTHER); // the texture picker then uses that texture LLTextureCtrl* texture = getChild<LLTextureCtrl>("screenshot"); @@ -822,7 +826,46 @@ void LLFloaterReporter::takeScreenshot() texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid); texture->setCaption(getString("Screenshot")); } +} + +void LLFloaterReporter::onOpen(const LLSD& key) +{ + mImageRaw = new LLImageRaw; + const S32 IMAGE_WIDTH = 1024; + const S32 IMAGE_HEIGHT = 768; + + // Take a screenshot, but don't draw this floater. + setVisible(FALSE); + if( !gViewerWindow->rawSnapshot(mImageRaw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE, TRUE, FALSE)) + { + LL_WARNS() << "Unable to take screenshot" << LL_ENDL; + setVisible(TRUE); + return; + } + setVisible(TRUE); + + if(gSavedPerAccountSettings.getBOOL("PreviousScreenshotForReport")) + { + std::string screenshot_filename(gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_PREV_FILENAME); + mPrevImageRaw = new LLImageRaw; + LLPointer<LLImageBMP> start_image_bmp = new LLImageBMP; + if(start_image_bmp->load(screenshot_filename)) + { + if (start_image_bmp->decode(mPrevImageRaw, 0.0f)) + { + LLNotificationsUtil::add("LoadPreviousReportScreenshot", LLSD(), LLSD(), boost::bind(&LLFloaterReporter::onLoadScreenshotDialog,this, _1, _2)); + return; + } + } + } + takeScreenshot(); +} + +void LLFloaterReporter::onLoadScreenshotDialog(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + takeScreenshot(option == 0); } void LLFloaterReporter::uploadImage() @@ -886,6 +929,11 @@ void LLFloaterReporter::setPosBox(const LLVector3d &pos) getChild<LLUICtrl>("pos_field")->setValue(pos_string); } +void LLFloaterReporter::onClose(bool app_quitting) +{ + gSavedPerAccountSettings.setBOOL("PreviousScreenshotForReport", app_quitting); +} + // void LLFloaterReporter::setDescription(const std::string& description, LLMeanCollisionData *mcd) // { diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index 1aff07bd37..e5232268c0 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -81,6 +81,8 @@ public: LLFloaterReporter(const LLSD& key); /*virtual*/ ~LLFloaterReporter(); /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onClose(bool app_quitting); virtual void draw(); void setReportType(EReportType type) { mReportType = type; } @@ -103,10 +105,12 @@ public: void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id); + void onLoadScreenshotDialog(const LLSD& notification, const LLSD& response); + private: static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null, const LLUUID& experience_id = LLUUID::null); - void takeScreenshot(); + void takeScreenshot(bool use_prev_screenshot = false); void sendReportViaCaps(std::string url); void uploadImage(); bool validateReport(); @@ -140,6 +144,9 @@ private: std::string mDefaultSummary; LLResourceData* mResourceDatap; boost::signals2::connection mAvatarNameCacheConnection; + + LLPointer<LLImageRaw> mImageRaw; + LLPointer<LLImageRaw> mPrevImageRaw; }; #endif diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index c7218ad9d5..8b3cfa7fd5 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -80,6 +80,11 @@ void LLFloaterSidePanelContainer::closeFloater(bool app_quitting) } LLFloater::closeFloater(app_quitting); + + if (getInstanceName() == "inventory" && !getKey().isUndefined()) + { + destroy(); + } } LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index d7ecd52e57..635514e26c 100644 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -53,6 +53,8 @@ public: /*virtual*/ void closeFloater(bool app_quitting = false); + void cleanup() { destroy(); } + LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); static void showPanel(const std::string& floater_name, const LLSD& key); diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index b5ba64716d..c0980719bb 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -762,7 +762,8 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL // hide old preview as the aspect ratio could be wrong checkAutoSnapshot(previewp, FALSE); LL_DEBUGS() << "updating thumbnail" << LL_ENDL; - getPreviewView()->updateSnapshot(TRUE); + // Don't update immediately, give window chance to redraw + getPreviewView()->updateSnapshot(TRUE, FALSE, 1.f); if(do_update) { LL_DEBUGS() << "Will update controls" << LL_ENDL; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 987a7449ee..b14b9b7578 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -1177,7 +1177,12 @@ void LLFloaterTools::updateLandImpacts() S32 rezzed_prims = parcel->getSimWidePrimCount(); S32 total_capacity = parcel->getSimWideMaxPrimCapacity(); - + LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + if (region) + { + S32 max_tasks_per_region = (S32)region->getMaxTasks(); + total_capacity = llmin(total_capacity, max_tasks_per_region); + } std::string remaining_capacity_str = ""; bool show_mesh_cost = gMeshRepo.meshRezEnabled(); diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h index ae3800e17b..2fb912a930 100644 --- a/indra/newview/llfriendcard.h +++ b/indra/newview/llfriendcard.h @@ -37,9 +37,10 @@ class LLFriendCardsManager : public LLSingleton<LLFriendCardsManager> , public LLFriendObserver { + LLSINGLETON(LLFriendCardsManager); + ~LLFriendCardsManager(); LOG_CLASS(LLFriendCardsManager); - friend class LLSingleton<LLFriendCardsManager>; friend class CreateFriendCardCallback; public: @@ -97,8 +98,6 @@ public: private: typedef boost::function<void()> callback_t; - LLFriendCardsManager(); - ~LLFriendCardsManager(); /** diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index 26a5924ec3..402bdf6039 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -51,6 +51,8 @@ public: class LLGestureMgr : public LLSingleton<LLGestureMgr>, public LLInventoryFetchItemsObserver { + LLSINGLETON(LLGestureMgr); + ~LLGestureMgr(); public: typedef boost::function<void (LLMultiGesture* loaded_gesture)> gesture_loaded_callback_t; @@ -58,8 +60,6 @@ public: typedef std::map<LLUUID, LLMultiGesture*> item_map_t; typedef std::map<LLUUID, gesture_loaded_callback_t> callback_map_t; - LLGestureMgr(); - ~LLGestureMgr(); void init(); diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index e5ce768035..940ef6eea1 100644 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -348,6 +348,8 @@ struct LLRoleActionSet class LLGroupMgr : public LLSingleton<LLGroupMgr> { + LLSINGLETON(LLGroupMgr); + ~LLGroupMgr(); LOG_CLASS(LLGroupMgr); public: @@ -369,8 +371,6 @@ public: public: - LLGroupMgr(); - ~LLGroupMgr(); void addObserver(LLGroupMgrObserver* observer); void addObserver(const LLUUID& group_id, LLParticularGroupObserver* observer); diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h index ebffe561b9..dd6195a9ce 100644 --- a/indra/newview/llhints.h +++ b/indra/newview/llhints.h @@ -29,6 +29,7 @@ #include "llpanel.h" #include "llnotifications.h" +#include "llinitdestroyclass.h" class LLHints : public LLInitClass<LLHints> diff --git a/indra/newview/llhudmanager.h b/indra/newview/llhudmanager.h index 9c5d49decd..7782739690 100644 --- a/indra/newview/llhudmanager.h +++ b/indra/newview/llhudmanager.h @@ -36,10 +36,10 @@ class LLMessageSystem; class LLHUDManager : public LLSingleton<LLHUDManager> { -public: - LLHUDManager(); + LLSINGLETON(LLHUDManager); ~LLHUDManager(); +public: LLHUDEffect *createViewerEffect(const U8 type, BOOL send_to_sim = TRUE, BOOL originated_here = TRUE); void updateEffects(); diff --git a/indra/newview/llimagefiltersmanager.h b/indra/newview/llimagefiltersmanager.h index 4751933065..f1ed3cf1c3 100644 --- a/indra/newview/llimagefiltersmanager.h +++ b/indra/newview/llimagefiltersmanager.h @@ -34,6 +34,8 @@ class LLImageFiltersManager : public LLSingleton<LLImageFiltersManager> { + LLSINGLETON(LLImageFiltersManager); + ~LLImageFiltersManager(); LOG_CLASS(LLImageFiltersManager); public: const std::vector<std::string> getFiltersList() const; @@ -43,10 +45,7 @@ private: void loadAllFilters(); void loadFiltersFromDir(const std::string& dir); - friend class LLSingleton<LLImageFiltersManager>; /*virtual*/ void initSingleton(); - LLImageFiltersManager(); - ~LLImageFiltersManager(); // List of filters : first is the user friendly localized name, second is the xml file name std::map<std::string,std::string> mFiltersList; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 41a8813acb..da40ac8393 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -33,6 +33,7 @@ #include "lllogchat.h" #include "llvoicechannel.h" +#include "llinitdestroyclass.h" #include "llcoros.h" #include "lleventcoro.h" @@ -61,6 +62,7 @@ private: */ class LLIMModel : public LLSingleton<LLIMModel> { + LLSINGLETON(LLIMModel); public: struct LLIMSession : public boost::signals2::trackable @@ -151,7 +153,6 @@ public: }; - LLIMModel(); /** Session id to session object */ std::map<LLUUID, LLIMSession*> mId2SessionMap; @@ -312,6 +313,7 @@ public: class LLIMMgr : public LLSingleton<LLIMMgr> { + LLSINGLETON(LLIMMgr); friend class LLIMModel; public: @@ -322,8 +324,6 @@ public: INVITATION_TYPE_IMMEDIATE = 2 }; - LLIMMgr(); - virtual ~LLIMMgr() {}; // Add a message to a session. The session can keyed to sesion id // or agent id. diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e6cd7b9f95..1de579d4c3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -41,6 +41,7 @@ #include "llfloateropenobject.h" #include "llfloaterreg.h" #include "llfloatermarketplacelistings.h" +#include "llfloateroutfitphotopreview.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterworldmap.h" #include "llfolderview.h" @@ -4453,7 +4454,7 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr if((inv_type == LLInventoryType::IT_TEXTURE) || (inv_type == LLInventoryType::IT_SNAPSHOT)) { - return TRUE; + return !move_is_into_current_outfit; } if (move_is_into_current_outfit && get_is_item_worn(inv_item->getUUID())) @@ -4508,9 +4509,15 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c { if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)) { - LLAppearanceMgr::instance().removeOutfitPhoto(mUUID); - LLPointer<LLInventoryCallback> cb = NULL; - link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb); + const LLUUID &my_outifts_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + if(mUUID != my_outifts_id) + { + LLFloaterOutfitPhotoPreview* photo_preview = LLFloaterReg::showTypedInstance<LLFloaterOutfitPhotoPreview>("outfit_photo_preview", inv_item->getUUID()); + if(photo_preview) + { + photo_preview->setOutfitID(mUUID); + } + } return; } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index d8f019374e..f04d6cc753 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -48,7 +48,6 @@ #include "llavataractions.h" #include "llclipboard.h" #include "lldonotdisturbnotificationstorage.h" -#include "llfloaterinventory.h" #include "llfloatersidepanelcontainer.h" #include "llfocusmgr.h" #include "llfolderview.h" @@ -752,36 +751,13 @@ void show_item_original(const LLUUID& item_uuid) void reset_inventory_filter() { - //inventory floater - bool floater_inventory_visible = false; - - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); + if (sidepanel_inventory) { - LLFloaterInventory* floater_inventory = dynamic_cast<LLFloaterInventory*>(*iter); - if (floater_inventory) + LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); + if (main_inventory) { - LLPanelMainInventory* main_inventory = floater_inventory->getMainInventoryPanel(); - main_inventory->onFilterEdit(""); - - if(floater_inventory->getVisible()) - { - floater_inventory_visible = true; - } - } - } - - if(!floater_inventory_visible) - { - LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - if (sidepanel_inventory) - { - LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); - if (main_inventory) - { - main_inventory->onFilterEdit(""); - } } } } diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 013a5a7629..495180f087 100644 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -46,8 +46,7 @@ struct IconEntry : public LLDictionaryEntry class LLIconDictionary : public LLSingleton<LLIconDictionary>, public LLDictionary<LLInventoryType::EIconName, IconEntry> { -public: - LLIconDictionary(); + LLSINGLETON(LLIconDictionary); }; typedef LLPointer<LLUIImage> LLUIImagePtr; diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 36e1cc97d1..1dc1aa395e 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -45,7 +45,7 @@ LLInventoryItemsList::Params::Params() LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p) : LLFlatListViewEx(p) -, mNeedsRefresh(false) +, mRefreshState(REFRESH_COMPLETE) , mForceRefresh(false) { // TODO: mCommitOnSelectionChange is set to "false" in LLFlatListView @@ -66,13 +66,13 @@ LLInventoryItemsList::~LLInventoryItemsList() void LLInventoryItemsList::refreshList(const LLInventoryModel::item_array_t item_array) { - getIDs().clear(); + getIDs().clear(); LLInventoryModel::item_array_t::const_iterator it = item_array.begin(); for( ; item_array.end() != it; ++it) { getIDs().push_back((*it)->getUUID()); } - mNeedsRefresh = true; + mRefreshState = REFRESH_ALL; } boost::signals2::connection LLInventoryItemsList::setRefreshCompleteCallback(const commit_signal_t::slot_type& cb) @@ -113,9 +113,9 @@ void LLInventoryItemsList::updateSelection() void LLInventoryItemsList::doIdle() { - if (!mNeedsRefresh) return; + if (mRefreshState == REFRESH_COMPLETE) return; - if (isInVisibleChain() || mForceRefresh) + if (isInVisibleChain() || mForceRefresh ) { refresh(); @@ -137,54 +137,130 @@ LLTrace::BlockTimerStatHandle FTM_INVENTORY_ITEMS_REFRESH("Inventory List Refres void LLInventoryItemsList::refresh() { - LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH); - static const unsigned ADD_LIMIT = 20; - - uuid_vec_t added_items; - uuid_vec_t removed_items; - - computeDifference(getIDs(), added_items, removed_items); - - bool add_limit_exceeded = false; - unsigned int nadded = 0; - - uuid_vec_t::const_iterator it = added_items.begin(); - for( ; added_items.end() != it; ++it) - { - if(nadded >= ADD_LIMIT) - { - add_limit_exceeded = true; - break; - } - LLViewerInventoryItem* item = gInventory.getItem(*it); - // Do not rearrange items on each adding, let's do that on filter call - llassert(item); - if (item) - { - addNewItem(item, false); - ++nadded; - } - } - - it = removed_items.begin(); - for( ; removed_items.end() != it; ++it) - { - // don't filter items right away - removeItemByUUID(*it, false); - } - - // Filter, rearrange and notify parent about shape changes - filterItems(); - - bool needs_refresh = add_limit_exceeded; - setNeedsRefresh(needs_refresh); - setForceRefresh(needs_refresh); - - // After list building completed, select items that had been requested to select before list was build - if(!needs_refresh) - { - updateSelection(); - } + LL_RECORD_BLOCK_TIME(FTM_INVENTORY_ITEMS_REFRESH); + + switch (mRefreshState) + { + case REFRESH_ALL: + { + mAddedItems.clear(); + mRemovedItems.clear(); + computeDifference(getIDs(), mAddedItems, mRemovedItems); + if (mRemovedItems.size() > 0) + { + mRefreshState = REFRESH_LIST_ERASE; + } + else if (mAddedItems.size() > 0) + { + mRefreshState = REFRESH_LIST_APPEND; + } + else + { + mRefreshState = REFRESH_LIST_SORT; + } + + rearrangeItems(); + notifyParentItemsRectChanged(); + break; + } + case REFRESH_LIST_ERASE: + { + uuid_vec_t::const_iterator it = mRemovedItems.begin(); + for (; mRemovedItems.end() != it; ++it) + { + // don't filter items right away + removeItemByUUID(*it, false); + } + mRemovedItems.clear(); + mRefreshState = REFRESH_LIST_SORT; // fix visibility and arrange + break; + } + case REFRESH_LIST_APPEND: + { + static const unsigned ADD_LIMIT = 25; // Note: affects perfomance + + unsigned int nadded = 0; + + // form a list to add + uuid_vec_t::iterator it = mAddedItems.begin(); + pairs_list_t panel_list; + while(mAddedItems.size() > 0 && nadded < ADD_LIMIT) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + llassert(item); + if (item) + { + LLPanel *list_item = createNewItem(item); + if (list_item) + { + item_pair_t* new_pair = new item_pair_t(list_item, item->getUUID()); + panel_list.push_back(new_pair); + ++nadded; + } + } + + it = mAddedItems.erase(it); + } + + // add the list + // Note: usually item pairs are sorted with std::sort, but we are calling + // this function on idle and pairs' list can take a lot of time to sort + // through, so we are sorting items into list while adding them + addItemPairs(panel_list, false); + + // update visibility of items in the list + std::string cur_filter = getFilterSubString(); + LLStringUtil::toUpper(cur_filter); + LLSD action; + action.with("match_filter", cur_filter); + + pairs_const_iterator_t pair_it = panel_list.begin(); + for (; pair_it != panel_list.end(); ++pair_it) + { + item_pair_t* item_pair = *pair_it; + if (item_pair->first->getParent() != NULL) + { + updateItemVisibility(item_pair->first, action); + } + } + + rearrangeItems(); + notifyParentItemsRectChanged(); + + if (mAddedItems.size() > 0) + { + mRefreshState = REFRESH_LIST_APPEND; + } + else + { + // Note: while we do sort and check visibility at REFRESH_LIST_APPEND, update + // could have changed something about existing items so redo checks for all items. + mRefreshState = REFRESH_LIST_SORT; + } + break; + } + case REFRESH_LIST_SORT: + { + // Filter, sort, rearrange and notify parent about shape changes + filterItems(); + + if (mAddedItems.size() == 0) + { + // After list building completed, select items that had been requested to select before list was build + updateSelection(); + mRefreshState = REFRESH_COMPLETE; + } + else + { + mRefreshState = REFRESH_LIST_APPEND; + } + break; + } + default: + break; + } + + setForceRefresh(mRefreshState != REFRESH_COMPLETE); } void LLInventoryItemsList::computeDifference( @@ -204,24 +280,15 @@ void LLInventoryItemsList::computeDifference( LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); } -void LLInventoryItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange /*= true*/) +LLPanel* LLInventoryItemsList::createNewItem(LLViewerInventoryItem* item) { - if (!item) - { - LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL; - llassert(item != NULL); - } - - LLPanelInventoryListItemBase *list_item = LLPanelInventoryListItemBase::create(item); - if (!list_item) - return; - - bool is_item_added = addItem(list_item, item->getUUID(), ADD_BOTTOM, rearrange); - if (!is_item_added) - { - LL_WARNS() << "Couldn't add flat list item." << LL_ENDL; - llassert(is_item_added); - } + if (!item) + { + LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL; + llassert(item != NULL); + return NULL; + } + return LLPanelInventoryListItemBase::create(item); } // EOF diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index 1aa230df99..fe05c2ed7c 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -51,9 +51,9 @@ public: /** * Let list know items need to be refreshed in next doIdle() */ - void setNeedsRefresh(bool needs_refresh){ mNeedsRefresh = needs_refresh; } + void setNeedsRefresh(bool needs_refresh){ mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; } - bool getNeedsRefresh(){ return mNeedsRefresh; } + U32 getNeedsRefresh(){ return mRefreshState; } /** * Sets the flag indicating that the list needs to be refreshed even if it is @@ -71,7 +71,7 @@ public: * This is needed for example to filter items of the list hidden by closed * accordion tab. */ - void doIdle(); // Real idle routine + virtual void doIdle(); // Real idle routine static void idle(void* user_data); // static glue to doIdle() protected: @@ -94,17 +94,29 @@ protected: void computeDifference(const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved); /** - * Add an item to the list - */ - virtual void addNewItem(LLViewerInventoryItem* item, bool rearrange = true); + * Create panel(item) from inventory item + */ + virtual LLPanel* createNewItem(LLViewerInventoryItem* item); + +protected: + enum ERefreshStates + { + REFRESH_COMPLETE = 0, + REFRESH_LIST_SORT, + REFRESH_LIST_APPEND, + REFRESH_LIST_ERASE, + REFRESH_ALL + }; + + ERefreshStates mRefreshState; private: uuid_vec_t mIDs; // IDs of items that were added in refreshList(). // Will be used in refresh() to determine added and removed ids uuid_vec_t mSelectTheseIDs; // IDs that will be selected if list is not loaded till now - - bool mNeedsRefresh; + uuid_vec_t mAddedItems; + uuid_vec_t mRemovedItems; bool mForceRefresh; diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 19fbfc2ed3..00d2908c1b 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -43,9 +43,9 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLInventoryModelBackgroundFetch : public LLSingleton<LLInventoryModelBackgroundFetch> { -public: - LLInventoryModelBackgroundFetch(); + LLSINGLETON(LLInventoryModelBackgroundFetch); ~LLInventoryModelBackgroundFetch(); +public: // Start and stop background breadth-first fetching of inventory contents. // This gets triggered when performing a filter-search. diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index ce8705b7ac..4427f32de9 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -656,7 +656,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask) } } -bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb) +bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t cb, bool init_name_hash) { S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN; S32 current_num_known_descendents = LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN; @@ -694,8 +694,15 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t if (can_be_added) { - mCategoryMap.insert(category_map_value_t( - cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents))); + if(init_name_hash) + { + LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id); + mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents,item_name_hash))); + } + else + { + mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents))); + } } return can_be_added; @@ -718,6 +725,18 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData( mItemNameHash.finalize(); } +LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData( + const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash) + + : mCatID(cat_id) + , mCallback(cb) + , mVersion(version) + , mDescendentsCount(num_descendents) + , mIsNameHashInitialized(true) + , mItemNameHash(name_hash) +{ +} + void LLScrollOnRenameObserver::changed(U32 mask) { if (mask & LLInventoryObserver::LABEL) diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 8cf6a6bdab..36d8ee3f59 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -267,14 +267,14 @@ public: * @return "true" if category was added, "false" if it could * not be found. */ - bool addCategory(const LLUUID& cat_id, callback_t cb); + bool addCategory(const LLUUID& cat_id, callback_t cb, bool init_name_hash = false); void removeCategory(const LLUUID& cat_id); protected: struct LLCategoryData { LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents); - + LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash); callback_t mCallback; S32 mVersion; S32 mDescendentsCount; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index f5dcbf838d..6a27c0fe21 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -34,7 +34,6 @@ #include "llappearancemgr.h" #include "llavataractions.h" #include "llclipboard.h" -#include "llfloaterinventory.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llfolderview.h" diff --git a/indra/newview/lllocationhistory.h b/indra/newview/lllocationhistory.h index 9fef42c5df..1cecbabd3b 100644 --- a/indra/newview/lllocationhistory.h +++ b/indra/newview/lllocationhistory.h @@ -103,6 +103,7 @@ public: class LLLocationHistory: public LLSingleton<LLLocationHistory> { + LLSINGLETON(LLLocationHistory); LOG_CLASS(LLLocationHistory); public: @@ -117,7 +118,6 @@ public: typedef boost::function<void(EChangeType event)> history_changed_callback_t; typedef boost::signals2::signal<void(EChangeType event)> history_changed_signal_t; - LLLocationHistory(); void addItem(const LLLocationHistoryItem& item); bool touchItem(const LLLocationHistoryItem& item); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 485d4677b1..b9194c6c67 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -132,15 +132,9 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line) class LLLogChatTimeScanner: public LLSingleton<LLLogChatTimeScanner> { -public: - LLLogChatTimeScanner() - { - // Note, date/time facets will be destroyed by string streams - mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT))); - mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT))); - mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT))); - } + LLSINGLETON(LLLogChatTimeScanner); +public: date getTodayPacificDate() { typedef boost::date_time::local_adjustor<ptime, -8, no_dst> pst; @@ -205,6 +199,15 @@ private: std::stringstream mTimeStream; }; +inline +LLLogChatTimeScanner::LLLogChatTimeScanner() +{ + // Note, date/time facets will be destroyed by string streams + mDateStream.imbue(std::locale(mDateStream.getloc(), new date_input_facet(DATE_FORMAT))); + mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_facet(TIME_FORMAT))); + mTimeStream.imbue(std::locale(mTimeStream.getloc(), new time_input_facet(DATE_FORMAT))); +} + LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; std::map<LLUUID,LLLoadHistoryThread *> LLLogChat::sLoadHistoryThreads; diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index c6773bbf68..282ddc1cea 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -40,12 +40,12 @@ class LLUpdaterService; // negotiate user authentication attempts. class LLLoginInstance : public LLSingleton<LLLoginInstance> { + LLSINGLETON(LLLoginInstance); + ~LLLoginInstance(); + public: class Disposable; - LLLoginInstance(); - ~LLLoginInstance(); - void connect(LLPointer<LLCredential> credentials); // Connect to the current grid choice. void connect(const std::string& uri, LLPointer<LLCredential> credentials); // Connect to the given uri. void reconnect(); // reconnect using the current credentials. diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h index f84c0ca94c..2ec3a74e4a 100644 --- a/indra/newview/llmainlooprepeater.h +++ b/indra/newview/llmainlooprepeater.h @@ -43,9 +43,8 @@ class LLMainLoopRepeater: public LLSingleton<LLMainLoopRepeater> { + LLSINGLETON(LLMainLoopRepeater); public: - LLMainLoopRepeater(void); - // Start the repeater service. void start(void); diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index 9d795c6ced..ec312baca3 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -86,11 +86,10 @@ namespace MarketplaceFetchCodes class LLMarketplaceInventoryImporter : public LLSingleton<LLMarketplaceInventoryImporter> { + LLSINGLETON(LLMarketplaceInventoryImporter); public: static void update(); - - LLMarketplaceInventoryImporter(); - + typedef boost::signals2::signal<void (bool)> status_changed_signal_t; typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t; @@ -181,10 +180,11 @@ class LLSLMDeleteListingsResponder; class LLMarketplaceData : public LLSingleton<LLMarketplaceData> { - friend class LLSingleton < LLMarketplaceData > ; + LLSINGLETON(LLMarketplaceData); + virtual ~LLMarketplaceData(); public: - friend class LLSLMGetMerchantResponder; + friend class LLSLMGetMerchantResponder; friend class LLSLMGetListingsResponder; friend class LLSLMCreateListingsResponder; friend class LLSLMGetListingResponder; @@ -242,9 +242,6 @@ public: void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1); private: - LLMarketplaceData(); - virtual ~LLMarketplaceData(); - // Modify Marketplace data set : each method returns true if the function succeeds, false if error // Used internally only by SLM Responders when data are received from the SLM Server bool addListing(const LLUUID& folder_id, S32 listing_id, const LLUUID& version_id, bool is_listed, const std::string& edit_url, S32 count); diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 36dd0904b6..60b58d17de 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -38,9 +38,7 @@ class LLViewerRegion; class LLMaterialMgr : public LLSingleton<LLMaterialMgr> { - friend class LLSingleton<LLMaterialMgr>; -protected: - LLMaterialMgr(); + LLSINGLETON(LLMaterialMgr); virtual ~LLMaterialMgr(); public: diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp index 8879cfd7fb..63d97f6ac2 100644 --- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp +++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp @@ -41,8 +41,7 @@ #include "llpathfindingnavmeshstatus.h" #include "llviewerregion.h" -LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh() - : LLSingleton<LLMenuOptionPathfindingRebakeNavmesh>(), +LLMenuOptionPathfindingRebakeNavmesh::LLMenuOptionPathfindingRebakeNavmesh() : mIsInitialized(false), mCanRebakeRegion(false), mRebakeNavMeshMode(kRebakeNavMesh_Default), diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.h b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h index 7b1d2873ba..649a387dd3 100644 --- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.h +++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.h @@ -37,6 +37,8 @@ class LLPathfindingNavMeshStatus; class LLMenuOptionPathfindingRebakeNavmesh : public LLSingleton<LLMenuOptionPathfindingRebakeNavmesh> { + LLSINGLETON(LLMenuOptionPathfindingRebakeNavmesh); + virtual ~LLMenuOptionPathfindingRebakeNavmesh(); LOG_CLASS(LLMenuOptionPathfindingRebakeNavmesh); public: @@ -49,8 +51,6 @@ public: kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable } ERebakeNavMeshMode; - LLMenuOptionPathfindingRebakeNavmesh(); - virtual ~LLMenuOptionPathfindingRebakeNavmesh(); void initialize(); void quit(); diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index 01cf68bcda..0f70c9d13f 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -47,6 +47,7 @@ #include "pipeline.h" #include <boost/tokenizer.hpp> +#include <boost/bind.hpp> #include "lldispatcher.h" #include "llxfermanager.h" @@ -56,6 +57,7 @@ #include "llworld.h" //for particle system banning #include "llimview.h" #include "llnotifications.h" +#include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "lltrans.h" @@ -146,22 +148,6 @@ std::string LLMute::getDisplayType() const } } - -/* static */ -LLMuteList* LLMuteList::getInstance() -{ - // Register callbacks at the first time that we find that the message system has been created. - static BOOL registered = FALSE; - if( !registered && gMessageSystem != NULL) - { - registered = TRUE; - // Register our various callbacks - gMessageSystem->setHandlerFuncFast(_PREHASH_MuteListUpdate, processMuteListUpdate); - gMessageSystem->setHandlerFuncFast(_PREHASH_UseCachedMuteList, processUseCachedMuteList); - } - return LLSingleton<LLMuteList>::getInstance(); // Call the "base" implementation. -} - //----------------------------------------------------------------------------- // LLMuteList() //----------------------------------------------------------------------------- @@ -169,6 +155,18 @@ LLMuteList::LLMuteList() : mIsLoaded(FALSE) { gGenericDispatcher.addHandler("emptymutelist", &sDispatchEmptyMuteList); + + // Register our callbacks. We may be constructed before gMessageSystem, so + // use callWhenReady() to register them as soon as gMessageSystem becomes + // available. + // When using bind(), must be explicit about default arguments such as + // that last NULL. + gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1, + _PREHASH_MuteListUpdate, processMuteListUpdate, + static_cast<void**>(NULL))); + gMessageSystem.callWhenReady(boost::bind(&LLMessageSystem::setHandlerFuncFast, _1, + _PREHASH_UseCachedMuteList, processUseCachedMuteList, + static_cast<void**>(NULL))); } //----------------------------------------------------------------------------- @@ -231,6 +229,16 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) return FALSE; } + S32 mute_list_limit = gSavedSettings.getS32("MuteListLimit"); + if (getMutes().size() >= mute_list_limit) + { + LL_WARNS() << "Mute limit is reached; ignored" << LL_ENDL; + LLSD args; + args["MUTE_LIMIT"] = mute_list_limit; + LLNotifications::instance().add(LLNotification::Params("MuteLimitReached").substitutions(args)); + return FALSE; + } + if (mute.mType == LLMute::BY_NAME) { // Can't mute empty string by name diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 4e7b6ee880..4ceddc97fd 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -71,6 +71,8 @@ public: class LLMuteList : public LLSingleton<LLMuteList> { + LLSINGLETON(LLMuteList); + ~LLMuteList(); public: // reasons for auto-unmuting a resident enum EAutoReason @@ -81,13 +83,6 @@ public: AR_COUNT // enum count }; - LLMuteList(); - ~LLMuteList(); - - // Implemented locally so that we can perform some delayed initialization. - // Callers should be careful to call this one and not LLSingleton<LLMuteList>::getInstance() - // which would circumvent that mechanism. -MG - static LLMuteList* getInstance(); void addObserver(LLMuteListObserver* observer); void removeObserver(LLMuteListObserver* observer); diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 29dbaedf7a..a44c6dd699 100644..100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -30,6 +30,7 @@ #include "llpanel.h" #include "llbutton.h" #include "lllayoutstack.h" +#include "llinitdestroyclass.h" class LLLocationInputCtrl; class LLMenuGL; @@ -84,12 +85,12 @@ protected: class LLNavigationBar : public LLPanel, public LLSingleton<LLNavigationBar>, private LLDestroyClass<LLNavigationBar> { + LLSINGLETON(LLNavigationBar); + virtual ~LLNavigationBar(); LOG_CLASS(LLNavigationBar); friend class LLDestroyClass<LLNavigationBar>; - + public: - LLNavigationBar(); - virtual ~LLNavigationBar(); /*virtual*/ void draw(); /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index f37c6b833c..52c79cc689 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -46,11 +46,11 @@ class LLToast; */ class LLNotificationManager : public LLSingleton<LLNotificationManager> { - typedef std::pair<std::string, LLEventHandler*> eventhandlers; -public: - LLNotificationManager(); + LLSINGLETON(LLNotificationManager); virtual ~LLNotificationManager(); + typedef std::pair<std::string, LLEventHandler*> eventhandlers; +public: //TODO: make private // this method initialize handlers' map for different types of notifications void init(void); diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index 3418b33d37..35fdfa88bb 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -45,9 +45,10 @@ typedef boost::function<LLNotificationResponderInterface * (const LLSD& pParams) class LLResponderRegistry : public LLRegistrySingleton<std::string, responder_constructor_t, LLResponderRegistry> { - public: - template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams); - LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams); + LLSINGLETON_EMPTY_CTOR(LLResponderRegistry); +public: + template<typename RESPONDER_TYPE> static LLNotificationResponderInterface * create(const LLSD& pParams); + LLNotificationResponderInterface * createResponder(const std::string& pNotificationName, const LLSD& pParams); }; template<typename RESPONDER_TYPE> LLNotificationResponderInterface * LLResponderRegistry::create(const LLSD& pParams) diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index de6a36ce2f..eeeb7e5c25 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -106,7 +106,8 @@ BOOL LLOutfitGallery::postBuild() { BOOL rv = LLOutfitListBase::postBuild(); mScrollPanel = getChild<LLScrollContainer>("gallery_scroll_panel"); - mGalleryPanel = getChild<LLPanel>("gallery_panel"); + LLPanel::Params params = LLPanel::getDefaultParams(); // Don't parse XML when creating dummy LLPanel + mGalleryPanel = LLUICtrlFactory::create<LLPanel>(params); mMessageTextBox = getChild<LLTextBox>("no_outfits_txt"); mOutfitGalleryMenu = new LLOutfitGalleryContextMenu(this); return rv; @@ -234,6 +235,7 @@ void LLOutfitGallery::removeLastRow() { mRowCount--; mGalleryPanel->removeChild(mLastRowPanel); + mUnusedRowPanels.push_back(mLastRowPanel); mRowPanels.pop_back(); mLastRowPanel = mRowPanels.back(); } @@ -335,6 +337,7 @@ void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item) { mItemPanels.back()->removeChild(item); mLastRowPanel->removeChild(mItemPanels.back()); + mUnusedItemPanels.push_back(mItemPanels.back()); mItemPanels.pop_back(); } @@ -374,7 +377,16 @@ LLPanel* LLOutfitGallery::buildItemPanel(int left) { LLPanel::Params lpparams; int top = 0; - LLPanel* lpanel = LLUICtrlFactory::create<LLPanel>(lpparams); + LLPanel* lpanel = NULL; + if(mUnusedItemPanels.empty()) + { + lpanel = LLUICtrlFactory::create<LLPanel>(lpparams); + } + else + { + lpanel = mUnusedItemPanels.back(); + mUnusedItemPanels.pop_back(); + } LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); lpanel->setRect(rect); lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight); @@ -387,7 +399,16 @@ LLPanel* LLOutfitGallery::buildItemPanel(int left) LLPanel* LLOutfitGallery::buildRowPanel(int left, int bottom) { LLPanel::Params sparams; - LLPanel* stack = LLUICtrlFactory::create<LLPanel>(sparams); + LLPanel* stack = NULL; + if(mUnusedRowPanels.empty()) + { + stack = LLUICtrlFactory::create<LLPanel>(sparams); + } + else + { + stack = mUnusedRowPanels.back(); + mUnusedRowPanels.pop_back(); + } moveRowPanel(stack, left, bottom); return stack; } @@ -417,6 +438,19 @@ LLOutfitGallery::~LLOutfitGallery() gInventory.removeObserver(mOutfitsObserver); } delete mOutfitsObserver; + + while (!mUnusedRowPanels.empty()) + { + LLPanel* panelp = mUnusedRowPanels.back(); + mUnusedRowPanels.pop_back(); + panelp->die(); + } + while (!mUnusedItemPanels.empty()) + { + LLPanel* panelp = mUnusedItemPanels.back(); + mUnusedItemPanels.pop_back(); + panelp->die(); + } } void LLOutfitGallery::setFilterSubString(const std::string& string) @@ -497,7 +531,7 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id) // Start observing changes in "My Outfits" category. mOutfitsObserver->addCategory(cat_id, - boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id)); + boost::bind(&LLOutfitGallery::refreshOutfit, this, cat_id), true); outfit_category->fetch(); refreshOutfit(cat_id); @@ -640,7 +674,6 @@ BOOL LLOutfitGalleryItem::postBuild() mOutfitNameText = getChild<LLTextBox>("outfit_name"); mOutfitWornText = getChild<LLTextBox>("outfit_worn_text"); - mFotoBgPanel = getChild<LLPanel>("foto_bg_panel"); mTextBgPanel = getChild<LLPanel>("text_bg_panel"); setOutfitWorn(false); mHidden = false; @@ -1093,7 +1126,7 @@ void LLOutfitGallery::uploadPhoto(LLUUID outfit_id) return; } - S32 expected_upload_cost = LLGlobalEconomy::Singleton::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). + 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; @@ -1161,7 +1194,7 @@ void LLOutfitGallery::onTexturePickerCommit(LLTextureCtrl::ETexturePickOp op, LL } else { - image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE); + image_item_id = floaterp->findItemID(floaterp->getAssetID(), FALSE, TRUE); if (image_item_id.isNull()) { LL_WARNS() << "id or image_item_id is NULL!" << LL_ENDL; diff --git a/indra/newview/lloutfitgallery.h b/indra/newview/lloutfitgallery.h index 6b13f264a4..b9fc10f015 100644 --- a/indra/newview/lloutfitgallery.h +++ b/indra/newview/lloutfitgallery.h @@ -158,6 +158,8 @@ private: void moveRowPanel(LLPanel* stack, int left, int bottom); std::vector<LLPanel*> mRowPanels; std::vector<LLPanel*> mItemPanels; + std::vector<LLPanel*> mUnusedRowPanels; + std::vector<LLPanel*> mUnusedItemPanels; std::vector<LLOutfitGalleryItem*> mItems; std::vector<LLOutfitGalleryItem*> mHiddenItems; LLScrollContainer* mScrollPanel; @@ -273,7 +275,6 @@ private: LLTextBox* mOutfitNameText; LLTextBox* mOutfitWornText; LLPanel* mTextBgPanel; - LLPanel* mFotoBgPanel; bool mSelected; bool mWorn; bool mDefaultImage; diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index 87d4b0c998..77041db68d 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -36,10 +36,10 @@ */ class LLOutfitObserver: public LLInventoryObserver, public LLSingleton<LLOutfitObserver> { -public: + LLSINGLETON(LLOutfitObserver); virtual ~LLOutfitObserver(); - friend class LLSingleton<LLOutfitObserver>; +public: virtual void changed(U32 mask); @@ -58,7 +58,6 @@ public: void addOutfitLockChangedCallback(const signal_t::slot_type& cb) { mOutfitLockChanged.connect(cb); } protected: - LLOutfitObserver(); /** Get a version of an inventory category specified by its UUID */ static S32 getCategoryVersion(const LLUUID& cat_id); diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 87c3c5042b..e1f51e62e3 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -872,8 +872,15 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) ++items_iter) { LLViewerInventoryCategory *cat = gInventory.getCategory(*items_iter); - if (!cat) return; - + if (!cat) + { + LLInventoryObject* obj = gInventory.getObject(*items_iter); + if(!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) + { + return; + } + cat = (LLViewerInventoryCategory*)obj; + } std::string name = cat->getName(); updateChangedCategoryName(cat, name); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index b7e1b2d3a4..f2d43a1037 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -117,8 +117,7 @@ class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary> //-------------------------------------------------------------------- // Constructors and Destructors //-------------------------------------------------------------------- -public: - LLEditWearableDictionary(); + LLSINGLETON(LLEditWearableDictionary); virtual ~LLEditWearableDictionary(); //-------------------------------------------------------------------- diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 54728885c1..48b659a81e 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -37,7 +37,6 @@ #include "llinventoryfunctions.h" #include "llinventoryicon.h" #include "llinventorymodel.h" -#include "llfloaterinventory.h" #include "llagent.h" #include "llagentui.h" diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index f9ec3df333..fa946ee5c7 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -33,7 +33,6 @@ #include "lldndbutton.h" #include "lleconomy.h" #include "llfilepicker.h" -#include "llfloaterinventory.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" @@ -115,7 +114,6 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p) mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2)); - //mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow, this)); mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); @@ -1265,6 +1263,18 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) LLSidepanelInventory* parent = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); return parent ? parent->canShare() : FALSE; } + if (command_name == "empty_trash") + { + const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); + return children != LLInventoryModel::CHILDREN_NO; + } + if (command_name == "empty_lostnfound") + { + const LLUUID &trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + LLInventoryModel::EHasChildren children = gInventory.categoryHasChildren(trash_id); + return children != LLInventoryModel::CHILDREN_NO; + } return TRUE; } @@ -1323,7 +1333,7 @@ void LLPanelMainInventory::setUploadCostIfNeeded() LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload"); if(upload_menu) { - S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); std::string cost_str; // getPriceUpload() returns -1 if no data available yet. diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index efa18b42c1..38936804ac 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -86,6 +86,8 @@ public: void setFocusFilterEditor(); + static void newWindow(); + protected: // // Misc functions @@ -110,7 +112,6 @@ protected: // menu callbacks void doToSelected(const LLSD& userdata); void closeAllFolders(); - void newWindow(); void doCreate(const LLSD& userdata); void resetFilters(); void setSortBy(const LLSD& userdata); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 8b9941c0ca..208ee77f2d 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -51,7 +51,6 @@ #include "llbutton.h" #include "llcombobox.h" #include "llfiltereditor.h" -#include "llfloaterinventory.h" #include "llinventorybridge.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" @@ -779,6 +778,10 @@ void LLPanelOutfitEdit::onVisibilityChanged(const LLSD &in_visible_chain) { update(); } + else + { + mWearableListManager->holdProgress(); //list population restarts with visibility + } } void LLPanelOutfitEdit::onAddWearableClicked(void) diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 3f700496a9..3a35c49007 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -42,6 +42,7 @@ #include "llpanelwearing.h" #include "llsaveoutfitcombobtn.h" #include "llsidepanelappearance.h" +#include "llviewercontrol.h" #include "llviewerfoldertype.h" static const std::string OUTFITS_TAB_NAME = "outfitslist_tab"; @@ -67,6 +68,10 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() : LLPanelOutfitsInventory::~LLPanelOutfitsInventory() { + if (mAppearanceTabs) + { + gSavedSettings.setS32("LastAppearanceTab", mAppearanceTabs->getCurrentPanelIndex()); + } } // virtual @@ -87,6 +92,9 @@ BOOL LLPanelOutfitsInventory::postBuild() mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this, true)); + if (!mAppearanceTabs->selectTab(gSavedSettings.getS32("LastAppearanceTab"))) + mAppearanceTabs->selectFirstTab(); + return TRUE; } diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 6e677bbce5..203c57b732 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -63,6 +63,7 @@ #include "roles_constants.h" #include "llgroupactions.h" #include "lltrans.h" +#include "llinventorymodel.h" U8 string_value_to_click_action(std::string p_value); @@ -1016,13 +1017,26 @@ void LLPanelPermissions::onCommitNextOwnerTransfer(LLUICtrl* ctrl, void* data) // static void LLPanelPermissions::onCommitName(LLUICtrl*, void* data) { - //LL_INFOS() << "LLPanelPermissions::onCommitName()" << LL_ENDL; LLPanelPermissions* self = (LLPanelPermissions*)data; LLLineEditor* tb = self->getChild<LLLineEditor>("Object Name"); - if(tb) + if (!tb) { - LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText()); -// LLSelectMgr::getInstance()->selectionSetObjectName(self->mLabelObjectName->getText()); + return; + } + LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText()); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->isAttachment() && (selection->getNumNodes() == 1) && !tb->getText().empty()) + { + LLUUID object_id = selection->getFirstObject()->getAttachmentItemID(); + LLViewerInventoryItem* item = findItem(object_id); + if (item) + { + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->rename(tb->getText()); + new_item->updateServer(FALSE); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + } } } @@ -1030,12 +1044,26 @@ void LLPanelPermissions::onCommitName(LLUICtrl*, void* data) // static void LLPanelPermissions::onCommitDesc(LLUICtrl*, void* data) { - //LL_INFOS() << "LLPanelPermissions::onCommitDesc()" << LL_ENDL; LLPanelPermissions* self = (LLPanelPermissions*)data; LLLineEditor* le = self->getChild<LLLineEditor>("Object Description"); - if(le) + if (!le) { - LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText()); + return; + } + LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText()); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + if (selection->isAttachment() && (selection->getNumNodes() == 1)) + { + LLUUID object_id = selection->getFirstObject()->getAttachmentItemID(); + LLViewerInventoryItem* item = findItem(object_id); + if (item) + { + LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); + new_item->setDescription(le->getText()); + new_item->updateServer(FALSE); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + } } } @@ -1159,3 +1187,12 @@ void LLPanelPermissions::onCommitIncludeInSearch(LLUICtrl* ctrl, void*) LLSelectMgr::getInstance()->selectionSetIncludeInSearch(box->get()); } + +LLViewerInventoryItem* LLPanelPermissions::findItem(LLUUID &object_id) +{ + if (!object_id.isNull()) + { + return gInventory.getItem(object_id); + } + return NULL; +} diff --git a/indra/newview/llpanelpermissions.h b/indra/newview/llpanelpermissions.h index 87805bbf90..2d15954baa 100644 --- a/indra/newview/llpanelpermissions.h +++ b/indra/newview/llpanelpermissions.h @@ -37,6 +37,7 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLNameBox; +class LLViewerInventoryItem; class LLPanelPermissions : public LLPanel { @@ -77,6 +78,8 @@ protected: static void onCommitClickAction(LLUICtrl* ctrl, void*); static void onCommitIncludeInSearch(LLUICtrl* ctrl, void*); + static LLViewerInventoryItem* findItem(LLUUID &object_id); + protected: void disableAll(); diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 2fa4ee376a..610b3a6396 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -502,10 +502,6 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, if(!parcel->getGroupID().isNull()) { - // FIXME: Using parcel group as region group. - gCacheName->getGroup(parcel->getGroupID(), - boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2)); - std::string owner = LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString(); mParcelOwner->setText(owner); @@ -524,12 +520,20 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, LLSLURL("agent", parcel->getOwnerID(), "inspect").getSLURLString(); mParcelOwner->setText(parcel_owner); LLAvatarNameCache::get(region->getOwner(), boost::bind(&LLPanelPlaceInfo::onAvatarNameCache, _1, _2, mRegionOwnerText)); + mRegionGroupText->setText( getString("none_text")); } if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus()) { mRegionOwnerText->setText(mRegionOwnerText->getText() + getString("sale_pending_text")); } + + if(!parcel->getGroupID().isNull()) + { + // FIXME: Using parcel group as region group. + gCacheName->getGroup(parcel->getGroupID(), + boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2)); + } } mEstateRatingText->setText(region->getSimAccessString()); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index a9a0c30e26..5d43c38612 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -711,6 +711,34 @@ void LLPanelPlaces::onEditButtonClicked() updateVerbs(); } +class LLUpdateLandmarkParent : public LLInventoryCallback +{ +public: + LLUpdateLandmarkParent(LLPointer<LLViewerInventoryItem> item, LLUUID new_parent) : + mItem(item), + mNewParentId(new_parent) + {}; + /* virtual */ void fire(const LLUUID& inv_item_id) + { + LLInventoryModel::update_list_t update; + LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1); + update.push_back(old_folder); + LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1); + update.push_back(new_folder); + gInventory.accountForUpdate(update); + + mItem->setParent(mNewParentId); + mItem->updateParentOnServer(FALSE); + + gInventory.updateItem(mItem); + gInventory.notifyObservers(); + } + +private: + LLPointer<LLViewerInventoryItem> mItem; + LLUUID mNewParentId; +}; + void LLPanelPlaces::onSaveButtonClicked() { if (!mLandmarkInfo || mItem.isNull()) @@ -726,6 +754,7 @@ void LLPanelPlaces::onSaveButtonClicked() LLUUID item_id = mItem->getUUID(); LLUUID folder_id = mLandmarkInfo->getLandmarkFolder(); + bool change_parent = folder_id != mItem->getParentUUID(); LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem); @@ -734,10 +763,16 @@ void LLPanelPlaces::onSaveButtonClicked() { new_item->rename(current_title_value); new_item->setDescription(current_notes_value); - new_item->updateServer(FALSE); + LLPointer<LLInventoryCallback> cb; + if (change_parent) + { + cb = new LLUpdateLandmarkParent(new_item, folder_id); + } + LLInventoryModel::LLCategoryUpdate up(mItem->getParentUUID(), 0); + gInventory.accountForUpdate(up); + update_inventory_item(new_item, cb); } - - if(folder_id != mItem->getParentUUID()) + else if (change_parent) { LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1); diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index b2952834fb..21ac7604ff 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -135,7 +135,7 @@ BOOL LLPanelSnapshotInventory::postBuild() // virtual void LLPanelSnapshotInventory::onOpen(const LLSD& key) { - getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); + getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload())); LLPanelSnapshot::onOpen(key); } @@ -155,7 +155,7 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) void LLPanelSnapshotInventoryBase::onSend() { - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); if (can_afford_transaction(expected_upload_cost)) { if (mSnapshotFloater) @@ -191,7 +191,7 @@ BOOL LLPanelOutfitSnapshotInventory::postBuild() // virtual void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key) { - getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload())); + getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload())); LLPanelSnapshot::onOpen(key); } diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 269f16c5e4..95c14e4226 100644 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -77,12 +77,12 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions() mCommitCallbackRegistrar.add("Snapshot.SendToFacebook", boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this)); mCommitCallbackRegistrar.add("Snapshot.SendToTwitter", boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this)); mCommitCallbackRegistrar.add("Snapshot.SendToFlickr", boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this)); - LLGlobalEconomy::Singleton::getInstance()->addObserver(this); + LLGlobalEconomy::getInstance()->addObserver(this); } LLPanelSnapshotOptions::~LLPanelSnapshotOptions() { - LLGlobalEconomy::Singleton::getInstance()->removeObserver(this); + LLGlobalEconomy::getInstance()->removeObserver(this); } // virtual @@ -100,7 +100,7 @@ void LLPanelSnapshotOptions::onOpen(const LLSD& key) void LLPanelSnapshotOptions::updateUploadCost() { - S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost)); } diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 3de9dc2f80..fe0608d544 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -104,7 +104,9 @@ private: //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> { +class LLTeleportHistoryFlatItemStorage: public LLSingleton<LLTeleportHistoryFlatItemStorage> +{ + LLSINGLETON_EMPTY_CTOR(LLTeleportHistoryFlatItemStorage); protected: typedef std::vector< LLHandle<LLTeleportHistoryFlatItem> > flat_item_list_t; diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h index f37bd9c048..78dd997029 100644 --- a/indra/newview/llpaneltopinfobar.h +++ b/indra/newview/llpaneltopinfobar.h @@ -28,6 +28,7 @@ #define LLPANELTOPINFOBAR_H_ #include "llpanel.h" +#include "llinitdestroyclass.h" class LLButton; class LLTextBox; @@ -36,6 +37,8 @@ class LLParcelChangeObserver; class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>, private LLDestroyClass<LLPanelTopInfoBar> { + LLSINGLETON(LLPanelTopInfoBar); + ~LLPanelTopInfoBar(); LOG_CLASS(LLPanelTopInfoBar); friend class LLDestroyClass<LLPanelTopInfoBar>; @@ -43,9 +46,6 @@ class LLPanelTopInfoBar : public LLPanel, public LLSingleton<LLPanelTopInfoBar>, public: typedef boost::signals2::signal<void ()> resize_signal_t; - LLPanelTopInfoBar(); - ~LLPanelTopInfoBar(); - /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 796372ba04..a150007177 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -232,6 +232,7 @@ BOOL LLPanelWearing::postBuild() { mAccordionCtrl = getChild<LLAccordionCtrl>("wearables_accordion"); mWearablesTab = getChild<LLAccordionCtrlTab>("tab_wearables"); + mWearablesTab->setIgnoreResizeNotification(true); mAttachmentsTab = getChild<LLAccordionCtrlTab>("tab_temp_attachments"); mAttachmentsTab->setDropDownStateChangedCallback(boost::bind(&LLPanelWearing::onAccordionTabStateChanged, this)); diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index 711a869e82..cb4c07a417 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -144,8 +144,7 @@ typedef boost::shared_ptr<LinksetsResponder> LinksetsResponderPtr; // LLPathfindingManager //--------------------------------------------------------------------------- -LLPathfindingManager::LLPathfindingManager() - : LLSingleton<LLPathfindingManager>(), +LLPathfindingManager::LLPathfindingManager(): mNavMeshMap(), mAgentStateSignal() { diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h index e8fad590ba..a44cd892da 100644 --- a/indra/newview/llpathfindingmanager.h +++ b/indra/newview/llpathfindingmanager.h @@ -48,6 +48,9 @@ class LinksetsResponder; class LLPathfindingManager : public LLSingleton<LLPathfindingManager> { + LLSINGLETON(LLPathfindingManager); + virtual ~LLPathfindingManager(); + friend class LLNavMeshSimStateChangeNode; friend class NavMeshStatusResponder; friend class LLAgentStateChangeNode; @@ -60,9 +63,6 @@ public: kRequestError } ERequestStatus; - LLPathfindingManager(); - virtual ~LLPathfindingManager(); - void initSystem(); void quitSystem(); diff --git a/indra/newview/llpathfindingpathtool.cpp b/indra/newview/llpathfindingpathtool.cpp index 006755e20b..3187325101 100644 --- a/indra/newview/llpathfindingpathtool.cpp +++ b/indra/newview/llpathfindingpathtool.cpp @@ -46,7 +46,6 @@ LLPathfindingPathTool::LLPathfindingPathTool() : LLTool(PATH_TOOL_NAME), - LLSingleton<LLPathfindingPathTool>(), mFinalPathData(), mTempPathData(), mPathResult(LLPathingLib::LLPL_NO_PATH), diff --git a/indra/newview/llpathfindingpathtool.h b/indra/newview/llpathfindingpathtool.h index 97284265f1..88cb3a15f8 100644 --- a/indra/newview/llpathfindingpathtool.h +++ b/indra/newview/llpathfindingpathtool.h @@ -36,6 +36,9 @@ class LLPathfindingPathTool : public LLTool, public LLSingleton<LLPathfindingPathTool> { + LLSINGLETON(LLPathfindingPathTool); + virtual ~LLPathfindingPathTool(); + public: typedef enum { @@ -59,9 +62,6 @@ public: kCharacterTypeD } ECharacterType; - LLPathfindingPathTool(); - virtual ~LLPathfindingPathTool(); - typedef boost::function<void (void)> path_event_callback_t; typedef boost::signals2::signal<void (void)> path_event_signal_t; typedef boost::signals2::connection path_event_slot_t; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 9c0222d0bc..264382ae82 100644 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -36,9 +36,8 @@ #include "llscriptfloater.h" #include "llviewermessage.h" #include "llviewernetwork.h" -LLPersistentNotificationStorage::LLPersistentNotificationStorage() - : LLSingleton<LLPersistentNotificationStorage>() - , LLNotificationStorage("") +LLPersistentNotificationStorage::LLPersistentNotificationStorage(): + LLNotificationStorage("") , mLoaded(false) { } diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h index bf0306380e..40c9923c74 100644 --- a/indra/newview/llpersistentnotificationstorage.h +++ b/indra/newview/llpersistentnotificationstorage.h @@ -45,10 +45,10 @@ class LLSD; class LLPersistentNotificationStorage : public LLSingleton<LLPersistentNotificationStorage>, public LLNotificationStorage { + LLSINGLETON(LLPersistentNotificationStorage); + ~LLPersistentNotificationStorage(); LOG_CLASS(LLPersistentNotificationStorage); public: - LLPersistentNotificationStorage(); - ~LLPersistentNotificationStorage(); void saveNotifications(); void loadNotifications(); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index a498d27d2b..55cb7d616b 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -30,7 +30,6 @@ #include "llplacesinventorybridge.h" -#include "llfloaterinventory.h" // for LLInventoryPanel #include "llfolderview.h" // for FIRST_SELECTED_ITEM #include "llinventorypanel.h" diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h index 2805fc4257..27d9b83bd1 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -27,7 +27,6 @@ #ifndef LL_LLINVENTORYSUBTREEPANEL_H #define LL_LLINVENTORYSUBTREEPANEL_H -#include "llfloaterinventory.h" #include "llinventorypanel.h" class LLLandmarksPanel; diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp index 836f63bffa..f40b3e0295 100644 --- a/indra/newview/llpresetsmanager.cpp +++ b/indra/newview/llpresetsmanager.cpp @@ -55,6 +55,10 @@ void LLPresetsManager::triggerChangeSignal() void LLPresetsManager::createMissingDefault() { + if(gDirUtilp->getLindenUserDir().empty()) + { + return; + } std::string default_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PRESETS_DIR, PRESETS_GRAPHIC, PRESETS_DEFAULT + ".xml"); if (!gDirUtilp->fileExists(default_file)) { diff --git a/indra/newview/llpresetsmanager.h b/indra/newview/llpresetsmanager.h index 21f9885f27..0014e32267 100644 --- a/indra/newview/llpresetsmanager.h +++ b/indra/newview/llpresetsmanager.h @@ -46,6 +46,9 @@ enum EDefaultOptions class LLPresetsManager : public LLSingleton<LLPresetsManager> { + LLSINGLETON(LLPresetsManager); + ~LLPresetsManager(); + public: typedef std::list<std::string> preset_name_list_t; @@ -67,9 +70,6 @@ public: preset_name_list_t mPresetNames; - LLPresetsManager(); - ~LLPresetsManager(); - preset_list_signal_t mPresetListChangeSignal; private: diff --git a/indra/newview/llproductinforequest.h b/indra/newview/llproductinforequest.h index 75dbf220d1..d1036374e8 100644 --- a/indra/newview/llproductinforequest.h +++ b/indra/newview/llproductinforequest.h @@ -41,12 +41,11 @@ */ class LLProductInfoRequestManager : public LLSingleton<LLProductInfoRequestManager> { + LLSINGLETON(LLProductInfoRequestManager); public: - LLProductInfoRequestManager(); std::string getDescriptionForSku(const std::string& sku); private: - friend class LLSingleton<LLProductInfoRequestManager>; /* virtual */ void initSingleton(); void getLandDescriptionsCoro(std::string url); diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index d0d6376867..c7aaf604f5 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -50,6 +50,7 @@ class LLDate; */ class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LLSimpleListener { + LLSINGLETON_EMPTY_CTOR(LLRecentPeople); LOG_CLASS(LLRecentPeople); public: typedef boost::signals2::signal<void ()> signal_t; diff --git a/indra/newview/llregioninfomodel.h b/indra/newview/llregioninfomodel.h index d22a0de463..ea9640efda 100644 --- a/indra/newview/llregioninfomodel.h +++ b/indra/newview/llregioninfomodel.h @@ -36,6 +36,7 @@ class LLMessageSystem; */ class LLRegionInfoModel : public LLSingleton<LLRegionInfoModel> { + LLSINGLETON(LLRegionInfoModel); LOG_CLASS(LLRegionInfoModel); public: @@ -73,10 +74,8 @@ public: std::string mSimType; protected: - friend class LLSingleton<LLRegionInfoModel>; friend class LLViewerRegion; - LLRegionInfoModel(); /** * Refresh model with data from the incoming server message. diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index cb5af50c5f..5b0d189137 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -74,9 +74,10 @@ protected: class LLRemoteParcelInfoProcessor : public LLSingleton<LLRemoteParcelInfoProcessor> { -public: + LLSINGLETON_EMPTY_CTOR(LLRemoteParcelInfoProcessor); virtual ~LLRemoteParcelInfoProcessor() {} +public: void addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer); void removeObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer); diff --git a/indra/newview/llrootview.h b/indra/newview/llrootview.h index 5223a314f3..2ac958e7b8 100644 --- a/indra/newview/llrootview.h +++ b/indra/newview/llrootview.h @@ -32,7 +32,9 @@ #include "lltooltip.h" class LLRootViewRegistry : public LLChildRegistry<LLRootViewRegistry> -{}; +{ + LLSINGLETON(LLRootViewRegistry); +}; class LLRootView : public LLView { diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index 2b6ea57b96..7cd531bd34 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -39,10 +39,10 @@ class LLViewerTexture; class LLSceneMonitor : public LLSingleton<LLSceneMonitor> { + LLSINGLETON(LLSceneMonitor); + ~LLSceneMonitor(); LOG_CLASS(LLSceneMonitor); public: - LLSceneMonitor(); - ~LLSceneMonitor(); void freezeAvatar(LLCharacter* avatarp); void setDebugViewerVisible(bool visible); diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index ba2c37ce7c..681787bcbe 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -117,6 +117,14 @@ BOOL LLScreenChannelBase::postBuild() void LLScreenChannelBase::reshape(S32 width, S32 height, BOOL called_from_parent) { + if (mChannelAlignment == CA_CENTRE) + { + // Keep notifications and alerts centered + // WorldViewRectScaled is out of date at reshape but Window has same width + S32 channel_bound = gViewerWindow->getWindowRectScaled().getWidth() / 2; + setRect(LLRect(channel_bound, 0, channel_bound, 0)); + updateRect(); //sets top and bottom only + } redrawToasts(); } diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h index 70451194b3..c0b84abdcb 100644 --- a/indra/newview/llscriptfloater.h +++ b/indra/newview/llscriptfloater.h @@ -41,6 +41,7 @@ class LLScriptFloaterManager : public LLSingleton<LLScriptFloaterManager> // *TODO // LLScriptFloaterManager and LLScriptFloater will need some refactoring after we // know how script notifications should look like. + LLSINGLETON_EMPTY_CTOR(LLScriptFloaterManager); public: typedef enum e_object_type diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h index 3309a8fcac..5aab5e6765 100644 --- a/indra/newview/llsearchhistory.h +++ b/indra/newview/llsearchhistory.h @@ -28,6 +28,7 @@ #define LL_LLSEARCHHISTORY_H #include "llsingleton.h" +#include "llinitdestroyclass.h" #include "llui.h" /** @@ -36,6 +37,7 @@ */ class LLSearchHistory : public LLSingleton<LLSearchHistory>, private LLDestroyClass<LLSearchHistory> { + LLSINGLETON(LLSearchHistory); friend class LLDestroyClass<LLSearchHistory>; public: @@ -71,7 +73,6 @@ public: */ void addEntry(const std::string& search_text); - LLSearchHistory(); /** * Class for storing data about single search request. diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 323689b788..dd934ce6b8 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6006,6 +6006,11 @@ S32 LLSelectNode::getLastSelectedTE() return mLastTESelected; } +S32 LLSelectNode::getLastOperatedTE() +{ + return mLastTESelected; +} + LLViewerObject* LLSelectNode::getObject() { if (!mObject) @@ -6244,6 +6249,9 @@ void pushWireframe(LLDrawable* drawable) void LLSelectNode::renderOneWireframe(const LLColor4& color) { + //Need to because crash on ATI 3800 (and similar cards) MAINT-5018 + LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); + LLViewerObject* objectp = getObject(); if (!objectp) { @@ -7197,7 +7205,9 @@ U32 LLObjectSelection::getSelectedObjectTriangleCount(S32* vcount) if (object) { - count += object->getTriangleCount(vcount); + S32 vt = 0; + count += object->getTriangleCount(&vt); + *vcount += vt; } } diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index bc50e443f8..2a893af266 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -170,6 +170,7 @@ public: void selectTE(S32 te_index, BOOL selected); BOOL isTESelected(S32 te_index); S32 getLastSelectedTE(); + S32 getLastOperatedTE(); S32 getTESelectMask() { return mTESelectMask; } void renderOneWireframe(const LLColor4& color); void renderOneSilhouette(const LLColor4 &color); @@ -388,6 +389,9 @@ struct LLSelectGetFirstTest; class LLSelectMgr : public LLEditMenuHandler, public LLSingleton<LLSelectMgr> { + LLSINGLETON(LLSelectMgr); + ~LLSelectMgr(); + public: static BOOL sRectSelectInclusive; // do we need to surround an object to pick it? static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded? @@ -413,9 +417,6 @@ public: LLCachedControl<bool> mDebugSelectMgr; public: - LLSelectMgr(); - ~LLSelectMgr(); - static void cleanupGlobals(); // LLEditMenuHandler interface diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index f07f0ed86c..a32ed258f8 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -383,12 +383,22 @@ void LLSidepanelAppearance::toggleOutfitEditPanel(BOOL visible, BOOL disable_cam void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearable *wearable, BOOL disable_camera_switch) { - if (!mEditWearable || ((mEditWearable->getWearable() == wearable) && mEditWearable->getVisible() == visible)) + if (!mEditWearable) { - // visibility isn't changing, hence nothing to do return; } + if (mEditWearable->getVisible() == visible && (!visible || mEditWearable->getWearable() != wearable)) + { + // visibility isn't changing and panel doesn't need an update, hence nothing to do + return; + } + + // If we're just switching between outfit and wearable editing or updating item, + // don't end customization and don't switch camera + // Don't end customization and don't switch camera without visibility change + BOOL change_state = !disable_camera_switch && mEditWearable->getVisible() != visible; + if (!wearable) { wearable = gAgentWearables.getViewerWearable(LLWearableType::WT_SHAPE, 0); @@ -403,8 +413,8 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearab if (visible) { - LLVOAvatarSelf::onCustomizeStart(disable_camera_switch); - mEditWearable->setWearable(wearable, disable_camera_switch); + LLVOAvatarSelf::onCustomizeStart(!change_state); + mEditWearable->setWearable(wearable, !change_state); mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency } else @@ -412,9 +422,9 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLViewerWearab // Save changes if closing. mEditWearable->saveChanges(); LLAppearanceMgr::getInstance()->updateIsDirty(); - if (!disable_camera_switch) // if we're just switching between outfit and wearable editing, don't end customization. + if (change_state) { - LLVOAvatarSelf::onCustomizeEnd(disable_camera_switch); + LLVOAvatarSelf::onCustomizeEnd(!change_state); } } } diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 6bcae1e858..c6a0198afd 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -34,6 +34,7 @@ #include "llbutton.h" #include "lldate.h" #include "llfirstuse.h" +#include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llfoldertype.h" #include "llfolderview.h" @@ -731,3 +732,16 @@ std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList() return inventory_selected_uuids; } + +void LLSidepanelInventory::cleanup() +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end();) + { + LLFloaterSidePanelContainer* iv = dynamic_cast<LLFloaterSidePanelContainer*>(*iter++); + if (iv) + { + iv->cleanup(); + } + } +} diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index 17a3098db9..5060f7025f 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -82,6 +82,8 @@ public: void updateVerbs(); + static void cleanup(); + protected: // Tracks highlighted (selected) item in inventory panel. LLInventoryItem *getSelectedItem(); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 049aae1336..58e48480c1 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -465,7 +465,11 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare LL_DEBUGS() << "window reshaped, updating thumbnail" << LL_ENDL; if (mViewContainer && mViewContainer->isInVisibleChain()) { - updateSnapshot(TRUE); + // We usually resize only on window reshape, so give it a chance to redraw, assign delay + updateSnapshot( + TRUE, // new snapshot is needed + FALSE, // thumbnail will be updated either way. + AUTO_SNAPSHOT_TIME_DELAY); // shutter delay. } } } @@ -1032,7 +1036,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name) LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); std::string who_took_it; LLAgentUI::buildFullname(who_took_it); - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string; std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string; LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY; diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 5cff70f377..617bae3984 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -341,20 +341,18 @@ protected: class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr> { + LLSINGLETON(LLActiveSpeakerMgr); LOG_CLASS(LLActiveSpeakerMgr); -public: - LLActiveSpeakerMgr(); protected: virtual void updateSpeakerList(); }; class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr> { - LOG_CLASS(LLLocalSpeakerMgr); -public: - LLLocalSpeakerMgr(); + LLSINGLETON(LLLocalSpeakerMgr); ~LLLocalSpeakerMgr (); + LOG_CLASS(LLLocalSpeakerMgr); protected: virtual void updateSpeakerList(); }; diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 78fe7863c8..5ca1d4b4a5 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -48,6 +48,8 @@ */ class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, LLVoiceClientParticipantObserver { + LLSINGLETON(SpeakingIndicatorManager); + ~SpeakingIndicatorManager(); LOG_CLASS(SpeakingIndicatorManager); public: @@ -91,10 +93,6 @@ private: typedef speaking_indicators_mmap_t::const_iterator indicator_const_iterator; typedef std::pair<indicator_const_iterator, indicator_const_iterator> indicator_range_t; - friend class LLSingleton<SpeakingIndicatorManager>; - SpeakingIndicatorManager(); - ~SpeakingIndicatorManager(); - /** * Callback to determine when voice channel is changed. * diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index dab25f144b..1bb3d65e05 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -194,6 +194,7 @@ #include "llstartuplistener.h" #include "lltoolbarview.h" #include "llexperiencelog.h" +#include "llcleanup.h" #include "llstacktrace.h" @@ -2811,7 +2812,7 @@ void LLStartUp::initExperiences() void LLStartUp::cleanupNameCache() { - LLAvatarNameCache::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarNameCache); delete gCacheName; gCacheName = NULL; @@ -3028,7 +3029,7 @@ bool LLStartUp::startLLProxy() } else { - LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration."<< LL_ENDL; + LL_WARNS("Proxy") << "Invalid other HTTP proxy configuration: " << httpProxyType << LL_ENDL; // Set the missing or wrong configuration back to something valid. gSavedSettings.setString("HttpProxyType", "None"); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 041eae4b3c..72c5c961aa 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -309,7 +309,7 @@ void LLStatusBar::refresh() (LLViewerMedia::hasInWorldMedia() || LLViewerMedia::hasParcelMedia() || LLViewerMedia::hasParcelAudio()); mMediaToggle->setEnabled(button_enabled); // Note the "sense" of the toggle is opposite whether media is playing or not - bool any_media_playing = (LLViewerMedia::isAnyMediaShowing() || + bool any_media_playing = (LLViewerMedia::isAnyMediaPlaying() || LLViewerMedia::isParcelMediaPlaying() || LLViewerMedia::isParcelAudioPlaying()); mMediaToggle->setValue(!any_media_playing); @@ -562,8 +562,8 @@ void LLStatusBar::onClickMediaToggle(void* data) { LLStatusBar *status_bar = (LLStatusBar*)data; // "Selected" means it was showing the "play" icon (so media was playing), and now it shows "pause", so turn off media - bool enable = ! status_bar->mMediaToggle->getValue(); - LLViewerMedia::setAllMediaEnabled(enable); + bool pause = status_bar->mMediaToggle->getValue(); + LLViewerMedia::setAllMediaPaused(pause); } BOOL can_afford_transaction(S32 cost) diff --git a/indra/newview/llstylemap.h b/indra/newview/llstylemap.h index 8aa0af535c..96b3920593 100644 --- a/indra/newview/llstylemap.h +++ b/indra/newview/llstylemap.h @@ -39,6 +39,7 @@ typedef std::map<LLUUID, LLStyle::Params> style_map_t; class LLStyleMap : public LLSingleton<LLStyleMap> { + LLSINGLETON_EMPTY_CTOR(LLStyleMap); public: // Just like the [] accessor but it will add the entry in if it doesn't exist. const LLStyle::Params &lookupAgent(const LLUUID &source); diff --git a/indra/newview/llsyntaxid.h b/indra/newview/llsyntaxid.h index 0afa6dc04b..1360b3e042 100644 --- a/indra/newview/llsyntaxid.h +++ b/indra/newview/llsyntaxid.h @@ -38,9 +38,9 @@ class fetchKeywordsFileResponder; class LLSyntaxIdLSL : public LLSingleton<LLSyntaxIdLSL> { - friend class LLSingleton<LLSyntaxIdLSL>; + LLSINGLETON(LLSyntaxIdLSL); friend class fetchKeywordsFileResponder; - + private: std::set<std::string> mInflightFetches; typedef boost::signals2::signal<void()> syntax_id_changed_signal_t; @@ -67,7 +67,6 @@ private: LLSD mKeywordsXml; public: - LLSyntaxIdLSL(); void initialize(); bool keywordFetchInProgress(); LLSD getKeywordsXML() const { return mKeywordsXml; }; diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index d02293e6ff..b96a2573a1 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -32,6 +32,7 @@ #include "llscreenchannel.h" #include "llsyswellitem.h" #include "lltransientdockablefloater.h" +#include "llinitdestroyclass.h" class LLAvatarName; class LLChiclet; diff --git a/indra/newview/llteleporthistory.h b/indra/newview/llteleporthistory.h index e9c29c39bf..db0ccdda59 100644 --- a/indra/newview/llteleporthistory.h +++ b/indra/newview/llteleporthistory.h @@ -73,6 +73,8 @@ public: */ class LLTeleportHistory: public LLSingleton<LLTeleportHistory> { + LLSINGLETON(LLTeleportHistory); + ~LLTeleportHistory(); LOG_CLASS(LLTeleportHistory); public: @@ -81,9 +83,6 @@ public: typedef boost::function<void()> history_callback_t; typedef boost::signals2::signal<void()> history_signal_t; - LLTeleportHistory(); - ~LLTeleportHistory(); - /** * Go back in the history. */ diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h index cf4c85a991..946ac0af1a 100644 --- a/indra/newview/llteleporthistorystorage.h +++ b/indra/newview/llteleporthistorystorage.h @@ -68,6 +68,8 @@ public: */ class LLTeleportHistoryStorage: public LLSingleton<LLTeleportHistoryStorage> { + LLSINGLETON(LLTeleportHistoryStorage); + ~LLTeleportHistoryStorage(); LOG_CLASS(LLTeleportHistoryStorage); public: @@ -78,9 +80,6 @@ public: typedef boost::function<void(S32 removed_index)> history_callback_t; typedef boost::signals2::signal<void(S32 removed_index)> history_signal_t; - LLTeleportHistoryStorage(); - ~LLTeleportHistoryStorage(); - /** * @return history items. */ diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h index b643056198..1b8df708c6 100644 --- a/indra/newview/lltextureatlasmanager.h +++ b/indra/newview/lltextureatlasmanager.h @@ -85,12 +85,11 @@ private: class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager> { -private: + LLSINGLETON(LLTextureAtlasManager); + ~LLTextureAtlasManager(); typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ; public: - LLTextureAtlasManager(); - ~LLTextureAtlasManager(); LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents, LLSpatialGroup* groupp, LLViewerTexture* imagep) ; diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 36c4f0d516..a541273621 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -547,10 +547,18 @@ bool LLTextureCacheRemoteWorker::doWrite() // First state / stage : check that what we're trying to cache is in an OK shape if (mState == INIT) { - llassert_always(mOffset == 0); // We currently do not support write offsets - llassert_always(mDataSize > 0); // Things will go badly wrong if mDataSize is nul or negative... - llassert_always(mImageSize >= mDataSize); - mState = CACHE; + if ((mOffset != 0) // We currently do not support write offsets + || (mDataSize <= 0) // Things will go badly wrong if mDataSize is nul or negative... + || (mImageSize < mDataSize)) + { + LL_WARNS() << "INIT state check failed" << LL_ENDL; + mDataSize = -1; // failed + done = true; + } + else + { + mState = CACHE; + } } // No LOCAL state for write(): because it doesn't make much sense to cache a local file... @@ -559,7 +567,7 @@ bool LLTextureCacheRemoteWorker::doWrite() if (!done && (mState == CACHE)) { bool alreadyCached = false; - LLTextureCache::Entry entry ; + LLTextureCache::Entry entry; // Checks if this image is already in the entry list idx = mCache->getHeaderCacheEntry(mID, entry); @@ -571,107 +579,132 @@ bool LLTextureCacheRemoteWorker::doWrite() // (almost always) write to the fast cache. if (mRawImage->getDataSize()) { - llassert_always(mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel)); + if(!mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel)) + { + LL_WARNS() << "writeToFastCache failed" << LL_ENDL; + mDataSize = -1; // failed + done = true; + } + } } } - } else { alreadyCached = mCache->updateEntry(idx, entry, mImageSize, mDataSize); // update the existing entry. } - if (idx < 0) - { - LL_WARNS() << "LLTextureCacheWorker: " << mID - << " Unable to create header entry for writing!" << LL_ENDL; - mDataSize = -1; // failed - done = true; - } - else + if (!done) { - if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) + if (idx < 0) { - // Small texture already cached case: we're done with writing + LL_WARNS() << "LLTextureCacheWorker: " << mID + << " Unable to create header entry for writing!" << LL_ENDL; + mDataSize = -1; // failed done = true; } else { - // If the texture has already been cached, we don't resave the header and go directly to the body part - mState = alreadyCached ? BODY : HEADER; + if (alreadyCached && (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)) + { + // Small texture already cached case: we're done with writing + done = true; + } + else + { + // If the texture has already been cached, we don't resave the header and go directly to the body part + mState = alreadyCached ? BODY : HEADER; + } } } } + // Third stage / state : write the header record in the header file (texture.cache) if (!done && (mState == HEADER)) { - llassert_always(idx >= 0); // we need an entry here or storing the header makes no sense - S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file - S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header - S32 bytes_written; - - if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE) + if (idx < 0) // we need an entry here or storing the header makes no sense { - // We need to write a full record in the header cache so, if the amount of data is smaller - // than a record, we need to transfer the data to a buffer padded with 0 and write that - U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE); - memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros - memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer - bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); - FREE_MEM(LLImageBase::getPrivatePool(), padBuffer); + LL_WARNS() << "index check failed" << LL_ENDL; + mDataSize = -1; // failed + done = true; } else { - // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file - bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); - } + S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE; // skip to the correct spot in the header file + S32 size = TEXTURE_CACHE_ENTRY_SIZE; // record size is fixed for the header + S32 bytes_written; - if (bytes_written <= 0) - { - LL_WARNS() << "LLTextureCacheWorker: " << mID + if (mDataSize < TEXTURE_CACHE_ENTRY_SIZE) + { + // We need to write a full record in the header cache so, if the amount of data is smaller + // than a record, we need to transfer the data to a buffer padded with 0 and write that + U8* padBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_CACHE_ENTRY_SIZE); + memset(padBuffer, 0, TEXTURE_CACHE_ENTRY_SIZE); // Init with zeros + memcpy(padBuffer, mWriteData, mDataSize); // Copy the write buffer + bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, padBuffer, offset, size, mCache->getLocalAPRFilePool()); + FREE_MEM(LLImageBase::getPrivatePool(), padBuffer); + } + else + { + // Write the header record (== first TEXTURE_CACHE_ENTRY_SIZE bytes of the raw file) in the header file + bytes_written = LLAPRFile::writeEx(mCache->mHeaderDataFileName, mWriteData, offset, size, mCache->getLocalAPRFilePool()); + } + + if (bytes_written <= 0) + { + LL_WARNS() << "LLTextureCacheWorker: " << mID << " Unable to write header entry!" << LL_ENDL; - mDataSize = -1; // failed - done = true; - } + mDataSize = -1; // failed + done = true; + } - // If we wrote everything (may be more with padding) in the header cache, - // we're done so we don't have a body to store - if (mDataSize <= bytes_written) - { - done = true; - } - else - { - mState = BODY; + // If we wrote everything (may be more with padding) in the header cache, + // we're done so we don't have a body to store + if (mDataSize <= bytes_written) + { + done = true; + } + else + { + mState = BODY; + } } } // Fourth stage / state : write the body file, i.e. the rest of the texture in a "UUID" file name if (!done && (mState == BODY)) { - llassert(mDataSize > TEXTURE_CACHE_ENTRY_SIZE); // wouldn't make sense to be here otherwise... - S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; - + if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) // wouldn't make sense to be here otherwise... { - // build the cache file name from the UUID - std::string filename = mCache->getTextureFileName(mID); -// LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL; - S32 bytes_written = LLAPRFile::writeEx( filename, - mWriteData + TEXTURE_CACHE_ENTRY_SIZE, - 0, file_size, - mCache->getLocalAPRFilePool()); - if (bytes_written <= 0) + LL_WARNS() << "mDataSize check failed" << LL_ENDL; + mDataSize = -1; // failed + done = true; + } + else + { + S32 file_size = mDataSize - TEXTURE_CACHE_ENTRY_SIZE; + { - LL_WARNS() << "LLTextureCacheWorker: " << mID + // build the cache file name from the UUID + std::string filename = mCache->getTextureFileName(mID); + // LL_INFOS() << "Writing Body: " << filename << " Bytes: " << file_offset+file_size << LL_ENDL; + S32 bytes_written = LLAPRFile::writeEx(filename, + mWriteData + TEXTURE_CACHE_ENTRY_SIZE, + 0, file_size, + mCache->getLocalAPRFilePool()); + if (bytes_written <= 0) + { + LL_WARNS() << "LLTextureCacheWorker: " << mID << " incorrect number of bytes written to body: " << bytes_written << " / " << file_size << LL_ENDL; - mDataSize = -1; // failed - done = true; + mDataSize = -1; // failed + done = true; + } } + + // Nothing else to do at that point... + done = true; } - - // Nothing else to do at that point... - done = true; } mRawImage = NULL; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 24bc55c998..c7adaa908f 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -43,7 +43,6 @@ #include "llinventorymodelbackgroundfetch.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" -#include "llfloaterinventory.h" #include "lllineeditor.h" #include "llui.h" #include "llviewerinventory.h" @@ -565,7 +564,7 @@ void LLFloaterTexturePicker::draw() } } -const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only) +const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library) { LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; @@ -585,7 +584,10 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co LLPermissions item_permissions = itemp->getPermissions(); if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID())) { - return itemp->getUUID(); + if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID())) + { + return itemp->getUUID(); + } } } // otherwise just return first instance, unless copyable requested @@ -595,7 +597,10 @@ const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL co } else { - return items[0]->getUUID(); + if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID())) + { + return items[0]->getUUID(); + } } } diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 61f99de5c0..840feddfaf 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -278,7 +278,7 @@ public: void setImageID(const LLUUID& image_asset_id, bool set_selection = true); void updateImageStats(); const LLUUID& getAssetID() { return mImageAssetID; } - const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); + const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only, BOOL ignore_library = FALSE); void setCanApplyImmediately(BOOL b); void setActive(BOOL active); diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index f6ca0bc9d7..f7dc32d0d7 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -47,7 +47,6 @@ #include "llglheaders.h" #include "llagent.h" #include "llavatariconctrl.h" -#include "llfloaterinventory.h" #include "llinventorytype.h" const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 7; diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp index 5e703933ca..4aad650b68 100644 --- a/indra/newview/lltool.cpp +++ b/indra/newview/lltool.cpp @@ -38,7 +38,6 @@ #include "lltoolfocus.h" #include "llfocusmgr.h" #include "llagent.h" -#include "llagentcamera.h" #include "llviewerjoystick.h" extern BOOL gDebugClicks; @@ -85,14 +84,7 @@ BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask) } // by default, didn't handle it // LL_INFOS() << "LLTool::handleMouseDown" << LL_ENDL; - if (gAgentCamera.cameraMouselook()) - { - gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); - } - else - { - gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN); - } + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN); return TRUE; } @@ -103,15 +95,8 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask) LL_INFOS() << "LLTool left mouse up" << LL_ENDL; } // by default, didn't handle it - // LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL; - if (gAgentCamera.cameraMouselook()) - { - gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP); - } - else - { - gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP); - } + // LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL; + gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP); return TRUE; } diff --git a/indra/newview/lltoolbrush.h b/indra/newview/lltoolbrush.h index 2ec6911de9..c108d83256 100644 --- a/indra/newview/lltoolbrush.h +++ b/indra/newview/lltoolbrush.h @@ -43,10 +43,10 @@ class LLViewerRegion; class LLToolBrushLand : public LLTool, public LLEditMenuHandler, public LLSingleton<LLToolBrushLand> { + LLSINGLETON(LLToolBrushLand); typedef std::set<LLViewerRegion*> region_list_t; public: - LLToolBrushLand(); // x,y in window coords, 0,0 = left,bot virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp index 2b4fa757f6..392c103d7c 100644 --- a/indra/newview/lltoolcomp.cpp +++ b/indra/newview/lltoolcomp.cpp @@ -683,7 +683,7 @@ LLToolCompGun::LLToolCompGun() : LLToolComposite(std::string("Mouselook")) { mGun = new LLToolGun(this); - mGrab = new LLToolGrab(this); + mGrab = new LLToolGrabBase(this); mNull = sNullTool; setCurrentTool(mGun); @@ -742,13 +742,12 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) { - // if the left button is blocked, don't put up the pie menu - if (gAgent.leftButtonBlocked()) - { - // in case of "grabbed" control flag will be set later - gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); - return FALSE; - } + // if the left button is grabbed, don't put up the pie menu + if (gAgent.leftButtonGrabbed()) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); + return FALSE; + } // On mousedown, start grabbing gGrabTransientTool = this; @@ -760,13 +759,12 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask) { - // if the left button is blocked, don't put up the pie menu - if (gAgent.leftButtonBlocked()) - { - // in case of "grabbed" control flag will be set later - gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); - return FALSE; - } + // if the left button is grabbed, don't put up the pie menu + if (gAgent.leftButtonGrabbed()) + { + gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN); + return FALSE; + } // On mousedown, start grabbing gGrabTransientTool = this; diff --git a/indra/newview/lltoolcomp.h b/indra/newview/lltoolcomp.h index e75d3c22e2..86506f725e 100644 --- a/indra/newview/lltoolcomp.h +++ b/indra/newview/lltoolcomp.h @@ -103,9 +103,9 @@ public: class LLToolCompInspect : public LLToolComposite, public LLSingleton<LLToolCompInspect> { -public: - LLToolCompInspect(); + LLSINGLETON(LLToolCompInspect); virtual ~LLToolCompInspect(); +public: // Overridden from LLToolComposite virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); @@ -128,9 +128,9 @@ private: class LLToolCompTranslate : public LLToolComposite, public LLSingleton<LLToolCompTranslate> { -public: - LLToolCompTranslate(); + LLSINGLETON(LLToolCompTranslate); virtual ~LLToolCompTranslate(); +public: // Overridden from LLToolComposite virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); @@ -149,9 +149,9 @@ public: class LLToolCompScale : public LLToolComposite, public LLSingleton<LLToolCompScale> { -public: - LLToolCompScale(); + LLSINGLETON(LLToolCompScale); virtual ~LLToolCompScale(); +public: // Overridden from LLToolComposite virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); @@ -171,9 +171,9 @@ public: class LLToolCompRotate : public LLToolComposite, public LLSingleton<LLToolCompRotate> { -public: - LLToolCompRotate(); + LLSINGLETON(LLToolCompRotate); virtual ~LLToolCompRotate(); +public: // Overridden from LLToolComposite virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); @@ -194,9 +194,9 @@ protected: class LLToolCompCreate : public LLToolComposite, public LLSingleton<LLToolCompCreate> { -public: - LLToolCompCreate(); + LLSINGLETON(LLToolCompCreate); virtual ~LLToolCompCreate(); +public: // Overridden from LLToolComposite virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); @@ -214,14 +214,14 @@ protected: // LLToolCompGun class LLToolGun; -class LLToolGrab; +class LLToolGrabBase; class LLToolSelect; class LLToolCompGun : public LLToolComposite, public LLSingleton<LLToolCompGun> { -public: - LLToolCompGun(); + LLSINGLETON(LLToolCompGun); virtual ~LLToolCompGun(); +public: // Overridden from LLToolComposite virtual BOOL handleHover(S32 x, S32 y, MASK mask); @@ -237,7 +237,7 @@ public: protected: LLToolGun* mGun; - LLToolGrab* mGrab; + LLToolGrabBase* mGrab; LLTool* mNull; }; diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 63be1ef09b..766046785b 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -43,11 +43,10 @@ class LLPickInfo; class LLToolDragAndDrop : public LLTool, public LLSingleton<LLToolDragAndDrop> { + LLSINGLETON(LLToolDragAndDrop); public: typedef boost::signals2::signal<void ()> enddrag_signal_t; - LLToolDragAndDrop(); - // overridden from LLTool virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); @@ -281,8 +280,8 @@ private: class LLDragAndDropDictionary : public LLSingleton<LLDragAndDropDictionary>, public LLDictionary<EDragAndDropType, DragAndDropEntry> { + LLSINGLETON(LLDragAndDropDictionary); public: - LLDragAndDropDictionary(); dragOrDrop3dImpl get(EDragAndDropType dad_type, EDropTarget drop_target); }; }; diff --git a/indra/newview/lltoolface.h b/indra/newview/lltoolface.h index 7eb13b0fbc..e4b8ae12b8 100644 --- a/indra/newview/lltoolface.h +++ b/indra/newview/lltoolface.h @@ -35,9 +35,9 @@ class LLPickInfo; class LLToolFace : public LLTool, public LLSingleton<LLToolFace> { -public: - LLToolFace(); + LLSINGLETON(LLToolFace); virtual ~LLToolFace(); +public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolfocus.h b/indra/newview/lltoolfocus.h index d23eb2cce6..cfc235b6c2 100644 --- a/indra/newview/lltoolfocus.h +++ b/indra/newview/lltoolfocus.h @@ -34,9 +34,9 @@ class LLPickInfo; class LLToolCamera : public LLTool, public LLSingleton<LLToolCamera> { -public: - LLToolCamera(); + LLSINGLETON(LLToolCamera); virtual ~LLToolCamera(); +public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index c0ca4d7a9a..5623036b91 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -69,7 +69,7 @@ extern BOOL gDebugClicks; // // Methods // -LLToolGrab::LLToolGrab( LLToolComposite* composite ) +LLToolGrabBase::LLToolGrabBase( LLToolComposite* composite ) : LLTool( std::string("Grab"), composite ), mMode( GRAB_INACTIVE ), mVerticalDragging( FALSE ), @@ -88,12 +88,12 @@ LLToolGrab::LLToolGrab( LLToolComposite* composite ) mHideBuildHighlight(FALSE) { } -LLToolGrab::~LLToolGrab() +LLToolGrabBase::~LLToolGrabBase() { } // virtual -void LLToolGrab::handleSelect() +void LLToolGrabBase::handleSelect() { if(gFloaterTools) { @@ -106,7 +106,7 @@ void LLToolGrab::handleSelect() gGrabBtnSpin = FALSE; } -void LLToolGrab::handleDeselect() +void LLToolGrabBase::handleDeselect() { if( hasMouseCapture() ) { @@ -123,7 +123,7 @@ void LLToolGrab::handleDeselect() } -BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleDoubleClick(S32 x, S32 y, MASK mask) { if (gDebugClicks) { @@ -133,7 +133,7 @@ BOOL LLToolGrab::handleDoubleClick(S32 x, S32 y, MASK mask) return FALSE; } -BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask) { if (gDebugClicks) { @@ -143,7 +143,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) // call the base class to propogate info to sim LLTool::handleMouseDown(x, y, mask); - if (!gAgent.leftButtonBlocked()) + if (!gAgent.leftButtonGrabbed()) { // can grab transparent objects (how touch event propagates, scripters rely on this) gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE); @@ -152,7 +152,7 @@ BOOL LLToolGrab::handleMouseDown(S32 x, S32 y, MASK mask) return TRUE; } -void LLToolGrab::pickCallback(const LLPickInfo& pick_info) +void LLToolGrabBase::pickCallback(const LLPickInfo& pick_info) { LLToolGrab::getInstance()->mGrabPick = pick_info; LLViewerObject *objectp = pick_info.getObject(); @@ -182,7 +182,7 @@ void LLToolGrab::pickCallback(const LLPickInfo& pick_info) } } -BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) +BOOL LLToolGrabBase::handleObjectHit(const LLPickInfo& info) { mGrabPick = info; LLViewerObject* objectp = mGrabPick.getObject(); @@ -315,7 +315,7 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) } -void LLToolGrab::startSpin() +void LLToolGrabBase::startSpin() { LLViewerObject* objectp = mGrabPick.getObject(); if (!objectp) @@ -339,7 +339,7 @@ void LLToolGrab::startSpin() } -void LLToolGrab::stopSpin() +void LLToolGrabBase::stopSpin() { mSpinGrabbing = FALSE; @@ -373,7 +373,7 @@ void LLToolGrab::stopSpin() } -void LLToolGrab::startGrab() +void LLToolGrabBase::startGrab() { // Compute grab_offset in the OBJECT's root's coordinate frame // (sometimes root == object) @@ -422,7 +422,7 @@ void LLToolGrab::startGrab() } -BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleHover(S32 x, S32 y, MASK mask) { if (!gViewerWindow->getLeftMouseDown()) { @@ -466,7 +466,7 @@ const F32 GRAB_SENSITIVITY_Y = 0.0075f; // Dragging. -void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverActive(S32 x, S32 y, MASK mask) { LLViewerObject* objectp = mGrabPick.getObject(); if (!objectp || !hasMouseCapture() ) return; @@ -724,7 +724,7 @@ void LLToolGrab::handleHoverActive(S32 x, S32 y, MASK mask) } -void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverNonPhysical(S32 x, S32 y, MASK mask) { LLViewerObject* objectp = mGrabPick.getObject(); if (!objectp || !hasMouseCapture() ) return; @@ -881,7 +881,7 @@ void LLToolGrab::handleHoverNonPhysical(S32 x, S32 y, MASK mask) // Not dragging. Just showing affordances -void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverInactive(S32 x, S32 y, MASK mask) { // JC - TODO - change cursor based on gGrabBtnVertical, gGrabBtnSpin LL_DEBUGS("UserInput") << "hover handled by LLToolGrab (inactive-not over editable object)" << LL_ENDL; @@ -889,7 +889,7 @@ void LLToolGrab::handleHoverInactive(S32 x, S32 y, MASK mask) } // User is trying to do something that's not allowed. -void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask) +void LLToolGrabBase::handleHoverFailed(S32 x, S32 y, MASK mask) { if( GRAB_NOOBJECT == mMode ) { @@ -930,7 +930,7 @@ void LLToolGrab::handleHoverFailed(S32 x, S32 y, MASK mask) -BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask) +BOOL LLToolGrabBase::handleMouseUp(S32 x, S32 y, MASK mask) { // call the base class to propogate info to sim LLTool::handleMouseUp(x, y, mask); @@ -961,7 +961,7 @@ BOOL LLToolGrab::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } -void LLToolGrab::stopEditing() +void LLToolGrabBase::stopEditing() { if( hasMouseCapture() ) { @@ -969,7 +969,7 @@ void LLToolGrab::stopEditing() } } -void LLToolGrab::onMouseCaptureLost() +void LLToolGrabBase::onMouseCaptureLost() { LLViewerObject* objectp = mGrabPick.getObject(); if (!objectp) @@ -1026,7 +1026,7 @@ void LLToolGrab::onMouseCaptureLost() } -void LLToolGrab::stopGrab() +void LLToolGrabBase::stopGrab() { LLViewerObject* objectp = mGrabPick.getObject(); if (!objectp) @@ -1067,29 +1067,29 @@ void LLToolGrab::stopGrab() } -void LLToolGrab::draw() +void LLToolGrabBase::draw() { } -void LLToolGrab::render() +void LLToolGrabBase::render() { } -BOOL LLToolGrab::isEditing() +BOOL LLToolGrabBase::isEditing() { return (mGrabPick.getObject().notNull()); } -LLViewerObject* LLToolGrab::getEditingObject() +LLViewerObject* LLToolGrabBase::getEditingObject() { return mGrabPick.getObject(); } -LLVector3d LLToolGrab::getEditingPointGlobal() +LLVector3d LLToolGrabBase::getEditingPointGlobal() { return getGrabPointGlobal(); } -LLVector3d LLToolGrab::getGrabPointGlobal() +LLVector3d LLToolGrabBase::getGrabPointGlobal() { switch(mMode) { diff --git a/indra/newview/lltoolgrab.h b/indra/newview/lltoolgrab.h index 5d24c8813e..02ed5c26d7 100644 --- a/indra/newview/lltoolgrab.h +++ b/indra/newview/lltoolgrab.h @@ -45,12 +45,17 @@ void send_ObjectGrab_message(LLViewerObject* object, const LLPickInfo & pick, co void send_ObjectDeGrab_message(LLViewerObject* object, const LLPickInfo & pick); - -class LLToolGrab : public LLTool, public LLSingleton<LLToolGrab> +/** + * LLToolGrabBase contains most of the semantics of LLToolGrab. It's just that + * LLToolGrab is an LLSingleton, but we also explicitly instantiate + * LLToolGrabBase as part of LLToolCompGun. You can't just make an extra + * instance of an LLSingleton! + */ +class LLToolGrabBase : public LLTool { public: - LLToolGrab( LLToolComposite* composite = NULL ); - ~LLToolGrab(); + LLToolGrabBase(LLToolComposite* composite=NULL); + ~LLToolGrabBase(); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); @@ -140,10 +145,14 @@ private: BOOL mClickedInMouselook; }; +/// This is the LLSingleton instance of LLToolGrab. +class LLToolGrab : public LLToolGrabBase, public LLSingleton<LLToolGrab> +{ + LLSINGLETON_EMPTY_CTOR(LLToolGrab); +}; + extern BOOL gGrabBtnVertical; extern BOOL gGrabBtnSpin; extern LLTool* gGrabTransientTool; #endif // LL_TOOLGRAB_H - - diff --git a/indra/newview/lltoolindividual.h b/indra/newview/lltoolindividual.h index 961a6a4d93..e7c2060fba 100644 --- a/indra/newview/lltoolindividual.h +++ b/indra/newview/lltoolindividual.h @@ -39,9 +39,9 @@ class LLPickInfo; class LLToolIndividual : public LLTool, public LLSingleton<LLToolIndividual> { -public: - LLToolIndividual(); + LLSINGLETON(LLToolIndividual); virtual ~LLToolIndividual(); +public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index e5b45750d9..28465d5d2c 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -42,9 +42,9 @@ const MASK MASK_COPY = MASK_SHIFT; class LLToolMgr : public LLSingleton<LLToolMgr> { -public: - LLToolMgr(); + LLSINGLETON(LLToolMgr); ~LLToolMgr(); +public: // Must be called after gSavedSettings set up. void initTools(); diff --git a/indra/newview/lltoolobjpicker.h b/indra/newview/lltoolobjpicker.h index 0c37be1f92..5ad9b67e21 100644 --- a/indra/newview/lltoolobjpicker.h +++ b/indra/newview/lltoolobjpicker.h @@ -35,8 +35,8 @@ class LLPickInfo; class LLToolObjPicker : public LLTool, public LLSingleton<LLToolObjPicker> { + LLSINGLETON(LLToolObjPicker); public: - LLToolObjPicker(); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 6391e675c5..95d155a474 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -37,9 +37,9 @@ class LLObjectSelection; class LLToolPie : public LLTool, public LLSingleton<LLToolPie> { + LLSINGLETON(LLToolPie); LOG_CLASS(LLToolPie); public: - LLToolPie( ); // Virtual functions inherited from LLMouseHandler virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down); diff --git a/indra/newview/lltoolpipette.h b/indra/newview/lltoolpipette.h index 8a83bf31af..7575d8ad18 100644 --- a/indra/newview/lltoolpipette.h +++ b/indra/newview/lltoolpipette.h @@ -43,10 +43,10 @@ class LLPickInfo; class LLToolPipette : public LLTool, public LLSingleton<LLToolPipette> { -public: - LLToolPipette(); + LLSINGLETON(LLToolPipette); virtual ~LLToolPipette(); +public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoolselectland.h b/indra/newview/lltoolselectland.h index b368a4b153..b5ba72f16d 100644 --- a/indra/newview/lltoolselectland.h +++ b/indra/newview/lltoolselectland.h @@ -35,10 +35,10 @@ class LLParcelSelection; class LLToolSelectLand : public LLTool, public LLSingleton<LLToolSelectLand> { -public: - LLToolSelectLand( ); + LLSINGLETON(LLToolSelectLand); virtual ~LLToolSelectLand(); +public: /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h index b4611c8c87..d126543f15 100644 --- a/indra/newview/lltransientfloatermgr.h +++ b/indra/newview/lltransientfloatermgr.h @@ -38,9 +38,7 @@ class LLTransientFloater; */ class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr> { -protected: - LLTransientFloaterMgr(); - friend class LLSingleton<LLTransientFloaterMgr>; + LLSINGLETON(LLTransientFloaterMgr); public: enum ETransientGroup diff --git a/indra/newview/lltwitterconnect.h b/indra/newview/lltwitterconnect.h index be481a17c1..e77048cc35 100644 --- a/indra/newview/lltwitterconnect.h +++ b/indra/newview/lltwitterconnect.h @@ -43,6 +43,7 @@ class LLEventPump; */ class LLTwitterConnect : public LLSingleton<LLTwitterConnect> { + LLSINGLETON(LLTwitterConnect); LOG_CLASS(LLTwitterConnect); public: enum EConnectionState @@ -81,10 +82,7 @@ public: void openTwitterWeb(std::string url); private: - friend class LLSingleton<LLTwitterConnect>; - LLTwitterConnect(); - ~LLTwitterConnect() {}; std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false); EConnectionState mConnectionState; diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index 08ba5a5f25..ad0c1734f9 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -48,8 +48,7 @@ struct ViewerAssetEntry : public LLDictionaryEntry class LLViewerAssetDictionary : public LLSingleton<LLViewerAssetDictionary>, public LLDictionary<LLViewerAssetType::EType, ViewerAssetEntry> { -public: - LLViewerAssetDictionary(); + LLSINGLETON(LLViewerAssetDictionary); }; LLViewerAssetDictionary::LLViewerAssetDictionary() diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 94f1b09fa9..cafaf8645a 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -174,7 +174,7 @@ S32 LLResourceUploadInfo::getEconomyUploadCost() getAssetType() == LLAssetType::AT_ANIMATION || getAssetType() == LLAssetType::AT_MESH) { - return LLGlobalEconomy::Singleton::instance().getPriceUpload(); + return LLGlobalEconomy::instance().getPriceUpload(); } return 0; @@ -824,8 +824,15 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res } LLSD args; - args["FILE"] = uploadInfo->getDisplayName(); - args["REASON"] = reason; + if(label == "ErrorMessage") + { + args["ERROR_MESSAGE"] = reason; + } + else + { + args["FILE"] = uploadInfo->getDisplayName(); + args["REASON"] = reason; + } LLNotificationsUtil::add(label, args); diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h index 8c302c6549..16f9b63113 100644 --- a/indra/newview/llvieweraudio.h +++ b/indra/newview/llvieweraudio.h @@ -43,6 +43,9 @@ void audio_update_wind(bool force_update = true); class LLViewerAudio : public LLSingleton<LLViewerAudio> { + LLSINGLETON(LLViewerAudio); + virtual ~LLViewerAudio(); + public: enum EFadeState @@ -52,9 +55,6 @@ public: FADE_OUT, }; - LLViewerAudio(); - virtual ~LLViewerAudio(); - void startInternetStreamWithAutoFade(std::string streamURI); void stopInternetStreamWithAutoFade(); diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 7b2887d725..f8c973690a 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -54,6 +54,7 @@ extern template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInst LL_ALIGN_PREFIX(16) class LLViewerCamera : public LLCamera, public LLSingleton<LLViewerCamera> { + LLSINGLETON(LLViewerCamera); public: void* operator new(size_t size) { @@ -82,8 +83,6 @@ public: static eCameraID sCurCameraID; - LLViewerCamera(); - void updateCameraLocation(const LLVector3 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 6d13d28e18..ec7a81584a 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -77,7 +77,6 @@ #include "llfloaterimagepreview.h" #include "llfloaterimsession.h" #include "llfloaterinspect.h" -#include "llfloaterinventory.h" #include "llfloaterjoystick.h" #include "llfloaterlagmeter.h" #include "llfloaterland.h" @@ -93,6 +92,7 @@ #include "llfloaternotificationstabbed.h" #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" +#include "llfloateroutfitphotopreview.h" #include "llfloateroutfitsnapshot.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindingconsole.h" @@ -277,6 +277,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>); LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>); + LLFloaterReg::add("outfit_photo_preview", "floater_outfit_photo_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitPhotoPreview>); LLFloaterPayUtil::registerFloater(); LLFloaterReg::add("pathfinding_characters", "floater_pathfinding_characters.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPathfindingCharacters>); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index b8ff2cc9b4..9cb2e0336a 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -103,8 +103,7 @@ struct ViewerFolderEntry : public LLDictionaryEntry class LLViewerFolderDictionary : public LLSingleton<LLViewerFolderDictionary>, public LLDictionary<LLFolderType::EType, ViewerFolderEntry> { -public: - LLViewerFolderDictionary(); + LLSINGLETON(LLViewerFolderDictionary); protected: bool initEnsemblesFromFile(); // Reads in ensemble information from foldertypes.xml }; diff --git a/indra/newview/llviewerhelp.h b/indra/newview/llviewerhelp.h index a983012e2e..da50e07a43 100644 --- a/indra/newview/llviewerhelp.h +++ b/indra/newview/llviewerhelp.h @@ -39,7 +39,7 @@ class LLUICtrl; class LLViewerHelp : public LLHelp, public LLSingleton<LLViewerHelp> { - friend class LLSingleton<LLViewerHelp>; + LLSINGLETON_EMPTY_CTOR(LLViewerHelp); public: /// display the specified help topic in the help viewer diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 0bbe9fa2c2..caffeadb73 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -49,7 +49,6 @@ #include "llinventorybridge.h" #include "llinventorypanel.h" -#include "llfloaterinventory.h" #include "lllandmarkactions.h" #include "llviewerassettype.h" @@ -94,107 +93,10 @@ void doInventoryCb(LLPointer<LLInventoryCallback> cb, LLUUID id) ///---------------------------------------------------------------------------- class LLLocalizedInventoryItemsDictionary : public LLSingleton<LLLocalizedInventoryItemsDictionary> { + LLSINGLETON(LLLocalizedInventoryItemsDictionary); public: std::map<std::string, std::string> mInventoryItemsDict; - LLLocalizedInventoryItemsDictionary() - { - mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape"); - mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin"); - mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair"); - mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes"); - mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt"); - mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants"); - mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes"); - mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks"); - mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket"); - mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves"); - mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt"); - mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants"); - mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt"); - mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha"); - mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo"); - mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics"); - mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); - - mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); - mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); - mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); - mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); - mInventoryItemsDict["Contents"] = LLTrans::getString("Contents"); - - mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture"); - mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures"); - mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures"); - mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures"); - mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures"); - mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures"); - - //predefined gestures - - //male - mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me"); - mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 - mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss"); - mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo"); - mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored"); - mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey"); - mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh"); - mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed"); - mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug"); - mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out"); - mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow"); - - //female - mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle"); - mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry"); - mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed"); - mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me"); - mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 - mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss"); - mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo"); - mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored"); - mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey"); - mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby"); - mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh"); - mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good"); - mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here"); - mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please"); - mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed"); - mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug"); - mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); - mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); - - //common - mInventoryItemsDict["/bow"] = LLTrans::getString("/bow"); - mInventoryItemsDict["/clap"] = LLTrans::getString("/clap"); - mInventoryItemsDict["/count"] = LLTrans::getString("/count"); - mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish"); - mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb"); - mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle"); - mInventoryItemsDict["/no"] = LLTrans::getString("/no"); - mInventoryItemsDict["/no!"] = LLTrans::getString("/no!"); - mInventoryItemsDict["/paper"] = LLTrans::getString("/paper"); - mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme"); - mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou"); - mInventoryItemsDict["/rock"] = LLTrans::getString("/rock"); - mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor"); - mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke"); - mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch"); - mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle"); - mInventoryItemsDict["/yes"] = LLTrans::getString("/yes"); - mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!"); - mInventoryItemsDict["afk"] = LLTrans::getString("afk"); - mInventoryItemsDict["dance1"] = LLTrans::getString("dance1"); - mInventoryItemsDict["dance2"] = LLTrans::getString("dance2"); - mInventoryItemsDict["dance3"] = LLTrans::getString("dance3"); - mInventoryItemsDict["dance4"] = LLTrans::getString("dance4"); - mInventoryItemsDict["dance5"] = LLTrans::getString("dance5"); - mInventoryItemsDict["dance6"] = LLTrans::getString("dance6"); - mInventoryItemsDict["dance7"] = LLTrans::getString("dance7"); - mInventoryItemsDict["dance8"] = LLTrans::getString("dance8"); - } - /** * Finds passed name in dictionary and replaces it with found localized value. * @@ -217,6 +119,103 @@ public: } }; +LLLocalizedInventoryItemsDictionary::LLLocalizedInventoryItemsDictionary() +{ + mInventoryItemsDict["New Shape"] = LLTrans::getString("New Shape"); + mInventoryItemsDict["New Skin"] = LLTrans::getString("New Skin"); + mInventoryItemsDict["New Hair"] = LLTrans::getString("New Hair"); + mInventoryItemsDict["New Eyes"] = LLTrans::getString("New Eyes"); + mInventoryItemsDict["New Shirt"] = LLTrans::getString("New Shirt"); + mInventoryItemsDict["New Pants"] = LLTrans::getString("New Pants"); + mInventoryItemsDict["New Shoes"] = LLTrans::getString("New Shoes"); + mInventoryItemsDict["New Socks"] = LLTrans::getString("New Socks"); + mInventoryItemsDict["New Jacket"] = LLTrans::getString("New Jacket"); + mInventoryItemsDict["New Gloves"] = LLTrans::getString("New Gloves"); + mInventoryItemsDict["New Undershirt"] = LLTrans::getString("New Undershirt"); + mInventoryItemsDict["New Underpants"] = LLTrans::getString("New Underpants"); + mInventoryItemsDict["New Skirt"] = LLTrans::getString("New Skirt"); + mInventoryItemsDict["New Alpha"] = LLTrans::getString("New Alpha"); + mInventoryItemsDict["New Tattoo"] = LLTrans::getString("New Tattoo"); + mInventoryItemsDict["New Physics"] = LLTrans::getString("New Physics"); + mInventoryItemsDict["Invalid Wearable"] = LLTrans::getString("Invalid Wearable"); + + mInventoryItemsDict["New Gesture"] = LLTrans::getString("New Gesture"); + mInventoryItemsDict["New Script"] = LLTrans::getString("New Script"); + mInventoryItemsDict["New Folder"] = LLTrans::getString("New Folder"); + mInventoryItemsDict["New Note"] = LLTrans::getString("New Note"); + mInventoryItemsDict["Contents"] = LLTrans::getString("Contents"); + + mInventoryItemsDict["Gesture"] = LLTrans::getString("Gesture"); + mInventoryItemsDict["Male Gestures"] = LLTrans::getString("Male Gestures"); + mInventoryItemsDict["Female Gestures"] = LLTrans::getString("Female Gestures"); + mInventoryItemsDict["Other Gestures"] = LLTrans::getString("Other Gestures"); + mInventoryItemsDict["Speech Gestures"] = LLTrans::getString("Speech Gestures"); + mInventoryItemsDict["Common Gestures"] = LLTrans::getString("Common Gestures"); + + //predefined gestures + + //male + mInventoryItemsDict["Male - Excuse me"] = LLTrans::getString("Male - Excuse me"); + mInventoryItemsDict["Male - Get lost"] = LLTrans::getString("Male - Get lost"); // double space after Male. EXT-8319 + mInventoryItemsDict["Male - Blow kiss"] = LLTrans::getString("Male - Blow kiss"); + mInventoryItemsDict["Male - Boo"] = LLTrans::getString("Male - Boo"); + mInventoryItemsDict["Male - Bored"] = LLTrans::getString("Male - Bored"); + mInventoryItemsDict["Male - Hey"] = LLTrans::getString("Male - Hey"); + mInventoryItemsDict["Male - Laugh"] = LLTrans::getString("Male - Laugh"); + mInventoryItemsDict["Male - Repulsed"] = LLTrans::getString("Male - Repulsed"); + mInventoryItemsDict["Male - Shrug"] = LLTrans::getString("Male - Shrug"); + mInventoryItemsDict["Male - Stick tougue out"] = LLTrans::getString("Male - Stick tougue out"); + mInventoryItemsDict["Male - Wow"] = LLTrans::getString("Male - Wow"); + + //female + mInventoryItemsDict["Female - Chuckle"] = LLTrans::getString("Female - Chuckle"); + mInventoryItemsDict["Female - Cry"] = LLTrans::getString("Female - Cry"); + mInventoryItemsDict["Female - Embarrassed"] = LLTrans::getString("Female - Embarrassed"); + mInventoryItemsDict["Female - Excuse me"] = LLTrans::getString("Female - Excuse me"); + mInventoryItemsDict["Female - Get lost"] = LLTrans::getString("Female - Get lost"); // double space after Female. EXT-8319 + mInventoryItemsDict["Female - Blow kiss"] = LLTrans::getString("Female - Blow kiss"); + mInventoryItemsDict["Female - Boo"] = LLTrans::getString("Female - Boo"); + mInventoryItemsDict["Female - Bored"] = LLTrans::getString("Female - Bored"); + mInventoryItemsDict["Female - Hey"] = LLTrans::getString("Female - Hey"); + mInventoryItemsDict["Female - Hey baby"] = LLTrans::getString("Female - Hey baby"); + mInventoryItemsDict["Female - Laugh"] = LLTrans::getString("Female - Laugh"); + mInventoryItemsDict["Female - Looking good"] = LLTrans::getString("Female - Looking good"); + mInventoryItemsDict["Female - Over here"] = LLTrans::getString("Female - Over here"); + mInventoryItemsDict["Female - Please"] = LLTrans::getString("Female - Please"); + mInventoryItemsDict["Female - Repulsed"] = LLTrans::getString("Female - Repulsed"); + mInventoryItemsDict["Female - Shrug"] = LLTrans::getString("Female - Shrug"); + mInventoryItemsDict["Female - Stick tougue out"]= LLTrans::getString("Female - Stick tougue out"); + mInventoryItemsDict["Female - Wow"] = LLTrans::getString("Female - Wow"); + + //common + mInventoryItemsDict["/bow"] = LLTrans::getString("/bow"); + mInventoryItemsDict["/clap"] = LLTrans::getString("/clap"); + mInventoryItemsDict["/count"] = LLTrans::getString("/count"); + mInventoryItemsDict["/extinguish"] = LLTrans::getString("/extinguish"); + mInventoryItemsDict["/kmb"] = LLTrans::getString("/kmb"); + mInventoryItemsDict["/muscle"] = LLTrans::getString("/muscle"); + mInventoryItemsDict["/no"] = LLTrans::getString("/no"); + mInventoryItemsDict["/no!"] = LLTrans::getString("/no!"); + mInventoryItemsDict["/paper"] = LLTrans::getString("/paper"); + mInventoryItemsDict["/pointme"] = LLTrans::getString("/pointme"); + mInventoryItemsDict["/pointyou"] = LLTrans::getString("/pointyou"); + mInventoryItemsDict["/rock"] = LLTrans::getString("/rock"); + mInventoryItemsDict["/scissor"] = LLTrans::getString("/scissor"); + mInventoryItemsDict["/smoke"] = LLTrans::getString("/smoke"); + mInventoryItemsDict["/stretch"] = LLTrans::getString("/stretch"); + mInventoryItemsDict["/whistle"] = LLTrans::getString("/whistle"); + mInventoryItemsDict["/yes"] = LLTrans::getString("/yes"); + mInventoryItemsDict["/yes!"] = LLTrans::getString("/yes!"); + mInventoryItemsDict["afk"] = LLTrans::getString("afk"); + mInventoryItemsDict["dance1"] = LLTrans::getString("dance1"); + mInventoryItemsDict["dance2"] = LLTrans::getString("dance2"); + mInventoryItemsDict["dance3"] = LLTrans::getString("dance3"); + mInventoryItemsDict["dance4"] = LLTrans::getString("dance4"); + mInventoryItemsDict["dance5"] = LLTrans::getString("dance5"); + mInventoryItemsDict["dance6"] = LLTrans::getString("dance6"); + mInventoryItemsDict["dance7"] = LLTrans::getString("dance7"); + mInventoryItemsDict["dance8"] = LLTrans::getString("dance8"); +} ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs @@ -1303,12 +1302,18 @@ void update_inventory_item( if (updates.has("asset_id")) { updates.erase("asset_id"); - updates["hash_id"] = update_item->getTransactionID(); + if (update_item->getTransactionID().notNull()) + { + updates["hash_id"] = update_item->getTransactionID(); + } } if (updates.has("shadow_id")) { updates.erase("shadow_id"); - updates["hash_id"] = update_item->getTransactionID(); + if (update_item->getTransactionID().notNull()) + { + updates["hash_id"] = update_item->getTransactionID(); + } } AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); AISAPI::UpdateItem(item_id, updates, cr); diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 5194679a0c..074d51b8b3 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -30,7 +30,7 @@ #include "llinventory.h" #include "llframetimer.h" #include "llwearable.h" -#include "llui.h" //for LLDestroyClass +#include "llinitdestroyclass.h" //for LLDestroyClass #include <boost/signals2.hpp> // boost::signals2::trackable diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index 80c758a5af..016b435ee8 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -45,10 +45,10 @@ typedef enum e_joystick_driver_state class LLViewerJoystick : public LLSingleton<LLViewerJoystick> { -public: - LLViewerJoystick(); + LLSINGLETON(LLViewerJoystick); virtual ~LLViewerJoystick(); - + +public: void init(bool autoenable); void terminate(); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 2186ed3c52..fd4315a319 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -57,6 +57,7 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed struct LLKeyboardActionRegistry : public LLRegistrySingleton<std::string, boost::function<void (EKeystate keystate)>, LLKeyboardActionRegistry> { + LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry); }; LLViewerKeyboard gViewerKeyboard; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 78c4d98d55..434c8f1d8c 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -167,6 +167,7 @@ static bool sForceUpdate = false; static LLUUID sOnlyAudibleTextureID = LLUUID::null; static F64 sLowestLoadableImplInterest = 0.0f; static bool sAnyMediaShowing = false; +static bool sAnyMediaPlaying = false; static boost::signals2::connection sTeleportFinishConnection; static std::string sUpdatedCookies; static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt"; @@ -606,6 +607,7 @@ void LLViewerMedia::updateMedia(void *dummy_arg) createSpareBrowserMediaSource(); sAnyMediaShowing = false; + sAnyMediaPlaying = false; sUpdatedCookies = getCookieStore()->getChangedCookies(); if(!sUpdatedCookies.empty()) { @@ -808,6 +810,11 @@ void LLViewerMedia::updateMedia(void *dummy_arg) sAnyMediaShowing = true; } + if (!pimpl->getUsedInUI() && pimpl->hasMedia() && pimpl->isMediaPlaying()) + { + sAnyMediaPlaying = true; + } + } } @@ -858,6 +865,13 @@ bool LLViewerMedia::isAnyMediaShowing() ////////////////////////////////////////////////////////////////////////////////////////// // static +bool LLViewerMedia::isAnyMediaPlaying() +{ + return sAnyMediaPlaying; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static void LLViewerMedia::setAllMediaEnabled(bool val) { // Set "tentative" autoplay first. We need to do this here or else @@ -913,6 +927,77 @@ void LLViewerMedia::setAllMediaEnabled(bool val) ////////////////////////////////////////////////////////////////////////////////////////// // static +void LLViewerMedia::setAllMediaPaused(bool val) +{ + // Set "tentative" autoplay first. We need to do this here or else + // re-enabling won't start up the media below. + gSavedSettings.setBOOL("MediaTentativeAutoPlay", !val); + + // Then + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for (; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + if (!pimpl->getUsedInUI()) + { + // upause/pause time based media, enable/disable any other + if (!val) + { + pimpl->setDisabled(val); + if (pimpl->isMediaTimeBased() && pimpl->isMediaPaused()) + { + pimpl->play(); + } + } + else if (pimpl->isMediaTimeBased() && pimpl->mMediaSource && (pimpl->isMediaPlaying() || pimpl->isMediaPaused())) + { + pimpl->pause(); + } + else + { + pimpl->setDisabled(val); + } + } + } + + // Also do Parcel Media and Parcel Audio + if (!val) + { + if (!LLViewerMedia::isParcelMediaPlaying() && LLViewerMedia::hasParcelMedia()) + { + LLViewerParcelMedia::play(LLViewerParcelMgr::getInstance()->getAgentParcel()); + } + + if (gSavedSettings.getBOOL("AudioStreamingMusic") && + !LLViewerMedia::isParcelAudioPlaying() && + gAudiop && + LLViewerMedia::hasParcelAudio()) + { + if (LLAudioEngine::AUDIO_PAUSED == gAudiop->isInternetStreamPlaying()) + { + // 'false' means unpause + gAudiop->pauseInternetStream(false); + } + else + { + LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLViewerMedia::getParcelAudioURL()); + } + } + } + else { + // This actually unloads the impl, as opposed to "stop"ping the media + LLViewerParcelMedia::stop(); + if (gAudiop) + { + LLViewerAudio::getInstance()->stopInternetStreamWithAutoFade(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +// static bool LLViewerMedia::isParcelMediaPlaying() { return (LLViewerMedia::hasParcelMedia() && LLViewerParcelMedia::getParcelMedia() && LLViewerParcelMedia::getParcelMedia()->hasMedia()); @@ -1820,7 +1905,9 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } else if(LLFile::stat(plugin_name, &s)) { +#if !LL_LINUX LL_WARNS_ONCE("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; +#endif } else { @@ -1862,8 +1949,10 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } } - +#if !LL_LINUX LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; +#endif + if(gAgent.isInitialized()) { if (std::find(sMimeTypesFailed.begin(), sMimeTypesFailed.end(), media_type) == sMimeTypesFailed.end()) diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 1fecf15fc9..5c876861c4 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -105,9 +105,12 @@ public: // Is any media currently "showing"? Includes Parcel Media. Does not include media in the UI. static bool isAnyMediaShowing(); + static bool isAnyMediaPlaying(); // Set all media enabled or disabled, depending on val. Does not include media in the UI. static void setAllMediaEnabled(bool val); - + // Set all media paused or playing, depending on val. Does not include media in the UI. + static void setAllMediaPaused(bool val); + static void updateMedia(void* dummy_arg = NULL); static void initClass(); diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index 0b2a64868e..368c671f84 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -41,10 +41,10 @@ class LLViewerMediaFocus : public LLFocusableElement, public LLSingleton<LLViewerMediaFocus> { -public: - LLViewerMediaFocus(); + LLSINGLETON(LLViewerMediaFocus); ~LLViewerMediaFocus(); - + +public: // Set/clear the face that has media focus (takes keyboard input and has the full set of controls) void setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal = LLVector3::zero); void clearFocus(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 72579d4d7a..99b7a98abc 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -62,7 +62,6 @@ #include "llfloaterbuycontents.h" #include "llbuycurrencyhtml.h" #include "llfloatergodtools.h" -#include "llfloaterinventory.h" #include "llfloaterimcontainer.h" #include "llfloaterland.h" #include "llfloaterimnearbychat.h" @@ -80,6 +79,7 @@ #include "lllandmarkactions.h" #include "llgroupmgr.h" #include "lltooltip.h" +#include "lltoolface.h" #include "llhints.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" @@ -89,6 +89,7 @@ #include "llinventoryfunctions.h" #include "llpanellogin.h" #include "llpanelblockedlist.h" +#include "llpanelmaininventory.h" #include "llmarketplacefunctions.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llmoveview.h" @@ -133,6 +134,7 @@ #include "llpathfindingmanager.h" #include "llstartup.h" #include "boost/unordered_map.hpp" +#include "llcleanup.h" using namespace LLAvatarAppearanceDefines; @@ -1211,14 +1213,15 @@ class LLAdvancedToggleWireframe : public view_listener_t bool handleEvent(const LLSD& userdata) { gUseWireframe = !(gUseWireframe); + gWindowResized = TRUE; + + LLPipeline::updateRenderDeferred(); if (gUseWireframe) { gInitialDeferredModeForWireframe = LLPipeline::sRenderDeferred; } - gWindowResized = TRUE; - LLPipeline::updateRenderDeferred(); gPipeline.resetVertexBuffers(); if (!gUseWireframe && !gInitialDeferredModeForWireframe && LLPipeline::sRenderDeferred != gInitialDeferredModeForWireframe && gPipeline.isInit()) @@ -5183,30 +5186,91 @@ class LLToolsEnableSelectNextPart : public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = (gSavedSettings.getBOOL("EditLinkedParts") && - !LLSelectMgr::getInstance()->getSelection()->isEmpty()); + bool new_value = (!LLSelectMgr::getInstance()->getSelection()->isEmpty() + && (gSavedSettings.getBOOL("EditLinkedParts") + || LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool())); return new_value; } }; -// Cycle selection through linked children in selected object. +// Cycle selection through linked children or/and faces in selected object. // FIXME: Order of children list is not always the same as sim's idea of link order. This may confuse // resis. Need link position added to sim messages to address this. -class LLToolsSelectNextPart : public view_listener_t +class LLToolsSelectNextPartFace : public view_listener_t { - bool handleEvent(const LLSD& userdata) - { + bool handleEvent(const LLSD& userdata) + { + bool cycle_faces = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool(); + bool cycle_linked = gSavedSettings.getBOOL("EditLinkedParts"); + + if (!cycle_faces && !cycle_linked) + { + // Nothing to do + return true; + } + + bool fwd = (userdata.asString() == "next"); + bool prev = (userdata.asString() == "previous"); + bool ifwd = (userdata.asString() == "includenext"); + bool iprev = (userdata.asString() == "includeprevious"); + + LLViewerObject* to_select = NULL; + bool restart_face_on_part = !cycle_faces; + S32 new_te = 0; + + if (cycle_faces) + { + // Cycle through faces of current selection, if end is reached, swithc to next part (if present) + LLSelectNode* nodep = LLSelectMgr::getInstance()->getSelection()->getFirstNode(); + if (!nodep) return false; + to_select = nodep->getObject(); + if (!to_select) return false; + + S32 te_count = to_select->getNumTEs(); + S32 selected_te = nodep->getLastOperatedTE(); + + if (fwd || ifwd) + { + if (selected_te < 0) + { + new_te = 0; + } + else if (selected_te + 1 < te_count) + { + // select next face + new_te = selected_te + 1; + } + else + { + // restart from first face on next part + restart_face_on_part = true; + } + } + else if (prev || iprev) + { + if (selected_te > te_count) + { + new_te = te_count - 1; + } + else if (selected_te - 1 >= 0) + { + // select previous face + new_te = selected_te - 1; + } + else + { + // restart from last face on next part + restart_face_on_part = true; + } + } + } + S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - if (gSavedSettings.getBOOL("EditLinkedParts") && object_count) + if (cycle_linked && object_count && restart_face_on_part) { LLViewerObject* selected = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if (selected && selected->getRootEdit()) { - bool fwd = (userdata.asString() == "next"); - bool prev = (userdata.asString() == "previous"); - bool ifwd = (userdata.asString() == "includenext"); - bool iprev = (userdata.asString() == "includeprevious"); - LLViewerObject* to_select = NULL; LLViewerObject::child_list_t children = selected->getRootEdit()->getChildren(); children.push_front(selected->getRootEdit()); // need root in the list too @@ -5248,22 +5312,40 @@ class LLToolsSelectNextPart : public view_listener_t } } } - - if (to_select) - { - if (gFocusMgr.childHasKeyboardFocus(gFloaterTools)) - { - gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes - } - if (fwd || prev) - { - LLSelectMgr::getInstance()->deselectAll(); - } - LLSelectMgr::getInstance()->selectObjectOnly(to_select); - return true; - } } } + + if (to_select) + { + if (gFocusMgr.childHasKeyboardFocus(gFloaterTools)) + { + gFocusMgr.setKeyboardFocus(NULL); // force edit toolbox to commit any changes + } + if (fwd || prev) + { + LLSelectMgr::getInstance()->deselectAll(); + } + if (cycle_faces) + { + if (restart_face_on_part) + { + if (fwd || ifwd) + { + new_te = 0; + } + else + { + new_te = to_select->getNumTEs() - 1; + } + } + LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, FALSE); + } + else + { + LLSelectMgr::getInstance()->selectObjectOnly(to_select); + } + return true; + } return true; } }; @@ -8509,7 +8591,7 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - LLAvatarNameCache::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarNameCache); if (gCacheName) gCacheName->clear(); } @@ -8553,7 +8635,7 @@ class LLToggleUIHints : public view_listener_t void LLUploadCostCalculator::calculateCost() { - S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // getPriceUpload() returns -1 if no data available yet. if(upload_cost >= 0) @@ -8770,7 +8852,7 @@ void initialize_menus() view_listener_t::addMenu(new LLToolsEditLinkedParts(), "Tools.EditLinkedParts"); view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY"); view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid"); - view_listener_t::addMenu(new LLToolsSelectNextPart(), "Tools.SelectNextPart"); + view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart"); commit.add("Tools.Link", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance())); commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance())); view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations"); @@ -9097,7 +9179,7 @@ void initialize_menus() view_listener_t::addMenu(new LLGoToObject(), "GoToObject"); commit.add("PayObject", boost::bind(&handle_give_money_dialog)); - commit.add("Inventory.NewWindow", boost::bind(&LLFloaterInventory::showAgentInventory)); + commit.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow)); enable.add("EnablePayObject", boost::bind(&enable_pay_object)); enable.add("EnablePayAvatar", boost::bind(&enable_pay_avatar)); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index b48b45502b..d46bb0199b 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -84,7 +84,7 @@ class LLFileEnableUpload : public view_listener_t bool handleEvent(const LLSD& userdata) { return true; -// bool new_value = gStatusBar && LLGlobalEconomy::Singleton::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::Singleton::getInstance()->getPriceUpload()); +// bool new_value = gStatusBar && LLGlobalEconomy::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::getInstance()->getPriceUpload()); // return new_value; } }; @@ -93,6 +93,12 @@ class LLFileEnableUploadModel : public view_listener_t { bool handleEvent(const LLSD& userdata) { + LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::findInstance("upload_model"); + if (fmp && fmp->isModelLoading()) + { + return false; + } + return true; } }; @@ -359,7 +365,7 @@ class LLFileUploadModel : public view_listener_t bool handleEvent(const LLSD& userdata) { LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) LLFloaterReg::getInstance("upload_model"); - if (fmp) + if (fmp && !fmp->isModelLoading()) { fmp->loadModel(3); } @@ -423,7 +429,7 @@ class LLFileUploadBulk : public view_listener_t if (picker.getMultipleOpenFiles()) { std::string filename = picker.getFirstFile(); - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); while (!filename.empty()) { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index f472db080f..d81cb804e4 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5467,9 +5467,12 @@ static std::string reason_from_transaction_type(S32 transaction_type, case TRANS_CLASSIFIED_CHARGE: return LLTrans::getString("to publish a classified ad"); + case TRANS_GIFT: + // Simulator returns "Payment" if no custom description has been entered + return (item_desc == "Payment" ? std::string() : item_desc); + // These have no reason to display, but are expected and should not // generate warnings - case TRANS_GIFT: case TRANS_PAY_OBJECT: case TRANS_OBJECT_PAYS: return std::string(); @@ -5579,6 +5582,7 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) LLSD payload; bool you_paid_someone = (source_id == gAgentID); + std::string gift_suffix = (transaction_type == TRANS_GIFT ? "_gift" : ""); if (you_paid_someone) { if(!gSavedSettings.getBOOL("NotifyMoneySpend")) @@ -5592,8 +5596,8 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) { if (dest_id.notNull()) { - message = success ? LLTrans::getString("you_paid_ldollars", args) : - LLTrans::getString("you_paid_failure_ldollars", args); + message = success ? LLTrans::getString("you_paid_ldollars" + gift_suffix, args) : + LLTrans::getString("you_paid_failure_ldollars" + gift_suffix, args); } else { @@ -5620,7 +5624,8 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) payload["dest_id"] = dest_id; notification = success ? "PaymentSent" : "PaymentFailure"; } - else { + else + { // ...someone paid you if(!gSavedSettings.getBOOL("NotifyMoneyReceived")) { @@ -5631,9 +5636,10 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) name_id = source_id; if (!reason.empty()) { - message = LLTrans::getString("paid_you_ldollars", args); + message = LLTrans::getString("paid_you_ldollars" + gift_suffix, args); } - else { + else + { message = LLTrans::getString("paid_you_ldollars_no_reason", args); } final_args["MESSAGE"] = message; @@ -6278,9 +6284,9 @@ void process_frozen_message(LLMessageSystem *msgsystem, void **user_data) // do some extra stuff once we get our economy data void process_economy_data(LLMessageSystem *msg, void** /*user_data*/) { - LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::Singleton::getInstance()); + LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::getInstance()); - S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL; @@ -6385,6 +6391,16 @@ bool unknown_script_question_cb(const LLSD& notification, const LLSD& response) return false; } +void experiencePermissionBlock(LLUUID experience, LLSD result) +{ + LLSD permission; + LLSD data; + permission["permission"] = "Block"; + data[experience.asString()] = permission; + data["experience"] = experience; + LLEventPumps::instance().obtain("experience_permission").post(data); +} + bool script_question_cb(const LLSD& notification, const LLSD& response) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); @@ -6461,14 +6477,8 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) if (!region) return false; - LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), LLExperienceCache::ExperienceGetFn_t()); + LLExperienceCache::instance().setExperiencePermission(experience, std::string("Block"), boost::bind(&experiencePermissionBlock, experience, _1)); - LLSD permission; - LLSD data; - permission["permission"] = "Block"; - data[experience.asString()] = permission; - data["experience"] = experience; - LLEventPumps::instance().obtain("experience_permission").post(data); } } return false; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index d8f5c71f8d..b0eaa37541 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -210,6 +210,7 @@ void set_dad_inbox_object(const LLUUID& object_id); class LLViewerMessage : public LLSingleton<LLViewerMessage> { + LLSINGLETON_EMPTY_CTOR(LLViewerMessage); public: typedef boost::function<void()> teleport_started_callback_t; typedef boost::signals2::signal<void()> teleport_started_signal_t; diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 2525886222..6937d064f9 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -95,13 +95,6 @@ LLGridManager::LLGridManager() } -LLGridManager::LLGridManager(const std::string& grid_file) -{ - // initialize with an explicity grid file for testing. - LL_DEBUGS("GridManager")<<LL_ENDL; - initialize(grid_file); -} - // // LLGridManager - class for managing the list of known grids, and the current // selection diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 228303d8e2..b8ff494b8b 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -58,16 +58,15 @@ protected: **/ class LLGridManager : public LLSingleton<LLGridManager> { + /// Instantiate the grid manager, load default grids, selects the default grid + LLSINGLETON(LLGridManager); + ~LLGridManager(); + public: /* ================================================================ * @name Initialization and Configuration * @{ */ - /// Instantiate the grid manager, load default grids, selects the default grid - LLGridManager(const std::string& grid_file); - LLGridManager(); - ~LLGridManager(); - /// add grids from an external grids file void initialize(const std::string& grid_file); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 4da26404e5..45dbd95bea 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -102,6 +102,7 @@ #include "llmediaentry.h" #include "llfloaterperms.h" #include "llvocache.h" +#include "llcleanup.h" //#define DEBUG_UPDATE_TYPE @@ -530,11 +531,11 @@ void LLViewerObject::initVOClasses() void LLViewerObject::cleanupVOClasses() { - LLVOGrass::cleanupClass(); - LLVOWater::cleanupClass(); - LLVOTree::cleanupClass(); - LLVOAvatar::cleanupClass(); - LLVOVolume::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVOGrass); + SUBSYSTEM_CLEANUP(LLVOWater); + SUBSYSTEM_CLEANUP(LLVOTree); + SUBSYSTEM_CLEANUP(LLVOAvatar); + SUBSYSTEM_CLEANUP(LLVOVolume); sObjectDataMap.clear(); } diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index bb6bbf3308..29219843c9 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -75,6 +75,8 @@ public: class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr> { + LLSINGLETON(LLViewerParcelMgr); + ~LLViewerParcelMgr(); public: typedef boost::function<void (const LLVector3d&, const bool& local)> teleport_finished_callback_t; @@ -82,9 +84,6 @@ public: typedef boost::function<void()> teleport_failed_callback_t; typedef boost::signals2::signal<void()> teleport_failed_signal_t; - LLViewerParcelMgr(); - ~LLViewerParcelMgr(); - static void cleanupGlobals(); BOOL selectionEmpty() const; diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index 40e8e1d45d..ab1cd715ab 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -135,9 +135,8 @@ protected: class LLViewerPartSim : public LLSingleton<LLViewerPartSim> { + LLSINGLETON(LLViewerPartSim); public: - LLViewerPartSim(); - virtual ~LLViewerPartSim(){} void destroyClass(); typedef std::vector<LLViewerPartGroup *> group_list_t; diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 7843652589..97a060d95e 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -246,13 +246,11 @@ extern LLTrace::EventStatHandle<LLUnit<F32, LLUnits::Percent> > OBJECT_CACHE_HIT class LLViewerStats : public LLSingleton<LLViewerStats> { -public: - void resetStats(); + LLSINGLETON(LLViewerStats); + ~LLViewerStats(); public: - - LLViewerStats(); - ~LLViewerStats(); + void resetStats(); void updateFrameStats(const F64Seconds time_diff); diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h index d1744f4910..c974bea49d 100644 --- a/indra/newview/llviewerstatsrecorder.h +++ b/indra/newview/llviewerstatsrecorder.h @@ -44,11 +44,11 @@ class LLViewerObject; class LLViewerStatsRecorder : public LLSingleton<LLViewerStatsRecorder> { - public: - LOG_CLASS(LLViewerStatsRecorder); - LLViewerStatsRecorder(); + LLSINGLETON(LLViewerStatsRecorder); + LOG_CLASS(LLViewerStatsRecorder); ~LLViewerStatsRecorder(); + public: void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size) { #if LL_RECORD_VIEWER_STATS diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 178aa1e646..3cef34445a 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1419,11 +1419,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) destroyRawImage(); return FALSE; } - mNeedsCreateTexture = FALSE; + mNeedsCreateTexture = FALSE; if (mRawImage.isNull()) { LL_ERRS() << "LLViewerTexture trying to create texture with no Raw Image" << LL_ENDL; } + if (mRawImage->isBufferInvalid()) + { + LL_WARNS() << "Can't create a texture: invalid image data" << LL_ENDL; + destroyRawImage(); + return FALSE; + } // LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", // mRawDiscardLevel, // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index ba76770838..070544063a 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -237,6 +237,7 @@ private: class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIImageList> { + LLSINGLETON_EMPTY_CTOR(LLUIImageList); public: // LLImageProviderInterface /*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 9e68bb78e0..61505b7c07 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -208,6 +208,7 @@ #include "llwindowlistener.h" #include "llviewerwindowlistener.h" #include "llpaneltopinfobar.h" +#include "llcleanup.h" #if LL_WINDOWS #include <tchar.h> // For Unicode conversion methods @@ -292,13 +293,8 @@ public: class RecordToChatConsole : public LLSingleton<RecordToChatConsole> { + LLSINGLETON(RecordToChatConsole); public: - RecordToChatConsole() - : LLSingleton<RecordToChatConsole>(), - mRecorder(new RecordToChatConsoleRecorder()) - { - } - void startRecorder() { LLError::addRecorder(mRecorder); } void stopRecorder() { LLError::removeRecorder(mRecorder); } @@ -306,6 +302,11 @@ private: LLError::RecorderPtr mRecorder; }; +RecordToChatConsole::RecordToChatConsole(): + mRecorder(new RecordToChatConsoleRecorder()) +{ +} + //////////////////////////////////////////////////////////////////////////// // // LLDebugText @@ -1598,17 +1599,20 @@ BOOL LLViewerWindow::handleDeviceChange(LLWindow *window) return FALSE; } -void LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) +BOOL LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) { if (ui_scale_factor >= MIN_UI_SCALE && ui_scale_factor <= MAX_UI_SCALE) { + gSavedSettings.setF32("LastSystemUIScaleFactor", ui_scale_factor); gSavedSettings.setF32("UIScaleFactor", ui_scale_factor); LLViewerWindow::reshape(window_width, window_height); mResDirty = true; + return TRUE; } else { LL_WARNS() << "DPI change caused UI scale to go out of bounds: " << ui_scale_factor << LL_ENDL; + return FALSE; } } @@ -2176,10 +2180,7 @@ void LLViewerWindow::shutdownViews() // destroy the nav bar, not currently part of gViewerWindow // *TODO: Make LLNavigationBar part of gViewerWindow - if (LLNavigationBar::instanceExists()) - { - delete LLNavigationBar::getInstance(); - } + LLNavigationBar::deleteSingleton(); LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ; // destroy menus after instantiating navbar above, as it needs @@ -2215,7 +2216,7 @@ void LLViewerWindow::shutdownGL() // Shutdown GL cleanly. Order is very important here. //-------------------------------------------------------- LLFontGL::destroyDefaultFonts(); - LLFontManager::cleanupClass(); + SUBSYSTEM_CLEANUP(LLFontManager); stop_glerror(); gSky.cleanup(); @@ -2238,7 +2239,7 @@ void LLViewerWindow::shutdownGL() LLWorldMapView::cleanupTextures(); LLViewerTextureManager::cleanup() ; - LLImageGL::cleanupClass() ; + SUBSYSTEM_CLEANUP(LLImageGL) ; LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; @@ -2251,7 +2252,7 @@ void LLViewerWindow::shutdownGL() gGL.shutdown(); - LLVertexBuffer::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVertexBuffer); LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ; } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 72b7370621..a134dfaaa9 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -211,7 +211,7 @@ public: /*virtual*/ void handleDataCopy(LLWindow *window, S32 data_type, void *data); /*virtual*/ BOOL handleTimerEvent(LLWindow *window); /*virtual*/ BOOL handleDeviceChange(LLWindow *window); - /*virtual*/ void handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); + /*virtual*/ BOOL handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); /*virtual*/ void handlePauseWatchdog(LLWindow *window); diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 082f5f0b1d..7aabde1b2d 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -223,6 +223,9 @@ private: // class LLVOCache : public LLSingleton<LLVOCache> { + LLSINGLETON(LLVOCache); + ~LLVOCache() ; + private: struct HeaderEntryInfo { @@ -253,13 +256,8 @@ private: }; typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t; typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t; -private: - friend class LLSingleton<LLVOCache>; - LLVOCache() ; public: - ~LLVOCache() ; - void initCache(ELLPath location, U32 size, U32 cache_version) ; void removeCache(ELLPath location, bool started = false) ; diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h index ef15b2c79e..309c3eebdd 100644 --- a/indra/newview/llvoicechannel.h +++ b/indra/newview/llvoicechannel.h @@ -167,8 +167,8 @@ private: class LLVoiceChannelProximal : public LLVoiceChannel, public LLSingleton<LLVoiceChannelProximal> { + LLSINGLETON(LLVoiceChannelProximal); public: - LLVoiceChannelProximal(); /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); /*virtual*/ void handleStatusChange(EStatusType status); diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index b05bcb23b7..32637dcf42 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -299,11 +299,11 @@ public: class LLVoiceClient: public LLSingleton<LLVoiceClient> { + LLSINGLETON(LLVoiceClient); LOG_CLASS(LLVoiceClient); -public: - LLVoiceClient(); ~LLVoiceClient(); +public: typedef boost::signals2::signal<void(void)> micro_changed_signal_t; micro_changed_signal_t mMicroChangedSignal; @@ -485,6 +485,8 @@ protected: **/ class LLSpeakerVolumeStorage : public LLSingleton<LLSpeakerVolumeStorage> { + LLSINGLETON(LLSpeakerVolumeStorage); + ~LLSpeakerVolumeStorage(); LOG_CLASS(LLSpeakerVolumeStorage); public: @@ -513,10 +515,6 @@ public: void removeSpeakerVolume(const LLUUID& speaker_id); private: - friend class LLSingleton<LLSpeakerVolumeStorage>; - LLSpeakerVolumeStorage(); - ~LLSpeakerVolumeStorage(); - const static std::string SETTINGS_FILE_NAME; void load(); diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index f32c7c975f..81e924e438 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -56,12 +56,11 @@ class LLVivoxVoiceClient : public LLSingleton<LLVivoxVoiceClient>, virtual public LLVoiceModuleInterface, virtual public LLVoiceEffectInterface { + LLSINGLETON(LLVivoxVoiceClient); LOG_CLASS(LLVivoxVoiceClient); -public: - LLVivoxVoiceClient(); virtual ~LLVivoxVoiceClient(); - - + +public: /// @name LLVoiceModuleInterface virtual implementations /// @see LLVoiceModuleInterface //@{ @@ -1027,10 +1026,10 @@ protected: class LLVivoxSecurity : public LLSingleton<LLVivoxSecurity> { - public: - LLVivoxSecurity(); - virtual ~LLVivoxSecurity(); + LLSINGLETON(LLVivoxSecurity); + virtual ~LLVivoxSecurity(); + public: std::string connectorHandle() { return mConnectorHandle; }; std::string accountHandle() { return mAccountHandle; }; diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 90bc6509a6..16130b5ca7 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -810,18 +810,18 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable) up *= sc; *(verticesp++) = mStarVertices[vtx]; - *(verticesp++) = mStarVertices[vtx]+left; + *(verticesp++) = mStarVertices[vtx]+up; *(verticesp++) = mStarVertices[vtx]+left+up; - *(verticesp++) = mStarVertices[vtx]+left; + *(verticesp++) = mStarVertices[vtx]; *(verticesp++) = mStarVertices[vtx]+left+up; - *(verticesp++) = mStarVertices[vtx]+up; + *(verticesp++) = mStarVertices[vtx]+left; - *(texcoordsp++) = LLVector2(0,0); - *(texcoordsp++) = LLVector2(0,1); + *(texcoordsp++) = LLVector2(1,0); *(texcoordsp++) = LLVector2(1,1); *(texcoordsp++) = LLVector2(0,1); - *(texcoordsp++) = LLVector2(1,1); *(texcoordsp++) = LLVector2(1,0); + *(texcoordsp++) = LLVector2(0,1); + *(texcoordsp++) = LLVector2(0,0); *(colorsp++) = LLColor4U(mStarColors[vtx]); *(colorsp++) = LLColor4U(mStarColors[vtx]); diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h index fee3ec6f20..9a6624258e 100644 --- a/indra/newview/llwatchdog.h +++ b/indra/newview/llwatchdog.h @@ -75,10 +75,10 @@ private: class LLWatchdogTimerThread; // Defined in the cpp class LLWatchdog : public LLSingleton<LLWatchdog> { -public: - LLWatchdog(); + LLSINGLETON(LLWatchdog); ~LLWatchdog(); +public: // Add an entry to the watchdog. void add(LLWatchdogEntry* e); void remove(LLWatchdogEntry* e); diff --git a/indra/newview/llwaterparammanager.h b/indra/newview/llwaterparammanager.h index dc7d41be2a..3f169e439a 100644 --- a/indra/newview/llwaterparammanager.h +++ b/indra/newview/llwaterparammanager.h @@ -214,6 +214,8 @@ struct WaterExpFloatControl /// WindLight parameter manager class - what controls all the wind light shaders class LLWaterParamManager : public LLSingleton<LLWaterParamManager> { + LLSINGLETON(LLWaterParamManager); + ~LLWaterParamManager(); LOG_CLASS(LLWaterParamManager); public: typedef std::list<std::string> preset_name_list_t; @@ -317,11 +319,7 @@ public: F32 mDensitySliderValue; private: - friend class LLSingleton<LLWaterParamManager>; /*virtual*/ void initSingleton(); - LLWaterParamManager(); - ~LLWaterParamManager(); - void loadAllPresets(); void loadPresetsFromDir(const std::string& dir); bool loadPreset(const std::string& path); diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index f8981d0c51..ee2270c323 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -653,24 +653,16 @@ LLWearableItemsList::~LLWearableItemsList() {} // virtual -void LLWearableItemsList::addNewItem(LLViewerInventoryItem* item, bool rearrange /*= true*/) +LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item) { - if (!item) - { - LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL; - llassert(item != NULL); - } - - LLPanelWearableOutfitItem *list_item = LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); - if (!list_item) - return; + if (!item) + { + LL_WARNS() << "No inventory item. Couldn't create flat list item." << LL_ENDL; + llassert(item != NULL); + return NULL; + } - bool is_item_added = addItem(list_item, item->getUUID(), ADD_BOTTOM, rearrange); - if (!is_item_added) - { - LL_WARNS() << "Couldn't add flat list item." << LL_ENDL; - llassert(is_item_added); - } + return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); } void LLWearableItemsList::updateList(const LLUUID& category_id) diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 18a30f083b..f3182ed163 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -411,8 +411,8 @@ public: */ class ContextMenu : public LLListContextMenu, public LLSingleton<ContextMenu> { + LLSINGLETON(ContextMenu); public: - ContextMenu(); /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); protected: @@ -453,7 +453,7 @@ public: virtual ~LLWearableItemsList(); - /*virtual*/ void addNewItem(LLViewerInventoryItem* item, bool rearrange = true); + /*virtual*/ LLPanel* createNewItem(LLViewerInventoryItem* item); void updateList(const LLUUID& category_id); diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h index d6f0fd09a6..782f7751e5 100644 --- a/indra/newview/llwearablelist.h +++ b/indra/newview/llwearablelist.h @@ -41,9 +41,9 @@ */ class LLWearableList : public LLSingleton<LLWearableList> { -public: - LLWearableList() {} + LLSINGLETON_EMPTY_CTOR(LLWearableList); ~LLWearableList(); +public: void cleanup() ; S32 getLength() const { return mList.size(); } diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h index a3cbf6dc03..90882cf04a 100644 --- a/indra/newview/llwindebug.h +++ b/indra/newview/llwindebug.h @@ -34,6 +34,7 @@ class LLWinDebug: public LLSingleton<LLWinDebug> { + LLSINGLETON_EMPTY_CTOR(LLWinDebug); public: static void init(); static void generateMinidump(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index e13aed98ed..a10102edf7 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -213,6 +213,8 @@ public: /// WindLight parameter manager class - what controls all the wind light shaders class LLWLParamManager : public LLSingleton<LLWLParamManager> { + LLSINGLETON(LLWLParamManager); + ~LLWLParamManager(); LOG_CLASS(LLWLParamManager); public: @@ -375,11 +377,7 @@ private: static std::string getSysDir(); static std::string getUserDir(); - friend class LLSingleton<LLWLParamManager>; /*virtual*/ void initSingleton(); - LLWLParamManager(); - ~LLWLParamManager(); - // list of all the parameters, listed by name std::map<LLWLParamKey, LLWLParamSet> mParamList; diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index b2d8418064..c9ac241d5a 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -61,8 +61,8 @@ class LLVOAvatar; class LLWorld : public LLSingleton<LLWorld> { + LLSINGLETON(LLWorld); public: - LLWorld(); void destroyClass(); LLViewerRegion* addRegion(const U64 ®ion_handle, const LLHost &host); diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h index 1a168e4b4d..5e5caa6a74 100644 --- a/indra/newview/llworldmap.h +++ b/indra/newview/llworldmap.h @@ -193,10 +193,10 @@ const S32 MAP_BLOCK_RES = (MAP_MAX_SIZE / MAP_BLOCK_SIZE); class LLWorldMap : public LLSingleton<LLWorldMap> { -public: - LLWorldMap(); + LLSINGLETON(LLWorldMap); ~LLWorldMap(); +public: // Clear all: list of region info, tiles, blocks and items void reset(); diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h index ac1ea1607c..65276df068 100644 --- a/indra/newview/llworldmapmessage.h +++ b/indra/newview/llworldmapmessage.h @@ -34,13 +34,13 @@ class LLMessageSystem; class LLWorldMapMessage : public LLSingleton<LLWorldMapMessage> { + LLSINGLETON(LLWorldMapMessage); + ~LLWorldMapMessage(); + public: typedef boost::function<void(U64 region_handle, const std::string& url, const LLUUID& snapshot_id, bool teleport)> url_callback_t; - LLWorldMapMessage(); - ~LLWorldMapMessage(); - // Process incoming answers to map stuff requests static void processMapBlockReply(LLMessageSystem*, void**); static void processMapItemReply(LLMessageSystem*, void**); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c6bbfb1c8f..890839e6e6 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -114,6 +114,7 @@ #include "llpathfindingpathtool.h" #include "llscenemonitor.h" #include "llprogressview.h" +#include "llcleanup.h" #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -7385,7 +7386,7 @@ void LLPipeline::doResetVertexBuffers(bool forced) } LLVOPartGroup::destroyGL(); - LLVertexBuffer::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVertexBuffer); //delete all name pool caches LLGLNamePool::cleanupPools(); diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index f2da22256c..760c294f90 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -150,6 +150,7 @@ with the same filename but different name <texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" /> <texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" /> <texture name="Command_Profile_Icon" file_name="toolbar_icons/profile.png" preload="true" /> + <texture name="Command_Report_Abuse_Icon" file_name="toolbar_icons/report_abuse.png" preload="true" /> <texture name="Command_Search_Icon" file_name="toolbar_icons/search.png" preload="true" /> <texture name="Command_Snapshot_Icon" file_name="toolbar_icons/snapshot.png" preload="true" /> <texture name="Command_Speak_Icon" file_name="toolbar_icons/speak.png" preload="true" /> diff --git a/indra/newview/skins/default/textures/toolbar_icons/report_abuse.png b/indra/newview/skins/default/textures/toolbar_icons/report_abuse.png Binary files differnew file mode 100644 index 0000000000..d5cb6ca259 --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/report_abuse.png diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index 8c0b5748de..779b168ae0 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -25,6 +25,7 @@ Grafik kort: [GRAPHICS_CARD] J2C Decoder Version: [J2C_VERSION] Audio Driver Version: [AUDIO_DRIVER_VERSION] LLCEFLib/CEF Version: [LLCEFLIB_VERSION] +LibVLC Version: [LIBVLC_VERSION] Voice Server Version: [VOICE_VERSION] </floater.string> <floater.string name="none"> diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 9dd94d2230..ea3dcf25d7 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -67,6 +67,7 @@ Grafikkarte: [GRAPHICS_CARD] J2C-Decoderversion: [J2C_VERSION] Audiotreiberversion: [AUDIO_DRIVER_VERSION] LLCEFLib/CEF-Version: [LLCEFLIB_VERSION] +LibVLC-Version: [LIBVLC_VERSION] Voice-Server-Version: [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/skins/default/xui/en/floater_avatar.xml b/indra/newview/skins/default/xui/en/floater_avatar.xml index cd5cca02bd..92c5d8bcbe 100644 --- a/indra/newview/skins/default/xui/en/floater_avatar.xml +++ b/indra/newview/skins/default/xui/en/floater_avatar.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="cascading" - ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" can_close="true" diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 521389d7b3..72a7b5540c 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -43,13 +43,11 @@ name="controls" width="226"> <panel - color="Transparent" follows="all" height="102" layout="topleft" left="8" name="preset_views_list" - opaque="true" top="24" width="212" visible="false"> @@ -100,14 +98,11 @@ </panel_camera_item> </panel> <panel - color="Transparent" follows="all" height="68" - item_pad="4" layout="topleft" left="8" name="camera_modes_list" - opaque="true" top="24" width="212" visible="false"> diff --git a/indra/newview/skins/default/xui/en/floater_destinations.xml b/indra/newview/skins/default/xui/en/floater_destinations.xml index 94ebaa9cb2..4fe8e3bdd1 100644 --- a/indra/newview/skins/default/xui/en/floater_destinations.xml +++ b/indra/newview/skins/default/xui/en/floater_destinations.xml @@ -1,11 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="cascading" - ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" can_close="true" - user_resize="true" can_resize="true" min_height="230" min_width="350" diff --git a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml index 8ec6735a01..52084e5f8e 100644 --- a/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml +++ b/indra/newview/skins/default/xui/en/floater_edit_hover_height.xml @@ -1,7 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater positioning="cascading" - ignore_ui_scale="false" legacy_header_height="225" can_minimize="true" can_close="true" diff --git a/indra/newview/skins/default/xui/en/floater_facebook.xml b/indra/newview/skins/default/xui/en/floater_facebook.xml index 2ea34fb751..b34d70516a 100644 --- a/indra/newview/skins/default/xui/en/floater_facebook.xml +++ b/indra/newview/skins/default/xui/en/floater_facebook.xml @@ -22,8 +22,7 @@ top="7" height="437" follows="all" - halign="center" - use_highlighting_on_hover="true"> + halign="center"> <panel filename="panel_facebook_status.xml" class="llfacebookstatuspanel" diff --git a/indra/newview/skins/default/xui/en/floater_flickr.xml b/indra/newview/skins/default/xui/en/floater_flickr.xml index 24de3ddd8d..52ef16c7e8 100644 --- a/indra/newview/skins/default/xui/en/floater_flickr.xml +++ b/indra/newview/skins/default/xui/en/floater_flickr.xml @@ -29,8 +29,7 @@ top="7" height="555" follows="all" - halign="center" - use_highlighting_on_hover="true"> + halign="center"> <panel filename="panel_flickr_photo.xml" class="llflickrphotopanel" diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index 28c89868bd..34fa0b0fe9 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -121,7 +121,6 @@ follows="all" layout="topleft" name="conversations_list_panel" - opaque="true" top_pad="0" left="5" right="-1"/> @@ -144,7 +143,6 @@ follows="all" layout="topleft" name="stub_panel" - opaque="true" top_pad="0" left="0" right="-1"> diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml index 5e84283ab0..90166232e9 100644 --- a/indra/newview/skins/default/xui/en/floater_moveview.xml +++ b/indra/newview/skins/default/xui/en/floater_moveview.xml @@ -155,7 +155,6 @@ layout="topleft" name="move right btn" quadrant="right" - right_delta="4" scale_image="false" tool_tip="Walk right (press Shift + Right Arrow or D)" top_pad="10" @@ -210,7 +209,6 @@ image_pressed_selected="Movement_Down_On" image_unselected="Movement_Down_Off" layout="topleft" - right_delta="0" name="move down btn" scale_image="false" tool_tip="Fly down (press C)" diff --git a/indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml b/indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml new file mode 100644 index 0000000000..bfc1c39e9d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_outfit_photo_preview.xml @@ -0,0 +1,65 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="false" + height="325" + layout="topleft" + name="outfit_photo_preview" + help_topic="preview_texture" + width="410"> + <floater.string + name="Title"> + Texture: [NAME] + </floater.string> + <floater.string + name="exceed_limits"> + Max outfit photo size is [MAX_WIDTH]*[MAX_HEIGHT]. Please select another texture. + </floater.string> + <floater.string + name="photo_confirmation"> + Set this as Outfit Photo for [OUTFIT]? + </floater.string> + <text + type="string" + halign="right" + length="1" + follows="right|bottom" + height="16" + layout="topleft" + left="110" + name="dimensions" + top="255" + width="200"> + [WIDTH]px x [HEIGHT]px + </text> + <text + type="string" + follows="left|top" + height="16" + layout="topleft" + name="notification" + left="25" + halign="center" + top_pad="5" + width="360"> + </text> + <button + follows="right|bottom" + height="22" + label="OK" + layout="topleft" + name="ok_btn" + top_pad="5" + right="-115" + top_delta="0" + width="90" /> + <button + follows="right|bottom" + height="22" + label="Cancel" + layout="topleft" + name="cancel_btn" + right="-20" + top_delta="0" + width="90" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml index 9d91f801a6..3e3f8b49ce 100644 --- a/indra/newview/skins/default/xui/en/floater_pay.xml +++ b/indra/newview/skins/default/xui/en/floater_pay.xml @@ -2,7 +2,7 @@ <floater legacy_header_height="18" can_minimize="false" - height="186" + height="208" layout="topleft" name="Give Money" help_topic="give_money" @@ -43,6 +43,26 @@ width="180"> Test Name That Is Extremely Long To Check Clipping </text> + <text + type="string" + follows="top|left" + height="18" + left="10" + name="payment_message_label" + top_pad="6" + width="120"> + Description (optional): + </text> + <line_editor + border_style="line" + follows="left|top|right" + height="19" + top_delta="-2" + layout="topleft" + max_length_bytes="127" + name="payment_message" + right="-11" + width="109" /> <panel border_thickness="0" height="104" @@ -125,7 +145,7 @@ top_pad="0" max_length_bytes="9" name="amount" - width="90" /> + right="-1" /> <button enabled="false" height="23" diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml index 6021ba0a5a..53618b684b 100644 --- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml +++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml @@ -85,8 +85,7 @@ layout="topleft" left_delta="-12" name="unknown" - top_pad="4" - width=""> + top_pad="4"> Size: [DIMENSIONS] </text> @@ -219,7 +218,6 @@ height="260" follows="left|top|right|bottom" column_padding="0" - can_resize="false" draw_heading="true" multi_select="true" search_column="1" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 3c28233875..91e4c1b603 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1104,7 +1104,6 @@ even though the user gets a free copy. name="Edit Cost" label="L$" label_width="15" - label_text.valign="center" valign="center" width="85" min_val="0" diff --git a/indra/newview/skins/default/xui/en/floater_twitter.xml b/indra/newview/skins/default/xui/en/floater_twitter.xml index 3e1a91e58d..5e8dfb8a52 100644 --- a/indra/newview/skins/default/xui/en/floater_twitter.xml +++ b/indra/newview/skins/default/xui/en/floater_twitter.xml @@ -20,8 +20,7 @@ tab_position="top" top="7" height="457" - halign="center" - use_highlighting_on_hover="true"> + halign="center"> <panel filename="panel_twitter_photo.xml" class="lltwitterphotopanel" diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml index 06d0b849a3..61cc9dfe77 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -95,6 +95,9 @@ <on_click function="Inventory.GearDefault.Custom.Action" parameter="empty_lostnfound" /> + <on_enable + function="Inventory.GearDefault.Enable" + parameter="empty_lostnfound" /> </menu_item_call> <menu_item_separator layout="topleft" /> @@ -152,5 +155,8 @@ <on_click function="Inventory.GearDefault.Custom.Action" parameter="empty_trash" /> + <on_enable + function="Inventory.GearDefault.Enable" + parameter="empty_trash" /> </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b34705777c..f911c2da7b 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -885,12 +885,12 @@ </menu_item_check> <menu create_jump_keys="true" - label="Select Linked Parts" - name="Select Linked Parts" + label="Select Elements" + name="Select Elements" tear_off="true"> <menu_item_call - label="Select Next Part" - name="Select Next Part" + label="Select Next Part or Face" + name="Select Next Part or Face" shortcut="control|."> <menu_item_call.on_click function="Tools.SelectNextPart" @@ -899,8 +899,8 @@ function="Tools.EnableSelectNextPart" /> </menu_item_call> <menu_item_call - label="Select Previous Part" - name="Select Previous Part" + label="Select Previous Part or Face" + name="Select Previous Part or Face" shortcut="control|,"> <menu_item_call.on_click function="Tools.SelectNextPart" @@ -909,8 +909,8 @@ function="Tools.EnableSelectNextPart" /> </menu_item_call> <menu_item_call - label="Include Next Part" - name="Include Next Part" + label="Include Next Part or Face" + name="Include Next Part or Face" shortcut="control|shift|."> <menu_item_call.on_click function="Tools.SelectNextPart" @@ -919,8 +919,8 @@ function="Tools.EnableSelectNextPart" /> </menu_item_call> <menu_item_call - label="Include Previous Part" - name="Include Previous Part" + label="Include Previous Part or Face" + name="Include Previous Part or Face" shortcut="control|shift|,"> <menu_item_call.on_click function="Tools.SelectNextPart" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 11e019e153..512deed054 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1498,7 +1498,20 @@ Delete Notecard? notext="Cancel" yestext="OK"/> </notification> - + + <notification + icon="alertmodal.tga" + name="LoadPreviousReportScreenshot" + type="alertmodal"> + <unique/> +Do you want to use previous screenshot for your report? + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="OK"/> + </notification> + <notification icon="alertmodal.tga" name="GestureSaveFailedTooManySteps" @@ -1880,7 +1893,16 @@ Go to [_URL] for information on purchasing L$? notext="Cancel" yestext="OK"/> </notification> - + + <notification + icon="alertmodal.tga" + name="MuteLimitReached" + persist="false" + type="notify"> +Unable to add new entry to block list because you reached the limit of [MUTE_LIMIT] entries. + <tag>fail</tag> + </notification> + <notification icon="alertmodal.tga" name="UnableToLinkObjects" @@ -6149,6 +6171,7 @@ Link to this from a web page to give others easy access to this location, or try icon="alertmodal.tga" name="WLSavePresetAlert" type="alertmodal"> + <unique/> Do you wish to overwrite the saved preset? <tag>confirm</tag> <usetemplate diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index ded814bbeb..3a34bcbe21 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -15,7 +15,6 @@ <layout_stack follows="left|right|top" height="172" - min_height="172" left="0" name="ui_stack" orientation="horizontal" @@ -50,7 +49,7 @@ label="Username" combo_editor.font="SansSerifLarge" max_chars="128" - commit_on_focus_lost="false" + combo_editor.commit_on_focus_lost="false" combo_editor.prevalidate_callback="ascii" tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine" name="username_combo" @@ -107,7 +106,7 @@ follows="left|top" image_unselected="PushButton_Login" image_pressed="PushButton_Login_Pressed" - image_hover="PushButton_Login_Over" + image_hover_unselected="PushButton_Login_Over" label="Log In" label_color="White" font="SansSerifMedium" diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index 756b8f8102..4d9316768b 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel background_opaque="false" - border_visible="false" + border_visible="false" background_visible="true" bg_alpha_color="PanelNotificationBackground" bg_opaque_color="PanelNotificationBackground" @@ -11,16 +11,16 @@ name="notification_panel" chrome="true" top="0" - height="140" + height="140" translate="false" width="305"> <!-- THIS PANEL CONTROLS TOAST HEIGHT? --> <panel - border_visible="false" - bevel_style="none" + border_visible="false" + bevel_style="none" background_visible="true" - bg_alpha_color="ToastBackground" - bg_opaque_color="ToastBackground" + bg_alpha_color="ToastBackground" + bg_opaque_color="ToastBackground" follows="left|right|top" height="100" label="info_panel" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml index c1272c6bf8..e3790ae09b 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml @@ -34,12 +34,9 @@ Searching... </text> <scroll_container - border="true" - bevel_style="none" follows="all" height="400" width="312" - min_width="312" layout="topleft" left="4" top="0" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 0deb1d03cf..0cd56af6d7 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -157,7 +157,6 @@ enabled_control="ShowScriptErrors" control_name="ShowScriptErrorsLocation" follows="top|left" - draw_border="false" height="16" layout="topleft" left_delta="50" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index c20f9b2c51..71e4009571 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -140,7 +140,6 @@ <radio_group control_name="PreferredBrowserBehavior" - draw_border="false" follows="left|top" height="60" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 53b74fa645..8f2e81b9f7 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -394,7 +394,6 @@ <radio_group enabled_control="EnableVoiceChat" control_name="VoiceEarLocation" - draw_border="false" follows="left|top" layout="topleft" left_delta="-168" diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 489d286e67..898e92e030 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -51,7 +51,7 @@ left_delta="50" name="version_channel_text" top_delta="0" - width="200"> + width="225"> unknown </text> <text @@ -73,7 +73,7 @@ left_delta="50" name="region_type" top_delta="0" - width="200"> + width="225"> unknown </text> <check_box diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml index 975b08be05..8e92552921 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml @@ -61,8 +61,7 @@ right="-2" height="319" follows="all" - halign="center" - use_highlighting_on_hover="true"> + halign="center"> <panel follows="all" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index d3e24a19ef..9995523e61 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -59,7 +59,6 @@ name="inbox_layout_panel" visible="false" min_dim="35" - max_dim="235" expanded_min_dim="90" height="235"> <panel diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 00d541015b..88ad8bbf7b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -45,9 +45,20 @@ Graphics Card Vendor: [GRAPHICS_CARD_VENDOR] Graphics Card: [GRAPHICS_CARD] </string> <string name="AboutDriver">Windows Graphics Driver Version: [GRAPHICS_DRIVER_VERSION]</string> + <string name="AboutOGL">OpenGL Version: [OPENGL_VERSION]</string> + <string name="AboutSettings"> +Window size: [WINDOW_WIDTH]x[WINDOW_HEIGHT] +Font Size Adjustment: [FONT_SIZE_ADJUSTMENT]pt +UI Scaling: [UI_SCALE] +Draw distance: [DRAW_DISTANCE]m +Bandwidth: [NET_BANDWITH]kbit/s +LOD factor: [LOD_FACTOR] +Render quality: [RENDER_QUALITY] / 7 +Advanced Lighting Model: [GPU_SHADERS] +Texture memory: [TEXTURE_MEMORY]MB +VFS (cache) creation time: [VFS_TIME] + </string> <string name="AboutLibs"> -OpenGL Version: [OPENGL_VERSION] - J2C Decoder Version: [J2C_VERSION] Audio Driver Version: [AUDIO_DRIVER_VERSION] LLCEFLib/CEF Version: [LLCEFLIB_VERSION] @@ -3729,12 +3740,15 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <!-- Financial operations strings --> <string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT] [REASON].</string> + <string name="paid_you_ldollars_gift">[NAME] paid you L$[AMOUNT]: [REASON]</string> <string name="paid_you_ldollars_no_reason">[NAME] paid you L$[AMOUNT].</string> <string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string> + <string name="you_paid_ldollars_gift">You paid [NAME] L$[AMOUNT]: [REASON]</string> <string name="you_paid_ldollars_no_info">You paid L$[AMOUNT].</string> <string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string> <string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string> <string name="you_paid_failure_ldollars">You failed to pay [NAME] L$[AMOUNT] [REASON].</string> + <string name="you_paid_failure_ldollars_gift">You failed to pay [NAME] L$[AMOUNT]: [REASON]</string> <string name="you_paid_failure_ldollars_no_info">You failed to pay L$[AMOUNT].</string> <string name="you_paid_failure_ldollars_no_reason">You failed to pay [NAME] L$[AMOUNT].</string> <string name="you_paid_failure_ldollars_no_name">You failed to pay L$[AMOUNT] [REASON].</string> @@ -4069,6 +4083,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Places_Label">Places</string> <string name="Command_Preferences_Label">Preferences</string> <string name="Command_Profile_Label">Profile</string> + <string name="Command_Report_Abuse_Label">Report Abuse</string> <string name="Command_Search_Label">Search</string> <string name="Command_Snapshot_Label">Snapshot</string> <string name="Command_Speak_Label">Speak</string> @@ -4100,6 +4115,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Places_Tooltip">Places you've saved</string> <string name="Command_Preferences_Tooltip">Preferences</string> <string name="Command_Profile_Tooltip">Edit or view your profile</string> + <string name="Command_Report_Abuse_Tooltip">Report Abuse</string> <string name="Command_Search_Tooltip">Find places, events, people</string> <string name="Command_Snapshot_Tooltip">Take a picture</string> <string name="Command_Speak_Tooltip">Speak with people nearby using your microphone</string> diff --git a/indra/newview/skins/default/xui/en/widgets/slider.xml b/indra/newview/skins/default/xui/en/widgets/slider.xml index f735d09476..6cceafc9ae 100644 --- a/indra/newview/skins/default/xui/en/widgets/slider.xml +++ b/indra/newview/skins/default/xui/en/widgets/slider.xml @@ -8,7 +8,6 @@ text_color="LabelTextColor" text_disabled_color="LabelDisabledColor"> <slider.value_editor name="slider editor" - max_length="10" follows="left|bottom"/> <slider.value_text name="slider text" follows="left|bottom"/> diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml index ba2fdf4f1f..1511116ba6 100644 --- a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml +++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml @@ -5,8 +5,7 @@ follows="left|top" > <multiselect_text font="SansSerifSmall"/> - <caption_text text="Multiple" - halign="center" + <caption_text halign="center" font="SansSerifSmall" v_pad="2"/> <border bevel_style="in"/> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 4e20793d86..d33a3fd07c 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -58,7 +58,8 @@ Tarjeta gráfica: [GRAPHICS_CARD] Versión de J2C Decoder: [J2C_VERSION] Versión de Audio Driver: [AUDIO_DRIVER_VERSION] Versión de LLCEFLib/CEF: [LLCEFLIB_VERSION] -Versión de Voice Server: [VOICE_VERSION] +Versión de LibVLC: [LIBVLC_VERSION] +Versión del servidor de voz: [VOICE_VERSION] </string> <string name="AboutTraffic"> Paquetes perdidos: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 843467df96..315fd82d41 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -67,6 +67,7 @@ Carte graphique : [GRAPHICS_CARD] Version J2C Decoder : [J2C_VERSION] Version Audio Driver : [AUDIO_DRIVER_VERSION] Version LLCEFLib/CEF : [LLCEFLIB_VERSION] +Version LibVLC : [LIBVLC_VERSION] Version serveur vocal : [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index bb2f221db9..279ab99ae3 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -64,6 +64,7 @@ Scheda grafica: [GRAPHICS_CARD] Versione J2C Decoder: [J2C_VERSION] Versione Driver audio: [AUDIO_DRIVER_VERSION] Versione LLCEFLib/CEF: [LLCEFLIB_VERSION] +Versione LibVLC: [LIBVLC_VERSION] Versione server voce: [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 904ce3880a..2fbe19cd66 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -67,7 +67,8 @@ OS バージョン:[OS_VERSION] J2C デコーダバージョン:[J2C_VERSION] オーディオドライババージョン:[AUDIO_DRIVER_VERSION] LLCEFLib/CEF バージョン: [LLCEFLIB_VERSION] -ボイスサーバーバージョン:[VOICE_VERSION] +LibVLC バージョン: [LIBVLC_VERSION] +ボイスサーバーバージョン: [VOICE_VERSION] </string> <string name="AboutTraffic"> パケットロス:[PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index dd85f1eb9b..e9dd18043d 100644 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -44,6 +44,7 @@ Wersja OpenGL: [OPENGL_VERSION] Wersja dekodera J2C: [J2C_VERSION] Wersja sterownika dźwięku (Audio Driver): [AUDIO_DRIVER_VERSION] Wersja LLCEFLib/CEF: [LLCEFLIB_VERSION] +Wersja LibVLC: [LIBVLC_VERSION] Wersja serwera głosu (Voice Server): [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index b3cb50a01e..72a48485a3 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -58,6 +58,7 @@ Placa gráfica: [GRAPHICS_CARD] Versão do J2C Decoder: [J2C_VERSION] Versão do driver de áudio: [AUDIO_DRIVER_VERSION] Versão de LLCEFLib/CEF: [LLCEFLIB_VERSION] +Versão de LibVLC: [LIBVLC_VERSION] Versão do servidor de voz: [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index da03af055c..138afe9ac9 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -67,6 +67,7 @@ SLURL: <nolink>[SLURL]</nolink> Версия декодера J2C: [J2C_VERSION] Версия драйвера звука: [AUDIO_DRIVER_VERSION] Версия LLCEFLib/CEF: [LLCEFLIB_VERSION] +Версия LibVLC: [LIBVLC_VERSION] Версия голосового сервера: [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index 6aad65da22..cc1856bb7d 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -67,7 +67,8 @@ Grafik Kartı: [GRAPHICS_CARD] J2C Kod Çözücü Sürümü: [J2C_VERSION] Ses Sürücüsü Sürümü: [AUDIO_DRIVER_VERSION] LLCEFLib/CEF Sürümü: [LLCEFLIB_VERSION] -Ses Sunucu Sürümü: [VOICE_VERSION] +LibVLC Sürümü: [LIBVLC_VERSION] +Ses Sunucusu Sürümü: [VOICE_VERSION] </string> <string name="AboutTraffic"> Kaybolan Paketler: [PACKETS_LOST,number,0]/[PACKETS_IN,number,0] ([PACKETS_PCT,number,1]%) diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index 5ce5adf3f0..bac15c12d0 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -67,6 +67,7 @@ J2C 解碼器版本: [J2C_VERSION] 音效驅動程式版本: [AUDIO_DRIVER_VERSION] LLCEFLib/CEF版本:[LLCEFLIB_VERSION] +LibVLC版本: [LIBVLC_VERSION] 語音伺服器版本: [VOICE_VERSION] </string> <string name="AboutTraffic"> diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index ea5014a59c..4f7f87b6b0 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -34,6 +34,7 @@ #include "../llagent.h" #include "message.h" #include "llurlentry.h" +#include "llpounceable.h" namespace { const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); @@ -62,7 +63,7 @@ void LLMessageSystem::addUUID(char const *,LLUUID const &) { } void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { } void LLMessageSystem::nextBlockFast(char const *) { } void LLMessageSystem::newMessage(char const *) { } -LLMessageSystem * gMessageSystem; +LLPounceable<LLMessageSystem*, LLPounceableStatic> gMessageSystem; char const* const _PREHASH_AgentID = 0; // never dereferenced during this test char const* const _PREHASH_AgentData = 0; // never dereferenced during this test LLAgent gAgent; diff --git a/indra/newview/tests/test_llxmlrpc_peer.py b/indra/newview/tests/test_llxmlrpc_peer.py index 281b72a058..cff40aa4c2 100755 --- a/indra/newview/tests/test_llxmlrpc_peer.py +++ b/indra/newview/tests/test_llxmlrpc_peer.py @@ -31,15 +31,23 @@ $/LicenseInfo$ import os import sys -from threading import Thread from SimpleXMLRPCServer import SimpleXMLRPCServer mydir = os.path.dirname(__file__) # expected to be .../indra/newview/tests/ -sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "lib", "python")) -sys.path.insert(1, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) +sys.path.insert(0, os.path.join(mydir, os.pardir, os.pardir, "llmessage", "tests")) from testrunner import freeport, run, debug class TestServer(SimpleXMLRPCServer): + # This server_bind() override is borrowed and simplified from + # BaseHTTPServer.HTTPServer.server_bind(): we want to capture the actual + # server port. BaseHTTPServer.HTTPServer.server_bind() stores the actual + # port in a server_port attribute, but SimpleXMLRPCServer isn't derived + # from HTTPServer. So do it ourselves. + def server_bind(self): + """Override server_bind to store the server port.""" + SimpleXMLRPCServer.server_bind(self) + self.server_port = self.socket.getsockname()[1] + def _dispatch(self, method, params): try: func = getattr(self, method) @@ -67,15 +75,21 @@ class TestServer(SimpleXMLRPCServer): pass if __name__ == "__main__": - # Instantiate a TestServer on the first free port in the specified port - # range. Doing this inline is better than in a daemon thread: if it blows - # up here, we'll get a traceback. If it blew up in some other thread, the - # traceback would get eaten and we'd run the subject test program anyway. - xmlrpcd, port = freeport(xrange(8000, 8020), - lambda port: TestServer(('127.0.0.1', port))) + # function to make a server with specified port + make_server = lambda port: TestServer(('127.0.0.1', port)) + + if not sys.platform.startswith("win"): + # Instantiate a TestServer on a port chosen by the runtime. + xmlrpcd = make_server(0) + else: + # "Then there's Windows" + # Instantiate a TestServer on the first free port in the specified + # port range. + xmlrpcd, port = freeport(xrange(8000, 8020), make_server) + # Pass the selected port number to the subject test program via the # environment. We don't want to impose requirements on the test program's # command-line parsing -- and anyway, for C++ integration tests, that's # performed in TUT code rather than our own. - os.environ["PORT"] = str(port) - sys.exit(run(server=Thread(name="xmlrpc", target=xmlrpcd.serve_forever), *sys.argv[1:])) + os.environ["PORT"] = str(xmlrpcd.server_port) + sys.exit(run(server_inst=xmlrpcd, *sys.argv[1:])) diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index 8718360f0c..76063e6db1 100644 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -103,7 +103,7 @@ namespace tut ~LLMessageSystemTestData() { // not end_messaging_system() - delete gMessageSystem; + delete static_cast<LLMessageSystem*>(gMessageSystem); gMessageSystem = NULL; // rm contents of temp dir |