diff --git a/etc/message.xml b/etc/message.xml index 330ecee48..42bbef035 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -50,7 +50,7 @@ OpenCircuit flavor - template + llsd trusted-sender false @@ -370,6 +370,14 @@ + DisplayNameUpdate + + flavor + llsd + trusted-sender + true + + ParcelVoiceInfo flavor @@ -419,6 +427,22 @@ true + SetDisplayNameReply + + flavor + llsd + trusted-sender + true + + + SimConsoleResponse + + flavor + llsd + trusted-sender + true + + DirLandReply flavor @@ -515,8 +539,24 @@ trusted-sender true - - + + NavMeshStatusUpdate + + flavor + llsd + trusted-sender + true + + + AgentStateUpdate + + flavor + llsd + trusted-sender + true + + + ScriptRunningReply flavor @@ -569,26 +609,9 @@ flavor llsd - trusted-sender - true - - - - DisplayNameUpdate - - flavor - llsd - trusted-sender - true - - - SetDisplayNameReply - - flavor - llsd - trusted-sender - true - + trusted-sender + true + capBans diff --git a/indra/llaudio/llstreamingaudio_fmodex.cpp b/indra/llaudio/llstreamingaudio_fmodex.cpp index 33fd30fee..d4e52d340 100644 --- a/indra/llaudio/llstreamingaudio_fmodex.cpp +++ b/indra/llaudio/llstreamingaudio_fmodex.cpp @@ -395,12 +395,12 @@ LLAudioStreamManagerFMODEX::LLAudioStreamManagerFMODEX(FMOD::System *system, con { mInternetStreamURL = url; - FMOD_CREATESOUNDEXINFO exinfo; + /*FMOD_CREATESOUNDEXINFO exinfo; memset(&exinfo,0,sizeof(exinfo)); exinfo.cbsize = sizeof(exinfo); - exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_MPEG; //Hint to speed up loading. + exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS; //Hint to speed up loading.*/ - FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, &exinfo, &mInternetStream); + FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); if (result!= FMOD_OK) { diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 6a2e74c4c..6818be493 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -193,19 +193,14 @@ void LLCharacter::requestStopMotion( LLMotion* motion) //----------------------------------------------------------------------------- // updateMotions() //----------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation"); -static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim"); - void LLCharacter::updateMotions(e_update_t update_type) { if (update_type == HIDDEN_UPDATE) { - LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION); mMotionController.updateMotionsMinimal(); } else { - LLFastTimer t(FTM_UPDATE_ANIMATION); // unpause if the number of outstanding pause requests has dropped to the initial one if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1) { diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index ab2f87275..d040a1a22 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -837,6 +837,7 @@ void LLMotionController::updateMotions(bool force_update) } updateLoadingMotions(); + return; } diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 88c64bde1..e0c24fc97 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -148,7 +148,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type) } // static -LLAssetType::EType LLAssetType::lookup( const char* name ) +LLAssetType::EType LLAssetType::lookup(const char* name) { return lookup(ll_safe_string(name)); } @@ -186,7 +186,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type) } // static -LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name ) +LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name) { return lookupHumanReadable(ll_safe_string(name)); } @@ -208,12 +208,9 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_ return AT_NONE; } -//NOTE: LLAssetType::lookupDragAndDropType & LLAssetType::generateDescriptionFor moved to newview/llviewerassettype.h - // static bool LLAssetType::lookupCanLink(EType asset_type) { - //Check that enabling all these other types as linkable doesn't break things. const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); const AssetEntry *entry = dict->lookup(asset_type); if (entry) @@ -221,9 +218,6 @@ bool LLAssetType::lookupCanLink(EType asset_type) return entry->mCanLink; } return false; - - /*return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY || - asset_type == AT_BODYPART || asset_type == AT_GESTURE);*/ } // static @@ -268,4 +262,3 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) } return false; } - diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 542b4ab15..993f16d04 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -35,7 +35,7 @@ #include #include "llerror.h" -#include "lltypeinfolookup.h" +#include "llstl.h" namespace LLInitParam { @@ -212,14 +212,6 @@ namespace LLInitParam public: - struct CompareTypeID - { - bool operator()(const std::type_info* lhs, const std::type_info* rhs) const - { - return lhs->before(*rhs); - } - }; - typedef std::vector > name_stack_t; typedef std::pair name_stack_range_t; typedef std::vector possible_values_t; @@ -228,9 +220,9 @@ namespace LLInitParam typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&); typedef boost::function parser_inspect_func_t; - typedef LLTypeInfoLookup parser_read_func_map_t; - typedef LLTypeInfoLookup parser_write_func_map_t; - typedef LLTypeInfoLookup parser_inspect_func_map_t; + typedef std::map parser_read_func_map_t; + typedef std::map parser_write_func_map_t; + typedef std::map parser_inspect_func_map_t; Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) : mParseSilently(false), diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h index 4ac689163..7544ab1d1 100644 --- a/indra/llcommon/llkeythrottle.h +++ b/indra/llcommon/llkeythrottle.h @@ -174,6 +174,7 @@ public: F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent); return averageCount; } + // call each time the key wants use State noteAction(const T& id, S32 weight = 1) { diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index dee0d50e1..9532410b7 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -376,24 +376,24 @@ private: // uses the MSVC compiler intrinsics __cpuid() and __rdtsc(). // Delays for the specified amount of milliseconds -static void _Delay(unsigned int ms) +static void _Delay(unsigned int ms) { - LARGE_INTEGER freq, c1, c2; - __int64 x; + LARGE_INTEGER freq, c1, c2; + __int64 x; - // Get High-Res Timer frequency + // Get High-Res Timer frequency if (!QueryPerformanceFrequency(&freq)) return; - + // Convert ms to High-Res Timer value x = freq.QuadPart/1000*ms; - // Get first snapshot of High-Res Timer value + // Get first snapshot of High-Res Timer value QueryPerformanceCounter(&c1); do { - // Get second snapshot - QueryPerformanceCounter(&c2); + // Get second snapshot + QueryPerformanceCounter(&c2); }while(c2.QuadPart-c1.QuadPart < x); // Loop while (second-first < x) } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 00cd5a555..fc2c8dacf 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -52,5 +52,4 @@ private: LLProcessorInfoImpl* mImpl; }; - -#endif +#endif // LLPROCESSOR_H diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index dce07410b..61dc62388 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -60,6 +60,9 @@ static const char LEGACY_NON_HEADER[] = ""; const std::string LLSD_BINARY_HEADER("LLSD/Binary"); const std::string LLSD_XML_HEADER("LLSD/XML"); +//used to deflate a gzipped asset (currently used for navmeshes) +#define windowBits 15 +#define ENABLE_ZLIB_GZIP 32 /** * LLSDSerialize */ @@ -2172,3 +2175,80 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size) free(result); return true; } +//This unzip function will only work with a gzip header and trailer - while the contents +//of the actual compressed data is the same for either format (gzip vs zlib ), the headers +//and trailers are different for the formats. +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 0x4000; + + U8 *in = new U8[size]; + is.read((char*) in, size); + + U8 out[CHUNK]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = size; + strm.next_in = in; + + + S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR) + { + inflateEnd(&strm); + free(result); + delete [] in; + valid = false; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + valid = false; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + valid = false; + return NULL; + } + + //result now points to the decompressed LLSD block + { + outsize= cur_size; + valid = true; + } + + return result; +} + diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 9a45f56a7..09150615c 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -755,6 +755,9 @@ public: LLPointer p = new LLSDXMLParser; return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED); } + // Line oriented parser, 30% faster than fromXML(), but can + // only be used when you know you have the complete XML + // document available in the stream. static S32 fromXMLDocument(LLSD& sd, std::istream& str) { LLPointer p = new LLSDXMLParser(); @@ -791,4 +794,5 @@ public: //dirty little zip functions -- yell at davep LL_COMMON_API std::string zip_llsd(LLSD& data); LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size); +LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size); #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 18842f276..105b69d34 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -39,7 +39,7 @@ #include #include #include -#include "stdtypes.h" // llcommon/stdtypes.h, needed for S32 and U32. +#include // Use to compare the first element only of a pair // e.g. typedef std::set, compare_pair > some_pair_set_t; @@ -477,4 +477,54 @@ llbind2nd(const _Operation& __oper, const _Tp& __x) return llbinder2nd<_Operation>(__oper, _Arg2_type(__x)); } +/** + * Compare std::type_info* pointers a la std::less. We break this out as a + * separate function for use in two different std::less specializations. + */ +inline +bool before(const std::type_info* lhs, const std::type_info* rhs) +{ +#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) + // If we're building on Linux with gcc, and it's either gcc 3.x or + // 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on + // Mac too, and some people build with gcc on Windows (cygwin or mingw). + // On Linux, different load modules may produce different type_info* + // pointers for the same type. Have to compare name strings to get good + // results. + return strcmp(lhs->name(), rhs->name()) < 0; +#else // not Linux, or gcc 4.4+ + // Just use before(), as we normally would + return lhs->before(*rhs); +#endif +} + +/** + * Specialize std::less to use std::type_info::before(). + * See MAINT-1175. It is NEVER a good idea to directly compare std::type_info* + * because, on Linux, you might get different std::type_info* pointers for the + * same type (from different load modules)! + */ +namespace std +{ + template <> + struct less: + public std::binary_function + { + bool operator()(const std::type_info* lhs, const std::type_info* rhs) const + { + return before(lhs, rhs); + } + }; + + template <> + struct less: + public std::binary_function + { + bool operator()(std::type_info* lhs, std::type_info* rhs) const + { + return before(lhs, rhs); + } + }; +} // std + #endif // LL_LLSTL_H diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h index 7510cc12e..0b6862444 100644 --- a/indra/llcommon/lltypeinfolookup.h +++ b/indra/llcommon/lltypeinfolookup.h @@ -12,9 +12,49 @@ #if ! defined(LL_LLTYPEINFOLOOKUP_H) #define LL_LLTYPEINFOLOOKUP_H -#include "llsortedvector.h" +#include +#include +#include +#include // std::binary_function #include +/** + * The following helper classes are based on the Boost.Unordered documentation: + * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html + */ + +/** + * Compute hash for a string passed as const char* + */ +struct const_char_star_hash: public std::unary_function +{ + std::size_t operator()(const char* str) const + { + std::size_t seed = 0; + for ( ; *str; ++str) + { + boost::hash_combine(seed, *str); + } + return seed; + } +}; + +/** + * Compute equality for strings passed as const char* + * + * I (nat) suspect that this is where the default behavior breaks for the + * const char* values returned from std::type_info::name(). If you compare the + * two const char* pointer values, as a naive, unspecialized implementation + * will surely do, they'll compare unequal. + */ +struct const_char_star_equal: public std::binary_function +{ + bool operator()(const char* lhs, const char* rhs) const + { + return strcmp(lhs, rhs) == 0; + } +}; + /** * LLTypeInfoLookup is specifically designed for use cases for which you might * consider std::map. We have several such data @@ -23,88 +63,55 @@ * different load modules will produce different std::type_info*. * LLTypeInfoLookup contains a workaround to address this issue. * - * Specifically, when we don't find the passed std::type_info*, - * LLTypeInfoLookup performs a linear search over registered entries to - * compare name() strings. Presuming that this succeeds, we cache the new - * (previously unrecognized) std::type_info* to speed future lookups. - * - * This worst-case fallback search (linear search with string comparison) - * should only happen the first time we look up a given type from a particular - * load module other than the one from which we initially registered types. - * (However, a lookup which wouldn't succeed anyway will always have - * worst-case performance.) This class is probably best used with less than a - * few dozen different types. + * The API deliberately diverges from std::map in several respects: + * * It avoids iterators, not only begin()/end() but also as return values + * from insert() and find(). This bypasses transform_iterator overhead. + * * Since we literally use compile-time types as keys, the essential insert() + * and find() methods accept the key type as a @em template parameter, + * accepting and returning value_type as a normal runtime value. This is to + * permit future optimization (e.g. compile-time type hashing) without + * changing the API. */ template class LLTypeInfoLookup { + // Use this for our underlying implementation: lookup by + // std::type_info::name() string. This is one of the rare cases in which I + // dare use const char* directly, rather than std::string, because I'm + // sure that every value returned by std::type_info::name() is static. + // HOWEVER, specify our own hash + equality functors: naively comparing + // distinct const char* values won't work. + typedef boost::unordered_map impl_map_type; + public: - typedef LLTypeInfoLookup self; - typedef LLSortedVector vector_type; - typedef typename vector_type::key_type key_type; - typedef typename vector_type::mapped_type mapped_type; - typedef typename vector_type::value_type value_type; - typedef typename vector_type::iterator iterator; - typedef typename vector_type::const_iterator const_iterator; + typedef VALUE value_type; LLTypeInfoLookup() {} - iterator begin() { return mVector.begin(); } - iterator end() { return mVector.end(); } - const_iterator begin() const { return mVector.begin(); } - const_iterator end() const { return mVector.end(); } - bool empty() const { return mVector.empty(); } - std::size_t size() const { return mVector.size(); } + bool empty() const { return mMap.empty(); } + std::size_t size() const { return mMap.size(); } - std::pair insert(const std::type_info* key, const VALUE& value) + template + bool insert(const value_type& value) { - return insert(value_type(key, value)); + // Obtain and store the std::type_info::name() string as the key. + // Return just the bool from std::map::insert()'s return pair. + return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second; } - std::pair insert(const value_type& pair) + template + boost::optional find() const { - return mVector.insert(pair); - } - - // const find() forwards to non-const find(): this can alter mVector! - const_iterator find(const std::type_info* key) const - { - return const_cast(this)->find(key); - } - - // non-const find() caches previously-unknown type_info* to speed future - // lookups. - iterator find(const std::type_info* key) - { - iterator found = mVector.find(key); - if (found != mVector.end()) - { - // If LLSortedVector::find() found, great, we're done. - return found; - } - // Here we didn't find the passed type_info*. On Linux, though, even - // for the same type, typeid(sametype) produces a different type_info* - // when used in different load modules. So the fact that we didn't - // find the type_info* we seek doesn't mean this type isn't - // registered. Scan for matching name() string. - for (typename vector_type::iterator ti(mVector.begin()), tend(mVector.end()); - ti != tend; ++ti) - { - if (std::string(ti->first->name()) == key->name()) - { - // This unrecognized 'key' is for the same type as ti->first. - // To speed future lookups, insert a new entry that lets us - // look up ti->second using this same 'key'. - return insert(key, ti->second).first; - } - } - // We simply have never seen a type with this type_info* from any load - // module. - return mVector.end(); + // Use the std::type_info::name() string as the key. + typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name()); + if (found == mMap.end()) + return boost::optional(); + return found->second; } private: - vector_type mVector; + impl_map_type mMap; }; #endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */ diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 74874585c..38084811b 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -33,9 +33,9 @@ // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes. #if LL_WINDOWS -# undef WIN32_LEAN_AND_MEAN -# include -# include +#undef WIN32_LEAN_AND_MEAN +#include +#include #endif #include "lldefs.h" @@ -452,7 +452,8 @@ static void get_random_bytes(void *buf, int nbytes) return; } -#if LL_WINDOWS +#if LL_WINDOWS + typedef struct _ASTAT_ { ADAPTER_STATUS adapt; @@ -460,58 +461,44 @@ typedef struct _ASTAT_ }ASTAT, * PASTAT; // static -S32 LLUUID::getNodeID(unsigned char *node_id) +S32 LLUUID::getNodeID(unsigned char *node_id) { - ASTAT Adapter; - NCB Ncb; - UCHAR uRetCode; - LANA_ENUM lenum; - int i; - int retval = 0; + ASTAT Adapter; + NCB Ncb; + UCHAR uRetCode; + LANA_ENUM lenum; + int i; + int retval = 0; - memset( &Ncb, 0, sizeof(Ncb) ); - Ncb.ncb_command = NCBENUM; - Ncb.ncb_buffer = (UCHAR *)&lenum; - Ncb.ncb_length = sizeof(lenum); - uRetCode = Netbios( &Ncb ); - // printf( "The NCBENUM return code is: 0x%x \n", uRetCode ); + memset( &Ncb, 0, sizeof(Ncb) ); + Ncb.ncb_command = NCBENUM; + Ncb.ncb_buffer = (UCHAR *)&lenum; + Ncb.ncb_length = sizeof(lenum); + uRetCode = Netbios( &Ncb ); - for(i=0; i < lenum.length ;i++) - { - memset( &Ncb, 0, sizeof(Ncb) ); - Ncb.ncb_command = NCBRESET; - Ncb.ncb_lana_num = lenum.lana[i]; + for(i=0; i < lenum.length ;i++) + { + memset( &Ncb, 0, sizeof(Ncb) ); + Ncb.ncb_command = NCBRESET; + Ncb.ncb_lana_num = lenum.lana[i]; - uRetCode = Netbios( &Ncb ); - // printf( "The NCBRESET on LANA %d return code is: 0x%x \n", - // lenum.lana[i], uRetCode ); + uRetCode = Netbios( &Ncb ); - memset( &Ncb, 0, sizeof (Ncb) ); - Ncb.ncb_command = NCBASTAT; - Ncb.ncb_lana_num = lenum.lana[i]; + memset( &Ncb, 0, sizeof (Ncb) ); + Ncb.ncb_command = NCBASTAT; + Ncb.ncb_lana_num = lenum.lana[i]; - strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */ - Ncb.ncb_buffer = (unsigned char *)&Adapter; - Ncb.ncb_length = sizeof(Adapter); + strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */ + Ncb.ncb_buffer = (unsigned char *)&Adapter; + Ncb.ncb_length = sizeof(Adapter); - uRetCode = Netbios( &Ncb ); -// printf( "The NCBASTAT on LANA %d return code is: 0x%x \n", -// lenum.lana[i], uRetCode ); - if ( uRetCode == 0 ) - { -// printf( "The Ethernet Number on LANA %d is: %02x%02x%02x%02x%02x%02x\n", -// lenum.lana[i], -// Adapter.adapt.adapter_address[0], -// Adapter.adapt.adapter_address[1], -// Adapter.adapt.adapter_address[2], -// Adapter.adapt.adapter_address[3], -// Adapter.adapt.adapter_address[4], -// Adapter.adapt.adapter_address[5] ); + uRetCode = Netbios( &Ncb ); + if ( uRetCode == 0 ) + { memcpy(node_id,Adapter.adapt.adapter_address,6); /* Flawfinder: ignore */ retval = 1; - - } - } + } + } return retval; } diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index d7ded1a26..3a0d66e4a 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -132,6 +132,7 @@ public: U8 mData[UUID_BYTES]; }; + typedef std::vector uuid_vec_t; // Construct diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index c8a0875f5..07ca00913 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -37,7 +37,6 @@ #include "v3math.h" #include "llvector4a.h" #include -#include #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG #define OCT_ERRS LL_ERRS("OctreeErrors") @@ -89,11 +88,12 @@ public: typedef LLOctreeTraveler oct_traveler; typedef LLTreeTraveler tree_traveler; - typedef typename std::set > element_list; - typedef typename element_list::iterator element_iter; - typedef typename element_list::const_iterator const_element_iter; + typedef LLPointer* element_list; + typedef LLPointer* element_iter; + typedef const LLPointer* const_element_iter; typedef typename std::vector*>::iterator tree_listener_iter; - typedef typename std::vector* > child_list; + typedef LLOctreeNode** child_list; + typedef LLOctreeNode** child_iter; typedef LLTreeNode BaseType; typedef LLOctreeNode oct_node; typedef LLOctreeListener oct_listener; @@ -115,6 +115,9 @@ public: : mParent((oct_node*)parent), mOctant(octant) { + mData = NULL; + mDataEnd = NULL; + mCenter = center; mSize = size; @@ -133,6 +136,16 @@ public: { BaseType::destroyListeners(); + for (U32 i = 0; i < mElementCount; ++i) + { + mData[i]->setBinIndex(-1); + mData[i] = NULL; + } + + free(mData); + mData = NULL; + mDataEnd = NULL; + for (U32 i = 0; i < getChildCount(); i++) { delete getChild(i); @@ -229,12 +242,17 @@ public: } void accept(oct_traveler* visitor) { visitor->visit(this); } - virtual bool isLeaf() const { return mChild.empty(); } + virtual bool isLeaf() const { return mChildCount == 0; } U32 getElementCount() const { return mElementCount; } + bool isEmpty() const { return mElementCount == 0; } element_list& getData() { return mData; } const element_list& getData() const { return mData; } - + element_iter getDataBegin() { return mData; } + element_iter getDataEnd() { return mDataEnd; } + const_element_iter getDataBegin() const { return mData; } + const_element_iter getDataEnd() const { return mDataEnd; } + U32 getChildCount() const { return mChildCount; } oct_node* getChild(U32 index) { return mChild[index]; } const oct_node* getChild(U32 index) const { return mChild[index]; } @@ -299,7 +317,7 @@ public: virtual bool insert(T* data) { - if (data == NULL) + if (data == NULL || data->getBinIndex() != -1) { OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; return false; @@ -309,22 +327,19 @@ public: //is it here? if (isInside(data->getPositionGroup())) { - if (((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius())) || + if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here -#if LL_OCTREE_PARANOIA_CHECK - //if this is a redundant insertion, error out (should never happen) - if (mData.find(data) != mData.end()) - { - llwarns << "Redundant octree insertion detected. " << data << llendl; - return false; - } -#endif + mElementCount++; + mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); - mData.insert(data); + //avoid unref on uninitialized memory + memset(mData+mElementCount-1, 0, sizeof(LLPointer)); + + mData[mElementCount-1] = data; + mDataEnd = mData + mElementCount; + data->setBinIndex(mElementCount-1); BaseType::insert(data); - - mElementCount = mData.size(); return true; } else @@ -358,10 +373,16 @@ public: if( lt == 0x7 ) { - mData.insert(data); - BaseType::insert(data); + mElementCount++; + mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); - mElementCount = mData.size(); + //avoid unref on uninitialized memory + memset(mData+mElementCount-1, 0, sizeof(LLPointer)); + + mData[mElementCount-1] = data; + mDataEnd = mData + mElementCount; + data->setBinIndex(mElementCount-1); + BaseType::insert(data); return true; } @@ -410,23 +431,59 @@ public: return false; } + void _remove(T* data, S32 i) + { //precondition -- mElementCount > 0, idx is in range [0, mElementCount) + + mElementCount--; + data->setBinIndex(-1); + + if (mElementCount > 0) + { + if (mElementCount != i) + { + mData[i] = mData[mElementCount]; //might unref data, do not access data after this point + mData[i]->setBinIndex(i); + } + + mData[mElementCount] = NULL; //needed for unref + mData = (element_list) realloc(mData, sizeof(LLPointer)*mElementCount); + mDataEnd = mData+mElementCount; + } + else + { + mData[0] = NULL; //needed for unref + free(mData); + mData = NULL; + mDataEnd = NULL; + } + + notifyRemoval(data); + checkAlive(); + } + bool remove(T* data) { - if (mData.find(data) != mData.end()) - { //we have data - mData.erase(data); - mElementCount = mData.size(); - this->notifyRemoval(data); - checkAlive(); - return true; + S32 i = data->getBinIndex(); + + if (i >= 0 && i < (S32)mElementCount) + { + if (mData[i] == data) + { //found it + _remove(data, i); + llassert(data->getBinIndex() == -1); + return true; + } } - else if (isInside(data)) + + if (isInside(data)) { oct_node* dest = getNodeAt(data); if (dest != this) { - return dest->remove(data); + bool ret = dest->remove(data); + llassert(data->getBinIndex() == -1); + return ret; } } @@ -445,19 +502,20 @@ public: //node is now root llwarns << "!!! OCTREE REMOVING FACE BY ADDRESS, SEVERE PERFORMANCE PENALTY |||" << llendl; node->removeByAddress(data); + llassert(data->getBinIndex() == -1); return true; } void removeByAddress(T* data) { - if (mData.find(data) != mData.end()) + for (U32 i = 0; i < mElementCount; ++i) { - mData.erase(data); - mElementCount = mData.size(); - this->notifyRemoval(data); - llwarns << "FOUND!" << llendl; - checkAlive(); - return; + if (mData[i] == data) + { //we have data + _remove(data, i); + llwarns << "FOUND!" << llendl; + return; + } } for (U32 i = 0; i < getChildCount(); i++) @@ -469,8 +527,8 @@ public: void clearChildren() { - mChild.clear(); mChildCount = 0; + U32* foo = (U32*) mChildMap; foo[0] = foo[1] = 0xFFFFFFFF; } @@ -532,7 +590,7 @@ public: mChildMap[child->getOctant()] = mChildCount; - mChild.push_back(child); + mChild[mChildCount] = child; ++mChildCount; child->setParent(this); @@ -561,9 +619,12 @@ public: mChild[index]->destroy(); delete mChild[index]; } - mChild.erase(mChild.begin() + index); + --mChildCount; + mChild[index] = mChild[mChildCount]; + + //rebuild child map U32* foo = (U32*) mChildMap; foo[0] = foo[1] = 0xFFFFFFFF; @@ -619,11 +680,12 @@ protected: oct_node* mParent; U8 mOctant; - child_list mChild; + LLOctreeNode* mChild[8]; U8 mChildMap[8]; U32 mChildCount; element_list mData; + element_iter mDataEnd; U32 mElementCount; }; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8b47a92ea..54a88a570 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -324,16 +324,16 @@ public: LLVector4a& min = node->mExtents[0]; LLVector4a& max = node->mExtents[1]; - if (!branch->getData().empty()) + if (!branch->isEmpty()) { //node has data, find AABB that binds data set - const LLVolumeTriangle* tri = *(branch->getData().begin()); + const LLVolumeTriangle* tri = *(branch->getDataBegin()); //initialize min/max to first available vertex min = *(tri->mV[0]); max = *(tri->mV[0]); for (LLOctreeNode::const_element_iter iter = - branch->getData().begin(); iter != branch->getData().end(); ++iter) + branch->getDataBegin(); iter != branch->getDataEnd(); ++iter) { //for each triangle in node //stretch by triangles in node @@ -348,7 +348,7 @@ public: max.setMax(max, *tri->mV[2]); } } - else if (!branch->getChildren().empty()) + else if (!branch->isLeaf()) { //no data, but child nodes exist LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp index d5bd5a78d..cf9aeece8 100644 --- a/indra/llmath/llvolumeoctree.cpp +++ b/indra/llmath/llvolumeoctree.cpp @@ -131,7 +131,7 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode* node) { for (LLOctreeNode::const_element_iter iter = - node->getData().begin(); iter != node->getData().end(); ++iter) + node->getDataBegin(); iter != node->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; @@ -236,8 +236,8 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode* branch) } //children fit, check data - for (LLOctreeNode::const_element_iter iter = branch->getData().begin(); - iter != branch->getData().end(); ++iter) + for (LLOctreeNode::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h index 688d91dc4..c25e37f1a 100644 --- a/indra/llmath/llvolumeoctree.h +++ b/indra/llmath/llvolumeoctree.h @@ -39,7 +39,7 @@ class LLVolumeTriangle : public LLRefCount public: LLVolumeTriangle() { - + mBinIndex = -1; } LLVolumeTriangle(const LLVolumeTriangle& rhs) @@ -64,9 +64,14 @@ public: U16 mIndex[3]; F32 mRadius; + mutable S32 mBinIndex; + virtual const LLVector4a& getPositionGroup() const; virtual const F32& getBinRadius() const; + + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 idx) const { mBinIndex = idx; } }; class LLVolumeOctreeListener : public LLOctreeListener diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 617d43980..fc057d969 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -72,9 +72,10 @@ static const U32 EASY_HANDLE_POOL_SIZE = 5; static const S32 MULTI_PERFORM_CALL_REPEAT = 5; -static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation +static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; +static // DEBUG // S32 gCurlEasyCount = 0; S32 gCurlMultiCount = 0; @@ -85,12 +86,9 @@ S32 gCurlMultiCount = 0; std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; -LLCurlThread* LLCurl::sCurlThread = NULL ; -LLMutex* LLCurl::sHandleMutexp = NULL ; -S32 LLCurl::sTotalHandles = 0 ; -bool LLCurl::sNotQuitting = true; -F32 LLCurl::sCurlRequestTimeOut = 120.f; //seonds -S32 LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined). + +bool LLCurl::sMultiThreaded = false; +static U32 sMainThreadID = 0; void check_curl_code(CURLcode code) { @@ -179,7 +177,6 @@ void LLCurl::Responder::completedRaw( { llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; } - completed(status, reason, content); } @@ -202,8 +199,8 @@ void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, c } -//namespace boost -//{ +namespace boost +{ void intrusive_ptr_add_ref(LLCurl::Responder* p) { ++p->mReferenceCount; @@ -211,32 +208,29 @@ void LLCurl::Responder::completedHeader(U32 status, const std::string& reason, c void intrusive_ptr_release(LLCurl::Responder* p) { - if (p && 0 == --p->mReferenceCount) + if(p && 0 == --p->mReferenceCount) { delete p; } } -//}; +}; ////////////////////////////////////////////////////////////////////////////// std::set LLCurl::Easy::sFreeHandles; std::set LLCurl::Easy::sActiveHandles; -LLMutex* LLCurl::Easy::sHandleMutexp = NULL ; +LLMutex* LLCurl::Easy::sHandleMutex = NULL; +LLMutex* LLCurl::Easy::sMultiMutex = NULL; //static CURL* LLCurl::Easy::allocEasyHandle() { - llassert(LLCurl::getCurlThread()) ; - CURL* ret = NULL; - - LLMutexLock lock(sHandleMutexp) ; - + LLMutexLock lock(sHandleMutex); if (sFreeHandles.empty()) { - ret = LLCurl::newEasyHandle(); + ret = curl_easy_init(); } else { @@ -256,29 +250,19 @@ CURL* LLCurl::Easy::allocEasyHandle() //static void LLCurl::Easy::releaseEasyHandle(CURL* handle) { - static const S32 MAX_NUM_FREE_HANDLES = 32 ; - if (!handle) { - return ; //handle allocation failed. - //llerrs << "handle cannot be NULL!" << llendl; + llerrs << "handle cannot be NULL!" << llendl; } - LLMutexLock lock(sHandleMutexp) ; + LLMutexLock lock(sHandleMutex); + if (sActiveHandles.find(handle) != sActiveHandles.end()) { sActiveHandles.erase(handle); - - if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) - { sFreeHandles.insert(handle); } else - { - LLCurl::deleteEasyHandle(handle) ; - } - } - else { llerrs << "Invalid handle." << llendl; } @@ -308,7 +292,7 @@ LLCurl::Easy* LLCurl::Easy::getEasy() // multi handles cache if they are added to one. CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); check_curl_code(result); - + // Disable SSL/TLS session caching. Some servers refuse to talk to us when session ids are enabled. // id.secondlife.com is such a server, when greeted with a SSL HELLO and a session id, it immediatly returns a RST packet and closes // the connections. @@ -316,7 +300,6 @@ LLCurl::Easy* LLCurl::Easy::getEasy() result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_SSL_SESSIONID_CACHE, 0); check_curl_code(result); - ++gCurlEasyCount; return easy; } @@ -327,14 +310,6 @@ LLCurl::Easy::~Easy() --gCurlEasyCount; curl_slist_free_all(mHeaders); for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); - - if (mResponder && LLCurl::sNotQuitting) //aborted - { - std::string reason("Request timeout, aborted.") ; - mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort - reason, mChannels, mOutput); - } - mResponder = NULL; } void LLCurl::Easy::resetState() @@ -373,11 +348,11 @@ const char* LLCurl::Easy::getErrorBuffer() void LLCurl::Easy::setCA() { - if (!sCAPath.empty()) + if(!sCAPath.empty()) { setoptString(CURLOPT_CAPATH, sCAPath); } - if (!sCAFile.empty()) + if(!sCAFile.empty()) { setoptString(CURLOPT_CAINFO, sCAFile); } @@ -403,7 +378,7 @@ U32 LLCurl::Easy::report(CURLcode code) if (code == CURLE_OK) { check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode)); - //*TODO: get reason from first line of mHeaderOutput + // *TODO: get reason from first line of mHeaderOutput } else { @@ -411,7 +386,7 @@ U32 LLCurl::Easy::report(CURLcode code) responseReason = strerror(code) + " : " + mErrorBuffer; setopt(CURLOPT_FRESH_CONNECT, TRUE); } - + if (mResponder) { mResponder->completedRaw(responseCode, responseReason, mChannels, mOutput); @@ -507,7 +482,6 @@ void LLCurl::Easy::prepRequest(const std::string& url, LLProxy::getInstance()->applyProxySettings(this); mOutput.reset(new LLBufferArray); - mOutput->setThreaded(true); setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback); setopt(CURLOPT_WRITEDATA, (void*)this); @@ -516,9 +490,8 @@ void LLCurl::Easy::prepRequest(const std::string& url, setopt(CURLOPT_HEADERFUNCTION, (void*)&curlHeaderCallback); setopt(CURLOPT_HEADERDATA, (void*)this); - // Allow up to five redirects - if (responder && responder->followRedir()) + if(responder && responder->followRedir()) { setopt(CURLOPT_FOLLOWLOCATION, 1); setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); @@ -551,74 +524,54 @@ void LLCurl::Easy::prepRequest(const std::string& url, } //////////////////////////////////////////////////////////////////////////// -LLCurl::Multi::Multi(F32 idle_time_out) - : mQueued(0), + +LLCurl::Multi::Multi() + : LLThread("Curl Multi"), + mQueued(0), mErrorCount(0), - mState(STATE_READY), - mDead(FALSE), - mValid(TRUE), - mMutexp(NULL), - mDeletionMutexp(NULL), - mEasyMutexp(NULL) + mPerformState(PERFORM_STATE_READY) { - mCurlMultiHandle = LLCurl::newMultiHandle(); + mQuitting = false; + + mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; + if (mThreaded) + { + mSignal = new LLCondition; + } + else + { + mSignal = NULL; + } + + mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) { llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; - mCurlMultiHandle = LLCurl::newMultiHandle(); + mCurlMultiHandle = curl_multi_init(); } - //llassert_always(mCurlMultiHandle); - - if(mCurlMultiHandle) - { - if(LLCurl::getCurlThread()->getThreaded()) - { - mMutexp = new LLMutex() ; - mDeletionMutexp = new LLMutex() ; - mEasyMutexp = new LLMutex() ; - } - LLCurl::getCurlThread()->addMulti(this) ; - - mIdleTimeOut = idle_time_out ; - if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) - { - mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; - } - + llassert_always(mCurlMultiHandle); ++gCurlMultiCount; } -} LLCurl::Multi::~Multi() { - cleanup(true) ; - - delete mDeletionMutexp ; - mDeletionMutexp = NULL ; -} + llassert(isStopped()); -void LLCurl::Multi::cleanup(bool deleted) -{ - if(!mCurlMultiHandle) + if (LLCurl::sMultiThreaded) { - return ; //nothing to clean. + LLCurl::Easy::sMultiMutex->lock(); } - llassert_always(deleted || !mValid) ; - LLMutexLock lock(mDeletionMutexp); - + delete mSignal; + mSignal = NULL; + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) { Easy* easy = *iter; check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); - - if(deleted) - { - easy->mResponder = NULL ; //avoid triggering mResponder. - } delete easy; } mEasyActiveList.clear(); @@ -628,169 +581,84 @@ void LLCurl::Multi::cleanup(bool deleted) for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer()); mEasyFreeList.clear(); - check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); - mCurlMultiHandle = NULL ; - - delete mMutexp ; - mMutexp = NULL ; - delete mEasyMutexp ; - mEasyMutexp = NULL ; - - mQueued = 0 ; - mState = STATE_COMPLETED; - + check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); --gCurlMultiCount; - return ; -} - -void LLCurl::Multi::lock() -{ - if(mMutexp) + if (LLCurl::sMultiThreaded) { - mMutexp->lock() ; + LLCurl::Easy::sMultiMutex->unlock(); } } -void LLCurl::Multi::unlock() -{ - if(mMutexp) - { - mMutexp->unlock() ; - } -} - -void LLCurl::Multi::markDead() -{ - { - LLMutexLock lock(mDeletionMutexp) ; - - if(mCurlMultiHandle != NULL) - { - mDead = TRUE ; - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; - - return; - } - } - - //not valid, delete it. - delete this; -} - -void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) -{ - lock() ; - mState = state ; - unlock() ; - - if(mState == STATE_READY) - { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_NORMAL) ; - } -} - -LLCurl::Multi::ePerformState LLCurl::Multi::getState() -{ - return mState; -} - -bool LLCurl::Multi::isCompleted() -{ - return STATE_COMPLETED == getState() ; -} - -bool LLCurl::Multi::waitToComplete() -{ - if(!isValid()) - { - return true ; - } - - if(!mMutexp) //not threaded - { - doPerform() ; - return true ; - } - - bool completed = (STATE_COMPLETED == mState) ; - if(!completed) - { - LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ; - } - - return completed; -} - CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) { - LLMutexLock lock(mMutexp) ; - CURLMsg* curlmsg = curl_multi_info_read(mCurlMultiHandle, msgs_in_queue); return curlmsg; } -//return true if dead -bool LLCurl::Multi::doPerform() +void LLCurl::Multi::perform() { - LLMutexLock lock(mDeletionMutexp) ; - - bool dead = mDead ; - - if(mDead) + if (mThreaded) { - setState(STATE_COMPLETED); - mQueued = 0 ; - } - else if(getState() != STATE_COMPLETED) - { - setState(STATE_PERFORMING); - - S32 q = 0; - for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count++) + mSignal->lock(); + if (mPerformState == PERFORM_STATE_READY) { - LLMutexLock lock(mMutexp) ; - - //WARNING: curl_multi_perform will block for many hundreds of milliseconds - // NEVER call this from the main thread, and NEVER allow the main thread to - // wait on a mutex held by this thread while curl_multi_perform is executing - CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); - if (CURLM_CALL_MULTI_PERFORM != code || q == 0) - { - check_curl_multi_code(code); - - break; - } + mSignal->signal(); } - - mQueued = q; - setState(STATE_COMPLETED) ; - mIdleTimer.reset() ; + mSignal->unlock(); } - else if(!mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. + else { - dead = true ; - } - else if(mValid && mIdleTimer.getElapsedTimeF32() > mIdleTimeOut - 1.f) //idle for too long, mark it invalid. - { - mValid = FALSE ; - } + doPerform(); + } +} - return dead ; +void LLCurl::Multi::run() +{ + llassert(mThreaded); + + mSignal->lock(); + while (!mQuitting) + { + mSignal->wait(); + mPerformState = PERFORM_STATE_PERFORMING; + if (!mQuitting) + { + LLMutexLock lock(LLCurl::Easy::sMultiMutex); + doPerform(); + } + } + mSignal->unlock(); +} + +void LLCurl::Multi::doPerform() +{ + S32 q = 0; + if (mThreaded) + mSignal->unlock(); + for (S32 call_count = 0; + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) + { + CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); + if (CURLM_CALL_MULTI_PERFORM != code || q == 0) + { + check_curl_multi_code(code); + break; + } + + } + if (mThreaded) + mSignal->lock(); + mQueued = q; + mPerformState = PERFORM_STATE_COMPLETED; } S32 LLCurl::Multi::process() { - if(!isValid()) - { - return 0 ; - } + perform(); - waitToComplete() ; - - if (getState() != STATE_COMPLETED) + if (mPerformState != PERFORM_STATE_COMPLETED) { return 0; } @@ -805,26 +673,17 @@ S32 LLCurl::Multi::process() if (msg->msg == CURLMSG_DONE) { U32 response = 0; - Easy* easy = NULL ; - - { - LLMutexLock lock(mEasyMutexp) ; - easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); - if (iter != mEasyActiveMap.end()) - { - easy = iter->second; - } - } - - if(easy) + easy_active_map_t::iterator iter = mEasyActiveMap.find(msg->easy_handle); + if (iter != mEasyActiveMap.end()) { + Easy* easy = iter->second; response = easy->report(msg->data.result); removeEasy(easy); } else { response = 499; - //*TODO: change to llwarns + // *TODO: change to llwarns llerrs << "cleaned up curl request completed!" << llendl; } if (response >= 400) @@ -835,28 +694,25 @@ S32 LLCurl::Multi::process() } } - setState(STATE_READY); - + mPerformState = PERFORM_STATE_READY; return processed; } LLCurl::Easy* LLCurl::Multi::allocEasy() { - Easy* easy = 0; + Easy* easy = 0; if (mEasyFreeList.empty()) - { + { easy = Easy::getEasy(); } else { - LLMutexLock lock(mEasyMutexp) ; easy = *(mEasyFreeList.begin()); mEasyFreeList.erase(easy); } if (easy) { - LLMutexLock lock(mEasyMutexp) ; mEasyActiveList.insert(easy); mEasyActiveMap[easy->getCurlHandle()] = easy; } @@ -865,7 +721,6 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { - LLMutexLock lock(mMutexp) ; CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); check_curl_multi_code(mcode); //if (mcode != CURLM_OK) @@ -878,153 +733,25 @@ bool LLCurl::Multi::addEasy(Easy* easy) void LLCurl::Multi::easyFree(Easy* easy) { - if(mEasyMutexp) - { - mEasyMutexp->lock() ; - } - mEasyActiveList.erase(easy); mEasyActiveMap.erase(easy->getCurlHandle()); - if (mEasyFreeList.size() < EASY_HANDLE_POOL_SIZE) - { - mEasyFreeList.insert(easy); - - if(mEasyMutexp) - { - mEasyMutexp->unlock() ; - } - + { easy->resetState(); + mEasyFreeList.insert(easy); } else { - if(mEasyMutexp) - { - mEasyMutexp->unlock() ; - } delete easy; } } void LLCurl::Multi::removeEasy(Easy* easy) { - { - LLMutexLock lock(mMutexp) ; - check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); - } + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); easyFree(easy); } -//------------------------------------------------------------ -//LLCurlThread -LLCurlThread::CurlRequest::CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread) : - LLQueuedThread::QueuedRequest(handle, LLQueuedThread::PRIORITY_NORMAL, FLAG_AUTO_COMPLETE), - mMulti(multi), - mCurlThread(curl_thread) -{ -} - -LLCurlThread::CurlRequest::~CurlRequest() -{ - if(mMulti) - { - mCurlThread->deleteMulti(mMulti) ; - mMulti = NULL ; - } -} - -bool LLCurlThread::CurlRequest::processRequest() -{ - bool completed = true ; - if(mMulti) - { - completed = mCurlThread->doMultiPerform(mMulti) ; - - if(!completed) - { - setPriority(LLQueuedThread::PRIORITY_LOW) ; - } - } - - return completed ; -} - -void LLCurlThread::CurlRequest::finishRequest(bool completed) -{ - if(mMulti->isDead()) - { - mCurlThread->deleteMulti(mMulti) ; - } - else - { - mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request. - } - - mMulti = NULL ; -} - -LLCurlThread::LLCurlThread(bool threaded) : - LLQueuedThread("curlthread", threaded) -{ -} - -//virtual -LLCurlThread::~LLCurlThread() -{ -} - -S32 LLCurlThread::update(F32 max_time_ms) -{ - return LLQueuedThread::update(max_time_ms); -} - -void LLCurlThread::addMulti(LLCurl::Multi* multi) -{ - multi->mHandle = generateHandle() ; - - CurlRequest* req = new CurlRequest(multi->mHandle, multi, this) ; - - if (!addRequest(req)) - { - llwarns << "curl request added when the thread is quitted" << llendl; - } -} - -void LLCurlThread::killMulti(LLCurl::Multi* multi) -{ - if(!multi) - { - return ; - } - - multi->markDead() ; -} - -//private -bool LLCurlThread::doMultiPerform(LLCurl::Multi* multi) -{ - return multi->doPerform() ; -} - -//private -void LLCurlThread::deleteMulti(LLCurl::Multi* multi) -{ - delete multi ; -} - -//private -void LLCurlThread::cleanupMulti(LLCurl::Multi* multi) -{ - multi->cleanup() ; - if(multi->isDead()) //check if marked dead during cleaning up. - { - deleteMulti(multi) ; - } -} - -//------------------------------------------------------------ - //static std::string LLCurl::strerror(CURLcode errorcode) { @@ -1039,30 +766,45 @@ LLCurlRequest::LLCurlRequest() : mActiveMulti(NULL), mActiveRequestCount(0) { + mThreadID = LLThread::currentID(); mProcessing = FALSE; } LLCurlRequest::~LLCurlRequest() { + llassert_always(mThreadID == LLThread::currentID()); + //stop all Multi handle background threads for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter) { - LLCurl::getCurlThread()->killMulti(*iter) ; + LLCurl::Multi* multi = *iter; + if (multi->mThreaded) + multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->lock(); + } + } + if (multi->mThreaded) + multi->mSignal->unlock(); } - mMultiSet.clear() ; + for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); } void LLCurlRequest::addMulti() { + llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); - if(!multi->isValid()) + if (multi->mThreaded) { - LLCurl::getCurlThread()->killMulti(multi) ; - mActiveMulti = NULL ; - mActiveRequestCount = 0 ; - return; + multi->start(); } - mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -1076,12 +818,7 @@ LLCurl::Easy* LLCurlRequest::allocEasy() { addMulti(); } - if(!mActiveMulti) - { - return NULL ; - } - - //llassert_always(mActiveMulti); + llassert_always(mActiveMulti); ++mActiveRequestCount; LLCurl::Easy* easy = mActiveMulti->allocEasy(); return easy; @@ -1183,6 +920,7 @@ bool LLCurlRequest::post(const std::string& url, // Note: call once per frame S32 LLCurlRequest::process() { + llassert_always(mThreadID == LLThread::currentID()); S32 res = 0; mProcessing = TRUE; @@ -1191,25 +929,28 @@ S32 LLCurlRequest::process() { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; - - if(!multi->isValid()) - { - if(multi == mActiveMulti) - { - mActiveMulti = NULL ; - mActiveRequestCount = 0 ; - } - mMultiSet.erase(curiter) ; - LLCurl::getCurlThread()->killMulti(multi) ; - continue ; - } - S32 tres = multi->process(); res += tres; if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) { mMultiSet.erase(curiter); - LLCurl::getCurlThread()->killMulti(multi); + if (multi->mThreaded) + multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->unlock(); + } + } + if (multi->mThreaded) + multi->mSignal->unlock(); + + delete multi; } } mProcessing = FALSE; @@ -1218,27 +959,15 @@ S32 LLCurlRequest::process() S32 LLCurlRequest::getQueued() { + llassert_always(mThreadID == LLThread::currentID()); S32 queued = 0; for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ) { curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; - - if(!multi->isValid()) - { - if(multi == mActiveMulti) - { - mActiveMulti = NULL ; - mActiveRequestCount = 0 ; - } - LLCurl::getCurlThread()->killMulti(multi); - mMultiSet.erase(curiter) ; - continue ; - } - queued += multi->mQueued; - if (multi->getState() != LLCurl::Multi::STATE_READY) + if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY) { ++queued; } @@ -1255,34 +984,41 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); - - if(mMulti->isValid()) + if (mMulti->mThreaded) { + mMulti->start(); + } mEasy = mMulti->allocEasy(); if (mEasy) { mEasy->setErrorBuffer(); mEasy->setCA(); - // Set proxy settings if configured to do so. - LLProxy::getInstance()->applyProxySettings(mEasy); - } -} - else - { - LLCurl::getCurlThread()->killMulti(mMulti) ; - mEasy = NULL ; - mMulti = NULL ; } } LLCurlEasyRequest::~LLCurlEasyRequest() { - LLCurl::getCurlThread()->killMulti(mMulti) ; + if (mMulti->mThreaded) + mMulti->mSignal->lock(); + mMulti->mQuitting = true; + if (mMulti->mThreaded) + { + while (!mMulti->isStopped()) + { + mMulti->mSignal->signal(); + mMulti->mSignal->unlock(); + apr_sleep(1000); + mMulti->mSignal->lock(); + } + } + if (mMulti->mThreaded) + mMulti->mSignal->unlock(); + delete mMulti; } void LLCurlEasyRequest::setopt(CURLoption option, S32 value) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(option, value); } @@ -1290,7 +1026,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value) void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setoptString(option, value); } @@ -1298,7 +1034,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value void LLCurlEasyRequest::setPost(char* postdata, S32 size) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_POST, 1); mEasy->setopt(CURLOPT_POSTFIELDS, postdata); @@ -1308,7 +1044,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size) void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER @@ -1317,7 +1053,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_WRITEDATA, userdata); @@ -1326,7 +1062,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback); mEasy->setopt(CURLOPT_READDATA, userdata); @@ -1335,7 +1071,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata) { - if (isValid() && mEasy) + if (mEasy) { mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback); mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); @@ -1344,7 +1080,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* void LLCurlEasyRequest::slist_append(const char* str) { - if (isValid() && mEasy) + if (mEasy) { mEasy->slist_append(str); } @@ -1355,7 +1091,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url) llassert_always(!mRequestSent); mRequestSent = true; lldebugs << url << llendl; - if (isValid() && mEasy) + if (mEasy) { mEasy->setHeaders(); mEasy->setoptString(CURLOPT_URL, url); @@ -1367,24 +1103,25 @@ void LLCurlEasyRequest::requestComplete() { llassert_always(mRequestSent); mRequestSent = false; - if (isValid() && mEasy) + if (mEasy) { mMulti->removeEasy(mEasy); } } +void LLCurlEasyRequest::perform() +{ + mMulti->perform(); +} + // Usage: Call getRestult until it returns false (no more messages) bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info) { - if(!isValid()) - { - return false ; - } - if (!mMulti->isCompleted()) + if (mMulti->mPerformState != LLCurl::Multi::PERFORM_STATE_COMPLETED) { //we're busy, try again later return false; } - mMulti->setState(LLCurl::Multi::STATE_READY) ; + mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY; if (!mEasy) { @@ -1444,7 +1181,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info) std::string LLCurlEasyRequest::getErrorString() { - return isValid() && mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); + return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); } //////////////////////////////////////////////////////////////////////////// @@ -1470,11 +1207,10 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded) +void LLCurl::initClass(bool multi_threaded) { - sCurlRequestTimeOut = curl_reuest_timeout ; //seconds - sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). - + sMainThreadID = LLThread::currentID(); + sMultiThreaded = multi_threaded; // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html @@ -1482,126 +1218,41 @@ void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool mul check_curl_code(code); + Easy::sHandleMutex = new LLMutex; + Easy::sMultiMutex = new LLMutex; + #if SAFE_SSL S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; iupdate(1)) //finish all tasks - { - break ; - } - } - sCurlThread->shutdown() ; - delete sCurlThread ; - sCurlThread = NULL ; - #if SAFE_SSL CRYPTO_set_locking_callback(NULL); for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer()); #endif + delete Easy::sHandleMutex; + Easy::sHandleMutex = NULL; + delete Easy::sMultiMutex; + Easy::sMultiMutex = NULL; + for (std::set::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) { CURL* curl = *iter; - LLCurl::deleteEasyHandle(curl); + curl_easy_cleanup(curl); } Easy::sFreeHandles.clear(); - delete Easy::sHandleMutexp ; - Easy::sHandleMutexp = NULL ; - - delete sHandleMutexp ; - sHandleMutexp = NULL ; - - // removed as per https://jira.secondlife.com/browse/SH-3115 - //llassert(Easy::sActiveHandles.empty()); -} - -//static -CURLM* LLCurl::newMultiHandle() -{ - LLMutexLock lock(sHandleMutexp) ; - - if(sTotalHandles + 1 > sMaxHandles) - { - llwarns << "no more handles available." << llendl ; - return NULL ; //failed - } - sTotalHandles++; - - CURLM* ret = curl_multi_init() ; - if(!ret) - { - llwarns << "curl_multi_init failed." << llendl ; - } - - return ret ; -} - -//static -CURLMcode LLCurl::deleteMultiHandle(CURLM* handle) -{ - if(handle) - { - LLMutexLock lock(sHandleMutexp) ; - sTotalHandles-- ; - return curl_multi_cleanup(handle) ; - } - return CURLM_OK ; -} - -//static -CURL* LLCurl::newEasyHandle() -{ - LLMutexLock lock(sHandleMutexp) ; - - if(sTotalHandles + 1 > sMaxHandles) - { - llwarns << "no more handles available." << llendl ; - return NULL ; //failed - } - sTotalHandles++; - - CURL* ret = curl_easy_init() ; - if(!ret) - { - llwarns << "curl_easy_init failed." << llendl ; - } - - return ret ; -} - -//static -void LLCurl::deleteEasyHandle(CURL* handle) -{ - if(handle) - { - LLMutexLock lock(sHandleMutexp) ; - curl_easy_cleanup(handle) ; - sTotalHandles-- ; - } + llassert(Easy::sActiveHandles.empty()); } const unsigned int LLCurl::MAX_REDIRECTS = 5; diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 42ab93e58..76ef595e9 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -42,11 +42,8 @@ #include "lliopipe.h" #include "llsd.h" #include "llthread.h" -#include "llqueuedthread.h" -#include "llframetimer.h" class LLMutex; -class LLCurlThread; // For whatever reason, this is not typedef'd in curl.h typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream); @@ -59,6 +56,8 @@ public: class Easy; class Multi; + static bool sMultiThreaded; + struct TransferInfo { TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {} @@ -125,7 +124,6 @@ public: { return false; } - public: /* but not really -- don't touch this */ U32 mReferenceCount; @@ -163,7 +161,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false); + static void initClass(bool multi_threaded = false); /** * @ brief Cleanup LLCurl class @@ -182,25 +180,10 @@ public: static void ssl_locking_callback(int mode, int type, const char *file, int line); static unsigned long ssl_thread_id(void); - static LLCurlThread* getCurlThread() { return sCurlThread ;} - - static CURLM* newMultiHandle() ; - static CURLMcode deleteMultiHandle(CURLM* handle) ; - static CURL* newEasyHandle() ; - static void deleteEasyHandle(CURL* handle) ; - private: static std::string sCAPath; static std::string sCAFile; static const unsigned int MAX_REDIRECTS; - static LLCurlThread* sCurlThread; - - static LLMutex* sHandleMutexp ; - static S32 sTotalHandles ; - static S32 sMaxHandles; -public: - static bool sNotQuitting; - static F32 sCurlRequestTimeOut; }; class LLCurl::Easy @@ -209,7 +192,7 @@ class LLCurl::Easy private: Easy(); - + public: static Easy* getEasy(); ~Easy(); @@ -218,41 +201,41 @@ public: void setErrorBuffer(); void setCA(); - + void setopt(CURLoption option, S32 value); // These assume the setter does not free value! void setopt(CURLoption option, void* value); void setopt(CURLoption option, char* value); - // Copies the string so that it is guaranteed to stick around + // Copies the string so that it is gauranteed to stick around void setoptString(CURLoption option, const std::string& value); - + void slist_append(const char* str); void setHeaders(); - + U32 report(CURLcode); void getTransferInfo(LLCurl::TransferInfo* info); - void prepRequest(const std::string& url, const std::vector& headers, LLCurl::ResponderPtr, S32 time_out = 0, bool post = false); - + void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, S32 time_out = 0, bool post = false); + const char* getErrorBuffer(); std::stringstream& getInput() { return mInput; } std::stringstream& getHeaderOutput() { return mHeaderOutput; } LLIOPipe::buffer_ptr_t& getOutput() { return mOutput; } const LLChannelDescriptors& getChannels() { return mChannels; } - + void resetState(); static CURL* allocEasyHandle(); static void releaseEasyHandle(CURL* handle); -private: +private: friend class LLCurl; friend class LLCurl::Multi; CURL* mCurlEasyHandle; struct curl_slist* mHeaders; - + std::stringstream mRequest; LLChannelDescriptors mChannels; LLIOPipe::buffer_ptr_t mOutput; @@ -262,125 +245,70 @@ private: // Note: char*'s not strings since we pass pointers to curl std::vector mStrings; - - LLCurl::ResponderPtr mResponder; + + ResponderPtr mResponder; static std::set sFreeHandles; static std::set sActiveHandles; - static LLMutex* sHandleMutexp ; + static LLMutex* sHandleMutex; + static LLMutex* sMultiMutex; }; -class LLCurl::Multi +class LLCurl::Multi : public LLThread { LOG_CLASS(Multi); - - friend class LLCurlThread ; - -private: - ~Multi(); - - void markDead() ; - bool doPerform(); - public: typedef enum { - STATE_READY=0, - STATE_PERFORMING=1, - STATE_COMPLETED=2 + PERFORM_STATE_READY=0, + PERFORM_STATE_PERFORMING=1, + PERFORM_STATE_COMPLETED=2 } ePerformState; - Multi(F32 idle_time_out = 0.f); + Multi(); + ~Multi(); - LLCurl::Easy* allocEasy(); - bool addEasy(LLCurl::Easy* easy); - void removeEasy(LLCurl::Easy* easy); + Easy* allocEasy(); + bool addEasy(Easy* easy); - void lock() ; - void unlock() ; - - void setState(ePerformState state) ; - ePerformState getState() ; - - bool isCompleted() ; - bool isValid() {return mCurlMultiHandle != NULL && mValid;} - bool isDead() {return mDead;} - - bool waitToComplete() ; + void removeEasy(Easy* easy); S32 process(); + void perform(); + void doPerform(); + virtual void run(); + CURLMsg* info_read(S32* msgs_in_queue); S32 mQueued; S32 mErrorCount; + S32 mPerformState; + + LLCondition* mSignal; + bool mQuitting; + bool mThreaded; + private: - void easyFree(LLCurl::Easy*); - void cleanup(bool deleted = false) ; + void easyFree(Easy*); CURLM* mCurlMultiHandle; - typedef std::set easy_active_list_t; + typedef std::set easy_active_list_t; easy_active_list_t mEasyActiveList; - typedef std::map easy_active_map_t; + typedef std::map easy_active_map_t; easy_active_map_t mEasyActiveMap; - typedef std::set easy_free_list_t; + typedef std::set easy_free_list_t; easy_free_list_t mEasyFreeList; - - LLQueuedThread::handle_t mHandle ; - ePerformState mState; - - BOOL mDead ; - BOOL mValid ; - LLMutex* mMutexp ; - LLMutex* mDeletionMutexp ; - LLMutex* mEasyMutexp ; - LLFrameTimer mIdleTimer ; - F32 mIdleTimeOut; }; -class LLCurlThread : public LLQueuedThread +namespace boost { -public: - - class CurlRequest : public LLQueuedThread::QueuedRequest - { - protected: - virtual ~CurlRequest(); // use deleteRequest() - - public: - CurlRequest(handle_t handle, LLCurl::Multi* multi, LLCurlThread* curl_thread); - - /*virtual*/ bool processRequest(); - /*virtual*/ void finishRequest(bool completed); - - private: - // input - LLCurl::Multi* mMulti; - LLCurlThread* mCurlThread; - }; - friend class CurlRequest; - -public: - LLCurlThread(bool threaded = true) ; - virtual ~LLCurlThread() ; - - S32 update(F32 max_time_ms); - - void addMulti(LLCurl::Multi* multi) ; - void killMulti(LLCurl::Multi* multi) ; - -private: - bool doMultiPerform(LLCurl::Multi* multi) ; - void deleteMulti(LLCurl::Multi* multi) ; - void cleanupMulti(LLCurl::Multi* multi) ; -} ; - - -void intrusive_ptr_add_ref(LLCurl::Responder* p); -void intrusive_ptr_release(LLCurl::Responder* p); + void intrusive_ptr_add_ref(LLCurl::Responder* p); + void intrusive_ptr_release(LLCurl::Responder* p); +}; class LLCurlRequest @@ -410,6 +338,7 @@ private: LLCurl::Multi* mActiveMulti; S32 mActiveRequestCount; BOOL mProcessing; + U32 mThreadID; // debug }; class LLCurlEasyRequest @@ -427,11 +356,9 @@ public: void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); + void perform(); bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL); std::string getErrorString(); - bool isCompleted() {return mMulti->isCompleted() ;} - bool wait() { return mMulti->waitToComplete(); } - bool isValid() {return mMulti && mMulti->isValid(); } LLCurl::Easy* getEasy() const { return mEasy; } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 75ccc3818..2662eb349 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -25,7 +25,7 @@ */ #include "linden_common.h" -#include + #include "llhttpclient.h" #include "llassetstorage.h" @@ -40,9 +40,7 @@ #include "message.h" #include - const F32 HTTP_REQUEST_EXPIRY_SECS = 60.0f; -LLURLRequest::SSLCertVerifyCallback LLHTTPClient::mCertVerifyCallback = NULL; //////////////////////////////////////////////////////////////////////////// @@ -160,7 +158,7 @@ namespace fstream.seekg(0, std::ios::end); U32 fileSize = (U32)fstream.tellg(); fstream.seekg(0, std::ios::beg); - std::vector fileBuffer(fileSize); + std::vector fileBuffer(fileSize); //Mem leak fix'd fstream.read(&fileBuffer[0], fileSize); ostream.write(&fileBuffer[0], fileSize); fstream.close(); @@ -189,11 +187,9 @@ namespace LLVFile vfile(gVFS, mUUID, mAssetType, LLVFile::READ); S32 fileSize = vfile.getSize(); - U8* fileBuffer; - fileBuffer = new U8 [fileSize]; - vfile.read(fileBuffer, fileSize); - ostream.write((char*)fileBuffer, fileSize); - delete [] fileBuffer; + std::vector fileBuffer(fileSize); + vfile.read(&fileBuffer[0], fileSize); + ostream.write((char*)&fileBuffer[0], fileSize); eos = true; return STATUS_DONE; } @@ -202,23 +198,16 @@ namespace LLAssetType::EType mAssetType; }; - LLPumpIO* theClientPump = NULL; } -void LLHTTPClient::setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback) -{ - LLHTTPClient::mCertVerifyCallback = callback; -} - static void request( const std::string& url, LLURLRequest::ERequestAction method, Injector* body_injector, LLCurl::ResponderPtr responder, const F32 timeout = HTTP_REQUEST_EXPIRY_SECS, - const LLSD& headers = LLSD() - ) + const LLSD& headers = LLSD()) { if (!LLHTTPClient::hasPump()) { @@ -228,26 +217,12 @@ static void request( LLPumpIO::chain_t chain; LLURLRequest* req = new LLURLRequest(method, url); - if(!req->isValid())//failed - { - delete req ; - return ; - } - req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); - - - lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " " - << headers << llendl; - - // Insert custom headers if the caller sent any - if (headers.isMap()) - { - if (headers.has("Cookie")) - { - req->allowCookies(); - } + req->checkRootCertificate(true); + // Insert custom headers is the caller sent any + if (headers.isMap()) + { LLSD::map_const_iterator iter = headers.beginMap(); LLSD::map_const_iterator end = headers.endMap(); @@ -429,16 +404,11 @@ static LLSD blocking_request( { lldebugs << "blockingRequest of " << url << llendl; char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; - CURL* curlp = LLCurl::newEasyHandle(); - llassert_always(curlp != NULL) ; - + CURL* curlp = curl_easy_init(); LLHTTPBuffer http_buffer; std::string body_str; // other request method checks root cert first, we skip? - - // Apply configured proxy settings - LLProxy::getInstance()->applyProxySettings(curlp); // * Set curl handle options curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts @@ -447,7 +417,7 @@ static LLSD blocking_request( curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); - + // * Setup headers (don't forget to free them after the call!) curl_slist* headers_list = NULL; if (headers.isMap()) @@ -525,7 +495,7 @@ static LLSD blocking_request( } // * Cleanup - LLCurl::deleteEasyHandle(curlp); + curl_easy_cleanup(curlp); return response; } @@ -625,8 +595,7 @@ bool LLHTTPClient::hasPump() return theClientPump != NULL; } -//static -LLPumpIO& LLHTTPClient::getPump() +LLPumpIO &LLHTTPClient::getPump() { return *theClientPump; } diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index dda7d550f..b4541c99e 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -34,10 +34,11 @@ #include #include -#include "llurlrequest.h" + #include "llassettype.h" #include "llcurl.h" #include "lliopipe.h" +#include "llurlrequest.h" extern const F32 HTTP_REQUEST_EXPIRY_SECS; @@ -55,7 +56,6 @@ public: typedef LLCurl::Responder Responder; typedef LLCurl::ResponderPtr ResponderPtr; - /** @name non-blocking API */ //@{ static void head( @@ -153,12 +153,6 @@ public: ///< for testing static LLPumpIO &getPump(); ///< Hippo special - - static void setCertVerifyCallback(LLURLRequest::SSLCertVerifyCallback callback); - static LLURLRequest::SSLCertVerifyCallback getCertVerifyCallback() { return mCertVerifyCallback; } - -protected: - static LLURLRequest::SSLCertVerifyCallback mCertVerifyCallback; }; #endif // LL_LLHTTPCLIENT_H diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index f5e08f393..6b6fd445f 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -32,17 +32,17 @@ #include #include #include + #include "llcurl.h" -#include "llfasttimer.h" #include "llioutil.h" #include "llmemtype.h" -#include "llproxy.h" #include "llpumpio.h" #include "llsd.h" #include "llstring.h" #include "apr_env.h" #include "llapr.h" #include "llscopedvolatileaprpool.h" +#include "llfasttimer.h" static const U32 HTTP_STATUS_PIPE_ERROR = 499; /** @@ -66,7 +66,7 @@ public: ~LLURLRequestDetail(); std::string mURL; LLCurlEasyRequest* mCurlRequest; - LLIOPipe::buffer_ptr_t mResponseBuffer; + LLBufferArray* mResponseBuffer; LLChannelDescriptors mChannels; U8* mLastRead; U32 mBodyLimit; @@ -77,60 +77,24 @@ public: LLURLRequestDetail::LLURLRequestDetail() : mCurlRequest(NULL), + mResponseBuffer(NULL), mLastRead(NULL), mBodyLimit(0), mByteAccumulator(0), - mIsBodyLimitSet(false), - mSSLVerifyCallback(NULL) + mIsBodyLimitSet(false) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mCurlRequest = new LLCurlEasyRequest(); - - if(!mCurlRequest->isValid()) //failed. - { - delete mCurlRequest ; - mCurlRequest = NULL ; - } } LLURLRequestDetail::~LLURLRequestDetail() { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); delete mCurlRequest; + mResponseBuffer = NULL; mLastRead = NULL; } -void LLURLRequest::setSSLVerifyCallback(SSLCertVerifyCallback callback, void *param) -{ - mDetail->mSSLVerifyCallback = callback; - mDetail->mCurlRequest->setSSLCtxCallback(LLURLRequest::_sslCtxCallback, (void *)this); - mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, true); - mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, 2); -} - - -// _sslCtxFunction -// Callback function called when an SSL Context is created via CURL -// used to configure the context for custom cert validation - -CURLcode LLURLRequest::_sslCtxCallback(CURL * curl, void *sslctx, void *param) -{ - LLURLRequest *req = (LLURLRequest *)param; - if(req == NULL || req->mDetail->mSSLVerifyCallback == NULL) - { - SSL_CTX_set_cert_verify_callback((SSL_CTX *)sslctx, NULL, NULL); - return CURLE_OK; - } - SSL_CTX * ctx = (SSL_CTX *) sslctx; - // disable any default verification for server certs - SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); - // set the verification callback. - SSL_CTX_set_cert_verify_callback(ctx, req->mDetail->mSSLVerifyCallback, (void *)req); - // the calls are void - return CURLE_OK; - -} - /** * class LLURLRequest */ @@ -189,13 +153,19 @@ std::string LLURLRequest::getURL() const { return mDetail->mURL; } - void LLURLRequest::addHeader(const char* header) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mDetail->mCurlRequest->slist_append(header); } +void LLURLRequest::checkRootCertificate(bool check) +{ + mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, (check? TRUE : FALSE)); + mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, ""); +} + + void LLURLRequest::setBodyLimit(U32 size) { mDetail->mBodyLimit = size; @@ -240,9 +210,9 @@ void LLURLRequest::useProxy(bool use_proxy) } } - lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl; + LL_DEBUGS("Proxy") << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (!env_proxy.empty() ? env_proxy : "(null)") << LL_ENDL; - if (use_proxy) + if (use_proxy && !env_proxy.empty()) { mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy); } @@ -262,24 +232,12 @@ void LLURLRequest::allowCookies() mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, ""); } -//virtual -bool LLURLRequest::isValid() -{ - return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid(); -} - // virtual LLIOPipe::EStatus LLURLRequest::handleError( LLIOPipe::EStatus status, LLPumpIO* pump) { LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); - - if(!isValid()) - { - return STATUS_EXPIRED ; - } - if(mCompletionCallback && pump) { LLURLRequestComplete* complete = NULL; @@ -309,7 +267,8 @@ LLIOPipe::EStatus LLURLRequest::process_impl( LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); //llinfos << "LLURLRequest::process_impl()" << llendl; if (!buffer) return STATUS_ERROR; - + if (!mDetail) return STATUS_ERROR; //Seems to happen on occasion. Need to hunt down why. + // we're still waiting or prcessing, check how many // bytes we have accumulated. const S32 MIN_ACCUMULATION = 100000; @@ -348,7 +307,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( // *FIX: bit of a hack, but it should work. The configure and // callback method expect this information to be ready. - mDetail->mResponseBuffer = buffer; + mDetail->mResponseBuffer = buffer.get(); mDetail->mChannels = channels; if(!configure()) { @@ -367,10 +326,7 @@ LLIOPipe::EStatus LLURLRequest::process_impl( static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform"); { LLFastTimer t(FTM_URL_PERFORM); - if(!mDetail->mCurlRequest->wait()) - { - return status ; - } + mDetail->mCurlRequest->perform(); } while(1) @@ -465,12 +421,6 @@ void LLURLRequest::initialize() LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); mState = STATE_INITIALIZED; mDetail = new LLURLRequestDetail; - - if(!isValid()) - { - return ; - } - mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this); mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 1ba51a5ac..625f11afd 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -40,7 +40,6 @@ #include "llerror.h" #include "llcurl.h" - extern const std::string CONTEXT_REQUEST; extern const std::string CONTEXT_DEST_URI_SD_LABEL; extern const std::string CONTEXT_RESPONSE; @@ -143,9 +142,8 @@ public: * Set whether request will check that remote server * certificates are signed by a known root CA when using HTTPS. */ - void setSSLVerifyCallback(SSLCertVerifyCallback callback, void * param); + void checkRootCertificate(bool check); - /** * @brief Return at most size bytes of body. * @@ -190,14 +188,11 @@ public: */ void allowCookies(); - /*virtual*/ bool isValid() ; - public: /** * @brief Give this pipe a chance to handle a generated error */ virtual EStatus handleError(EStatus status, LLPumpIO* pump); - protected: /** @@ -223,11 +218,9 @@ protected: ERequestAction mAction; LLURLRequestDetail* mDetail; LLIOPipe::ptr_t mCompletionCallback; - S32 mRequestTransferedBytes; - S32 mResponseTransferedBytes; + S32 mRequestTransferedBytes; + S32 mResponseTransferedBytes; - static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param); - private: /** * @brief Initialize the object. Called during construction. diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 58389f932..fbc663347 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -945,7 +945,6 @@ char const* const _PREHASH_SysGPU = LLMessageStringTable::getInstance()->getStri char const* const _PREHASH_AvatarInterestsReply = LLMessageStringTable::getInstance()->getString("AvatarInterestsReply"); char const* const _PREHASH_StartLure = LLMessageStringTable::getInstance()->getString("StartLure"); char const* const _PREHASH_SysRAM = LLMessageStringTable::getInstance()->getString("SysRAM"); -char const* const _PREHASH_ObjectPosition = LLMessageStringTable::getInstance()->getString("ObjectPosition"); char const* const _PREHASH_SitPosition = LLMessageStringTable::getInstance()->getString("SitPosition"); char const* const _PREHASH_StartTime = LLMessageStringTable::getInstance()->getString("StartTime"); char const* const _PREHASH_BornOn = LLMessageStringTable::getInstance()->getString("BornOn"); @@ -1001,7 +1000,6 @@ char const* const _PREHASH_SnapshotID = LLMessageStringTable::getInstance()->get char const* const _PREHASH_Aspect = LLMessageStringTable::getInstance()->getString("Aspect"); char const* const _PREHASH_ParamSize = LLMessageStringTable::getInstance()->getString("ParamSize"); char const* const _PREHASH_VoteCast = LLMessageStringTable::getInstance()->getString("VoteCast"); -char const* const _PREHASH_CastsShadows = LLMessageStringTable::getInstance()->getString("CastsShadows"); char const* const _PREHASH_EveryoneMask = LLMessageStringTable::getInstance()->getString("EveryoneMask"); char const* const _PREHASH_ObjectSpinUpdate = LLMessageStringTable::getInstance()->getString("ObjectSpinUpdate"); char const* const _PREHASH_MaturePublish = LLMessageStringTable::getInstance()->getString("MaturePublish"); @@ -1050,7 +1048,6 @@ char const* const _PREHASH_SimIP = LLMessageStringTable::getInstance()->getStrin char const* const _PREHASH_GodID = LLMessageStringTable::getInstance()->getString("GodID"); char const* const _PREHASH_TeleportMinPrice = LLMessageStringTable::getInstance()->getString("TeleportMinPrice"); char const* const _PREHASH_VoteItem = LLMessageStringTable::getInstance()->getString("VoteItem"); -char const* const _PREHASH_ObjectRotation = LLMessageStringTable::getInstance()->getString("ObjectRotation"); char const* const _PREHASH_SitRotation = LLMessageStringTable::getInstance()->getString("SitRotation"); char const* const _PREHASH_SnapSelection = LLMessageStringTable::getInstance()->getString("SnapSelection"); char const* const _PREHASH_SoundTrigger = LLMessageStringTable::getInstance()->getString("SoundTrigger"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 48ad2c743..b4523ea8e 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -945,7 +945,6 @@ extern char const* const _PREHASH_SysGPU; extern char const* const _PREHASH_AvatarInterestsReply; extern char const* const _PREHASH_StartLure; extern char const* const _PREHASH_SysRAM; -extern char const* const _PREHASH_ObjectPosition; extern char const* const _PREHASH_SitPosition; extern char const* const _PREHASH_StartTime; extern char const* const _PREHASH_BornOn; @@ -1001,7 +1000,6 @@ extern char const* const _PREHASH_SnapshotID; extern char const* const _PREHASH_Aspect; extern char const* const _PREHASH_ParamSize; extern char const* const _PREHASH_VoteCast; -extern char const* const _PREHASH_CastsShadows; extern char const* const _PREHASH_EveryoneMask; extern char const* const _PREHASH_ObjectSpinUpdate; extern char const* const _PREHASH_MaturePublish; @@ -1050,7 +1048,6 @@ extern char const* const _PREHASH_SimIP; extern char const* const _PREHASH_GodID; extern char const* const _PREHASH_TeleportMinPrice; extern char const* const _PREHASH_VoteItem; -extern char const* const _PREHASH_ObjectRotation; extern char const* const _PREHASH_SitRotation; extern char const* const _PREHASH_SnapSelection; extern char const* const _PREHASH_SoundTrigger; diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index b58d0c95f..4ad2a3fef 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -239,7 +239,7 @@ public: std::string getHoverText() const { return mHoverText; }; std::string getHoverLink() const { return mHoverLink; }; - std::string getMediaName() const { return mMediaName; }; + const std::string& getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; // Crash the plugin. If you use this outside of a testbed, you will be punished. diff --git a/indra/llprimitive/object_flags.h b/indra/llprimitive/object_flags.h index c873f502b..f48b97d58 100644 --- a/indra/llprimitive/object_flags.h +++ b/indra/llprimitive/object_flags.h @@ -2,31 +2,25 @@ * @file object_flags.h * @brief Flags for object creation and transmission * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -34,43 +28,47 @@ #define LL_OBJECT_FLAGS_H // downstream flags from sim->viewer -const U32 FLAGS_USE_PHYSICS = 0x00000001; -const U32 FLAGS_CREATE_SELECTED = 0x00000002; -const U32 FLAGS_OBJECT_MODIFY = 0x00000004; -const U32 FLAGS_OBJECT_COPY = 0x00000008; -const U32 FLAGS_OBJECT_ANY_OWNER = 0x00000010; -const U32 FLAGS_OBJECT_YOU_OWNER = 0x00000020; -const U32 FLAGS_SCRIPTED = 0x00000040; -const U32 FLAGS_HANDLE_TOUCH = 0x00000080; -const U32 FLAGS_OBJECT_MOVE = 0x00000100; -const U32 FLAGS_TAKES_MONEY = 0x00000200; -const U32 FLAGS_PHANTOM = 0x00000400; -const U32 FLAGS_INVENTORY_EMPTY = 0x00000800; +const U32 FLAGS_USE_PHYSICS = (1U << 0); +const U32 FLAGS_CREATE_SELECTED = (1U << 1); +const U32 FLAGS_OBJECT_MODIFY = (1U << 2); +const U32 FLAGS_OBJECT_COPY = (1U << 3); +const U32 FLAGS_OBJECT_ANY_OWNER = (1U << 4); +const U32 FLAGS_OBJECT_YOU_OWNER = (1U << 5); +const U32 FLAGS_SCRIPTED = (1U << 6); +const U32 FLAGS_HANDLE_TOUCH = (1U << 7); +const U32 FLAGS_OBJECT_MOVE = (1U << 8); +const U32 FLAGS_TAKES_MONEY = (1U << 9); +const U32 FLAGS_PHANTOM = (1U << 10); +const U32 FLAGS_INVENTORY_EMPTY = (1U << 11); -const U32 FLAGS_JOINT_HINGE = 0x00001000; -const U32 FLAGS_JOINT_P2P = 0x00002000; -const U32 FLAGS_JOINT_LP2P = 0x00004000; -// const U32 FLAGS_JOINT_WHEEL = 0x00008000; -const U32 FLAGS_INCLUDE_IN_SEARCH = 0x00008000; +const U32 FLAGS_AFFECTS_NAVMESH = (1U << 12); +const U32 FLAGS_CHARACTER = (1U << 13); +const U32 FLAGS_VOLUME_DETECT = (1U << 14); +const U32 FLAGS_INCLUDE_IN_SEARCH = (1U << 15); -const U32 FLAGS_ALLOW_INVENTORY_DROP = 0x00010000; -const U32 FLAGS_OBJECT_TRANSFER = 0x00020000; -const U32 FLAGS_OBJECT_GROUP_OWNED = 0x00040000; -//const U32 FLAGS_OBJECT_YOU_OFFICER = 0x00080000; +const U32 FLAGS_ALLOW_INVENTORY_DROP = (1U << 16); +const U32 FLAGS_OBJECT_TRANSFER = (1U << 17); +const U32 FLAGS_OBJECT_GROUP_OWNED = (1U << 18); +//const U32 FLAGS_UNUSED_000 = (1U << 19); // was FLAGS_OBJECT_YOU_OFFICER -const U32 FLAGS_CAMERA_DECOUPLED = 0x00100000; -const U32 FLAGS_ANIM_SOURCE = 0x00200000; -const U32 FLAGS_CAMERA_SOURCE = 0x00400000; +const U32 FLAGS_CAMERA_DECOUPLED = (1U << 20); +const U32 FLAGS_ANIM_SOURCE = (1U << 21); +const U32 FLAGS_CAMERA_SOURCE = (1U << 22); -const U32 FLAGS_CAST_SHADOWS = 0x00800000; +//const U32 FLAGS_UNUSED_001 = (1U << 23); // was FLAGS_CAST_SHADOWS -const U32 FLAGS_OBJECT_OWNER_MODIFY = 0x10000000; +//const U32 FLAGS_UNUSED_002 = (1U << 24); +//const U32 FLAGS_UNUSED_003 = (1U << 25); +//const U32 FLAGS_UNUSED_004 = (1U << 26); +//const U32 FLAGS_UNUSED_005 = (1U << 27); -const U32 FLAGS_TEMPORARY_ON_REZ = 0x20000000; -const U32 FLAGS_TEMPORARY = 0x40000000; -const U32 FLAGS_ZLIB_COMPRESSED = 0x80000000; +const U32 FLAGS_OBJECT_OWNER_MODIFY = (1U << 28); -const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; +const U32 FLAGS_TEMPORARY_ON_REZ = (1U << 29); +const U32 FLAGS_TEMPORARY = (1U << 30); +//const U32 FLAGS_UNUSED_007 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED + +const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; typedef enum e_havok_joint_type { diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 6d7054e7e..42139dfec 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -2001,7 +2001,6 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) void LLImageGL::setCategory(S32 category) { -#if 0 //turn this off temporarily because it is not in use now. if(!gAuditTexture) { return ; @@ -2022,7 +2021,6 @@ void LLImageGL::setCategory(S32 category) mCategory = -1 ; } } -#endif } //for debug use @@ -2053,14 +2051,16 @@ S32 LLImageGL::getTextureCounterIndex(U32 val) void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category) { sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; - sTextureMemByCategory[category] += (S32)val * ncomponents ; + if(category > -1) + sTextureMemByCategory[category] += (S32)val * ncomponents ; } //static void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category) { sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; - sTextureMemByCategory[category] += (S32)val * ncomponents ; + if(category > -1) + sTextureMemByCategory[category] -= (S32)val * ncomponents ; } void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 25e775c1e..846badc60 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -33,34 +33,247 @@ #include "linden_common.h" #include "llpostprocess.h" -#include "llglslshader.h" -#include "llsdserialize.h" -#include "llrender.h" -#include "llvertexbuffer.h" #include "lldir.h" +#include "llgl.h" +#include "llglslshader.h" +#include "llrender.h" +#include "llsdserialize.h" +#include "llsdutil.h" +#include "llsdutil_math.h" +#include "llvertexbuffer.h" +#include "llfasttimer.h" + extern LLGLSLShader gPostColorFilterProgram; extern LLGLSLShader gPostNightVisionProgram; extern LLGLSLShader gPostGaussianBlurProgram; +extern LLGLSLShader gPostPosterizeProgram; static const unsigned int NOISE_SIZE = 512; -/// CALCULATING LUMINANCE (Using NTSC lum weights) -/// http://en.wikipedia.org/wiki/Luma_%28video%29 -static const float LUMINANCE_R = 0.299f; -static const float LUMINANCE_G = 0.587f; -static const float LUMINANCE_B = 0.114f; - static const char * const XML_FILENAME = "postprocesseffects.xml"; -LLPostProcess::LLPostProcess(void) : - mVBO(NULL), - mAllEffects(LLSD::emptyMap()), - mScreenWidth(1), mScreenHeight(1) +template<> LLSD LLPostProcessShader::LLShaderSetting::getDefaultValue() { - mSceneRenderTexture = NULL ; - mNoiseTexture = NULL ; - + return mDefault.getValue(); +} +template<> void LLPostProcessShader::LLShaderSetting::setValue(const LLSD& value) +{ + mValue = ll_vector4_from_sd(value); +} + +LLSD LLPostProcessShader::getDefaults() +{ + LLSD defaults; + for(std::vector::iterator it=mSettings.begin();it!=mSettings.end();++it) + { + defaults[(*it)->mSettingName]=(*it)->getDefaultValue(); + } + return defaults; +} +void LLPostProcessShader::loadSettings(const LLSD& settings) +{ + for(std::vector::iterator it=mSettings.begin();it!=mSettings.end();++it) + { + LLSD value = settings[(*it)->mSettingName]; + (*it)->setValue(value); + } +} + +class LLColorFilterShader : public LLPostProcessShader +{ +private: + LLShaderSetting mEnabled; + LLShaderSetting mGamma, mBrightness, mContrast, mSaturation; + LLShaderSetting mContrastBase; +public: + LLColorFilterShader() : + mEnabled("enable_color_filter",false), + mGamma("gamma",1.f), + mBrightness("brightness",1.f), + mContrast("contrast",1.f), + mSaturation("saturation",1.f), + mContrastBase("contrast_base",LLVector4(1.f,1.f,1.f,0.5f)) + { + mSettings.push_back(&mEnabled); + mSettings.push_back(&mGamma); + mSettings.push_back(&mBrightness); + mSettings.push_back(&mContrast); + mSettings.push_back(&mSaturation); + mSettings.push_back(&mContrastBase); + } + + bool isEnabled() { return mEnabled && gPostColorFilterProgram.mProgramObject; } + S32 getColorChannel() { return 0; } + S32 getDepthChannel() { return -1; } + + QuadType bind() + { + if(!isEnabled()) + return QUAD_NONE; + + /// CALCULATING LUMINANCE (Using NTSC lum weights) + /// http://en.wikipedia.org/wiki/Luma_%28video%29 + static const float LUMINANCE_R = 0.299f; + static const float LUMINANCE_G = 0.587f; + static const float LUMINANCE_B = 0.114f; + + gPostColorFilterProgram.bind(); + + gPostColorFilterProgram.uniform1f("gamma", mGamma); + gPostColorFilterProgram.uniform1f("brightness", mBrightness); + gPostColorFilterProgram.uniform1f("contrast", mContrast); + float baseI = (mContrastBase.mValue[VX] + mContrastBase.mValue[VY] + mContrastBase.mValue[VZ]) / 3.0f; + baseI = mContrastBase.mValue[VW] / ((baseI < 0.001f) ? 0.001f : baseI); + float baseR = mContrastBase.mValue[VX] * baseI; + float baseG = mContrastBase.mValue[VY] * baseI; + float baseB = mContrastBase.mValue[VZ] * baseI; + gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV); + gPostColorFilterProgram.uniform1f("saturation", mSaturation); + gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV); + return QUAD_NORMAL; + } + bool draw(U32 pass) {return pass == 1;} + void unbind() + { + gPostColorFilterProgram.unbind(); + } +}; + +class LLNightVisionShader : public LLPostProcessShader +{ +private: + LLShaderSetting mEnabled; + LLShaderSetting mBrightnessMult, mNoiseStrength; +public: + LLNightVisionShader() : + mEnabled("enable_night_vision",false), + mBrightnessMult("brightness_multiplier",3.f), + mNoiseStrength("noise_strength",.4f) + { + mSettings.push_back(&mEnabled); + mSettings.push_back(&mBrightnessMult); + mSettings.push_back(&mNoiseStrength); + } + bool isEnabled() { return mEnabled && gPostNightVisionProgram.mProgramObject; } + S32 getColorChannel() { return 0; } + S32 getDepthChannel() { return -1; } + QuadType bind() + { + if(!isEnabled()) + return QUAD_NONE; + + gPostNightVisionProgram.bind(); + + LLPostProcess::getInstance()->bindNoise(1); + + gPostNightVisionProgram.uniform1f("brightMult", mBrightnessMult); + gPostNightVisionProgram.uniform1f("noiseStrength", mNoiseStrength); + + return QUAD_NOISE; + + } + bool draw(U32 pass) {return pass == 1;} + void unbind() + { + gPostNightVisionProgram.unbind(); + } +}; + +class LLGaussBlurShader : public LLPostProcessShader +{ +private: + LLShaderSetting mEnabled; + LLShaderSetting mNumPasses; + GLint mPassLoc; +public: + LLGaussBlurShader() : + mEnabled("enable_gauss_blur",false), + mNumPasses("gauss_blur_passes",2), + mPassLoc(0) + { + mSettings.push_back(&mEnabled); + mSettings.push_back(&mNumPasses); + } + bool isEnabled() { return mEnabled && mNumPasses && gPostGaussianBlurProgram.mProgramObject; } + S32 getColorChannel() { return 0; } + S32 getDepthChannel() { return -1; } + QuadType bind() + { + if(!isEnabled()) + return QUAD_NONE; + + gPostGaussianBlurProgram.bind(); + + mPassLoc = gPostGaussianBlurProgram.getUniformLocation("horizontalPass"); + + return QUAD_NORMAL; + } + bool draw(U32 pass) + { + if((S32)pass > mNumPasses*2) + return false; + glUniform1iARB(mPassLoc, (pass-1) % 2); + return true; + } + void unbind() + { + gPostGaussianBlurProgram.unbind(); + } +}; + +class LLPosterizeShader : public LLPostProcessShader +{ +private: + LLShaderSetting mEnabled; + LLShaderSetting mNumLayers; +public: + LLPosterizeShader() : + mEnabled("enable_posterize",false), + mNumLayers("posterize_layers",2) + { + mSettings.push_back(&mEnabled); + mSettings.push_back(&mNumLayers); + } + bool isEnabled() { return mEnabled && gPostPosterizeProgram.mProgramObject; } + S32 getColorChannel() { return 0; } + S32 getDepthChannel() { return -1; } + QuadType bind() + { + if(!isEnabled()) + return QUAD_NONE; + + gPostPosterizeProgram.bind(); + + gPostPosterizeProgram.uniform1i("layerCount", mNumLayers); + + return QUAD_NORMAL; + } + bool draw(U32 pass) + { + return pass == 1; + } + void unbind() + { + gPostPosterizeProgram.unbind(); + } +}; + +LLPostProcess::LLPostProcess(void) : + mVBO(NULL), + mDepthTexture(0), + mNoiseTexture(NULL), + mScreenWidth(0), + mScreenHeight(0), + mNoiseTextureScale(0.f), + mSelectedEffectInfo(LLSD::emptyMap()), + mAllEffectInfo(LLSD::emptyMap()) +{ + mShaders.push_back(new LLColorFilterShader()); + mShaders.push_back(new LLNightVisionShader()); + mShaders.push_back(new LLGaussBlurShader()); + mShaders.push_back(new LLPosterizeShader()); + /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.*/ std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; @@ -71,99 +284,43 @@ LLPostProcess::LLPostProcess(void) : { LLPointer parser = new LLSDXMLParser(); - parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED); + parser->parse(effectsXML, mAllEffectInfo, LLSDSerialize::SIZE_UNLIMITED); } - if (!mAllEffects.has("default")) + if (!mAllEffectInfo.has("default")) + mAllEffectInfo["default"] = LLSD::emptyMap(); + + LLSD& defaults = mAllEffectInfo["default"]; + + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) { - LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap()); - - /*defaultEffect["enable_night_vision"] = LLSD::Boolean(false); - defaultEffect["enable_color_filter"] = LLSD::Boolean(false);*/ - - /// NVG Defaults - defaultEffect["brightness_multiplier"] = 3.0; - defaultEffect["noise_size"] = 25.0; - defaultEffect["noise_strength"] = 0.4; - - // TODO BTest potentially add this to tweaks? - mNoiseTextureScale = 1.0f; - - /// Color Filter Defaults - defaultEffect["gamma"] = 1.0; - defaultEffect["brightness"] = 1.0; - defaultEffect["contrast"] = 1.0; - defaultEffect["saturation"] = 1.0; - - LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray()); - contrastBase.append(1.0); - contrastBase.append(1.0); - contrastBase.append(1.0); - contrastBase.append(0.5); - - defaultEffect["gauss_blur_passes"] = 2; + LLSD shader_defaults = (*it)->getDefaults(); + for (LLSD::map_const_iterator it2 = defaults.beginMap();it2 != defaults.endMap();++it2) + { + if(!defaults.has(it2->first)) + defaults[it2->first]=it2->second; + } + } + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + { + (*it)->loadSettings(defaults); } - setSelectedEffect("default"); - // */ } LLPostProcess::~LLPostProcess(void) { - invalidate() ; -} - -/*static*/void LLPostProcess::cleanupClass() -{ - if(instanceExists()) - getInstance()->invalidate() ; -} - -void LLPostProcess::setSelectedEffect(std::string const & effectName) -{ - mSelectedEffectName = effectName; - static_cast(tweaks) = mAllEffects[effectName]; -} - -void LLPostProcess::saveEffect(std::string const & effectName) -{ - mAllEffects[effectName] = tweaks; - - std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); - //llinfos << "Saving PostProcess Effects settings to " << pathName << llendl; - - llofstream effectsXML(pathName); - - LLPointer formatter = new LLSDXMLFormatter(); - - formatter->format(mAllEffects, effectsXML); -} -void LLPostProcess::invalidate() -{ - mSceneRenderTexture = NULL ; - mNoiseTexture = NULL ; - mVBO = NULL ; -} - -void LLPostProcess::apply(unsigned int width, unsigned int height) -{ - if(shadersEnabled()) - { - if (mVBO.isNull() || width != mScreenWidth || height != mScreenHeight) - { - initialize(width, height); - } - doEffects(); - } + destroyGL() ; } void LLPostProcess::initialize(unsigned int width, unsigned int height) { - invalidate(); + destroyGL(); mScreenWidth = width; mScreenHeight = height; - createScreenTexture(); + createScreenTextures(); + createNoiseTexture(); //Setup our VBO. { @@ -185,127 +342,129 @@ void LLPostProcess::initialize(unsigned int width, unsigned int height) mVBO->flush(); } - - checkError(); - createNoiseTexture(); - checkError(); + stop_glerror(); } -inline bool LLPostProcess::shadersEnabled(void) +void LLPostProcess::createScreenTextures() { - return (tweaks.useColorFilter().asBoolean() || - tweaks.useNightVisionShader().asBoolean() || - tweaks.useGaussBlurFilter().asBoolean() ); -} + const LLTexUnit::eTextureType type = LLTexUnit::TT_RECT_TEXTURE; -void LLPostProcess::applyShaders(void) -{ - bool copy_buffer = false; - if (tweaks.useColorFilter()) + mRenderTarget[0].allocate(mScreenWidth,mScreenHeight,GL_RGBA,FALSE,FALSE,type,FALSE); + if(mRenderTarget[0].getFBO())//Only need pingpong between two rendertargets if FBOs are supported. + mRenderTarget[1].allocate(mScreenWidth,mScreenHeight,GL_RGBA,FALSE,FALSE,type,FALSE); + stop_glerror(); + + if(mDepthTexture) + LLImageGL::deleteTextures(type, 0, 0, 1, &mDepthTexture, true); + + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) { - applyColorFilterShader(); - checkError(); - copy_buffer = true; - } - if (tweaks.useGaussBlurFilter()) - { - /// If any of the above shaders have been called update the frame buffer; - if (copy_buffer) - copyFrameBuffer(); - applyGaussBlurShader(); - checkError(); - copy_buffer = true; - } - if (tweaks.useNightVisionShader()) - { - /// If any of the above shaders have been called update the frame buffer; - if (copy_buffer) - copyFrameBuffer(); - applyNightVisionShader(); - checkError(); - copy_buffer = true; - } -} - -void LLPostProcess::applyColorFilterShader(void) -{ - if(gPostColorFilterProgram.mProgramObject == 0) - return; - - gPostColorFilterProgram.bind(); - - gGL.getTexUnit(0)->bind(mSceneRenderTexture); - - gPostColorFilterProgram.uniform1f("gamma", tweaks.getGamma()); - gPostColorFilterProgram.uniform1f("brightness", tweaks.getBrightness()); - gPostColorFilterProgram.uniform1f("contrast", tweaks.getContrast()); - float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f; - baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI); - float baseR = tweaks.getContrastBaseR() * baseI; - float baseG = tweaks.getContrastBaseG() * baseI; - float baseB = tweaks.getContrastBaseB() * baseI; - gPostColorFilterProgram.uniform3fv("contrastBase", 1, LLVector3(baseR, baseG, baseB).mV); - gPostColorFilterProgram.uniform1f("saturation", tweaks.getSaturation()); - gPostColorFilterProgram.uniform3fv("lumWeights", 1, LLVector3(LUMINANCE_R, LUMINANCE_G, LUMINANCE_B).mV); - - /// Draw a screen space quad - drawOrthoQuad(QUAD_NORMAL); - gPostColorFilterProgram.unbind(); -} - -void LLPostProcess::applyNightVisionShader(void) -{ - if(gPostNightVisionProgram.mProgramObject == 0) - return; - - gPostNightVisionProgram.bind(); - - gGL.getTexUnit(0)->bind(mSceneRenderTexture); - gGL.getTexUnit(1)->bind(mNoiseTexture); - - gPostNightVisionProgram.uniform1f("brightMult", tweaks.getBrightMult()); - gPostNightVisionProgram.uniform1f("noiseStrength", tweaks.getNoiseStrength()); - mNoiseTextureScale = 0.001f + ((100.f - tweaks.getNoiseSize()) / 100.f); - mNoiseTextureScale *= (mScreenHeight / NOISE_SIZE); - - /// Draw a screen space quad - drawOrthoQuad(QUAD_NOISE); - gPostNightVisionProgram.unbind(); -} - -void LLPostProcess::applyGaussBlurShader(void) -{ - int pass_count = tweaks.getGaussBlurPasses(); - if(!pass_count || gPostGaussianBlurProgram.mProgramObject == 0) - return; - - gPostGaussianBlurProgram.bind(); - - gGL.getTexUnit(0)->bind(mSceneRenderTexture); - - GLint horiz_pass = gPostGaussianBlurProgram.getUniformLocation("horizontalPass"); - for(int i = 0;igetDepthChannel()>=0) { - if(i || j) - copyFrameBuffer(); - glUniform1iARB(horiz_pass, j); - drawOrthoQuad(QUAD_NORMAL); + LLImageGL::generateTextures(type, GL_DEPTH_COMPONENT24, 1, &mDepthTexture); + gGL.getTexUnit(0)->bindManual(type, mDepthTexture); + LLImageGL::setManualImage(LLTexUnit::getInternalType(type), 0, GL_DEPTH_COMPONENT24, mScreenWidth, mScreenHeight, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + stop_glerror(); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + stop_glerror(); + break; + } + } +} + +void LLPostProcess::createNoiseTexture() +{ + std::vector buffer(NOISE_SIZE * NOISE_SIZE); + for (unsigned int i = 0; i < NOISE_SIZE; i++){ + for (unsigned int k = 0; k < NOISE_SIZE; k++){ + buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f); + } + } + + mNoiseTexture = new LLImageGL(FALSE) ; + if(mNoiseTexture->createGLTexture()) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture->getTexName()); + LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); + stop_glerror(); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); + stop_glerror(); + } +} + +void LLPostProcess::destroyGL() +{ + mRenderTarget[0].release(); + mRenderTarget[1].release(); + if(mDepthTexture) + LLImageGL::deleteTextures(LLTexUnit::TT_RECT_TEXTURE, 0, 0, 1, &mDepthTexture, true); + mDepthTexture=0; + mNoiseTexture = NULL ; + mVBO = NULL ; +} + +/*static*/void LLPostProcess::cleanupClass() +{ + if(instanceExists()) + getInstance()->destroyGL() ; +} + +void LLPostProcess::copyFrameBuffer() +{ + mRenderTarget[!!mRenderTarget[0].getFBO()].bindTexture(0,0); + glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,0,0,mScreenWidth, mScreenHeight); + + if(mDepthTexture) + { + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + { + if((*it)->isEnabled() && (*it)->getDepthChannel()>=0) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture); + glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,0,0,mScreenWidth, mScreenHeight); + break; + } + } + } + +} + +void LLPostProcess::bindNoise(U32 channel) +{ + gGL.getTexUnit(channel)->bind(mNoiseTexture); +} + +void LLPostProcess::renderEffects(unsigned int width, unsigned int height) +{ + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + { + if((*it)->isEnabled()) + { + if (mVBO.isNull() || width != mScreenWidth || height != mScreenHeight) + { + initialize(width, height); + } + doEffects(); + return; } } - gPostGaussianBlurProgram.unbind(); } void LLPostProcess::doEffects(void) { LLVertexBuffer::unbind(); + mNoiseTextureScale = 0.001f + ((100.f - mSelectedEffectInfo["noise_size"].asFloat()) / 100.f); + mNoiseTextureScale *= (mScreenHeight / NOISE_SIZE); + /// Copy the screen buffer to the render texture copyFrameBuffer(); + stop_glerror(); //Disable depth. Set blendmode to replace. - LLGLDepthTest depth(GL_FALSE); + LLGLDepthTest depth(GL_FALSE,GL_FALSE); LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_REPLACE); @@ -319,7 +478,6 @@ void LLPostProcess::doEffects(void) gGL.loadIdentity(); applyShaders(); - checkError(); LLGLSLShader::bindNoShader(); @@ -333,13 +491,46 @@ void LLPostProcess::doEffects(void) gGL.setSceneBlendType(LLRender::BT_ALPHA); //Restore blendstate. Alpha is ASSUMED for hud/ui render, etc. gGL.getTexUnit(1)->disable(); - checkError(); } -void LLPostProcess::copyFrameBuffer() +void LLPostProcess::applyShaders(void) { - gGL.getTexUnit(0)->bindManual(mSceneRenderTexture->getTarget(), mSceneRenderTexture->getTexName()); - glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, mScreenWidth, mScreenHeight, 0); + QuadType quad; + bool primary_rendertarget = 1; + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + { + if((quad = (*it)->bind()) != QUAD_NONE) + { + S32 color_channel = (*it)->getColorChannel(); + S32 depth_channel = (*it)->getDepthChannel(); + + if(depth_channel >= 0) + gGL.getTexUnit(depth_channel)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mDepthTexture); + + U32 pass = 1; + + while((*it)->draw(pass++)) + { + mRenderTarget[!primary_rendertarget].bindTarget(); + + if(color_channel >= 0) + mRenderTarget[mRenderTarget[0].getFBO() ? primary_rendertarget : !primary_rendertarget].bindTexture(0,color_channel); + + drawOrthoQuad(quad); + mRenderTarget[!primary_rendertarget].flush(); + if(mRenderTarget[0].getFBO()) + primary_rendertarget = !primary_rendertarget; + } + (*it)->unbind(); + } + } + //Only need to copy to framebuffer if FBOs are supported, else we've already been drawing to the framebuffer to begin with. + if(mRenderTarget[0].getFBO()) + { + //copyContentsToFramebuffer also binds the main framebuffer. + LLRenderTarget::copyContentsToFramebuffer(mRenderTarget[primary_rendertarget],0,0,mScreenWidth,mScreenHeight,0,0,mScreenWidth,mScreenHeight,GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + stop_glerror(); } void LLPostProcess::drawOrthoQuad(QuadType type) @@ -364,64 +555,59 @@ void LLPostProcess::drawOrthoQuad(QuadType type) mVBO->drawArrays(LLRender::TRIANGLE_STRIP, 0, 4); } -void LLPostProcess::createScreenTexture() +void LLPostProcess::setSelectedEffect(std::string const & effectName) { - std::vector data(mScreenWidth * mScreenHeight * 3, 0) ; - - mSceneRenderTexture = new LLImageGL(FALSE) ; - if(mSceneRenderTexture->createGLTexture()) + mSelectedEffectName = effectName; + mSelectedEffectInfo = mAllEffectInfo[effectName]; + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, mSceneRenderTexture->getTexName()); - LLImageGL::setManualImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, mScreenWidth, mScreenHeight, GL_RGB, GL_UNSIGNED_BYTE, &data[0]); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + (*it)->loadSettings(mSelectedEffectInfo); } } -void LLPostProcess::createNoiseTexture() -{ - std::vector buffer(NOISE_SIZE * NOISE_SIZE); - for (unsigned int i = 0; i < NOISE_SIZE; i++){ - for (unsigned int k = 0; k < NOISE_SIZE; k++){ - buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f); - } - } - - mNoiseTexture = new LLImageGL(FALSE) ; - if(mNoiseTexture->createGLTexture()) - { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseTexture->getTexName()); - LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); - } -} - -bool LLPostProcess::checkError(void) +void LLPostProcess::setSelectedEffectValue(std::string const & setting, LLSD& value) { - GLenum glErr; - bool retCode = false; - - glErr = glGetError(); - while (glErr != GL_NO_ERROR) - { - // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl; - char const * err_str_raw = (const char *) gluErrorString(glErr); - - if(err_str_raw == NULL) - { - std::ostringstream err_builder; - err_builder << "unknown error number " << glErr; - mShaderErrorString = err_builder.str(); - } - else - { - mShaderErrorString = err_str_raw; - } - - retCode = true; - glErr = glGetError(); - } - return retCode; + char buf[256]; + S32 elem=0; + if(sscanf(setting.c_str(),"%255[^[][%d]", buf, &elem) == 2) + { + mSelectedEffectInfo[std::string(buf)][elem] = value; + } + else + { + mSelectedEffectInfo[setting] = value; + } + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + { + (*it)->loadSettings(mSelectedEffectInfo); + } } +void LLPostProcess::resetSelectedEffect() +{ + if(!llsd_equals(mAllEffectInfo[mSelectedEffectName], mSelectedEffectInfo)) + { + mSelectedEffectInfo = mAllEffectInfo[mSelectedEffectName]; + for(std::list >::iterator it=mShaders.begin();it!=mShaders.end();++it) + { + (*it)->loadSettings(mSelectedEffectInfo); + } + } +} + +void LLPostProcess::saveEffectAs(std::string const & effectName) +{ + mAllEffectInfo[effectName] = mSelectedEffectInfo; + + std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); + //llinfos << "Saving PostProcess Effects settings to " << pathName << llendl; + + llofstream effectsXML(pathName); + + LLPointer formatter = new LLSDXMLFormatter(); + + formatter->format(mAllEffectInfo, effectsXML); +} + + + diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h index 459fa6851..830598a92 100644 --- a/indra/llrender/llpostprocess.h +++ b/indra/llrender/llpostprocess.h @@ -34,189 +34,123 @@ #define LL_POSTPROCESS_H #include -#include -#include "llgl.h" -#include "llglheaders.h" +#include "llsd.h" +#include "llrendertarget.h" + +class LLSD; + +typedef enum _QuadType { + QUAD_NONE, + QUAD_NORMAL, + QUAD_NOISE +} QuadType; + +//LLPostProcessShader is an attempt to encapsulate the shaders a little better. +class LLPostProcessShader : public LLRefCount //Abstract. PostProcess shaders derive off of this common base. +{ +protected: + //LLShaderSetting is used to associate key names to member variables to avoid LLSD lookups when drawing. + //It also facilitates automating the assigning of defaults to, as well as parsing from, the effects LLSD list. + //This replaces the entire old PostProcessTweaks structure. More will be done in the future to move into a more + //xml-driven configuration. + struct LLShaderSettingBase + { + LLShaderSettingBase(const char* name) : mSettingName(name) {} + const char* mSettingName; //LLSD key names as found in postprocesseffects.xml. eg 'contrast_base' + virtual LLSD getDefaultValue() = 0; //Converts the member variable as an LLSD. Used to set defaults absent in postprocesseffects.xml + virtual void setValue(const LLSD& value) = 0; //Connects the LLSD element to the member variable. Used when loading effects (such as default) + }; + template + struct LLShaderSetting : public LLShaderSettingBase + { + LLShaderSetting(const char* setting_name, T def) : LLShaderSettingBase(setting_name), mValue(def), mDefault(def) {} + T mValue; //The member variable mentioned above. + T mDefault; //Set via ctor. Value is inserted into the defaults LLSD list if absent from postprocesseffects.xml + LLSD getDefaultValue() { return mDefault; } //See LLShaderSettingBase::getDefaultValue + void setValue(const LLSD& value) { mValue = value; } //See LLShaderSettingBase::setValue + operator T() { return mValue; } //Typecast operator overload so this object can be handled as if it was whatever T represents. + }; + std::vector mSettings; //Contains a list of all the 'settings' this shader uses. Manually add via push_back in ctor. +public: + virtual ~LLPostProcessShader() {}; + virtual bool isEnabled() = 0; //Returning false avoids bind/draw/unbind calls. If no shaders are enabled, framebuffer copying is skipped. + virtual S32 getColorChannel() = 0; //If color buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer. + virtual S32 getDepthChannel() = 0; //If depth buffer is used in this shader returns > -1 to cue LLPostProcess on copying it from the framebuffer. + virtual QuadType bind() = 0; //Bind shader and textures, set up attribs. Returns the 'type' of quad to be drawn. + virtual bool draw(U32 pass) = 0; //returning false means finished. Used to update per-pass attributes and such. LLPostProcess will call + //drawOrthoQuad when this returns true, increment pass, then call this again, and keep repeating this until false is returned. + virtual void unbind() = 0; //Unbind shader and textures. + + LLSD getDefaults(); //Returns a full LLSD kvp list filled with default values. + void loadSettings(const LLSD& settings); //Parses the effects LLSD list and sets the member variables linked to them (via LLShaderSetting::setValue()) +}; + +//LLVector4 does not implicitly convert to and from LLSD, so template specilizations are necessary. +template<> LLSD LLPostProcessShader::LLShaderSetting::getDefaultValue(); +template<> void LLPostProcessShader::LLShaderSetting::setValue(const LLSD& value); class LLPostProcess : public LLSingleton { -public: - - typedef enum _QuadType { - QUAD_NORMAL, - QUAD_NOISE - } QuadType; - - /// GLSL Shader Encapsulation Struct - //typedef std::map glslUniforms; - - struct PostProcessTweaks : public LLSD { - inline PostProcessTweaks() : LLSD(LLSD::emptyMap()) - { - } - - inline LLSD & brightMult() { - return (*this)["brightness_multiplier"]; - } - - inline LLSD & noiseStrength() { - return (*this)["noise_strength"]; - } - - inline LLSD & noiseSize() { - return (*this)["noise_size"]; - } - - inline LLSD & brightness() { - return (*this)["brightness"]; - } - - inline LLSD & contrast() { - return (*this)["contrast"]; - } - - inline LLSD & contrastBaseR() { - return (*this)["contrast_base"][0]; - } - - inline LLSD & contrastBaseG() { - return (*this)["contrast_base"][1]; - } - - inline LLSD & contrastBaseB() { - return (*this)["contrast_base"][2]; - } - - inline LLSD & contrastBaseIntensity() { - return (*this)["contrast_base"][3]; - } - - inline LLSD & saturation() { - return (*this)["saturation"]; - } - - inline LLSD & useNightVisionShader() { - return (*this)["enable_night_vision"]; - } - - inline LLSD & useColorFilter() { - return (*this)["enable_color_filter"]; - } - - inline LLSD & useGaussBlurFilter() { - return (*this)["enable_gauss_blur"]; - } - - inline F32 getBrightMult() const { - return F32((*this)["brightness_multiplier"].asReal()); - } - - inline F32 getNoiseStrength() const { - return F32((*this)["noise_strength"].asReal()); - } - - inline F32 getNoiseSize() const { - return F32((*this)["noise_size"].asReal()); - } - - inline F32 getGamma() const { - return F32((*this)["gamma"].asReal()); - } - - inline F32 getBrightness() const { - return F32((*this)["brightness"].asReal()); - } - - inline F32 getContrast() const { - return F32((*this)["contrast"].asReal()); - } - - inline F32 getContrastBaseR() const { - return F32((*this)["contrast_base"][0].asReal()); - } - - inline F32 getContrastBaseG() const { - return F32((*this)["contrast_base"][1].asReal()); - } - - inline F32 getContrastBaseB() const { - return F32((*this)["contrast_base"][2].asReal()); - } - - inline F32 getContrastBaseIntensity() const { - return F32((*this)["contrast_base"][3].asReal()); - } - - inline F32 getSaturation() const { - return F32((*this)["saturation"].asReal()); - } - - inline LLSD & getGaussBlurPasses() { - return (*this)["gauss_blur_passes"]; - } - }; - - PostProcessTweaks tweaks; - - // the map of all availible effects - LLSD mAllEffects; - private: + std::list > mShaders; //List of all registered LLPostProcessShader instances. + LLPointer mVBO; - LLPointer mSceneRenderTexture ; + U32 mNextDrawTarget; //Need to pingpong between two rendertargets. Cannot sample target texture of currently bound FBO. + // However this is ONLY the case if fbos are actually supported, else swapping isn't needed. + LLRenderTarget mRenderTarget[2]; + U32 mDepthTexture; LLPointer mNoiseTexture ; + + U32 mScreenWidth; + U32 mScreenHeight; + F32 mNoiseTextureScale; + + // The name of currently selected effect in mAllEffectInfo + std::string mSelectedEffectName; + // The map of settings for currently selected effect. + LLSD mSelectedEffectInfo; + // The map of all availible effects + LLSD mAllEffectInfo; public: LLPostProcess(void); - ~LLPostProcess(void); +private: + // OpenGL initialization + void initialize(unsigned int width, unsigned int height); //Sets mScreenWidth and mScreenHeight + // calls createScreenTextures and createNoiseTexture + // creates VBO + void createScreenTextures(); //Creates color texture and depth texture(if needed). + void createNoiseTexture(); //Creates 'random' noise texture. - void apply(unsigned int width, unsigned int height); - void invalidate() ; - - // Cleanup of global data that's only inited once per class. +public: + // Teardown + // Called on destroyGL or cleanupClass. Releases VBOs, rendertargets and textures. + void destroyGL(); + // Cleanup of global data that's only inited once per class. static void cleanupClass(); - void setSelectedEffect(std::string const & effectName); - - inline std::string const & getSelectedEffect(void) const { - return mSelectedEffectName; - } - - void saveEffect(std::string const & effectName); - -private: - /// read in from file - std::string mShaderErrorString; - unsigned int mScreenWidth; - unsigned int mScreenHeight; - - float mNoiseTextureScale; - - // the name of currently selected effect in mAllEffects - // invariant: tweaks == mAllEffects[mSelectedEffectName] - std::string mSelectedEffectName; - - /// General functions - void initialize(unsigned int width, unsigned int height); - void doEffects(void); - void applyShaders(void); - bool shadersEnabled(void); - - /// Night Vision Functions - void applyNightVisionShader(void); - - /// Color Filter Functions - void applyColorFilterShader(void); - - /// Gaussian blur Filter Functions - void applyGaussBlurShader(void); - - /// OpenGL Helper Functions + // Setup for draw. void copyFrameBuffer(); - void createScreenTexture(); - void createNoiseTexture(); - bool checkError(void); - void drawOrthoQuad(QuadType type); + void bindNoise(U32 channel); + + // Draw + void renderEffects(unsigned int width, unsigned int height); //Entry point for newview. +private: + void doEffects(void); //Sets up viewmatrix, blits the framebuffer, then calls applyShaders. + void applyShaders(void); //Iterates over all active post shaders, manages binding, calls drawOrthoQuad for render. + void drawOrthoQuad(QuadType type); //Finally draws fullscreen quad with the shader currently bound. + +public: + // UI interaction + // Getters + inline LLSD const & getAllEffectInfo(void) const { return mAllEffectInfo; } + inline std::string const & getSelectedEffectName(void) const { return mSelectedEffectName; } + inline LLSD const & getSelectedEffectInfo(void) const { return mSelectedEffectInfo; } + // Setters + void setSelectedEffect(std::string const & effectName); + void setSelectedEffectValue(std::string const & setting, LLSD& value); + void resetSelectedEffect(); + void saveEffectAs(std::string const & effectName); }; #endif // LL_POSTPROCESS_H diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index d73b17a51..31cc03994 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1480,9 +1480,8 @@ void LLRender::translateUI(F32 x, F32 y, F32 z) llerrs << "Need to push a UI translation frame before offsetting" << llendl; } - mUIOffset.back().mV[0] += x; - mUIOffset.back().mV[1] += y; - mUIOffset.back().mV[2] += z; + LLVector4a add(x,y,x); + mUIOffset.back()->add(add); } void LLRender::scaleUI(F32 x, F32 y, F32 z) @@ -1492,27 +1491,28 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z) llerrs << "Need to push a UI transformation frame before scaling." << llendl; } - mUIScale.back().scaleVec(LLVector3(x,y,z)); + LLVector4a scale(x,y,z); + mUIScale.back()->mul(scale); } void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.push_back(LLVector3(0,0,0)); + mUIOffset.push_back(new LLVector4a(0.f)); } else { - mUIOffset.push_back(mUIOffset.back()); + mUIOffset.push_back(new LLVector4a(*mUIOffset.back())); } if (mUIScale.empty()) { - mUIScale.push_back(LLVector3(1,1,1)); + mUIScale.push_back(new LLVector4a(1.f)); } else { - mUIScale.push_back(mUIScale.back()); + mUIScale.push_back(new LLVector4a(*mUIScale.back())); } } @@ -1522,7 +1522,9 @@ void LLRender::popUIMatrix() { llerrs << "UI offset stack blown." << llendl; } + delete mUIOffset.back(); mUIOffset.pop_back(); + delete mUIScale.back(); mUIScale.pop_back(); } @@ -1532,7 +1534,7 @@ LLVector3 LLRender::getUITranslation() { return LLVector3(0,0,0); } - return mUIOffset.back(); + return LLVector3(mUIOffset.back()->getF32ptr()); } LLVector3 LLRender::getUIScale() @@ -1541,7 +1543,7 @@ LLVector3 LLRender::getUIScale() { return LLVector3(1,1,1); } - return mUIScale.back(); + return LLVector3(mUIOffset.back()->getF32ptr()); } @@ -1551,8 +1553,8 @@ void LLRender::loadUIIdentity() { llerrs << "Need to push UI translation frame before clearing offset." << llendl; } - mUIOffset.back().setVec(0,0,0); - mUIScale.back().setVec(1,1,1); + mUIOffset.back()->splat(0.f); + mUIScale.back()->splat(1.f); } void LLRender::setColorMask(bool writeColor, bool writeAlpha) @@ -1913,7 +1915,7 @@ void LLRender::flush() } } -void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) +void LLRender::vertex4a(const LLVector4a& vertex) { //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] if (mCount > 2048) @@ -1935,12 +1937,13 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) if (mUIOffset.empty()) { - mVerticesp[mCount] = LLVector3(x,y,z); + mVerticesp[mCount]=vertex; } else { - LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); - mVerticesp[mCount] = vert; + //LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); + mVerticesp[mCount].setAdd(vertex,*mUIOffset.back()); + mVerticesp[mCount].mul(*mUIScale.back()); } if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) @@ -1968,7 +1971,7 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -2025,7 +2028,7 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -2083,7 +2086,7 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 v mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -2143,26 +2146,6 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLCol mColorsp[mCount] = mColorsp[mCount-1]; } -void LLRender::vertex2i(const GLint& x, const GLint& y) -{ - vertex3f((GLfloat) x, (GLfloat) y, 0); -} - -void LLRender::vertex2f(const GLfloat& x, const GLfloat& y) -{ - vertex3f(x,y,0); -} - -void LLRender::vertex2fv(const GLfloat* v) -{ - vertex3f(v[0], v[1], 0); -} - -void LLRender::vertex3fv(const GLfloat* v) -{ - vertex3f(v[0], v[1], v[2]); -} - void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y) { mTexcoordsp[mCount] = LLVector2(x,y); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 5032c0e08..6e412926d 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -364,12 +364,14 @@ public: void begin(const GLuint& mode); void end(); - void vertex2i(const GLint& x, const GLint& y); - void vertex2f(const GLfloat& x, const GLfloat& y); - void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z); - void vertex2fv(const GLfloat* v); - void vertex3fv(const GLfloat* v); - + + LL_FORCE_INLINE void vertex2i(const GLint& x, const GLint& y) { vertex4a(LLVector4a((GLfloat)x,(GLfloat)y,0.f)); } + LL_FORCE_INLINE void vertex2f(const GLfloat& x, const GLfloat& y) { vertex4a(LLVector4a(x,y,0.f)); } + LL_FORCE_INLINE void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) { vertex4a(LLVector4a(x,y,z)); } + LL_FORCE_INLINE void vertex2fv(const GLfloat* v) { vertex4a(LLVector4a(v[0],v[1],0.f)); } + LL_FORCE_INLINE void vertex3fv(const GLfloat* v) { vertex4a(LLVector4a(v[0],v[1],v[2])); } + void vertex4a(const LLVector4a& v); + void texCoord2i(const GLint& x, const GLint& y); void texCoord2f(const GLfloat& x, const GLfloat& y); void texCoord2fv(const GLfloat* tc); @@ -387,9 +389,9 @@ public: void diffuseColor4fv(const F32* c); void diffuseColor4ubv(const U8* c); - void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count); - void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); @@ -449,7 +451,7 @@ private: F32 mCurrAlphaFuncVal; LLPointer mBuffer; - LLStrider mVerticesp; + LLStrider mVerticesp; LLStrider mTexcoordsp; LLStrider mColorsp; std::vector mTexUnits; @@ -463,8 +465,8 @@ private: F32 mMaxAnisotropy; - std::vector mUIOffset; - std::vector mUIScale; + std::vector mUIOffset; + std::vector mUIScale; }; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 93aaf0510..f58445414 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -76,6 +76,45 @@ LLRenderTarget::~LLRenderTarget() release(); } +void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt) +{ + //for accounting, get the number of pixels added/subtracted + S32 pix_diff = (resx*resy)-(mResX*mResY); + + mResX = resx; + mResY = resy; + + for (U32 i = 0; i < mTex.size(); ++i) + { //resize color attachments + gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + sBytesAllocated += pix_diff*4; + } + + if (mDepth) + { //resize depth attachment + if (mStencil && mFBO) + { + //use render buffers where stencil buffers are in play + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + else + { + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + U32 internal_type = LLTexUnit::getInternalType(mUsage); + if(!mStencil) + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + else + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8, mResX, mResY, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL, false); + } + + sBytesAllocated += pix_diff*4; + } + if(mSampleBuffer) + mSampleBuffer->resize(resx,resy); +} void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) { @@ -95,9 +134,10 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo mUsage = usage; mUseDepth = depth; - if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) { + glGenFramebuffers(1, (GLuint *) &mFBO); + if (depth) { if (!allocateDepth()) @@ -107,8 +147,6 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo } } - glGenFramebuffers(1, (GLuint *) &mFBO); - if (mDepth) { glBindFramebuffer(GL_FRAMEBUFFER, mFBO); @@ -126,7 +164,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo } glBindFramebuffer(GL_FRAMEBUFFER, 0); } - + stop_glerror(); } @@ -219,7 +257,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) bool LLRenderTarget::allocateDepth() { - if (mStencil) + if (mStencil && mFBO) { //use render buffers where stencil buffers are in play glGenRenderbuffers(1, (GLuint *) &mDepth); @@ -231,24 +269,30 @@ bool LLRenderTarget::allocateDepth() } else { - LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth); + if(!mStencil) + LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth); + else + LLImageGL::generateTextures(mUsage, GL_DEPTH24_STENCIL8, 1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); stop_glerror(); clear_glerror(); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + if(!mStencil) + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + else + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8, mResX, mResY, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL, false); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - sBytesAllocated += mResX*mResY*4; - if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate depth buffer for render target." << llendl; return false; } + sBytesAllocated += mResX*mResY*4; + return true; } @@ -301,7 +345,7 @@ void LLRenderTarget::release() { if (mDepth) { - if (mStencil) + if (mStencil && mFBO) { glDeleteRenderbuffers(1, (GLuint*) &mDepth); stop_glerror(); @@ -309,7 +353,11 @@ void LLRenderTarget::release() else { //Release before delete. - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); + if(mFBO) + { + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); + } LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true); stop_glerror(); } @@ -453,6 +501,7 @@ void LLRenderTarget::flush(bool fetch_depth) { gGL.getTexUnit(0)->bind(this); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); + stop_glerror(); if (fetch_depth) { @@ -461,8 +510,10 @@ void LLRenderTarget::flush(bool fetch_depth) allocateDepth(); } - gGL.getTexUnit(0)->bind(this); - glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); + gGL.getTexUnit(0)->bind(this,true); + glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY); + stop_glerror(); + //glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); @@ -472,7 +523,7 @@ void LLRenderTarget::flush(bool fetch_depth) stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); - + if (mSampleBuffer) { LLGLEnable multisample(GL_MULTISAMPLE); @@ -482,7 +533,7 @@ void LLRenderTarget::flush(bool fetch_depth) check_framebuffer_status(); glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO); check_framebuffer_status(); - + stop_glerror(); if(gGLManager.mIsATI) { @@ -532,7 +583,6 @@ void LLRenderTarget::flush(bool fetch_depth) } } } - void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { @@ -553,7 +603,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, } else { - if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) + if (mask == GL_DEPTH_BUFFER_BIT && !mStencil && source.mStencil != mStencil) { stop_glerror(); @@ -642,7 +692,8 @@ void LLRenderTarget::getViewport(S32* viewport) // LLMultisampleBuffer implementation //================================================== LLMultisampleBuffer::LLMultisampleBuffer() : - mSamples(0) + mSamples(0), + mColorFormat(0) { } @@ -743,6 +794,7 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth mUsage = usage; mUseDepth = depth; mStencil = stencil; + mColorFormat = color_fmt; { @@ -780,6 +832,42 @@ bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth return addColorAttachment(color_fmt); } +void LLMultisampleBuffer::resize(U32 resx, U32 resy) +{ + //for accounting, get the number of pixels added/subtracted + S32 pix_diff = (resx*resy)-(mResX*mResY); + + mResX = resx; + mResY = resy; + + for (U32 i = 0; i < mTex.size(); ++i) + { //resize color attachments + glBindRenderbuffer(GL_RENDERBUFFER, mTex[i]); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, mColorFormat, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + sBytesAllocated += pix_diff*4; + } + + if (mDepth) + { //resize depth attachment + if (mStencil) + { + //use render buffers where stencil buffers are in play + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + else + { + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT24, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + } + sBytesAllocated += pix_diff*4; + } +} + bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) @@ -829,12 +917,13 @@ bool LLMultisampleBuffer::allocateDepth() clear_glerror(); if (mStencil) { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); } else { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT24, mResX, mResY); } + if (glGetError() != GL_NO_ERROR) { llwarns << "Unable to allocate depth buffer for multisample render target." << llendl; @@ -845,4 +934,3 @@ bool LLMultisampleBuffer::allocateDepth() return true; } - diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 9ed95770e..d9a529ff0 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -80,6 +80,12 @@ public: //multiple calls will release previously allocated resources bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE); + //resize existing attachments to use new resolution and color format + // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined + // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded + // DO use for render targets that resize often and aren't likely to ruin someone's day if they break + void resize(U32 resx, U32 resy, U32 color_fmt); + //provide this render target with a multisample resource. void setSampleBuffer(LLMultisampleBuffer* buffer); @@ -145,6 +151,8 @@ public: //one renderable attachment (i.e. color buffer, depth buffer). bool isComplete() const; + U32 getFBO() const {return mFBO;} + static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } protected: @@ -168,6 +176,7 @@ protected: class LLMultisampleBuffer : public LLRenderTarget { U32 mSamples; + U32 mColorFormat; public: LLMultisampleBuffer(); virtual ~LLMultisampleBuffer(); @@ -180,6 +189,7 @@ public: bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples); virtual bool addColorAttachment(U32 color_fmt); virtual bool allocateDepth(); + void resize(U32 resx, U32 resy); }; #endif //!LL_MESA_HEADLESS diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index ade7480d2..fcede5363 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -679,7 +679,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade vec4 diffuseLookup(vec2 texcoord) { - switch (vary_texture_index.r)) + switch (vary_texture_index)) { case 0: ret = texture2D(tex0, texcoord); break; case 1: ret = texture2D(tex1, texcoord); break; @@ -703,7 +703,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (texture_index_channels > 1) { - text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n"); + text[count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); } text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); @@ -721,7 +721,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //switches are unreliable on some NVIDIA drivers for (S32 i = 0; i < texture_index_channels; ++i) { - std::string if_string = llformat("\t%sif (vary_texture_index.r == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); + std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); text[count++] = strdup(if_string.c_str()); } text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); @@ -730,13 +730,13 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade else { text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); - text[count++] = strdup("\tswitch (vary_texture_index.r)\n"); + text[count++] = strdup("\tswitch (vary_texture_index)\n"); text[count++] = strdup("\t{\n"); //switch body for (S32 i = 0; i < texture_index_channels; ++i) { - std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i); + std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); text[count++] = strdup(case_str.c_str()); } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index bc4c201d9..896560d4d 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1249,7 +1249,7 @@ void LLVertexBuffer::setupVertexArray() 1, //TYPE_WEIGHT, 4, //TYPE_WEIGHT4, 4, //TYPE_CLOTHWEIGHT, - 4, //TYPE_TEXTURE_INDEX + 1, //TYPE_TEXTURE_INDEX }; U32 attrib_type[] = @@ -1266,7 +1266,7 @@ void LLVertexBuffer::setupVertexArray() GL_FLOAT, //TYPE_WEIGHT, GL_FLOAT, //TYPE_WEIGHT4, GL_FLOAT, //TYPE_CLOTHWEIGHT, - GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX + GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX }; bool attrib_integer[] = @@ -2313,7 +2313,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) #if !LL_DARWIN S32 loc = TYPE_TEXTURE_INDEX; void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); - glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); #endif } if (data_mask & MAP_VERTEX) diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index bf5fc316d..c5cf582e5 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -520,7 +520,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex const S32 NUM_VERTICES = 9 * 4; // 9 quads LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; + LLVector4a pos[NUM_VERTICES]; S32 index = 0; @@ -528,157 +528,157 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex { // draw bottom left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; // draw bottom middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; // draw bottom right uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; // draw left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; // draw middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; // draw right uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; // draw top left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index].set(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); + pos[index].set(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; // draw top middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; // draw top right uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index].set(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + pos[index].set(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); index++; - + gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); } gGL.end(); @@ -720,7 +720,7 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre { const S32 NUM_VERTICES = 4; // 9 quads LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; + LLVector4a pos[NUM_VERTICES]; gGL.begin(LLRender::QUADS); { @@ -734,19 +734,19 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre S32 scaled_height = llround(height * ui_scale.mV[VY]); uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); index++; uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); index++; uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); + pos[index].set(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); index++; uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); + pos[index].set(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); index++; gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index c476e25d3..b0e95c54a 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -336,6 +336,7 @@ bool LLView::addChild(LLView* child, S32 tab_group) // add to front of child list, as normal mChildList.push_front(child); + mChildHashMap[child->getName()]=child; // add to ctrl list if is LLUICtrl if (child->isCtrl()) @@ -374,6 +375,14 @@ void LLView::removeChild(LLView* child) // if we are removing an item we are currently iterating over, that would be bad llassert(child->mInDraw == false); mChildList.remove( child ); + for(boost::unordered_map::iterator it=mChildHashMap.begin(); it != mChildHashMap.end(); ++it) + { + if(it->second == child) + { + mChildHashMap.erase(it); + break; + } + } child->mParentView = NULL; if (child->isCtrl()) { @@ -607,6 +616,7 @@ void LLView::deleteAllChildren() LLView* viewp = mChildList.front(); delete viewp; // will remove the child from mChildList } + mChildHashMap.clear(); } void LLView::setAllChildrenEnabled(BOOL b) @@ -1506,13 +1516,18 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ //if(name.empty()) // return NULL; // Look for direct children *first* - BOOST_FOREACH(LLView* childp, mChildList) + /*BOOST_FOREACH(LLView* childp, mChildList) { llassert(childp); if (childp->getName() == name) { return childp; } + }*/ + boost::unordered_map::const_iterator it = mChildHashMap.find(name); + if(it != mChildHashMap.end()) + { + return it->second; } if (recurse) { diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 721c82fbb..ee2ad2d3e 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -56,6 +56,7 @@ #include "llcursortypes.h" #include "llinitparam.h" #include "llfocusmgr.h" +#include const U32 FOLLOWS_NONE = 0x00; const U32 FOLLOWS_LEFT = 0x01; @@ -186,6 +187,15 @@ public: void initFromParams(const LLView::Params&); + template + struct CachedUICtrl + { + CachedUICtrl():mPtr(NULL){} + T* connect(LLView* parent,const char* pName){return mPtr = parent->getChild(pName);} + T* operator->(){return mPtr;} + operator T*() const{return mPtr;} + T* mPtr; + }; protected: LLView(const LLView::Params&); //friend class LLUICtrlFactory; @@ -454,6 +464,7 @@ public: const child_list_t* getChildList() const { return &mChildList; } child_list_const_iter_t beginChild() const { return mChildList.begin(); } child_list_const_iter_t endChild() const { return mChildList.end(); } + boost::unordered_map mChildHashMap; // LLMouseHandler functions // Default behavior is to pass events to children @@ -467,13 +478,17 @@ public: /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it. - /*virtual*/ const std::string& getName() const; + /*virtual*/ const std::string& getName() const; /*virtual*/ void onMouseCaptureLost(); /*virtual*/ BOOL hasMouseCapture(); /*virtual*/ BOOL isView(); // Hack to support LLFocusMgr /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const; /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const; + template T* findChild(const std::string& name) + { + return getChild(name,true,false); + } template T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const { LLView* child = getChildView(name, recurse, FALSE); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e2f289679..251b2f588 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -244,6 +244,7 @@ set(viewer_SOURCE_FILES llfloaterpostprocess.cpp llfloaterpreference.cpp llfloaterproperties.cpp + llfloaterregiondebugconsole.cpp llfloaterregioninfo.cpp llfloaterreporter.cpp llfloatersearchreplace.cpp @@ -373,6 +374,7 @@ set(viewer_SOURCE_FILES llpanelmsgs.cpp llpanelnetwork.cpp llpanelobject.cpp + llpanelpathfindingrebakenavmesh.cpp llpanelpermissions.cpp llpanelpick.cpp llpanelplace.cpp @@ -381,6 +383,15 @@ set(viewer_SOURCE_FILES llpanelweb.cpp llparcelselection.cpp llpatchvertexarray.cpp + llpathfindingcharacter.cpp + llpathfindingcharacterlist.cpp + llpathfindinglinkset.cpp + llpathfindinglinksetlist.cpp + llpathfindingmanager.cpp + llpathfindingnavmesh.cpp + llpathfindingnavmeshstatus.cpp + llpathfindingobject.cpp + llpathfindingobjectlist.cpp llphysicsmotion.cpp llphysicsshapebuilderutil.cpp llpolymesh.cpp @@ -736,6 +747,7 @@ set(viewer_HEADER_FILES llfloaterpreference.h llfloaterperms.h llfloaterproperties.h + llfloaterregiondebugconsole.h llfloaterregioninfo.h llfloaterreporter.h llfloatersearchreplace.h @@ -858,7 +870,6 @@ set(viewer_HEADER_FILES llpanellandmedia.h llpanellandobjects.h llpanellandoptions.h - llpanelLCD.h llpanellogin.h llpanelmaininventory.h llpanelmorph.h @@ -866,6 +877,7 @@ set(viewer_HEADER_FILES llpanelmsgs.h llpanelnetwork.h llpanelobject.h + llpanelpathfindingrebakenavmesh.h llpanelpermissions.h llpanelpick.h llpanelplace.h @@ -874,6 +886,15 @@ set(viewer_HEADER_FILES llpanelweb.h llparcelselection.h llpatchvertexarray.h + llpathfindingcharacter.h + llpathfindingcharacterlist.h + llpathfindinglinkset.h + llpathfindinglinksetlist.h + llpathfindingmanager.h + llpathfindingnavmesh.h + llpathfindingnavmeshstatus.h + llpathfindingobject.h + llpathfindingobjectlist.h llphysicsmotion.h llphysicsshapebuilderutil.h llpolymesh.h @@ -1572,6 +1593,14 @@ if (LINUX) set(product ${VIEWER_BRANDING_NAME_CAMELCASE}-${ARCH}-${viewer_VERSION}) + if (FMODEX) + if(MANIFEST_LIBRARIES) + set(MANIFEST_LIBRARIES "${MANIFEST_LIBRARIES}|${FMODEX_LIBRARY}") + else(MANIFEST_LIBRARIES) + set(MANIFEST_LIBRARIES "--extra_libraries=${FMODEX_LIBRARY}") + endif(MANIFEST_LIBRARIES) + endif (FMODEX) + add_custom_command( OUTPUT ${product}.tar.bz2 COMMAND ${PYTHON_EXECUTABLE} @@ -1590,6 +1619,7 @@ if (LINUX) --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched --buildtype=${CMAKE_BUILD_TYPE} + ${MANIFEST_LIBRARIES} DEPENDS secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 16991b62e..08a211576 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7242,6 +7242,17 @@ Value help/index.html + WebProfileURL + + Comment + URL for Web Profiles + Persist + 0 + Type + String + Value + https://my.secondlife.com/[AGENT_NAME] + HighResSnapshot Comment @@ -13398,7 +13409,7 @@ Type S32 Value - 10 + 5 SystemLanguage diff --git a/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl b/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl new file mode 100644 index 000000000..1da0cdbad --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/effects/PosterizeF.glsl @@ -0,0 +1,23 @@ +/** + * @file colorFilterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#extension GL_ARB_texture_rectangle : enable + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 gl_FragColor; +#endif + +uniform sampler2DRect tex0; +uniform int layerCount; + +VARYING vec2 vary_texcoord0; + +void main(void) +{ + vec3 color = pow(floor(pow(vec3(texture2D(tex0, vary_texcoord0.st)),vec3(.6)) * layerCount)/layerCount,vec3(1.66666)); + gl_FragColor = vec4(color, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl index 7c0699d72..ca29bf314 100644 --- a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl @@ -23,9 +23,9 @@ * $/LicenseInfo$ */ -ATTRIBUTE ivec4 texture_index; +ATTRIBUTE int texture_index; -VARYING_FLAT ivec4 vary_texture_index; +VARYING_FLAT int vary_texture_index; void passTextureIndex() { diff --git a/indra/newview/app_settings/windlight/postprocesseffects.xml b/indra/newview/app_settings/windlight/postprocesseffects.xml index 9261f3287..0914b275a 100644 --- a/indra/newview/app_settings/windlight/postprocesseffects.xml +++ b/indra/newview/app_settings/windlight/postprocesseffects.xml @@ -174,6 +174,8 @@ 0 enable_gauss_blur 0 + enable_posterize + 0 gauss_blur_passes 2 extract_high @@ -186,6 +188,8 @@ 0.40000000000000002 saturation 1 - + posterize_layers + 10 + \ No newline at end of file diff --git a/indra/newview/hipporestrequest.cpp b/indra/newview/hipporestrequest.cpp index 7b64b35d8..8953dec87 100644 --- a/indra/newview/hipporestrequest.cpp +++ b/indra/newview/hipporestrequest.cpp @@ -256,7 +256,7 @@ static void request(const std::string &url, LLPumpIO::chain_t chain; LLURLRequest *req = new LLURLRequest(method, url); - req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); + req->checkRootCertificate(true); /* // Insert custom headers if the caller sent any diff --git a/indra/newview/importtracker.cpp b/indra/newview/importtracker.cpp index b926d7aac..ce2e6bb1e 100644 --- a/indra/newview/importtracker.cpp +++ b/indra/newview/importtracker.cpp @@ -203,7 +203,7 @@ void ImportTracker::get_update(S32 newid, BOOL justCreated, BOOL createSelected) msg->addBOOLFast(_PREHASH_UsePhysics, gSavedSettings.getBOOL("EmeraldBuildPrefs_Physical")); msg->addBOOLFast(_PREHASH_IsTemporary, gSavedSettings.getBOOL("EmeraldBuildPrefs_Temporary")); msg->addBOOLFast(_PREHASH_IsPhantom, gSavedSettings.getBOOL("EmeraldBuildPrefs_Phantom") ); - msg->addBOOL("CastsShadows", true ); + msg->addBOOL("CastsShadows", false ); msg->sendReliable(gAgent.getRegion()->getHost()); if(gSavedSettings.getBOOL("EmeraldBuildPrefs_EmbedItem")) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 1d8b429ba..5f0539b7c 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -49,6 +49,7 @@ #include "llmoveview.h" #include "llchatbar.h" #include "llnotificationsutil.h" +#include "llpanelpathfindingrebakenavmesh.h" #include "llparcel.h" #include "llrendersphere.h" #include "llsdmessage.h" @@ -1874,6 +1875,8 @@ void LLAgent::endAnimationUpdateUI() gMenuBarView->setVisible(TRUE); gStatusBar->setVisibleForMouselook(true); + LLPanelPathfindingRebakeNavmesh::getInstance()->setVisible(TRUE); + LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); @@ -1962,6 +1965,7 @@ void LLAgent::endAnimationUpdateUI() // hide menus gMenuBarView->setVisible(FALSE); gStatusBar->setVisibleForMouselook(false); + LLPanelPathfindingRebakeNavmesh::getInstance()->setVisible(FALSE); // clear out camera lag effect gAgentCamera.clearCameraLag(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c0bb21085..955a420c6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -83,6 +83,7 @@ #include "llvector4a.h" #include "llfont.h" #include "llvocache.h" +#include "llvopartgroup.h" #include "llfloaterteleporthistory.h" #include "llweb.h" @@ -216,11 +217,6 @@ ////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor // -#if LL_WINDOWS && LL_LCD_COMPILE - #include "lllcd.h" -#endif - - //---------------------------------------------------------------------------- // viewer.cpp - these are only used in viewer, should be easily moved. @@ -602,6 +598,10 @@ bool LLAppViewer::init() // initialize SSE options LLVector4a::initClass(); + + //initialize particle index pool + LLVOPartGroup::initClass(); + // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API gDirUtilp->initAppDirs("SecondLife"); @@ -637,9 +637,8 @@ bool LLAppViewer::init() mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling")); // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. - LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"), - gSavedSettings.getS32("CurlMaximumNumberOfHandles"), - gSavedSettings.getBOOL("CurlUseMultipleThreads")); + LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut")); + LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ; initThreads(); @@ -810,13 +809,6 @@ bool LLAppViewer::init() // call all self-registered classes LLInitClassList::instance().fireCallbacks(); -#if LL_LCD_COMPILE - // start up an LCD window on a logitech keyboard, if there is one - HINSTANCE hInstance = GetModuleHandle(NULL); - gLcdScreen = new LLLCD(hInstance); - CreateLCDDebugWindows(); -#endif - LLFolderViewItem::initClass(); // SJB: Needs to happen after initWindow(), not sure why but related to fonts gGLManager.getGLInfo(gDebugInfo); @@ -1198,11 +1190,6 @@ bool LLAppViewer::mainLoop() pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots gGLActive = FALSE; -#if LL_LCD_COMPILE - // update LCD Screen - pingMainloopTimeout("Main:LCD"); - gLcdScreen->UpdateDisplay(); -#endif } } @@ -1570,12 +1557,6 @@ bool LLAppViewer::cleanup() // gDXHardware.cleanup(); //#endif // LL_WINDOWS -#if LL_LCD_COMPILE - // shut down the LCD window on a logitech keyboard, if there is one - delete gLcdScreen; - gLcdScreen = NULL; -#endif - LLVolumeMgr* volume_manager = LLPrimitive::getVolumeManager(); if (!volume_manager->cleanup()) { @@ -1678,6 +1659,8 @@ bool LLAppViewer::cleanup() writeDebugInfo(); + if(!gDirUtilp->getLindenUserDir(true).empty()) + LLViewerMedia::saveCookieFile(); // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index c34fee56b..12e26b1c4 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -165,6 +165,9 @@ BOOL LLChatBar::postBuild() mInputEditor->setEnableLineHistory(TRUE); } + mHistoryBtn.connect(this,"History"); + mSayBtn.connect(this,"Say"); + mIsBuilt = TRUE; return TRUE; @@ -228,9 +231,9 @@ void LLChatBar::refresh() gAgent.stopTyping(); } - childSetValue("History", LLFloaterChat::instanceVisible(LLSD())); + mHistoryBtn->setValue(LLFloaterChat::instanceVisible(LLSD())); - childSetEnabled("Say", mInputEditor->getText().size() > 0); + mSayBtn->setEnabled(mInputEditor->getText().size() > 0); //childSetEnabled("Shout", mInputEditor->getText().size() > 0); createDummyWidget Making Dummy -HgB } diff --git a/indra/newview/llchatbar.h b/indra/newview/llchatbar.h index c4fed67d9..5e0391d08 100644 --- a/indra/newview/llchatbar.h +++ b/indra/newview/llchatbar.h @@ -110,6 +110,9 @@ protected: LLComboBox* mGestureCombo; LLChatBarGestureObserver* mObserver; + + CachedUICtrl mHistoryBtn; + CachedUICtrl mSayBtn; }; extern LLChatBar *gChatBar; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index b9df32f06..97b9764ab 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -113,6 +113,7 @@ void LLDrawable::init() mGeneration = -1; mBinRadius = 1.f; + mBinIndex = -1; mSpatialBridge = NULL; } @@ -790,19 +791,7 @@ void LLDrawable::updateTexture() if (getVOVolume()) { - /*if (isActive()) - { - if (isRoot()) - { - mQuietCount = 0; - } - else - { - getParent()->mQuietCount = 0; - } - }*/ - - getVOVolume()->mFaceMappingChanged = TRUE; + //getVOVolume()->mFaceMappingChanged = TRUE; gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } } @@ -963,6 +952,12 @@ void LLDrawable::updateUVMinMax() { } +LLSpatialGroup* LLDrawable::getSpatialGroup() const +{ + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); + return mSpatialGroupp; +} + void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) @@ -985,6 +980,8 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) } mSpatialGroupp = groupp; + + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); } LLSpatialPartition* LLDrawable::getSpatialPartition() @@ -1107,6 +1104,8 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 dat mDrawable = root; root->setSpatialBridge(this); + mBinIndex = -1; + mRenderType = mDrawable->mRenderType; mDrawableType = mDrawable->mRenderType; @@ -1500,7 +1499,13 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - mDrawable->setSpatialGroup(NULL); + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(mDrawable); + mDrawable->setSpatialGroup(NULL); + } + if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1511,7 +1516,12 @@ void LLSpatialBridge::cleanupReferences() LLDrawable* drawable = child->mDrawable; if (drawable) { - drawable->setSpatialGroup(NULL); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(drawable); + drawable->setSpatialGroup(NULL); + } } } } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 6f07c82be..bd2d23c5f 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -115,6 +115,9 @@ public: F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } F32 getBinRadius() const { return mBinRadius; } + S32 getBinIndex() const { return mBinIndex; } + void setBinIndex(S32 index) const { mBinIndex = index; } + void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } LLXformMatrix* getXform() { return &mXform; } @@ -200,7 +203,7 @@ public: S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... void setSpatialGroup(LLSpatialGroup *groupp); - LLSpatialGroup *getSpatialGroup() const { return mSpatialGroupp; } + LLSpatialGroup *getSpatialGroup() const; LLSpatialPartition* getSpatialPartition(); // Statics @@ -321,6 +324,7 @@ private: mutable U32 mVisible; F32 mRadius; F32 mBinRadius; + mutable S32 mBinIndex; S32 mGeneration; LLVector3 mCurrentScale; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 968ed740a..69a3cf419 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -446,7 +446,7 @@ void LLRenderPass::renderTexture(U32 type, U32 mask) void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { - for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) + for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 500f8b67a..865e89f89 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -355,7 +355,7 @@ void LLDrawPoolAlpha::render(S32 pass) void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) { - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; if (group->mSpatialPartition->mRenderByGroup && @@ -392,7 +392,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) BOOL use_shaders = gPipeline.canUseVertexShaders(); - for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) + for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; llassert(group); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index a37f117c4..3e818faa4 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1203,15 +1203,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass >= 7 && pass < 9) { - LLGLEnable blend(GL_BLEND); - - gGL.setColorMask(true, true); - gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA, - LLRender::BF_ZERO, - LLRender::BF_ONE_MINUS_SOURCE_ALPHA); - - if (pass == 7) { renderRiggedAlpha(avatarp); @@ -1227,20 +1218,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (pass == 9) { - LLGLEnable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.flush(); - - LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(-1.0f, -1.0f); - gGL.setSceneBlendType(LLRender::BT_ADD); - - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - gGL.setColorMask(false, true); - renderRiggedGlow(avatarp); - gGL.setColorMask(true, false); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + return; } @@ -1640,17 +1619,56 @@ void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_ALPHA); + if (!mRiggedFace[RIGGED_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_ALPHA); + } } void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty()) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); + } } void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) { - renderRigged(avatar, RIGGED_GLOW, true); + if (!mRiggedFace[RIGGED_GLOW].empty()) + { + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + renderRigged(avatar, RIGGED_GLOW, true); + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + } } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 65ab71abc..60af91ac8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -848,12 +848,12 @@ void LLDrawPoolBump::renderDeferred(S32 pass) LLFastTimer ftm(FTM_RENDER_BUMP); U32 type = LLRenderPass::PASS_BUMP; - LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_BINORMAL | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; - for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; @@ -1449,10 +1449,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI void LLDrawPoolBump::renderBump(U32 type, U32 mask) { - LLCullResult::drawinfo_list_t::iterator begin = gPipeline.beginRenderMap(type); - LLCullResult::drawinfo_list_t::iterator end = gPipeline.endRenderMap(type); + LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type); + LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type); - for (LLCullResult::drawinfo_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i) { LLDrawInfo& params = **i; diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 93c437d2d..a1cba861c 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -155,6 +155,7 @@ LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) : mAvatarp(avatarp), mWearablep(NULL) { + mDefaultVec.clear(); } LLDriverParam::LLDriverParam(LLWearable *wearablep) : @@ -162,6 +163,7 @@ LLDriverParam::LLDriverParam(LLWearable *wearablep) : mAvatarp(NULL), mWearablep(wearablep) { + mDefaultVec.clear(); } LLDriverParam::~LLDriverParam() @@ -341,18 +343,19 @@ F32 LLDriverParam::getTotalDistortion() return sum; } -const LLVector3 &LLDriverParam::getAvgDistortion() +const LLVector4a &LLDriverParam::getAvgDistortion() { // It's not actually correct to take the average of averages, but it good enough here. - LLVector3 sum; + LLVector4a sum; + sum.clear(); S32 count = 0; for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getAvgDistortion(); + sum.add(driven->mParam->getAvgDistortion()); count++; } - sum /= (F32)count; + sum.mul( 1.f/(F32)count); mDefaultVec = sum; return mDefaultVec; @@ -375,21 +378,22 @@ F32 LLDriverParam::getMaxDistortion() } -LLVector3 LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) +LLVector4a LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { - LLVector3 sum; + LLVector4a sum; + sum.clear(); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); - sum += driven->mParam->getVertexDistortion( index, poly_mesh ); + sum.add(driven->mParam->getVertexDistortion( index, poly_mesh )); } return sum; } -const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { mCurrentDistortionParam = NULL; - const LLVector3* v = NULL; + const LLVector4a* v = NULL; for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { LLDrivenEntry* driven = &(*iter); @@ -404,7 +408,7 @@ const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly return v; }; -const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { llassert( mCurrentDistortionParam ); if( !mCurrentDistortionParam ) @@ -432,7 +436,7 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ } // We're already in the middle of a param's distortions, so get the next one. - const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh ); + const LLVector4a* v = driven->mParam->getNextDistortion( index, poly_mesh ); if( (!v) && (iter != mDriven.end()) ) { // This param is finished, so start the next param. It might not have any diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index fb1b44458..7a4d711d4 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -105,18 +105,18 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector3& getAvgDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); protected: F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); - LLVector3 mDefaultVec; // temp holder + LLVector4a mDefaultVec; // temp holder typedef std::vector entry_list_t; entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index e52bb5959..ba818ed90 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -169,19 +169,10 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mGeomCount = 0; mGeomIndex = 0; mIndicesCount = 0; - if (drawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || - drawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES -#if ENABLE_CLASSIC_CLOUDS - || drawablep->getRenderType() == LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS -#endif - ) - { //indicate to LLParticlePartition that this particle is uninitialized - mIndicesIndex = 0xFFFFFFFF; - } - else - { - mIndicesIndex = 0; - } + + //special value to indicate uninitialized position + mIndicesIndex = 0xFFFFFFFF; + mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; @@ -214,17 +205,10 @@ void LLFace::destroy() mTexture->removeFace(this) ; } - if (mDrawablep.notNull() && - (mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || - mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES -#if ENABLE_CLASSIC_CLOUDS - || mDrawablep->getRenderType() == LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS -#endif - ) && - mIndicesIndex != 0xFFFFFFFF) + if (isState(LLFace::PARTICLE)) { LLVOPartGroup::freeVBSlot(getGeomIndex()/4); - mIndicesIndex = 0xFFFFFFFF; + clearState(LLFace::PARTICLE); } if (mDrawPoolp) @@ -335,7 +319,20 @@ void LLFace::setTexture(LLViewerTexture* tex) void LLFace::dirtyTexture() { - gPipeline.markTextured(getDrawable()); + LLDrawable* drawablep = getDrawable(); + + if (mVObjp.notNull() && mVObjp->getVolume() && + mTexture.notNull() && mTexture->getComponents() == 4) + { //dirty texture on an alpha object should be treated as an LoD update + LLVOVolume* vobj = drawablep->getVOVolume(); + if (vobj) + { + vobj->mLODChanged = TRUE; + } + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE); + } + + gPipeline.markTextured(drawablep); } void LLFace::switchTexture(LLViewerTexture* new_texture) @@ -1209,19 +1206,25 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) { - llwarns << "Index buffer overflow!" << llendl; - llwarns << "Indices Count: " << mIndicesCount - << " VF Num Indices: " << num_indices - << " Indices Index: " << mIndicesIndex - << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; - llwarns << " Face Index: " << f - << " Pool Type: " << mPoolType << llendl; + if (gDebugGL) + { + llwarns << "Index buffer overflow!" << llendl; + llwarns << "Indices Count: " << mIndicesCount + << " VF Num Indices: " << num_indices + << " Indices Index: " << mIndicesIndex + << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; + llwarns << " Face Index: " << f + << " Pool Type: " << mPoolType << llendl; + } return FALSE; } if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) { - llwarns << "Vertex buffer overflow!" << llendl; + if (gDebugGL) + { + llwarns << "Vertex buffer overflow!" << llendl; + } return FALSE; } } @@ -1632,7 +1635,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (!do_xform) { LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM); - LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32)); + S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF; + LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size); } else { @@ -1853,15 +1857,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a texIdx; - U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + S32 index = mTextureIndex < 255 ? mTextureIndex : 0; F32 val = 0.f; - U8* vp = (U8*) &val; - vp[0] = index; - vp[1] = 0; - vp[2] = 0; - vp[3] = 0; - + S32* vp = (S32*) &val; + *vp = index; + llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); LLVector4Logical mask; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 5513ecd41..4cab49205 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -84,6 +84,7 @@ public: USE_FACE_COLOR = 0x0010, TEXTURE_ANIM = 0x0020, RIGGED = 0x0040, + PARTICLE = 0x0080, }; static void initClass(); diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 11edb6071..8b0fd109f 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -255,50 +255,28 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons { } -//--------------------------------------------------------------------------------- -// This calculates the physics of the flexible object. Note that it has to be 0 -// updated every time step. In the future, perhaps there could be an -// optimization similar to what Havok does for objects that are stationary. -//--------------------------------------------------------------------------------- -static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); -BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) + +void LLVolumeImplFlexible::updateRenderRes() { - if (mVO->mDrawable.isNull()) - { - // Don't do anything until we have a drawable - return FALSE; // (we are not initialized or updated) - } + LLDrawable* drawablep = mVO->mDrawable; - BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; - - //flexible objects never go static - mVO->mDrawable->mQuietCount = 0; - if (!mVO->mDrawable->isRoot()) - { - LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); - parent->mDrawable->mQuietCount = 0; - } - - LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - S32 new_res = mAttributes->getSimulateLOD(); - //number of segments only cares about z axis - F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); +#if 1 //optimal approximation of previous behavior that doesn't rely on atan2 + F32 app_angle = mVO->getScale().mV[2]/drawablep->mDistanceWRTCamera; // Rendering sections increases with visible angle on the screen + mRenderRes = (S32) (12.f*app_angle); +#else //legacy behavior + //number of segments only cares about z axis + F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, drawablep->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); + + // Rendering sections increases with visible angle on the screen mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView()); - if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS) - { - mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS; - } - - - // Bottom cap at 1/4 the original number of sections - if (mRenderRes < mAttributes->getSimulateLOD()-1) - { - mRenderRes = mAttributes->getSimulateLOD()-1; - } +#endif + + mRenderRes = llclamp(mRenderRes, new_res-1, (S32) FLEXIBLE_OBJECT_MAX_SECTIONS); + // Throttle back simulation of segments we're not rendering if (mRenderRes < new_res) { @@ -311,43 +289,67 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 setAttributesOfAllSections(); mInitialized = TRUE; } - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) - { - return FALSE; // (we are not initialized or updated) - } +} +//--------------------------------------------------------------------------------- +// This calculates the physics of the flexible object. Note that it has to be 0 +// updated every time step. In the future, perhaps there could be an +// optimization similar to what Havok does for objects that are stationary. +//--------------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_FLEXIBLE_UPDATE("Update Flexies"); +void LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + LLDrawable* drawablep = mVO->mDrawable; - bool visible = mVO->mDrawable->isVisible(); - - if (force_update && visible) + if (drawablep) { - gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); - } - else if (visible && - !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) && - mVO->getPixelArea() > 256.f) - { - U32 id; - F32 pixel_area = mVO->getPixelArea(); + //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - if (mVO->isRootEdit()) + //flexible objects never go static + drawablep->mQuietCount = 0; + if (!drawablep->isRoot()) { - id = mID; - } - else - { - LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); - id = parent->getVolumeInterfaceID(); + LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); + parent->mDrawable->mQuietCount = 0; } - U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; - - if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { - gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); - } + bool visible = drawablep->isVisible(); + + if ((mSimulateRes == 0) && visible) + { + updateRenderRes(); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + else if (visible && + !drawablep->isState(LLDrawable::IN_REBUILD_Q1) && + mVO->getPixelArea() > 256.f) + { + U32 id; + F32 pixel_area = mVO->getPixelArea(); + + if (mVO->isRootEdit()) + { + id = mID; + } + else + { + LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); + id = parent->getVolumeInterfaceID(); + } + + U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + + if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) + { + updateRenderRes(); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_POSITION, FALSE); + } + } + } + if(!mInitialized) + updateRenderRes(); } - - return force_update; } inline S32 log2(S32 x) @@ -368,8 +370,11 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLPath *path = &volume->getPath(); if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible()) { - //mVO->markForUpdate(TRUE); - if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0)) + BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE; + + doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0); + + if (!force_update || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { return; // we did not get updated or initialized, proceeding without can be dangerous } diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index faed3801b..7d68a67da 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -84,7 +84,8 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLVector3 getFramePosition() const; LLQuaternion getFrameRotation() const; LLVolumeInterfaceType getInterfaceType() const { return INTERFACE_FLEXIBLE; } - BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + void updateRenderRes(); + void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); BOOL doUpdateGeometry(LLDrawable *drawable); LLVector3 getPivotPosition() const; void onSetVolume(const LLVolumeParams &volume_params, const S32 detail); diff --git a/indra/newview/llfloateractivespeakers.cpp b/indra/newview/llfloateractivespeakers.cpp index 6e49d5d91..f0f856ef0 100644 --- a/indra/newview/llfloateractivespeakers.cpp +++ b/indra/newview/llfloateractivespeakers.cpp @@ -353,6 +353,13 @@ BOOL LLPanelActiveSpeakers::postBuild() childSetCommitCallback("moderator_allow_text", onModeratorMuteText, this); childSetCommitCallback("moderation_mode", onChangeModerationMode, this); + mVolumeSlider.connect(this,"speaker_volume"); + mModeratorCtrlLbl.connect(this,"moderator_controls_label"); + mModeratorAllowVoiceCheckbox.connect(this,"moderator_allow_voice"); + mModeratorAllowTextCheckbox.connect(this,"moderator_allow_text"); + mModeratorModePanel.connect(this,"moderation_mode_panel"); + mModeratorControlsPanel.connect(this,"moderator_controls"); + // update speaker UI handleSpeakerSelect(); @@ -625,25 +632,21 @@ void LLPanelActiveSpeakers::refreshSpeakers() //&& !LLMuteList::getInstance()->isLinden(selected_speakerp->mDisplayName)); && !LLMuteList::getInstance()->isLinden(selected_speakerp->mLegacyName)); } - childSetValue("speaker_volume", gVoiceClient->getUserVolume(selected_id)); - childSetEnabled("speaker_volume", LLVoiceClient::voiceEnabled() + mVolumeSlider->setValue(gVoiceClient->getUserVolume(selected_id)); + mVolumeSlider->setEnabled(LLVoiceClient::voiceEnabled() && gVoiceClient->getVoiceEnabled(selected_id) && selected_id.notNull() && selected_id != gAgent.getID() && (selected_speakerp.notNull() && (selected_speakerp->mType == LLSpeaker::SPEAKER_AGENT || selected_speakerp->mType == LLSpeaker::SPEAKER_EXTERNAL))); - childSetEnabled( - "moderator_controls_label", - selected_id.notNull()); + mModeratorCtrlLbl->setEnabled(selected_id.notNull()); - childSetEnabled( - "moderator_allow_voice", + mModeratorAllowVoiceCheckbox->setEnabled( selected_id.notNull() && mSpeakerMgr->isVoiceActive() && gVoiceClient->getVoiceEnabled(selected_id)); - childSetEnabled( - "moderator_allow_text", + mModeratorAllowTextCheckbox->setEnabled( selected_id.notNull()); if (mProfileBtn) @@ -668,8 +671,8 @@ void LLPanelActiveSpeakers::refreshSpeakers() LLPointer self_speakerp = mSpeakerMgr->findSpeaker(gAgent.getID()); if(self_speakerp) { - childSetVisible("moderation_mode_panel", self_speakerp->mIsModerator && mSpeakerMgr->isVoiceActive()); - childSetVisible("moderator_controls", self_speakerp->mIsModerator); + mModeratorModePanel->setVisible(self_speakerp->mIsModerator && mSpeakerMgr->isVoiceActive()); + mModeratorControlsPanel->setVisible(self_speakerp->mIsModerator); } // keep scroll value stable diff --git a/indra/newview/llfloateractivespeakers.h b/indra/newview/llfloateractivespeakers.h index 97221cb60..b8a9ece01 100644 --- a/indra/newview/llfloateractivespeakers.h +++ b/indra/newview/llfloateractivespeakers.h @@ -46,6 +46,9 @@ class LLButton; class LLPanelActiveSpeakers; class LLSpeakerMgr; class LLVoiceChannel; +class LLSlider; +class LLTextBox; +class LLCheckBoxCtrl; // data for a given participant in a voice channel @@ -296,6 +299,13 @@ protected: LLPointer mSpeakerAddListener; LLPointer mSpeakerRemoveListener; LLPointer mSpeakerClearListener; + + CachedUICtrl mVolumeSlider; + CachedUICtrl mModeratorCtrlLbl; + CachedUICtrl mModeratorAllowVoiceCheckbox; + CachedUICtrl mModeratorAllowTextCheckbox; + CachedUICtrl mModeratorModePanel; + CachedUICtrl mModeratorControlsPanel; }; diff --git a/indra/newview/llfloateravatarinfo.cpp b/indra/newview/llfloateravatarinfo.cpp index d3fc5596d..f60e24623 100644 --- a/indra/newview/llfloateravatarinfo.cpp +++ b/indra/newview/llfloateravatarinfo.cpp @@ -42,6 +42,7 @@ #include "llcommandhandler.h" #include "llpanelavatar.h" #include "lluictrlfactory.h" +#include "llweb.h" // linden library includes #include "llinventory.h" @@ -293,3 +294,13 @@ LLPreview::EAssetStatus LLFloaterAvatarInfo::getAssetStatus() } return mAssetStatus; } + +std::string getProfileURL(const std::string& agent_name) +{ + std::string url = gSavedSettings.getString("WebProfileURL"); + LLSD subs; + subs["AGENT_NAME"] = agent_name; + url = LLWeb::expandURLSubstitutions(url,subs); + LLStringUtil::toLower(url); + return url; +} diff --git a/indra/newview/llfloateravatarinfo.h b/indra/newview/llfloateravatarinfo.h index 9d78e18ec..6e608e9e4 100644 --- a/indra/newview/llfloateravatarinfo.h +++ b/indra/newview/llfloateravatarinfo.h @@ -101,5 +101,6 @@ private: EOnlineStatus mSuggestedOnlineStatus; }; +std::string getProfileURL(const std::string& agent_name); #endif diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index dec68245d..1a097aabb 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -135,9 +135,9 @@ void LLFloaterChat::draw() { // enable say and shout only when text available - childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel")); + mToggleActiveSpeakersBtn->setValue(mPanel->getVisible()); - LLChatBar* chat_barp = getChild("chat_panel", TRUE); + LLChatBar* chat_barp = mChatPanel; if (chat_barp) { chat_barp->refresh(); @@ -156,6 +156,9 @@ BOOL LLFloaterChat::postBuild() { chat_barp->setGestureCombo(getChild( "Gesture")); } + + mToggleActiveSpeakersBtn.connect(this,"toggle_active_speakers_btn"); + mChatPanel.connect(this,"chat_panel"); return TRUE; } @@ -452,20 +455,6 @@ void LLFloaterChat::addChat(const LLChat& chat, } // [/RLVa:KB] -#if LL_LCD_COMPILE - // add into LCD displays - if (!invisible_script_debug_chat) - { - if (!from_instant_message) - { - AddNewChatToLCD(chat.mText); - } - else - { - AddNewIMToLCD(chat.mText); - } - } -#endif if (!invisible_script_debug_chat && !chat.mMuted && gConsole diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h index 4f9a03be5..a3ef23fd0 100644 --- a/indra/newview/llfloaterchat.h +++ b/indra/newview/llfloaterchat.h @@ -50,6 +50,7 @@ class LLUUID; class LLCheckBoxCtrl; class LLPanelActiveSpeakers; class LLLogChat; +class LLChatBar; class LLFloaterChat : public LLFloater, public LLUISingleton @@ -95,6 +96,9 @@ public: LLPanelActiveSpeakers* mPanel; BOOL mScrolledToEnd; + + CachedUICtrl mToggleActiveSpeakersBtn; + CachedUICtrl mChatPanel; }; #endif diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp index 4f6b5fb5a..7028e5016 100644 --- a/indra/newview/llfloaterdaycycle.cpp +++ b/indra/newview/llfloaterdaycycle.cpp @@ -57,7 +57,6 @@ #include "lldaycyclemanager.h" #include "llwlparamset.h" #include "llwlparammanager.h" -#include "llpostprocess.h" #include "llfloaterwindlight.h" diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index d94c7cf8d..2b09b57d4 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -80,8 +80,6 @@ // stuff for Contact groups #include "ascentfloatercontactgroups.h" -//Maximum number of people you can select to do an operation on at once. -#define MAX_FRIEND_SELECT 20 #define DEFAULT_PERIOD 5.0 #define RIGHTS_CHANGE_TIMEOUT 5.0 #define OBSERVER_TIMEOUT 0.5 @@ -368,8 +366,6 @@ void LLPanelFriends::onChangeContactGroup(LLUICtrl* ctrl, void* user_data) BOOL LLPanelFriends::postBuild() { mFriendsList = getChild("friend_list"); - mFriendsList->setMaxSelectable(MAX_FRIEND_SELECT); - mFriendsList->setMaximumSelectCallback(onMaximumSelect); mFriendsList->setCommitOnSelectionChange(TRUE); childSetCommitCallback("friend_list", onSelectName, this); childSetCommitCallback("buddy_group_combobox", onChangeContactGroup, this); @@ -816,14 +812,6 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data) } } -//static -void LLPanelFriends::onMaximumSelect(void* user_data) -{ - LLSD args; - args["MAX_SELECT"] = llformat("%d", MAX_FRIEND_SELECT); - LLNotificationsUtil::add("MaxListSelectMessage", args); -}; - // static void LLPanelFriends::onClickProfile(void* user_data) { diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index b930d6627..e97aecc0f 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -135,7 +135,6 @@ private: static bool callbackAddFriend(const LLSD& notification, const LLSD& response); static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); static void onPickAvatar(const std::vector& names, const std::vector& ids, void* user_data); - static void onMaximumSelect(void* user_data); static void onContactSearchEdit(const std::string& search_string, void* user_data); static void onClickIM(void* user_data); static void onClickAssign(void* user_data); diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp index 40eb5e048..fd42f6d02 100644 --- a/indra/newview/llfloaterpostprocess.cpp +++ b/indra/newview/llfloaterpostprocess.cpp @@ -115,17 +115,8 @@ LLFloaterPostProcess* LLFloaterPostProcess::instance() void LLFloaterPostProcess::onControlChanged(LLUICtrl* ctrl, void* userData) { - char const *VariableName = (char const *)userData; - char buf[256]; - S32 elem=0; - if(sscanf(VariableName,"%255[^[][%d]", buf, &elem) == 2) - { - LLPostProcess::getInstance()->tweaks[(const char*)buf][elem] = ctrl->getValue(); - } - else - { - LLPostProcess::getInstance()->tweaks[VariableName] = ctrl->getValue(); - } + LLSD v = ctrl->getValue(); + LLPostProcess::getInstance()->setSelectedEffectValue((char const *)userData, v); } void LLFloaterPostProcess::onLoadEffect(void* userData) @@ -145,7 +136,7 @@ void LLFloaterPostProcess::onSaveEffect(void* userData) std::string effectName(editBox->getValue().asString()); - if (LLPostProcess::getInstance()->mAllEffects.has(effectName)) + if (LLPostProcess::getInstance()->getAllEffectInfo().has(effectName)) { LLSD payload; payload["effect_name"] = effectName; @@ -153,7 +144,7 @@ void LLFloaterPostProcess::onSaveEffect(void* userData) } else { - LLPostProcess::getInstance()->saveEffect(effectName); + LLPostProcess::getInstance()->saveEffectAs(effectName); sPostProcess->syncMenu(); } } @@ -175,7 +166,7 @@ bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLS // if they choose save, do it. Otherwise, don't do anything if (option == 0) { - LLPostProcess::getInstance()->saveEffect(notification["payload"]["effect_name"].asString()); + LLPostProcess::getInstance()->saveEffectAs(notification["payload"]["effect_name"].asString()); sPostProcess->syncMenu(); } @@ -209,17 +200,17 @@ void LLFloaterPostProcess::syncMenu() comboBox->removeall(); LLSD::map_const_iterator currEffect; - for(currEffect = LLPostProcess::getInstance()->mAllEffects.beginMap(); - currEffect != LLPostProcess::getInstance()->mAllEffects.endMap(); + for(currEffect = LLPostProcess::getInstance()->getAllEffectInfo().beginMap(); + currEffect != LLPostProcess::getInstance()->getAllEffectInfo().endMap(); ++currEffect) { comboBox->add(currEffect->first); } // set the current effect as selected. - comboBox->selectByValue(LLPostProcess::getInstance()->getSelectedEffect()); + comboBox->selectByValue(LLPostProcess::getInstance()->getSelectedEffectName()); - LLSD &tweaks = LLPostProcess::getInstance()->tweaks; + const LLSD &tweaks = LLPostProcess::getInstance()->getSelectedEffectInfo(); //Iterate down all uniforms handled by post-process shaders. Update any linked ui elements. for (LLSD::map_const_iterator it = tweaks.beginMap(); it != tweaks.endMap(); ++it) { diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index e5646174e..6d839b66d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -58,7 +58,6 @@ #include "llpanelgeneral.h" #include "llpanelinput.h" #include "llpanellogin.h" -#include "llpanelLCD.h" #include "llpanelmsgs.h" #include "llpanelweb.h" #include "llpanelskins.h" @@ -178,20 +177,6 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def mTabContainer->addTabPanel(mPrefsIM->getPanel(), mPrefsIM->getPanel()->getLabel()); mPrefsIM->getPanel()->setDefaultBtn(default_btn); -#if LL_LCD_COMPILE - - // only add this option if we actually have a logitech keyboard / speaker set - if (gLcdScreen->Enabled()) - { - mLCDPanel = new LLPanelLCD(); - mTabContainer->addTabPanel(mLCDPanel, mLCDPanel->getLabel()); - mLCDPanel->setDefaultBtn(default_btn); - } - -#else - mLCDPanel = NULL; -#endif - mMsgPanel = new LLPanelMsgs(); mTabContainer->addTabPanel(mMsgPanel, mMsgPanel->getLabel()); mMsgPanel->setDefaultBtn(default_btn); @@ -318,14 +303,6 @@ void LLPreferenceCore::apply() mPrefsAscentVan->apply(); mWebPanel->apply(); -#if LL_LCD_COMPILE - // only add this option if we actually have a logitech keyboard / speaker set - if (gLcdScreen->Enabled()) - { - mLCDPanel->apply(); - } -#endif -// mWebPanel->apply(); } @@ -347,14 +324,6 @@ void LLPreferenceCore::cancel() mPrefsAscentVan->cancel(); mWebPanel->cancel(); -#if LL_LCD_COMPILE - // only add this option if we actually have a logitech keyboard / speaker set - if (gLcdScreen->Enabled()) - { - mLCDPanel->cancel(); - } -#endif -// mWebPanel->cancel(); } // static diff --git a/indra/newview/llfloaterregiondebugconsole.cpp b/indra/newview/llfloaterregiondebugconsole.cpp new file mode 100644 index 000000000..9312781c4 --- /dev/null +++ b/indra/newview/llfloaterregiondebugconsole.cpp @@ -0,0 +1,237 @@ +/** + * @file llfloaterregiondebugconsole.h + * @author Brad Kittenbrink + * @brief Quick and dirty console for region debug settings + * + * $LicenseInfo:firstyear=2010&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 "llfloaterregiondebugconsole.h" + +#include "llagent.h" +#include "llhttpclient.h" +#include "llhttpnode.h" +#include "lllineeditor.h" +#include "lltexteditor.h" +#include "llviewerregion.h" +#include "lluictrlfactory.h" + +// Two versions of the sim console API are supported. +// +// SimConsole capability (deprecated): +// This is the initial implementation that is supported by some versions of the +// simulator. It is simple and straight forward, just POST a command and the +// body of the response has the result. This API is deprecated because it +// doesn't allow the sim to use any asynchronous API. +// +// SimConsoleAsync capability: +// This capability replaces the original SimConsole capability. It is similar +// in that the command is POSTed to the SimConsoleAsync cap, but the response +// comes in through the event poll, which gives the simulator more flexibility +// and allows it to perform complex operations without blocking any frames. +// +// We will assume the SimConsoleAsync capability is available, and fall back to +// the SimConsole cap if it is not. The simulator will only support one or the +// other. + +namespace +{ + // Signal used to notify the floater of responses from the asynchronous + // API. + console_reply_signal_t sConsoleReplySignal; + + const std::string PROMPT("\n\n> "); + const std::string UNABLE_TO_SEND_COMMAND( + "ERROR: The last command was not received by the server."); + const std::string CONSOLE_UNAVAILABLE( + "ERROR: No console available for this region/simulator."); + const std::string CONSOLE_NOT_SUPPORTED( + "This region does not support the simulator console."); + + // This responder handles the initial response. Unless error() is called + // we assume that the simulator has received our request. Error will be + // called if this request times out. + class AsyncConsoleResponder : public LLHTTPClient::Responder + { + public: + /* virtual */ + void error(U32 status, const std::string& reason) + { + sConsoleReplySignal(UNABLE_TO_SEND_COMMAND); + } + }; + + class ConsoleResponder : public LLHTTPClient::Responder + { + public: + ConsoleResponder(LLTextEditor *output) : mOutput(output) + { + } + + /*virtual*/ + void error(U32 status, const std::string& reason) + { + if (mOutput) + { + mOutput->appendText( + UNABLE_TO_SEND_COMMAND + PROMPT, + false, false); + } + } + + /*virtual*/ + void result(const LLSD& content) + { + if (mOutput) + { + mOutput->appendText( + content.asString() + PROMPT, false, false); + } + } + + LLTextEditor * mOutput; + }; + + // This handles responses for console commands sent via the asynchronous + // API. + class ConsoleResponseNode : public LLHTTPNode + { + public: + /* virtual */ + void post( + LLHTTPNode::ResponsePtr reponse, + const LLSD& context, + const LLSD& input) const + { + llinfos << "Received response from the debug console: " + << input << llendl; + sConsoleReplySignal(input["body"].asString()); + } + }; +} + +boost::signals2::connection LLFloaterRegionDebugConsole::setConsoleReplyCallback(const console_reply_signal_t::slot_type& cb) +{ + return sConsoleReplySignal.connect(cb); +} + +LLFloaterRegionDebugConsole::LLFloaterRegionDebugConsole() +: LLFloater(), mOutput(NULL) +{ + mReplySignalConnection = sConsoleReplySignal.connect( + boost::bind( + &LLFloaterRegionDebugConsole::onReplyReceived, + this, + _1)); + + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_region_debug_console.xml"); +} + +LLFloaterRegionDebugConsole::~LLFloaterRegionDebugConsole() +{ + mReplySignalConnection.disconnect(); +} + +BOOL LLFloaterRegionDebugConsole::postBuild() +{ + LLLineEditor* input = getChild("region_debug_console_input"); + input->setEnableLineHistory(true); + input->setCommitCallback(boost::bind(&LLFloaterRegionDebugConsole::onInput, this, _1, _2)); + input->setFocus(true); + input->setCommitOnFocusLost(false); + + mOutput = getChild("region_debug_console_output"); + + std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync"); + if (url.empty()) + { + // Fall back to see if the old API is supported. + url = gAgent.getRegion()->getCapability("SimConsole"); + if (url.empty()) + { + mOutput->appendText( + CONSOLE_NOT_SUPPORTED + PROMPT, + false, false); + return TRUE; + } + } + + mOutput->appendText("> ", false, false); + return TRUE; +} + +void LLFloaterRegionDebugConsole::onClose(bool app_quitting) +{ + LLFloater::onClose(app_quitting); + + if (!app_quitting) + { + delete this; + } +} + +void LLFloaterRegionDebugConsole::onInput(LLUICtrl* ctrl, const LLSD& param) +{ + LLLineEditor* input = static_cast(ctrl); + std::string text = input->getText() + "\n"; + + std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync"); + if (url.empty()) + { + // Fall back to the old API + url = gAgent.getRegion()->getCapability("SimConsole"); + if (url.empty()) + { + text += CONSOLE_UNAVAILABLE + PROMPT; + } + else + { + // Using SimConsole (deprecated) + LLHTTPClient::post( + url, + LLSD(input->getText()), + new ConsoleResponder(mOutput)); + } + } + else + { + // Using SimConsoleAsync + LLHTTPClient::post( + url, + LLSD(input->getText()), + new AsyncConsoleResponder); + } + + mOutput->appendText(text, false, false); + input->clear(); +} + +void LLFloaterRegionDebugConsole::onReplyReceived(const std::string& output) +{ + mOutput->appendText(output + PROMPT, false, false); +} + +LLHTTPRegistration + gHTTPRegistrationMessageDebugConsoleResponse( + "/message/SimConsoleResponse"); diff --git a/indra/newview/llfloaterregiondebugconsole.h b/indra/newview/llfloaterregiondebugconsole.h new file mode 100644 index 000000000..bc20ea9c4 --- /dev/null +++ b/indra/newview/llfloaterregiondebugconsole.h @@ -0,0 +1,63 @@ +/** + * @file llfloaterregiondebugconsole.h + * @author Brad Kittenbrink + * @brief Quick and dirty console for region debug settings + * + * $LicenseInfo:firstyear=2010&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_LLFLOATERREGIONDEBUGCONSOLE_H +#define LL_LLFLOATERREGIONDEBUGCONSOLE_H + +#include + +#include "llfloater.h" +#include "llhttpclient.h" + +class LLTextEditor; + +typedef boost::signals2::signal< + void (const std::string& output)> console_reply_signal_t; + +class LLFloaterRegionDebugConsole : public LLFloater, public LLHTTPClient::Responder, public LLSingleton +{ +public: + LLFloaterRegionDebugConsole(); + virtual ~LLFloaterRegionDebugConsole(); + + // virtual + BOOL postBuild(); + void onClose(bool app_quitting); + + void onInput(LLUICtrl* ctrl, const LLSD& param); + + LLTextEditor * mOutput; + + static boost::signals2::connection setConsoleReplyCallback(const console_reply_signal_t::slot_type& cb); + + private: + void onReplyReceived(const std::string& output); + + boost::signals2::connection mReplySignalConnection; +}; + +#endif // LL_LLFLOATERREGIONDEBUGCONSOLE_H diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index 07fae3df2..74f82e884 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -110,9 +110,6 @@ void click_popup_minimize(void*); void click_popup_grab_drag(LLUICtrl *, void*); void click_popup_grab_lift(LLUICtrl *, void*); void click_popup_grab_spin(LLUICtrl *, void*); -void click_popup_rotate_left(void*); -void click_popup_rotate_reset(void*); -void click_popup_rotate_right(void*); void click_popup_dozer_mode(LLUICtrl *, void *user); void commit_slider_dozer_size(LLUICtrl *, void*); void commit_slider_dozer_force(LLUICtrl *, void*); @@ -947,25 +944,6 @@ void commit_slider_zoom(LLUICtrl *ctrl, void*) gAgentCamera.setCameraZoomFraction(zoom_level); } -void click_popup_rotate_left(void*) -{ - LLSelectMgr::getInstance()->selectionRotateAroundZ( 45.f ); - dialog_refresh_all(); -} - -void click_popup_rotate_reset(void*) -{ - LLSelectMgr::getInstance()->selectionResetRotation(); - dialog_refresh_all(); -} - -void click_popup_rotate_right(void*) -{ - LLSelectMgr::getInstance()->selectionRotateAroundZ( -45.f ); - dialog_refresh_all(); -} - - void click_popup_dozer_mode(LLUICtrl *, void *user) { S32 mode = (S32)(intptr_t) user; diff --git a/indra/newview/llfloaterwater.cpp b/indra/newview/llfloaterwater.cpp index 04ef4e5af..0a72fdadf 100644 --- a/indra/newview/llfloaterwater.cpp +++ b/indra/newview/llfloaterwater.cpp @@ -62,7 +62,6 @@ #include "llwaterparamset.h" #include "llwaterparammanager.h" -#include "llpostprocess.h" #undef max diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp index 942763ad8..d84eaf2a2 100644 --- a/indra/newview/llfloaterwindlight.cpp +++ b/indra/newview/llfloaterwindlight.cpp @@ -62,7 +62,6 @@ #include "llwlparamset.h" #include "llwlparammanager.h" -#include "llpostprocess.h" #undef max diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index ebb0cb1aa..8563b98a4 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -118,20 +118,20 @@ public: virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse); virtual BOOL addFolder( LLFolderViewFolder* folder); - // Finds width and height of this object and it's children. Also - // makes sure that this view and it's children are the right size. + // Find width and height of this object and its children. Also + // makes sure that this view and its children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } - // applies filters to control visibility of inventory items + // Apply filters to control visibility of inventory items virtual void filter( LLInventoryFilter& filter); - // get the last selected item + // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); - // Record the selected item and pass it down the hierachy. + // Record the selected item and pass it down the hierarchy. virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); @@ -141,13 +141,13 @@ public: // Called once a frame to update the selection if mSelectThisID has been set void updateSelection(); - // This method is used to toggle the selection of an item. Walks - // children, and keeps track of selected objects. + // This method is used to toggle the selection of an item. + // Walks children and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); virtual std::set getSelectionList() const; - // make sure if ancestor is selected, descendents are not + // Make sure if ancestor is selected, descendents are not void sanitizeSelection(); void clearSelection(); void addToSelectionList(LLFolderViewItem* item); @@ -158,21 +158,21 @@ public: void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; } LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; } - // deletion functionality + // Deletion functionality void removeSelectedItems(); - // open the selected item. + // Open the selected item void openSelectedItems( void ); void propertiesSelectedItems( void ); - // change the folder type + // Change the folder type void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type); void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); - // copy & paste + // Copy & paste virtual void copy(); virtual BOOL canCopy() const; @@ -185,7 +185,7 @@ public: virtual void doDelete(); virtual BOOL canDoDelete() const; - // public rename functionality - can only start the process + // Public rename functionality - can only start the process void startRenamingSelectedItem( void ); // These functions were used when there was only one folderview, diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index ce2bb321a..f6cff6f16 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -408,7 +408,7 @@ void LLHoverView::updateText() LLViewerObject *parent = (LLViewerObject *)object->getParent(); if (object && - (object->usePhysics() || + (object->flagUsePhysics() || object->flagScripted() || object->flagHandleTouch() || (parent && parent->flagHandleTouch()) || object->flagTakesMoney() || (parent && parent->flagTakesMoney()) || @@ -423,7 +423,7 @@ void LLHoverView::updateText() line.append(LLTrans::getString("TooltipFlagScript") + " "); } - if (object->usePhysics()) + if (object->flagUsePhysics()) { line.append(LLTrans::getString("TooltipFlagPhysics") + " "); } @@ -456,7 +456,7 @@ void LLHoverView::updateText() line.append(LLTrans::getString("TooltipFlagTemporary") + " "); } - if (object->usePhysics() || + if (object->flagUsePhysics() || object->flagHandleTouch() || (parent && parent->flagHandleTouch()) ) { diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index ed2349717..27774273a 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1411,6 +1411,15 @@ BOOL LLFloaterIMPanel::postBuild() } setDefaultBtn("send_btn"); + + mActiveSpeakersPanel.connect(this,"active_speakers_panel"); + mToggleActiveSpeakersBtn.connect(this,"toggle_active_speakers_btn"); + mVolumeSlider.connect(this,"speaker_volume"); + mEndCallBtn.connect(this,"end_call_btn"); + mStartCallBtn.connect(this,"start_call_btn"); + mSendBtn.connect(this,"send_btn"); + mMuteBtn.connect(this,"mute_btn"); + return TRUE; } @@ -1466,10 +1475,10 @@ void LLFloaterIMPanel::draw() && mCallBackEnabled; // hide/show start call and end call buttons - childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); - childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); - childSetEnabled("start_call_btn", enable_connect); - childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty()); + mEndCallBtn->setVisible(LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); + mStartCallBtn->setVisible(LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); + mStartCallBtn->setEnabled(enable_connect); + mSendBtn->setEnabled(!childGetValue("chat_editor").asString().empty()); LLPointer self_speaker = mSpeakers->findSpeaker(gAgent.getID()); if(!mTextIMPossible) @@ -1497,10 +1506,10 @@ void LLFloaterIMPanel::draw() // show speakers window when voice first connects if (mShowSpeakersOnConnect && mVoiceChannel->isActive()) { - childSetVisible("active_speakers_panel", TRUE); + mActiveSpeakersPanel->setVisible(true); mShowSpeakersOnConnect = FALSE; } - childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel")); + mToggleActiveSpeakersBtn->setValue(mActiveSpeakersPanel->getVisible()); if (mTyping) { @@ -1531,11 +1540,11 @@ void LLFloaterIMPanel::draw() else { // refresh volume and mute checkbox - childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); - childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID)); + mVolumeSlider->setVisible(LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); + mVolumeSlider->setValue(gVoiceClient->getUserVolume(mOtherParticipantUUID)); - childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat)); - childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); + mMuteBtn->setValue(LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat)); + mMuteBtn->setVisible(LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); } LLFloater::draw(); } diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 9daed909f..943bd37c1 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -48,6 +48,8 @@ class LLInventoryItem; class LLInventoryCategory; class LLIMSpeakerMgr; class LLPanelActiveSpeakers; +class LLPanel; +class LLButton; class LLVoiceChannel : public LLVoiceClientStatusObserver { @@ -385,6 +387,13 @@ private: boost::signals2::connection mFocusLostSignal; + CachedUICtrl mActiveSpeakersPanel; + CachedUICtrl mToggleActiveSpeakersBtn; + CachedUICtrl mVolumeSlider; + CachedUICtrl mEndCallBtn; + CachedUICtrl mStartCallBtn; + CachedUICtrl mSendBtn; + CachedUICtrl mMuteBtn; void disableWhileSessionStarting(); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index cd0118ee9..304f00e4b 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -484,9 +484,12 @@ BOOL LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask) { LLSelectNode* selectNode = *iter; LLViewerObject* object = selectNode->getObject(); + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); // have permission to move and object is root of selection or individually selected - if (object->permMove() && (object->isRootEdit() || selectNode->mIndividualSelection)) + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (object->isRootEdit() || selectNode->mIndividualSelection)) { object->mUnselectedChildrenPositions.clear() ; } @@ -572,9 +575,12 @@ void LLManipRotate::drag( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject* object = selectNode->getObject(); + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); // have permission to move and object is root of selection or individually selected - if (object->permMove() && (object->isRootEdit() || selectNode->mIndividualSelection)) + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (object->isRootEdit() || selectNode->mIndividualSelection)) { if (!object->isRootEdit()) { @@ -626,9 +632,11 @@ void LLManipRotate::drag( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject* object = selectNode->getObject(); + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); // to avoid cumulative position changes we calculate the objects new position using its saved position - if (object && object->permMove()) + if (object && object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced())) { LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); @@ -709,7 +717,10 @@ void LLManipRotate::drag( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject*cur = selectNode->getObject(); - if( cur->permModify() && cur->permMove() && !cur->isAvatar()) + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !cur->isAvatar()) { selectNode->mLastRotation = cur->getRotation(); selectNode->mLastPositionLocal = cur->getPosition(); @@ -1876,7 +1887,10 @@ BOOL LLManipRotate::canAffectSelection() { virtual bool apply(LLViewerObject* objectp) { - return objectp->permMove() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); + return objectp->permMove() && !objectp->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); } } func; can_rotate = mObjectSelection->applyToObjects(&func); diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 9d09c30cf..bb282fb4d 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -825,7 +825,10 @@ void LLManipScale::drag( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject*cur = selectNode->getObject(); - if( cur->permModify() && cur->permMove() && !cur->isAvatar()) + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !cur->isAvatar()) { selectNode->mLastScale = cur->getScale(); selectNode->mLastPositionLocal = cur->getPosition(); @@ -972,7 +975,10 @@ void LLManipScale::dragCorner( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject* cur = selectNode->getObject(); - if( cur->permModify() && cur->permMove() && !cur->isAvatar() ) + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !cur->isAvatar() ) { const LLVector3& scale = selectNode->mSavedScale; @@ -994,7 +1000,10 @@ void LLManipScale::dragCorner( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject* cur = selectNode->getObject(); - if( cur->permModify() && cur->permMove() && !cur->isAvatar() && cur->isRootEdit() ) + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !cur->isAvatar() && cur->isRootEdit() ) { const LLVector3& scale = selectNode->mSavedScale; cur->setScale( scale_factor * scale ); @@ -1042,7 +1051,10 @@ void LLManipScale::dragCorner( S32 x, S32 y ) { LLSelectNode* selectNode = *iter; LLViewerObject*cur = selectNode->getObject(); - if( cur->permModify() && cur->permMove() && !cur->isAvatar() && !cur->isRootEdit() ) + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !cur->isAvatar() && !cur->isRootEdit() ) { const LLVector3& scale = selectNode->mSavedScale; cur->setScale( scale_factor * scale, FALSE ); @@ -1250,7 +1262,10 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto { LLSelectNode* selectNode = *iter; LLViewerObject*cur = selectNode->getObject(); - if( cur->permModify() && cur->permMove() && !cur->isAvatar() ) + LLViewerObject *root_object = (cur == NULL) ? NULL : cur->getRootEdit(); + if( cur->permModify() && cur->permMove() && !cur->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !cur->isAvatar() ) { LLBBox cur_bbox = cur->getBoundingBoxAgent(); LLVector3 start_local = cur_bbox.agentToLocal( drag_start_agent ); @@ -2057,7 +2072,10 @@ BOOL LLManipScale::canAffectSelection() { virtual bool apply(LLViewerObject* objectp) { - return objectp->permModify() && objectp->permMove() && !objectp->isSeat(); + LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); + return objectp->permModify() && objectp->permMove() && !objectp->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + !objectp->isSeat(); } } func; can_scale = mObjectSelection->applyToObjects(&func); diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b6feb554a..7c86889a1 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -705,7 +705,9 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } } - if (object->permMove()) + LLViewerObject* root_object = (object == NULL) ? NULL : object->getRootEdit(); + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced())) { // handle attachments in local space if (object->isAttachment() && object->mDrawable.notNull()) @@ -2328,7 +2330,10 @@ BOOL LLManipTranslate::canAffectSelection() { virtual bool apply(LLViewerObject* objectp) { - return objectp->permMove() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + LLViewerObject *root_object = (objectp == NULL) ? NULL : objectp->getRootEdit(); + return objectp->permMove() && !objectp->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); } } func; can_move = mObjectSelection->applyToObjects(&func); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 43fa98fbd..a203559c1 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -170,7 +170,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) if (mMediaSource) { - mMediaSource->mouseMove(x, y); + mMediaSource->mouseMove(x, y, mask); gViewerWindow->setCursor(mLastSetCursor); } @@ -198,7 +198,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) if (mMediaSource) { - mMediaSource->mouseUp(x, y); + mMediaSource->mouseUp(x, y, mask); /*// *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, // in addition to the onFocusReceived() call below. Undo this. JC @@ -222,7 +222,7 @@ BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) convertInputCoords(x, y); if (mMediaSource) - mMediaSource->mouseDown(x, y); + mMediaSource->mouseDown(x, y, mask); gFocusMgr.setMouseCapture( this ); @@ -265,11 +265,11 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) { if (LLUICtrl::handleRightMouseDown(x, y, mask)) return TRUE; - /*S32 media_x = x, media_y = y; + S32 media_x = x, media_y = y; convertInputCoords(media_x, media_y); if (mMediaSource) - mMediaSource->mouseDown(media_x, media_y); + mMediaSource->mouseDown(media_x, media_y, mask, 1); gFocusMgr.setMouseCapture( this ); @@ -277,7 +277,7 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) { setFocus( TRUE ); } - */ + return TRUE; } @@ -289,7 +289,7 @@ BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask ) convertInputCoords(x, y); if (mMediaSource) - mMediaSource->mouseLeftDoubleClick( x, y); + mMediaSource->mouseDoubleClick( x, y, mask); gFocusMgr.setMouseCapture( this ); @@ -916,20 +916,16 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_NAVIGATE_BEGIN: { - LL_INFOS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL; - if(mMediaSource && mHideLoading) - { - mMediaSource->suspendUpdates(true); - } + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL; }; break; case MEDIA_EVENT_NAVIGATE_COMPLETE: { - LL_INFOS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL; - if(mMediaSource && mHideLoading) + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL; + if(mHidingInitialLoad) { - mMediaSource->suspendUpdates(false); + mHidingInitialLoad = false; } }; break; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 602a1f153..ef25ae0e3 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -177,6 +177,7 @@ class LLMediaCtrl : bool mStretchToFill; bool mMaintainAspectRatio; bool mHideLoading; + bool mHidingInitialLoad; bool mDecoupleTextureSize; S32 mTextureWidth; S32 mTextureHeight; diff --git a/indra/newview/llmediaremotectrl.cpp b/indra/newview/llmediaremotectrl.cpp index 68db6b6b3..e8d04ff2b 100644 --- a/indra/newview/llmediaremotectrl.cpp +++ b/indra/newview/llmediaremotectrl.cpp @@ -89,6 +89,16 @@ BOOL LLMediaRemoteCtrl::postBuild() childSetAction("media_pause",LLOverlayBar::toggleMediaPlay,this); childSetAction("music_pause",LLOverlayBar::toggleMusicPlay,this); + mMusicPlayBtn.connect(this,"music_play"); + mMusicStopBtn.connect(this,"music_stop"); + mMusicPauseBtn.connect(this,"music_pause"); + mMediaPlayBtn.connect(this,"media_play"); + mMediaStopBtn.connect(this,"media_stop"); + mMediaPauseBtn.connect(this,"media_pause"); + mMediaIcon.connect(this,"media_icon"); + mMusicIcon.connect(this,"music_icon"); + mExpandBtn.connect(this,"expand"); + childSetAction("expand", onClickExpandBtn, this); LLButton *pause = getChild("music_pause"); @@ -101,7 +111,7 @@ void LLMediaRemoteCtrl::draw() { enableMediaButtons(); - LLButton* expand_button = getChild("expand"); + LLButton* expand_button = mExpandBtn; if (expand_button) { if (expand_button->getToggleState()) @@ -147,8 +157,8 @@ void LLMediaRemoteCtrl::setToolTip(const std::string& msg) std::string tool_tip = LLMIMETypes::findToolTip(mime_type); std::string play_tip = LLMIMETypes::findPlayTip(mime_type); // childSetToolTip("media_stop", mControls->getString("stop_label") + "\n" + tool_tip); - childSetToolTip("media_icon", tool_tip); - childSetToolTip("media_play", play_tip); + mMediaIcon->setToolTip(tool_tip); + mMediaIcon->setToolTip(play_tip); } void LLMediaRemoteCtrl::enableMediaButtons() @@ -227,13 +237,13 @@ void LLMediaRemoteCtrl::enableMediaButtons() // Don't test the mime-type: this is not updated in a consistent basis. The existence of a valid gAudiop is enough guarantee. } const std::string media_icon_name = LLMIMETypes::findIcon(media_type); - LLButton* music_play_btn = getChild("music_play"); - LLButton* music_stop_btn = getChild("music_stop"); - LLButton* music_pause_btn = getChild("music_pause"); - LLButton* media_play_btn = getChild("media_play"); - LLButton* media_stop_btn = getChild("media_stop"); - LLButton* media_pause_btn = getChild("media_pause"); - LLIconCtrl* media_icon = getChild("media_icon"); + LLButton* music_play_btn = mMusicPlayBtn; + LLButton* music_stop_btn = mMusicStopBtn; + LLButton* music_pause_btn = mMusicPauseBtn; + LLButton* media_play_btn = mMediaPlayBtn; + LLButton* media_stop_btn = mMediaPlayBtn; + LLButton* media_pause_btn = mMediaPauseBtn; + LLIconCtrl* media_icon = mMediaIcon; music_play_btn->setEnabled(play_music_enabled); music_stop_btn->setEnabled(stop_music_enabled); @@ -262,7 +272,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() music_pause_btn->setToolTip(mCachedPauseTip); } - childSetColor("music_icon", music_icon_color); + mMusicIcon->setColor(music_icon_color); if(!media_icon_name.empty()) { media_icon->setImage(media_icon_name); @@ -273,7 +283,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() media_pause_btn->setEnabled(media_show_pause); media_pause_btn->setVisible(media_show_pause); media_play_btn->setVisible(! media_show_pause); - childSetColor("media_icon", media_icon_color); + mMediaIcon->setColor(media_icon_color); setToolTip(media_url); } diff --git a/indra/newview/llmediaremotectrl.h b/indra/newview/llmediaremotectrl.h index 9fedfd386..22ff29866 100644 --- a/indra/newview/llmediaremotectrl.h +++ b/indra/newview/llmediaremotectrl.h @@ -36,6 +36,7 @@ #include "llpanel.h" class LLButton; +class LLIconCtrl; //////////////////////////////////////////////////////////////////////////////// // @@ -61,6 +62,16 @@ protected: void build(); std::string mCachedPauseTip; + + CachedUICtrl mMusicPlayBtn; + CachedUICtrl mMusicStopBtn; + CachedUICtrl mMusicPauseBtn; + CachedUICtrl mMediaPlayBtn; + CachedUICtrl mMediaStopBtn; + CachedUICtrl mMediaPauseBtn; + CachedUICtrl mExpandBtn; + CachedUICtrl mMediaIcon; + CachedUICtrl mMusicIcon; }; #endif diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp index ebbe2d114..5522f27a4 100644 --- a/indra/newview/lloverlaybar.cpp +++ b/indra/newview/lloverlaybar.cpp @@ -79,6 +79,8 @@ #include "rlvhandler.h" // [/RLVa:KB] +#include + // // Globals // @@ -189,7 +191,16 @@ BOOL LLOverlayBar::postBuild() setFocusRoot(TRUE); mBuilt = true; - mOriginalIMLabel = getChild("New IM")->getLabelSelected(); + mChatbarAndButtons.connect(this,"chatbar_and_buttons"); + mNewIM.connect(this,"New IM"); + mNotBusy.connect(this,"Set Not Busy"); + mMouseLook.connect(this,"Mouselook"); + mStandUp.connect(this,"Stand Up"); + mFlyCam.connect(this,"Flycam"); + mChatBar.connect(this,"chat_bar"); + mVoiceRemoteContainer.connect(this,"voice_remote_container"); + + mOriginalIMLabel = mNewIM->getLabelSelected(); layoutButtons(); @@ -203,6 +214,7 @@ BOOL LLOverlayBar::postBuild() childSetVisible("AdvSettings_container_exp", sAdvSettingsPopup); childSetVisible("ao_remote_container", gSavedSettings.getBOOL("EnableAORemote")); + return TRUE; } @@ -214,6 +226,12 @@ LLOverlayBar::~LLOverlayBar() // virtual void LLOverlayBar::reshape(S32 width, S32 height, BOOL called_from_parent) { + S32 delta_width = width - getRect().getWidth(); + S32 delta_height = height - getRect().getHeight(); + + if (!delta_width && !delta_height && !sForceReshape) + return; + LLView::reshape(width, height, called_from_parent); if (mBuilt) @@ -224,53 +242,60 @@ void LLOverlayBar::reshape(S32 width, S32 height, BOOL called_from_parent) void LLOverlayBar::layoutButtons() { - LLView* state_buttons_panel = getChildView("state_buttons"); + LLView* state_buttons_panel = getChildView("state_management_buttons_container"); if (state_buttons_panel->getVisible()) { - LLViewQuery query; - LLWidgetTypeFilter widget_filter; - query.addPreFilter(LLEnabledFilter::getInstance()); - query.addPreFilter(&widget_filter); + U32 required_width=0; + const child_list_t& view_list = *(state_buttons_panel->getChildList()); + BOOST_FOREACH(LLView* viewp, view_list) + { + required_width+=viewp->getRect().getWidth(); + } - child_list_t button_list = query(state_buttons_panel); + const S32 MAX_BAR_WIDTH = 800; + //const S32 MAX_BUTTON_WIDTH = 150; - const S32 MAX_BAR_WIDTH = 600; - S32 bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH); - - // calculate button widths - const S32 MAX_BUTTON_WIDTH = 150; - S32 segment_width = llclamp(lltrunc((F32)(bar_width) / (F32)button_list.size()), 0, MAX_BUTTON_WIDTH); - S32 btn_width = segment_width - gSavedSettings.getS32("StatusBarPad"); + static LLCachedControl status_bar_pad("StatusBarPad",10); + S32 usable_bar_width = llclamp(state_buttons_panel->getRect().getWidth(), 0, MAX_BAR_WIDTH) - (view_list.size()-1) * status_bar_pad; + F32 element_scale = (F32)usable_bar_width / (F32)required_width; // Evenly space all buttons, starting from left S32 left = 0; S32 bottom = 1; - for (child_list_reverse_iter_t child_iter = button_list.rbegin(); - child_iter != button_list.rend(); ++child_iter) + BOOST_REVERSE_FOREACH(LLView* viewp, view_list) { - LLView *view = *child_iter; - LLRect r = view->getRect(); - r.setOriginAndSize(left, bottom, btn_width, r.getHeight()); - view->setRect(r); - left += segment_width; + LLRect r = viewp->getRect(); + S32 new_width = r.getWidth() * element_scale; + //if(dynamic_cast(viewp)) + // new_width = llclamp(new_width,0,MAX_BUTTON_WIDTH); + r.setOriginAndSize(left, bottom, new_width, r.getHeight()); + viewp->setShape(r,false); + left += viewp->getRect().getWidth() + status_bar_pad; } } } +LLButton* LLOverlayBar::updateButtonVisiblity(LLButton* button, bool visible) +{ + if (button && (bool)button->getVisible() != visible) + { + button->setVisible(visible); + sendChildToFront(button); + moveChildToBackOfTabGroup(button); + } + return button; +} + // Per-frame updates of visibility void LLOverlayBar::refresh() { - BOOL buttons_changed = FALSE; + bool buttons_changed = FALSE; - BOOL im_received = gIMMgr->getIMReceived(); - int unread_count = gIMMgr->getIMUnreadCount(); - LLButton* button = getChild("New IM"); - - if ((button && button->getVisible() != im_received) || - (button && button->getVisible())) + if(LLButton* button = updateButtonVisiblity(mNewIM,gIMMgr->getIMReceived())) { + int unread_count = gIMMgr->getIMUnreadCount(); if (unread_count > 0) { if (unread_count > 1) @@ -284,86 +309,16 @@ void LLOverlayBar::refresh() button->setLabel("1 " + mOriginalIMLabel); } } - button->setVisible(im_received); - sendChildToFront(button); - moveChildToBackOfTabGroup(button); - buttons_changed = TRUE; + buttons_changed = true; } - - BOOL busy = gAgent.getBusy(); - button = getChild("Set Not Busy"); - if (button && button->getVisible() != busy) - { - button->setVisible(busy); - sendChildToFront(button); - moveChildToBackOfTabGroup(button); - buttons_changed = TRUE; - } - - BOOL flycam = LLViewerJoystick::getInstance()->getOverrideCamera(); - button = getChild("Flycam"); - if (button && button->getVisible() != flycam) - { - button->setVisible(flycam); - sendChildToFront(button); - moveChildToBackOfTabGroup(button); - buttons_changed = TRUE; - } - - BOOL mouselook_grabbed; - mouselook_grabbed = gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_DOWN_INDEX) - || gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_UP_INDEX); - button = getChild("Mouselook"); - - if (button && button->getVisible() != mouselook_grabbed) - { - button->setVisible(mouselook_grabbed); - sendChildToFront(button); - moveChildToBackOfTabGroup(button); - buttons_changed = TRUE; - } - - BOOL sitting = FALSE; - if (gAgentAvatarp) - { -// sitting = gAgentAvatarp->isSitting(); + buttons_changed |= updateButtonVisiblity(mNotBusy,gAgent.getBusy()) != NULL; + buttons_changed |= updateButtonVisiblity(mFlyCam,LLViewerJoystick::getInstance()->getOverrideCamera()) != NULL; + buttons_changed |= updateButtonVisiblity(mMouseLook,gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_DOWN_INDEX)||gAgent.isControlGrabbed(CONTROL_ML_LBUTTON_UP_INDEX)) != NULL; // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) - sitting = gAgentAvatarp->isSitting() && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); +// buttons_changed |= updateButtonVisiblity("Stand Up", isAgentAvatarValid() && gAgentAvatarp->isSitting()) != NULL; + buttons_changed |= updateButtonVisiblity(mStandUp,isAgentAvatarValid() && gAgentAvatarp->isSitting() && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) != NULL; // [/RLVa:KB] - } - button = getChild("Stand Up"); - - if (button && button->getVisible() != sitting) - { - button->setVisible(sitting); - sendChildToFront(button); - moveChildToBackOfTabGroup(button); - buttons_changed = TRUE; - } - - BOOL teleporting = FALSE; - if ((gAgent.getTeleportState() == LLAgent::TELEPORT_START) || - (gAgent.getTeleportState() == LLAgent::TELEPORT_REQUESTED) || - (gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING) || - (gAgent.getTeleportState() == LLAgent::TELEPORT_START)) - { - teleporting = TRUE; - } - else - { - teleporting = FALSE; - } - - - button = getChild("Cancel TP"); - - if (button && button->getVisible() != teleporting) - { - button->setVisible(teleporting); - sendChildToFront(button); - moveChildToBackOfTabGroup(button); - buttons_changed = TRUE; - } + buttons_changed |= updateButtonVisiblity(mCancelBtn,(gAgent.getTeleportState() >= LLAgent::TELEPORT_START) && (gAgent.getTeleportState() <= LLAgent::TELEPORT_MOVING)) != NULL; moveChildToBackOfTabGroup(mAORemote); moveChildToBackOfTabGroup(mMediaRemote); @@ -384,7 +339,7 @@ void LLOverlayBar::refresh() childSetVisible("AdvSettings_container", FALSE); childSetVisible("AdvSettings_container_exp", FALSE); childSetVisible("ao_remote_container", FALSE); - childSetVisible("state_buttons", FALSE); + childSetVisible("state_management_buttons_container", FALSE); } else { @@ -394,15 +349,15 @@ void LLOverlayBar::refresh() childSetVisible("AdvSettings_container", !sAdvSettingsPopup);//!gSavedSettings.getBOOL("wlfAdvSettingsPopup")); childSetVisible("AdvSettings_container_exp", sAdvSettingsPopup);//gSavedSettings.getBOOL("wlfAdvSettingsPopup")); childSetVisible("ao_remote_container", gSavedSettings.getBOOL("EnableAORemote")); - childSetVisible("state_buttons", TRUE); + childSetVisible("state_management_buttons_container", TRUE); } } if(!in_mouselook) - childSetVisible("voice_remote_container", LLVoiceClient::voiceEnabled()); + mVoiceRemoteContainer->setVisible(LLVoiceClient::voiceEnabled()); // always let user toggle into and out of chatbar static const LLCachedControl chat_visible("ChatVisible",true); - childSetVisible("chat_bar", chat_visible); + mChatBar->setVisible(chat_visible); if (buttons_changed) { diff --git a/indra/newview/lloverlaybar.h b/indra/newview/lloverlaybar.h index 8f9c8ed2f..365b2ac41 100644 --- a/indra/newview/lloverlaybar.h +++ b/indra/newview/lloverlaybar.h @@ -52,6 +52,7 @@ class LLSlider; class LLVoiceRemoteCtrl; class wlfPanel_AdvSettings; class AORemoteCtrl; +class LLChatBar; class LLOverlayBar : public LLPanel @@ -64,10 +65,14 @@ public: /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); /*virtual*/ BOOL postBuild(); + LLButton* updateButtonVisiblity(LLButton* button, bool visible); + void layoutButtons(); // helpers for returning desired state BOOL musicPlaying() { return mMusicState == PLAYING; } + + LLView* getChatbarAndButtons() const {return mChatbarAndButtons;} static void onClickIMReceived(void* data); static void onClickSetNotBusy(void* data); @@ -114,7 +119,14 @@ protected: S32 mMusicState; std::string mOriginalIMLabel; - + CachedUICtrl mChatbarAndButtons; + CachedUICtrl mNewIM; + CachedUICtrl mNotBusy; + CachedUICtrl mMouseLook; + CachedUICtrl mStandUp; + CachedUICtrl mFlyCam; + CachedUICtrl mChatBar; + CachedUICtrl mVoiceRemoteContainer; private: diff --git a/indra/newview/llpanelLCD.cpp b/indra/newview/llpanelLCD.cpp deleted file mode 100644 index ba7efba7b..000000000 --- a/indra/newview/llpanelLCD.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @file llpanellcd.cpp - * @brief lcd options panel - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelLCD.h" - -// linden library includes -#include "llerror.h" -#include "llrect.h" -#include "llfontgl.h" -#include "message.h" -#include "lluictrlfactory.h" - -// project includes -#include "llviewerwindow.h" -#include "llcheckboxctrl.h" -#include "llradiogroup.h" -#include "llresmgr.h" -#include "lltextbox.h" -#include "llui.h" -#include "llviewercontrol.h" - -//Ventrella -#include "llagent.h" -//end Ventrella - -// for Logitech LCD keyboards / speakers -#ifndef LL_LCD_H -#include "lllcd.h" -#endif - - -// -// Globals -// - -// -// Static functions -// - - -LLPanelLCD::LLPanelLCD() -{ - LLUICtrlFactory::getInstance()->buildPanel(this, "panel_preferences_lcd.xml"); -} - -BOOL LLPanelLCD::postBuild() -{ - requires("LCDDestination"); - requires("DisplayLinden"); - requires("DisplayDebug"); - requires("DisplayDebugConsole"); - requires("DisplayRegion"); - requires("DisplayChat"); - requires("DisplayIM"); - - if (!checkRequirements()) - { - return FALSE; - } - - refresh(); - - return TRUE; -} - - -LLPanelLCD::~LLPanelLCD() -{ - // Children all cleaned up by default view destructor. -} - -void LLPanelLCD::refresh() -{ - mLCDDestination = gSavedSettings.getS32("LCDDestination"); - mDisplayChat = gSavedSettings.getBOOL("DisplayChat"); - mDisplayIM = gSavedSettings.getBOOL("DisplayIM"); - mDisplayRegion = gSavedSettings.getBOOL("DisplayRegion"); - mDisplayDebug = gSavedSettings.getBOOL("DisplayDebug"); - mDisplayDebugConsole = gSavedSettings.getBOOL("DisplayDebugConsole"); - mDisplayLinden = gSavedSettings.getBOOL("DisplayLinden"); - - LLPanel::refresh(); -} - -void LLPanelLCD::apply() -{ - // nothing really to do here. -} - - -void LLPanelLCD::cancel() -{ - // doing this to restore situation when we entered this function - gSavedSettings.setS32("LCDDestination", mLCDDestination); - gSavedSettings.setBOOL("DisplayChat", mDisplayChat); - gSavedSettings.setBOOL("DisplayIM", mDisplayIM); - gSavedSettings.setBOOL("DisplayRegion", mDisplayRegion); - gSavedSettings.setBOOL("DisplayDebug", mDisplayDebug); - gSavedSettings.setBOOL("DisplayDebugConsole", mDisplayDebugConsole); - gSavedSettings.setBOOL("DisplayLinden", mDisplayLinden); -} \ No newline at end of file diff --git a/indra/newview/llpanelLCD.h b/indra/newview/llpanelLCD.h deleted file mode 100644 index 21eec3fc0..000000000 --- a/indra/newview/llpanelLCD.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file llpanelLCD.h - * @brief lcd options panel - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_PANEL_LCD_H -#define LL_PANEL_LCD_H - -#include "llpanel.h" - -class LLCheckBoxCtrl; - - -class LLPanelLCD : public LLPanel -{ -public: - LLPanelLCD(); - virtual ~LLPanelLCD(); - - virtual BOOL postBuild(); - virtual void refresh(); - void apply(); - void cancel(); - -protected: - S32 mLCDDestination; - BOOL mDisplayChat; - BOOL mDisplayRegion; - BOOL mDisplayDebug; - BOOL mDisplayDebugConsole; - BOOL mDisplayLinden; - BOOL mDisplayIM; - -}; - -#endif diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index cd03f92c6..c92e7c62d 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -121,7 +121,7 @@ void LLPanelContents::getState(LLViewerObject *objectp ) // BUG? Check for all objects being editable? bool editable = gAgent.isGodlike() - || (objectp->permModify() + || (objectp->permModify() && !objectp->isPermanentEnforced() && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); @@ -150,6 +150,9 @@ void LLPanelContents::getState(LLViewerObject *objectp ) all_volume && ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))); + + getChildView("button permissions")->setEnabled(!objectp->isPermanentEnforced()); + mPanelInventory->setEnabled(!objectp->isPermanentEnforced()); } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index a427529a5..d19d14a4b 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -516,7 +516,7 @@ void LLPanelFace::getState() && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()) { - BOOL editable = objectp->permModify(); + BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced(); // only turn on auto-adjust button if there is a media renderer and the media is loaded diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index fc78ecae6..4c2d0a38f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -394,7 +394,6 @@ LLPanelObject::LLPanelObject(const std::string& name) mIsPhysical(FALSE), mIsTemporary(FALSE), mIsPhantom(FALSE), - mCastShadows(TRUE), mSelectedType(MI_BOX) { } @@ -478,10 +477,10 @@ void LLPanelObject::getState( ) } // can move or rotate only linked group with move permissions, or sub-object with move and modify perms - BOOL enable_move = objectp->permMove() && ((!objectp->isAttachment() && objectp->permModify()) || !gSavedSettings.getBOOL("EditLinkedParts")); - BOOL enable_scale = objectp->permMove() && objectp->permModify(); - BOOL enable_rotate = objectp->permMove() && ((objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); - BOOL enable_link = objectp->permMove() && ((!objectp->isAttachment() && objectp->permModify()) || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_move = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_scale = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && objectp->permModify(); + BOOL enable_rotate = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); + childSetEnabled("build_math_constants",true); S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) @@ -528,8 +527,8 @@ void LLPanelObject::getState( ) mCtrlPosX->setEnabled(enable_move); mCtrlPosY->setEnabled(enable_move); mCtrlPosZ->setEnabled(enable_move); - mBtnLinkObj->setEnabled((enable_link && !single_volume)); - mBtnUnlinkObj->setEnabled((enable_link && (selected_count > 1))); + mBtnLinkObj->setEnabled((enable_move && !single_volume)); + mBtnUnlinkObj->setEnabled((enable_move && (selected_count > 1))); mBtnCopyPos->setEnabled(enable_move); mBtnPastePos->setEnabled(enable_move); mBtnPastePosClip->setEnabled(enable_move); @@ -624,9 +623,15 @@ void LLPanelObject::getState( ) childSetVisible("select_single", TRUE); childSetEnabled("select_single", TRUE); } + BOOL is_flexible = volobjp && volobjp->isFlexible(); + BOOL is_permanent = root_objectp->flagObjectPermanent(); + BOOL is_permanent_enforced = root_objectp->isPermanentEnforced(); + BOOL is_character = root_objectp->flagCharacter(); + llassert(!is_permanent || !is_character); // should never have a permanent object that is also a character + // Lock checkbox - only modifiable if you own the object. BOOL self_owned = (gAgent.getID() == owner_id); - mCheckLock->setEnabled( roots_selected > 0 && self_owned ); + mCheckLock->setEnabled( roots_selected > 0 && self_owned && !is_permanent_enforced); // More lock and debit checkbox - get the values BOOL valid; @@ -656,29 +661,27 @@ void LLPanelObject::getState( ) } } - BOOL is_flexible = volobjp && volobjp->isFlexible(); - // Physics checkbox - mIsPhysical = root_objectp->usePhysics(); + mIsPhysical = root_objectp->flagUsePhysics(); + llassert(!is_permanent || !mIsPhysical); // should never have a permanent object that is also physical + mCheckPhysics->set( mIsPhysical ); mCheckPhysics->setEnabled( roots_selected>0 && (editable || gAgent.isGodlike()) - && !is_flexible); + && !is_flexible && !is_permanent); mIsTemporary = root_objectp->flagTemporaryOnRez(); + llassert(!is_permanent || !mIsTemporary); // should never has a permanent object that is also temporary + mCheckTemporary->set( mIsTemporary ); - mCheckTemporary->setEnabled( roots_selected>0 && editable ); + mCheckTemporary->setEnabled( roots_selected>0 && editable && !is_permanent); mIsPhantom = root_objectp->flagPhantom(); + BOOL is_volume_detect = root_objectp->flagVolumeDetect(); + llassert(!is_character || !mIsPhantom); // should never have a character that is also a phantom mCheckPhantom->set( mIsPhantom ); - mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible ); + mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible && !is_permanent_enforced && !is_character && !is_volume_detect); -#if 0 // 1.9.2 - mCastShadows = root_objectp->flagCastShadows(); - mCheckCastShadows->set( mCastShadows ); - mCheckCastShadows->setEnabled( roots_selected==1 && editable ); -#endif - // Update material part // slightly inefficient - materials are unique per object, not per TE U8 material_code = 0; @@ -731,6 +734,7 @@ void LLPanelObject::getState( ) BOOL hole_enabled = FALSE; F32 scale_x=1.f, scale_y=1.f; BOOL isMesh = FALSE; + if( !objectp || !objectp->getVolume() || !editable || !single_volume) { // Clear out all geometry fields. @@ -759,11 +763,10 @@ void LLPanelObject::getState( ) { // Only allowed to change these parameters for objects // that you have permissions on AND are not attachments. - enabled = root_objectp->permModify(); - - const LLVolumeParams &volume_params = objectp->getVolume()->getParams(); - + enabled = root_objectp->permModify() && !root_objectp->isPermanentEnforced(); + // Volume type + const LLVolumeParams &volume_params = objectp->getVolume()->getParams(); U8 path = volume_params.getPathParams().getCurveType(); U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); U8 profile = profile_and_hole & LL_PCODE_PROFILE_MASK; @@ -1525,22 +1528,6 @@ void LLPanelObject::sendIsPhantom() } } -void LLPanelObject::sendCastShadows() -{ - BOOL value = mCheckCastShadows->get(); - if( mCastShadows != value ) - { - LLSelectMgr::getInstance()->selectionUpdateCastShadows(value); - mCastShadows = value; - - llinfos << "update cast shadows sent" << llendl; - } - else - { - llinfos << "update cast shadows not changed" << llendl; - } -} - // static void LLPanelObject::onCommitMaterial( LLUICtrl* ctrl, void* userdata ) { @@ -2369,10 +2356,6 @@ void LLPanelObject::clearCtrls() mCheckTemporary ->setEnabled( FALSE ); mCheckPhantom ->set(FALSE); mCheckPhantom ->setEnabled( FALSE ); -#if 0 // 1.9.2 - mCheckCastShadows->set(FALSE); - mCheckCastShadows->setEnabled( FALSE ); -#endif mComboMaterial ->setEnabled( FALSE ); mLabelMaterial ->setEnabled( FALSE ); // Disable text labels @@ -2468,14 +2451,6 @@ void LLPanelObject::onCommitPhantom( LLUICtrl* ctrl, void* userdata ) self->sendIsPhantom(); } -// static -void LLPanelObject::onCommitCastShadows( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - self->sendCastShadows(); -} - - // static void LLPanelObject::onSelectSculpt(LLUICtrl* ctrl, void* userdata) { diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h index 504e3d94f..6bcf109ad 100644 --- a/indra/newview/llpanelobject.h +++ b/indra/newview/llpanelobject.h @@ -72,7 +72,6 @@ public: static void onCommitPhysics( LLUICtrl* ctrl, void* userdata); static void onCommitTemporary( LLUICtrl* ctrl, void* userdata); static void onCommitPhantom( LLUICtrl* ctrl, void* userdata); - static void onCommitCastShadows( LLUICtrl* ctrl, void* userdata); static void onLinkObj( void* user_data); static void onUnlinkObj( void* user_data); @@ -110,7 +109,6 @@ protected: void sendIsPhysical(); void sendIsTemporary(); void sendIsPhantom(); - void sendCastShadows(); void sendSculpt(); void getVolumeParams(LLVolumeParams& volume_params); @@ -207,7 +205,6 @@ protected: LLCheckBoxCtrl *mCheckPhysics; LLCheckBoxCtrl *mCheckTemporary; LLCheckBoxCtrl *mCheckPhantom; - LLCheckBoxCtrl *mCheckCastShadows; LLTextureCtrl *mCtrlSculptTexture; LLTextBox *mLabelSculptType; @@ -222,7 +219,6 @@ protected: BOOL mIsPhysical; // to avoid sending "physical" when not changed BOOL mIsTemporary; // to avoid sending "temporary" when not changed BOOL mIsPhantom; // to avoid sending "phantom" when not changed - BOOL mCastShadows; // to avoid sending "cast shadows" when not changed S32 mSelectedType; // So we know what selected type we last were LLUUID mSculptTextureRevert; // so we can revert the sculpt texture on cancel diff --git a/indra/newview/llpanelpathfindingrebakenavmesh.cpp b/indra/newview/llpanelpathfindingrebakenavmesh.cpp new file mode 100644 index 000000000..ca4bcfb67 --- /dev/null +++ b/indra/newview/llpanelpathfindingrebakenavmesh.cpp @@ -0,0 +1,281 @@ +/** +* @file llpanelpathfindingrebakenavmesh.cpp +* @brief Implementation of llpanelpathfindingrebakenavmesh +* @author Prep@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpanelpathfindingrebakenavmesh.h" + +#include +#include + +#include "llagent.h" +#include "llbutton.h" +#include "llenvmanager.h" +#include "llnotificationsutil.h" +#include "llpanel.h" +#include "llpathfindingmanager.h" +#include "llpathfindingnavmesh.h" +#include "llpathfindingnavmeshstatus.h" +#include "lltoolbar.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" +#include "lluictrlfactory.h" + + +LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getInstance() +{ + static LLPanelPathfindingRebakeNavmesh* panel = getPanel(); + return panel; +} + +BOOL LLPanelPathfindingRebakeNavmesh::postBuild() +{ + //Rebake button + mNavMeshRebakeButton = getChild("navmesh_btn"); + llassert(mNavMeshRebakeButton != NULL); + mNavMeshRebakeButton->setCommitCallback(boost::bind(&LLPanelPathfindingRebakeNavmesh::onNavMeshRebakeClick, this)); + //LLHints::registerHintTarget("navmesh_btn", mNavMeshRebakeButton->getHandle()); + + //Sending rebake request + mNavMeshSendingButton = findChild("navmesh_btn_sending"); + llassert(mNavMeshSendingButton != NULL); + //LLHints::registerHintTarget("navmesh_btn_sending", mNavMeshSendingButton->getHandle()); + + //rebaking... + mNavMeshBakingButton = findChild("navmesh_btn_baking"); + llassert(mNavMeshBakingButton != NULL); + //LLHints::registerHintTarget("navmesh_btn_baking", mNavMeshBakingButton->getHandle()); + + setMode(kRebakeNavMesh_Default); + + createNavMeshStatusListenerForCurrentRegion(); + + if ( !mRegionCrossingSlot.connected() ) + { + mRegionCrossingSlot = LLEnvManagerNew::getInstance()->setRegionChangeCallback(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleRegionBoundaryCrossed, this)); + } + + if (!mAgentStateSlot.connected()) + { + mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleAgentState, this, _1)); + } + LLPathfindingManager::getInstance()->requestGetAgentState(); + + return LLPanel::postBuild(); +} + +void LLPanelPathfindingRebakeNavmesh::draw() +{ + if (doDraw()) + { + updatePosition(); + LLPanel::draw(); + } +} + +BOOL LLPanelPathfindingRebakeNavmesh::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) +{ + gViewerWindow->unblockToolTips(); + + if (mNavMeshRebakeButton->getVisible()) + { + msg=mNavMeshRebakeButton->getToolTip(); + //LLToolTipMgr::instance().show(mNavMeshRebakeButton->getToolTip()); + } + else if (mNavMeshSendingButton->getVisible()) + { + msg=mNavMeshSendingButton->getToolTip(); + //LLToolTipMgr::instance().show(mNavMeshSendingButton->getToolTip()); + } + else if (mNavMeshBakingButton->getVisible()) + { + msg=mNavMeshBakingButton->getToolTip(); + //LLToolTipMgr::instance().show(mNavMeshBakingButton->getToolTip()); + } + + // Convert rect local to screen coordinates + localPointToScreen( + 0, 0, + &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) ); + localPointToScreen( + getRect().getWidth(), getRect().getHeight(), + &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); + return true;//LLPanel::handleToolTip(x, y, mask); +} + +LLPanelPathfindingRebakeNavmesh::LLPanelPathfindingRebakeNavmesh() + : LLPanel(), + mCanRebakeRegion(FALSE), + mRebakeNavMeshMode(kRebakeNavMesh_Default), + mNavMeshRebakeButton(NULL), + mNavMeshSendingButton(NULL), + mNavMeshBakingButton(NULL), + mNavMeshSlot(), + mRegionCrossingSlot(), + mAgentStateSlot() +{ + // make sure we have the only instance of this class + static bool b = true; + llassert_always(b); + b=false; +} + +LLPanelPathfindingRebakeNavmesh::~LLPanelPathfindingRebakeNavmesh() +{ +} + +LLPanelPathfindingRebakeNavmesh* LLPanelPathfindingRebakeNavmesh::getPanel() +{ + LLPanelPathfindingRebakeNavmesh* panel = new LLPanelPathfindingRebakeNavmesh(); + LLUICtrlFactory::getInstance()->buildPanel(panel,"panel_navmesh_rebake.xml"); + return panel; +} + +void LLPanelPathfindingRebakeNavmesh::setMode(ERebakeNavMeshMode pRebakeNavMeshMode) +{ + if (pRebakeNavMeshMode == kRebakeNavMesh_Available) + { + LLNotificationsUtil::add("PathfindingRebakeNavmesh"); + } + mNavMeshRebakeButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_Available); + mNavMeshSendingButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_RequestSent); + mNavMeshBakingButton->setVisible(pRebakeNavMeshMode == kRebakeNavMesh_InProgress); + mRebakeNavMeshMode = pRebakeNavMeshMode; +} + +LLPanelPathfindingRebakeNavmesh::ERebakeNavMeshMode LLPanelPathfindingRebakeNavmesh::getMode() const +{ + return mRebakeNavMeshMode; +} + +void LLPanelPathfindingRebakeNavmesh::onNavMeshRebakeClick() +{ + setMode(kRebakeNavMesh_RequestSent); + LLPathfindingManager::getInstance()->requestRebakeNavMesh(boost::bind(&LLPanelPathfindingRebakeNavmesh::handleRebakeNavMeshResponse, this, _1)); +} + +void LLPanelPathfindingRebakeNavmesh::handleAgentState(BOOL pCanRebakeRegion) +{ + mCanRebakeRegion = pCanRebakeRegion; +} + +void LLPanelPathfindingRebakeNavmesh::handleRebakeNavMeshResponse(bool pResponseStatus) +{ + if (getMode() == kRebakeNavMesh_RequestSent) + { + setMode(pResponseStatus ? kRebakeNavMesh_InProgress : kRebakeNavMesh_Default); + } + + if (!pResponseStatus) + { + LLNotificationsUtil::add("PathfindingCannotRebakeNavmesh"); + } +} + +void LLPanelPathfindingRebakeNavmesh::handleNavMeshStatus(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + ERebakeNavMeshMode rebakeNavMeshMode = kRebakeNavMesh_Default; + if (pNavMeshStatus.isValid()) + { + switch (pNavMeshStatus.getStatus()) + { + case LLPathfindingNavMeshStatus::kPending : + case LLPathfindingNavMeshStatus::kRepending : + rebakeNavMeshMode = kRebakeNavMesh_Available; + break; + case LLPathfindingNavMeshStatus::kBuilding : + rebakeNavMeshMode = kRebakeNavMesh_InProgress; + break; + case LLPathfindingNavMeshStatus::kComplete : + rebakeNavMeshMode = kRebakeNavMesh_NotAvailable; + break; + default : + rebakeNavMeshMode = kRebakeNavMesh_Default; + llassert(0); + break; + } + } + + setMode(rebakeNavMeshMode); +} + +void LLPanelPathfindingRebakeNavmesh::handleRegionBoundaryCrossed() +{ + createNavMeshStatusListenerForCurrentRegion(); + mCanRebakeRegion = FALSE; + LLPathfindingManager::getInstance()->requestGetAgentState(); +} + +void LLPanelPathfindingRebakeNavmesh::createNavMeshStatusListenerForCurrentRegion() +{ + if (mNavMeshSlot.connected()) + { + mNavMeshSlot.disconnect(); + } + + LLViewerRegion *currentRegion = gAgent.getRegion(); + if (currentRegion != NULL) + { + mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(currentRegion, boost::bind(&LLPanelPathfindingRebakeNavmesh::handleNavMeshStatus, this, _2)); + LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(currentRegion, true); + } +} + +bool LLPanelPathfindingRebakeNavmesh::doDraw() const +{ + return (mCanRebakeRegion && (mRebakeNavMeshMode != kRebakeNavMesh_NotAvailable)); +} + +void LLPanelPathfindingRebakeNavmesh::updatePosition() +{ +#if 0 + S32 y_pos = 0; + S32 bottom_tb_center = 0; + + if (LLToolBar* toolbar_bottom = gToolBarView->getChild("toolbar_bottom")) + { + y_pos = toolbar_bottom->getRect().getHeight(); + bottom_tb_center = toolbar_bottom->getRect().getCenterX(); + } + + S32 left_tb_width = 0; + if (LLToolBar* toolbar_left = gToolBarView->getChild("toolbar_left")) + { + left_tb_width = toolbar_left->getRect().getWidth(); + } + + if(LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container")) + { + panel_ssf_container->setOrigin(0, y_pos); + } + + S32 x_pos = bottom_tb_center-getRect().getWidth()/2 - left_tb_width + 113 /* width of stand/fly button *//* + 10 *//* margin */; + + /*setOrigin( x_pos, 0);*/ +#endif +} diff --git a/indra/newview/llpanelpathfindingrebakenavmesh.h b/indra/newview/llpanelpathfindingrebakenavmesh.h new file mode 100644 index 000000000..5aa1c68d8 --- /dev/null +++ b/indra/newview/llpanelpathfindingrebakenavmesh.h @@ -0,0 +1,96 @@ +/** +* @file llpanelpathfindingrebakenavmesh.h +* @brief Header file for llpanelpathfindingrebakenavmesh +* @author Prep@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPANELPATHFINDINGREBAKENAVMESH_H +#define LL_LLPANELPATHFINDINGREBAKENAVMESH_H + +#include + +#include "llpanel.h" +#include "llpathfindingmanager.h" +#include "llpathfindingnavmesh.h" + +class LLButton; +class LLPathfindingNavMeshStatus; + +class LLPanelPathfindingRebakeNavmesh : public LLPanel +{ + + LOG_CLASS(LLPanelPathfindingRebakeNavmesh); + +public: + static LLPanelPathfindingRebakeNavmesh* getInstance(); + + virtual BOOL postBuild(); + + virtual void draw(); + virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); + +protected: + +private: + typedef enum + { + kRebakeNavMesh_Available, + kRebakeNavMesh_RequestSent, + kRebakeNavMesh_InProgress, + kRebakeNavMesh_NotAvailable, + kRebakeNavMesh_Default = kRebakeNavMesh_NotAvailable + } ERebakeNavMeshMode; + + LLPanelPathfindingRebakeNavmesh(); + virtual ~LLPanelPathfindingRebakeNavmesh(); + + static LLPanelPathfindingRebakeNavmesh* getPanel(); + + void setMode(ERebakeNavMeshMode pRebakeNavMeshMode); + ERebakeNavMeshMode getMode() const; + + void onNavMeshRebakeClick(); + + void handleAgentState(BOOL pCanRebakeRegion); + void handleRebakeNavMeshResponse(bool pResponseStatus); + void handleNavMeshStatus(const LLPathfindingNavMeshStatus &pNavMeshStatus); + void handleRegionBoundaryCrossed(); + + void createNavMeshStatusListenerForCurrentRegion(); + + bool doDraw() const; + void updatePosition(); + + BOOL mCanRebakeRegion; + ERebakeNavMeshMode mRebakeNavMeshMode; + + LLButton* mNavMeshRebakeButton; + LLButton* mNavMeshSendingButton; + LLButton* mNavMeshBakingButton; + + LLPathfindingNavMesh::navmesh_slot_t mNavMeshSlot; + boost::signals2::connection mRegionCrossingSlot; + LLPathfindingManager::agent_state_slot_t mAgentStateSlot; +}; + +#endif // LL_LLPANELPATHFINDINGREBAKENAVMESH_H diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 8e42927fd..c501e9de0 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -66,6 +66,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" #include "roles_constants.h" +#include "lltrans.h" #include "hippogridmanager.h" @@ -280,6 +281,10 @@ void LLPanelPermissions::refresh() BOOL is_perm_modify = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() && LLSelectMgr::getInstance()->selectGetRootsModify()) || LLSelectMgr::getInstance()->selectGetModify(); + BOOL is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) + || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced(); + const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); S32 string_index = 0; std::string MODIFY_INFO_STRINGS[] = @@ -287,12 +292,18 @@ void LLPanelPermissions::refresh() getString("text modify info 1"), getString("text modify info 2"), getString("text modify info 3"), - getString("text modify info 4") + getString("text modify info 4"), + getString("text modify info 5"), + getString("text modify info 6") }; if(!is_perm_modify) { string_index += 2; } + else if (!is_nonpermanent_enforced) + { + string_index += 4; + } if(!is_one_object) { ++string_index; @@ -300,6 +311,34 @@ void LLPanelPermissions::refresh() childSetEnabled("perm_modify",true); childSetText("perm_modify",MODIFY_INFO_STRINGS[string_index]); + std::string pfAttrName; + + if ((LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsNonPathfinding()) + || LLSelectMgr::getInstance()->selectGetNonPathfinding()) + { + pfAttrName = "Pathfinding_Object_Attr_None"; + } + else if ((LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsPermanent()) + || LLSelectMgr::getInstance()->selectGetPermanent()) + { + pfAttrName = "Pathfinding_Object_Attr_Permanent"; + } + else if ((LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsCharacter()) + || LLSelectMgr::getInstance()->selectGetCharacter()) + { + pfAttrName = "Pathfinding_Object_Attr_Character"; + } + else + { + pfAttrName = "Pathfinding_Object_Attr_MultiSelect"; + } + + getChildView("pathfinding_attributes_value")->setEnabled(TRUE); + getChild("pathfinding_attributes_value")->setValue(LLTrans::getString(pfAttrName)); + childSetEnabled("Permissions:",true); // Update creator text field @@ -394,12 +433,12 @@ void LLPanelPermissions::refresh() } } - childSetEnabled("button set group",owners_identical && (mOwnerID == gAgent.getID())); + childSetEnabled("button set group",owners_identical && (mOwnerID == gAgent.getID()) && is_nonpermanent_enforced); childSetEnabled("button open group", group_id.notNull()); // figure out the contents of the name, description, & category BOOL edit_name_desc = FALSE; - if(is_one_object && objectp->permModify()) + if(is_one_object && objectp->permModify() && !objectp->isPermanentEnforced()) { edit_name_desc = TRUE; } @@ -628,15 +667,13 @@ void LLPanelPermissions::refresh() bool has_change_perm_ability = false; bool has_change_sale_ability = false; - if(valid_base_perms - && (self_owned - || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE)))) + if(valid_base_perms && is_nonpermanent_enforced && + (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE)))) { has_change_perm_ability = true; } - if(valid_base_perms - && (self_owned - || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE)))) + if(valid_base_perms && is_nonpermanent_enforced && + (self_owned || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE)))) { has_change_sale_ability = true; } @@ -847,8 +884,8 @@ void LLPanelPermissions::refresh() ComboClickAction->setCurrentByIndex((S32)click_action); } } - childSetEnabled("label click action",is_perm_modify && all_volume); - childSetEnabled("clickaction",is_perm_modify && all_volume); + childSetEnabled("label click action",is_perm_modify && is_nonpermanent_enforced && all_volume); + childSetEnabled("clickaction",is_perm_modify && is_nonpermanent_enforced && all_volume); } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 17f6ff4a9..ac0085757 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -83,13 +83,17 @@ #include "llviewercontrol.h" #include "llmeshrepository.h" +#include "llnotificationsutil.h" + +#include + // "Features" Tab BOOL LLPanelVolume::postBuild() { // Flexible Objects Parameters { - childSetCommitCallback("Flexible1D Checkbox Ctrl",onCommitIsFlexible,this); + getChild("Flexible1D Checkbox Ctrl")->setCommitCallback(boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL); childSetCommitCallback("FlexNumSections",onCommitFlexible,this); getChild("FlexNumSections")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexGravity",onCommitFlexible,this); @@ -246,7 +250,7 @@ void LLPanelVolume::getState( ) owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); // BUG? Check for all objects being editable? - BOOL editable = root_objectp->permModify(); + BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced(); BOOL single_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) && LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1; @@ -344,7 +348,7 @@ void LLPanelVolume::getState( ) getChild("Flexible1D Checkbox Ctrl")->setValue(is_flexible); if (is_flexible || (volobjp && volobjp->canBeFlexible())) { - getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh()); + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp && !volobjp->isMesh() && !objectp->isPermanentEnforced()); } else { @@ -449,7 +453,7 @@ void LLPanelVolume::getState( ) mComboPhysicsShapeType->add(getString("Convex Hull"), LLSD(2)); mComboPhysicsShapeType->setValue(LLSD(objectp->getPhysicsShapeType())); - mComboPhysicsShapeType->setEnabled(editable); + mComboPhysicsShapeType->setEnabled(editable && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced())); mObject = objectp; mRootObject = root_objectp; @@ -810,10 +814,26 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) self->refresh(); } -// static -void LLPanelVolume::onCommitIsFlexible( LLUICtrl* ctrl, void* userdata ) +void LLPanelVolume::onCommitIsFlexible(LLUICtrl *, void*) { - LLPanelVolume* self = (LLPanelVolume*) userdata; - self->sendIsFlexible(); + if (mObject->flagObjectPermanent()) + { + LLNotificationsUtil::add("PathfindingLinksets_ChangeToFlexiblePath", LLSD(), LLSD(), boost::bind(&LLPanelVolume::handleResponseChangeToFlexible, this, _1, _2)); + } + else + { + sendIsFlexible(); + } } +void LLPanelVolume::handleResponseChangeToFlexible(const LLSD &pNotification, const LLSD &pResponse) +{ + if (LLNotificationsUtil::getSelectedOption(pNotification, pResponse) == 0) + { + sendIsFlexible(); + } + else + { + getChild("Flexible1D Checkbox Ctrl")->setValue(FALSE); + } +} diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index abf460dd0..1446c72db 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -68,7 +68,7 @@ public: static void onCommitIsLight( LLUICtrl* ctrl, void* userdata); static void onCommitLight( LLUICtrl* ctrl, void* userdata); - static void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); + void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); static void onCommitFlexible( LLUICtrl* ctrl, void* userdata); static void onCommitPhysicsParam( LLUICtrl* ctrl, void* userdata); @@ -89,6 +89,8 @@ protected: void sendPhysicsFriction(LLUICtrl* ctrl, void* userdata); void sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata); void sendPhysicsDensity(LLUICtrl* ctrl, void* userdata); + + void handleResponseChangeToFlexible(const LLSD &pNotification, const LLSD &pResponse); /* LLTextBox* mLabelSelectSingleMessage; // Light diff --git a/indra/newview/llpathfindingcharacter.cpp b/indra/newview/llpathfindingcharacter.cpp new file mode 100644 index 000000000..00f2ebc4b --- /dev/null +++ b/indra/newview/llpathfindingcharacter.cpp @@ -0,0 +1,99 @@ +/** +* @file llpathfindingcharacter.cpp +* @brief Definition of a pathfinding character that contains various properties required for havok pathfinding. +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingcharacter.h" + +#include + +#include "llpathfindingobject.h" +#include "llsd.h" + +#define CHARACTER_CPU_TIME_FIELD "cpu_time" +#define CHARACTER_HORIZONTAL_FIELD "horizontal" +#define CHARACTER_LENGTH_FIELD "length" +#define CHARACTER_RADIUS_FIELD "radius" + +//--------------------------------------------------------------------------- +// LLPathfindingCharacter +//--------------------------------------------------------------------------- + +LLPathfindingCharacter::LLPathfindingCharacter(const std::string &pUUID, const LLSD& pCharacterData) + : LLPathfindingObject(pUUID, pCharacterData), + mCPUTime(0U), + mIsHorizontal(FALSE), + mLength(0.0f), + mRadius(0.0f) +{ + parseCharacterData(pCharacterData); +} + +LLPathfindingCharacter::LLPathfindingCharacter(const LLPathfindingCharacter& pOther) + : LLPathfindingObject(pOther), + mCPUTime(pOther.mCPUTime), + mIsHorizontal(pOther.mIsHorizontal), + mLength(pOther.mLength), + mRadius(pOther.mRadius) +{ +} + +LLPathfindingCharacter::~LLPathfindingCharacter() +{ +} + +LLPathfindingCharacter& LLPathfindingCharacter::operator =(const LLPathfindingCharacter& pOther) +{ + dynamic_cast(*this) = pOther; + + mCPUTime = pOther.mCPUTime; + mIsHorizontal = pOther.mIsHorizontal; + mLength = pOther.mLength; + mRadius = pOther.mRadius; + + return *this; +} + +void LLPathfindingCharacter::parseCharacterData(const LLSD &pCharacterData) +{ + llassert(pCharacterData.has(CHARACTER_CPU_TIME_FIELD)); + llassert(pCharacterData.get(CHARACTER_CPU_TIME_FIELD).isReal()); + mCPUTime = pCharacterData.get(CHARACTER_CPU_TIME_FIELD).asReal(); + + llassert(pCharacterData.has(CHARACTER_HORIZONTAL_FIELD)); + llassert(pCharacterData.get(CHARACTER_HORIZONTAL_FIELD).isBoolean()); + mIsHorizontal = pCharacterData.get(CHARACTER_HORIZONTAL_FIELD).asBoolean(); + + llassert(pCharacterData.has(CHARACTER_LENGTH_FIELD)); + llassert(pCharacterData.get(CHARACTER_LENGTH_FIELD).isReal()); + mLength = pCharacterData.get(CHARACTER_LENGTH_FIELD).asReal(); + + llassert(pCharacterData.has(CHARACTER_RADIUS_FIELD)); + llassert(pCharacterData.get(CHARACTER_RADIUS_FIELD).isReal()); + mRadius = pCharacterData.get(CHARACTER_RADIUS_FIELD).asReal(); +} diff --git a/indra/newview/llpathfindingcharacter.h b/indra/newview/llpathfindingcharacter.h new file mode 100644 index 000000000..7cf9f401b --- /dev/null +++ b/indra/newview/llpathfindingcharacter.h @@ -0,0 +1,63 @@ +/** +* @file llpathfindingcharacter.h +* @brief Definition of a pathfinding character that contains various properties required for havok pathfinding. +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGCHARACTER_H +#define LL_LLPATHFINDINGCHARACTER_H + +#include + +#include "llpathfindingobject.h" + +class LLSD; + +class LLPathfindingCharacter : public LLPathfindingObject +{ +public: + LLPathfindingCharacter(const std::string &pUUID, const LLSD &pCharacterData); + LLPathfindingCharacter(const LLPathfindingCharacter& pOther); + virtual ~LLPathfindingCharacter(); + + LLPathfindingCharacter& operator =(const LLPathfindingCharacter& pOther); + + inline F32 getCPUTime() const {return mCPUTime;}; + + inline BOOL isHorizontal() const {return mIsHorizontal;}; + inline F32 getLength() const {return mLength;}; + inline F32 getRadius() const {return mRadius;}; + +protected: + +private: + void parseCharacterData(const LLSD &pCharacterData); + + F32 mCPUTime; + + BOOL mIsHorizontal; + F32 mLength; + F32 mRadius; +}; + +#endif // LL_LLPATHFINDINGCHARACTER_H diff --git a/indra/newview/llpathfindingcharacterlist.cpp b/indra/newview/llpathfindingcharacterlist.cpp new file mode 100644 index 000000000..12340cebf --- /dev/null +++ b/indra/newview/llpathfindingcharacterlist.cpp @@ -0,0 +1,69 @@ +/** +* @file llpathfindingcharacterlist.cpp +* @brief Implementation of llpathfindingcharacterlist +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingcharacterlist.h" + +#include "llpathfindingcharacter.h" +#include "llpathfindingobject.h" +#include "llpathfindingobjectlist.h" +#include "llsd.h" + +//--------------------------------------------------------------------------- +// LLPathfindingCharacterList +//--------------------------------------------------------------------------- + +LLPathfindingCharacterList::LLPathfindingCharacterList() + : LLPathfindingObjectList() +{ +} + +LLPathfindingCharacterList::LLPathfindingCharacterList(const LLSD& pCharacterListData) + : LLPathfindingObjectList() +{ + parseCharacterListData(pCharacterListData); +} + +LLPathfindingCharacterList::~LLPathfindingCharacterList() +{ +} + +void LLPathfindingCharacterList::parseCharacterListData(const LLSD& pCharacterListData) +{ + LLPathfindingObjectMap &objectMap = getObjectMap(); + + for (LLSD::map_const_iterator characterDataIter = pCharacterListData.beginMap(); + characterDataIter != pCharacterListData.endMap(); ++characterDataIter) + { + const std::string& uuid(characterDataIter->first); + const LLSD& characterData = characterDataIter->second; + LLPathfindingObjectPtr character(new LLPathfindingCharacter(uuid, characterData)); + objectMap.insert(std::pair(uuid, character)); + } +} diff --git a/indra/newview/llpathfindingcharacterlist.h b/indra/newview/llpathfindingcharacterlist.h new file mode 100644 index 000000000..4ecf70001 --- /dev/null +++ b/indra/newview/llpathfindingcharacterlist.h @@ -0,0 +1,47 @@ +/** +* @file llpathfindingcharacterlist.h +* @brief Header file for llpathfindingcharacterlist +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGCHARACTERLIST_H +#define LL_LLPATHFINDINGCHARACTERLIST_H + +#include "llpathfindingobjectlist.h" + +class LLSD; + +class LLPathfindingCharacterList : public LLPathfindingObjectList +{ +public: + LLPathfindingCharacterList(); + LLPathfindingCharacterList(const LLSD& pCharacterListData); + virtual ~LLPathfindingCharacterList(); + +protected: + +private: + void parseCharacterListData(const LLSD& pCharacterListData); +}; + +#endif // LL_LLPATHFINDINGCHARACTERLIST_H diff --git a/indra/newview/llpathfindinglinkset.cpp b/indra/newview/llpathfindinglinkset.cpp new file mode 100644 index 000000000..fe4daabd8 --- /dev/null +++ b/indra/newview/llpathfindinglinkset.cpp @@ -0,0 +1,387 @@ +/** +* @file llpathfindinglinkset.cpp +* @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding. +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindinglinkset.h" + +#include + +#include "llpathfindingobject.h" +#include "llsd.h" + +#define LINKSET_LAND_IMPACT_FIELD "landimpact" +#define LINKSET_MODIFIABLE_FIELD "modifiable" +#define LINKSET_CATEGORY_FIELD "navmesh_category" +#define LINKSET_CAN_BE_VOLUME "can_be_volume" +#define LINKSET_PHANTOM_FIELD "phantom" +#define LINKSET_WALKABILITY_A_FIELD "A" +#define LINKSET_WALKABILITY_B_FIELD "B" +#define LINKSET_WALKABILITY_C_FIELD "C" +#define LINKSET_WALKABILITY_D_FIELD "D" + +#define LINKSET_CATEGORY_VALUE_INCLUDE 0 +#define LINKSET_CATEGORY_VALUE_EXCLUDE 1 +#define LINKSET_CATEGORY_VALUE_IGNORE 2 + +//--------------------------------------------------------------------------- +// LLPathfindingLinkset +//--------------------------------------------------------------------------- + +const S32 LLPathfindingLinkset::MIN_WALKABILITY_VALUE(0); +const S32 LLPathfindingLinkset::MAX_WALKABILITY_VALUE(100); + +LLPathfindingLinkset::LLPathfindingLinkset(const LLSD& pTerrainData) + : LLPathfindingObject(), + mIsTerrain(true), + mLandImpact(0U), + mIsModifiable(FALSE), + mCanBeVolume(FALSE), + mLinksetUse(kUnknown), + mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE) +{ + parsePathfindingData(pTerrainData); +} + +LLPathfindingLinkset::LLPathfindingLinkset(const std::string &pUUID, const LLSD& pLinksetData) + : LLPathfindingObject(pUUID, pLinksetData), + mIsTerrain(false), + mLandImpact(0U), + mIsModifiable(TRUE), + mCanBeVolume(TRUE), + mLinksetUse(kUnknown), + mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE), + mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE) +{ + parseLinksetData(pLinksetData); + parsePathfindingData(pLinksetData); +} + +LLPathfindingLinkset::LLPathfindingLinkset(const LLPathfindingLinkset& pOther) + : LLPathfindingObject(pOther), + mIsTerrain(pOther.mIsTerrain), + mLandImpact(pOther.mLandImpact), + mIsModifiable(pOther.mIsModifiable), + mCanBeVolume(pOther.mCanBeVolume), + mLinksetUse(pOther.mLinksetUse), + mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA), + mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB), + mWalkabilityCoefficientC(pOther.mWalkabilityCoefficientC), + mWalkabilityCoefficientD(pOther.mWalkabilityCoefficientD) +{ +} + +LLPathfindingLinkset::~LLPathfindingLinkset() +{ +} + +LLPathfindingLinkset& LLPathfindingLinkset::operator =(const LLPathfindingLinkset& pOther) +{ + dynamic_cast(*this) = pOther; + + mIsTerrain = pOther.mIsTerrain; + mLandImpact = pOther.mLandImpact; + mIsModifiable = pOther.mIsModifiable; + mCanBeVolume = pOther.mCanBeVolume; + mLinksetUse = pOther.mLinksetUse; + mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA; + mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB; + mWalkabilityCoefficientC = pOther.mWalkabilityCoefficientC; + mWalkabilityCoefficientD = pOther.mWalkabilityCoefficientD; + + return *this; +} + +BOOL LLPathfindingLinkset::isPhantom() const +{ + return isPhantom(getLinksetUse()); +} + +LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUseWithToggledPhantom(ELinksetUse pLinksetUse) +{ + BOOL isPhantom = LLPathfindingLinkset::isPhantom(pLinksetUse); + ENavMeshGenerationCategory navMeshGenerationCategory = getNavMeshGenerationCategory(pLinksetUse); + + return getLinksetUse(!isPhantom, navMeshGenerationCategory); +} + +bool LLPathfindingLinkset::isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const +{ + return (!isModifiable() && (isPhantom() != isPhantom(pLinksetUse))); +} + +bool LLPathfindingLinkset::isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const +{ + return (!canBeVolume() && ((pLinksetUse == kMaterialVolume) || (pLinksetUse == kExclusionVolume))); +} + +LLSD LLPathfindingLinkset::encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const +{ + LLSD itemData; + + if (!isTerrain() && (pLinksetUse != kUnknown) && (getLinksetUse() != pLinksetUse) && + (canBeVolume() || ((pLinksetUse != kMaterialVolume) && (pLinksetUse != kExclusionVolume)))) + { + if (isModifiable()) + { + itemData[LINKSET_PHANTOM_FIELD] = static_cast(isPhantom(pLinksetUse)); + } + + itemData[LINKSET_CATEGORY_FIELD] = convertCategoryToLLSD(getNavMeshGenerationCategory(pLinksetUse)); + } + + if (mWalkabilityCoefficientA != pA) + { + itemData[LINKSET_WALKABILITY_A_FIELD] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + if (mWalkabilityCoefficientB != pB) + { + itemData[LINKSET_WALKABILITY_B_FIELD] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + if (mWalkabilityCoefficientC != pC) + { + itemData[LINKSET_WALKABILITY_C_FIELD] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + if (mWalkabilityCoefficientD != pD) + { + itemData[LINKSET_WALKABILITY_D_FIELD] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE); + } + + return itemData; +} + +void LLPathfindingLinkset::parseLinksetData(const LLSD &pLinksetData) +{ + llassert(pLinksetData.has(LINKSET_LAND_IMPACT_FIELD)); + llassert(pLinksetData.get(LINKSET_LAND_IMPACT_FIELD).isInteger()); + llassert(pLinksetData.get(LINKSET_LAND_IMPACT_FIELD).asInteger() >= 0); + mLandImpact = pLinksetData.get(LINKSET_LAND_IMPACT_FIELD).asInteger(); + + llassert(pLinksetData.has(LINKSET_MODIFIABLE_FIELD)); + llassert(pLinksetData.get(LINKSET_MODIFIABLE_FIELD).isBoolean()); + mIsModifiable = pLinksetData.get(LINKSET_MODIFIABLE_FIELD).asBoolean(); +} + +void LLPathfindingLinkset::parsePathfindingData(const LLSD &pLinksetData) +{ + bool isPhantom = false; + if (pLinksetData.has(LINKSET_PHANTOM_FIELD)) + { + llassert(pLinksetData.get(LINKSET_PHANTOM_FIELD).isBoolean()); + isPhantom = pLinksetData.get(LINKSET_PHANTOM_FIELD).asBoolean(); + } + + llassert(pLinksetData.has(LINKSET_CATEGORY_FIELD)); + mLinksetUse = getLinksetUse(isPhantom, convertCategoryFromLLSD(pLinksetData.get(LINKSET_CATEGORY_FIELD))); + + if (pLinksetData.has(LINKSET_CAN_BE_VOLUME)) + { + llassert(pLinksetData.get(LINKSET_CAN_BE_VOLUME).isBoolean()); + mCanBeVolume = pLinksetData.get(LINKSET_CAN_BE_VOLUME).asBoolean(); + } + + llassert(pLinksetData.has(LINKSET_WALKABILITY_A_FIELD)); + llassert(pLinksetData.get(LINKSET_WALKABILITY_A_FIELD).isInteger()); + mWalkabilityCoefficientA = pLinksetData.get(LINKSET_WALKABILITY_A_FIELD).asInteger(); + llassert(mWalkabilityCoefficientA >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientA <= MAX_WALKABILITY_VALUE); + + llassert(pLinksetData.has(LINKSET_WALKABILITY_B_FIELD)); + llassert(pLinksetData.get(LINKSET_WALKABILITY_B_FIELD).isInteger()); + mWalkabilityCoefficientB = pLinksetData.get(LINKSET_WALKABILITY_B_FIELD).asInteger(); + llassert(mWalkabilityCoefficientB >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientB <= MAX_WALKABILITY_VALUE); + + llassert(pLinksetData.has(LINKSET_WALKABILITY_C_FIELD)); + llassert(pLinksetData.get(LINKSET_WALKABILITY_C_FIELD).isInteger()); + mWalkabilityCoefficientC = pLinksetData.get(LINKSET_WALKABILITY_C_FIELD).asInteger(); + llassert(mWalkabilityCoefficientC >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientC <= MAX_WALKABILITY_VALUE); + + llassert(pLinksetData.has(LINKSET_WALKABILITY_D_FIELD)); + llassert(pLinksetData.get(LINKSET_WALKABILITY_D_FIELD).isInteger()); + mWalkabilityCoefficientD = pLinksetData.get(LINKSET_WALKABILITY_D_FIELD).asInteger(); + llassert(mWalkabilityCoefficientD >= MIN_WALKABILITY_VALUE); + llassert(mWalkabilityCoefficientD <= MAX_WALKABILITY_VALUE); +} + +BOOL LLPathfindingLinkset::isPhantom(ELinksetUse pLinksetUse) +{ + BOOL retVal; + + switch (pLinksetUse) + { + case kWalkable : + case kStaticObstacle : + case kDynamicObstacle : + retVal = false; + break; + case kMaterialVolume : + case kExclusionVolume : + case kDynamicPhantom : + retVal = true; + break; + case kUnknown : + default : + retVal = false; + llassert(0); + break; + } + + return retVal; +} + +LLPathfindingLinkset::ELinksetUse LLPathfindingLinkset::getLinksetUse(bool pIsPhantom, ENavMeshGenerationCategory pNavMeshGenerationCategory) +{ + ELinksetUse linksetUse = kUnknown; + + if (pIsPhantom) + { + switch (pNavMeshGenerationCategory) + { + case kNavMeshGenerationIgnore : + linksetUse = kDynamicPhantom; + break; + case kNavMeshGenerationInclude : + linksetUse = kMaterialVolume; + break; + case kNavMeshGenerationExclude : + linksetUse = kExclusionVolume; + break; + default : + linksetUse = kUnknown; + llassert(0); + break; + } + } + else + { + switch (pNavMeshGenerationCategory) + { + case kNavMeshGenerationIgnore : + linksetUse = kDynamicObstacle; + break; + case kNavMeshGenerationInclude : + linksetUse = kWalkable; + break; + case kNavMeshGenerationExclude : + linksetUse = kStaticObstacle; + break; + default : + linksetUse = kUnknown; + llassert(0); + break; + } + } + + return linksetUse; +} + +LLPathfindingLinkset::ENavMeshGenerationCategory LLPathfindingLinkset::getNavMeshGenerationCategory(ELinksetUse pLinksetUse) +{ + ENavMeshGenerationCategory navMeshGenerationCategory; + switch (pLinksetUse) + { + case kWalkable : + case kMaterialVolume : + navMeshGenerationCategory = kNavMeshGenerationInclude; + break; + case kStaticObstacle : + case kExclusionVolume : + navMeshGenerationCategory = kNavMeshGenerationExclude; + break; + case kDynamicObstacle : + case kDynamicPhantom : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + break; + case kUnknown : + default : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + llassert(0); + break; + } + + return navMeshGenerationCategory; +} + +LLSD LLPathfindingLinkset::convertCategoryToLLSD(ENavMeshGenerationCategory pNavMeshGenerationCategory) +{ + LLSD llsd; + + switch (pNavMeshGenerationCategory) + { + case kNavMeshGenerationIgnore : + llsd = static_cast(LINKSET_CATEGORY_VALUE_IGNORE); + break; + case kNavMeshGenerationInclude : + llsd = static_cast(LINKSET_CATEGORY_VALUE_INCLUDE); + break; + case kNavMeshGenerationExclude : + llsd = static_cast(LINKSET_CATEGORY_VALUE_EXCLUDE); + break; + default : + llsd = static_cast(LINKSET_CATEGORY_VALUE_IGNORE); + llassert(0); + break; + } + + return llsd; +} + +LLPathfindingLinkset::ENavMeshGenerationCategory LLPathfindingLinkset::convertCategoryFromLLSD(const LLSD &llsd) +{ + ENavMeshGenerationCategory navMeshGenerationCategory; + + llassert(llsd.isInteger()); + switch (llsd.asInteger()) + { + case LINKSET_CATEGORY_VALUE_IGNORE : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + break; + case LINKSET_CATEGORY_VALUE_INCLUDE : + navMeshGenerationCategory = kNavMeshGenerationInclude; + break; + case LINKSET_CATEGORY_VALUE_EXCLUDE : + navMeshGenerationCategory = kNavMeshGenerationExclude; + break; + default : + navMeshGenerationCategory = kNavMeshGenerationIgnore; + llassert(0); + break; + } + + return navMeshGenerationCategory; +} diff --git a/indra/newview/llpathfindinglinkset.h b/indra/newview/llpathfindinglinkset.h new file mode 100644 index 000000000..73b4d6bad --- /dev/null +++ b/indra/newview/llpathfindinglinkset.h @@ -0,0 +1,108 @@ +/** +* @file llpathfindinglinkset.h +* @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding. +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGLINKSET_H +#define LL_LLPATHFINDINGLINKSET_H + +#include + +#include "llpathfindingobject.h" + +class LLSD; + +class LLPathfindingLinkset : public LLPathfindingObject +{ +public: + typedef enum + { + kUnknown, + kWalkable, + kStaticObstacle, + kDynamicObstacle, + kMaterialVolume, + kExclusionVolume, + kDynamicPhantom + } ELinksetUse; + + LLPathfindingLinkset(const LLSD &pTerrainData); + LLPathfindingLinkset(const std::string &pUUID, const LLSD &pLinksetData); + LLPathfindingLinkset(const LLPathfindingLinkset& pOther); + virtual ~LLPathfindingLinkset(); + + LLPathfindingLinkset& operator = (const LLPathfindingLinkset& pOther); + + inline bool isTerrain() const {return mIsTerrain;}; + inline U32 getLandImpact() const {return mLandImpact;}; + BOOL isModifiable() const {return mIsModifiable;}; + BOOL isPhantom() const; + BOOL canBeVolume() const {return mCanBeVolume;}; + static ELinksetUse getLinksetUseWithToggledPhantom(ELinksetUse pLinksetUse); + + inline ELinksetUse getLinksetUse() const {return mLinksetUse;}; + + inline S32 getWalkabilityCoefficientA() const {return mWalkabilityCoefficientA;}; + inline S32 getWalkabilityCoefficientB() const {return mWalkabilityCoefficientB;}; + inline S32 getWalkabilityCoefficientC() const {return mWalkabilityCoefficientC;}; + inline S32 getWalkabilityCoefficientD() const {return mWalkabilityCoefficientD;}; + + bool isShowUnmodifiablePhantomWarning(ELinksetUse pLinksetUse) const; + bool isShowCannotBeVolumeWarning(ELinksetUse pLinksetUse) const; + LLSD encodeAlteredFields(ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; + + static const S32 MIN_WALKABILITY_VALUE; + static const S32 MAX_WALKABILITY_VALUE; + +protected: + +private: + typedef enum + { + kNavMeshGenerationIgnore, + kNavMeshGenerationInclude, + kNavMeshGenerationExclude + } ENavMeshGenerationCategory; + + void parseLinksetData(const LLSD &pLinksetData); + void parsePathfindingData(const LLSD &pLinksetData); + + static BOOL isPhantom(ELinksetUse pLinksetUse); + static ELinksetUse getLinksetUse(bool pIsPhantom, ENavMeshGenerationCategory pNavMeshGenerationCategory); + static ENavMeshGenerationCategory getNavMeshGenerationCategory(ELinksetUse pLinksetUse); + static LLSD convertCategoryToLLSD(ENavMeshGenerationCategory pNavMeshGenerationCategory); + static ENavMeshGenerationCategory convertCategoryFromLLSD(const LLSD &llsd); + + bool mIsTerrain; + U32 mLandImpact; + BOOL mIsModifiable; + BOOL mCanBeVolume; + ELinksetUse mLinksetUse; + S32 mWalkabilityCoefficientA; + S32 mWalkabilityCoefficientB; + S32 mWalkabilityCoefficientC; + S32 mWalkabilityCoefficientD; +}; + +#endif // LL_LLPATHFINDINGLINKSET_H diff --git a/indra/newview/llpathfindinglinksetlist.cpp b/indra/newview/llpathfindinglinksetlist.cpp new file mode 100644 index 000000000..746fa342a --- /dev/null +++ b/indra/newview/llpathfindinglinksetlist.cpp @@ -0,0 +1,196 @@ +/** +* @file llpathfindinglinksetlist.cpp +* @brief Implementation of llpathfindinglinksetlist +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindinglinksetlist.h" + +#include +#include + +#include "llpathfindinglinkset.h" +#include "llpathfindingobject.h" +#include "llpathfindingobjectlist.h" +#include "llsd.h" + +//--------------------------------------------------------------------------- +// LLPathfindingLinksetList +//--------------------------------------------------------------------------- + +LLPathfindingLinksetList::LLPathfindingLinksetList() + : LLPathfindingObjectList() +{ +} + +LLPathfindingLinksetList::LLPathfindingLinksetList(const LLSD& pLinksetListData) + : LLPathfindingObjectList() +{ + parseLinksetListData(pLinksetListData); +} + +LLPathfindingLinksetList::~LLPathfindingLinksetList() +{ +} + +LLSD LLPathfindingLinksetList::encodeObjectFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const +{ + LLSD listData; + + for (const_iterator linksetIter = begin(); linksetIter != end(); ++linksetIter) + { + const LLPathfindingObjectPtr objectPtr = linksetIter->second; + const LLPathfindingLinkset *linkset = dynamic_cast(objectPtr.get()); + + if (!linkset->isTerrain()) + { + LLSD linksetData = linkset->encodeAlteredFields(pLinksetUse, pA, pB, pC, pD); + if (!linksetData.isUndefined()) + { + const std::string& uuid(linksetIter->first); + listData[uuid] = linksetData; + } + } + } + + return listData; +} + +LLSD LLPathfindingLinksetList::encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const +{ + LLSD terrainData; + + for (const_iterator linksetIter = begin(); linksetIter != end(); ++linksetIter) + { + const LLPathfindingObjectPtr objectPtr = linksetIter->second; + const LLPathfindingLinkset *linkset = dynamic_cast(objectPtr.get()); + + if (linkset->isTerrain()) + { + terrainData = linkset->encodeAlteredFields(pLinksetUse, pA, pB, pC, pD); + break; + } + } + + return terrainData; +} + +bool LLPathfindingLinksetList::isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const +{ + bool isShowWarning = false; + + for (const_iterator objectIter = begin(); !isShowWarning && (objectIter != end()); ++objectIter) + { + const LLPathfindingObjectPtr objectPtr = objectIter->second; + const LLPathfindingLinkset *linkset = dynamic_cast(objectPtr.get()); + isShowWarning = linkset->isShowUnmodifiablePhantomWarning(pLinksetUse); + } + + return isShowWarning; +} + +bool LLPathfindingLinksetList::isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const +{ + bool isShowWarning = false; + + for (const_iterator objectIter = begin(); !isShowWarning && (objectIter != end()); ++objectIter) + { + const LLPathfindingObjectPtr objectPtr = objectIter->second; + const LLPathfindingLinkset *linkset = dynamic_cast(objectPtr.get()); + isShowWarning = linkset->isShowCannotBeVolumeWarning(pLinksetUse); + } + + return isShowWarning; +} + +void LLPathfindingLinksetList::determinePossibleStates(BOOL &pCanBeWalkable, BOOL &pCanBeStaticObstacle, BOOL &pCanBeDynamicObstacle, + BOOL &pCanBeMaterialVolume, BOOL &pCanBeExclusionVolume, BOOL &pCanBeDynamicPhantom) const +{ + pCanBeWalkable = FALSE; + pCanBeStaticObstacle = FALSE; + pCanBeDynamicObstacle = FALSE; + pCanBeMaterialVolume = FALSE; + pCanBeExclusionVolume = FALSE; + pCanBeDynamicPhantom = FALSE; + + for (const_iterator objectIter = begin(); + !(pCanBeWalkable && pCanBeStaticObstacle && pCanBeDynamicObstacle && pCanBeMaterialVolume && pCanBeExclusionVolume && pCanBeDynamicPhantom) && (objectIter != end()); + ++objectIter) + { + const LLPathfindingObjectPtr objectPtr = objectIter->second; + const LLPathfindingLinkset *linkset = dynamic_cast(objectPtr.get()); + + if (linkset->isTerrain()) + { + pCanBeWalkable = TRUE; + } + else + { + if (linkset->isModifiable()) + { + pCanBeWalkable = TRUE; + pCanBeStaticObstacle = TRUE; + pCanBeDynamicObstacle = TRUE; + pCanBeDynamicPhantom = TRUE; + if (linkset->canBeVolume()) + { + pCanBeMaterialVolume = TRUE; + pCanBeExclusionVolume = TRUE; + } + } + else if (linkset->isPhantom()) + { + pCanBeDynamicPhantom = TRUE; + if (linkset->canBeVolume()) + { + pCanBeMaterialVolume = TRUE; + pCanBeExclusionVolume = TRUE; + } + } + else + { + pCanBeWalkable = TRUE; + pCanBeStaticObstacle = TRUE; + pCanBeDynamicObstacle = TRUE; + } + } + } +} + +void LLPathfindingLinksetList::parseLinksetListData(const LLSD& pLinksetListData) +{ + LLPathfindingObjectMap &objectMap = getObjectMap(); + + for (LLSD::map_const_iterator linksetDataIter = pLinksetListData.beginMap(); + linksetDataIter != pLinksetListData.endMap(); ++linksetDataIter) + { + const std::string& uuid(linksetDataIter->first); + const LLSD& linksetData = linksetDataIter->second; + LLPathfindingObjectPtr linksetPtr(new LLPathfindingLinkset(uuid, linksetData)); + objectMap.insert(std::pair(uuid, linksetPtr)); + } +} diff --git a/indra/newview/llpathfindinglinksetlist.h b/indra/newview/llpathfindinglinksetlist.h new file mode 100644 index 000000000..77c635864 --- /dev/null +++ b/indra/newview/llpathfindinglinksetlist.h @@ -0,0 +1,57 @@ +/** +* @file llpathfindinglinksetlist.h +* @brief Header file for llpathfindinglinksetlist +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGLINKSETLIST_H +#define LL_LLPATHFINDINGLINKSETLIST_H + +#include "llpathfindinglinkset.h" +#include "llpathfindingobjectlist.h" + +class LLSD; + +class LLPathfindingLinksetList : public LLPathfindingObjectList +{ +public: + LLPathfindingLinksetList(); + LLPathfindingLinksetList(const LLSD& pLinksetListData); + virtual ~LLPathfindingLinksetList(); + + LLSD encodeObjectFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; + LLSD encodeTerrainFields(LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD) const; + + bool isShowUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; + bool isShowCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; + + void determinePossibleStates(BOOL &pCanBeWalkable, BOOL &pCanBeStaticObstacle, BOOL &pCanBeDynamicObstacle, + BOOL &pCanBeMaterialVolume, BOOL &pCanBeExclusionVolume, BOOL &pCanBeDynamicPhantom) const; + +protected: + +private: + void parseLinksetListData(const LLSD& pLinksetListData); +}; + +#endif // LL_LLPATHFINDINGLINKSETLIST_H diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp new file mode 100644 index 000000000..48775693a --- /dev/null +++ b/indra/newview/llpathfindingmanager.cpp @@ -0,0 +1,1050 @@ +/** +* @file llpathfindingmanager.cpp +* @brief Implementation of llpathfindingmanager +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingmanager.h" + +#include +#include + +#include +#include +#include +#include + +#include "llagent.h" +#include "llhttpclient.h" +#include "llhttpnode.h" +#include "llnotificationsutil.h" +#include "llpathfindingcharacterlist.h" +#include "llpathfindinglinkset.h" +#include "llpathfindinglinksetlist.h" +#include "llpathfindingnavmesh.h" +#include "llpathfindingnavmeshstatus.h" +#include "llpathfindingobject.h" +//#include "llpathinglib.h" +#include "llsingleton.h" +#include "llsd.h" +#include "lltrans.h" +#include "lluuid.h" +#include "llviewerregion.h" +#include "llweb.h" + +#define CAP_SERVICE_RETRIEVE_NAVMESH "RetrieveNavMeshSrc" + +#define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus" + +#define CAP_SERVICE_OBJECT_LINKSETS "ObjectNavMeshProperties" +#define CAP_SERVICE_TERRAIN_LINKSETS "TerrainNavMeshProperties" + +#define CAP_SERVICE_CHARACTERS "CharacterProperties" + +#define SIM_MESSAGE_NAVMESH_STATUS_UPDATE "/message/NavMeshStatusUpdate" +#define SIM_MESSAGE_AGENT_STATE_UPDATE "/message/AgentStateUpdate" +#define SIM_MESSAGE_BODY_FIELD "body" + +#define CAP_SERVICE_AGENT_STATE "AgentState" + +#define AGENT_STATE_CAN_REBAKE_REGION_FIELD "can_modify_navmesh" + +//--------------------------------------------------------------------------- +// LLNavMeshSimStateChangeNode +//--------------------------------------------------------------------------- + +class LLNavMeshSimStateChangeNode : public LLHTTPNode +{ +public: + virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const; +}; + +LLHTTPRegistration gHTTPRegistrationNavMeshSimStateChangeNode(SIM_MESSAGE_NAVMESH_STATUS_UPDATE); + + +//--------------------------------------------------------------------------- +// LLAgentStateChangeNode +//--------------------------------------------------------------------------- +class LLAgentStateChangeNode : public LLHTTPNode +{ +public: + virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const; +}; + +LLHTTPRegistration gHTTPRegistrationAgentStateChangeNode(SIM_MESSAGE_AGENT_STATE_UPDATE); + +//--------------------------------------------------------------------------- +// NavMeshStatusResponder +//--------------------------------------------------------------------------- + +class NavMeshStatusResponder : public LLHTTPClient::Responder +{ +public: + NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly); + virtual ~NavMeshStatusResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + std::string mCapabilityURL; + LLViewerRegion *mRegion; + LLUUID mRegionUUID; + bool mIsGetStatusOnly; +}; + +//--------------------------------------------------------------------------- +// NavMeshResponder +//--------------------------------------------------------------------------- + +class NavMeshResponder : public LLHTTPClient::Responder +{ +public: + NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr); + virtual ~NavMeshResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + std::string mCapabilityURL; + U32 mNavMeshVersion; + LLPathfindingNavMeshPtr mNavMeshPtr; +}; + +//--------------------------------------------------------------------------- +// AgentStateResponder +//--------------------------------------------------------------------------- + +class AgentStateResponder : public LLHTTPClient::Responder +{ +public: + AgentStateResponder(const std::string &pCapabilityURL); + virtual ~AgentStateResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + std::string mCapabilityURL; +}; + + +//--------------------------------------------------------------------------- +// NavMeshRebakeResponder +//--------------------------------------------------------------------------- +class NavMeshRebakeResponder : public LLHTTPClient::Responder +{ +public: + NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback); + virtual ~NavMeshRebakeResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string& pReason); + +protected: + +private: + std::string mCapabilityURL; + LLPathfindingManager::rebake_navmesh_callback_t mRebakeNavMeshCallback; +}; + +//--------------------------------------------------------------------------- +// LinksetsResponder +//--------------------------------------------------------------------------- + +class LinksetsResponder +{ +public: + LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested); + virtual ~LinksetsResponder(); + + void handleObjectLinksetsResult(const LLSD &pContent); + void handleObjectLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL); + void handleTerrainLinksetsResult(const LLSD &pContent); + void handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL); + +protected: + +private: + void sendCallback(); + + typedef enum + { + kNotRequested, + kWaiting, + kReceivedGood, + kReceivedError + } EMessagingState; + + LLPathfindingManager::request_id_t mRequestId; + LLPathfindingManager::object_request_callback_t mLinksetsCallback; + + EMessagingState mObjectMessagingState; + EMessagingState mTerrainMessagingState; + + LLPathfindingObjectListPtr mObjectLinksetListPtr; + LLPathfindingObjectPtr mTerrainLinksetPtr; +}; + +typedef boost::shared_ptr LinksetsResponderPtr; + +//--------------------------------------------------------------------------- +// ObjectLinksetsResponder +//--------------------------------------------------------------------------- + +class ObjectLinksetsResponder : public LLHTTPClient::Responder +{ +public: + ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr); + virtual ~ObjectLinksetsResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string &pReason); + +protected: + +private: + std::string mCapabilityURL; + LinksetsResponderPtr mLinksetsResponsderPtr; +}; + +//--------------------------------------------------------------------------- +// TerrainLinksetsResponder +//--------------------------------------------------------------------------- + +class TerrainLinksetsResponder : public LLHTTPClient::Responder +{ +public: + TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr); + virtual ~TerrainLinksetsResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string &pReason); + +protected: + +private: + std::string mCapabilityURL; + LinksetsResponderPtr mLinksetsResponsderPtr; +}; + +//--------------------------------------------------------------------------- +// CharactersResponder +//--------------------------------------------------------------------------- + +class CharactersResponder : public LLHTTPClient::Responder +{ +public: + CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback); + virtual ~CharactersResponder(); + + virtual void result(const LLSD &pContent); + virtual void error(U32 pStatus, const std::string &pReason); + +protected: + +private: + std::string mCapabilityURL; + LLPathfindingManager::request_id_t mRequestId; + LLPathfindingManager::object_request_callback_t mCharactersCallback; +}; + +//--------------------------------------------------------------------------- +// LLPathfindingManager +//--------------------------------------------------------------------------- + +LLPathfindingManager::LLPathfindingManager() + : LLSingleton(), + mNavMeshMap(), + mAgentStateSignal() +{ +} + +LLPathfindingManager::~LLPathfindingManager() +{ + quitSystem(); +} + +void LLPathfindingManager::initSystem() +{ + /*if (LLPathingLib::getInstance() == NULL) + { + LLPathingLib::initSystem(); + }*/ +} + +void LLPathfindingManager::quitSystem() +{ + /*if (LLPathingLib::getInstance() != NULL) + { + LLPathingLib::quitSystem(); + }*/ +} + +bool LLPathfindingManager::isPathfindingViewEnabled() const +{ + return false; + //return (LLPathingLib::getInstance() != NULL); +} + +bool LLPathfindingManager::isPathfindingEnabledForCurrentRegion() const +{ + return isPathfindingEnabledForRegion(getCurrentRegion()); +} + +bool LLPathfindingManager::isPathfindingEnabledForRegion(LLViewerRegion *pRegion) const +{ + std::string retrieveNavMeshURL = getRetrieveNavMeshURLForRegion(pRegion); + return !retrieveNavMeshURL.empty(); +} + +bool LLPathfindingManager::isAllowViewTerrainProperties() const +{ + LLViewerRegion* region = getCurrentRegion(); + return (gAgent.isGodlike() || ((region != NULL) && region->canManageEstate())); +} + +LLPathfindingNavMesh::navmesh_slot_t LLPathfindingManager::registerNavMeshListenerForRegion(LLViewerRegion *pRegion, LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegion); + return navMeshPtr->registerNavMeshListener(pNavMeshCallback); +} + +void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion, bool pIsGetStatusOnly) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegion); + + if (pRegion == NULL) + { + navMeshPtr->handleNavMeshNotEnabled(); + } + else if (!pRegion->capabilitiesReceived()) + { + navMeshPtr->handleNavMeshWaitForRegionLoad(); + pRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetNavMeshForRegion, this, _1, pIsGetStatusOnly)); + } + else if (!isPathfindingEnabledForRegion(pRegion)) + { + navMeshPtr->handleNavMeshNotEnabled(); + } + else + { + std::string navMeshStatusURL = getNavMeshStatusURLForRegion(pRegion); + llassert(!navMeshStatusURL.empty()); + navMeshPtr->handleNavMeshCheckVersion(); + LLHTTPClient::ResponderPtr navMeshStatusResponder = new NavMeshStatusResponder(navMeshStatusURL, pRegion, pIsGetStatusOnly); + LLHTTPClient::get(navMeshStatusURL, navMeshStatusResponder); + } +} + +void LLPathfindingManager::requestGetLinksets(request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const +{ + LLPathfindingObjectListPtr emptyLinksetListPtr; + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr); + } + else if (!currentRegion->capabilitiesReceived()) + { + pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr); + currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetLinksetsForRegion, this, _1, pRequestId, pLinksetsCallback)); + } + else + { + std::string objectLinksetsURL = getObjectLinksetsURLForCurrentRegion(); + std::string terrainLinksetsURL = getTerrainLinksetsURLForCurrentRegion(); + if (objectLinksetsURL.empty() || terrainLinksetsURL.empty()) + { + pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr); + } + else + { + pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr); + + bool doRequestTerrain = isAllowViewTerrainProperties(); + LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, true, doRequestTerrain)); + + LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr); + LLHTTPClient::get(objectLinksetsURL, objectLinksetsResponder); + + if (doRequestTerrain) + { + LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr); + LLHTTPClient::get(terrainLinksetsURL, terrainLinksetsResponder); + } + } + } +} + +void LLPathfindingManager::requestSetLinksets(request_id_t pRequestId, const LLPathfindingObjectListPtr &pLinksetListPtr, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD, object_request_callback_t pLinksetsCallback) const +{ + LLPathfindingObjectListPtr emptyLinksetListPtr; + + std::string objectLinksetsURL = getObjectLinksetsURLForCurrentRegion(); + std::string terrainLinksetsURL = getTerrainLinksetsURLForCurrentRegion(); + if (objectLinksetsURL.empty() || terrainLinksetsURL.empty()) + { + pLinksetsCallback(pRequestId, kRequestNotEnabled, emptyLinksetListPtr); + } + else if ((pLinksetListPtr == NULL) || pLinksetListPtr->isEmpty()) + { + pLinksetsCallback(pRequestId, kRequestCompleted, emptyLinksetListPtr); + } + else + { + const LLPathfindingLinksetList *linksetList = dynamic_cast(pLinksetListPtr.get()); + + LLSD objectPostData = linksetList->encodeObjectFields(pLinksetUse, pA, pB, pC, pD); + LLSD terrainPostData; + if (isAllowViewTerrainProperties()) + { + terrainPostData = linksetList->encodeTerrainFields(pLinksetUse, pA, pB, pC, pD); + } + + if (objectPostData.isUndefined() && terrainPostData.isUndefined()) + { + pLinksetsCallback(pRequestId, kRequestCompleted, emptyLinksetListPtr); + } + else + { + pLinksetsCallback(pRequestId, kRequestStarted, emptyLinksetListPtr); + + LinksetsResponderPtr linksetsResponderPtr(new LinksetsResponder(pRequestId, pLinksetsCallback, !objectPostData.isUndefined(), !terrainPostData.isUndefined())); + + if (!objectPostData.isUndefined()) + { + LLHTTPClient::ResponderPtr objectLinksetsResponder = new ObjectLinksetsResponder(objectLinksetsURL, linksetsResponderPtr); + LLHTTPClient::put(objectLinksetsURL, objectPostData, objectLinksetsResponder); + } + + if (!terrainPostData.isUndefined()) + { + LLHTTPClient::ResponderPtr terrainLinksetsResponder = new TerrainLinksetsResponder(terrainLinksetsURL, linksetsResponderPtr); + LLHTTPClient::put(terrainLinksetsURL, terrainPostData, terrainLinksetsResponder); + } + } + } +} + +void LLPathfindingManager::requestGetCharacters(request_id_t pRequestId, object_request_callback_t pCharactersCallback) const +{ + LLPathfindingObjectListPtr emptyCharacterListPtr; + + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + pCharactersCallback(pRequestId, kRequestNotEnabled, emptyCharacterListPtr); + } + else if (!currentRegion->capabilitiesReceived()) + { + pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr); + currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetCharactersForRegion, this, _1, pRequestId, pCharactersCallback)); + } + else + { + std::string charactersURL = getCharactersURLForCurrentRegion(); + if (charactersURL.empty()) + { + pCharactersCallback(pRequestId, kRequestNotEnabled, emptyCharacterListPtr); + } + else + { + pCharactersCallback(pRequestId, kRequestStarted, emptyCharacterListPtr); + + LLHTTPClient::ResponderPtr charactersResponder = new CharactersResponder(charactersURL, pRequestId, pCharactersCallback); + LLHTTPClient::get(charactersURL, charactersResponder); + } + } +} + +LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateListener(agent_state_callback_t pAgentStateCallback) +{ + return mAgentStateSignal.connect(pAgentStateCallback); +} + +void LLPathfindingManager::requestGetAgentState() +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + mAgentStateSignal(FALSE); + } + else + { + if (!currentRegion->capabilitiesReceived()) + { + currentRegion->setCapabilitiesReceivedCallback(boost::bind(&LLPathfindingManager::handleDeferredGetAgentStateForRegion, this, _1)); + } + else if (!isPathfindingEnabledForRegion(currentRegion)) + { + mAgentStateSignal(FALSE); + } + else + { + std::string agentStateURL = getAgentStateURLForRegion(currentRegion); + llassert(!agentStateURL.empty()); + LLHTTPClient::ResponderPtr responder = new AgentStateResponder(agentStateURL); + LLHTTPClient::get(agentStateURL, responder); + } + } +} + +void LLPathfindingManager::requestRebakeNavMesh(rebake_navmesh_callback_t pRebakeNavMeshCallback) +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if (currentRegion == NULL) + { + pRebakeNavMeshCallback(false); + } + else if (!isPathfindingEnabledForRegion(currentRegion)) + { + pRebakeNavMeshCallback(false); + } + else + { + std::string navMeshStatusURL = getNavMeshStatusURLForCurrentRegion(); + llassert(!navMeshStatusURL.empty()); + LLSD postData; + postData["command"] = "rebuild"; + LLHTTPClient::ResponderPtr responder = new NavMeshRebakeResponder(navMeshStatusURL, pRebakeNavMeshCallback); + LLHTTPClient::post(navMeshStatusURL, postData, responder); + } +} + +void LLPathfindingManager::sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPtr navMeshPtr, LLViewerRegion *pRegion, const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + if ((pRegion == NULL) || !pRegion->isAlive()) + { + navMeshPtr->handleNavMeshNotEnabled(); + } + else + { + std::string navMeshURL = getRetrieveNavMeshURLForRegion(pRegion); + + if (navMeshURL.empty()) + { + navMeshPtr->handleNavMeshNotEnabled(); + } + else + { + navMeshPtr->handleNavMeshStart(pNavMeshStatus); + LLHTTPClient::ResponderPtr responder = new NavMeshResponder(navMeshURL, pNavMeshStatus.getVersion(), navMeshPtr); + + LLSD postData; + LLHTTPClient::post(navMeshURL, postData, responder); + } + } +} + +void LLPathfindingManager::handleDeferredGetAgentStateForRegion(const LLUUID &pRegionUUID) +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetAgentState(); + } +} + +void LLPathfindingManager::handleDeferredGetNavMeshForRegion(const LLUUID &pRegionUUID, bool pIsGetStatusOnly) +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetNavMeshForRegion(currentRegion, pIsGetStatusOnly); + } +} + +void LLPathfindingManager::handleDeferredGetLinksetsForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetLinksets(pRequestId, pLinksetsCallback); + } +} + +void LLPathfindingManager::handleDeferredGetCharactersForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pCharactersCallback) const +{ + LLViewerRegion *currentRegion = getCurrentRegion(); + + if ((currentRegion != NULL) && (currentRegion->getRegionID() == pRegionUUID)) + { + requestGetCharacters(pRequestId, pCharactersCallback); + } +} + +void LLPathfindingManager::handleNavMeshStatusRequest(const LLPathfindingNavMeshStatus &pNavMeshStatus, LLViewerRegion *pRegion, bool pIsGetStatusOnly) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pNavMeshStatus.getRegionUUID()); + + if (!pNavMeshStatus.isValid()) + { + navMeshPtr->handleNavMeshError(); + } + else + { + if (navMeshPtr->hasNavMeshVersion(pNavMeshStatus)) + { + navMeshPtr->handleRefresh(pNavMeshStatus); + } + else if (pIsGetStatusOnly) + { + navMeshPtr->handleNavMeshNewVersion(pNavMeshStatus); + } + else + { + sendRequestGetNavMeshForRegion(navMeshPtr, pRegion, pNavMeshStatus); + } + } +} + +void LLPathfindingManager::handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pNavMeshStatus.getRegionUUID()); + + if (!pNavMeshStatus.isValid()) + { + navMeshPtr->handleNavMeshError(); + } + else + { + navMeshPtr->handleNavMeshNewVersion(pNavMeshStatus); + } +} + +void LLPathfindingManager::handleAgentState(BOOL pCanRebakeRegion) +{ + mAgentStateSignal(pCanRebakeRegion); +} + +LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(const LLUUID &pRegionUUID) +{ + LLPathfindingNavMeshPtr navMeshPtr; + NavMeshMap::iterator navMeshIter = mNavMeshMap.find(pRegionUUID); + if (navMeshIter == mNavMeshMap.end()) + { + navMeshPtr = LLPathfindingNavMeshPtr(new LLPathfindingNavMesh(pRegionUUID)); + mNavMeshMap.insert(std::pair(pRegionUUID, navMeshPtr)); + } + else + { + navMeshPtr = navMeshIter->second; + } + + return navMeshPtr; +} + +LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(LLViewerRegion *pRegion) +{ + LLUUID regionUUID; + if (pRegion != NULL) + { + regionUUID = pRegion->getRegionID(); + } + + return getNavMeshForRegion(regionUUID); +} + +std::string LLPathfindingManager::getNavMeshStatusURLForCurrentRegion() const +{ + return getNavMeshStatusURLForRegion(getCurrentRegion()); +} + +std::string LLPathfindingManager::getNavMeshStatusURLForRegion(LLViewerRegion *pRegion) const +{ + return getCapabilityURLForRegion(pRegion, CAP_SERVICE_NAVMESH_STATUS); +} + +std::string LLPathfindingManager::getRetrieveNavMeshURLForRegion(LLViewerRegion *pRegion) const +{ + return getCapabilityURLForRegion(pRegion, CAP_SERVICE_RETRIEVE_NAVMESH); +} + +std::string LLPathfindingManager::getObjectLinksetsURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_OBJECT_LINKSETS); +} + +std::string LLPathfindingManager::getTerrainLinksetsURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_TERRAIN_LINKSETS); +} + +std::string LLPathfindingManager::getCharactersURLForCurrentRegion() const +{ + return getCapabilityURLForCurrentRegion(CAP_SERVICE_CHARACTERS); +} + +std::string LLPathfindingManager::getAgentStateURLForRegion(LLViewerRegion *pRegion) const +{ + return getCapabilityURLForRegion(pRegion, CAP_SERVICE_AGENT_STATE); +} + +std::string LLPathfindingManager::getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const +{ + return getCapabilityURLForRegion(getCurrentRegion(), pCapabilityName); +} + +std::string LLPathfindingManager::getCapabilityURLForRegion(LLViewerRegion *pRegion, const std::string &pCapabilityName) const +{ + std::string capabilityURL(""); + + if (pRegion != NULL) + { + capabilityURL = pRegion->getCapability(pCapabilityName); + } + + if (capabilityURL.empty()) + { + llwarns << "cannot find capability '" << pCapabilityName << "' for current region '" + << ((pRegion != NULL) ? pRegion->getName() : "") << "'" << llendl; + } + + return capabilityURL; +} + +LLViewerRegion *LLPathfindingManager::getCurrentRegion() const +{ + return gAgent.getRegion(); +} + +//--------------------------------------------------------------------------- +// LLNavMeshSimStateChangeNode +//--------------------------------------------------------------------------- + +void LLNavMeshSimStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const +{ + llassert(pInput.has(SIM_MESSAGE_BODY_FIELD)); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).isMap()); + LLPathfindingNavMeshStatus navMeshStatus(pInput.get(SIM_MESSAGE_BODY_FIELD)); + LLPathfindingManager::getInstance()->handleNavMeshStatusUpdate(navMeshStatus); +} + +//--------------------------------------------------------------------------- +// LLAgentStateChangeNode +//--------------------------------------------------------------------------- + +void LLAgentStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const +{ + llassert(pInput.has(SIM_MESSAGE_BODY_FIELD)); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).isMap()); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).has(AGENT_STATE_CAN_REBAKE_REGION_FIELD)); + llassert(pInput.get(SIM_MESSAGE_BODY_FIELD).get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean()); + BOOL canRebakeRegion = pInput.get(SIM_MESSAGE_BODY_FIELD).get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean(); + + LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion); +} + +//--------------------------------------------------------------------------- +// NavMeshStatusResponder +//--------------------------------------------------------------------------- + +NavMeshStatusResponder::NavMeshStatusResponder(const std::string &pCapabilityURL, LLViewerRegion *pRegion, bool pIsGetStatusOnly) + : LLHTTPClient::Responder(), + mCapabilityURL(pCapabilityURL), + mRegion(pRegion), + mRegionUUID(), + mIsGetStatusOnly(pIsGetStatusOnly) +{ + if (mRegion != NULL) + { + mRegionUUID = mRegion->getRegionID(); + } +} + +NavMeshStatusResponder::~NavMeshStatusResponder() +{ +} + +void NavMeshStatusResponder::result(const LLSD &pContent) +{ + LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID, pContent); + LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); +} + +void NavMeshStatusResponder::error(U32 pStatus, const std::string& pReason) +{ + llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + LLPathfindingNavMeshStatus navMeshStatus(mRegionUUID); + LLPathfindingManager::getInstance()->handleNavMeshStatusRequest(navMeshStatus, mRegion, mIsGetStatusOnly); +} + +//--------------------------------------------------------------------------- +// NavMeshResponder +//--------------------------------------------------------------------------- + +NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr) + : LLHTTPClient::Responder(), + mCapabilityURL(pCapabilityURL), + mNavMeshVersion(pNavMeshVersion), + mNavMeshPtr(pNavMeshPtr) +{ +} + +NavMeshResponder::~NavMeshResponder() +{ +} + +void NavMeshResponder::result(const LLSD &pContent) +{ + mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion); +} + +void NavMeshResponder::error(U32 pStatus, const std::string& pReason) +{ + mNavMeshPtr->handleNavMeshError(pStatus, pReason, mCapabilityURL, mNavMeshVersion); +} + +//--------------------------------------------------------------------------- +// AgentStateResponder +//--------------------------------------------------------------------------- + +AgentStateResponder::AgentStateResponder(const std::string &pCapabilityURL) +: LLHTTPClient::Responder() +, mCapabilityURL(pCapabilityURL) +{ +} + +AgentStateResponder::~AgentStateResponder() +{ +} + +void AgentStateResponder::result(const LLSD &pContent) +{ + llassert(pContent.has(AGENT_STATE_CAN_REBAKE_REGION_FIELD)); + llassert(pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).isBoolean()); + BOOL canRebakeRegion = pContent.get(AGENT_STATE_CAN_REBAKE_REGION_FIELD).asBoolean(); + LLPathfindingManager::getInstance()->handleAgentState(canRebakeRegion); +} + +void AgentStateResponder::error(U32 pStatus, const std::string &pReason) +{ + llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + LLPathfindingManager::getInstance()->handleAgentState(FALSE); +} + + +//--------------------------------------------------------------------------- +// navmesh rebake responder +//--------------------------------------------------------------------------- +NavMeshRebakeResponder::NavMeshRebakeResponder(const std::string &pCapabilityURL, LLPathfindingManager::rebake_navmesh_callback_t pRebakeNavMeshCallback) + : LLHTTPClient::Responder(), + mCapabilityURL(pCapabilityURL), + mRebakeNavMeshCallback(pRebakeNavMeshCallback) +{ +} + +NavMeshRebakeResponder::~NavMeshRebakeResponder() +{ +} + +void NavMeshRebakeResponder::result(const LLSD &pContent) +{ + mRebakeNavMeshCallback(true); +} + +void NavMeshRebakeResponder::error(U32 pStatus, const std::string &pReason) +{ + llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + mRebakeNavMeshCallback(false); +} + +//--------------------------------------------------------------------------- +// LinksetsResponder +//--------------------------------------------------------------------------- + +LinksetsResponder::LinksetsResponder(LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pLinksetsCallback, bool pIsObjectRequested, bool pIsTerrainRequested) + : mRequestId(pRequestId), + mLinksetsCallback(pLinksetsCallback), + mObjectMessagingState(pIsObjectRequested ? kWaiting : kNotRequested), + mTerrainMessagingState(pIsTerrainRequested ? kWaiting : kNotRequested), + mObjectLinksetListPtr(), + mTerrainLinksetPtr() +{ +} + +LinksetsResponder::~LinksetsResponder() +{ +} + +void LinksetsResponder::handleObjectLinksetsResult(const LLSD &pContent) +{ + mObjectLinksetListPtr = LLPathfindingObjectListPtr(new LLPathfindingLinksetList(pContent)); + + mObjectMessagingState = kReceivedGood; + if (mTerrainMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::handleObjectLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL) +{ + llwarns << "error with request to URL '" << pURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + mObjectMessagingState = kReceivedError; + if (mTerrainMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::handleTerrainLinksetsResult(const LLSD &pContent) +{ + mTerrainLinksetPtr = LLPathfindingObjectPtr(new LLPathfindingLinkset(pContent)); + + mTerrainMessagingState = kReceivedGood; + if (mObjectMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::handleTerrainLinksetsError(U32 pStatus, const std::string &pReason, const std::string &pURL) +{ + mTerrainMessagingState = kReceivedError; + if (mObjectMessagingState != kWaiting) + { + sendCallback(); + } +} + +void LinksetsResponder::sendCallback() +{ + llassert(mObjectMessagingState != kWaiting); + llassert(mTerrainMessagingState != kWaiting); + LLPathfindingManager::ERequestStatus requestStatus = + ((((mObjectMessagingState == kReceivedGood) || (mObjectMessagingState == kNotRequested)) && + ((mTerrainMessagingState == kReceivedGood) || (mTerrainMessagingState == kNotRequested))) ? + LLPathfindingManager::kRequestCompleted : LLPathfindingManager::kRequestError); + + if (mObjectMessagingState != kReceivedGood) + { + mObjectLinksetListPtr = LLPathfindingObjectListPtr(new LLPathfindingLinksetList()); + } + + if (mTerrainMessagingState == kReceivedGood) + { + mObjectLinksetListPtr->update(mTerrainLinksetPtr); + } + + mLinksetsCallback(mRequestId, requestStatus, mObjectLinksetListPtr); +} + +//--------------------------------------------------------------------------- +// ObjectLinksetsResponder +//--------------------------------------------------------------------------- + +ObjectLinksetsResponder::ObjectLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) + : LLHTTPClient::Responder(), + mCapabilityURL(pCapabilityURL), + mLinksetsResponsderPtr(pLinksetsResponsderPtr) +{ +} + +ObjectLinksetsResponder::~ObjectLinksetsResponder() +{ +} + +void ObjectLinksetsResponder::result(const LLSD &pContent) +{ + mLinksetsResponsderPtr->handleObjectLinksetsResult(pContent); +} + +void ObjectLinksetsResponder::error(U32 pStatus, const std::string &pReason) +{ + mLinksetsResponsderPtr->handleObjectLinksetsError(pStatus, pReason, mCapabilityURL); +} + +//--------------------------------------------------------------------------- +// TerrainLinksetsResponder +//--------------------------------------------------------------------------- + +TerrainLinksetsResponder::TerrainLinksetsResponder(const std::string &pCapabilityURL, LinksetsResponderPtr pLinksetsResponsderPtr) + : LLHTTPClient::Responder(), + mCapabilityURL(pCapabilityURL), + mLinksetsResponsderPtr(pLinksetsResponsderPtr) +{ +} + +TerrainLinksetsResponder::~TerrainLinksetsResponder() +{ +} + +void TerrainLinksetsResponder::result(const LLSD &pContent) +{ + mLinksetsResponsderPtr->handleTerrainLinksetsResult(pContent); +} + +void TerrainLinksetsResponder::error(U32 pStatus, const std::string &pReason) +{ + mLinksetsResponsderPtr->handleTerrainLinksetsError(pStatus, pReason, mCapabilityURL); +} + +//--------------------------------------------------------------------------- +// CharactersResponder +//--------------------------------------------------------------------------- + +CharactersResponder::CharactersResponder(const std::string &pCapabilityURL, LLPathfindingManager::request_id_t pRequestId, LLPathfindingManager::object_request_callback_t pCharactersCallback) + : LLHTTPClient::Responder(), + mCapabilityURL(pCapabilityURL), + mRequestId(pRequestId), + mCharactersCallback(pCharactersCallback) +{ +} + +CharactersResponder::~CharactersResponder() +{ +} + +void CharactersResponder::result(const LLSD &pContent) +{ + LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList(pContent)); + mCharactersCallback(mRequestId, LLPathfindingManager::kRequestCompleted, characterListPtr); +} + +void CharactersResponder::error(U32 pStatus, const std::string &pReason) +{ + llwarns << "error with request to URL '" << mCapabilityURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + + LLPathfindingObjectListPtr characterListPtr = LLPathfindingObjectListPtr(new LLPathfindingCharacterList()); + mCharactersCallback(mRequestId, LLPathfindingManager::kRequestError, characterListPtr); +} diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h new file mode 100644 index 000000000..c61ff244f --- /dev/null +++ b/indra/newview/llpathfindingmanager.h @@ -0,0 +1,127 @@ +/** +* @file llpathfindingmanager.h +* @brief Header file for llpathfindingmanager +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGMANAGER_H +#define LL_LLPATHFINDINGMANAGER_H + +#include +#include + +#include +#include + +#include "llpathfindinglinkset.h" +#include "llpathfindingobjectlist.h" +#include "llpathfindingnavmesh.h" +#include "llsingleton.h" + +class LLPathfindingNavMeshStatus; +class LLUUID; +class LLViewerRegion; + +class LLPathfindingManager : public LLSingleton +{ + friend class LLNavMeshSimStateChangeNode; + friend class NavMeshStatusResponder; + friend class LLAgentStateChangeNode; + friend class AgentStateResponder; +public: + typedef enum { + kRequestStarted, + kRequestCompleted, + kRequestNotEnabled, + kRequestError + } ERequestStatus; + + LLPathfindingManager(); + virtual ~LLPathfindingManager(); + + void initSystem(); + void quitSystem(); + + bool isPathfindingViewEnabled() const; + bool isPathfindingEnabledForCurrentRegion() const; + bool isPathfindingEnabledForRegion(LLViewerRegion *pRegion) const; + + bool isAllowViewTerrainProperties() const; + + LLPathfindingNavMesh::navmesh_slot_t registerNavMeshListenerForRegion(LLViewerRegion *pRegion, LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback); + void requestGetNavMeshForRegion(LLViewerRegion *pRegion, bool pIsGetStatusOnly); + + typedef U32 request_id_t; + typedef boost::function object_request_callback_t; + + void requestGetLinksets(request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const; + void requestSetLinksets(request_id_t pRequestId, const LLPathfindingObjectListPtr &pLinksetListPtr, LLPathfindingLinkset::ELinksetUse pLinksetUse, S32 pA, S32 pB, S32 pC, S32 pD, object_request_callback_t pLinksetsCallback) const; + + void requestGetCharacters(request_id_t pRequestId, object_request_callback_t pCharactersCallback) const; + + typedef boost::function agent_state_callback_t; + typedef boost::signals2::signal agent_state_signal_t; + typedef boost::signals2::connection agent_state_slot_t; + + agent_state_slot_t registerAgentStateListener(agent_state_callback_t pAgentStateCallback); + void requestGetAgentState(); + + typedef boost::function rebake_navmesh_callback_t; + void requestRebakeNavMesh(rebake_navmesh_callback_t pRebakeNavMeshCallback); + +protected: + +private: + typedef std::map NavMeshMap; + + void sendRequestGetNavMeshForRegion(LLPathfindingNavMeshPtr navMeshPtr, LLViewerRegion *pRegion, const LLPathfindingNavMeshStatus &pNavMeshStatus); + + void handleDeferredGetAgentStateForRegion(const LLUUID &pRegionUUID); + void handleDeferredGetNavMeshForRegion(const LLUUID &pRegionUUID, bool pIsGetStatusOnly); + void handleDeferredGetLinksetsForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pLinksetsCallback) const; + void handleDeferredGetCharactersForRegion(const LLUUID &pRegionUUID, request_id_t pRequestId, object_request_callback_t pCharactersCallback) const; + + void handleNavMeshStatusRequest(const LLPathfindingNavMeshStatus &pNavMeshStatus, LLViewerRegion *pRegion, bool pIsGetStatusOnly); + void handleNavMeshStatusUpdate(const LLPathfindingNavMeshStatus &pNavMeshStatus); + + void handleAgentState(BOOL pCanRebakeRegion); + + LLPathfindingNavMeshPtr getNavMeshForRegion(const LLUUID &pRegionUUID); + LLPathfindingNavMeshPtr getNavMeshForRegion(LLViewerRegion *pRegion); + + std::string getNavMeshStatusURLForCurrentRegion() const; + std::string getNavMeshStatusURLForRegion(LLViewerRegion *pRegion) const; + std::string getRetrieveNavMeshURLForRegion(LLViewerRegion *pRegion) const; + std::string getObjectLinksetsURLForCurrentRegion() const; + std::string getTerrainLinksetsURLForCurrentRegion() const; + std::string getCharactersURLForCurrentRegion() const; + std::string getAgentStateURLForRegion(LLViewerRegion *pRegion) const; + std::string getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const; + std::string getCapabilityURLForRegion(LLViewerRegion *pRegion, const std::string &pCapabilityName) const; + LLViewerRegion *getCurrentRegion() const; + + NavMeshMap mNavMeshMap; + agent_state_signal_t mAgentStateSignal; +}; + +#endif // LL_LLPATHFINDINGMANAGER_H diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp new file mode 100644 index 000000000..e01dd3a15 --- /dev/null +++ b/indra/newview/llpathfindingnavmesh.cpp @@ -0,0 +1,205 @@ +/** +* @file llpathfindingnavmesh.cpp +* @brief Implementation of llpathfindingnavmesh +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingnavmesh.h" + +#include + +#include "llpathfindingnavmeshstatus.h" +#include "llsd.h" +#include "llsdserialize.h" +#include "lluuid.h" + +#define NAVMESH_VERSION_FIELD "navmesh_version" +#define NAVMESH_DATA_FIELD "navmesh_data" + +//--------------------------------------------------------------------------- +// LLPathfindingNavMesh +//--------------------------------------------------------------------------- + +LLPathfindingNavMesh::LLPathfindingNavMesh(const LLUUID &pRegionUUID) + : mNavMeshStatus(pRegionUUID), + mNavMeshRequestStatus(kNavMeshRequestUnknown), + mNavMeshSignal(), + mNavMeshData() + +{ +} + +LLPathfindingNavMesh::~LLPathfindingNavMesh() +{ +} + +LLPathfindingNavMesh::navmesh_slot_t LLPathfindingNavMesh::registerNavMeshListener(navmesh_callback_t pNavMeshCallback) +{ + return mNavMeshSignal.connect(pNavMeshCallback); +} + +bool LLPathfindingNavMesh::hasNavMeshVersion(const LLPathfindingNavMeshStatus &pNavMeshStatus) const +{ + return ((mNavMeshStatus.getVersion() == pNavMeshStatus.getVersion()) && + ((mNavMeshRequestStatus == kNavMeshRequestStarted) || (mNavMeshRequestStatus == kNavMeshRequestCompleted) || + ((mNavMeshRequestStatus == kNavMeshRequestChecking) && !mNavMeshData.empty()))); +} + +void LLPathfindingNavMesh::handleNavMeshWaitForRegionLoad() +{ + setRequestStatus(kNavMeshRequestWaiting); +} + +void LLPathfindingNavMesh::handleNavMeshCheckVersion() +{ + setRequestStatus(kNavMeshRequestChecking); +} + +void LLPathfindingNavMesh::handleRefresh(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + llassert(mNavMeshStatus.getRegionUUID() == pNavMeshStatus.getRegionUUID()); + llassert(mNavMeshStatus.getVersion() == pNavMeshStatus.getVersion()); + mNavMeshStatus = pNavMeshStatus; + if (mNavMeshRequestStatus == kNavMeshRequestChecking) + { + llassert(!mNavMeshData.empty()); + setRequestStatus(kNavMeshRequestCompleted); + } + else + { + sendStatus(); + } +} + +void LLPathfindingNavMesh::handleNavMeshNewVersion(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + llassert(mNavMeshStatus.getRegionUUID() == pNavMeshStatus.getRegionUUID()); + if (mNavMeshStatus.getVersion() == pNavMeshStatus.getVersion()) + { + mNavMeshStatus = pNavMeshStatus; + sendStatus(); + } + else + { + mNavMeshData.clear(); + mNavMeshStatus = pNavMeshStatus; + setRequestStatus(kNavMeshRequestNeedsUpdate); + } +} + +void LLPathfindingNavMesh::handleNavMeshStart(const LLPathfindingNavMeshStatus &pNavMeshStatus) +{ + llassert(mNavMeshStatus.getRegionUUID() == pNavMeshStatus.getRegionUUID()); + mNavMeshStatus = pNavMeshStatus; + setRequestStatus(kNavMeshRequestStarted); +} + +void LLPathfindingNavMesh::handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion) +{ + llassert(pContent.has(NAVMESH_VERSION_FIELD)); + if (pContent.has(NAVMESH_VERSION_FIELD)) + { + llassert(pContent.get(NAVMESH_VERSION_FIELD).isInteger()); + llassert(pContent.get(NAVMESH_VERSION_FIELD).asInteger() >= 0); + U32 embeddedNavMeshVersion = static_cast(pContent.get(NAVMESH_VERSION_FIELD).asInteger()); + llassert(embeddedNavMeshVersion == pNavMeshVersion); // stinson 03/13/2012 : does this ever occur? + if (embeddedNavMeshVersion != pNavMeshVersion) + { + llwarns << "Mismatch between expected and embedded navmesh versions occurred" << llendl; + pNavMeshVersion = embeddedNavMeshVersion; + } + } + + if (mNavMeshStatus.getVersion() == pNavMeshVersion) + { + ENavMeshRequestStatus status; + if ( pContent.has(NAVMESH_DATA_FIELD) ) + { + const LLSD::Binary &value = pContent.get(NAVMESH_DATA_FIELD).asBinary(); + unsigned int binSize = value.size(); + std::string newStr(reinterpret_cast(&value[0]), binSize); + std::istringstream streamdecomp( newStr ); + unsigned int decompBinSize = 0; + bool valid = false; + U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ; + if ( !valid ) + { + llwarns << "Unable to decompress the navmesh llsd." << llendl; + status = kNavMeshRequestError; + } + else + { + llassert(pUncompressedNavMeshContainer); + mNavMeshData.resize( decompBinSize ); + memcpy( &mNavMeshData[0], &pUncompressedNavMeshContainer[0], decompBinSize ); + status = kNavMeshRequestCompleted; + } + if ( pUncompressedNavMeshContainer ) + { + free( pUncompressedNavMeshContainer ); + } + } + else + { + llwarns << "No mesh data received" << llendl; + status = kNavMeshRequestError; + } + setRequestStatus(status); + } +} + +void LLPathfindingNavMesh::handleNavMeshNotEnabled() +{ + mNavMeshData.clear(); + setRequestStatus(kNavMeshRequestNotEnabled); +} + +void LLPathfindingNavMesh::handleNavMeshError() +{ + mNavMeshData.clear(); + setRequestStatus(kNavMeshRequestError); +} + +void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const std::string &pURL, U32 pNavMeshVersion) +{ + llwarns << "error with request to URL '" << pURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl; + if (mNavMeshStatus.getVersion() == pNavMeshVersion) + { + handleNavMeshError(); + } +} + +void LLPathfindingNavMesh::setRequestStatus(ENavMeshRequestStatus pNavMeshRequestStatus) +{ + mNavMeshRequestStatus = pNavMeshRequestStatus; + sendStatus(); +} + +void LLPathfindingNavMesh::sendStatus() +{ + mNavMeshSignal(mNavMeshRequestStatus, mNavMeshStatus, mNavMeshData); +} diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h new file mode 100644 index 000000000..7a844f54c --- /dev/null +++ b/indra/newview/llpathfindingnavmesh.h @@ -0,0 +1,91 @@ +/** +* @file llpathfindingnavmesh.h +* @brief Header file for llpathfindingnavmesh +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGNAVMESH_H +#define LL_LLPATHFINDINGNAVMESH_H + +#include + +#include +#include +#include + +#include "llpathfindingnavmeshstatus.h" +#include "llsd.h" + +class LLPathfindingNavMesh; +class LLUUID; + +typedef boost::shared_ptr LLPathfindingNavMeshPtr; + +class LLPathfindingNavMesh +{ +public: + typedef enum { + kNavMeshRequestUnknown, + kNavMeshRequestWaiting, + kNavMeshRequestChecking, + kNavMeshRequestNeedsUpdate, + kNavMeshRequestStarted, + kNavMeshRequestCompleted, + kNavMeshRequestNotEnabled, + kNavMeshRequestError + } ENavMeshRequestStatus; + + typedef boost::function navmesh_callback_t; + typedef boost::signals2::signal navmesh_signal_t; + typedef boost::signals2::connection navmesh_slot_t; + + LLPathfindingNavMesh(const LLUUID &pRegionUUID); + virtual ~LLPathfindingNavMesh(); + + navmesh_slot_t registerNavMeshListener(navmesh_callback_t pNavMeshCallback); + + bool hasNavMeshVersion(const LLPathfindingNavMeshStatus &pNavMeshStatus) const; + + void handleNavMeshWaitForRegionLoad(); + void handleNavMeshCheckVersion(); + void handleRefresh(const LLPathfindingNavMeshStatus &pNavMeshStatus); + void handleNavMeshNewVersion(const LLPathfindingNavMeshStatus &pNavMeshStatus); + void handleNavMeshStart(const LLPathfindingNavMeshStatus &pNavMeshStatus); + void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion); + void handleNavMeshNotEnabled(); + void handleNavMeshError(); + void handleNavMeshError(U32 pStatus, const std::string &pReason, const std::string &pURL, U32 pNavMeshVersion); + +protected: + +private: + void setRequestStatus(ENavMeshRequestStatus pNavMeshRequestStatus); + void sendStatus(); + + LLPathfindingNavMeshStatus mNavMeshStatus; + ENavMeshRequestStatus mNavMeshRequestStatus; + navmesh_signal_t mNavMeshSignal; + LLSD::Binary mNavMeshData; +}; + +#endif // LL_LLPATHFINDINGNAVMESH_H diff --git a/indra/newview/llpathfindingnavmeshstatus.cpp b/indra/newview/llpathfindingnavmeshstatus.cpp new file mode 100644 index 000000000..2eaa6075c --- /dev/null +++ b/indra/newview/llpathfindingnavmeshstatus.cpp @@ -0,0 +1,145 @@ +/** +* @file llpathfindingnavmeshstatus.cpp +* @brief Implementation of llpathfindingnavmeshstatus +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingnavmeshstatus.h" + +#include + +#include "llsd.h" +#include "llstring.h" +#include "lluuid.h" + +#define REGION_FIELD "region_id" +#define STATUS_FIELD "status" +#define VERSION_FIELD "version" + +const std::string LLPathfindingNavMeshStatus::sStatusPending("pending"); +const std::string LLPathfindingNavMeshStatus::sStatusBuilding("building"); +const std::string LLPathfindingNavMeshStatus::sStatusComplete("complete"); +const std::string LLPathfindingNavMeshStatus::sStatusRepending("repending"); + + +//--------------------------------------------------------------------------- +// LLPathfindingNavMeshStatus +//--------------------------------------------------------------------------- + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus() + : mIsValid(false), + mRegionUUID(), + mVersion(0U), + mStatus(kComplete) +{ +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID) + : mIsValid(false), + mRegionUUID(pRegionUUID), + mVersion(0U), + mStatus(kComplete) +{ +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID, const LLSD &pContent) + : mIsValid(true), + mRegionUUID(pRegionUUID), + mVersion(0U), + mStatus(kComplete) +{ + parseStatus(pContent); +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLSD &pContent) + : mIsValid(true), + mRegionUUID(), + mVersion(0U), + mStatus(kComplete) +{ + llassert(pContent.has(REGION_FIELD)); + llassert(pContent.get(REGION_FIELD).isUUID()); + mRegionUUID = pContent.get(REGION_FIELD).asUUID(); + + parseStatus(pContent); +} + +LLPathfindingNavMeshStatus::LLPathfindingNavMeshStatus(const LLPathfindingNavMeshStatus &pOther) + : mIsValid(pOther.mIsValid), + mRegionUUID(pOther.mRegionUUID), + mVersion(pOther.mVersion), + mStatus(pOther.mStatus) +{ +} + +LLPathfindingNavMeshStatus::~LLPathfindingNavMeshStatus() +{ +} + +LLPathfindingNavMeshStatus &LLPathfindingNavMeshStatus::operator =(const LLPathfindingNavMeshStatus &pOther) +{ + mIsValid = pOther.mIsValid; + mRegionUUID = pOther.mRegionUUID; + mVersion = pOther.mVersion; + mStatus = pOther.mStatus; + + return *this; +} + +void LLPathfindingNavMeshStatus::parseStatus(const LLSD &pContent) +{ + llassert(pContent.has(VERSION_FIELD)); + llassert(pContent.get(VERSION_FIELD).isInteger()); + llassert(pContent.get(VERSION_FIELD).asInteger() >= 0); + mVersion = static_cast(pContent.get(VERSION_FIELD).asInteger()); + + llassert(pContent.has(STATUS_FIELD)); + llassert(pContent.get(STATUS_FIELD).isString()); + std::string status = pContent.get(STATUS_FIELD).asString(); + + if (LLStringUtil::compareStrings(status, sStatusPending) == 0) + { + mStatus = kPending; + } + else if (LLStringUtil::compareStrings(status, sStatusBuilding) == 0) + { + mStatus = kBuilding; + } + else if (LLStringUtil::compareStrings(status, sStatusComplete) == 0) + { + mStatus = kComplete; + } + else if (LLStringUtil::compareStrings(status, sStatusRepending) == 0) + { + mStatus = kRepending; + } + else + { + mStatus = kComplete; + llassert(0); + } +} diff --git a/indra/newview/llpathfindingnavmeshstatus.h b/indra/newview/llpathfindingnavmeshstatus.h new file mode 100644 index 000000000..74533fa48 --- /dev/null +++ b/indra/newview/llpathfindingnavmeshstatus.h @@ -0,0 +1,77 @@ +/** +* @file llpathfindingnavmeshstatus.h +* @brief Header file for llpathfindingnavmeshstatus +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGNAVMESHSTATUS_H +#define LL_LLPATHFINDINGNAVMESHSTATUS_H + +#include + +#include "lluuid.h" + +class LLSD; + +class LLPathfindingNavMeshStatus +{ +public: + typedef enum + { + kPending, + kBuilding, + kComplete, + kRepending + } ENavMeshStatus; + + LLPathfindingNavMeshStatus(); + LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID); + LLPathfindingNavMeshStatus(const LLUUID &pRegionUUID, const LLSD &pContent); + LLPathfindingNavMeshStatus(const LLSD &pContent); + LLPathfindingNavMeshStatus(const LLPathfindingNavMeshStatus &pOther); + virtual ~LLPathfindingNavMeshStatus(); + + LLPathfindingNavMeshStatus &operator =(const LLPathfindingNavMeshStatus &pOther); + + bool isValid() const {return mIsValid;}; + const LLUUID &getRegionUUID() const {return mRegionUUID;}; + U32 getVersion() const {return mVersion;}; + ENavMeshStatus getStatus() const {return mStatus;}; + +protected: + +private: + void parseStatus(const LLSD &pContent); + + bool mIsValid; + LLUUID mRegionUUID; + U32 mVersion; + ENavMeshStatus mStatus; + + static const std::string sStatusPending; + static const std::string sStatusBuilding; + static const std::string sStatusComplete; + static const std::string sStatusRepending; +}; + +#endif // LL_LLPATHFINDINGNAVMESHSTATUS_H diff --git a/indra/newview/llpathfindingobject.cpp b/indra/newview/llpathfindingobject.cpp new file mode 100644 index 000000000..916eceb4c --- /dev/null +++ b/indra/newview/llpathfindingobject.cpp @@ -0,0 +1,162 @@ +/** +* @file llpathfindingobject.cpp +* @brief Implementation of llpathfindingobject +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingobject.h" + +#include + +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llsd.h" +#include "lluuid.h" +#include "v3math.h" + +#define PATHFINDING_OBJECT_NAME_FIELD "name" +#define PATHFINDING_OBJECT_DESCRIPTION_FIELD "description" +#define PATHFINDING_OBJECT_OWNER_FIELD "owner" +#define PATHFINDING_OBJECT_POSITION_FIELD "position" +#define PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD "owner_is_group" + +//--------------------------------------------------------------------------- +// LLPathfindingObject +//--------------------------------------------------------------------------- + +LLPathfindingObject::LLPathfindingObject() + : mUUID(), + mName(), + mDescription(), + mOwnerUUID(), + mHasOwnerName(false), + mOwnerName(), + mIsGroupOwned(false), + mLocation() +{ +} + +LLPathfindingObject::LLPathfindingObject(const std::string &pUUID, const LLSD &pObjectData) + : mUUID(pUUID), + mName(), + mDescription(), + mOwnerUUID(), + mHasOwnerName(false), + mOwnerName(), + mIsGroupOwned(false), + mLocation() +{ + parseObjectData(pObjectData); +} + +LLPathfindingObject::LLPathfindingObject(const LLPathfindingObject& pOther) + : mUUID(pOther.mUUID), + mName(pOther.mName), + mDescription(pOther.mDescription), + mOwnerUUID(pOther.mOwnerUUID), + mHasOwnerName(false), + mOwnerName(), + mIsGroupOwned(pOther.mIsGroupOwned), + mLocation(pOther.mLocation) +{ + fetchOwnerName(); +} + +LLPathfindingObject::~LLPathfindingObject() +{ +} + +LLPathfindingObject &LLPathfindingObject::operator =(const LLPathfindingObject& pOther) +{ + mUUID = pOther.mUUID; + mName = pOther.mName; + mDescription = pOther.mDescription; + mOwnerUUID = pOther.mOwnerUUID; + fetchOwnerName(); + mIsGroupOwned = pOther.mIsGroupOwned; + mLocation = pOther.mLocation; + + return *this; +} + +std::string LLPathfindingObject::getOwnerName() const +{ + std::string ownerName; + + if (hasOwner()) + { + ownerName = mOwnerName.getCompleteName(); + } + + return ownerName; +} + +void LLPathfindingObject::parseObjectData(const LLSD &pObjectData) +{ + llassert(pObjectData.has(PATHFINDING_OBJECT_NAME_FIELD)); + llassert(pObjectData.get(PATHFINDING_OBJECT_NAME_FIELD).isString()); + mName = pObjectData.get(PATHFINDING_OBJECT_NAME_FIELD).asString(); + + llassert(pObjectData.has(PATHFINDING_OBJECT_DESCRIPTION_FIELD)); + llassert(pObjectData.get(PATHFINDING_OBJECT_DESCRIPTION_FIELD).isString()); + mDescription = pObjectData.get(PATHFINDING_OBJECT_DESCRIPTION_FIELD).asString(); + + llassert(pObjectData.has(PATHFINDING_OBJECT_OWNER_FIELD)); + llassert(pObjectData.get(PATHFINDING_OBJECT_OWNER_FIELD).isUUID()); + mOwnerUUID = pObjectData.get(PATHFINDING_OBJECT_OWNER_FIELD).asUUID(); + fetchOwnerName(); + + if (pObjectData.has(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD)) + { + llassert(pObjectData.get(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD).isBoolean()); + mIsGroupOwned = pObjectData.get(PATHFINDING_OBJECT_IS_GROUP_OWNED_FIELD).asBoolean(); + } + + llassert(pObjectData.has(PATHFINDING_OBJECT_POSITION_FIELD)); + llassert(pObjectData.get(PATHFINDING_OBJECT_POSITION_FIELD).isArray()); + mLocation.setValue(pObjectData.get(PATHFINDING_OBJECT_POSITION_FIELD)); +} + +void LLPathfindingObject::fetchOwnerName() +{ + mHasOwnerName = false; + if (hasOwner()) + { + mHasOwnerName = LLAvatarNameCache::get(mOwnerUUID, &mOwnerName); + if (!mHasOwnerName) + { + LLAvatarNameCache::get(mOwnerUUID, boost::bind(&LLPathfindingObject::handleAvatarNameFetch, this, _1, _2)); + } + } +} + +void LLPathfindingObject::handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName) +{ + llassert(mOwnerUUID == pOwnerUUID); + mOwnerName = pAvatarName; + mHasOwnerName = true; +} diff --git a/indra/newview/llpathfindingobject.h b/indra/newview/llpathfindingobject.h new file mode 100644 index 000000000..d45cc554f --- /dev/null +++ b/indra/newview/llpathfindingobject.h @@ -0,0 +1,80 @@ +/** +* @file llpathfindingobject.h +* @brief Header file for llpathfindingobject +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGOBJECT_H +#define LL_LLPATHFINDINGOBJECT_H + +#include + +#include + +#include "llavatarname.h" +#include "lluuid.h" +#include "v3math.h" + +class LLPathfindingObject; +class LLSD; + +typedef boost::shared_ptr LLPathfindingObjectPtr; + +class LLPathfindingObject +{ +public: + LLPathfindingObject(); + LLPathfindingObject(const std::string &pUUID, const LLSD &pObjectData); + LLPathfindingObject(const LLPathfindingObject& pOther); + virtual ~LLPathfindingObject(); + + LLPathfindingObject& operator =(const LLPathfindingObject& pOther); + + inline const LLUUID& getUUID() const {return mUUID;}; + inline const std::string& getName() const {return mName;}; + inline const std::string& getDescription() const {return mDescription;}; + inline BOOL hasOwner() const {return mOwnerUUID.notNull();}; + inline bool hasOwnerName() const {return mHasOwnerName;}; + std::string getOwnerName() const; + inline BOOL isGroupOwned() const {return mIsGroupOwned;}; + inline const LLVector3& getLocation() const {return mLocation;}; + +protected: + +private: + void parseObjectData(const LLSD &pObjectData); + + void fetchOwnerName(); + void handleAvatarNameFetch(const LLUUID &pOwnerUUID, const LLAvatarName &pAvatarName); + + LLUUID mUUID; + std::string mName; + std::string mDescription; + LLUUID mOwnerUUID; + bool mHasOwnerName; + LLAvatarName mOwnerName; + BOOL mIsGroupOwned; + LLVector3 mLocation; +}; + +#endif // LL_LLPATHFINDINGOBJECT_H diff --git a/indra/newview/llpathfindingobjectlist.cpp b/indra/newview/llpathfindingobjectlist.cpp new file mode 100644 index 000000000..68a7e736e --- /dev/null +++ b/indra/newview/llpathfindingobjectlist.cpp @@ -0,0 +1,112 @@ +/** +* @file llpathfindingobjectlist.cpp +* @brief Implementation of llpathfindingobjectlist +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llpathfindingobjectlist.h" + +#include +#include + +#include "llpathfindingobject.h" + +//--------------------------------------------------------------------------- +// LLPathfindingObjectList +//--------------------------------------------------------------------------- + +LLPathfindingObjectList::LLPathfindingObjectList() + : mObjectMap() +{ +} + +LLPathfindingObjectList::~LLPathfindingObjectList() +{ +} + +bool LLPathfindingObjectList::isEmpty() const +{ + return mObjectMap.empty(); +} + +void LLPathfindingObjectList::update(LLPathfindingObjectPtr pUpdateObjectPtr) +{ + if (pUpdateObjectPtr != NULL) + { + std::string updateObjectId = pUpdateObjectPtr->getUUID().asString(); + + LLPathfindingObjectMap::iterator foundObjectIter = mObjectMap.find(updateObjectId); + if (foundObjectIter == mObjectMap.end()) + { + mObjectMap.insert(std::pair(updateObjectId, pUpdateObjectPtr)); + } + else + { + foundObjectIter->second = pUpdateObjectPtr; + } + } +} + +void LLPathfindingObjectList::update(LLPathfindingObjectListPtr pUpdateObjectListPtr) +{ + if ((pUpdateObjectListPtr != NULL) && !pUpdateObjectListPtr->isEmpty()) + { + for (LLPathfindingObjectMap::const_iterator updateObjectIter = pUpdateObjectListPtr->begin(); + updateObjectIter != pUpdateObjectListPtr->end(); ++updateObjectIter) + { + const LLPathfindingObjectPtr updateObjectPtr = updateObjectIter->second; + update(updateObjectPtr); + } + } +} + +LLPathfindingObjectPtr LLPathfindingObjectList::find(const std::string &pObjectId) const +{ + LLPathfindingObjectPtr objectPtr; + + LLPathfindingObjectMap::const_iterator objectIter = mObjectMap.find(pObjectId); + if (objectIter != mObjectMap.end()) + { + objectPtr = objectIter->second; + } + + return objectPtr; +} + +LLPathfindingObjectList::const_iterator LLPathfindingObjectList::begin() const +{ + return mObjectMap.begin(); +} + +LLPathfindingObjectList::const_iterator LLPathfindingObjectList::end() const +{ + return mObjectMap.end(); +} + +LLPathfindingObjectMap &LLPathfindingObjectList::getObjectMap() +{ + return mObjectMap; +} diff --git a/indra/newview/llpathfindingobjectlist.h b/indra/newview/llpathfindingobjectlist.h new file mode 100644 index 000000000..3ad8e8b09 --- /dev/null +++ b/indra/newview/llpathfindingobjectlist.h @@ -0,0 +1,67 @@ +/** +* @file llpathfindingobjectlist.h +* @brief Header file for llpathfindingobjectlist +* @author Stinson@lindenlab.com +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_LLPATHFINDINGOBJECTLIST_H +#define LL_LLPATHFINDINGOBJECTLIST_H + +#include +#include + +#include + +#include "llpathfindingobject.h" + +class LLPathfindingObjectList; + +typedef boost::shared_ptr LLPathfindingObjectListPtr; +typedef std::map LLPathfindingObjectMap; + +class LLPathfindingObjectList +{ +public: + LLPathfindingObjectList(); + virtual ~LLPathfindingObjectList(); + + bool isEmpty() const; + + void update(LLPathfindingObjectPtr pUpdateObjectPtr); + void update(LLPathfindingObjectListPtr pUpdateObjectListPtr); + + LLPathfindingObjectPtr find(const std::string &pObjectId) const; + + typedef LLPathfindingObjectMap::const_iterator const_iterator; + const_iterator begin() const; + const_iterator end() const; + + +protected: + LLPathfindingObjectMap &getObjectMap(); + +private: + LLPathfindingObjectMap mObjectMap; +}; + +#endif // LL_LLPATHFINDINGOBJECTLIST_H diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index fbcd93912..1df29b37e 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -2,31 +2,25 @@ * @file llphysicsmotion.cpp * @brief Implementation of LLPhysicsMotion class. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2011, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -74,6 +68,19 @@ inline F64 llsgn(const F64 a) class LLPhysicsMotion { public: + typedef enum + { + SMOOTHING = 0, + MASS, + GRAVITY, + SPRING, + GAIN, + DAMPING, + DRAG, + MAX_EFFECT, + NUM_PARAMS + } eParamName; + /* param_driver_name: The param that controls the params that are being affected by the physics. joint_name: The joint that the body part is attached to. The joint is @@ -107,8 +114,12 @@ public: mVelocity_local(0) { mJointState = new LLJointState; - } + for (U32 i = 0; i < NUM_PARAMS; ++i) + { + mParamCache[i] = NULL; + } + } void getString(std::ostringstream &oss); BOOL initialize(); @@ -124,19 +135,46 @@ public: void reset(); protected: - F32 getParamValue(const std::string& controller_key) - { - const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key); + + F32 getParamValue(eParamName param) + { + static std::string controller_key[] = + { + "Smoothing", + "Mass", + "Gravity", + "Spring", + "Gain", + "Damping", + "Drag", + "MaxEffect" + }; + + if (!mParamCache[param]) + { + const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key[param]); if (entry == mParamControllers.end()) { - return sDefaultController[controller_key]; + return sDefaultController[controller_key[param]]; } const std::string& param_name = (*entry).second.c_str(); - return mCharacter->getVisualParamWeight(param_name.c_str()); - } + mParamCache[param] = mCharacter->getVisualParam(param_name.c_str()); + } + + if (mParamCache[param]) + { + return mParamCache[param]->getWeight(); + } + else + { + return sDefaultController[controller_key[param]]; + } + } + + void setParamValue(LLViewerVisualParam *param, const F32 new_value_local, - F32 behavior_maxeffect); + F32 behavior_maxeffect); F32 toLocal(const LLVector3 &world); F32 calculateVelocity_local(); @@ -164,6 +202,8 @@ private: F32 mLastTime; + LLVisualParam* mParamCache[NUM_PARAMS]; + static default_controller_map_t sDefaultController; }; @@ -268,7 +308,7 @@ void LLPhysicsMotion::getString(std::ostringstream &oss) oss << " Controllers:" << std::endl; for(controller_map_t::const_iterator it = mParamControllers.begin(); it!= mParamControllers.end(); ++it) { - oss << " mParamControllers[\"" << it->first << "\"] = \"" << it->second << "\" =" << getParamValue(it->first) << std::endl; + oss << " mParamControllers[\"" << it->first << "\"] = \"" << it->second << "\" =" << mCharacter->getVisualParamWeight(it->first.c_str()) << std::endl; } } @@ -574,15 +614,16 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) LLJoint *joint = mJointState->getJoint(); - const F32 behavior_mass = getParamValue("Mass"); - const F32 behavior_gravity = getParamValue("Gravity"); - const F32 behavior_spring = getParamValue("Spring"); - const F32 behavior_gain = getParamValue("Gain"); - const F32 behavior_damping = getParamValue("Damping"); - const F32 behavior_drag = getParamValue("Drag"); - const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. + const F32 behavior_mass = getParamValue(MASS); + const F32 behavior_gravity = getParamValue(GRAVITY); + const F32 behavior_spring = getParamValue(SPRING); + const F32 behavior_gain = getParamValue(GAIN); + const F32 behavior_damping = getParamValue(DAMPING); + const F32 behavior_drag = getParamValue(DRAG); + F32 behavior_maxeffect = getParamValue(MAX_EFFECT); + + const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. - F32 behavior_maxeffect = getParamValue("MaxEffect"); if (physics_test) behavior_maxeffect = 1.0f; diff --git a/indra/newview/llphysicsmotion.h b/indra/newview/llphysicsmotion.h index 7e6bddd17..7412c9d88 100644 --- a/indra/newview/llphysicsmotion.h +++ b/indra/newview/llphysicsmotion.h @@ -2,31 +2,25 @@ * @file llphysicsmotion.h * @brief Implementation of LLPhysicsMotion class. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2011, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -113,6 +107,7 @@ public: virtual void onDeactivate(); LLCharacter* getCharacter() { return mCharacter; } + protected: void addMotion(LLPhysicsMotion *motion); private: diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 491cf43f3..d7b342b25 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -229,16 +229,20 @@ U32 LLPolyMeshSharedData::getNumKB() BOOL LLPolyMeshSharedData::allocateVertexData( U32 numVertices ) { U32 i; - mBaseCoords = new LLVector3[ numVertices ]; - mBaseNormals = new LLVector3[ numVertices ]; - mBaseBinormals = new LLVector3[ numVertices ]; + mBaseCoords = new LLVector4a[ numVertices ]; + mBaseNormals = new LLVector4a[ numVertices ]; + mBaseBinormals = new LLVector4a[ numVertices ]; mTexCoords = new LLVector2[ numVertices ]; mDetailTexCoords = new LLVector2[ numVertices ]; mWeights = new F32[ numVertices ]; for (i = 0; i < numVertices; i++) { + mBaseCoords[i].clear(); + mBaseNormals[i].clear(); + mBaseBinormals[i].clear(); + mTexCoords[i].clear(); mWeights[i] = 0.f; - } + } mNumVertices = numVertices; return TRUE; } @@ -408,40 +412,48 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName ) allocateVertexData( numVertices ); - //---------------------------------------------------------------- - // Coords - //---------------------------------------------------------------- - numRead = fread(mBaseCoords, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseCoords, sizeof(float), 3*numVertices); - if (numRead != numVertices) + for (U16 i = 0; i < numVertices; ++i) { - llerrs << "can't read Coordinates from " << fileName << llendl; - return FALSE; - } + //---------------------------------------------------------------- + // Coords + //---------------------------------------------------------------- + numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseCoords[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << "can't read Coordinates from " << fileName << llendl; + return FALSE; + } + } - //---------------------------------------------------------------- - // Normals - //---------------------------------------------------------------- - numRead = fread(mBaseNormals, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseNormals, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << " can't read Normals from " << fileName << llendl; - return FALSE; - } + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Normals + //---------------------------------------------------------------- + numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseNormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Normals from " << fileName << llendl; + return FALSE; + } + } - //---------------------------------------------------------------- - // Binormals - //---------------------------------------------------------------- - numRead = fread(mBaseBinormals, 3*sizeof(float), numVertices, fp); - llendianswizzle(mBaseBinormals, sizeof(float), 3*numVertices); - if (numRead != numVertices) - { - llerrs << " can't read Binormals from " << fileName << llendl; - return FALSE; + for (U16 i = 0; i < numVertices; ++i) + { + //---------------------------------------------------------------- + // Binormals + //---------------------------------------------------------------- + numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp); + llendianswizzle(&mBaseBinormals[i], sizeof(float), 3); + if (numRead != 3) + { + llerrs << " can't read Binormals from " << fileName << llendl; + return FALSE; + } } - //---------------------------------------------------------------- // TexCoords //---------------------------------------------------------------- @@ -767,21 +779,28 @@ LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_ { // Allocate memory without initializing every vector // NOTE: This makes asusmptions about the size of LLVector[234] - int nverts = mSharedData->mNumVertices; - int nfloats = nverts * (2*4 + 3*3 + 2 + 4); + S32 nverts = mSharedData->mNumVertices; + //make sure it's an even number of verts for alignment + nverts += nverts%2; + S32 nfloats = nverts * ( + 4 + //coords + 4 + //normals + 4 + //weights + 2 + //coords + 4 + //scaled normals + 4 + //binormals + 4); //scaled binormals + //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); - int offset = 0; - mCoords = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mNormals = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - - // these members don't need to be 16-byte aligned, but the first one might be - // read during an aligned memcpy of mTexCoords - mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + S32 offset = 0; + mCoords = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + mScaledNormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; + mScaledBinormals = (LLVector4a*)(mVertexData + offset); offset += 4*nverts; initializeForMorph(); } } @@ -966,38 +985,47 @@ BOOL LLPolyMesh::saveLLM(LLFILE *fp) //---------------------------------------------------------------- // Coords //---------------------------------------------------------------- - LLVector3* coords = mSharedData->mBaseCoords; - - llendianswizzle(coords, sizeof(float), 3*numVertices); - if (fwrite(coords, 3*sizeof(float), numVertices, fp) != numVertices) + for (U16 i = 0; i < numVertices; ++i) { - llwarns << "Short write" << llendl; + LLVector4a& coords = mSharedData->mBaseCoords[i]; + + llendianswizzle(coords.getF32ptr(), sizeof(float), 3); + if (fwrite(coords.getF32ptr(), 3*sizeof(float), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(coords.getF32ptr(), sizeof(float), 3); } - llendianswizzle(coords, sizeof(float), 3*numVertices); //---------------------------------------------------------------- // Normals //---------------------------------------------------------------- - LLVector3* normals = mSharedData->mBaseNormals; - - llendianswizzle(normals, sizeof(float), 3*numVertices); - if (fwrite(normals, 3*sizeof(float), numVertices, fp) != numVertices) + for (U16 i = 0; i < numVertices; ++i) { - llwarns << "Short write" << llendl; + LLVector4a& normals = mSharedData->mBaseNormals[i]; + + llendianswizzle(normals.getF32ptr(), sizeof(float), 3); + if (fwrite(normals.getF32ptr(), 3*sizeof(float), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(normals.getF32ptr(), sizeof(float), 3); } - llendianswizzle(normals, sizeof(float), 3*numVertices); //---------------------------------------------------------------- // Binormals //---------------------------------------------------------------- - LLVector3* binormals = mSharedData->mBaseBinormals; - - llendianswizzle(binormals, sizeof(float), 3*numVertices); - if (fwrite(binormals, 3*sizeof(float), numVertices, fp) != numVertices) + for (U16 i = 0; i < numVertices; ++i) { - llwarns << "Short write" << llendl; + LLVector4a& binormals = mSharedData->mBaseBinormals[i]; + + llendianswizzle(binormals.getF32ptr(), sizeof(float), 3); + if (fwrite(binormals.getF32ptr(), 3*sizeof(float), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(binormals.getF32ptr(), sizeof(float), 3); } - llendianswizzle(binormals, sizeof(float), 3*numVertices); //---------------------------------------------------------------- // TexCoords @@ -1224,24 +1252,24 @@ BOOL LLPolyMesh::saveOBJ(LLFILE *fp) int nfaces = mSharedData->mNumFaces; int i; - LLVector4* coords = getWritableCoords(); + LLVector4a* coords = getWritableCoords(); for ( i=0; imBaseCoords, mCoords, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mSharedData->mBaseNormals, mNormals, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mSharedData->mBaseBinormals, mBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mSharedData->mTexCoords, mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mSharedData->mBaseCoords, (F32*) mCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mSharedData->mBaseNormals, (F32*) mNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mSharedData->mBaseBinormals, (F32*) mBinormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mSharedData->mTexCoords, (F32*) mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); // Update all avatars by applying the delta @@ -1479,27 +1496,29 @@ BOOL LLPolyMesh::setSharedFromCurrent() LLPolyMesh* mesh = avatarp->getMesh(mSharedData); if (mesh) { - LLVector4 *mesh_coords = mesh->getWritableCoords(); - LLVector4 *mesh_normals = mesh->getWritableNormals(); - LLVector3 *mesh_binormals = mesh->getWritableBinormals(); - LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); - LLVector3 *mesh_scaled_normals = mesh->getScaledNormals(); - LLVector3 *mesh_scaled_binormals = mesh->getScaledBinormals(); + LLVector4a *mesh_coords = mesh->getWritableCoords(); + LLVector4a *mesh_normals = mesh->getWritableNormals(); + LLVector4a *mesh_binormals = mesh->getWritableBinormals(); + LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); + LLVector4a *mesh_scaled_normals = mesh->getScaledNormals(); + LLVector4a *mesh_scaled_binormals = mesh->getScaledBinormals(); for( vert_index = 0; vert_index < nverts; vert_index++) { - mesh_coords[vert_index] -= delta_coords[vert_index]; + mesh_coords[vert_index].sub(delta_coords[vert_index]); mesh_tex_coords[vert_index] -= delta_tex_coords[vert_index]; - mesh_scaled_normals[vert_index] -= LLVector3(delta_normals[vert_index]); - LLVector3 normalized_normal = mesh_scaled_normals[vert_index]; - normalized_normal.normVec(); - mesh_normals[vert_index] = LLVector4(normalized_normal); + mesh_scaled_normals[vert_index].sub(delta_normals[vert_index]); + LLVector4a normalized_normal = mesh_scaled_normals[vert_index]; + normalized_normal.normalize3(); + mesh_normals[vert_index] = normalized_normal; - mesh_scaled_binormals[vert_index] -= delta_binormals[vert_index]; - LLVector3 tangent = mesh_scaled_binormals[vert_index] % normalized_normal; - LLVector3 normalized_binormal = normalized_normal % tangent; - normalized_binormal.normVec(); + mesh_scaled_binormals[vert_index].sub(delta_binormals[vert_index]); + LLVector4a tangent; + tangent.setCross3(mesh_scaled_binormals[vert_index], normalized_normal); + LLVector4a normalized_binormal; + normalized_binormal.setCross3(normalized_normal, tangent); + normalized_binormal.normalize3(); mesh_binormals[vert_index] = normalized_binormal; } @@ -1598,7 +1617,7 @@ void LLPolyMesh::dumpDiagInfo(void*) //----------------------------------------------------------------------------- // getWritableCoords() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableCoords() +LLVector4a *LLPolyMesh::getWritableCoords() { return mCoords; } @@ -1606,7 +1625,7 @@ LLVector4 *LLPolyMesh::getWritableCoords() //----------------------------------------------------------------------------- // getWritableNormals() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableNormals() +LLVector4a *LLPolyMesh::getWritableNormals() { return mNormals; } @@ -1614,7 +1633,7 @@ LLVector4 *LLPolyMesh::getWritableNormals() //----------------------------------------------------------------------------- // getWritableBinormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getWritableBinormals() +LLVector4a *LLPolyMesh::getWritableBinormals() { return mBinormals; } @@ -1623,7 +1642,7 @@ LLVector3 *LLPolyMesh::getWritableBinormals() //----------------------------------------------------------------------------- // getWritableClothingWeights() //----------------------------------------------------------------------------- -LLVector4 *LLPolyMesh::getWritableClothingWeights() +LLVector4a *LLPolyMesh::getWritableClothingWeights() { return mClothingWeights; } @@ -1639,7 +1658,7 @@ LLVector2 *LLPolyMesh::getWritableTexCoords() //----------------------------------------------------------------------------- // getScaledNormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getScaledNormals() +LLVector4a *LLPolyMesh::getScaledNormals() { return mScaledNormals; } @@ -1647,7 +1666,7 @@ LLVector3 *LLPolyMesh::getScaledNormals() //----------------------------------------------------------------------------- // getScaledBinormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getScaledBinormals() +LLVector4a *LLPolyMesh::getScaledBinormals() { return mScaledBinormals; } @@ -1661,19 +1680,20 @@ void LLPolyMesh::initializeForMorph() if (!mSharedData) return; + LLVector4a::memcpyNonAliased16((F32*) mCoords, (F32*) mSharedData->mBaseCoords, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); + for (U32 i = 0; i < (U32)mSharedData->mNumVertices; ++i) { - mCoords[i] = LLVector4(mSharedData->mBaseCoords[i]); - mNormals[i] = LLVector4(mSharedData->mBaseNormals[i]); + mClothingWeights[i].clear(); } - - memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices); } + //----------------------------------------------------------------------------- // getMorphList() //----------------------------------------------------------------------------- @@ -1818,8 +1838,8 @@ BOOL LLPolySkeletalDistortionInfo::parseXml(LLXmlTreeNode* node) //----------------------------------------------------------------------------- LLPolySkeletalDistortion::LLPolySkeletalDistortion(LLVOAvatar *avatarp) { - mAvatar = avatarp; - mDefaultVec.setVec(0.001f, 0.001f, 0.001f); + mAvatar = avatarp; + mDefaultVec.splat(0.001f); } //----------------------------------------------------------------------------- @@ -1947,36 +1967,49 @@ LLPolyMorphData *clone_morph_param_direction(const LLPolyMorphData *src_data, const LLVector3 &direction, const std::string &name) { - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = direction; - cloned_morph_data->mNormals[v] = LLVector3(0,0,0); - cloned_morph_data->mBinormals[v] = LLVector3(0,0,0); - } - return cloned_morph_data; + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + LLVector4a dir; + dir.load3(direction.mV); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + cloned_morph_data->mCoords[v] = dir; + cloned_morph_data->mNormals[v].clear(); + cloned_morph_data->mBinormals[v].clear(); + } + return cloned_morph_data; } LLPolyMorphData *clone_morph_param_cleavage(const LLPolyMorphData *src_data, F32 scale, const std::string &name) { - LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); - cloned_morph_data->mName = name; - for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) - { - cloned_morph_data->mCoords[v] = src_data->mCoords[v]*scale; - cloned_morph_data->mNormals[v] = src_data->mNormals[v]*scale; - cloned_morph_data->mBinormals[v] = src_data->mBinormals[v]*scale; - if (cloned_morph_data->mCoords[v][1] < 0) - { - cloned_morph_data->mCoords[v][1] *= -1; - cloned_morph_data->mNormals[v][1] *= -1; - cloned_morph_data->mBinormals[v][1] *= -1; - } - } - return cloned_morph_data; + LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data); + cloned_morph_data->mName = name; + + LLVector4a sc; + sc.splat(scale); + + LLVector4a nsc; + nsc.set(scale, -scale, scale, scale); + + for (U32 v=0; v < cloned_morph_data->mNumIndices; v++) + { + if (cloned_morph_data->mCoords[v][1] < 0) + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],nsc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v],nsc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],nsc); + } + else + { + cloned_morph_data->mCoords[v].setMul(src_data->mCoords[v],sc); + cloned_morph_data->mNormals[v].setMul(src_data->mNormals[v], sc); + cloned_morph_data->mBinormals[v].setMul(src_data->mBinormals[v],sc); + } + } + return cloned_morph_data; } // End diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index 4b7927564..d09909309 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -73,9 +73,9 @@ private: // vertex data S32 mNumVertices; - LLVector3 *mBaseCoords; - LLVector3 *mBaseNormals; - LLVector3 *mBaseBinormals; + LLVector4a *mBaseCoords; + LLVector4a *mBaseNormals; + LLVector4a *mBaseBinormals; LLVector2 *mTexCoords; LLVector2 *mDetailTexCoords; F32 *mWeights; @@ -235,41 +235,41 @@ public: } // Get coords - const LLVector4 *getCoords() const{ + const LLVector4a *getCoords() const{ return mCoords; } // non const version - LLVector4 *getWritableCoords(); + LLVector4a *getWritableCoords(); // Get normals - const LLVector4 *getNormals() const{ + const LLVector4a *getNormals() const{ return mNormals; } // Get normals - const LLVector3 *getBinormals() const{ + const LLVector4a *getBinormals() const{ return mBinormals; } // Get base mesh normals - const LLVector3 *getBaseNormals() const{ + const LLVector4a *getBaseNormals() const{ llassert(mSharedData); return mSharedData->mBaseNormals; } // Get base mesh normals - const LLVector3 *getBaseBinormals() const{ + const LLVector4a *getBaseBinormals() const{ llassert(mSharedData); return mSharedData->mBaseBinormals; } // intermediate morphed normals and output normals - LLVector4 *getWritableNormals(); - LLVector3 *getScaledNormals(); + LLVector4a *getWritableNormals(); + LLVector4a *getScaledNormals(); - LLVector3 *getWritableBinormals(); - LLVector3 *getScaledBinormals(); + LLVector4a *getWritableBinormals(); + LLVector4a *getScaledBinormals(); // Get texCoords const LLVector2 *getTexCoords() const { @@ -293,9 +293,9 @@ public: F32 *getWritableWeights() const; - LLVector4 *getWritableClothingWeights(); + LLVector4a *getWritableClothingWeights(); - const LLVector4 *getClothingWeights() + const LLVector4a *getClothingWeights() { return mClothingWeights; } @@ -363,17 +363,17 @@ protected: // Single array of floats for allocation / deletion F32 *mVertexData; // deformed vertices (resulting from application of morph targets) - LLVector4 *mCoords; + LLVector4a *mCoords; // deformed normals (resulting from application of morph targets) - LLVector3 *mScaledNormals; + LLVector4a *mScaledNormals; // output normals (after normalization) - LLVector4 *mNormals; + LLVector4a *mNormals; // deformed binormals (resulting from application of morph targets) - LLVector3 *mScaledBinormals; + LLVector4a *mScaledBinormals; // output binormals (after normalization) - LLVector3 *mBinormals; + LLVector4a *mBinormals; // weight values that mark verts as clothing/skin - LLVector4 *mClothingWeights; + LLVector4a *mClothingWeights; // output texture coordinates LLVector2 *mTexCoords; @@ -441,17 +441,17 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 0.1f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mDefaultVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mDefaultVec; } /*virtual*/ F32 getMaxDistortion() { return 0.1f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector3(0.001f, 0.001f, 0.001f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh){return LLVector4a(0.001f, 0.001f, 0.001f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return &mDefaultVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; protected: typedef std::map joint_vec_map_t; joint_vec_map_t mJointScales; joint_vec_map_t mJointOffsets; - LLVector3 mDefaultVec; + LLVector4a mDefaultVec; // Backlink only; don't make this an LLPointer. LLVOAvatar *mAvatar; }; diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 73a0b525c..b43837e89 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -49,7 +49,7 @@ LLPolyMorphData::LLPolyMorphData(const std::string& morph_name) mNumIndices = 0; mCurrentIndex = 0; mTotalDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); mMaxDistortion = 0.f; mVertexIndices = NULL; mCoords = NULL; @@ -74,9 +74,9 @@ LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : { const S32 numVertices = mNumIndices; - mCoords = new LLVector3[numVertices]; - mNormals = new LLVector3[numVertices]; - mBinormals = new LLVector3[numVertices]; + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; mTexCoords = new LLVector2[numVertices]; mVertexIndices = new U32[numVertices]; @@ -90,6 +90,7 @@ LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) : } } + //----------------------------------------------------------------------------- // ~LLPolyMorphData() //----------------------------------------------------------------------------- @@ -121,16 +122,16 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) //------------------------------------------------------------------------- // allocate vertices //------------------------------------------------------------------------- - mCoords = new LLVector3[numVertices]; - mNormals = new LLVector3[numVertices]; - mBinormals = new LLVector3[numVertices]; + mCoords = new LLVector4a[numVertices]; + mNormals = new LLVector4a[numVertices]; + mBinormals = new LLVector4a[numVertices]; mTexCoords = new LLVector2[numVertices]; // Actually, we are allocating more space than we need for the skiplist mVertexIndices = new U32[numVertices]; mNumIndices = 0; mTotalDistortion = 0.f; mMaxDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); mMesh = mesh; //------------------------------------------------------------------------- @@ -152,36 +153,36 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) } - numRead = fread(&mCoords[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); + numRead = fread(&mCoords[v], sizeof(F32), 3, fp); + llendianswizzle(&mCoords[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target vertex coordinates" << llendl; return FALSE; } - F32 magnitude = mCoords[v].magVec(); + F32 magnitude = mCoords[v].getLength3().getF32(); mTotalDistortion += magnitude; - mAvgDistortion.mV[VX] += fabs(mCoords[v].mV[VX]); - mAvgDistortion.mV[VY] += fabs(mCoords[v].mV[VY]); - mAvgDistortion.mV[VZ] += fabs(mCoords[v].mV[VZ]); + LLVector4a t; + t.setAbs(mCoords[v]); + mAvgDistortion.add(t); if (magnitude > mMaxDistortion) { mMaxDistortion = magnitude; } - numRead = fread(&mNormals[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); + numRead = fread(&mNormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mNormals[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target normal" << llendl; return FALSE; } - numRead = fread(&mBinormals[v].mV, sizeof(F32), 3, fp); - llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); + numRead = fread(&mBinormals[v], sizeof(F32), 3, fp); + llendianswizzle(&mBinormals[v], sizeof(F32), 3); if (numRead != 3) { llwarns << "Can't read morph target binormal" << llendl; @@ -200,8 +201,8 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) mNumIndices++; } - mAvgDistortion = mAvgDistortion * (1.f/(F32)mNumIndices); - mAvgDistortion.normVec(); + mAvgDistortion.mul(1.f/(F32)mNumIndices); + mAvgDistortion.normalize3fast(); return TRUE; } @@ -235,26 +236,26 @@ BOOL LLPolyMorphData::saveLLM(LLFILE *fp) } llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); - llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); - if (fwrite(&mCoords[v].mV, sizeof(F32), 3, fp) != 3) + llendianswizzle(mCoords[v].getF32ptr(), sizeof(F32), 3); + if (fwrite(mCoords[v].getF32ptr(), sizeof(F32), 3, fp) != 3) { llwarns << "Short write" << llendl; } - llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); + llendianswizzle(mCoords[v].getF32ptr(), sizeof(F32), 3); - llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); - if (fwrite(&mNormals[v].mV, sizeof(F32), 3, fp) != 3) + llendianswizzle(mNormals[v].getF32ptr(), sizeof(F32), 3); + if (fwrite(mNormals[v].getF32ptr(), sizeof(F32), 3, fp) != 3) { llwarns << "Short write" << llendl; } - llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); + llendianswizzle(mNormals[v].getF32ptr(), sizeof(F32), 3); - llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); - if (fwrite(&mBinormals[v].mV, sizeof(F32), 3, fp) != 3) + llendianswizzle(mBinormals[v].getF32ptr(), sizeof(F32), 3); + if (fwrite(mBinormals[v].getF32ptr(), sizeof(F32), 3, fp) != 3) { llwarns << "Short write" << llendl; } - llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); + llendianswizzle(mBinormals[v].getF32ptr(), sizeof(F32), 3); llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); if (fwrite(&mTexCoords[v].mV, sizeof(F32), 2, fp) != 2) @@ -277,17 +278,17 @@ BOOL LLPolyMorphData::saveOBJ(LLFILE *fp) LLPolyMesh mesh(mMesh, NULL); - LLVector4 *coords = mesh.getWritableCoords(); - LLVector4 *normals = mesh.getWritableNormals(); + LLVector4a *coords = mesh.getWritableCoords(); + LLVector4a *normals = mesh.getWritableNormals(); LLVector2 *tex_coords = mesh.getWritableTexCoords(); for(U32 vert_index_morph = 0; vert_index_morph < mNumIndices; vert_index_morph++) { S32 vert_index_mesh = mVertexIndices[vert_index_morph]; - coords[vert_index_mesh] += LLVector4(mCoords[vert_index_morph]); - normals[vert_index_mesh] += LLVector4(mNormals[vert_index_morph]); - normals[vert_index_mesh].normVec(); + coords[vert_index_mesh].add(mCoords[vert_index_morph]); + normals[vert_index_mesh].add(mNormals[vert_index_morph]); + normals[vert_index_mesh].normalize3(); tex_coords[vert_index_mesh] += mTexCoords[vert_index_morph]; } @@ -302,9 +303,9 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) if (!morph) return FALSE; - LLVector4 *morph_coords = morph->getWritableCoords(); - LLVector4 *morph_normals = morph->getWritableNormals(); - LLVector3 *morph_binormals = morph->getWritableBinormals(); + LLVector4a *morph_coords = morph->getWritableCoords(); + LLVector4a *morph_normals = morph->getWritableNormals(); + LLVector4a *morph_binormals = morph->getWritableBinormals(); LLVector2 *morph_tex_coords = morph->getWritableTexCoords(); // We now have the morph loaded as a mesh. We have to subtract the @@ -313,19 +314,19 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) LLPolyMesh delta(mMesh, NULL); U32 nverts = delta.getNumVertices(); - LLVector4 *delta_coords = delta.getWritableCoords(); - LLVector4 *delta_normals = delta.getWritableNormals(); - LLVector3 *delta_binormals = delta.getWritableBinormals(); + LLVector4a *delta_coords = delta.getWritableCoords(); + LLVector4a *delta_normals = delta.getWritableNormals(); + LLVector4a *delta_binormals = delta.getWritableBinormals(); LLVector2 *delta_tex_coords = delta.getWritableTexCoords(); U32 num_significant = 0; U32 vert_index; for( vert_index = 0; vert_index < nverts; vert_index++) { - delta_coords[vert_index] = morph_coords[vert_index] - delta_coords[vert_index]; - delta_normals[vert_index] = morph_normals[vert_index] - delta_normals[vert_index]; - delta_binormals[vert_index] = morph_binormals[vert_index] - delta_binormals[vert_index]; - delta_tex_coords[vert_index] = morph_tex_coords[vert_index] - delta_tex_coords[vert_index]; + delta_coords[vert_index].setSub( morph_coords[vert_index], delta_coords[vert_index]); + delta_normals[vert_index].setSub( morph_normals[vert_index], delta_normals[vert_index]); + delta_binormals[vert_index].setSub( morph_binormals[vert_index], delta_binormals[vert_index]); + delta_tex_coords[vert_index] = morph_tex_coords[vert_index] - delta_tex_coords[vert_index]; // For the normals and binormals, we really want the deltas // to be perpendicular to the mesh (bi)normals in the plane @@ -333,10 +334,10 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) // that the morph (bi)normals form the hypotenuses of right // triangles. Right now, we just compute the difference vector. - if (delta_coords[vert_index].length() > SIGNIFICANT_DELTA - || delta_normals[vert_index].length() > SIGNIFICANT_DELTA - || delta_binormals[vert_index].length() > SIGNIFICANT_DELTA - || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA) + if (delta_coords[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA + || delta_normals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA + || delta_binormals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA + || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA) { num_significant++; } @@ -353,39 +354,39 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) if (num_significant == 0) nindices = 1; - LLVector3* new_coords = new LLVector3[nindices]; - LLVector3* new_normals = new LLVector3[nindices]; - LLVector3* new_binormals = new LLVector3[nindices]; + LLVector4a* new_coords = new LLVector4a[nindices]; + LLVector4a* new_normals = new LLVector4a[nindices]; + LLVector4a* new_binormals = new LLVector4a[nindices]; LLVector2* new_tex_coords = new LLVector2[nindices]; U32* new_vertex_indices = new U32[nindices]; // We'll set the distortion directly mTotalDistortion = 0.f; mMaxDistortion = 0.f; - mAvgDistortion.zeroVec(); + mAvgDistortion.clear(); U32 morph_index = 0; for( vert_index = 0; vert_index < nverts; vert_index++) { - if (delta_coords[vert_index].length() > SIGNIFICANT_DELTA - || delta_normals[vert_index].length() > SIGNIFICANT_DELTA - || delta_binormals[vert_index].length() > SIGNIFICANT_DELTA - || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA + if (delta_coords[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA + || delta_normals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA + || delta_binormals[vert_index].getLength3().getF32() > SIGNIFICANT_DELTA + || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA || num_significant == 0) { new_vertex_indices[morph_index] = vert_index; - new_coords[morph_index] = LLVector3(delta_coords[vert_index]); - new_normals[morph_index] = LLVector3(delta_normals[vert_index]); + new_coords[morph_index] = delta_coords[vert_index]; + new_normals[morph_index] = delta_normals[vert_index]; new_binormals[morph_index] = delta_binormals[vert_index]; new_tex_coords[morph_index] = delta_tex_coords[vert_index]; - F32 magnitude = new_coords[morph_index].magVec(); + F32 magnitude = new_coords[morph_index].getLength3().getF32(); mTotalDistortion += magnitude; - mAvgDistortion.mV[VX] += fabs(new_coords[morph_index].mV[VX]); - mAvgDistortion.mV[VY] += fabs(new_coords[morph_index].mV[VY]); - mAvgDistortion.mV[VZ] += fabs(new_coords[morph_index].mV[VZ]); + LLVector4a t; + t.setAbs(new_coords[morph_index]); + mAvgDistortion.add(t); if (magnitude > mMaxDistortion) { @@ -397,8 +398,8 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) } } - mAvgDistortion = mAvgDistortion * (1.f/(F32)nindices); - mAvgDistortion.normVec(); + mAvgDistortion.mul(1.f/(F32)nindices); + mAvgDistortion.normalize3(); //------------------------------------------------------------------------- // compute the change in the morph @@ -412,9 +413,9 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) { vert_index = mVertexIndices[morph_index]; - delta_coords[vert_index] -= LLVector4(mCoords[morph_index]); - delta_normals[vert_index] -= LLVector4(mNormals[morph_index]); - delta_binormals[vert_index] -= mBinormals[morph_index]; + delta_coords[vert_index].sub( mCoords[morph_index]); + delta_normals[vert_index].sub( mNormals[morph_index]); + delta_binormals[vert_index].sub(mBinormals[morph_index]); delta_tex_coords[vert_index] -= mTexCoords[morph_index]; } @@ -451,27 +452,35 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) continue; }*/ - LLVector4 *mesh_coords = mesh->getWritableCoords(); - LLVector4 *mesh_normals = mesh->getWritableNormals(); - LLVector3 *mesh_binormals = mesh->getWritableBinormals(); - LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); - LLVector3 *mesh_scaled_normals = mesh->getScaledNormals(); - LLVector3 *mesh_scaled_binormals = mesh->getScaledBinormals(); + LLVector4a *mesh_coords = mesh->getWritableCoords(); + LLVector4a *mesh_normals = mesh->getWritableNormals(); + LLVector4a *mesh_binormals = mesh->getWritableBinormals(); + LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); + LLVector4a *mesh_scaled_normals = mesh->getScaledNormals(); + LLVector4a *mesh_scaled_binormals = mesh->getScaledBinormals(); for( vert_index = 0; vert_index < nverts; vert_index++) { - mesh_coords[vert_index] += delta_coords[vert_index] * weight; + delta_coords[vert_index].mul(weight); + mesh_coords[vert_index].add(delta_coords[vert_index]); + mesh_tex_coords[vert_index] += delta_tex_coords[vert_index] * weight; - mesh_scaled_normals[vert_index] += LLVector3(delta_normals[vert_index] * weight * NORMAL_SOFTEN_FACTOR); - LLVector3 normalized_normal = mesh_scaled_normals[vert_index]; - normalized_normal.normVec(); - mesh_normals[vert_index] = LLVector4(normalized_normal); + delta_normals[vert_index].mul(weight * NORMAL_SOFTEN_FACTOR); + mesh_scaled_normals[vert_index].add(delta_normals[vert_index]); + + LLVector4a normalized_normal = mesh_scaled_normals[vert_index]; + normalized_normal.normalize3(); + mesh_normals[vert_index] = normalized_normal; - mesh_scaled_binormals[vert_index] += delta_binormals[vert_index] * weight * NORMAL_SOFTEN_FACTOR; - LLVector3 tangent = mesh_scaled_binormals[vert_index] % normalized_normal; - LLVector3 normalized_binormal = normalized_normal % tangent; - normalized_binormal.normVec(); + delta_binormals[vert_index].mul(weight * NORMAL_SOFTEN_FACTOR); + mesh_scaled_binormals[vert_index].add(delta_binormals[vert_index]); + + LLVector4a tangent; + tangent.setCross3(mesh_scaled_binormals[vert_index], normalized_normal); + LLVector4a normalized_binormal; + normalized_binormal.setCross3(normalized_normal, tangent); + normalized_binormal.normalize3(); mesh_binormals[vert_index] = normalized_binormal; } @@ -658,9 +667,9 @@ BOOL LLPolyMorphTarget::parseData(LLXmlTreeNode* node) //----------------------------------------------------------------------------- // getVertexDistortion() //----------------------------------------------------------------------------- -LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) +LLVector4a LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh *mesh) { - if (!mMorphData || mMesh != mesh) return LLVector3::zero; + if (!mMorphData || mMesh != mesh) return LLVector4a::getZero(); for(U32 index = 0; index < mMorphData->mNumIndices; index++) { @@ -670,17 +679,17 @@ LLVector3 LLPolyMorphTarget::getVertexDistortion(S32 requested_index, LLPolyMesh } } - return LLVector3::zero; + return LLVector4a::getZero(); } //----------------------------------------------------------------------------- // getFirstDistortion() //----------------------------------------------------------------------------- -const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { - if (!mMorphData) return &LLVector3::zero; + if (!mMorphData) return &LLVector4a::getZero(); - LLVector3* resultVec; + LLVector4a* resultVec; mMorphData->mCurrentIndex = 0; if (mMorphData->mNumIndices) { @@ -702,11 +711,11 @@ const LLVector3 *LLPolyMorphTarget::getFirstDistortion(U32 *index, LLPolyMesh ** //----------------------------------------------------------------------------- // getNextDistortion() //----------------------------------------------------------------------------- -const LLVector3 *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) +const LLVector4a *LLPolyMorphTarget::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { - if (!mMorphData) return &LLVector3::zero; + if (!mMorphData) return &LLVector4a::getZero(); - LLVector3* resultVec; + LLVector4a* resultVec; mMorphData->mCurrentIndex++; if (mMorphData->mCurrentIndex < mMorphData->mNumIndices) { @@ -742,7 +751,7 @@ F32 LLPolyMorphTarget::getTotalDistortion() //----------------------------------------------------------------------------- // getAvgDistortion() //----------------------------------------------------------------------------- -const LLVector3& LLPolyMorphTarget::getAvgDistortion() +const LLVector4a& LLPolyMorphTarget::getAvgDistortion() { if (mMorphData) { @@ -750,7 +759,7 @@ const LLVector3& LLPolyMorphTarget::getAvgDistortion() } else { - return LLVector3::zero; + return LLVector4a::getZero(); } } @@ -799,15 +808,15 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) if (delta_weight != 0.f) { llassert(!mMesh->isLOD()); - LLVector4 *coords = mMesh->getWritableCoords(); + LLVector4a *coords = mMesh->getWritableCoords(); - LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector4 *normals = mMesh->getWritableNormals(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *normals = mMesh->getWritableNormals(); - LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); - LLVector3 *binormals = mMesh->getWritableBinormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *binormals = mMesh->getWritableBinormals(); - LLVector4 *clothing_weights = mMesh->getWritableClothingWeights(); + LLVector4a *clothing_weights = mMesh->getWritableClothingWeights(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); F32 *maskWeightArray = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; @@ -822,31 +831,38 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) maskWeight = maskWeightArray[vert_index_morph]; } - coords[vert_index_mesh] += LLVector4(mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight); + + LLVector4a pos = mMorphData->mCoords[vert_index_morph]; + pos.mul(delta_weight*maskWeight); + coords[vert_index_mesh].add(pos); if (getInfo()->mIsClothingMorph && clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight; - LLVector4* clothing_weight = &clothing_weights[vert_index_mesh]; - clothing_weight->mV[VX] += clothing_offset.mV[VX]; - clothing_weight->mV[VY] += clothing_offset.mV[VY]; - clothing_weight->mV[VZ] += clothing_offset.mV[VZ]; - clothing_weight->mV[VW] = maskWeight; + LLVector4a clothing_offset = mMorphData->mCoords[vert_index_morph]; + clothing_offset.mul(delta_weight * maskWeight); + LLVector4a* clothing_weight = &clothing_weights[vert_index_mesh]; + clothing_weight->add(clothing_offset); + clothing_weight->getF32ptr()[VW] = maskWeight; } // calculate new normals based on half angles - scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; - LLVector3 normalized_normal = scaled_normals[vert_index_mesh]; - normalized_normal.normVec(); - normals[vert_index_mesh] = LLVector4(normalized_normal); + LLVector4a norm = mMorphData->mNormals[vert_index_morph]; + norm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[vert_index_mesh].add(norm); + norm = scaled_normals[vert_index_mesh]; + norm.normalize3fast(); + normals[vert_index_mesh] = norm; // calculate new binormals - scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; - LLVector3 tangent = scaled_binormals[vert_index_mesh] % normalized_normal; - LLVector3 normalized_binormal = normalized_normal % tangent; - normalized_binormal.normVec(); - binormals[vert_index_mesh] = normalized_binormal; - + LLVector4a binorm = mMorphData->mBinormals[vert_index_morph]; + binorm.mul(delta_weight*maskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[vert_index_mesh].add(binorm); + LLVector4a tangent; + tangent.setCross3(scaled_binormals[vert_index_mesh], norm); + LLVector4a& normalized_binormal = binormals[vert_index_mesh]; + normalized_binormal.setCross3(norm, tangent); + normalized_binormal.normalize3fast(); + tex_coords[vert_index_mesh] += mMorphData->mTexCoords[vert_index_morph] * delta_weight * maskWeight; } @@ -873,7 +889,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) //----------------------------------------------------------------------------- void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert) { - LLVector4 *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; if (!mVertMask) { @@ -887,29 +903,47 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 if (maskWeights) { - LLVector4 *coords = mMesh->getWritableCoords(); - LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); + LLVector4a *coords = mMesh->getWritableCoords(); + LLVector4a *scaled_normals = mMesh->getScaledNormals(); + LLVector4a *scaled_binormals = mMesh->getScaledBinormals(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); + LLVector4Logical clothing_mask; + clothing_mask.clear(); + clothing_mask.setElement<0>(); + clothing_mask.setElement<1>(); + clothing_mask.setElement<2>(); + + for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) { F32 lastMaskWeight = mLastWeight * maskWeights[vert]; S32 out_vert = mMorphData->mVertexIndices[vert]; // remove effect of existing masked morph - coords[out_vert] -= LLVector4(mMorphData->mCoords[vert]) * lastMaskWeight; - scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; - scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; + LLVector4a t; + t = mMorphData->mCoords[vert]; + t.mul(lastMaskWeight); + coords[out_vert].sub(t); + + t = mMorphData->mNormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_normals[out_vert].sub(t); + + t = mMorphData->mBinormals[vert]; + t.mul(lastMaskWeight*NORMAL_SOFTEN_FACTOR); + scaled_binormals[out_vert].sub(t); + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; if (clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight; - LLVector4* clothing_weight = &clothing_weights[out_vert]; - clothing_weight->mV[VX] -= clothing_offset.mV[VX]; - clothing_weight->mV[VY] -= clothing_offset.mV[VY]; - clothing_weight->mV[VZ] -= clothing_offset.mV[VZ]; + LLVector4a clothing_offset = mMorphData->mCoords[vert]; + clothing_offset.mul(lastMaskWeight); + LLVector4a* clothing_weight = &clothing_weights[out_vert]; + LLVector4a t; + t.setSub(*clothing_weight, clothing_offset); + clothing_weight->setSelectWithMask(clothing_mask, t, *clothing_weight); } } } @@ -945,7 +979,7 @@ LLPolyVertexMask::~LLPolyVertexMask() //----------------------------------------------------------------------------- // generateMask() //----------------------------------------------------------------------------- -void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights) +void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights) { // RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/) // BOOL debugImg = FALSE; @@ -989,7 +1023,7 @@ void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, if (clothing_weights) { - clothing_weights[vertIndex].mV[VW] = mWeights[index]; + clothing_weights[vertIndex].getF32ptr()[VW] = mWeights[index]; } } mWeightsGenerated = TRUE; diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index be7019fdf..dac698437 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -68,14 +68,14 @@ public: U32 mNumIndices; U32* mVertexIndices; U32 mCurrentIndex; - LLVector3* mCoords; - LLVector3* mNormals; - LLVector3* mBinormals; + LLVector4a* mCoords; + LLVector4a* mNormals; + LLVector4a* mBinormals; LLVector2* mTexCoords; F32 mTotalDistortion; // vertex distortion summed over entire morph F32 mMaxDistortion; // maximum single vertex distortion in a given morph - LLVector3 mAvgDistortion; // average vertex distortion, to infer directionality of the morph + LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph LLPolyMeshSharedData* mMesh; }; @@ -88,7 +88,7 @@ public: LLPolyVertexMask(LLPolyMorphData* morph_data); ~LLPolyVertexMask(); - void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4 *clothing_weights); + void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights); F32* getMorphMaskWeights(); @@ -167,11 +167,11 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); - /*virtual*/ const LLVector3& getAvgDistortion(); + /*virtual*/ const LLVector4a& getAvgDistortion(); /*virtual*/ F32 getMaxDistortion(); - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); void addPendingMorphMask() { mNumMorphMasksPending++; } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 41b3c3f00..a6f6ca8c1 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -2,31 +2,25 @@ * @file llselectmgr.cpp * @brief A manager for selected objects and faces. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * 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$ */ @@ -281,7 +275,7 @@ void LLSelectMgr::overrideObjectUpdates() virtual bool apply(LLSelectNode* selectNode) { LLViewerObject* object = selectNode->getObject(); - if (object && object->permMove()) + if (object && object->permMove() && !object->isPermanentEnforced()) { if (!selectNode->mLastPositionLocal.isExactlyZero()) { @@ -600,6 +594,12 @@ bool LLSelectMgr::linkObjects() return true; } + if (!LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) + { + LLNotificationsUtil::add("CannotLinkPermanent"); + return true; + } + LLUUID owner_id; std::string owner_name; if (!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name)) @@ -645,7 +645,9 @@ bool LLSelectMgr::enableLinkObjects() { virtual bool apply(LLViewerObject* object) { - return object->permModify(); + LLViewerObject *root_object = (object == NULL) ? NULL : object->getRootEdit(); + return object->permModify() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()); } } func; const bool firstonly = true; @@ -668,10 +670,12 @@ bool LLSelectMgr::enableLinkObjects() bool LLSelectMgr::enableUnlinkObjects() { LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject(); + LLViewerObject *root_object = (first_editable_object == NULL) ? NULL : first_editable_object->getRootEdit(); bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() && first_editable_object && - !first_editable_object->isAttachment(); + !first_editable_object->isAttachment() && !first_editable_object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()); // [RLVa:KB] - Checked: 2011-03-19 (RLVa-1.3.0f) | Modified: RLVa-0.2.0g if ( (new_value) && ((rlv_handler_t::isEnabled()) && (!gRlvHandler.canStand())) ) { @@ -981,7 +985,7 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) } if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) - || (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove())) + || (gSavedSettings.getBOOL("SelectMovableOnly") && (!objectp->permMove() || objectp->isPermanentEnforced()))) { // only select my own objects return; @@ -2292,50 +2296,6 @@ void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) gMessageSystem->addString("Parameter", buf); } -//----------------------------------------------------------------------------- -// Rotation options -//----------------------------------------------------------------------------- -void LLSelectMgr::selectionResetRotation() -{ - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLQuaternion identity(0.f, 0.f, 0.f, 1.f); - object->setRotation(identity); - if (object->mDrawable.notNull()) - { - gPipeline.markMoved(object->mDrawable, TRUE); - } - object->sendRotationUpdate(); - return true; - } - } func; - getSelection()->applyToRootObjects(&func); -} - -void LLSelectMgr::selectionRotateAroundZ(F32 degrees) -{ - LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) ); - struct f : public LLSelectedObjectFunctor - { - LLQuaternion mRot; - f(const LLQuaternion& rot) : mRot(rot) {} - virtual bool apply(LLViewerObject* object) - { - object->setRotation( object->getRotationEdit() * mRot ); - if (object->mDrawable.notNull()) - { - gPipeline.markMoved(object->mDrawable, TRUE); - } - object->sendRotationUpdate(); - return true; - } - } func(rot); - getSelection()->applyToRootObjects(&func); -} - - //----------------------------------------------------------------------------- // selectionTexScaleAutofit() //----------------------------------------------------------------------------- @@ -2549,6 +2509,341 @@ BOOL LLSelectMgr::selectGetRootsModify() } +//----------------------------------------------------------------------------- +// selectGetNonPermanentEnforced() - return TRUE if all objects are not +// permanent enforced +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetNonPermanentEnforced() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->isPermanentEnforced()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsNonPermanentEnforced() - return TRUE if all root objects are +// not permanent enforced +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsNonPermanentEnforced() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->isPermanentEnforced()) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetPermanent() - return TRUE if all objects are permanent +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetPermanent() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagObjectPermanent()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsPermanent() - return TRUE if all root objects are +// permanent +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsPermanent() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( !object->flagObjectPermanent()) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetCharacter() - return TRUE if all objects are character +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetCharacter() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsCharacter() - return TRUE if all root objects are +// character +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsCharacter() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter()) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetNonPathfinding() - return TRUE if all objects are not pathfinding +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetNonPathfinding() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent() || object->flagCharacter()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsNonPathfinding() - return TRUE if all root objects are not +// pathfinding +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsNonPathfinding() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent() || object->flagCharacter()) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetNonPermanent() - return TRUE if all objects are not permanent +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetNonPermanent() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsNonPermanent() - return TRUE if all root objects are not +// permanent +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsNonPermanent() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->flagObjectPermanent()) + { + return FALSE; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetNonCharacter() - return TRUE if all objects are not character +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetNonCharacter() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( object->flagCharacter()) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetRootsNonCharacter() - return TRUE if all root objects are not +// character +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetRootsNonCharacter() +{ + for (LLObjectSelection::root_iterator iter = getSelection()->root_begin(); + iter != getSelection()->root_end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !node->mValid ) + { + return FALSE; + } + if( object->flagCharacter()) + { + return FALSE; + } + } + + return TRUE; +} + + +//----------------------------------------------------------------------------- +// selectGetEditableLinksets() - return TRUE if all objects are editable +// pathfinding linksets +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetEditableLinksets() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if (object->flagUsePhysics() || + object->flagTemporaryOnRez() || + object->flagCharacter() || + object->flagVolumeDetect() || + object->flagAnimSource() || + (object->getRegion() != gAgent.getRegion()) || + (!gAgent.isGodlike() && + !gAgent.canManageEstate() && + !object->permYouOwner() && + !object->permMove())) + { + return FALSE; + } + } + return TRUE; +} + +//----------------------------------------------------------------------------- +// selectGetViewableCharacters() - return TRUE if all objects are characters +// viewable within the pathfinding characters floater +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetViewableCharacters() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + if( !object->flagCharacter() || + (object->getRegion() != gAgent.getRegion())) + { + return FALSE; + } + } + return TRUE; +} + + //----------------------------------------------------------------------------- // selectGetRootsTransfer() - return TRUE if current agent can transfer all // selected root objects. @@ -4200,13 +4495,6 @@ void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom) getSelection()->applyToObjects(&func); } -void LLSelectMgr::selectionUpdateCastShadows(BOOL cast_shadows) -{ - LLSelectMgrApplyFlags func( FLAGS_CAST_SHADOWS, cast_shadows); - getSelection()->applyToObjects(&func); -} - - //---------------------------------------------------------------------- // Helpful packing functions for sendObjectMessage() //---------------------------------------------------------------------- @@ -6284,7 +6572,7 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) } if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !object->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && !object->permMove())) + (gSavedSettings.getBOOL("SelectMovableOnly") && (!object->permMove() || object->isPermanentEnforced()))) { // only select my own objects return FALSE; @@ -6978,7 +7266,7 @@ LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root_first) bool apply(LLSelectNode* node) { LLViewerObject* obj = node->getObject(); - return obj && obj->permMove(); + return obj && obj->permMove() && !obj->isPermanentEnforced(); } } func; LLSelectNode* res = get_root_first ? getFirstRootNode(&func, TRUE) : getFirstNode(&func); @@ -7016,9 +7304,10 @@ LLViewerObject* LLObjectSelection::getFirstDeleteableObject() LLViewerObject* obj = node->getObject(); // you can delete an object if you are the owner // or you have permission to modify it. - if( obj && ( (obj->permModify()) || - (obj->permYouOwner()) || - (!obj->permAnyOwner()) )) // public + if( obj && !obj->isPermanentEnforced() && + ( (obj->permModify()) || + (obj->permYouOwner()) || + (!obj->permAnyOwner()) )) // public { if( !obj->isAttachment() ) { @@ -7058,7 +7347,7 @@ LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_parent) bool apply(LLSelectNode* node) { LLViewerObject* obj = node->getObject(); - return obj && obj->permMove(); + return obj && obj->permMove() && !obj->isPermanentEnforced(); } } func; return getFirstSelectedObject(&func, get_parent); @@ -7127,7 +7416,7 @@ bool LLSelectMgr::selectionMove(const LLVector3& displ, { obj = (*it)->getObject(); bool enable_pos = false, enable_rot = false; - bool perm_move = obj->permMove(); + bool perm_move = obj->permMove() && !obj->isPermanentEnforced(); bool perm_mod = obj->permModify(); LLVector3d sel_center(getSelectionCenterGlobal()); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 9961710d5..f3c52dbfe 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -505,7 +505,6 @@ public: void selectionUpdatePhysics(BOOL use_physics); void selectionUpdateTemporary(BOOL is_temporary); void selectionUpdatePhantom(BOOL is_ghost); - void selectionUpdateCastShadows(BOOL cast_shadows); void selectionDump(); BOOL selectionAllPCode(LLPCode code); // all objects have this PCode @@ -543,8 +542,6 @@ public: void selectionTexScaleAutofit(F32 repeats_per_meter); void adjustTexturesByScale(BOOL send_to_sim, BOOL stretch); - void selectionResetRotation(); // sets rotation quat to identity - void selectionRotateAroundZ(F32 degrees); bool selectionMove(const LLVector3& displ, F32 rx, F32 ry, F32 rz, U32 update_type); void sendSelectionMove(); @@ -567,6 +564,33 @@ public: BOOL selectGetRootsModify(); BOOL selectGetModify(); + // returns TRUE if is all objects are non-permanent-enforced + BOOL selectGetRootsNonPermanentEnforced(); + BOOL selectGetNonPermanentEnforced(); + + // returns TRUE if is all objects are permanent + BOOL selectGetRootsPermanent(); + BOOL selectGetPermanent(); + + // returns TRUE if is all objects are character + BOOL selectGetRootsCharacter(); + BOOL selectGetCharacter(); + + // returns TRUE if is all objects are not permanent + BOOL selectGetRootsNonPathfinding(); + BOOL selectGetNonPathfinding(); + + // returns TRUE if is all objects are not permanent + BOOL selectGetRootsNonPermanent(); + BOOL selectGetNonPermanent(); + + // returns TRUE if is all objects are not character + BOOL selectGetRootsNonCharacter(); + BOOL selectGetNonCharacter(); + + BOOL selectGetEditableLinksets(); + BOOL selectGetViewableCharacters(); + // returns TRUE if selected objects can be transferred. BOOL selectGetRootsTransfer(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 2d476dfbb..20c390931 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -424,7 +424,7 @@ void LLSpatialGroup::validate() validateDrawMap(); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; sg_assert(drawable->getSpatialGroup() == this); @@ -640,7 +640,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma { const OctreeNode* node = mOctreeNode; - if (node->getData().empty()) + if (node->isEmpty()) { //don't do anything if there are no objects if (empty && mOctreeNode->getParent()) { //only root is allowed to be empty @@ -657,14 +657,14 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& ma clearState(OBJECT_DIRTY); //initialize bounding box to first element - OctreeNode::const_element_iter i = node->getData().begin(); + OctreeNode::const_element_iter i = node->getDataBegin(); LLDrawable* drawablep = *i; const LLVector4a* minMax = drawablep->getSpatialExtents(); newMin = minMax[0]; newMax = minMax[1]; - for (++i; i != node->getData().end(); ++i) + for (++i; i != node->getDataEnd(); ++i) { drawablep = *i; minMax = drawablep->getSpatialExtents(); @@ -805,7 +805,7 @@ void LLSpatialGroup::shift(const LLVector4a &offset) mObjectExtents[0].add(offset); mObjectExtents[1].add(offset); - //if (!mSpatialPartition->mRenderByGroup) + if (!mSpatialPartition->mRenderByGroup) { setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); @@ -1124,7 +1124,7 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) llerrs << "Spatial group dirty on distance update." << llendl; } #endif - if (!getData().empty() /*&& !LLSpatialPartition::sFreezeState*/) + if (!isEmpty() /*&& !LLSpatialPartition::sFreezeState*/) { mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : (F32) mOctreeNode->getSize().getLength3().getF32(); @@ -1276,7 +1276,7 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); setState(DEAD); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; if (drawable->getSpatialGroup() == this) @@ -1363,7 +1363,7 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) } - for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) + for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; for (S32 j = 0; j < drawable->getNumFaces(); j++) @@ -1720,12 +1720,14 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - drawablep->setSpatialGroup(NULL); - if (!curp->removeObject(drawablep)) { OCT_ERRS << "Failed to remove drawable from octree!" << llendl; } + else + { + drawablep->setSpatialGroup(NULL); + } assert_octree_valid(mOctree); @@ -1996,7 +1998,7 @@ public: virtual void processGroup(LLSpatialGroup* group) { - llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty()) + llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->isEmpty()) if (mRes < 2) { @@ -2063,7 +2065,7 @@ public: { LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -2187,7 +2189,7 @@ public: LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup) @@ -2500,7 +2502,7 @@ void renderOctree(LLSpatialGroup* group) gGL.flush(); glLineWidth(1.f); gGL.flush(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; if (!group->mSpatialPartition->isBridge()) @@ -2546,7 +2548,7 @@ void renderOctree(LLSpatialGroup* group) } else { - if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty() + if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() && group->mSpatialPartition->mRenderByGroup) { col.setVec(0.8f, 0.4f, 0.1f, 0.1f); @@ -2614,7 +2616,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->getData().empty(); + !group->isEmpty(); if (render_objects) { @@ -3356,7 +3358,7 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) void renderPhysicsShapes(LLSpatialGroup* group) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; LLVOVolume* volume = drawable->getVOVolume(); @@ -3601,7 +3603,7 @@ public: LLVector3 center, size; - if (branch->getData().empty()) + if (branch->isEmpty()) { gGL.diffuseColor3f(1.f,0.2f,0.f); center.set(branch->getCenter().getF32ptr()); @@ -3637,8 +3639,8 @@ public: } gGL.begin(LLRender::TRIANGLES); - for (LLOctreeNode::const_element_iter iter = branch->getData().begin(); - iter != branch->getData().end(); + for (LLOctreeNode::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); ++iter) { const LLVolumeTriangle* tri = *iter; @@ -3875,7 +3877,7 @@ public: if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { - if (!group->getData().empty()) + if (!group->isEmpty()) { gGL.diffuseColor3f(0,0,1); drawBoxOutline(group->mObjectBounds[0], @@ -3883,7 +3885,7 @@ public: } } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4068,7 +4070,7 @@ public: return; } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { LLDrawable* drawable = *i; @@ -4291,7 +4293,7 @@ public: virtual void visit(const LLSpatialGroup::OctreeNode* branch) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { check(*i); } @@ -4476,29 +4478,64 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) } LLCullResult::LLCullResult() -{ +{ + mVisibleGroupsAllocated = 0; + mAlphaGroupsAllocated = 0; + mOcclusionGroupsAllocated = 0; + mDrawableGroupsAllocated = 0; + mVisibleListAllocated = 0; + mVisibleBridgeAllocated = 0; + + mVisibleGroups = NULL; + mVisibleGroupsEnd = NULL; + mAlphaGroups = NULL; + mAlphaGroupsEnd = NULL; + mOcclusionGroups = NULL; + mOcclusionGroupsEnd = NULL; + mDrawableGroups = NULL; + mDrawableGroupsEnd = NULL; + mVisibleList = NULL; + mVisibleListEnd = NULL; + mVisibleBridge = NULL; + mVisibleBridgeEnd = NULL; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i] = NULL; + mRenderMapEnd[i] = NULL; + mRenderMapAllocated[i] = 0; + } + clear(); } +void LLCullResult::pushBack(void**& head, U32& count, void* val) +{ + count++; + head = (void**) realloc((void*) head, sizeof(void*) * count); + head[count-1] = val; +} + void LLCullResult::clear() { mVisibleGroupsSize = 0; - mVisibleGroupsEnd = mVisibleGroups.begin(); + mVisibleGroupsEnd = mVisibleGroups; mAlphaGroupsSize = 0; - mAlphaGroupsEnd = mAlphaGroups.begin(); + mAlphaGroupsEnd = mAlphaGroups; mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = mOcclusionGroups.begin(); + mOcclusionGroupsEnd = mOcclusionGroups; mDrawableGroupsSize = 0; - mDrawableGroupsEnd = mDrawableGroups.begin(); + mDrawableGroupsEnd = mDrawableGroups; mVisibleListSize = 0; - mVisibleListEnd = mVisibleList.begin(); + mVisibleListEnd = mVisibleList; mVisibleBridgeSize = 0; - mVisibleBridgeEnd = mVisibleBridge.begin(); + mVisibleBridgeEnd = mVisibleBridge; + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) { @@ -4507,176 +4544,176 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; - mRenderMapEnd[i] = mRenderMap[i].begin(); + mRenderMapEnd[i] = mRenderMap[i]; } } -LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() +LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() { - return mVisibleGroups.begin(); + return mVisibleGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() +LLCullResult::sg_iterator LLCullResult::endVisibleGroups() { return mVisibleGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() +LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() { - return mAlphaGroups.begin(); + return mAlphaGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() +LLCullResult::sg_iterator LLCullResult::endAlphaGroups() { return mAlphaGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { - return mOcclusionGroups.begin(); + return mOcclusionGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() { return mOcclusionGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() +LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() { - return mDrawableGroups.begin(); + return mDrawableGroups; } -LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() +LLCullResult::sg_iterator LLCullResult::endDrawableGroups() { return mDrawableGroupsEnd; } -LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() +LLCullResult::drawable_iterator LLCullResult::beginVisibleList() { - return mVisibleList.begin(); + return mVisibleList; } -LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() +LLCullResult::drawable_iterator LLCullResult::endVisibleList() { return mVisibleListEnd; } -LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() { - return mVisibleBridge.begin(); + return mVisibleBridge; } -LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() { return mVisibleBridgeEnd; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) { - return mRenderMap[type].begin(); + return mRenderMap[type]; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) { return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) { - if (mVisibleGroupsSize < mVisibleGroups.size()) + if (mVisibleGroupsSize < mVisibleGroupsAllocated) { mVisibleGroups[mVisibleGroupsSize] = group; } else { - mVisibleGroups.push_back(group); + pushBack((void**&) mVisibleGroups, mVisibleGroupsAllocated, (void*) group); } ++mVisibleGroupsSize; - mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; + mVisibleGroupsEnd = mVisibleGroups+mVisibleGroupsSize; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) { - if (mAlphaGroupsSize < mAlphaGroups.size()) + if (mAlphaGroupsSize < mAlphaGroupsAllocated) { mAlphaGroups[mAlphaGroupsSize] = group; } else { - mAlphaGroups.push_back(group); + pushBack((void**&) mAlphaGroups, mAlphaGroupsAllocated, (void*) group); } ++mAlphaGroupsSize; - mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; + mAlphaGroupsEnd = mAlphaGroups+mAlphaGroupsSize; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { - if (mOcclusionGroupsSize < mOcclusionGroups.size()) + if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) { mOcclusionGroups[mOcclusionGroupsSize] = group; } else { - mOcclusionGroups.push_back(group); + pushBack((void**&) mOcclusionGroups, mOcclusionGroupsAllocated, (void*) group); } ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; + mOcclusionGroupsEnd = mOcclusionGroups+mOcclusionGroupsSize; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) { - if (mDrawableGroupsSize < mDrawableGroups.size()) + if (mDrawableGroupsSize < mDrawableGroupsAllocated) { mDrawableGroups[mDrawableGroupsSize] = group; } else { - mDrawableGroups.push_back(group); + pushBack((void**&) mDrawableGroups, mDrawableGroupsAllocated, (void*) group); } ++mDrawableGroupsSize; - mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; + mDrawableGroupsEnd = mDrawableGroups+mDrawableGroupsSize; } void LLCullResult::pushDrawable(LLDrawable* drawable) { - if (mVisibleListSize < mVisibleList.size()) + if (mVisibleListSize < mVisibleListAllocated) { mVisibleList[mVisibleListSize] = drawable; } else { - mVisibleList.push_back(drawable); + pushBack((void**&) mVisibleList, mVisibleListAllocated, (void*) drawable); } ++mVisibleListSize; - mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; + mVisibleListEnd = mVisibleList+mVisibleListSize; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) { - if (mVisibleBridgeSize < mVisibleBridge.size()) + if (mVisibleBridgeSize < mVisibleBridgeAllocated) { mVisibleBridge[mVisibleBridgeSize] = bridge; } else { - mVisibleBridge.push_back(bridge); + pushBack((void**&) mVisibleBridge, mVisibleBridgeAllocated, (void*) bridge); } ++mVisibleBridgeSize; - mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize; + mVisibleBridgeEnd = mVisibleBridge+mVisibleBridgeSize; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) { - if (mRenderMapSize[type] < mRenderMap[type].size()) + if (mRenderMapSize[type] < mRenderMapAllocated[type]) { mRenderMap[type][mRenderMapSize[type]] = draw_info; } else { - mRenderMap[type].push_back(draw_info); + pushBack((void**&) mRenderMap[type], mRenderMapAllocated[type], (void*) draw_info); } ++mRenderMapSize[type]; - mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type]; + mRenderMapEnd[type] = mRenderMap[type] + mRenderMapSize[type]; } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 95ba1c036..890a52f0d 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -330,8 +330,13 @@ public: void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } + + //octree wrappers to make code more readable element_list& getData() { return mOctreeNode->getData(); } + element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } + element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } + bool isEmpty() const { return mOctreeNode->isEmpty(); } void drawObjectBox(LLColor4 col); @@ -522,34 +527,39 @@ class LLCullResult public: LLCullResult(); - typedef std::vector sg_list_t; - typedef std::vector drawable_list_t; - typedef std::vector bridge_list_t; - typedef std::vector drawinfo_list_t; + typedef LLSpatialGroup** sg_list_t; + typedef LLDrawable** drawable_list_t; + typedef LLSpatialBridge** bridge_list_t; + typedef LLDrawInfo** drawinfo_list_t; + + typedef LLSpatialGroup** sg_iterator; + typedef LLSpatialBridge** bridge_iterator; + typedef LLDrawInfo** drawinfo_iterator; + typedef LLDrawable** drawable_iterator; void clear(); - sg_list_t::iterator beginVisibleGroups(); - sg_list_t::iterator endVisibleGroups(); + sg_iterator beginVisibleGroups(); + sg_iterator endVisibleGroups(); - sg_list_t::iterator beginAlphaGroups(); - sg_list_t::iterator endAlphaGroups(); + sg_iterator beginAlphaGroups(); + sg_iterator endAlphaGroups(); bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } - sg_list_t::iterator beginOcclusionGroups(); - sg_list_t::iterator endOcclusionGroups(); + sg_iterator beginOcclusionGroups(); + sg_iterator endOcclusionGroups(); - sg_list_t::iterator beginDrawableGroups(); - sg_list_t::iterator endDrawableGroups(); + sg_iterator beginDrawableGroups(); + sg_iterator endDrawableGroups(); - drawable_list_t::iterator beginVisibleList(); - drawable_list_t::iterator endVisibleList(); + drawable_iterator beginVisibleList(); + drawable_iterator endVisibleList(); - bridge_list_t::iterator beginVisibleBridge(); - bridge_list_t::iterator endVisibleBridge(); + bridge_iterator beginVisibleBridge(); + bridge_iterator endVisibleBridge(); - drawinfo_list_t::iterator beginRenderMap(U32 type); - drawinfo_list_t::iterator endRenderMap(U32 type); + drawinfo_iterator beginRenderMap(U32 type); + drawinfo_iterator endRenderMap(U32 type); void pushVisibleGroup(LLSpatialGroup* group); void pushAlphaGroup(LLSpatialGroup* group); @@ -569,28 +579,41 @@ public: void assertDrawMapsEmpty(); private: + + void pushBack(void** &head, U32& count, void* val); + U32 mVisibleGroupsSize; U32 mAlphaGroupsSize; U32 mOcclusionGroupsSize; U32 mDrawableGroupsSize; U32 mVisibleListSize; U32 mVisibleBridgeSize; + + U32 mVisibleGroupsAllocated; + U32 mAlphaGroupsAllocated; + U32 mOcclusionGroupsAllocated; + U32 mDrawableGroupsAllocated; + U32 mVisibleListAllocated; + U32 mVisibleBridgeAllocated; + U32 mRenderMapSize[LLRenderPass::NUM_RENDER_TYPES]; sg_list_t mVisibleGroups; - sg_list_t::iterator mVisibleGroupsEnd; + sg_iterator mVisibleGroupsEnd; sg_list_t mAlphaGroups; - sg_list_t::iterator mAlphaGroupsEnd; + sg_iterator mAlphaGroupsEnd; sg_list_t mOcclusionGroups; - sg_list_t::iterator mOcclusionGroupsEnd; + sg_iterator mOcclusionGroupsEnd; sg_list_t mDrawableGroups; - sg_list_t::iterator mDrawableGroupsEnd; + sg_iterator mDrawableGroupsEnd; drawable_list_t mVisibleList; - drawable_list_t::iterator mVisibleListEnd; + drawable_iterator mVisibleListEnd; bridge_list_t mVisibleBridge; - bridge_list_t::iterator mVisibleBridgeEnd; + bridge_iterator mVisibleBridgeEnd; drawinfo_list_t mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; - drawinfo_list_t::iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; + U32 mRenderMapAllocated[LLRenderPass::NUM_RENDER_TYPES]; + drawinfo_iterator mRenderMapEnd[LLRenderPass::NUM_RENDER_TYPES]; + }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 26773586c..596d8d154 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -200,7 +200,6 @@ #include "llnamelistctrl.h" #include "llnamebox.h" #include "llnameeditor.h" -#include "llpostprocess.h" #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llagentlanguage.h" @@ -221,6 +220,8 @@ #include "shfloatermediaticker.h" // +#include "llpathfindingmanager.h" + #include "llavatarnamecache.h" #include "lgghunspell_wrapper.h" @@ -1094,12 +1095,14 @@ bool idle_startup() // END TODO LLPanelLogin::close(); } - + //For HTML parsing in text boxes. LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") ); // Load URL History File LLURLHistory::loadFile("url_history.xml"); + // Load media plugin cookies + LLViewerMedia::loadCookieFile(); //------------------------------------------------- // Handle startup progress screen @@ -2740,6 +2743,10 @@ bool idle_startup() // reset timers now that we are running "logged in" logic LLFastTimer::reset(); display_startup(); + + llassert(LLPathfindingManager::getInstance() != NULL); + LLPathfindingManager::getInstance()->initSystem(); + return TRUE; } @@ -4304,7 +4311,6 @@ bool process_login_success_response(std::string& password) #endif } - // Override grid info with anything sent in the login response std::string tmp = response["gridname"].asString(); if (!tmp.empty()) gHippoGridManager->getConnectedGrid()->setGridName(tmp); @@ -4349,6 +4355,14 @@ bool process_login_success_response(std::string& password) gHippoGridManager->saveFile(); gHippoLimits->setLimits(); + // Start the process of fetching the OpenID session cookie for this user login + std::string openid_url = response["openid_url"]; + if(!openid_url.empty()) + { + std::string openid_token = response["openid_token"]; + LLViewerMedia::openIDSetup(openid_url, openid_token); + } + gIMMgr->loadIgnoreGroup(); bool success = false; diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h index 74c22b0cd..2c0da60b4 100644 --- a/indra/newview/lltexlayerparams.h +++ b/indra/newview/lltexlayerparams.h @@ -76,11 +76,11 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f);} - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f);} + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions BOOL render( S32 x, S32 y, S32 width, S32 height ); @@ -94,7 +94,7 @@ private: LLPointer mStaticImageRaw; BOOL mNeedsCreateTexture; BOOL mStaticImageInvalid; - LLVector3 mAvgDistortionVec; + LLVector4a mAvgDistortionVec; F32 mCachedEffectiveWeight; public: @@ -155,18 +155,18 @@ public: // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion() { return 1.f; } - /*virtual*/ const LLVector3& getAvgDistortion() { return mAvgDistortionVec; } + /*virtual*/ const LLVector4a& getAvgDistortion() { return mAvgDistortionVec; } /*virtual*/ F32 getMaxDistortion() { return 3.f; } - /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector3(1.f, 1.f, 1.f); } - /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; - /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; + /*virtual*/ LLVector4a getVertexDistortion(S32 index, LLPolyMesh *poly_mesh) { return LLVector4a(1.f, 1.f, 1.f); } + /*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return &mAvgDistortionVec;}; + /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh) { index = 0; poly_mesh = NULL; return NULL;}; // New functions LLColor4 getNetColor() const; protected: virtual void onGlobalColorChanged(bool upload_bake) {} private: - LLVector3 mAvgDistortionVec; + LLVector4a mAvgDistortionVec; }; class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index 08a1b26ef..f668f5bfc 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -161,6 +161,13 @@ BOOL LLToolBar::postBuild() childSetAction("inventory_btn", onClickInventory, this); childSetControlName("inventory_btn", "ShowInventory"); + mCommunicateBtn.connect(this, "communicate_btn"); + mFlyBtn.connect(this, "fly_btn"); + mBuildBtn.connect(this, "build_btn"); + mMapBtn.connect(this, "map_btn"); + mRadarBtn.connect(this, "radar_btn"); + mInventoryBtn.connect(this, "inventory_button"); + for (child_list_const_iter_t child_iter = getChildList()->begin(); child_iter != getChildList()->end(); ++child_iter) { @@ -292,7 +299,9 @@ void LLToolBar::refresh() if(!isAgentAvatarValid()) return; - BOOL show = gSavedSettings.getBOOL("ShowToolBar"); + static LLCachedControl show("ShowToolBar", true); + static LLCachedControl ascent_fly_always_enabled("AscentFlyAlwaysEnabled", true); + static LLCachedControl ascent_build_always_enabled("AscentBuildAlwaysEnabled", true); BOOL mouselook = gAgentCamera.cameraMouselook(); setVisible(show && !mouselook); @@ -302,9 +311,8 @@ void LLToolBar::refresh() sitting = gAgentAvatarp->isSitting(); } - childSetEnabled("fly_btn", (gAgent.canFly() || gAgent.getFlying() || gSavedSettings.getBOOL("AscentFlyAlwaysEnabled")) && !sitting ); - - childSetEnabled("build_btn", (LLViewerParcelMgr::getInstance()->allowAgentBuild() || gSavedSettings.getBOOL("AscentBuildAlwaysEnabled")) ); + mFlyBtn->setEnabled((gAgent.canFly() || gAgent.getFlying() || ascent_fly_always_enabled) && !sitting ); + mBuildBtn->setEnabled((LLViewerParcelMgr::getInstance()->allowAgentBuild() || ascent_build_always_enabled)); // Check to see if we're in build mode BOOL build_mode = LLToolMgr::getInstance()->inEdit(); @@ -323,11 +331,11 @@ void LLToolBar::refresh() { // If we're rez-restricted, we can still edit => allow build floater // If we're edit-restricted, we can still rez => allow build floater - childSetEnabled("build_btn", !(gRlvHandler.hasBehaviour(RLV_BHVR_REZ) && gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ); + mBuildBtn->setEnabled(!(gRlvHandler.hasBehaviour(RLV_BHVR_REZ) && gRlvHandler.hasBehaviour(RLV_BHVR_EDIT))); - childSetEnabled("map_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWWORLDMAP) ); - childSetEnabled("radar_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWMINIMAP) ); - childSetEnabled("inventory_btn", !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV) ); + mMapBtn->setEnabled(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWWORLDMAP)); + mRadarBtn->setEnabled(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWMINIMAP)); + mInventoryBtn->setEnabled(!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWINV)); } // [/RLVa:KB] @@ -339,7 +347,7 @@ void LLToolBar::refresh() void LLToolBar::updateCommunicateList() { - LLFlyoutButton* communicate_button = getChild("communicate_btn"); + LLFlyoutButton* communicate_button = mCommunicateBtn; LLSD selected = communicate_button->getValue(); communicate_button->removeall(); diff --git a/indra/newview/lltoolbar.h b/indra/newview/lltoolbar.h index 197d16dd3..24b05c8ae 100644 --- a/indra/newview/lltoolbar.h +++ b/indra/newview/lltoolbar.h @@ -44,6 +44,8 @@ extern S32 TOOL_BAR_HEIGHT; class LLFakeResizeHandle; #endif // LL_DARWIN +class LLFlyoutButton; + class LLToolBar : public LLPanel { @@ -97,6 +99,13 @@ private: #if LL_DARWIN LLFakeResizeHandle *mResizeHandle; #endif // LL_DARWIN + + CachedUICtrl mCommunicateBtn; + CachedUICtrl mFlyBtn; + CachedUICtrl mBuildBtn; + CachedUICtrl mMapBtn; + CachedUICtrl mRadarBtn; + CachedUICtrl mInventoryBtn; }; extern LLToolBar *gToolBar; diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp index 32aa96c65..0bde80872 100644 --- a/indra/newview/lltoolgrab.cpp +++ b/indra/newview/lltoolgrab.cpp @@ -214,28 +214,41 @@ BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) // Clicks on scripted or physical objects are temporary grabs, so // not "Build mode" - mHideBuildHighlight = script_touch || objectp->usePhysics(); + mHideBuildHighlight = script_touch || objectp->flagUsePhysics(); - if (!objectp->usePhysics()) + if (!objectp->flagUsePhysics()) { - // In mouselook, we shouldn't be able to grab non-physical, - // non-touchable objects. If it has a touch handler, we - // do grab it (so llDetectedGrab works), but movement is - // blocked on the server side. JC - if (gAgentCamera.cameraMouselook() && !script_touch) + if (script_touch) { - mMode = GRAB_LOCKED; - gViewerWindow->hideCursor(); - gViewerWindow->moveCursorToCenter(); + mMode = GRAB_NONPHYSICAL; // if it has a script, use the non-physical grab } else { - mMode = GRAB_NONPHYSICAL; + // In mouselook, we shouldn't be able to grab non-physical, + // non-touchable objects. If it has a touch handler, we + // do grab it (so llDetectedGrab works), but movement is + // blocked on the server side. JC + if (gAgentCamera.cameraMouselook()) + { + mMode = GRAB_LOCKED; + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); + } + else if (objectp->permMove() && !objectp->isPermanentEnforced()) + { + mMode = GRAB_ACTIVE_CENTER; + gViewerWindow->hideCursor(); + gViewerWindow->moveCursorToCenter(); + } + else + { + mMode = GRAB_LOCKED; + } + + } - // Don't bail out here, go on and grab so buttons can get - // their "touched" event. } - else if( !objectp->permMove() ) + else if( objectp->flagCharacter() || !objectp->permMove() || objectp->isPermanentEnforced()) { // if mouse is over a physical object without move permission, show feedback if user tries to move it. mMode = GRAB_LOCKED; diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index f2a9a7138..0dc00f826 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -276,7 +276,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) // Switch to grab tool if physical or triggerable if (object && !object->isAvatar() && - ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) && + ((object->flagUsePhysics() || (parent && !parent->isAvatar() && parent->flagUsePhysics())) || touchable) && !always_show) { // [RLVa:KB] - Checked: 2010-01-02 (RLVa-1.1.0l) | Modified: RLVa-1.1.0l @@ -704,8 +704,8 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); } // [/RLVa:KB] - else if ((object && !object->isAvatar() && object->usePhysics()) - || (parent && !parent->isAvatar() && parent->usePhysics())) + else if ((object && !object->isAvatar() && object->flagUsePhysics()) + || (parent && !parent->isAvatar() && parent->flagUsePhysics())) { gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLGRAB); } @@ -928,7 +928,7 @@ static bool handle_media_click(const LLPickInfo& pick) } else { - media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY); + media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY, gKeyboard->currentMask(TRUE)); media_impl->mouseCapture(); // the mouse-up will happen when capture is lost } @@ -974,7 +974,7 @@ static bool handle_media_hover(const LLPickInfo& pick) { if(LLViewerMediaFocus::getInstance()->getFocus()) { - media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY); + media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY, gKeyboard->currentMask(TRUE)); } // Set mouse over flag if unset diff --git a/indra/newview/llurl.cpp b/indra/newview/llurl.cpp index ab65ead4c..83a5839a9 100644 --- a/indra/newview/llurl.cpp +++ b/indra/newview/llurl.cpp @@ -286,5 +286,11 @@ const char * LLURL::getFullPath() return(sReturnString); } +const char * LLURL::getAuthority() +{ + strncpy(LLURL::sReturnString,mAuthority, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLURL::sReturnString[LL_MAX_PATH -1] = '\0'; + return(sReturnString); +} char LLURL::sReturnString[LL_MAX_PATH] = ""; diff --git a/indra/newview/llurl.h b/indra/newview/llurl.h index 9a089dd83..e41b83d29 100644 --- a/indra/newview/llurl.h +++ b/indra/newview/llurl.h @@ -79,6 +79,7 @@ public: virtual const char *getFQURL() const; virtual const char *getFullPath(); + virtual const char *getAuthority(); virtual const char *updateRelativePath(const LLURL &url); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 64f0b24ba..291d3a3fe 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1009,7 +1009,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.flush(); - if(LLRenderTarget::sUseFBO) + if(gPipeline.mDeferredScreen.getFBO()) { LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), 0, 0, @@ -1021,7 +1021,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo else { gPipeline.mScreen.flush(); - if(LLRenderTarget::sUseFBO) + if(gPipeline.mScreen.getFBO()) { LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(), 0, 0, @@ -1283,14 +1283,12 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) if (to_texture) { gPipeline.renderBloom(gSnapshot, zoom_factor, subfield, tiling); - gPipeline.mScreen.flush(); //blit, etc. } - /// We copy the frame buffer straight into a texture here, - /// and then display it again with compositor effects. - /// Using render to texture would be faster/better, but I don't have a - /// grasp of their full display stack just yet. + if(gPipeline.canUseVertexShaders()) - LLPostProcess::getInstance()->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); + { + LLPostProcess::getInstance()->renderEffects(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()); + } render_hud_elements(); render_hud_attachments(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 56f0403e9..5b13d747b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -33,21 +33,31 @@ #include "llviewerprecompiledheaders.h" #include "llviewermedia.h" -#include "llviewermediafocus.h" -#include "llhoverview.h" -#include "llmimetypes.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llviewertexturelist.h" -//#include "viewerversion.h" -#include "llpluginclassmedia.h" - -#include "llnotifications.h" +#include "llappviewer.h" +#include "lldir.h" +#include "lldiriterator.h" #include "llevent.h" // LLSimpleListener -#include "llnotificationsutil.h" -#include "lluuid.h" +#include "llhoverview.h" #include "llkeyboard.h" +#include "llmimetypes.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpluginclassmedia.h" +#include "llplugincookiestore.h" +#include "llurldispatcher.h" +#include "lluuid.h" +#include "llviewermediafocus.h" +#include "llviewercontrol.h" +#include "llviewertexture.h" +#include "llviewertexturelist.h" +#include "llviewerwindow.h" +#include "llwindow.h" +#include "llvieweraudio.h" +#include "llweb.h" + +#include "llfloateravatarinfo.h" // for getProfileURL() function +//#include "viewerversion.h" // Merov: Temporary definitions while porting the new viewer media code to Snowglobe const int LEFT_BUTTON = 0; @@ -75,11 +85,6 @@ public: completeAny(status, mime_type); } - virtual void error( U32 status, const std::string& reason ) - { - // completeAny(status, "none/none"); - } - void completeAny(U32 status, const std::string& mime_type) { if(!mInitialized && ! mime_type.empty()) @@ -96,8 +101,83 @@ public: viewer_media_t mMediaImpl; bool mInitialized; }; + +class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder +{ +LOG_CLASS(LLViewerMediaOpenIDResponder); +public: + LLViewerMediaOpenIDResponder( ) + { + } + + ~LLViewerMediaOpenIDResponder() + { + } + + /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; + LL_DEBUGS("MediaAuth") << content << LL_ENDL; + std::string cookie = content["set-cookie"].asString(); + + LLViewerMedia::openIDCookieResponse(cookie); + } + + /* virtual */ void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + // This is just here to disable the default behavior (attempting to parse the response as llsd). + // We don't care about the content of the response, only the set-cookie header. + } + +}; + +class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder +{ +LOG_CLASS(LLViewerMediaWebProfileResponder); +public: + LLViewerMediaWebProfileResponder(std::string host) + { + mHost = host; + } + + ~LLViewerMediaWebProfileResponder() + { + } + + /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + LL_WARNS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL; + LL_WARNS("MediaAuth") << content << LL_ENDL; + + std::string cookie = content["set-cookie"].asString(); + + LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost); + } + + void completedRaw( + U32 status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + // This is just here to disable the default behavior (attempting to parse the response as llsd). + // We don't care about the content of the response, only the set-cookie header. + } + + std::string mHost; +}; + +LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; +LLURL LLViewerMedia::sOpenIDURL; +std::string LLViewerMedia::sOpenIDCookie; typedef std::list impl_list; static impl_list sViewerMediaImplList; +static std::string sUpdatedCookies; +static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt"; ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMedia @@ -105,10 +185,12 @@ static impl_list sViewerMediaImplList; ////////////////////////////////////////////////////////////////////////////////////////// // static viewer_media_t LLViewerMedia::newMediaImpl(const std::string& media_url, - const LLUUID& texture_id, - S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop, - std::string mime_type) + const LLUUID& texture_id, + S32 media_width, + S32 media_height, + U8 media_auto_scale, + U8 media_loop, + std::string mime_type) { LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id); if(media_impl == NULL || texture_id.isNull()) @@ -255,7 +337,8 @@ void LLViewerMedia::setVolume(F32 volume) for(; iter != end; iter++) { LLViewerMediaImpl* pimpl = *iter; - pimpl->setVolume(volume); + LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); + plugin->setVolume(volume); } } @@ -263,6 +346,13 @@ void LLViewerMedia::setVolume(F32 volume) // static void LLViewerMedia::updateMedia() { + sUpdatedCookies = getCookieStore()->getChangedCookies(); + if(!sUpdatedCookies.empty()) + { + lldebugs << "updated cookies will be sent to all loaded plugins: " << llendl; + lldebugs << sUpdatedCookies << llendl; + } + impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); @@ -273,6 +363,349 @@ void LLViewerMedia::updateMedia() } } +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::clearAllCookies() +{ + // Clear all cookies for all plugins + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + for (; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); + if(plugin) + { + plugin->clear_cookies(); + } + } + + // Clear all cookies from the cookie store + getCookieStore()->setAllCookies(""); + + // FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly. + // It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded. + // Until such time as we can centralize cookie storage, the following hack should cover these cases: + + // HACK: Look for cookie files in all possible places and delete them. + // NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file) + + // Places that cookie files can be: + // /browser_profile/cookies + // /first_last/browser_profile/cookies (note that there may be any number of these!) + // /first_last/plugin_cookies.txt (note that there may be any number of these!) + + std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter(); + std::string target; + std::string filename; + + lldebugs << "base dir = " << base_dir << llendl; + + // The non-logged-in version is easy + target = base_dir; + target += "browser_profile"; + target += gDirUtilp->getDirDelimiter(); + target += "cookies"; + lldebugs << "target = " << target << llendl; + if(LLFile::isfile(target)) + { + LLFile::remove(target); + } + + // the hard part: iterate over all user directories and delete the cookie file from each one + LLDirIterator dir_iter(base_dir, "*_*"); + while (dir_iter.next(filename)) + { + target = base_dir; + target += filename; + target += gDirUtilp->getDirDelimiter(); + target += "browser_profile"; + target += gDirUtilp->getDirDelimiter(); + target += "cookies"; + lldebugs << "target = " << target << llendl; + if(LLFile::isfile(target)) + { + LLFile::remove(target); + } + + // Other accounts may have new-style cookie files too -- delete them as well + target = base_dir; + target += filename; + target += gDirUtilp->getDirDelimiter(); + target += PLUGIN_COOKIE_FILE_NAME; + lldebugs << "target = " << target << llendl; + if(LLFile::isfile(target)) + { + LLFile::remove(target); + } + } + + // If we have an OpenID cookie, re-add it to the cookie store. + setOpenIDCookie(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::clearAllCaches() +{ + // Clear all plugins' caches + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + for (; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + pimpl->clearCache(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::setCookiesEnabled(bool enabled) +{ + // Set the "cookies enabled" flag for all loaded plugins + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + for (; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); + if(plugin) + { + plugin->enable_cookies(enabled); + } + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +///////////////////////////////////////////////////////////////////////////////////////// +// static +LLPluginCookieStore *LLViewerMedia::getCookieStore() +{ + if(sCookieStore == NULL) + { + sCookieStore = new LLPluginCookieStore; + } + + return sCookieStore; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::loadCookieFile() +{ + // build filename for each user + std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME); + + if (resolved_filename.empty()) + { + llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl; + return; + } + + // open the file for reading + llifstream file(resolved_filename); + if (!file.is_open()) + { + llwarns << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << llendl; + return; + } + + getCookieStore()->readAllCookies(file, true); + + file.close(); + + // send the clear_cookies message to all loaded plugins + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + for (; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); + if(plugin) + { + plugin->clear_cookies(); + } + } + + // If we have an OpenID cookie, re-add it to the cookie store. + setOpenIDCookie(); +} + + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::saveCookieFile() +{ + // build filename for each user + std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME); + + if (resolved_filename.empty()) + { + llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl; + return; + } + + // open a file for writing + llofstream file (resolved_filename); + if (!file.is_open()) + { + llwarns << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << llendl; + return; + } + + getCookieStore()->writePersistentCookies(file); + + file.close(); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure) +{ + std::stringstream cookie; + + cookie << name << "=" << LLPluginCookieStore::quoteString(value); + + if(expires.notNull()) + { + cookie << "; expires=" << expires.asRFC1123(); + } + + cookie << "; domain=" << domain; + + cookie << "; path=" << path; + + if(secure) + { + cookie << "; secure"; + } + + getCookieStore()->setCookies(cookie.str()); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure) +{ + // A session cookie just has a NULL date. + addCookie(name, value, domain, LLDate(), path, secure); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path ) +{ + // To remove a cookie, add one with the same name, domain, and path that expires in the past. + + addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path); +} + + +LLSD LLViewerMedia::getHeaders() +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Content-Type"] = "application/xml"; + headers["Cookie"] = sOpenIDCookie; + headers["User-Agent"] = getCurrentUserAgent(); + + return headers; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::setOpenIDCookie() +{ + if(!sOpenIDCookie.empty()) + { + // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] + // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. + // We therefore do it here. + std::string authority = sOpenIDURL.mAuthority; + std::string::size_type host_start = authority.find('@'); + if(host_start == std::string::npos) + { + // no username/password + host_start = 0; + } + else + { + // Hostname starts after the @. + // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) + ++host_start; + } + std::string::size_type host_end = authority.rfind(':'); + if((host_end == std::string::npos) || (host_end < host_start)) + { + // no port + host_end = authority.size(); + } + + getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); + + // Do a web profile get so we can store the cookie + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Cookie"] = sOpenIDCookie; + headers["User-Agent"] = getCurrentUserAgent(); + + std::string profile_url = getProfileURL(""); + LLURL raw_profile_url( profile_url.c_str() ); + + LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << llendl; + LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << llendl; + LLHTTPClient::get(profile_url, + new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), + headers); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token) +{ + LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; + + // post the token to the url + // the responder will need to extract the cookie(s). + + // Save the OpenID URL for later -- we may need the host when adding the cookie. + sOpenIDURL.init(openid_url.c_str()); + + // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. + sOpenIDCookie.clear(); + + LLSD headers = LLSD::emptyMap(); + // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header + headers["Accept"] = "*/*"; + // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream" + headers["Content-Type"] = "application/x-www-form-urlencoded"; + + // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here. + size_t size = openid_token.size(); + U8 *data = new U8[size]; + memcpy(data, openid_token.data(), size); + + LLHTTPClient::postRaw( + openid_url, + data, + size, + new LLViewerMediaOpenIDResponder(), + headers); + +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::openIDCookieResponse(const std::string &cookie) +{ + LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL; + + sOpenIDCookie += cookie; + + setOpenIDCookie(); +} ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::cleanupClass() @@ -309,7 +742,10 @@ LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, mTextureUsedWidth(0), mTextureUsedHeight(0), mSuspendUpdates(false), - mVisible(true) + mVisible(true), + mHasFocus(false), + mClearCache(false), + mBackgroundColor(LLColor4::white) { createMediaSource(); } @@ -379,10 +815,10 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height) { std::string plugin_basename = LLMIMETypes::implType(media_type); - + if(plugin_basename.empty()) { - LL_WARNS("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; + LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL; } else { @@ -391,16 +827,29 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string user_data_path = gDirUtilp->getOSUserAppDir(); user_data_path += gDirUtilp->getDirDelimiter(); + // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) + // If the linden username returned is blank, that can only mean we are + // at the login page displaying login Web page or Web browser test via Develop menu. + // In this case we just use whatever gDirUtilp->getOSUserAppDir() gives us (this + // is what we always used before this change) + std::string linden_user_dir = gDirUtilp->getLindenUserDir(true); + if ( ! linden_user_dir.empty() ) + { + // gDirUtilp->getLindenUserDir() is whole path, not just Linden name + user_data_path = linden_user_dir; + user_data_path += gDirUtilp->getDirDelimiter(); + }; + // See if the plugin executable exists llstat s; if(LLFile::stat(launcher_name, &s)) { - LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL; + LL_WARNS_ONCE("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL; llassert(false); // Fail in debugging mode. } else if(LLFile::stat(plugin_name, &s)) { - LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; + LL_WARNS_ONCE("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; llassert(false); // Fail in debugging mode. } else @@ -421,7 +870,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); media_source->setJavascriptEnabled( javascript_enabled ); - + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); @@ -463,7 +912,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // and unconditionally set the mime type mMimeType = media_type; - LLPluginClassMedia* media_source = newSourceFromMediaType(media_type, this, mMediaWidth, mMediaHeight); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight); if (media_source) { @@ -471,6 +920,8 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) media_source->setLoop(mMediaLoop); media_source->setAutoScale(mMediaAutoScale); media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); + media_source->focus(mHasFocus); + media_source->setBackgroundColor(mBackgroundColor); if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors")) { @@ -484,6 +935,23 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" ); media_source->addCertificateFilePath( ca_path ); + if(mClearCache) + { + mClearCache = false; + media_source->clear_cache(); + } + + // TODO: Only send cookies to plugins that need them + // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message. + // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message, + // which could cause odd race conditions. + std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies(); + lldebugs << "setting cookies: " << all_cookies << llendl; + if(!all_cookies.empty()) + { + media_source->set_cookies(all_cookies); + } + mPluginBase = media_source; return true; @@ -585,6 +1053,8 @@ void LLViewerMediaImpl::setVolume(F32 volume) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::focus(bool focus) { + mHasFocus = focus; + LLPluginClassMedia* plugin = getMediaPlugin(); if (plugin) { @@ -601,20 +1071,27 @@ void LLViewerMediaImpl::focus(bool focus) } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::mouseDown(S32 x, S32 y) +bool LLViewerMediaImpl::hasFocus() const +{ + // FIXME: This might be able to be a bit smarter by hooking into LLViewerMediaFocus, etc. + return mHasFocus; +} + +void LLViewerMediaImpl::clearCache() { LLPluginClassMedia* plugin = getMediaPlugin(); - scaleMouse(&x, &y); - mLastMouseX = x; - mLastMouseY = y; - if (plugin) + if(plugin) { - plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); + plugin->clear_cache(); + } + else + { + mClearCache = true; } } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::mouseUp(S32 x, S32 y) +void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button) { LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); @@ -622,12 +1099,12 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y) mLastMouseY = y; if (plugin) { - plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask); } } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::mouseMove(S32 x, S32 y) +void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button) { LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); @@ -635,12 +1112,12 @@ void LLViewerMediaImpl::mouseMove(S32 x, S32 y) mLastMouseY = y; if (plugin) { - plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask); } } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) +void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask) { LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); @@ -648,7 +1125,96 @@ void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) mLastMouseY = y; if (plugin) { - plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask); + } +} + + +////////////////////////////////////////////////////////////////////////////////////////// +//static +void LLViewerMediaImpl::scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y) +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + F32 texture_x = texture_coords.mV[VX]; + F32 texture_y = texture_coords.mV[VY]; + + // Deal with repeating textures by wrapping the coordinates into the range [0, 1.0) + texture_x = fmodf(texture_x, 1.0f); + if(texture_x < 0.0f) + texture_x = 1.0 + texture_x; + + texture_y = fmodf(texture_y, 1.0f); + if(texture_y < 0.0f) + texture_y = 1.0 + texture_y; + + // scale x and y to texel units. + *x = llround(texture_x * plugin->getTextureWidth()); + *y = llround((1.0f - texture_y) * plugin->getTextureHeight()); + + // Adjust for the difference between the actual texture height and the amount of the texture in use. + *y -= (plugin->getTextureHeight() - plugin->getHeight()); +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button) +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + if(plugin) + { + S32 x, y; + scaleTextureCoords(texture_coords, &x, &y); + + mouseDown(x, y, mask, button); + } +} + +void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button) +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + if(plugin) + { + S32 x, y; + scaleTextureCoords(texture_coords, &x, &y); + + mouseUp(x, y, mask, button); + } +} + +void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask) +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + if(plugin) + { + S32 x, y; + scaleTextureCoords(texture_coords, &x, &y); + + mouseMove(x, y, mask); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button) +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (plugin) + { + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask) +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + scaleMouse(&x, &y); + mLastMouseX = x; + mLastMouseY = y; + if (plugin) + { + plugin->scrollEvent(x, y, mask); } } @@ -658,7 +1224,7 @@ void LLViewerMediaImpl::onMouseCaptureLost() LLPluginClassMedia* plugin = getMediaPlugin(); if (plugin) { - plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0); } } @@ -676,6 +1242,18 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) return TRUE; } + +////////////////////////////////////////////////////////////////////////////////////////// +const std::string& LLViewerMediaImpl::getName() const +{ + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + { + return plugin->getMediaName(); + } + + return LLStringUtil::null; +}; ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateHome() { @@ -787,7 +1365,7 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if(!result) { - LLSD native_key_data = LLSD::emptyMap(); + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); result = plugin->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. @@ -810,7 +1388,7 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) if (uni_char >= 32 // discard 'control' characters && uni_char != 127) // SDL thinks this is 'delete' - yuck. { - LLSD native_key_data = LLSD::emptyMap(); + LLSD native_key_data = gViewerWindow->getWindow()->getNativeKeyData(); plugin->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); } @@ -883,6 +1461,17 @@ void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) void LLViewerMediaImpl::update() { LLPluginClassMedia* plugin = getMediaPlugin(); + + if(plugin) + { + // If we didn't just create the impl, it may need to get cookie updates. + if(!sUpdatedCookies.empty()) + { + // TODO: Only send cookies to plugins that need them + plugin->set_cookies(sUpdatedCookies); + } + } + if (!plugin) { return; @@ -962,21 +1551,21 @@ void LLViewerMediaImpl::updateImagesMediaStreams() } LLViewerMediaTexture* placeholder_image = (LLViewerMediaTexture*)LLViewerTextureManager::getFetchedTexture( mTextureId ); - LLPluginClassMedia* plugin = getMediaPlugin(); - placeholder_image->getLastReferencedTimer()->reset(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (mNeedsNewTexture || placeholder_image->getUseMipMaps() - || ! placeholder_image->mIsMediaTexture + || !placeholder_image->mIsMediaTexture || (placeholder_image->getWidth() != plugin->getTextureWidth()) || (placeholder_image->getHeight() != plugin->getTextureHeight()) || (mTextureUsedWidth != plugin->getWidth()) || (mTextureUsedHeight != plugin->getHeight()) ) { - llinfos << "initializing media placeholder" << llendl; - llinfos << "movie image id " << mTextureId << llendl; + LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; + LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; int texture_width = plugin->getTextureWidth(); int texture_height = plugin->getTextureHeight(); @@ -990,7 +1579,9 @@ void LLViewerMediaImpl::updateImagesMediaStreams() // MEDIAOPT: seems insane that we actually have to make an imageraw then // immediately discard it LLPointer raw = new LLImageRaw(texture_width, texture_height, texture_depth); - raw->clear(0x0f, 0x0f, 0x0f, 0xff); + // Clear the texture to the background color, ignoring alpha. + // convert background color channels from [0.0, 1.0] to [0, 255]; + raw->clear(int(mBackgroundColor.mV[VX] * 255.0f), int(mBackgroundColor.mV[VY] * 255.0f), int(mBackgroundColor.mV[VZ] * 255.0f), 0xff); int discard_level = 0; // ask media source for correct GL image format constants @@ -1154,6 +1745,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClass // Just chain the event to observers. emitEvent(self, event); } +//////////////////////////////////////////////////////////////////////////////// +// virtual +void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie) +{ + LLViewerMedia::getCookieStore()->setCookies(cookie); +} //////////////////////////////////////////////////////////////////////////////// // virtual @@ -1221,3 +1818,13 @@ LLViewerMediaImpl::canPaste() const return FALSE; } +void LLViewerMediaImpl::setBackgroundColor(LLColor4 color) +{ + mBackgroundColor = color; + + LLPluginClassMedia* plugin = getMediaPlugin(); + if(plugin) + { + plugin->setBackgroundColor(mBackgroundColor); + } +}; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index aebfbec76..f33b3f13a 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -33,15 +33,19 @@ #ifndef LLVIEWERMEDIA_H #define LLVIEWERMEDIA_H -#include "llviewermediaeventemitter.h" -#include "llviewerpluginmanager.h" #include "llfocusmgr.h" #include "llpanel.h" +#include "llviewermediaeventemitter.h" +#include "llviewerpluginmanager.h" +#include "llpluginclassmedia.h" +#include "v4color.h" +#include "llurl.h" class LLViewerMediaImpl; class LLUUID; class LLSD; class LLViewerTexture; +class LLPluginCookieStore; typedef LLPointer viewer_media_t; @@ -72,6 +76,33 @@ class LLViewerMedia static void cleanupClass(); + // Clear all cookies for all plugins + static void clearAllCookies(); + + // Clear all plugins' caches + static void clearAllCaches(); + + // Set the "cookies enabled" flag for all loaded plugins + static void setCookiesEnabled(bool enabled); + + static LLPluginCookieStore *getCookieStore(); + static void loadCookieFile(); + static void saveCookieFile(); + static void addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path = std::string("/"), bool secure = false ); + static void addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path = std::string("/"), bool secure = false ); + static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") ); + + static void openIDSetup(const std::string &openid_url, const std::string &openid_token); + static void openIDCookieResponse(const std::string &cookie); + + static LLSD getHeaders(); + +private: + static void setOpenIDCookie(); + + static LLPluginCookieStore *sCookieStore; + static LLURL sOpenIDURL; + static std::string sOpenIDCookie; }; // Implementation functions not exported into header file @@ -81,6 +112,8 @@ class LLViewerMediaImpl LOG_CLASS(LLViewerMediaImpl); public: + friend class LLViewerMedia; + LLViewerMediaImpl(const std::string& media_url, const LLUUID& texture_id, S32 media_width, @@ -98,9 +131,6 @@ public: LLPluginClassMedia* getMediaPlugin() const { return (LLPluginClassMedia*)mPluginBase; } void setSize(int width, int height); - // Inherited from LLViewerPluginManager. - /*virtual*/ void update(); - void play(); void stop(); void pause(); @@ -108,10 +138,16 @@ public: void seek(F32 time); void setVolume(F32 volume); void focus(bool focus); - void mouseDown(S32 x, S32 y); - void mouseUp(S32 x, S32 y); - void mouseMove(S32 x, S32 y); - void mouseLeftDoubleClick(S32 x,S32 y ); + // True if the impl has user focus. + bool hasFocus() const; + void mouseDown(S32 x, S32 y, MASK mask, S32 button = 0); + void mouseUp(S32 x, S32 y, MASK mask, S32 button = 0); + void mouseMove(S32 x, S32 y, MASK mask); + void mouseDown(const LLVector2& texture_coords, MASK mask, S32 button = 0); + void mouseUp(const LLVector2& texture_coords, MASK mask, S32 button = 0); + void mouseMove(const LLVector2& texture_coords, MASK mask); + void mouseDoubleClick(S32 x,S32 y, MASK mask, S32 button = 0); + void scrollWheel(S32 x, S32 y, MASK mask); void mouseCapture(); void navigateHome(); @@ -124,11 +160,14 @@ public: std::string getMediaURL() { return mMediaURL; } std::string getHomeURL() { return mHomeURL; } void setHomeURL(const std::string& home_url) { mHomeURL = home_url; } + void clearCache(); std::string getMimeType() { return mMimeType; } void getTextureSize(S32 *texture_width, S32 *texture_height); void scaleMouse(S32 *mouse_x, S32 *mouse_y); + void scaleTextureCoords(const LLVector2& texture_coords, S32 *x, S32 *y); void updateMovieImage(const LLUUID& image_id, BOOL active); + void update(); void updateImagesMediaStreams(); LLUUID getMediaTextureID(); @@ -166,7 +205,7 @@ public: /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; }; /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; }; - /*virtual*/ const std::string& getName() const { return LLStringUtil::null; }; + /*virtual*/ const std::string& getName() const; /*virtual*/ BOOL isView() const { return FALSE; }; /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}; /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}; @@ -174,6 +213,7 @@ public: // Inherited from LLPluginClassMediaOwner /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent); + /*virtual*/ void handleCookieSet(LLPluginClassMedia* self, const std::string &cookie); // LLEditMenuHandler overrides /*virtual*/ void cut(); @@ -184,8 +224,10 @@ public: /*virtual*/ void paste(); /*virtual*/ BOOL canPaste() const; - -public: + + bool mNeedsNewTexture; + void setBackgroundColor(LLColor4 color); +private: // a single media url with some data and an impl. LLUUID mTextureId; bool mMovieImageHasMips; @@ -198,11 +240,13 @@ public: S32 mMediaHeight; bool mMediaAutoScale; bool mMediaLoop; - bool mNeedsNewTexture; S32 mTextureUsedWidth; S32 mTextureUsedHeight; bool mSuspendUpdates; bool mVisible; + bool mHasFocus; + bool mClearCache; + LLColor4 mBackgroundColor; private: /*LLViewerMediaTexture*/LLViewerTexture *updatePlaceholderImage(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c359a356d..5a40a767d 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -143,6 +143,7 @@ #include "llfloaterperms.h" #include "llfloaterpostprocess.h" #include "llfloaterpreference.h" +#include "llfloaterregiondebugconsole.h" #include "llfloaterregioninfo.h" #include "llfloaterreporter.h" #include "llfloaterscriptdebug.h" @@ -258,6 +259,7 @@ #include "slfloatermediafilter.h" #include "llviewerobjectbackup.h" #include "llagentui.h" +#include "llpathfindingmanager.h" #include "hippogridmanager.h" @@ -372,7 +374,6 @@ void near_sit_object(); BOOL is_selection_buy_not_take(); S32 selection_price(); BOOL enable_take(); -void handle_take(); bool confirm_take(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle selection_handle); void handle_buy_object(LLSaleInfo sale_info); @@ -417,6 +418,21 @@ void handle_god_mode(void*); // God menu void handle_leave_god_mode(void*); +//Generic handler for singleton-based floaters. +template +BOOL handle_singleton_check(void *) +{ + return T::instanceExists(); +} +template +void handle_singleton_toggle(void *) +{ + if(!T::instanceExists()) + T::getInstance(); + else + T::getInstance()->close(); +} + // void handle_fake_away_status(void*); void handle_area_search(void*); @@ -546,7 +562,6 @@ BOOL get_visibility(void*); void request_friendship(const LLUUID& agent_id); // Tools menu -void handle_force_unlock(void*); void handle_selected_texture_info(void*); void handle_dump_image_list(void*); @@ -809,7 +824,7 @@ void init_menus() menu->addChild(new LLMenuItemCallGL( "Asset Blacklist", &handle_blacklist, NULL)); menu->addChild(new LLMenuItemCheckGL( "Streaming Audio Display", - &handle_ticker_toggle, &handle_ticker_enabled, &handle_ticker_check, NULL )); + &handle_ticker_toggle, &handle_ticker_enabled, &handle_singleton_check, NULL )); @@ -1280,6 +1295,7 @@ void init_debug_ui_menu(LLMenuGL* menu) (void*)"DoubleClickTeleport")); menu->addSeparator(); // menu->addChild(new LLMenuItemCallGL( "Print Packets Lost", &print_packets_lost, NULL, NULL, 'L', MASK_SHIFT )); + menu->addChild(new LLMenuItemCheckGL("Region Debug", handle_singleton_toggle, NULL, handle_singleton_check,NULL,'`', MASK_CONTROL|MASK_SHIFT)); menu->addChild(new LLMenuItemCheckGL("Debug SelectMgr", menu_toggle_control, NULL, menu_check_control, (void*)"DebugSelectMgr")); menu->addChild(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks)); menu->addChild(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects)); @@ -2718,6 +2734,16 @@ class LLObjectMeasure : public view_listener_t } }; +bool enable_object_select_in_pathfinding_linksets() +{ + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetEditableLinksets(); +} + +bool enable_object_select_in_pathfinding_characters() +{ + return LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLSelectMgr::getInstance()->selectGetViewableCharacters(); +} + class LLAvatarAnims : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -4494,8 +4520,9 @@ static bool get_derezzable_objects( { case DRD_TAKE_INTO_AGENT_INVENTORY: case DRD_TRASH: - if( (node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) - || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)) ) + if (!object->isPermanentEnforced() && + ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) + || (node->allowOperationOnNode(PERM_OWNER, GP_OBJECT_MANIPULATE)))) { can_derez_current = TRUE; } @@ -4915,9 +4942,10 @@ BOOL enable_take() return TRUE; } # endif - if((node->mPermissions->allowTransferTo(gAgent.getID()) + if(!object->isPermanentEnforced() && + ((node->mPermissions->allowTransferTo(gAgent.getID()) && object->permModify()) - || (node->mPermissions->getOwner() == gAgent.getID())) + || (node->mPermissions->getOwner() == gAgent.getID()))) { return TRUE; } @@ -5161,6 +5189,7 @@ class LLToolsSaveToInventory : public view_listener_t return true; } }; + class LLToolsSaveToObjectInventory : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -5175,6 +5204,22 @@ class LLToolsSaveToObjectInventory : public view_listener_t } }; +class LLToolsEnablePathfinding : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion(); + } +}; + +class LLToolsEnablePathfindingView : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + return (LLPathfindingManager::getInstance() != NULL) && LLPathfindingManager::getInstance()->isPathfindingEnabledForCurrentRegion() && LLPathfindingManager::getInstance()->isPathfindingViewEnabled(); + } +}; + // Round the position of all root objects to the grid class LLToolsSnapObjectXY : public view_listener_t { @@ -6306,30 +6351,6 @@ void dump_inventory(void*) gInventory.dumpInventory(); } -// forcibly unlock an object -void handle_force_unlock(void*) -{ - // First, make it public. - LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null, TRUE); - - // Second, lie to the viewer and mark it editable and unowned - - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - object->mFlags |= FLAGS_OBJECT_MOVE; - object->mFlags |= FLAGS_OBJECT_MODIFY; - object->mFlags |= FLAGS_OBJECT_COPY; - - object->mFlags &= ~FLAGS_OBJECT_ANY_OWNER; - object->mFlags &= ~FLAGS_OBJECT_YOU_OWNER; - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func); -} - void handle_dump_followcam(void*) { LLFollowCamMgr::dump(); @@ -7290,6 +7311,7 @@ BOOL object_selected_and_point_valid(void *user_data) return (selection->getRootObjectCount() == 1) && (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && selection->getFirstRootObject()->permYouOwner() && + !selection->getFirstRootObject()->flagObjectPermanent() && !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL); } @@ -7965,8 +7987,8 @@ BOOL enable_save_into_inventory(void*) return TRUE; } } -#endif return FALSE; +#endif } BOOL enable_save_into_task_inventory(void*) @@ -9372,6 +9394,9 @@ void initialize_menus() addMenu(new LLToolsEnableTakeCopy(), "Tools.EnableTakeCopy"); addMenu(new LLToolsEnableSaveToObjectInventory(), "Tools.SaveToObjectInventory"); + addMenu(new LLToolsEnablePathfinding(), "Tools.EnablePathfinding"); + addMenu(new LLToolsEnablePathfindingView(), "Tools.EnablePathfindingView"); + /*addMenu(new LLToolsVisibleBuyObject(), "Tools.VisibleBuyObject"); addMenu(new LLToolsVisibleTakeObject(), "Tools.VisibleTakeObject");*/ diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index afe003e0a..e88a43b3a 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5284,7 +5284,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) LLViewerObject* object = gObjectList.findObject(object_id); if (object) { - object->mFlags |= FLAGS_ANIM_SOURCE; + object->setFlagsWithoutUpdate(FLAGS_ANIM_SOURCE, TRUE); BOOL anim_found = FALSE; LLVOAvatar::AnimSourceIterator anim_it = avatarp->mAnimationSources.find(object_id); @@ -5431,7 +5431,7 @@ void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_dat LLViewerObject* objectp = gObjectList.findObject(source_id); if (objectp) { - objectp->mFlags |= FLAGS_CAMERA_SOURCE; + objectp->setFlagsWithoutUpdate(FLAGS_CAMERA_SOURCE, TRUE); } S32 num_objects = mesgsys->getNumberOfBlocks("CameraProperty"); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index c4692f38c..73392750a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -205,6 +205,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mID(id), mLocalID(0), mTotalCRC(0), + mListIndex(-1), mTEImages(NULL), mGLName(0), mbCanSelect(TRUE), @@ -457,7 +458,7 @@ void LLViewerObject::dump() const /* llinfos << "Velocity: " << getVelocity() << llendl; llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl; - llinfos << "UsePhysics: " << usePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl; + llinfos << "UsePhysics: " << flagUsePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl; llinfos << "AppAngle: " << mAppAngle << llendl; llinfos << "PixelArea: " << mPixelArea << llendl; @@ -2065,6 +2066,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // // + // If we're going to skip this message, why are we + // doing all the parenting, etc above? U32 packet_id = mesgsys->getCurrentRecvPacketID(); if (packet_id < mLatestRecvPacketID && mLatestRecvPacketID - packet_id < 65536) @@ -2125,12 +2128,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } } - if (new_rot != mLastRot + if (new_rot != getRotation() || new_angv != old_angv) { - if (new_rot != mLastRot) + if (new_rot != getRotation()) { - mLastRot = new_rot; setRotation(new_rot); } @@ -2232,8 +2234,9 @@ BOOL LLViewerObject::isActive() const BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - static LLFastTimer::DeclareTimer ftm("Viewer Object"); - LLFastTimer t(ftm); + //static LLFastTimer::DeclareTimer ftm("Viewer Object"); + //LLFastTimer t(ftm); + if (mDead) { // It's dead. Don't update it. @@ -4151,38 +4154,6 @@ void LLViewerObject::sendMaterialUpdate() const } -// formerly send_object_rotation -void LLViewerObject::sendRotationUpdate() const -{ - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - gMessageSystem->newMessageFast(_PREHASH_ObjectRotation); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID); - gMessageSystem->addQuatFast(_PREHASH_Rotation, getRotationEdit()); - //llinfos << "Sent rotation " << getRotationEdit() << llendl; - gMessageSystem->sendReliable( regionp->getHost() ); -} - -/* Obsolete, we use MultipleObjectUpdate instead -//// formerly send_object_position_global -//void LLViewerObject::sendPositionUpdate() const -//{ -// gMessageSystem->newMessageFast(_PREHASH_ObjectPosition); -// gMessageSystem->nextBlockFast(_PREHASH_AgentData); -// gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); -// gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -// gMessageSystem->nextBlockFast(_PREHASH_ObjectData); -// gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); -// gMessageSystem->addVector3Fast(_PREHASH_Position, getPositionRegion()); -// LLViewerRegion* regionp = getRegion(); -// gMessageSystem->sendReliable(regionp->getHost()); -//} -*/ - //formerly send_object_shape(LLViewerObject *object) void LLViewerObject::sendShapeUpdate() { @@ -5267,7 +5238,7 @@ BOOL LLViewerObject::permAnyOwner() const { if (isRootEdit()) { - return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0); + return flagObjectAnyOwner(); } else { @@ -5289,7 +5260,7 @@ BOOL LLViewerObject::permYouOwner() const return TRUE; } # endif - return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0); + return flagObjectYouOwner(); #endif } else @@ -5303,7 +5274,7 @@ BOOL LLViewerObject::permGroupOwner() const { if (isRootEdit()) { - return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0); + return flagObjectGroupOwned(); } else { @@ -5326,7 +5297,7 @@ BOOL LLViewerObject::permOwnerModify() const return TRUE; } # endif - return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0); + return flagObjectOwnerModify(); #endif } else @@ -5350,7 +5321,7 @@ BOOL LLViewerObject::permModify() const return TRUE; } # endif - return ((mFlags & FLAGS_OBJECT_MODIFY) != 0); + return flagObjectModify(); #endif } else @@ -5374,7 +5345,7 @@ BOOL LLViewerObject::permCopy() const return TRUE; } # endif - return ((mFlags & FLAGS_OBJECT_COPY) != 0); + return flagObjectCopy(); #endif } else @@ -5398,7 +5369,7 @@ BOOL LLViewerObject::permMove() const return TRUE; } # endif - return ((mFlags & FLAGS_OBJECT_MOVE) != 0); + return flagObjectMove(); #endif } else @@ -5422,7 +5393,7 @@ BOOL LLViewerObject::permTransfer() const return TRUE; } # endif - return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); + return flagObjectTransfer(); #endif } else @@ -5468,21 +5439,19 @@ void LLViewerObject::markForUpdate(BOOL priority) } } +bool LLViewerObject::isPermanentEnforced() const +{ + return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike(); +} + bool LLViewerObject::getIncludeInSearch() const { - return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0); + return flagIncludeInSearch(); } void LLViewerObject::setIncludeInSearch(bool include_in_search) { - if (include_in_search) - { - mFlags |= FLAGS_INCLUDE_IN_SEARCH; - } - else - { - mFlags &= ~FLAGS_INCLUDE_IN_SEARCH; - } + setFlags(FLAGS_INCLUDE_IN_SEARCH, include_in_search); } void LLViewerObject::setRegion(LLViewerRegion *regionp) @@ -5507,8 +5476,8 @@ void LLViewerObject::setRegion(LLViewerRegion *regionp) bool LLViewerObject::specialHoverCursor() const { - return (mFlags & FLAGS_USE_PHYSICS) - || (mFlags & FLAGS_HANDLE_TOUCH) + return flagUsePhysics() + || flagHandleTouch() || (mClickAction != 0); } @@ -5521,10 +5490,15 @@ void LLViewerObject::updateFlags(BOOL physics_changed) gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, getLocalID() ); - gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, usePhysics() ); + gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, flagUsePhysics() ); gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() ); gMessageSystem->addBOOL("IsPhantom", flagPhantom() ); - gMessageSystem->addBOOL("CastsShadows", flagCastShadows() ); + + // stinson 02/28/2012 : This CastsShadows BOOL is no longer used in either the viewer or the simulator + // The simulator code does not even unpack this value when the message is received. + // This could be potentially hijacked in the future for another use should the urgent need arise. + gMessageSystem->addBOOL("CastsShadows", FALSE ); + if (physics_changed) { gMessageSystem->nextBlock("ExtraPhysics"); @@ -5538,6 +5512,19 @@ void LLViewerObject::updateFlags(BOOL physics_changed) } BOOL LLViewerObject::setFlags(U32 flags, BOOL state) +{ + BOOL setit = setFlagsWithoutUpdate(flags, state); + + // BUG: Sometimes viewer physics and simulator physics get + // out of sync. To fix this, always send update to simulator. +// if (setit) + { + updateFlags(); + } + return setit; +} + +BOOL LLViewerObject::setFlagsWithoutUpdate(U32 flags, BOOL state) { BOOL setit = FALSE; if (state) @@ -5556,13 +5543,6 @@ BOOL LLViewerObject::setFlags(U32 flags, BOOL state) setit = TRUE; } } - - // BUG: Sometimes viewer physics and simulator physics get - // out of sync. To fix this, always send update to simulator. -// if (setit) - { - updateFlags(); - } return setit; } diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 403b27490..ac3b6ba28 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -233,6 +233,8 @@ public: const LLUUID &getID() const { return mID; } U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mTotalCRC; } + S32 getListIndex() const { return mListIndex; } + void setListIndex(S32 idx) { mListIndex = idx; } virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } @@ -314,7 +316,6 @@ public: inline void setRotation(const F32 x, const F32 y, const F32 z, BOOL damped = FALSE); inline void setRotation(const LLQuaternion& quat, BOOL damped = FALSE); - void sendRotationUpdate() const; /*virtual*/ void setNumTEs(const U8 num_tes); /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); @@ -483,26 +484,38 @@ public: BOOL permCopy() const; BOOL permMove() const; BOOL permTransfer() const; - inline BOOL usePhysics() const { return ((mFlags & FLAGS_USE_PHYSICS) != 0); } + inline BOOL flagUsePhysics() const { return ((mFlags & FLAGS_USE_PHYSICS) != 0); } + inline BOOL flagObjectAnyOwner() const { return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0); } + inline BOOL flagObjectYouOwner() const { return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0); } + inline BOOL flagObjectGroupOwned() const { return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0); } + inline BOOL flagObjectOwnerModify() const { return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0); } + inline BOOL flagObjectModify() const { return ((mFlags & FLAGS_OBJECT_MODIFY) != 0); } + inline BOOL flagObjectCopy() const { return ((mFlags & FLAGS_OBJECT_COPY) != 0); } + inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } + inline BOOL flagObjectTransfer() const { return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); } + inline BOOL flagObjectPermanent() const { return ((mFlags & FLAGS_AFFECTS_NAVMESH) != 0); } + inline BOOL flagCharacter() const { return ((mFlags & FLAGS_CHARACTER) != 0); } + inline BOOL flagVolumeDetect() const { return ((mFlags & FLAGS_VOLUME_DETECT) != 0); } + inline BOOL flagIncludeInSearch() const { return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0); } inline BOOL flagScripted() const { return ((mFlags & FLAGS_SCRIPTED) != 0); } inline BOOL flagHandleTouch() const { return ((mFlags & FLAGS_HANDLE_TOUCH) != 0); } inline BOOL flagTakesMoney() const { return ((mFlags & FLAGS_TAKES_MONEY) != 0); } inline BOOL flagPhantom() const { return ((mFlags & FLAGS_PHANTOM) != 0); } inline BOOL flagInventoryEmpty() const { return ((mFlags & FLAGS_INVENTORY_EMPTY) != 0); } - inline BOOL flagCastShadows() const { return ((mFlags & FLAGS_CAST_SHADOWS) != 0); } inline BOOL flagAllowInventoryAdd() const { return ((mFlags & FLAGS_ALLOW_INVENTORY_DROP) != 0); } inline BOOL flagTemporary() const { return ((mFlags & FLAGS_TEMPORARY) != 0); } inline BOOL flagTemporaryOnRez() const { return ((mFlags & FLAGS_TEMPORARY_ON_REZ) != 0); } inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); } inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); } inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); } - inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } U8 getPhysicsShapeType() const; inline F32 getPhysicsGravity() const { return mPhysicsGravity; } inline F32 getPhysicsFriction() const { return mPhysicsFriction; } inline F32 getPhysicsDensity() const { return mPhysicsDensity; } inline F32 getPhysicsRestitution() const { return mPhysicsRestitution; } + + bool isPermanentEnforced() const; bool getIncludeInSearch() const; void setIncludeInSearch(bool include_in_search); @@ -519,6 +532,7 @@ public: void updateFlags(BOOL physics_changed = FALSE); BOOL setFlags(U32 flag, BOOL state); + BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); void setPhysicsShapeType(U8 type); void setPhysicsGravity(F32 gravity); void setPhysicsFriction(F32 friction); @@ -604,15 +618,20 @@ public: // Last total CRC received from sim, used for caching U32 mTotalCRC; + // index into LLViewerObjectList::mActiveObjects or -1 if not in list + S32 mListIndex; + LLPointer *mTEImages; // Selection, picking and rendering variables U32 mGLName; // GL "name" used by selection code BOOL mbCanSelect; // true if user can select this object by clicking +private: // Grabbed from UPDATE_FLAGS U32 mFlags; +public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; F32 mPhysicsGravity; @@ -690,6 +709,7 @@ protected: F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation F64 mLastMessageUpdateSecs; // Last update from a message from the simulator TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator + // extra data sent from the sim...currently only used for tree species info U8* mData; public://Jay: IDGAF @@ -731,7 +751,6 @@ protected: F32 mTimeDilation; // Time dilation sent with the object. F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) - LLQuaternion mLastRot; // last rotation received from the simulator LLVOJointInfo* mJointInfo; U8 mState; // legacy diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index 9b0100f6e..138916f79 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -650,9 +650,9 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list, bool i prim_llsd["scale"] = object->getScale().getValue(); // Flags - prim_llsd["shadows"] = object->flagCastShadows(); + prim_llsd["shadows"] = FALSE; prim_llsd["phantom"] = object->flagPhantom(); - prim_llsd["physical"] = (BOOL)(object->mFlags & FLAGS_USE_PHYSICS); + prim_llsd["physical"] = object->flagUsePhysics(); // Volume params LLVolumeParams params = object->getVolume()->getParams(); @@ -994,9 +994,9 @@ void LLObjectBackup::xmlToPrim(LLSD prim_llsd, LLViewerObject* object) object->setScale(prim_llsd["scale"]); - if (prim_llsd.has("shadows")) + /*if (prim_llsd.has("shadows")) if (prim_llsd["shadows"].asInteger() == 1) - object->setFlags(FLAGS_CAST_SHADOWS, true); + object->setFlags(FLAGS_CAST_SHADOWS, true);*/ if (prim_llsd.has("phantom")) if (prim_llsd["phantom"].asInteger() == 1) @@ -1068,7 +1068,6 @@ void LLObjectBackup::xmlToPrim(LLSD prim_llsd, LLViewerObject* object) //if (mPrimImportIter != mThisGroup.endMap()) // mPrimImportIter++; - object->sendRotationUpdate(); object->sendTEUpdate(); object->sendShapeUpdate(); LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_SCALE | UPD_POSITION); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 758a8c3e9..b1810eeed 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -406,9 +406,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } else if (compressed) { - U8 compbuffer[2048]; S32 uncompressed_length = 2048; - S32 compressed_length; compressed_dp.reset(); U32 flags = 0; @@ -417,21 +415,9 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); } - if (flags & FLAGS_ZLIB_COMPRESSED) - { - compressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compbuffer, 0, i); - uncompressed_length = 2048; - uncompress(compressed_dpbuffer, (unsigned long *)&uncompressed_length, - compbuffer, compressed_length); - compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); - } - else - { - uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); - compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); - } + uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); + mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); + compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); if (update_type != OUT_TERSE_IMPROVED) @@ -932,21 +918,30 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) LLViewerObject *objectp = NULL; // Make a copy of the list in case something in idleUpdate() messes with it - std::vector idle_list; - + static std::vector idle_list; + + U32 idle_count = 0; + static LLFastTimer::DeclareTimer idle_copy("Idle Copy"); { LLFastTimer t(idle_copy); - idle_list.reserve( mActiveObjects.size() ); - - for (std::set >::iterator active_iter = mActiveObjects.begin(); + + for (std::vector >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) { objectp = *active_iter; if (objectp) { - idle_list.push_back( objectp ); + if (idle_count >= idle_list.size()) + { + idle_list.push_back( objectp ); + } + else + { + idle_list[idle_count] = objectp; + } + ++idle_count; } else { // There shouldn't be any NULL pointers in the list, but they have caused @@ -956,11 +951,12 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } } + std::vector::iterator idle_end = idle_list.begin()+idle_count; static const LLCachedControl freeze_time("FreezeTime",0); if (freeze_time) { for (std::vector::iterator iter = idle_list.begin(); - iter != idle_list.end(); iter++) + iter != idle_end; iter++) { objectp = *iter; if ( @@ -976,17 +972,17 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) else { for (std::vector::iterator idle_iter = idle_list.begin(); - idle_iter != idle_list.end(); idle_iter++) + idle_iter != idle_end; idle_iter++) { objectp = *idle_iter; - if (!objectp->idleUpdate(agent, world, frame_time)) + if (objectp->idleUpdate(agent, world, frame_time)) { - // If Idle Update returns false, kill object! - kill_list.push_back(objectp); + num_active_objects++; } else { - num_active_objects++; + // If Idle Update returns false, kill object! + kill_list.push_back(objectp); } } for (std::vector::iterator kill_iter = kill_list.begin(); @@ -1229,7 +1225,7 @@ void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list in cleanupReferences." << llendl; objectp->setOnActiveList(FALSE); - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); } if (objectp->isOnMap()) @@ -1296,6 +1292,7 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) return TRUE; } + return FALSE; } @@ -1419,6 +1416,26 @@ void LLViewerObjectList::cleanDeadObjects(BOOL use_timer) mNumDeadObjects = 0; } +void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) +{ + S32 idx = objectp->getListIndex(); + if (idx != -1) + { //remove by moving last element to this object's position + llassert(mActiveObjects[idx] == objectp); + + objectp->setListIndex(-1); + + S32 last_index = mActiveObjects.size()-1; + + if (idx != last_index) + { + mActiveObjects[idx] = mActiveObjects[last_index]; + mActiveObjects[idx]->setListIndex(idx); + mActiveObjects.pop_back(); + } + } +} + void LLViewerObjectList::updateActive(LLViewerObject *objectp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -1433,13 +1450,29 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) if (active) { //llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl; - mActiveObjects.insert(objectp); - objectp->setOnActiveList(TRUE); + S32 idx = objectp->getListIndex(); + if (idx <= -1) + { + mActiveObjects.push_back(objectp); + objectp->setListIndex(mActiveObjects.size()-1); + objectp->setOnActiveList(TRUE); + } + else + { + llassert(idx < (S32)mActiveObjects.size()); + llassert(mActiveObjects[idx] == objectp); + + if (idx >= (S32)mActiveObjects.size() || + mActiveObjects[idx] != objectp) + { + llwarns << "Invalid object list index detected!" << llendl; + } + } } else { //llinfos << "Removing " << objectp->mID << " " << objectp->getPCodeString() << " from active list." << llendl; - mActiveObjects.erase(objectp); + removeFromActiveList(objectp); objectp->setOnActiveList(FALSE); } } diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 9266dcf2d..5a48656b7 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -128,7 +128,9 @@ public: void dirtyAllObjectInventory(); + void removeFromActiveList(LLViewerObject* objectp); void updateActive(LLViewerObject *objectp); + void updateAvatarVisibility(); // Selection related stuff @@ -206,7 +208,7 @@ public: typedef std::vector > vobj_list_t; vobj_list_t mObjects; - std::set > mActiveObjects; + std::vector > mActiveObjects; vobj_list_t mMapObjects; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 6755005a8..11e47bd77 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1562,8 +1562,10 @@ void LLViewerRegion::unpackRegionHandshake() void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) { + capabilityNames.append("AgentState"); //capabilityNames.append("AttachmentResources"); //Script limits (llfloaterscriptlimits.cpp) //capabilityNames.append("AvatarPickerSearch"); //Display name/SLID lookup (llfloateravatarpicker.cpp) + capabilityNames.append("CharacterProperties"); capabilityNames.append("ChatSessionRequest"); capabilityNames.append("CopyInventoryFromNotecard"); capabilityNames.append("CreateInventoryCategory"); @@ -1596,7 +1598,9 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) #if MESH_IMPORT capabilityNames.append("MeshUploadFlag"); #endif //MESH_IMPORT + capabilityNames.append("NavMeshGenerationStatus"); capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("ObjectNavMeshProperties"); capabilityNames.append("ParcelPropertiesUpdate"); capabilityNames.append("ParcelNavigateMedia"); capabilityNames.append("ParcelVoiceInfoRequest"); @@ -1605,17 +1609,19 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("RemoteParcelRequest"); capabilityNames.append("RequestTextureDownload"); capabilityNames.append("ResourceCostSelected"); //Unreferenced? + capabilityNames.append("RetrieveNavMeshSrc"); capabilityNames.append("SearchStatRequest"); capabilityNames.append("SearchStatTracking"); capabilityNames.append("SendPostcard"); capabilityNames.append("SendUserReport"); capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("ServerReleaseNotes"); - //capabilityNames.append("SimConsole"); + capabilityNames.append("SimConsole"); capabilityNames.append("SimulatorFeatures"); capabilityNames.append("SetDisplayName"); - //capabilityNames.append("SimConsoleAsync"); + capabilityNames.append("SimConsoleAsync"); capabilityNames.append("StartGroupProposal"); + capabilityNames.append("TerrainNavMeshProperties"); capabilityNames.append("TextureStats"); capabilityNames.append("UntrustedSimulatorMessage"); capabilityNames.append("UpdateAgentInformation"); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 6ab2cfd17..2b2de806f 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -170,6 +170,7 @@ LLGLSLShader gGlowExtractProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in LLGLSLShader gPostColorFilterProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList LLGLSLShader gPostNightVisionProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList LLGLSLShader gPostGaussianBlurProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList +LLGLSLShader gPostPosterizeProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList // Deferred rendering shaders LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED); @@ -958,6 +959,23 @@ BOOL LLViewerShaderMgr::loadShadersEffects() gPostGaussianBlurProgram.uniform1i("tex0", 0); } } + + { + vector shaderUniforms; + shaderUniforms.reserve(1); + shaderUniforms.push_back("layerCount"); + + gPostPosterizeProgram.mName = "Posterize Shader (Post)"; + gPostPosterizeProgram.mShaderFiles.clear(); + gPostPosterizeProgram.mShaderFiles.push_back(make_pair("effects/PosterizeF.glsl", GL_FRAGMENT_SHADER_ARB)); + gPostPosterizeProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB)); + gPostPosterizeProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; + if(gPostPosterizeProgram.createShader(NULL, &shaderUniforms)) + { + gPostPosterizeProgram.bind(); + gPostPosterizeProgram.uniform1i("tex0", 0); + } + } #endif return success; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 4166cc5f2..98962a0fa 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -62,9 +62,6 @@ #include "llviewernetwork.h" #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived #include "sgmemstat.h" -#if LL_LCD_COMPILE -#include "lllcd.h" -#endif class StatAttributes @@ -201,10 +198,7 @@ const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] = // ST_TEX_BAKES StatAttributes("Texture Bakes", FALSE, FALSE), // ST_TEX_REBAKES - StatAttributes("Texture Rebakes", FALSE, FALSE), - - // ST_LOGITECH_KEYBOARD - StatAttributes("Logitech LCD", FALSE, FALSE) + StatAttributes("Texture Rebakes", FALSE, FALSE) }; @@ -699,14 +693,6 @@ void update_statistics(U32 frame_count) mem_stats_timer.reset(); } } - - -#if LL_LCD_COMPILE - bool LCDenabled = gLcdScreen->Enabled(); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, LCDenabled); -#else - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LOGITECH_LCD, false); -#endif } class ViewerStatsResponder : public LLHTTPClient::Responder diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index ec91b7efd..93d482da7 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -181,9 +181,8 @@ public: ST_WINDOW_HEIGHT = 55, ST_TEX_BAKES = 56, ST_TEX_REBAKES = 57, - ST_LOGITECH_LCD = 58, - ST_COUNT = 59 + ST_COUNT = 58 }; @@ -282,7 +281,7 @@ public: }; StatsAccumulator mAgentPositionSnaps; - + private: F64 mStats[ST_COUNT]; diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h index 8eaa0af0a..259c0d6ee 100644 --- a/indra/newview/llviewervisualparam.h +++ b/indra/newview/llviewervisualparam.h @@ -84,11 +84,11 @@ public: // New Virtual functions virtual F32 getTotalDistortion() = 0; - virtual const LLVector3& getAvgDistortion() = 0; + virtual const LLVector4a& getAvgDistortion() = 0; virtual F32 getMaxDistortion() = 0; - virtual LLVector3 getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; - virtual const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; - virtual const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual LLVector4a getVertexDistortion(S32 index, LLPolyMesh *mesh) = 0; + virtual const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **mesh) = 0; + virtual const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **mesh) = 0; // interface methods F32 getDisplayOrder() const { return getInfo()->mEditGroupDisplayOrder; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1320a0b79..9a2626301 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -131,6 +131,7 @@ #include "llmodaldialog.h" #include "llmorphview.h" #include "llmoveview.h" +#include "llpanelpathfindingrebakenavmesh.h" #include "llnotify.h" #include "lloverlaybar.h" #include "llpreviewtexture.h" @@ -1565,6 +1566,7 @@ LLViewerWindow::LLViewerWindow( LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable")); LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; gGL.init() ; + LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ; if (LLFeatureManager::getInstance()->isSafe() || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) @@ -1589,7 +1591,6 @@ LLViewerWindow::LLViewerWindow( // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. - LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ; gTextureList.init(); LLViewerTextureManager::init() ; gBumpImageList.init(); @@ -1958,6 +1959,10 @@ void LLViewerWindow::initWorldUI() // put behind everything else in the UI mRootView->addChildInBack(gHUDView); } + + LLPanel* panel_ssf_container = getRootView()->getChild("state_management_buttons_container"); + LLPanelPathfindingRebakeNavmesh *panel_rebake_navmesh = LLPanelPathfindingRebakeNavmesh::getInstance(); + panel_ssf_container->addChild(panel_rebake_navmesh); } // initWorldUI that wasn't before logging in. Some of this may require the access the 'LindenUserDir'. @@ -3097,7 +3102,7 @@ void LLViewerWindow::updateUI() } // snap floaters to top of chat bar/button strip - LLView* chatbar_and_buttons = gOverlayBar->getChild("chatbar_and_buttons", TRUE); + LLView* chatbar_and_buttons = gOverlayBar->getChatbarAndButtons(); // find top of chatbar and state buttons, if either are visible if (chatbar_and_buttons && chatbar_and_buttons->getLocalBoundingRect().notEmpty()) { @@ -3428,8 +3433,11 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, { LLSelectNode* nodep = *iter; LLViewerObject* object = nodep->getObject(); + LLViewerObject *root_object = (object == NULL) ? NULL : object->getRootEdit(); BOOL this_object_movable = FALSE; - if (object->permMove() && (object->permModify() || selecting_linked_set)) + if (object->permMove() && !object->isPermanentEnforced() && + ((root_object == NULL) || !root_object->isPermanentEnforced()) && + (object->permModify() || selecting_linked_set)) { moveable_object_selected = TRUE; this_object_movable = TRUE; @@ -4842,7 +4850,7 @@ void LLViewerWindow::stopGL(BOOL save_state) if(LLPostProcess::instanceExists()) { - LLPostProcess::getInstance()->invalidate(); + LLPostProcess::getInstance()->destroyGL(); } gTextureList.destroyGL(save_state); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 832d27299..63aef9afc 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1180,6 +1180,7 @@ LLVOAvatar::~LLVOAvatar() lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; mRoot.removeAllChildren(); + mJointMap.clear(); deleteAndClearArray(mSkeleton); deleteAndClearArray(mCollisionVolumes); @@ -2341,6 +2342,7 @@ void LLVOAvatar::buildCharacter() // remove all of mRoot's children //------------------------------------------------------------------------- mRoot.removeAllChildren(); + mJointMap.clear(); mIsBuilt = FALSE; //------------------------------------------------------------------------- @@ -5888,7 +5890,20 @@ const LLUUID& LLVOAvatar::getID() const // RN: avatar joints are multi-rooted to include screen-based attachments LLJoint *LLVOAvatar::getJoint( const std::string &name ) { - LLJoint* jointp = mRoot.findJoint(name); + joint_map_t::iterator iter = mJointMap.find(name); + + LLJoint* jointp = NULL; + + if (iter == mJointMap.end() || iter->second == NULL) + { //search for joint and cache found joint in lookup table + jointp = mRoot.findJoint(name); + mJointMap[name] = jointp; + } + else + { //return cached pointer + jointp = iter->second; + } + return jointp; } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index e0d4b3bf5..81529a2f3 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -376,6 +376,10 @@ public: LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; + + typedef std::map joint_map_t; + joint_map_t mJointMap; + protected: static BOOL parseSkeletonFile(const std::string& filename); void buildCharacter(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index bfa6dc60d..fbf0f63ae 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -712,7 +712,7 @@ void LLVOAvatarSelf::stopMotionFromSource(const LLUUID& source_id) LLViewerObject* object = gObjectList.findObject(source_id); if (object) { - object->mFlags &= ~FLAGS_ANIM_SOURCE; + object->setFlagsWithoutUpdate(FLAGS_ANIM_SOURCE, FALSE); } } diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 5a58ae770..6434dd619 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -645,7 +645,7 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count mFaceList.clear(); LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; diff --git a/indra/newview/llvoiceremotectrl.cpp b/indra/newview/llvoiceremotectrl.cpp index b496f07a7..f8d402a61 100644 --- a/indra/newview/llvoiceremotectrl.cpp +++ b/indra/newview/llvoiceremotectrl.cpp @@ -90,7 +90,12 @@ BOOL LLVoiceRemoteCtrl::postBuild() childSetAction("voice_channel_bg", onClickVoiceChannel, this); - + mEndCallBtn.connect(this,"end_call_btn"); + mVoiceVolIcon.connect(this,"voice_volume"); + mVoiceChanIcon.connect(this,"voice_channel_icon"); + mVoiceChanBgBtn.connect(this,"voice_channel_bg"); + mChanLabelTextBox.connect(this,"channel_label"); + mShowChanBtn.connect(this,"show_channel"); return TRUE; } @@ -106,14 +111,15 @@ void LLVoiceRemoteCtrl::draw() mTalkBtn->setEnabled(voice_active); mTalkLockBtn->setEnabled(voice_active); + static LLCachedControl ptt_currently_enabled("PTTCurrentlyEnabled",false); // propagate ptt state to button display, if (!mTalkBtn->hasMouseCapture()) { // not in push to talk mode, or push to talk is active means I'm talking - mTalkBtn->setToggleState(!gSavedSettings.getBOOL("PTTCurrentlyEnabled") || gVoiceClient->getUserPTTState()); + mTalkBtn->setToggleState(!ptt_currently_enabled || gVoiceClient->getUserPTTState()); } mSpeakersBtn->setToggleState(LLFloaterActiveSpeakers::instanceVisible(LLSD())); - mTalkLockBtn->setToggleState(!gSavedSettings.getBOOL("PTTCurrentlyEnabled")); + mTalkLockBtn->setToggleState(!ptt_currently_enabled); std::string talk_blip_image; if (gVoiceClient->getIsSpeaking(gAgent.getID())) @@ -148,7 +154,7 @@ void LLVoiceRemoteCtrl::draw() talk_blip_image = "icn_voice_ptt-off.tga"; } - LLIconCtrl* icon = getChild("voice_volume"); + LLIconCtrl* icon = mVoiceVolIcon; if (icon) { icon->setImage(talk_blip_image); @@ -162,23 +168,23 @@ void LLVoiceRemoteCtrl::draw() } LLVoiceChannel* current_channel = LLVoiceChannel::getCurrentVoiceChannel(); - childSetEnabled("end_call_btn", LLVoiceClient::voiceEnabled() + mEndCallBtn->setEnabled(LLVoiceClient::voiceEnabled() && current_channel && current_channel->isActive() && current_channel != LLVoiceChannelProximal::getInstance()); - childSetValue("channel_label", active_channel_name); - childSetToolTip("voice_channel_bg", active_channel_name); + mChanLabelTextBox->setValue(active_channel_name); + mVoiceChanBgBtn->setToolTip(active_channel_name); if (current_channel) { - LLIconCtrl* voice_channel_icon = getChild("voice_channel_icon"); + LLIconCtrl* voice_channel_icon = mVoiceChanIcon; if (voice_channel_icon && voice_floater) { voice_channel_icon->setImage(voice_floater->getString("voice_icon")); } - LLButton* voice_channel_bg = getChild("voice_channel_bg"); + LLButton* voice_channel_bg = mVoiceChanBgBtn; if (voice_channel_bg) { LLColor4 bg_color; @@ -198,7 +204,7 @@ void LLVoiceRemoteCtrl::draw() } } - LLButton* expand_button = getChild("show_channel"); + LLButton* expand_button = mShowChanBtn; if (expand_button) { if (expand_button->getToggleState()) diff --git a/indra/newview/llvoiceremotectrl.h b/indra/newview/llvoiceremotectrl.h index 8522a6f37..86504fe38 100644 --- a/indra/newview/llvoiceremotectrl.h +++ b/indra/newview/llvoiceremotectrl.h @@ -36,6 +36,8 @@ #include "llpanel.h" class LLButton; +class LLIconCtrl; +class LLTextBox; class LLVoiceRemoteCtrl : public LLPanel { @@ -59,6 +61,12 @@ protected: LLButton* mTalkBtn; LLButton* mTalkLockBtn; LLButton* mSpeakersBtn; + CachedUICtrl mEndCallBtn; + CachedUICtrl mVoiceVolIcon; + CachedUICtrl mVoiceChanIcon; + CachedUICtrl mVoiceChanBgBtn; + CachedUICtrl mChanLabelTextBox; + CachedUICtrl mShowChanBtn; }; #endif // LL_LLVOICEREMOTECTRL_H diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 434c8ca64..0a5a76900 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -49,7 +49,6 @@ #include "llviewerregion.h" #include "pipeline.h" #include "llspatialpartition.h" -#include "llviewerobjectlist.h" const F32 MAX_PART_LIFETIME = 120.f; @@ -59,8 +58,7 @@ LLPointer LLVOPartGroup::sVB = NULL; S32 LLVOPartGroup::sVBSlotFree[]; S32* LLVOPartGroup::sVBSlotCursor = NULL; -//static -void LLVOPartGroup::restoreGL() +void LLVOPartGroup::initClass() { for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) { @@ -68,7 +66,11 @@ void LLVOPartGroup::restoreGL() } sVBSlotCursor = sVBSlotFree; +} +//static +void LLVOPartGroup::restoreGL() +{ sVB = new LLVertexBuffer(VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); U32 count = LL_MAX_PARTICLE_COUNT; sVB->allocateBuffer(count*4, count*6, true); @@ -120,32 +122,6 @@ void LLVOPartGroup::restoreGL() //static void LLVOPartGroup::destroyGL() { - //Just iterate over all particle faces and mark their vbo index as 'uninitialized' since sVBSlotFree & sVBSlotCursor will be clobbered. - for (int i=0; imDrawable) - { - if (obj->mDrawable->getRenderType() == LLPipeline::RENDER_TYPE_PARTICLES || - obj->mDrawable->getRenderType() == LLPipeline::RENDER_TYPE_HUD_PARTICLES -#if ENABLE_CLASSIC_CLOUDS - || obj->mDrawable->getRenderType() == LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS -#endif - ) - { - for (S32 j = 0; j < obj->mDrawable->getNumFaces(); ++j) - { - LLFace* facep = obj->mDrawable->getFace(j); - if(facep) - facep->setIndicesIndex(0xFFFFFFFF); - } - } - } - } - for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) - { - sVBSlotFree[i] = i; - } sVB = NULL; } @@ -160,7 +136,6 @@ S32 LLVOPartGroup::findAvailableVBSlot() S32 ret = *sVBSlotCursor; sVBSlotCursor++; - return ret; } @@ -582,7 +557,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co mFaceList.clear(); LLViewerCamera* camera = LLViewerCamera::getInstance(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; @@ -654,7 +629,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLFace* facep = *i; LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); - if (facep->getIndicesStart() == 0xFFFFFFFF) + if (!facep->isState(LLFace::PARTICLE)) { //set the indices of this face S32 idx = LLVOPartGroup::findAvailableVBSlot(); if (idx >= 0) @@ -663,6 +638,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) facep->setIndicesIndex(idx*6); facep->setVertexBuffer(LLVOPartGroup::sVB); facep->setPoolType(LLDrawPool::POOL_ALPHA); + facep->setState(LLFace::PARTICLE); } else { diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 4c2e073d7..4948ddf55 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -51,6 +51,7 @@ public: static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; static S32* sVBSlotCursor; + static void initClass(); static void restoreGL(); static void destroyGL(); static S32 findAvailableVBSlot(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b785f22f5..c9e38c270 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -430,8 +430,8 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { LLViewerObject::idleUpdate(agent, world, time); - static LLFastTimer::DeclareTimer ftm("Volume Idle"); - LLFastTimer t(ftm); + //static LLFastTimer::DeclareTimer ftm("Volume Idle"); + //LLFastTimer t(ftm); if (mDead || mDrawable.isNull()) { @@ -2390,7 +2390,7 @@ U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const produces_light = 1; } - for (U32 i = 0; i < num_faces; ++i) + for (S32 i = 0; i < (S32)num_faces; ++i) { const LLFace* face = drawablep->getFace(i); if (!face) continue; @@ -3486,7 +3486,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); //get all the faces into a list - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -3892,7 +3892,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (!LLPipeline::sDelayVBUpdate) { //drawables have been rebuilt, clear rebuild status - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; drawablep->clearState(LLDrawable::REBUILD_ALL); @@ -3932,7 +3932,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) std::set mapped_buffers; - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; @@ -3956,8 +3956,14 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) if (buff) { llassert(!face->isState(LLFace::RIGGED)); - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + if (buff->isLocked()) { @@ -3998,7 +4004,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; warningsCount = 1; } - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; for (S32 i = 0; i < drawablep->getNumFaces(); ++i) @@ -4164,11 +4170,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: facep->setTextureIndex(cur_tex); texture_list.push_back(tex); - //if (can_batch_texture(facep)) + if (can_batch_texture(facep)) { while (i != faces.end()) { facep = *i; + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + break; + } if (facep->getTexture() != tex) { if (distance_sort) @@ -4194,12 +4205,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: cur_tex++; } - if (!can_batch_texture(facep)) - { //face is bump mapped or has an animated texture matrix -- can't - //batch more than 1 texture at a time - break; - } - if (cur_tex >= texture_index_channels) { //cut batches when index channels are depleted break; @@ -4221,9 +4226,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: facep->setTextureIndex(cur_tex); } + tex = texture_list[0]; } - - tex = texture_list[0]; } else { @@ -4299,8 +4303,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: llassert(!facep->isState(LLFace::RIGGED)); - facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true); + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + llwarns << "Failed to get geometry for face!" << llendl; + } if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) { @@ -4469,7 +4476,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun //for each drawable - for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index cc7b5cf10..dbf9800db 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -70,7 +70,7 @@ class LLVolumeInterface public: virtual ~LLVolumeInterface() { } virtual LLVolumeInterfaceType getInterfaceType() const = 0; - virtual BOOL doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; + virtual void doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) = 0; virtual BOOL doUpdateGeometry(LLDrawable *drawable) = 0; virtual LLVector3 getPivotPosition() const = 0; virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; @@ -297,6 +297,7 @@ public: U8 mTexAnimMode; private: friend class LLDrawable; + friend class LLFace; BOOL mFaceMappingChanged; LLFrameTimer mTextureUpdateTimer; diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 28bfe034a..4dbcfc578 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -35,11 +35,20 @@ #include "llweb.h" -#include "llviewerwindow.h" -#include "llwindow.h" +// Library includes +#include "llwindow.h" // spawnWebBrowser() -#include "llviewercontrol.h" +#include "llagent.h" +#include "llappviewer.h" #include "llfloatermediabrowser.h" +#include "llparcel.h" +#include "llviewercontrol.h" +#include "llviewernetwork.h" +#include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewerwindow.h" + +#include "sgversion.h" // static void LLWeb::initClass() @@ -125,6 +134,64 @@ std::string LLWeb::escapeURL(const std::string& url) return escaped_url; } +//static +std::string LLWeb::expandURLSubstitutions(const std::string &url, + const LLSD &default_subs) +{ + gCurrentVersion = llformat("%s %d.%d.%d.%d", + gVersionChannel, + gVersionMajor, + gVersionMinor, + gVersionPatch, + gVersionBuild ); + + LLSD substitution = default_subs; + substitution["VERSION"] = gCurrentVersion; + substitution["VERSION_MAJOR"] = gVersionMajor; + substitution["VERSION_MINOR"] = gVersionMinor; + substitution["VERSION_PATCH"] = gVersionPatch; + substitution["VERSION_BUILD"] = gVersionBuild; + substitution["CHANNEL"] = gVersionChannel; + substitution["GRID"] = LLViewerLogin::getInstance()->getGridLabel(); + substitution["OS"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); + substitution["SESSION_ID"] = gAgent.getSessionID(); + substitution["FIRST_LOGIN"] = gAgent.isFirstLogin(); + + // work out the current language + std::string lang = LLUI::getLanguage(); + if (lang == "en-us") + { + // *HACK: the correct fix is to change English.lproj/language.txt, + // but we're late in the release cycle and this is a less risky fix + lang = "en"; + } + substitution["LANGUAGE"] = lang; + + // find the region ID + LLUUID region_id; + LLViewerRegion *region = gAgent.getRegion(); + if (region) + { + region_id = region->getRegionID(); + } + substitution["REGION_ID"] = region_id; + + // find the parcel local ID + S32 parcel_id = 0; + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + parcel_id = parcel->getLocalID(); + } + substitution["PARCEL_ID"] = llformat("%d", parcel_id); + + // expand all of the substitution strings and escape the url + std::string expanded_url = url; + LLStringUtil::format(expanded_url, substitution); + + return LLWeb::escapeURL(expanded_url); +} + // virtual void LLWeb::URLLoader::load(const std::string& url) { diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 8dd13ffcb..73f5c7ebe 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -57,6 +57,10 @@ public: // Returns escaped (eg, " " to "%20") url static std::string escapeURL(const std::string& url); + /// Expands various strings like [LANG], [VERSION], etc. in a URL + static std::string expandURLSubstitutions(const std::string &url, + const LLSD &default_subs); + class URLLoader : public LLAlertDialog::URLLoader { virtual void load(const std::string& url); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index af5e977b2..11dc653aa 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -227,16 +227,6 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip) mCurlRequest = new LLCurlEasyRequest(); } - if(!mCurlRequest->isValid()) - { - llwarns << "mCurlRequest is invalid." << llendl ; - - delete mCurlRequest ; - mCurlRequest = NULL ; - return ; - } - - LLProxy::getInstance()->applyProxySettings(mCurlRequest); // mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging @@ -292,7 +282,7 @@ LLXMLRPCTransaction::Impl::~Impl() bool LLXMLRPCTransaction::Impl::process() { - if(!mCurlRequest || !mCurlRequest->isValid()) + if(!mCurlRequest || !mCurlRequest->getEasy()) { llwarns << "transaction failed." << llendl ; @@ -326,7 +316,7 @@ bool LLXMLRPCTransaction::Impl::process() //const F32 MAX_PROCESSING_TIME = 0.05f; //LLTimer timer; - mCurlRequest->wait(); + mCurlRequest->perform(); /*while (mCurlRequest->perform() > 0) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f2b0642e1..8440b836a 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -54,6 +54,7 @@ #include "llglheaders.h" #include "llrender.h" #include "llwindow.h" +#include "llpostprocess.h" // newview includes #include "llagent.h" @@ -453,15 +454,6 @@ void LLPipeline::init() mSpotLightFade[i] = 1.f; } - if (mCubeVB.isNull()) - { - mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB); - } - if(mDeferredVB.isNull()) - { - mDeferredVB = new LLVertexBuffer(DEFERRED_VB_MASK, 0); - mDeferredVB->allocateBuffer(8, 0, true); - } setLightingDetail(-1); gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); @@ -702,9 +694,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) //allocate deferred rendering color buffers - static const LLCachedControl shadow_precision("DeferredHighPrecision",true); - const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later - if (!mDeferredScreen.allocate(resX, resY, format, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mDeferredScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; if (!addDeferredAttachments(mDeferredScreen)) return false; @@ -874,6 +864,9 @@ void LLPipeline::releaseGLBuffers() gBumpImageList.destroyGL(); LLVOAvatar::resetImpostors(); + + if(LLPostProcess::instanceExists()) + LLPostProcess::getInstance()->destroyGL(); } void LLPipeline::releaseLUTBuffers() @@ -1174,7 +1167,7 @@ public: { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty()) + if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) { for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -1781,7 +1774,7 @@ void LLPipeline::clearReferences() void check_references(LLSpatialGroup* group, LLDrawable* drawable) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { if (drawable == *i) { @@ -1803,7 +1796,7 @@ void check_references(LLDrawable* drawable, LLFace* face) void check_references(LLSpatialGroup* group, LLFace* face) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawable = *i; check_references(drawable, face); @@ -1815,25 +1808,25 @@ void LLPipeline::checkReferences(LLFace* face) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, face); } - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { LLDrawable* drawable = *iter; check_references(drawable, face); @@ -1847,25 +1840,25 @@ void LLPipeline::checkReferences(LLDrawable* drawable) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, drawable); } - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { if (drawable == *iter) { @@ -1898,19 +1891,19 @@ void LLPipeline::checkReferences(LLDrawInfo* draw_info) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; check_references(group, draw_info); @@ -1924,7 +1917,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) #if 0 if (sCull) { - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { if (group == *iter) { @@ -1932,7 +1925,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) { if (group == *iter) { @@ -1940,7 +1933,7 @@ void LLPipeline::checkReferences(LLSpatialGroup* group) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { if (group == *iter) { @@ -2179,7 +2172,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) { - if (group->getData().empty()) + if (group->isEmpty()) { return; } @@ -2282,7 +2275,7 @@ void LLPipeline::doOcclusion(LLCamera& camera) } mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX); - for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; group->doOcclusion(&camera); @@ -2816,7 +2809,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) //LLVertexBuffer::unbind(); grabReferences(result); - for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); @@ -2827,7 +2820,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) else { group->setVisible(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { markVisible(*i, camera); } @@ -2842,9 +2835,9 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { LLSpatialGroup* last_group = NULL; - for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { - LLCullResult::bridge_list_t::iterator cur_iter = i; + LLCullResult::bridge_iterator cur_iter = i; LLSpatialBridge* bridge = *cur_iter; LLSpatialGroup* group = bridge->getSpatialGroup(); @@ -2874,7 +2867,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } - for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; group->checkOcclusion(); @@ -2896,7 +2889,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) { LLFastTimer ftm(FTM_STATESORT_DRAWABLE); - for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); + for (LLCullResult::drawable_iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) { LLDrawable *drawablep = *iter; @@ -2915,7 +2908,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) LLMemType mt(LLMemType::MTYPE_PIPELINE_STATE_SORT); if (!sSkipUpdate && group->changeLOD()) { - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { LLDrawable* drawablep = *i; stateSort(drawablep, camera); @@ -3045,13 +3038,13 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } -void forAllDrawables(LLCullResult::sg_list_t::iterator begin, - LLCullResult::sg_list_t::iterator end, +void forAllDrawables(LLCullResult::sg_iterator begin, + LLCullResult::sg_iterator end, void (*func)(LLDrawable*)) { - for (LLCullResult::sg_list_t::iterator i = begin; i != end; ++i) + for (LLCullResult::sg_iterator i = begin; i != end; ++i) { - for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j) + for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { func(*j); } @@ -3132,7 +3125,7 @@ void renderPhysicalBeacons(LLDrawable* drawablep) if (vobj && !vobj->isAvatar() //&& !vobj->getParent() - && vobj->usePhysics()) + && vobj->flagUsePhysics()) { if (gPipeline.sRenderBeacons) { @@ -3219,7 +3212,7 @@ void LLPipeline::postSort(LLCamera& camera) llpushcallstacks ; //rebuild drawable geometry - for (LLCullResult::sg_list_t::iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginDrawableGroups(); i != sCull->endDrawableGroups(); ++i) { LLSpatialGroup* group = *i; if (!sUseOcclusion || @@ -3237,7 +3230,7 @@ void LLPipeline::postSort(LLCamera& camera) //build render map - for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; @@ -4179,7 +4172,7 @@ void LLPipeline::renderPhysicsDisplay() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) @@ -4281,7 +4274,7 @@ void LLPipeline::renderDebug() } } - for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) @@ -6165,12 +6158,14 @@ void LLPipeline::doResetVertexBuffers() LLVOPartGroup::destroyGL(); + if(LLPostProcess::instanceExists()) + LLPostProcess::getInstance()->destroyGL(); + LLVertexBuffer::cleanupClass(); //delete all name pool caches LLGLNamePool::cleanupPools(); - if (LLVertexBuffer::sGLCount > 0) { llwarns << "VBO wipe failed -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl; @@ -6977,7 +6972,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b } - if (LLRenderTarget::sUseFBO) + if (mScreen.getFBO()) { //copy depth buffer from mScreen to framebuffer LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); @@ -9371,7 +9366,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture) { - for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) + for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i) { LLSpatialGroup* group = *i; if (!group->isDead() && @@ -9461,81 +9456,86 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) stateSort(*LLViewerCamera::getInstance(), result); - const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); - LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - LLCamera camera = *viewer_camera; - - camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); - LLVector2 tdim; + U32 resY = 0; + U32 resX = 0; - - LLVector4a half_height; - half_height.setSub(ext[1], ext[0]); - half_height.mul(0.5f); - - LLVector4a left; - left.load3(camera.getLeftAxis().mV); - left.mul(left); - left.normalize3fast(); - - LLVector4a up; - up.load3(camera.getUpAxis().mV); - up.mul(up); - up.normalize3fast(); - - tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); - tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); - - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - - F32 distance = (pos-camera.getOrigin()).length(); - F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; - F32 aspect = tdim.mV[0]/tdim.mV[1]; - glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); - glh_set_current_projection(persp); - gGL.loadMatrix(persp.m); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - glh::matrix4f mat; - camera.getOpenGLTransform(mat.m); - - mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; - - gGL.loadMatrix(mat.m); - glh_set_current_modelview(mat); - - glClearColor(0.0f,0.0f,0.0f,0.0f); - gGL.setColorMask(true, true); - - // get the number of pixels per angle - F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); - - //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) - U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); - U32 resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); - - if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() || - resY != avatar->mImpostor.getHeight()) { - static const LLCachedControl shadow_precision("DeferredHighPrecision",true); //TO-DO: Profile 16bit format later - avatar->mImpostor.allocate(resX,resY, (!LLPipeline::sRenderDeferred || shadow_precision) ? GL_RGBA : GL_RGBA16F_ARB,TRUE,FALSE); + const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); + LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); - if (LLPipeline::sRenderDeferred) + camera.lookAt(viewer_camera->getOrigin(), pos, viewer_camera->getUpAxis()); + + LLVector4a half_height; + half_height.setSub(ext[1], ext[0]); + half_height.mul(0.5f); + + LLVector4a left; + left.load3(camera.getLeftAxis().mV); + left.mul(left); + left.normalize3fast(); + + LLVector4a up; + up.load3(camera.getUpAxis().mV); + up.mul(up); + up.normalize3fast(); + + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); + + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + + F32 distance = (pos-camera.getOrigin()).length(); + F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; + F32 aspect = tdim.mV[0]/tdim.mV[1]; + glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); + glh_set_current_projection(persp); + gGL.loadMatrix(persp.m); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + glh::matrix4f mat; + camera.getOpenGLTransform(mat.m); + + mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat; + + gGL.loadMatrix(mat.m); + glh_set_current_modelview(mat); + + glClearColor(0.0f,0.0f,0.0f,0.0f); + gGL.setColorMask(true, true); + + // get the number of pixels per angle + F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); + + //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) + resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); + resX = llmin(nhpo2((U32) (atanf(tdim.mV[0]/distance)*2.f*RAD_TO_DEG*pa)), (U32) 512); + + if (!avatar->mImpostor.isComplete()) { - addDeferredAttachments(avatar->mImpostor); + avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE); + + if (LLPipeline::sRenderDeferred) + { + addDeferredAttachments(avatar->mImpostor); + } + + gGL.getTexUnit(0)->bind(&avatar->mImpostor); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } + else if(resX != avatar->mImpostor.getWidth() || + resY != avatar->mImpostor.getHeight()) + { + avatar->mImpostor.resize(resX,resY,GL_RGBA); } - gGL.getTexUnit(0)->bind(&avatar->mImpostor); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + avatar->mImpostor.bindTarget(); } - avatar->mImpostor.bindTarget(); - if (LLPipeline::sRenderDeferred) { avatar->mImpostor.clear(); @@ -9636,22 +9636,22 @@ BOOL LLPipeline::hasRenderBatches(const U32 type) const return sCull->getRenderMapSize(type) > 0; } -LLCullResult::drawinfo_list_t::iterator LLPipeline::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::beginRenderMap(U32 type) { return sCull->beginRenderMap(type); } -LLCullResult::drawinfo_list_t::iterator LLPipeline::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLPipeline::endRenderMap(U32 type) { return sCull->endRenderMap(type); } -LLCullResult::sg_list_t::iterator LLPipeline::beginAlphaGroups() +LLCullResult::sg_iterator LLPipeline::beginAlphaGroups() { return sCull->beginAlphaGroups(); } -LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() +LLCullResult::sg_iterator LLPipeline::endAlphaGroups() { return sCull->endAlphaGroups(); } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 33e522bb9..6dd80b5b1 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -296,10 +296,10 @@ public: void setLight(LLDrawable *drawablep, BOOL is_light); BOOL hasRenderBatches(const U32 type) const; - LLCullResult::drawinfo_list_t::iterator beginRenderMap(U32 type); - LLCullResult::drawinfo_list_t::iterator endRenderMap(U32 type); - LLCullResult::sg_list_t::iterator beginAlphaGroups(); - LLCullResult::sg_list_t::iterator endAlphaGroups(); + LLCullResult::drawinfo_iterator beginRenderMap(U32 type); + LLCullResult::drawinfo_iterator endRenderMap(U32 type); + LLCullResult::sg_iterator beginAlphaGroups(); + LLCullResult::sg_iterator endAlphaGroups(); void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); diff --git a/indra/newview/shfloatermediaticker.cpp b/indra/newview/shfloatermediaticker.cpp index f3e1849af..a2c995153 100644 --- a/indra/newview/shfloatermediaticker.cpp +++ b/indra/newview/shfloatermediaticker.cpp @@ -255,10 +255,6 @@ BOOL handle_ticker_enabled(void *) { return gAudiop && gAudiop->getStreamingAudioImpl() && gAudiop->getStreamingAudioImpl()->supportsMetaData(); } -BOOL handle_ticker_check(void *) -{ - return SHFloaterMediaTicker::instanceExists(); -} void handle_ticker_toggle(void *) { if(!handle_ticker_enabled(NULL)) diff --git a/indra/newview/shfloatermediaticker.h b/indra/newview/shfloatermediaticker.h index 3fa23bdda..4668f33bd 100644 --- a/indra/newview/shfloatermediaticker.h +++ b/indra/newview/shfloatermediaticker.h @@ -54,6 +54,5 @@ private: //Menu callbacks. BOOL handle_ticker_enabled(void *); -BOOL handle_ticker_check(void *); void handle_ticker_toggle(void *); diff --git a/indra/newview/skins/default/xui/en-us/floater_post_process.xml b/indra/newview/skins/default/xui/en-us/floater_post_process.xml index 4f26382b1..8280d1f84 100644 --- a/indra/newview/skins/default/xui/en-us/floater_post_process.xml +++ b/indra/newview/skins/default/xui/en-us/floater_post_process.xml @@ -146,6 +146,25 @@ left="14" max_val="1" min_val="0" mouse_opaque="true" name="noise_strength" show_text="true" value="1.0" width="220" /> + + + + Layer Count + + + @@ -549,6 +549,40 @@ mouse_opaque="true" name="F:" v_pad="0" width="74"> F: + + + + Pathfinding attributes: + + + Test + + You can modify this object. @@ -561,6 +595,12 @@ You cannot modify these objects. + + You can't modify this object across a region boundary + + + You can't modify these objects across a region boundary + Must select entire object to set permissions. diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 4c0be8b3d..efe9ef5da 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -101,6 +101,21 @@ + +