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
@@ -370,6 +370,14 @@
+ DisplayNameUpdate
+
+
ParcelVoiceInfo
+ SetDisplayNameReply
+
+
+ SimConsoleResponse
+
+
DirLandReply
-
-
+
+ NavMeshStatusUpdate
+
+
+ AgentStateUpdate
+
+
+
ScriptRunningReply
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