Merge branch 'DRTVWR-588-maint-W' into marchcat/588-w-pbr-merge

# Conflicts:
#	indra/llrender/llgl.cpp
#	indra/llrender/llvertexbuffer.cpp
#	indra/llui/llflatlistview.cpp
#	indra/newview/lldrawpoolground.cpp
#	indra/newview/llspatialpartition.cpp
#	indra/newview/lltexturefetch.cpp
#	indra/newview/llviewergenericmessage.cpp
#	indra/newview/llviewertexture.cpp
#	indra/newview/llvosky.cpp
#	indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
#	indra/newview/skins/default/xui/en/floater_stats.xml
#	indra/newview/skins/default/xui/en/floater_texture_fetch_debugger.xml
#	indra/newview/skins/default/xui/en/notifications.xml
#	indra/newview/skins/default/xui/en/panel_performance_preferences.xml
master
Andrey Lihatskiy 2023-11-30 12:28:26 +02:00
commit 0465c761a4
701 changed files with 3154 additions and 2928 deletions

View File

@ -360,6 +360,11 @@ jobs:
# name the release page for the build number so we can find it # name the release page for the build number so we can find it
# easily (analogous to looking up a codeticket build page) # easily (analogous to looking up a codeticket build page)
name: "v${{ github.run_id }}" name: "v${{ github.run_id }}"
# SL-20546: want the channel and version to be visible on the
# release page
body: |
${{ needs.build.outputs.viewer_channel }}
${{ needs.build.outputs.viewer_version }}
prerelease: true prerelease: true
generate_release_notes: true generate_release_notes: true
# the only reason we generate a GH release is to post build products # the only reason we generate a GH release is to post build products

View File

@ -291,6 +291,7 @@ Beq Janus
SL-18637 SL-18637
SL-19317 SL-19317
SL-19660 SL-19660
SL-20610
Beth Walcher Beth Walcher
Bezilon Kasei Bezilon Kasei
Biancaluce Robbiani Biancaluce Robbiani

View File

@ -104,7 +104,6 @@ BOOL LLApp::sLogInSignal = FALSE;
// Keeps track of application status // Keeps track of application status
LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED}; LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
LLAppErrorHandler LLApp::sErrorHandler = NULL; LLAppErrorHandler LLApp::sErrorHandler = NULL;
BOOL LLApp::sErrorThreadRunning = FALSE;
LLApp::LLApp() LLApp::LLApp()
@ -787,13 +786,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
return; return;
} }
// Flag status to ERROR, so thread_error does its work. // Flag status to ERROR
LLApp::setError(); LLApp::setError();
// Block in the signal handler until somebody says that we're done.
while (LLApp::sErrorThreadRunning && !LLApp::isStopped())
{
ms_sleep(10);
}
if (LLApp::sLogInSignal) if (LLApp::sLogInSignal)
{ {

View File

@ -291,7 +291,6 @@ protected:
static void setStatus(EAppStatus status); // Use this to change the application status. static void setStatus(EAppStatus status); // Use this to change the application status.
static LLScalarCond<EAppStatus> sStatus; // Reflects current application status static LLScalarCond<EAppStatus> sStatus; // Reflects current application status
static BOOL sErrorThreadRunning; // Set while the error thread is running
static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.

View File

@ -38,6 +38,12 @@ const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAP
bool gAPRInitialized = false; bool gAPRInitialized = false;
int abortfunc(int retcode)
{
LL_WARNS("APR") << "Allocation failure in apr pool with code " << (S32)retcode << LL_ENDL;
return 0;
}
void ll_init_apr() void ll_init_apr()
{ {
// Initialize APR and create the global pool // Initialize APR and create the global pool
@ -45,7 +51,7 @@ void ll_init_apr()
if (!gAPRPoolp) if (!gAPRPoolp)
{ {
apr_pool_create(&gAPRPoolp, NULL); apr_pool_create_ex(&gAPRPoolp, NULL, abortfunc, NULL);
} }
if(!LLAPRFile::sAPRFilePoolp) if(!LLAPRFile::sAPRFilePoolp)

View File

@ -123,7 +123,7 @@ LLCoros::LLCoros():
// Previously we used // Previously we used
// boost::context::guarded_stack_allocator::default_stacksize(); // boost::context::guarded_stack_allocator::default_stacksize();
// empirically this is insufficient. // empirically this is insufficient.
mStackSize(768*1024), mStackSize(900*1024),
// mCurrent does NOT own the current CoroData instance -- it simply // mCurrent does NOT own the current CoroData instance -- it simply
// points to it. So initialize it with a no-op deleter. // points to it. So initialize it with a no-op deleter.
mCurrent{ [](CoroData*){} } mCurrent{ [](CoroData*){} }

View File

@ -87,11 +87,10 @@ protected:
} }
void addEntry(Index index, Entry *entry) void addEntry(Index index, Entry *entry)
{ {
if (lookup(index)) if (!this->emplace(index, entry).second)
{ {
LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL; LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL;
} }
(*this)[index] = entry;
} }
}; };

View File

@ -46,33 +46,32 @@
template <class Type> class LLPointer template <class Type> class LLPointer
{ {
public: public:
LLPointer() :
LLPointer() :
mPointer(NULL) mPointer(NULL)
{ {
} }
LLPointer(Type* ptr) : LLPointer(Type* ptr) :
mPointer(ptr) mPointer(ptr)
{ {
ref(); ref();
} }
LLPointer(const LLPointer<Type>& ptr) : LLPointer(const LLPointer<Type>& ptr) :
mPointer(ptr.mPointer) mPointer(ptr.mPointer)
{ {
ref(); ref();
} }
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. // Support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass> template<typename Subclass>
LLPointer(const LLPointer<Subclass>& ptr) : LLPointer(const LLPointer<Subclass>& ptr) :
mPointer(ptr.get()) mPointer(ptr.get())
{ {
ref(); ref();
} }
~LLPointer() ~LLPointer()
{ {
unref(); unref();
} }
@ -83,39 +82,39 @@ public:
const Type& operator*() const { return *mPointer; } const Type& operator*() const { return *mPointer; }
Type& operator*() { return *mPointer; } Type& operator*() { return *mPointer; }
operator BOOL() const { return (mPointer != NULL); } operator BOOL() const { return (mPointer != NULL); }
operator bool() const { return (mPointer != NULL); } operator bool() const { return (mPointer != NULL); }
bool operator!() const { return (mPointer == NULL); } bool operator!() const { return (mPointer == NULL); }
bool isNull() const { return (mPointer == NULL); } bool isNull() const { return (mPointer == NULL); }
bool notNull() const { return (mPointer != NULL); } bool notNull() const { return (mPointer != NULL); }
operator Type*() const { return mPointer; } operator Type*() const { return mPointer; }
bool operator !=(Type* ptr) const { return (mPointer != ptr); } bool operator !=(Type* ptr) const { return (mPointer != ptr); }
bool operator ==(Type* ptr) const { return (mPointer == ptr); } bool operator ==(Type* ptr) const { return (mPointer == ptr); }
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
LLPointer<Type>& operator =(Type* ptr) LLPointer<Type>& operator =(Type* ptr)
{ {
assign(ptr); assign(ptr);
return *this; return *this;
} }
LLPointer<Type>& operator =(const LLPointer<Type>& ptr) LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
{ {
assign(ptr); assign(ptr);
return *this; return *this;
} }
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass> template<typename Subclass>
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
{ {
assign(ptr.get()); assign(ptr.get());
return *this; return *this;
} }
// Just exchange the pointers, which will not change the reference counts. // Just exchange the pointers, which will not change the reference counts.
static void swap(LLPointer<Type>& a, LLPointer<Type>& b) static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
{ {
@ -129,16 +128,6 @@ protected:
void ref(); void ref();
void unref(); void unref();
#else #else
void assign(const LLPointer<Type>& ptr)
{
if( mPointer != ptr.mPointer )
{
unref();
mPointer = ptr.mPointer;
ref();
}
}
void ref() void ref()
{ {
if (mPointer) if (mPointer)
@ -161,7 +150,18 @@ protected:
} }
} }
} }
#endif #endif // LL_LIBRARY_INCLUDE
void assign(const LLPointer<Type>& ptr)
{
if (mPointer != ptr.mPointer)
{
unref();
mPointer = ptr.mPointer;
ref();
}
}
protected: protected:
Type* mPointer; Type* mPointer;
}; };
@ -169,18 +169,18 @@ protected:
template <class Type> class LLConstPointer template <class Type> class LLConstPointer
{ {
public: public:
LLConstPointer() : LLConstPointer() :
mPointer(NULL) mPointer(NULL)
{ {
} }
LLConstPointer(const Type* ptr) : LLConstPointer(const Type* ptr) :
mPointer(ptr) mPointer(ptr)
{ {
ref(); ref();
} }
LLConstPointer(const LLConstPointer<Type>& ptr) : LLConstPointer(const LLConstPointer<Type>& ptr) :
mPointer(ptr.mPointer) mPointer(ptr.mPointer)
{ {
ref(); ref();
@ -188,7 +188,7 @@ public:
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass> template<typename Subclass>
LLConstPointer(const LLConstPointer<Subclass>& ptr) : LLConstPointer(const LLConstPointer<Subclass>& ptr) :
mPointer(ptr.get()) mPointer(ptr.get())
{ {
ref(); ref();
@ -203,55 +203,55 @@ public:
const Type* operator->() const { return mPointer; } const Type* operator->() const { return mPointer; }
const Type& operator*() const { return *mPointer; } const Type& operator*() const { return *mPointer; }
operator BOOL() const { return (mPointer != NULL); } operator BOOL() const { return (mPointer != NULL); }
operator bool() const { return (mPointer != NULL); } operator bool() const { return (mPointer != NULL); }
bool operator!() const { return (mPointer == NULL); } bool operator!() const { return (mPointer == NULL); }
bool isNull() const { return (mPointer == NULL); } bool isNull() const { return (mPointer == NULL); }
bool notNull() const { return (mPointer != NULL); } bool notNull() const { return (mPointer != NULL); }
operator const Type*() const { return mPointer; } operator const Type*() const { return mPointer; }
bool operator !=(const Type* ptr) const { return (mPointer != ptr); } bool operator !=(const Type* ptr) const { return (mPointer != ptr); }
bool operator ==(const Type* ptr) const { return (mPointer == ptr); } bool operator ==(const Type* ptr) const { return (mPointer == ptr); }
bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
LLConstPointer<Type>& operator =(const Type* ptr) LLConstPointer<Type>& operator =(const Type* ptr)
{ {
if( mPointer != ptr ) if( mPointer != ptr )
{ {
unref(); unref();
mPointer = ptr; mPointer = ptr;
ref(); ref();
} }
return *this; return *this;
} }
LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr) LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr)
{ {
if( mPointer != ptr.mPointer ) if( mPointer != ptr.mPointer )
{ {
unref(); unref();
mPointer = ptr.mPointer; mPointer = ptr.mPointer;
ref(); ref();
} }
return *this; return *this;
} }
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
template<typename Subclass> template<typename Subclass>
LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr)
{ {
if( mPointer != ptr.get() ) if( mPointer != ptr.get() )
{ {
unref(); unref();
mPointer = ptr.get(); mPointer = ptr.get();
ref(); ref();
} }
return *this; return *this;
} }
// Just exchange the pointers, which will not change the reference counts. // Just exchange the pointers, which will not change the reference counts.
static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b) static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b)
{ {
@ -262,11 +262,11 @@ public:
protected: protected:
#ifdef LL_LIBRARY_INCLUDE #ifdef LL_LIBRARY_INCLUDE
void ref(); void ref();
void unref(); void unref();
#else #else // LL_LIBRARY_INCLUDE
void ref() void ref()
{ {
if (mPointer) if (mPointer)
{ {
mPointer->ref(); mPointer->ref();
@ -277,9 +277,9 @@ protected:
{ {
if (mPointer) if (mPointer)
{ {
const Type *tempp = mPointer; const Type *temp = mPointer;
mPointer = NULL; mPointer = NULL;
tempp->unref(); temp->unref();
if (mPointer != NULL) if (mPointer != NULL)
{ {
LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
@ -287,7 +287,8 @@ protected:
} }
} }
} }
#endif #endif // LL_LIBRARY_INCLUDE
protected: protected:
const Type* mPointer; const Type* mPointer;
}; };
@ -297,13 +298,13 @@ class LLCopyOnWritePointer : public LLPointer<Type>
{ {
public: public:
typedef LLCopyOnWritePointer<Type> self_t; typedef LLCopyOnWritePointer<Type> self_t;
typedef LLPointer<Type> pointer_t; typedef LLPointer<Type> pointer_t;
LLCopyOnWritePointer() LLCopyOnWritePointer()
: mStayUnique(false) : mStayUnique(false)
{} {}
LLCopyOnWritePointer(Type* ptr) LLCopyOnWritePointer(Type* ptr)
: LLPointer<Type>(ptr), : LLPointer<Type>(ptr),
mStayUnique(false) mStayUnique(false)
{} {}

View File

@ -529,6 +529,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
// preserve existing semantics, we promise that mAttached defaults to the // preserve existing semantics, we promise that mAttached defaults to the
// same setting as mAutokill. // same setting as mAutokill.
mAttached(params.attached.isProvided()? params.attached : params.autokill), mAttached(params.attached.isProvided()? params.attached : params.autokill),
mPool(NULL),
mPipes(NSLOTS) mPipes(NSLOTS)
{ {
// Hmm, when you construct a ptr_vector with a size, it merely reserves // Hmm, when you construct a ptr_vector with a size, it merely reserves
@ -549,8 +550,14 @@ LLProcess::LLProcess(const LLSDOrParams& params):
mPostend = params.postend; mPostend = params.postend;
apr_pool_create(&mPool, gAPRPoolp);
if (!mPool)
{
LLTHROW(LLProcessError(STRINGIZE("failed to create apr pool")));
}
apr_procattr_t *procattr = NULL; apr_procattr_t *procattr = NULL;
chkapr(apr_procattr_create(&procattr, gAPRPoolp)); chkapr(apr_procattr_create(&procattr, mPool));
// IQA-490, CHOP-900: On Windows, ask APR to jump through hoops to // IQA-490, CHOP-900: On Windows, ask APR to jump through hoops to
// constrain the set of handles passed to the child process. Before we // constrain the set of handles passed to the child process. Before we
@ -689,14 +696,14 @@ LLProcess::LLProcess(const LLSDOrParams& params):
// one. Hand-expand chkapr() macro so we can fill in the actual command // one. Hand-expand chkapr() macro so we can fill in the actual command
// string instead of the variable names. // string instead of the variable names.
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
gAPRPoolp))) mPool)))
{ {
LLTHROW(LLProcessError(STRINGIZE(params << " failed"))); LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
} }
// arrange to call status_callback() // arrange to call status_callback()
apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in, apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
gAPRPoolp); mPool);
// and make sure we poll it once per "mainloop" tick // and make sure we poll it once per "mainloop" tick
sProcessListener.addPoll(*this); sProcessListener.addPoll(*this);
mStatus.mState = RUNNING; mStatus.mState = RUNNING;
@ -815,6 +822,12 @@ LLProcess::~LLProcess()
{ {
kill("destructor"); kill("destructor");
} }
if (mPool)
{
apr_pool_destroy(mPool);
mPool = NULL;
}
} }
bool LLProcess::kill(const std::string& who) bool LLProcess::kill(const std::string& who)

View File

@ -568,6 +568,7 @@ private:
// explicitly want this ptr_vector to be able to store NULLs // explicitly want this ptr_vector to be able to store NULLs
typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector; typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector;
PipeVector mPipes; PipeVector mPipes;
apr_pool_t* mPool;
}; };
/// for logging /// for logging

View File

@ -30,7 +30,7 @@
#include "llerror.h" #include "llerror.h"
// maximum reference count before sounding memory leak alarm // maximum reference count before sounding memory leak alarm
const S32 gMaxRefCount = S32_MAX; const S32 gMaxRefCount = LL_REFCOUNT_FREE;
LLRefCount::LLRefCount(const LLRefCount& other) LLRefCount::LLRefCount(const LLRefCount& other)
: mRef(0) : mRef(0)
@ -49,7 +49,7 @@ LLRefCount::LLRefCount() :
} }
LLRefCount::~LLRefCount() LLRefCount::~LLRefCount()
{ {
if (mRef != LL_REFCOUNT_FREE && mRef != 0) if (mRef != LL_REFCOUNT_FREE && mRef != 0)
{ {
LL_ERRS() << "deleting non-zero reference" << LL_ENDL; LL_ERRS() << "deleting non-zero reference" << LL_ENDL;

View File

@ -51,24 +51,20 @@ protected:
public: public:
LLRefCount(); LLRefCount();
inline void validateRefCount() const
{
llassert(mRef > 0); // ref count below 0, likely corrupted
llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
}
inline void ref() const inline void ref() const
{ {
mRef++; llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
validateRefCount(); mRef++;
} llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
}
inline S32 unref() const inline S32 unref() const
{ {
validateRefCount(); llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
llassert(mRef > 0); // ref count below 1, likely corrupted
if (0 == --mRef) if (0 == --mRef)
{ {
mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging mRef = LL_REFCOUNT_FREE; // set to nonsense yet recognizable value to aid in debugging
delete this; delete this;
return 0; return 0;
} }
@ -82,8 +78,8 @@ public:
return mRef; return mRef;
} }
private: private:
mutable S32 mRef; mutable S32 mRef;
}; };
@ -106,7 +102,7 @@ protected:
public: public:
LLThreadSafeRefCount(); LLThreadSafeRefCount();
LLThreadSafeRefCount(const LLThreadSafeRefCount&); LLThreadSafeRefCount(const LLThreadSafeRefCount&);
LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
{ {
mRef = 0; mRef = 0;
return *this; return *this;
@ -114,8 +110,8 @@ public:
void ref() void ref()
{ {
mRef++; mRef++;
} }
void unref() void unref()
{ {
@ -136,36 +132,36 @@ public:
return currentVal; return currentVal;
} }
private: private:
LLAtomicS32 mRef; LLAtomicS32 mRef;
}; };
/** /**
* intrusive pointer support for LLThreadSafeRefCount * intrusive pointer support for LLThreadSafeRefCount
* this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
*/ */
inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)
{ {
p->ref(); p->ref();
} }
inline void intrusive_ptr_release(LLThreadSafeRefCount* p) inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
{ {
p->unref(); p->unref();
} }
/** /**
* intrusive pointer support * intrusive pointer support
* this allows you to use boost::intrusive_ptr with any LLRefCount-derived type * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type
*/ */
inline void intrusive_ptr_add_ref(LLRefCount* p) inline void intrusive_ptr_add_ref(LLRefCount* p)
{ {
p->ref(); p->ref();
} }
inline void intrusive_ptr_release(LLRefCount* p) inline void intrusive_ptr_release(LLRefCount* p)
{ {
p->unref(); p->unref();
} }
#endif #endif

View File

@ -1235,9 +1235,17 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
} }
else else
{ {
#if 0
// EXT-1565 : Zai Lynch, James Linden : 15/Oct/09
// [BSI] Feedback: Viewer clock mentions SLT, but would prefer it to show PST/PDT
// "slt" = Second Life Time, which is deprecated. // "slt" = Second Life Time, which is deprecated.
// If not utc or user local time, fallback to Pacific time // If not utc or user local time, fallback to Pacific time
replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST"; replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
#else
// SL-20370 : Steeltoe Linden : 29/Sep/23
// Change "PDT" to "SLT" on menu bar
replacement = "SLT";
#endif
} }
return true; return true;
} }

View File

@ -33,8 +33,6 @@
namespace LLTrace namespace LLTrace
{ {
MemStatHandle gTraceMemStat("LLTrace");
StatBase::StatBase( const char* name, const char* description ) StatBase::StatBase( const char* name, const char* description )
: mName(name), : mName(name),
mDescription(description ? description : "") mDescription(description ? description : "")

View File

@ -193,61 +193,6 @@ void add(CountStatHandle<T>& count, VALUE_T value)
#endif #endif
} }
template<>
class StatType<MemAccumulator::AllocationFacet>
: public StatType<MemAccumulator>
{
public:
StatType(const char* name, const char* description = "")
: StatType<MemAccumulator>(name, description)
{}
};
template<>
class StatType<MemAccumulator::DeallocationFacet>
: public StatType<MemAccumulator>
{
public:
StatType(const char* name, const char* description = "")
: StatType<MemAccumulator>(name, description)
{}
};
class MemStatHandle : public StatType<MemAccumulator>
{
public:
typedef StatType<MemAccumulator> stat_t;
MemStatHandle(const char* name, const char* description = "")
: stat_t(name, description)
{
mName = name;
}
void setName(const char* name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mName = name;
setKey(name);
}
/*virtual*/ const char* getUnitLabel() const { return "KB"; }
StatType<MemAccumulator::AllocationFacet>& allocations()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return static_cast<StatType<MemAccumulator::AllocationFacet>&>(*(StatType<MemAccumulator>*)this);
}
StatType<MemAccumulator::DeallocationFacet>& deallocations()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return static_cast<StatType<MemAccumulator::DeallocationFacet>&>(*(StatType<MemAccumulator>*)this);
}
};
// measures effective memory footprint of specified type // measures effective memory footprint of specified type
// specialize to cover different types // specialize to cover different types
template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void> template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void>
@ -334,33 +279,6 @@ struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES>
} }
}; };
template<typename T>
inline void claim_alloc(MemStatHandle& measurement, const T& value)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
auto size = MeasureMem<T>::measureFootprint(value);
if(size == 0) return;
MemAccumulator& accumulator = measurement.getCurrentAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
accumulator.mAllocations.record(size);
#endif
}
template<typename T>
inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
auto size = MeasureMem<T>::measureFootprint(value);
if(size == 0) return;
MemAccumulator& accumulator = measurement.getCurrentAccumulator();
accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
accumulator.mDeallocations.add(size);
#endif
}
} }
#endif // LL_LLTRACE_H #endif // LL_LLTRACE_H

View File

@ -1,24 +1,24 @@
/** /**
* @file lltracesampler.cpp * @file lltracesampler.cpp
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc. * Copyright (C) 2012, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -32,66 +32,45 @@
namespace LLTrace namespace LLTrace
{ {
extern MemStatHandle gTraceMemStat;
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// AccumulatorBufferGroup // AccumulatorBufferGroup
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
AccumulatorBufferGroup::AccumulatorBufferGroup() AccumulatorBufferGroup::AccumulatorBufferGroup()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
} }
AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other) AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other)
: mCounts(other.mCounts), : mCounts(other.mCounts),
mSamples(other.mSamples), mSamples(other.mSamples),
mEvents(other.mEvents), mEvents(other.mEvents),
mStackTimers(other.mStackTimers), mStackTimers(other.mStackTimers)
mMemStats(other.mMemStats)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
} }
AccumulatorBufferGroup::~AccumulatorBufferGroup() AccumulatorBufferGroup::~AccumulatorBufferGroup()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
disclaim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
} }
void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other) void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
other.mCounts.reset(&mCounts); other.mCounts.reset(&mCounts);
other.mSamples.reset(&mSamples); other.mSamples.reset(&mSamples);
other.mEvents.reset(&mEvents); other.mEvents.reset(&mEvents);
other.mStackTimers.reset(&mStackTimers); other.mStackTimers.reset(&mStackTimers);
other.mMemStats.reset(&mMemStats);
} }
void AccumulatorBufferGroup::makeCurrent() void AccumulatorBufferGroup::makeCurrent()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mCounts.makeCurrent(); mCounts.makeCurrent();
mSamples.makeCurrent(); mSamples.makeCurrent();
mEvents.makeCurrent(); mEvents.makeCurrent();
mStackTimers.makeCurrent(); mStackTimers.makeCurrent();
mMemStats.makeCurrent();
ThreadRecorder* thread_recorder = get_thread_recorder(); ThreadRecorder* thread_recorder = get_thread_recorder();
AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers; AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
@ -109,12 +88,11 @@ void AccumulatorBufferGroup::makeCurrent()
//static //static
void AccumulatorBufferGroup::clearCurrent() void AccumulatorBufferGroup::clearCurrent()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
AccumulatorBuffer<CountAccumulator>::clearCurrent(); AccumulatorBuffer<CountAccumulator>::clearCurrent();
AccumulatorBuffer<SampleAccumulator>::clearCurrent(); AccumulatorBuffer<SampleAccumulator>::clearCurrent();
AccumulatorBuffer<EventAccumulator>::clearCurrent(); AccumulatorBuffer<EventAccumulator>::clearCurrent();
AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent(); AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent();
AccumulatorBuffer<MemAccumulator>::clearCurrent();
} }
bool AccumulatorBufferGroup::isCurrent() const bool AccumulatorBufferGroup::isCurrent() const
@ -124,44 +102,39 @@ bool AccumulatorBufferGroup::isCurrent() const
void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mCounts.addSamples(other.mCounts, SEQUENTIAL); mCounts.addSamples(other.mCounts, SEQUENTIAL);
mSamples.addSamples(other.mSamples, SEQUENTIAL); mSamples.addSamples(other.mSamples, SEQUENTIAL);
mEvents.addSamples(other.mEvents, SEQUENTIAL); mEvents.addSamples(other.mEvents, SEQUENTIAL);
mMemStats.addSamples(other.mMemStats, SEQUENTIAL);
mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL); mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL);
} }
void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other) void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mCounts.addSamples(other.mCounts, NON_SEQUENTIAL); mCounts.addSamples(other.mCounts, NON_SEQUENTIAL);
mSamples.addSamples(other.mSamples, NON_SEQUENTIAL); mSamples.addSamples(other.mSamples, NON_SEQUENTIAL);
mEvents.addSamples(other.mEvents, NON_SEQUENTIAL); mEvents.addSamples(other.mEvents, NON_SEQUENTIAL);
mMemStats.addSamples(other.mMemStats, NON_SEQUENTIAL);
// for now, hold out timers from merge, need to be displayed per thread // for now, hold out timers from merge, need to be displayed per thread
//mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL); //mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL);
} }
void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other) void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mCounts.reset(other ? &other->mCounts : NULL); mCounts.reset(other ? &other->mCounts : NULL);
mSamples.reset(other ? &other->mSamples : NULL); mSamples.reset(other ? &other->mSamples : NULL);
mEvents.reset(other ? &other->mEvents : NULL); mEvents.reset(other ? &other->mEvents : NULL);
mStackTimers.reset(other ? &other->mStackTimers : NULL); mStackTimers.reset(other ? &other->mStackTimers : NULL);
mMemStats.reset(other ? &other->mMemStats : NULL);
} }
void AccumulatorBufferGroup::sync() void AccumulatorBufferGroup::sync()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
if (isCurrent()) if (isCurrent())
{ {
F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
mSamples.sync(time_stamp); mSamples.sync(time_stamp);
mMemStats.sync(time_stamp);
} }
} }
@ -197,10 +170,9 @@ F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const Samp
return a.getSumOfSquares(); return a.getSumOfSquares();
} }
void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type ) void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
{ {
if (append_type == NON_SEQUENTIAL) if (append_type == NON_SEQUENTIAL)
{ {
return; return;
} }
@ -299,7 +271,7 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT
void EventAccumulator::reset( const EventAccumulator* other ) void EventAccumulator::reset( const EventAccumulator* other )
{ {
mNumSamples = 0; mNumSamples = 0;
mSum = 0; mSum = 0;
mMin = F32(NaN); mMin = F32(NaN);
mMax = F32(NaN); mMax = F32(NaN);
@ -308,5 +280,4 @@ void EventAccumulator::reset( const EventAccumulator* other )
mLastValue = other ? other->mLastValue : NaN; mLastValue = other ? other->mLastValue : NaN;
} }
} }

View File

@ -1,26 +1,26 @@
/** /**
* @file lltraceaccumulators.h * @file lltraceaccumulators.h
* @brief Storage for accumulating statistics * @brief Storage for accumulating statistics
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc. * Copyright (C) 2012, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -28,7 +28,6 @@
#ifndef LL_LLTRACEACCUMULATORS_H #ifndef LL_LLTRACEACCUMULATORS_H
#define LL_LLTRACEACCUMULATORS_H #define LL_LLTRACEACCUMULATORS_H
#include "stdtypes.h" #include "stdtypes.h"
#include "llpreprocessor.h" #include "llpreprocessor.h"
#include "llunits.h" #include "llunits.h"
@ -66,7 +65,7 @@ namespace LLTrace
: mStorageSize(0), : mStorageSize(0),
mStorage(NULL) mStorage(NULL)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
const AccumulatorBuffer& other = *getDefaultBuffer(); const AccumulatorBuffer& other = *getDefaultBuffer();
resize(sNextStorageSlot); resize(sNextStorageSlot);
for (S32 i = 0; i < sNextStorageSlot; i++) for (S32 i = 0; i < sNextStorageSlot; i++)
@ -77,7 +76,7 @@ namespace LLTrace
~AccumulatorBuffer() ~AccumulatorBuffer()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
if (isCurrent()) if (isCurrent())
{ {
LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
@ -85,14 +84,14 @@ namespace LLTrace
delete[] mStorage; delete[] mStorage;
} }
LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index)
{ {
return mStorage[index]; return mStorage[index];
} }
LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
{ {
return mStorage[index]; return mStorage[index];
} }
@ -100,7 +99,7 @@ namespace LLTrace
: mStorageSize(0), : mStorageSize(0),
mStorage(NULL) mStorage(NULL)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
resize(sNextStorageSlot); resize(sNextStorageSlot);
for (S32 i = 0; i < sNextStorageSlot; i++) for (S32 i = 0; i < sNextStorageSlot; i++)
{ {
@ -110,7 +109,7 @@ namespace LLTrace
void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type) void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
for (size_t i = 0; i < sNextStorageSlot; i++) for (size_t i = 0; i < sNextStorageSlot; i++)
{ {
@ -120,7 +119,7 @@ namespace LLTrace
void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other) void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
for (size_t i = 0; i < sNextStorageSlot; i++) for (size_t i = 0; i < sNextStorageSlot; i++)
{ {
@ -130,7 +129,7 @@ namespace LLTrace
void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL) void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
llassert(mStorageSize >= sNextStorageSlot); llassert(mStorageSize >= sNextStorageSlot);
for (size_t i = 0; i < sNextStorageSlot; i++) for (size_t i = 0; i < sNextStorageSlot; i++)
{ {
@ -140,7 +139,7 @@ namespace LLTrace
void sync(F64SecondsImplicit time_stamp) void sync(F64SecondsImplicit time_stamp)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
llassert(mStorageSize >= sNextStorageSlot); llassert(mStorageSize >= sNextStorageSlot);
for (size_t i = 0; i < sNextStorageSlot; i++) for (size_t i = 0; i < sNextStorageSlot; i++)
{ {
@ -160,13 +159,13 @@ namespace LLTrace
static void clearCurrent() static void clearCurrent()
{ {
LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
} }
// NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
size_t reserveSlot() size_t reserveSlot()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
size_t next_slot = sNextStorageSlot++; size_t next_slot = sNextStorageSlot++;
if (next_slot >= mStorageSize) if (next_slot >= mStorageSize)
{ {
@ -180,7 +179,7 @@ namespace LLTrace
void resize(size_t new_size) void resize(size_t new_size)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
if (new_size <= mStorageSize) return; if (new_size <= mStorageSize) return;
ACCUMULATOR* old_storage = mStorage; ACCUMULATOR* old_storage = mStorage;
@ -214,14 +213,14 @@ namespace LLTrace
return mStorageSize; return mStorageSize;
} }
static size_t getNumIndices() static size_t getNumIndices()
{ {
return sNextStorageSlot; return sNextStorageSlot;
} }
static self_t* getDefaultBuffer() static self_t* getDefaultBuffer()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
static bool sInitialized = false; static bool sInitialized = false;
if (!sInitialized) if (!sInitialized)
{ {
@ -336,7 +335,7 @@ namespace LLTrace
void sample(F64 value) void sample(F64 value)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
// store effect of last value // store effect of last value
@ -399,7 +398,7 @@ namespace LLTrace
F64 mMean, F64 mMean,
mSumOfSquares; mSumOfSquares;
F64SecondsImplicit F64SecondsImplicit
mLastSampleTimeStamp, mLastSampleTimeStamp,
mTotalSamplingTime; mTotalSamplingTime;
@ -409,7 +408,7 @@ namespace LLTrace
S32 mNumSamples; S32 mNumSamples;
// distinct from mNumSamples, since we might have inherited a last value from // distinct from mNumSamples, since we might have inherited a last value from
// a previous sampling period // a previous sampling period
bool mHasValue; bool mHasValue;
}; };
class CountAccumulator class CountAccumulator
@ -457,14 +456,14 @@ namespace LLTrace
class alignas(32) TimeBlockAccumulator class alignas(32) TimeBlockAccumulator
{ {
public: public:
typedef F64Seconds value_t; typedef F64Seconds value_t;
static F64Seconds getDefaultValue() { return F64Seconds(0); } static F64Seconds getDefaultValue() { return F64Seconds(0); }
typedef TimeBlockAccumulator self_t; typedef TimeBlockAccumulator self_t;
// fake classes that allows us to view different facets of underlying statistic // fake classes that allows us to view different facets of underlying statistic
struct CallCountFacet struct CallCountFacet
{ {
typedef S32 value_t; typedef S32 value_t;
}; };
@ -515,12 +514,12 @@ namespace LLTrace
BlockTimerStatHandle* getParent() { return mParent; } BlockTimerStatHandle* getParent() { return mParent; }
BlockTimerStatHandle* mBlock; BlockTimerStatHandle* mBlock;
BlockTimerStatHandle* mParent; BlockTimerStatHandle* mParent;
std::vector<BlockTimerStatHandle*> mChildren; std::vector<BlockTimerStatHandle*> mChildren;
bool mCollapsed; bool mCollapsed;
bool mNeedsSorting; bool mNeedsSorting;
}; };
struct BlockTimerStackRecord struct BlockTimerStackRecord
{ {
class BlockTimer* mActiveTimer; class BlockTimer* mActiveTimer;
@ -528,65 +527,6 @@ namespace LLTrace
U64 mChildTime; U64 mChildTime;
}; };
struct MemAccumulator
{
typedef F64Bytes value_t;
static F64Bytes getDefaultValue() { return F64Bytes(0); }
typedef MemAccumulator self_t;
// fake classes that allows us to view different facets of underlying statistic
struct AllocationFacet
{
typedef F64Bytes value_t;
static F64Bytes getDefaultValue() { return F64Bytes(0); }
};
struct DeallocationFacet
{
typedef F64Bytes value_t;
static F64Bytes getDefaultValue() { return F64Bytes(0); }
};
void addSamples(const MemAccumulator& other, EBufferAppendType append_type)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mAllocations.addSamples(other.mAllocations, append_type);
mDeallocations.addSamples(other.mDeallocations, append_type);
if (append_type == SEQUENTIAL)
{
mSize.addSamples(other.mSize, SEQUENTIAL);
}
else
{
F64 allocation_delta(other.mAllocations.getSum() - other.mDeallocations.getSum());
mSize.sample(mSize.hasValue()
? mSize.getLastValue() + allocation_delta
: allocation_delta);
}
}
void reset(const MemAccumulator* other)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mSize.reset(other ? &other->mSize : NULL);
mAllocations.reset(other ? &other->mAllocations : NULL);
mDeallocations.reset(other ? &other->mDeallocations : NULL);
}
void sync(F64SecondsImplicit time_stamp)
{
mSize.sync(time_stamp);
}
bool hasValue() const { return mSize.hasValue(); }
SampleAccumulator mSize;
EventAccumulator mAllocations;
CountAccumulator mDeallocations;
};
struct AccumulatorBufferGroup : public LLRefCount struct AccumulatorBufferGroup : public LLRefCount
{ {
AccumulatorBufferGroup(); AccumulatorBufferGroup();
@ -607,9 +547,7 @@ namespace LLTrace
AccumulatorBuffer<SampleAccumulator> mSamples; AccumulatorBuffer<SampleAccumulator> mSamples;
AccumulatorBuffer<EventAccumulator> mEvents; AccumulatorBuffer<EventAccumulator> mEvents;
AccumulatorBuffer<TimeBlockAccumulator> mStackTimers; AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
AccumulatorBuffer<MemAccumulator> mMemStats;
}; };
} }
#endif // LL_LLTRACEACCUMULATORS_H #endif // LL_LLTRACEACCUMULATORS_H

View File

@ -1,24 +1,24 @@
/** /**
* @file lltracesampler.cpp * @file lltracesampler.cpp
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc. * Copyright (C) 2012, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -32,7 +32,7 @@
#include "lltracethreadrecorder.h" #include "lltracethreadrecorder.h"
#include "llthread.h" #include "llthread.h"
inline F64 lerp(F64 a, F64 b, F64 u) inline F64 lerp(F64 a, F64 b, F64 u)
{ {
return a + ((b - a) * u); return a + ((b - a) * u);
} }
@ -40,34 +40,29 @@ inline F64 lerp(F64 a, F64 b, F64 u)
namespace LLTrace namespace LLTrace
{ {
extern MemStatHandle gTraceMemStat;
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// Recording // Recording
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
Recording::Recording(EPlayState state) Recording::Recording(EPlayState state)
: mElapsedSeconds(0), : mElapsedSeconds(0),
mActiveBuffers(NULL) mActiveBuffers(NULL)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
claim_alloc(gTraceMemStat, this);
mBuffers = new AccumulatorBufferGroup(); mBuffers = new AccumulatorBufferGroup();
claim_alloc(gTraceMemStat, mBuffers);
setPlayState(state); setPlayState(state);
} }
Recording::Recording( const Recording& other ) Recording::Recording( const Recording& other )
: mActiveBuffers(NULL) : mActiveBuffers(NULL)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
claim_alloc(gTraceMemStat, this);
*this = other; *this = other;
} }
Recording& Recording::operator = (const Recording& other) Recording& Recording::operator = (const Recording& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
// this will allow us to seamlessly start without affecting any data we've acquired from other // this will allow us to seamlessly start without affecting any data we've acquired from other
setPlayState(PAUSED); setPlayState(PAUSED);
@ -85,14 +80,11 @@ Recording& Recording::operator = (const Recording& other)
return *this; return *this;
} }
Recording::~Recording() Recording::~Recording()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
disclaim_alloc(gTraceMemStat, this);
disclaim_alloc(gTraceMemStat, mBuffers);
// allow recording destruction without thread recorder running, // allow recording destruction without thread recorder running,
// otherwise thread shutdown could crash if a recording outlives the thread recorder // otherwise thread shutdown could crash if a recording outlives the thread recorder
// besides, recording construction and destruction is fine without a recorder...just don't attempt to start one // besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
if (isStarted() && LLTrace::get_thread_recorder() != NULL) if (isStarted() && LLTrace::get_thread_recorder() != NULL)
@ -107,14 +99,14 @@ void Recording::update()
#if LL_TRACE_ENABLED #if LL_TRACE_ENABLED
if (isStarted()) if (isStarted())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
// must have // must have
llassert(mActiveBuffers != NULL llassert(mActiveBuffers != NULL
&& LLTrace::get_thread_recorder() != NULL); && LLTrace::get_thread_recorder() != NULL);
if(!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL) if (!mActiveBuffers->isCurrent() && LLTrace::get_thread_recorder() != NULL)
{ {
AccumulatorBufferGroup* buffers = mBuffers.write(); AccumulatorBufferGroup* buffers = mBuffers.write();
LLTrace::get_thread_recorder()->deactivate(buffers); LLTrace::get_thread_recorder()->deactivate(buffers);
@ -128,7 +120,7 @@ void Recording::update()
void Recording::handleReset() void Recording::handleReset()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED #if LL_TRACE_ENABLED
mBuffers.write()->reset(); mBuffers.write()->reset();
@ -139,7 +131,7 @@ void Recording::handleReset()
void Recording::handleStart() void Recording::handleStart()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED #if LL_TRACE_ENABLED
mSamplingTimer.reset(); mSamplingTimer.reset();
mBuffers.setStayUnique(true); mBuffers.setStayUnique(true);
@ -151,7 +143,7 @@ void Recording::handleStart()
void Recording::handleStop() void Recording::handleStop()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED #if LL_TRACE_ENABLED
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
// must have thread recorder running on this thread // must have thread recorder running on this thread
@ -204,7 +196,6 @@ F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>
return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond()); return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond());
} }
S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat) S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
{ {
update(); update();
@ -219,7 +210,7 @@ F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL; const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0)) return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
/ ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value())); / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
} }
@ -241,144 +232,9 @@ F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& s
return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value(); return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value();
} }
bool Recording::hasValue(const StatType<MemAccumulator>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mSize.hasValue() || (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.hasValue() : false);
}
F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(llmin(accumulator.mSize.getMin(), (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMin() : F32_MAX)));
}
F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->mSize.hasValue())
{
F32 t = 0.0f;
S32 div = accumulator.mSize.getSampleCount() + active_accumulator->mSize.getSampleCount();
if (div > 0)
{
t = active_accumulator->mSize.getSampleCount() / div;
}
return F64Bytes(lerp(accumulator.mSize.getMean(), active_accumulator->mSize.getMean(), t));
}
else
{
return F64Bytes(accumulator.mSize.getMean());
}
}
F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(llmax(accumulator.mSize.getMax(), active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMax() : F32_MIN));
}
F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator.mSize, active_accumulator->mSize);
return F64Bytes(sqrtf(sum_of_squares / (accumulator.mSize.getSamplingTime().value() + active_accumulator->mSize.getSamplingTime().value())));
}
else
{
return F64Bytes(accumulator.mSize.getStandardDeviation());
}
}
F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(active_accumulator ? active_accumulator->mSize.getLastValue() : accumulator.mSize.getLastValue());
}
bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mAllocations.hasValue() || (active_accumulator ? active_accumulator->mAllocations.hasValue() : false);
}
F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0));
}
F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes((accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)) / mElapsedSeconds.value());
}
S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mAllocations.getSampleCount() + (active_accumulator ? active_accumulator->mAllocations.getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mDeallocations.hasValue() || (active_accumulator ? active_accumulator->mDeallocations.hasValue() : false);
}
F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes(accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0));
}
F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return F64Bytes((accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)) / mElapsedSeconds.value());
}
S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
{
update();
const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
return accumulator.mDeallocations.getSampleCount() + (active_accumulator ? active_accumulator->mDeallocations.getSampleCount() : 0);
}
bool Recording::hasValue(const StatType<CountAccumulator>& stat) bool Recording::hasValue(const StatType<CountAccumulator>& stat)
{ {
update(); update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false); return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false);
@ -386,7 +242,7 @@ bool Recording::hasValue(const StatType<CountAccumulator>& stat)
F64 Recording::getSum(const StatType<CountAccumulator>& stat) F64 Recording::getSum(const StatType<CountAccumulator>& stat)
{ {
update(); update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0); return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
@ -394,7 +250,7 @@ F64 Recording::getSum(const StatType<CountAccumulator>& stat)
F64 Recording::getPerSec( const StatType<CountAccumulator>& stat ) F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
{ {
update(); update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0); F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
@ -403,7 +259,7 @@ F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat ) S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
{ {
update(); update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()]; const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL; const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0); return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
@ -411,7 +267,7 @@ S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
bool Recording::hasValue(const StatType<SampleAccumulator>& stat) bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue()); return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
@ -419,7 +275,7 @@ bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
F64 Recording::getMin( const StatType<SampleAccumulator>& stat ) F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX); return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
@ -427,7 +283,7 @@ F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
F64 Recording::getMax( const StatType<SampleAccumulator>& stat ) F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN); return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
@ -435,17 +291,17 @@ F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
F64 Recording::getMean( const StatType<SampleAccumulator>& stat ) F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue()) if (active_accumulator && active_accumulator->hasValue())
{ {
F32 t = 0.0f; F32 t = 0.0f;
S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
if (div > 0) if (div > 0)
{ {
t = active_accumulator->getSampleCount() / div; t = active_accumulator->getSampleCount() / div;
} }
return lerp(accumulator.getMean(), active_accumulator->getMean(), t); return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
} }
else else
@ -456,7 +312,7 @@ F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat ) F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
@ -473,7 +329,7 @@ F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat ) F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue()); return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue());
@ -481,7 +337,7 @@ F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat ) S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
{ {
update(); update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()]; const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0); return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0);
@ -489,7 +345,7 @@ S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
bool Recording::hasValue(const StatType<EventAccumulator>& stat) bool Recording::hasValue(const StatType<EventAccumulator>& stat)
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue()); return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
@ -497,7 +353,7 @@ bool Recording::hasValue(const StatType<EventAccumulator>& stat)
F64 Recording::getSum( const StatType<EventAccumulator>& stat) F64 Recording::getSum( const StatType<EventAccumulator>& stat)
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0)); return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0));
@ -505,7 +361,7 @@ F64 Recording::getSum( const StatType<EventAccumulator>& stat)
F64 Recording::getMin( const StatType<EventAccumulator>& stat ) F64 Recording::getMin( const StatType<EventAccumulator>& stat )
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX); return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
@ -513,7 +369,7 @@ F64 Recording::getMin( const StatType<EventAccumulator>& stat )
F64 Recording::getMax( const StatType<EventAccumulator>& stat ) F64 Recording::getMax( const StatType<EventAccumulator>& stat )
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN); return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
@ -521,17 +377,17 @@ F64 Recording::getMax( const StatType<EventAccumulator>& stat )
F64 Recording::getMean( const StatType<EventAccumulator>& stat ) F64 Recording::getMean( const StatType<EventAccumulator>& stat )
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue()) if (active_accumulator && active_accumulator->hasValue())
{ {
F32 t = 0.0f; F32 t = 0.0f;
S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
if (div > 0) if (div > 0)
{ {
t = active_accumulator->getSampleCount() / div; t = active_accumulator->getSampleCount() / div;
} }
return lerp(accumulator.getMean(), active_accumulator->getMean(), t); return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
} }
else else
@ -542,7 +398,7 @@ F64 Recording::getMean( const StatType<EventAccumulator>& stat )
F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat ) F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
@ -559,7 +415,7 @@ F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
F64 Recording::getLastValue( const StatType<EventAccumulator>& stat ) F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue(); return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue();
@ -567,7 +423,7 @@ F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat ) S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
{ {
update(); update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()]; const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0); return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
@ -577,7 +433,7 @@ S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
// PeriodicRecording // PeriodicRecording
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state) PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
: mAutoResize(num_periods == 0), : mAutoResize(num_periods == 0),
mCurPeriod(0), mCurPeriod(0),
mNumRecordedPeriods(0), mNumRecordedPeriods(0),
@ -585,15 +441,13 @@ PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
// code in several methods. // code in several methods.
mRecordingPeriods(num_periods ? num_periods : 1) mRecordingPeriods(num_periods ? num_periods : 1)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
setPlayState(state); setPlayState(state);
claim_alloc(gTraceMemStat, this);
} }
PeriodicRecording::~PeriodicRecording() PeriodicRecording::~PeriodicRecording()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
disclaim_alloc(gTraceMemStat, this);
} }
void PeriodicRecording::nextPeriod() void PeriodicRecording::nextPeriod()
@ -615,12 +469,11 @@ void PeriodicRecording::nextPeriod()
void PeriodicRecording::appendRecording(Recording& recording) void PeriodicRecording::appendRecording(Recording& recording)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().appendRecording(recording); getCurRecording().appendRecording(recording);
nextPeriod(); nextPeriod();
} }
void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
@ -693,16 +546,14 @@ F64Seconds PeriodicRecording::getDuration() const
return duration; return duration;
} }
LLTrace::Recording PeriodicRecording::snapshotCurRecording() const LLTrace::Recording PeriodicRecording::snapshotCurRecording() const
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
Recording recording_copy(getCurRecording()); Recording recording_copy(getCurRecording());
recording_copy.stop(); recording_copy.stop();
return recording_copy; return recording_copy;
} }
Recording& PeriodicRecording::getLastRecording() Recording& PeriodicRecording::getLastRecording()
{ {
return getPrevRecording(1); return getPrevRecording(1);
@ -737,19 +588,19 @@ const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const
void PeriodicRecording::handleStart() void PeriodicRecording::handleStart()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().start(); getCurRecording().start();
} }
void PeriodicRecording::handleStop() void PeriodicRecording::handleStop()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().pause(); getCurRecording().pause();
} }
void PeriodicRecording::handleReset() void PeriodicRecording::handleReset()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().stop(); getCurRecording().stop();
if (mAutoResize) if (mAutoResize)
@ -771,13 +622,13 @@ void PeriodicRecording::handleReset()
void PeriodicRecording::handleSplitTo(PeriodicRecording& other) void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().splitTo(other.getCurRecording()); getCurRecording().splitTo(other.getCurRecording());
} }
F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false; bool has_value = false;
@ -792,14 +643,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, siz
} }
} }
return has_value return has_value
? min_val ? min_val
: NaN; : NaN;
} }
F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false; bool has_value = false;
@ -814,15 +665,15 @@ F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, siz
} }
} }
return has_value return has_value
? max_val ? max_val
: NaN; : NaN;
} }
// calculates means using aggregates per period // calculates means using aggregates per period
F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 mean = 0; F64 mean = 0;
@ -838,14 +689,14 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, si
} }
} }
return valid_period_count return valid_period_count
? mean / (F64)valid_period_count ? mean / (F64)valid_period_count
: NaN; : NaN;
} }
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 period_mean = getPeriodMean(stat, num_periods); F64 period_mean = getPeriodMean(stat, num_periods);
@ -870,7 +721,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false; bool has_value = false;
@ -885,14 +736,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, si
} }
} }
return has_value return has_value
? min_val ? min_val
: NaN; : NaN;
} }
F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/) F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false; bool has_value = false;
@ -907,15 +758,15 @@ F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, siz
} }
} }
return has_value return has_value
? max_val ? max_val
: NaN; : NaN;
} }
F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
S32 valid_period_count = 0; S32 valid_period_count = 0;
@ -938,7 +789,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, s
F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
std::vector<F64> buf; std::vector<F64> buf;
@ -964,7 +815,7 @@ F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat,
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ ) F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 period_mean = getPeriodMean(stat, num_periods); F64 period_mean = getPeriodMean(stat, num_periods);
@ -987,105 +838,13 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
: NaN; : NaN;
} }
F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes min_val(std::numeric_limits<F64>::max());
for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
min_val = llmin(min_val, recording.getMin(stat));
}
return min_val;
}
F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodMin(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes max_val(0.0);
for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
max_val = llmax(max_val, recording.getMax(stat));
}
return max_val;
}
F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodMax(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes mean(0);
for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
mean += recording.getMean(stat);
}
return mean / F64(num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodMean(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64Kilobytes period_mean = getPeriodMean(stat, num_periods);
S32 valid_period_count = 0;
F64 sum_of_squares = 0;
for (size_t i = 1; i <= num_periods; i++)
{
Recording& recording = getPrevRecording(i);
if (recording.hasValue(stat))
{
F64Kilobytes delta = recording.getMean(stat) - period_mean;
sum_of_squares += delta.value() * delta.value();
valid_period_count++;
}
}
return F64Kilobytes(valid_period_count
? sqrt(sum_of_squares / (F64)valid_period_count)
: NaN);
}
F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods)
{
return getPeriodStandardDeviation(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// ExtendableRecording // ExtendableRecording
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
void ExtendableRecording::extend() void ExtendableRecording::extend()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
// push the data back to accepted recording // push the data back to accepted recording
mAcceptedRecording.appendRecording(mPotentialRecording); mAcceptedRecording.appendRecording(mPotentialRecording);
// flush data, so we can start from scratch // flush data, so we can start from scratch
@ -1094,76 +853,72 @@ void ExtendableRecording::extend()
void ExtendableRecording::handleStart() void ExtendableRecording::handleStart()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.start(); mPotentialRecording.start();
} }
void ExtendableRecording::handleStop() void ExtendableRecording::handleStop()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.pause(); mPotentialRecording.pause();
} }
void ExtendableRecording::handleReset() void ExtendableRecording::handleReset()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mAcceptedRecording.reset(); mAcceptedRecording.reset();
mPotentialRecording.reset(); mPotentialRecording.reset();
} }
void ExtendableRecording::handleSplitTo(ExtendableRecording& other) void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.splitTo(other.mPotentialRecording); mPotentialRecording.splitTo(other.mPotentialRecording);
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// ExtendablePeriodicRecording // ExtendablePeriodicRecording
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
ExtendablePeriodicRecording::ExtendablePeriodicRecording()
ExtendablePeriodicRecording::ExtendablePeriodicRecording() : mAcceptedRecording(0),
: mAcceptedRecording(0),
mPotentialRecording(0) mPotentialRecording(0)
{} {}
void ExtendablePeriodicRecording::extend() void ExtendablePeriodicRecording::extend()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
// push the data back to accepted recording // push the data back to accepted recording
mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
// flush data, so we can start from scratch // flush data, so we can start from scratch
mPotentialRecording.reset(); mPotentialRecording.reset();
} }
void ExtendablePeriodicRecording::handleStart() void ExtendablePeriodicRecording::handleStart()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.start(); mPotentialRecording.start();
} }
void ExtendablePeriodicRecording::handleStop() void ExtendablePeriodicRecording::handleStop()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.pause(); mPotentialRecording.pause();
} }
void ExtendablePeriodicRecording::handleReset() void ExtendablePeriodicRecording::handleReset()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mAcceptedRecording.reset(); mAcceptedRecording.reset();
mPotentialRecording.reset(); mPotentialRecording.reset();
} }
void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other) void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other)
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.splitTo(other.mPotentialRecording); mPotentialRecording.splitTo(other.mPotentialRecording);
} }
PeriodicRecording& get_frame_recording() PeriodicRecording& get_frame_recording()
{ {
static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED); static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED);
@ -1174,7 +929,7 @@ PeriodicRecording& get_frame_recording()
void LLStopWatchControlsMixinCommon::start() void LLStopWatchControlsMixinCommon::start()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState) switch (mPlayState)
{ {
case STOPPED: case STOPPED:
@ -1196,7 +951,7 @@ void LLStopWatchControlsMixinCommon::start()
void LLStopWatchControlsMixinCommon::stop() void LLStopWatchControlsMixinCommon::stop()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState) switch (mPlayState)
{ {
case STOPPED: case STOPPED:
@ -1216,7 +971,7 @@ void LLStopWatchControlsMixinCommon::stop()
void LLStopWatchControlsMixinCommon::pause() void LLStopWatchControlsMixinCommon::pause()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState) switch (mPlayState)
{ {
case STOPPED: case STOPPED:
@ -1236,7 +991,7 @@ void LLStopWatchControlsMixinCommon::pause()
void LLStopWatchControlsMixinCommon::unpause() void LLStopWatchControlsMixinCommon::unpause()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState) switch (mPlayState)
{ {
case STOPPED: case STOPPED:
@ -1256,7 +1011,7 @@ void LLStopWatchControlsMixinCommon::unpause()
void LLStopWatchControlsMixinCommon::resume() void LLStopWatchControlsMixinCommon::resume()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState) switch (mPlayState)
{ {
case STOPPED: case STOPPED:
@ -1277,7 +1032,7 @@ void LLStopWatchControlsMixinCommon::resume()
void LLStopWatchControlsMixinCommon::restart() void LLStopWatchControlsMixinCommon::restart()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState) switch (mPlayState)
{ {
case STOPPED: case STOPPED:
@ -1301,13 +1056,13 @@ void LLStopWatchControlsMixinCommon::restart()
void LLStopWatchControlsMixinCommon::reset() void LLStopWatchControlsMixinCommon::reset()
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
handleReset(); handleReset();
} }
void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state ) void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state )
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch(state) switch(state)
{ {
case STOPPED: case STOPPED:

View File

@ -1,25 +1,25 @@
/** /**
* @file lltracerecording.h * @file lltracerecording.h
* @brief Sampling object for collecting runtime statistics originating from lltrace. * @brief Sampling object for collecting runtime statistics originating from lltrace.
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc. * Copyright (C) 2012, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -112,7 +112,6 @@ private:
// atomically stop this object while starting the other // atomically stop this object while starting the other
// no data can be missed in between stop and start // no data can be missed in between stop and start
virtual void handleSplitTo(DERIVED& other) {}; virtual void handleSplitTo(DERIVED& other) {};
}; };
namespace LLTrace namespace LLTrace
@ -129,8 +128,6 @@ namespace LLTrace
template<typename T> template<typename T>
class EventStatHandle; class EventStatHandle;
class MemStatHandle;
template<typename T> template<typename T>
struct RelatedTypes struct RelatedTypes
{ {
@ -152,7 +149,7 @@ namespace LLTrace
typedef S32 sum_t; typedef S32 sum_t;
}; };
class Recording class Recording
: public LLStopWatchControlsMixin<Recording> : public LLStopWatchControlsMixin<Recording>
{ {
public: public:
@ -182,24 +179,6 @@ namespace LLTrace
F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
// Memory accessors
bool hasValue(const StatType<MemAccumulator>& stat);
F64Kilobytes getMin(const StatType<MemAccumulator>& stat);
F64Kilobytes getMean(const StatType<MemAccumulator>& stat);
F64Kilobytes getMax(const StatType<MemAccumulator>& stat);
F64Kilobytes getStandardDeviation(const StatType<MemAccumulator>& stat);
F64Kilobytes getLastValue(const StatType<MemAccumulator>& stat);
bool hasValue(const StatType<MemAccumulator::AllocationFacet>& stat);
F64Kilobytes getSum(const StatType<MemAccumulator::AllocationFacet>& stat);
F64Kilobytes getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat);
S32 getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat);
bool hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat);
F64Kilobytes getSum(const StatType<MemAccumulator::DeallocationFacet>& stat);
F64Kilobytes getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat);
S32 getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat);
// CountStatHandle accessors // CountStatHandle accessors
bool hasValue(const StatType<CountAccumulator>& stat); bool hasValue(const StatType<CountAccumulator>& stat);
F64 getSum(const StatType<CountAccumulator>& stat); F64 getSum(const StatType<CountAccumulator>& stat);
@ -318,7 +297,7 @@ namespace LLTrace
/*virtual*/ void handleSplitTo(Recording& other); /*virtual*/ void handleSplitTo(Recording& other);
// returns data for current thread // returns data for current thread
class ThreadRecorder* getThreadRecorder(); class ThreadRecorder* getThreadRecorder();
LLTimer mSamplingTimer; LLTimer mSamplingTimer;
F64Seconds mElapsedSeconds; F64Seconds mElapsedSeconds;
@ -335,10 +314,10 @@ namespace LLTrace
~PeriodicRecording(); ~PeriodicRecording();
void nextPeriod(); void nextPeriod();
auto getNumRecordedPeriods() auto getNumRecordedPeriods()
{ {
// current period counts if not active // current period counts if not active
return mNumRecordedPeriods + (isStarted() ? 0 : 1); return mNumRecordedPeriods + (isStarted() ? 0 : 1);
} }
F64Seconds getDuration() const; F64Seconds getDuration() const;
@ -367,7 +346,7 @@ namespace LLTrace
} }
return num_samples; return num_samples;
} }
// //
// PERIODIC MIN // PERIODIC MIN
// //
@ -376,7 +355,7 @@ namespace LLTrace
template <typename T> template <typename T>
typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false; bool has_value = false;
@ -391,15 +370,15 @@ namespace LLTrace
} }
} }
return has_value return has_value
? min_val ? min_val
: T::getDefaultValue(); : T::getDefaultValue();
} }
template<typename T> template<typename T>
T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
} }
@ -407,7 +386,7 @@ namespace LLTrace
template<typename T> template<typename T>
T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
} }
@ -415,17 +394,14 @@ namespace LLTrace
template<typename T> template<typename T>
T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
} }
F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T> template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max()); typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
@ -440,7 +416,7 @@ namespace LLTrace
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
} }
@ -452,7 +428,7 @@ namespace LLTrace
template <typename T> template <typename T>
typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false; bool has_value = false;
@ -467,15 +443,15 @@ namespace LLTrace
} }
} }
return has_value return has_value
? max_val ? max_val
: T::getDefaultValue(); : T::getDefaultValue();
} }
template<typename T> template<typename T>
T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
} }
@ -483,7 +459,7 @@ namespace LLTrace
template<typename T> template<typename T>
T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
} }
@ -491,17 +467,14 @@ namespace LLTrace
template<typename T> template<typename T>
T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
} }
F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T> template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 max_val = std::numeric_limits<F64>::min(); F64 max_val = std::numeric_limits<F64>::min();
@ -516,7 +489,7 @@ namespace LLTrace
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
} }
@ -528,7 +501,7 @@ namespace LLTrace
template <typename T> template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes<typename T::value_t>::fractional_t mean(0); typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
@ -549,14 +522,14 @@ namespace LLTrace
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
} }
F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
} }
@ -564,17 +537,14 @@ namespace LLTrace
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
} }
F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template <typename T> template <typename T>
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods()); num_periods = llmin(num_periods, getNumRecordedPeriods());
typename RelatedTypes<typename T::value_t>::fractional_t mean = 0; typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
@ -596,7 +566,7 @@ namespace LLTrace
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
} }
@ -635,10 +605,10 @@ namespace LLTrace
F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max()); F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
} }
@ -646,13 +616,10 @@ namespace LLTrace
template<typename T> template<typename T>
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max()) typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
{ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods)); return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
} }
F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
private: private:
// implementation for LLStopWatchControlsMixin // implementation for LLStopWatchControlsMixin
/*virtual*/ void handleStart(); /*virtual*/ void handleStart();
@ -731,7 +698,7 @@ namespace LLTrace
PeriodicRecording& getResults() { return mAcceptedRecording; } PeriodicRecording& getResults() { return mAcceptedRecording; }
const PeriodicRecording& getResults() const {return mAcceptedRecording;} const PeriodicRecording& getResults() const {return mAcceptedRecording;}
void nextPeriod() { mPotentialRecording.nextPeriod(); } void nextPeriod() { mPotentialRecording.nextPeriod(); }
private: private:

View File

@ -32,7 +32,7 @@
namespace LLTrace namespace LLTrace
{ {
extern MemStatHandle gTraceMemStat; //extern MemStatHandle gTraceMemStat;
static ThreadRecorder* sMasterThreadRecorder = NULL; static ThreadRecorder* sMasterThreadRecorder = NULL;
@ -81,9 +81,9 @@ void ThreadRecorder::init()
BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1; BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
claim_alloc(gTraceMemStat, this); //claim_alloc(gTraceMemStat, this);
claim_alloc(gTraceMemStat, mRootTimer); //claim_alloc(gTraceMemStat, mRootTimer);
claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); //claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
#endif #endif
} }
@ -101,9 +101,9 @@ ThreadRecorder::~ThreadRecorder()
#if LL_TRACE_ENABLED #if LL_TRACE_ENABLED
LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL); LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
disclaim_alloc(gTraceMemStat, this); //disclaim_alloc(gTraceMemStat, this);
disclaim_alloc(gTraceMemStat, sizeof(BlockTimer)); //disclaim_alloc(gTraceMemStat, sizeof(BlockTimer));
disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); //disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
deactivate(&mThreadRecordingBuffers); deactivate(&mThreadRecordingBuffers);

View File

@ -46,11 +46,12 @@ namespace tut
// the real time required for each push() call. Explicitly increment // the real time required for each push() call. Explicitly increment
// the timestamp for each one -- but since we're passing explicit // the timestamp for each one -- but since we're passing explicit
// timestamps, make the queue reorder them. // timestamps, make the queue reorder them.
queue.push(Queue::TimeTuple(Queue::Clock::now() + 200ms, "ghi")); auto now{ Queue::Clock::now() };
queue.push(Queue::TimeTuple(now + 200ms, "ghi"));
// Given the various push() overloads, you have to match the type // Given the various push() overloads, you have to match the type
// exactly: conversions are ambiguous. // exactly: conversions are ambiguous.
queue.push("abc"s); queue.push("abc"s);
queue.push(Queue::Clock::now() + 100ms, "def"); queue.push(now + 100ms, "def");
queue.close(); queue.close();
auto entry = queue.pop(); auto entry = queue.pop();
ensure_equals("failed to pop first", std::get<0>(entry), "abc"s); ensure_equals("failed to pop first", std::get<0>(entry), "abc"s);

View File

@ -50,6 +50,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec)
if (file_size == 0) if (file_size == 0)
{ {
mWarning = "texture_load_empty_file";
setLastError("File is empty",src_filename); setLastError("File is empty",src_filename);
return false; return false;
} }
@ -90,6 +91,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp()
if (signature[0] != 'B' || signature[1] != 'M') if (signature[0] != 'B' || signature[1] != 'M')
{ {
LL_WARNS() << "Not a BMP" << LL_ENDL; LL_WARNS() << "Not a BMP" << LL_ENDL;
mWarning = "texture_load_format_error";
return false; return false;
} }
@ -140,6 +142,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng()
if (memcmp(signature, png_magic, PNG_MAGIC_SIZE) != 0) if (memcmp(signature, png_magic, PNG_MAGIC_SIZE) != 0)
{ {
LL_WARNS() << "Not a PNG" << LL_ENDL; LL_WARNS() << "Not a PNG" << LL_ENDL;
mWarning = "texture_load_format_error";
return false; return false;
} }
@ -183,6 +186,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0) if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0)
{ {
LL_WARNS() << "Not a JPEG" << LL_ENDL; LL_WARNS() << "Not a JPEG" << LL_ENDL;
mWarning = "texture_load_format_error";
return false; return false;
} }
fseek(fp, 0, SEEK_SET); // go back to start of the file fseek(fp, 0, SEEK_SET); // go back to start of the file

View File

@ -55,6 +55,12 @@ public:
{ {
return mLastError; return mLastError;
} }
const std::string& getWarningName()
{
return mWarning;
}
protected: protected:
void clean() void clean()
@ -129,6 +135,7 @@ protected:
std::string mSrcFilename; std::string mSrcFilename;
std::string mLastError; std::string mLastError;
std::string mWarning;
U8* mData; U8* mData;

View File

@ -1040,7 +1040,12 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
weight_map::iterator iterPos = mSkinWeights.begin(); weight_map::iterator iterPos = mSkinWeights.begin();
weight_map::iterator iterEnd = mSkinWeights.end(); weight_map::iterator iterEnd = mSkinWeights.end();
llassert(!mSkinWeights.empty()); if (mSkinWeights.empty())
{
// function calls iter->second on all return paths
// everything that calls this function should precheck that there is data.
LL_ERRS() << "called getJointInfluences with empty weights list" << LL_ENDL;
}
for ( ; iterPos!=iterEnd; ++iterPos ) for ( ; iterPos!=iterEnd; ++iterPos )
{ {
@ -1067,11 +1072,16 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
const F32 epsilon = 1e-5f; const F32 epsilon = 1e-5f;
weight_map::iterator iter_up = mSkinWeights.lower_bound(pos); weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
weight_map::iterator iter_down = iter_up; weight_map::iterator iter_down = iter_up;
if (iter_up != mSkinWeights.end()) weight_map::iterator best = iter_up;
{ if (iter_up != mSkinWeights.end())
iter_down = ++iter_up; {
} iter_down = ++iter_up;
weight_map::iterator best = iter_up; }
else
{
// Assumes that there is at least one element
--best;
}
F32 min_dist = (iter->first - pos).magVec(); F32 min_dist = (iter->first - pos).magVec();

View File

@ -126,12 +126,12 @@ public:
void setSelected(bool is_selected); void setSelected(bool is_selected);
bool getCollapsible() {return mCollapsible;}; bool getCollapsible() { return mCollapsible; };
void setCollapsible(bool collapsible) {mCollapsible = collapsible;}; void setCollapsible(bool collapsible) { mCollapsible = collapsible; };
void changeOpenClose(bool is_open); void changeOpenClose(bool is_open);
void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;}; void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; };
bool canOpenClose() const { return mCanOpenClose; }; bool canOpenClose() const { return mCanOpenClose; };
virtual BOOL postBuild(); virtual BOOL postBuild();
@ -142,8 +142,8 @@ public:
void draw(); void draw();
void storeOpenCloseState (); void storeOpenCloseState();
void restoreOpenCloseState (); void restoreOpenCloseState();
protected: protected:
LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&); LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&);

View File

@ -288,7 +288,7 @@ void LLContainerView::setLabel(const std::string& label)
mLabel = label; mLabel = label;
} }
void LLContainerView::setDisplayChildren(const BOOL displayChildren) void LLContainerView::setDisplayChildren(BOOL displayChildren)
{ {
mDisplayChildren = displayChildren; mDisplayChildren = displayChildren;
for (child_list_const_iter_t child_iter = getChildList()->begin(); for (child_list_const_iter_t child_iter = getChildList()->begin();

View File

@ -78,7 +78,7 @@ public:
void setLabel(const std::string& label); void setLabel(const std::string& label);
void showLabel(BOOL show) { mShowLabel = show; } void showLabel(BOOL show) { mShowLabel = show; }
void setDisplayChildren(const BOOL displayChildren); void setDisplayChildren(BOOL displayChildren);
BOOL getDisplayChildren() { return mDisplayChildren; } BOOL getDisplayChildren() { return mDisplayChildren; }
void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;}

View File

@ -1361,26 +1361,28 @@ void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show)
mForceShowingUnmatchedItems = show; mForceShowingUnmatchedItems = show;
} }
void LLFlatListViewEx::setFilterSubString(const std::string& filter_str) void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent)
{ {
if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString)) if (0 != LLStringUtil::compareInsensitive(filter_str, mFilterSubString))
{ {
mFilterSubString = filter_str; mFilterSubString = filter_str;
updateNoItemsMessage(mFilterSubString); updateNoItemsMessage(mFilterSubString);
filterItems(); filterItems(false, notify_parent);
} }
} }
void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action) bool LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
{ {
if (!item) return; if (!item)
return false;
BOOL visible = TRUE;
// 0 signifies that filter is matched, // 0 signifies that filter is matched,
// i.e. we don't hide items that don't support 'match_filter' action, separators etc. // i.e. we don't hide items that don't support 'match_filter' action, separators etc.
if (0 == item->notify(action)) if (0 == item->notify(action))
{ {
mHasMatchedItems = true; mHasMatchedItems = true;
item->setVisible(true);
} }
else else
{ {
@ -1388,34 +1390,45 @@ void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
if (!mForceShowingUnmatchedItems) if (!mForceShowingUnmatchedItems)
{ {
selectItem(item, false); selectItem(item, false);
visible = FALSE;
} }
item->setVisible(mForceShowingUnmatchedItems);
} }
if (item->getVisible() != visible)
{
item->setVisible(visible);
return true;
}
return false;
} }
void LLFlatListViewEx::filterItems() void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)
{ {
typedef std::vector <LLPanel*> item_panel_list_t;
std::string cur_filter = mFilterSubString; std::string cur_filter = mFilterSubString;
LLStringUtil::toUpper(cur_filter); LLStringUtil::toUpper(cur_filter);
LLSD action; LLSD action;
action.with("match_filter", cur_filter); action.with("match_filter", cur_filter);
item_panel_list_t items;
getItems(items);
mHasMatchedItems = false; mHasMatchedItems = false;
item_panel_list_t::iterator iter = items.begin(), iter_end = items.end(); bool visibility_changed = false;
while (iter < iter_end) pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end();
while (iter != iter_end)
{ {
LLPanel* pItem = *(iter++); LLPanel* pItem = (*(iter++))->first;
updateItemVisibility(pItem, action); visibility_changed |= updateItemVisibility(pItem, action);
} }
sort(); if (re_sort)
notifyParentItemsRectChanged(); {
sort();
}
if (visibility_changed && notify_parent)
{
notifyParentItemsRectChanged();
}
} }
bool LLFlatListViewEx::hasMatchedItems() bool LLFlatListViewEx::hasMatchedItems()

View File

@ -300,6 +300,7 @@ public:
virtual S32 notify(const LLSD& info) ; virtual S32 notify(const LLSD& info) ;
virtual ~LLFlatListView(); virtual ~LLFlatListView();
protected: protected:
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
@ -375,7 +376,9 @@ protected:
LLRect getLastSelectedItemRect(); LLRect getLastSelectedItemRect();
void ensureSelectedVisible(); void ensureSelectedVisible();
const pairs_list_t& getItemPairs() { return mItemPairs; }
private: private:
@ -482,14 +485,14 @@ public:
/** /**
* Sets up new filter string and filters the list. * Sets up new filter string and filters the list.
*/ */
void setFilterSubString(const std::string& filter_str); void setFilterSubString(const std::string& filter_str, bool notify_parent);
std::string getFilterSubString() { return mFilterSubString; } std::string getFilterSubString() { return mFilterSubString; }
/** /**
* Filters the list, rearranges and notifies parent about shape changes. * Filters the list, rearranges and notifies parent about shape changes.
* Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration. * Derived classes may want to overload rearrangeItems() to exclude repeated separators after filtration.
*/ */
void filterItems(); void filterItems(bool re_sort, bool notify_parent);
/** /**
* Returns true if last call of filterItems() found at least one matching item * Returns true if last call of filterItems() found at least one matching item
@ -513,7 +516,7 @@ protected:
* @param item - item we are changing * @param item - item we are changing
* @param item - action - parameters to determin visibility from * @param item - action - parameters to determin visibility from
*/ */
void updateItemVisibility(LLPanel* item, const LLSD &action); bool updateItemVisibility(LLPanel* item, const LLSD &action);
private: private:
std::string mNoFilteredItemsMsg; std::string mNoFilteredItemsMsg;

View File

@ -187,14 +187,18 @@ LLFolderViewItem::~LLFolderViewItem()
BOOL LLFolderViewItem::postBuild() BOOL LLFolderViewItem::postBuild()
{ {
LLFolderViewModelItem& vmi = *getViewModelItem(); LLFolderViewModelItem* vmi = getViewModelItem();
// getDisplayName() is expensive (due to internal getLabelSuffix() and name building) llassert(vmi); // not supposed to happen, if happens, find out why and fix
// it also sets search strings so it requires a filter reset if (vmi)
mLabel = vmi.getDisplayName(); {
setToolTip(vmi.getName()); // getDisplayName() is expensive (due to internal getLabelSuffix() and name building)
// it also sets search strings so it requires a filter reset
mLabel = vmi->getDisplayName();
setToolTip(vmi->getName());
// Dirty the filter flag of the model from the view (CHUI-849) // Dirty the filter flag of the model from the view (CHUI-849)
vmi.dirtyFilter(); vmi->dirtyFilter();
}
// Don't do full refresh on constructor if it is possible to avoid // Don't do full refresh on constructor if it is possible to avoid
// it significantly slows down bulk view creation. // it significantly slows down bulk view creation.

View File

@ -479,7 +479,7 @@ LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring");
// Walk through a string, applying the rules specified by the keyword token list and // Walk through a string, applying the rules specified by the keyword token list and
// create a list of color segments. // create a list of color segments.
void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLWString& wtext, const LLColor4 &defaultColor, LLTextEditor& editor) void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLWString& wtext, LLTextEditor& editor, LLStyleConstSP style)
{ {
LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING); LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING);
seg_list->clear(); seg_list->clear();
@ -491,7 +491,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 text_len = wtext.size() + 1; S32 text_len = wtext.size() + 1;
seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) ); seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) );
const llwchar* base = wtext.c_str(); const llwchar* base = wtext.c_str();
const llwchar* cur = base; const llwchar* cur = base;
@ -501,9 +501,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
{ {
if( *cur == '\n' ) if( *cur == '\n' )
{ {
LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(cur-base); LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, cur-base);
text_segment->setToken( 0 ); text_segment->setToken( 0 );
insertSegment( *seg_list, text_segment, text_len, defaultColor, editor); insertSegment( *seg_list, text_segment, text_len, style, editor);
cur++; cur++;
if( !*cur || *cur == '\n' ) if( !*cur || *cur == '\n' )
{ {
@ -541,7 +541,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_end = cur - base; S32 seg_end = cur - base;
//create segments from seg_start to seg_end //create segments from seg_start to seg_end
insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor);
line_done = TRUE; // to break out of second loop. line_done = TRUE; // to break out of second loop.
break; break;
} }
@ -648,7 +648,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead();
} }
insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor); insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, style, editor);
/* /*
LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor );
text_segment->setToken( cur_delimiter ); text_segment->setToken( cur_delimiter );
@ -682,7 +682,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
// LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL; // LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL;
insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor);
} }
cur += seg_len; cur += seg_len;
continue; continue;
@ -697,30 +697,32 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
} }
} }
void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor ) void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, LLStyleConstSP style, LLTextEditor& editor )
{ {
std::string::size_type pos = wtext.find('\n',seg_start); std::string::size_type pos = wtext.find('\n',seg_start);
LLStyleConstSP cur_token_style = new LLStyle(LLStyle::Params().font(style->getFont()).color(cur_token->getColor()));
while (pos!=-1 && pos < (std::string::size_type)seg_end) while (pos!=-1 && pos < (std::string::size_type)seg_end)
{ {
if (pos!=seg_start) if (pos!=seg_start)
{ {
LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, pos, editor ); LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, pos, editor);
text_segment->setToken( cur_token ); text_segment->setToken( cur_token );
insertSegment( seg_list, text_segment, text_len, defaultColor, editor); insertSegment( seg_list, text_segment, text_len, style, editor);
} }
LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(pos); LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, pos);
text_segment->setToken( cur_token ); text_segment->setToken( cur_token );
insertSegment( seg_list, text_segment, text_len, defaultColor, editor); insertSegment( seg_list, text_segment, text_len, style, editor);
seg_start = pos+1; seg_start = pos+1;
pos = wtext.find('\n',seg_start); pos = wtext.find('\n',seg_start);
} }
LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, seg_end, editor);
text_segment->setToken( cur_token ); text_segment->setToken( cur_token );
insertSegment( seg_list, text_segment, text_len, defaultColor, editor); insertSegment( seg_list, text_segment, text_len, style, editor);
} }
void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor )
@ -744,6 +746,27 @@ void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSe
} }
} }
void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor )
{
LLTextSegmentPtr last = seg_list.back();
S32 new_seg_end = new_segment->getEnd();
if( new_segment->getStart() == last->getStart() )
{
seg_list.pop_back();
}
else
{
last->setEnd( new_segment->getStart() );
}
seg_list.push_back( new_segment );
if( new_seg_end < text_len )
{
seg_list.push_back( new LLNormalTextSegment( style, new_seg_end, text_len, editor ) );
}
}
#ifdef _DEBUG #ifdef _DEBUG
void LLKeywords::dump() void LLKeywords::dump()
{ {

View File

@ -29,6 +29,7 @@
#include "lldir.h" #include "lldir.h"
#include "llstyle.h"
#include "llstring.h" #include "llstring.h"
#include "v3color.h" #include "v3color.h"
#include "v4color.h" #include "v4color.h"
@ -115,8 +116,8 @@ public:
void findSegments(std::vector<LLTextSegmentPtr> *seg_list, void findSegments(std::vector<LLTextSegmentPtr> *seg_list,
const LLWString& text, const LLWString& text,
const LLColor4 &defaultColor, class LLTextEditor& editor,
class LLTextEditor& editor); LLStyleConstSP style);
void initialize(LLSD SyntaxXML); void initialize(LLSD SyntaxXML);
void processTokens(); void processTokens();
@ -181,9 +182,11 @@ protected:
S32 text_len, S32 text_len,
S32 seg_start, S32 seg_start,
S32 seg_end, S32 seg_end,
const LLColor4 &defaultColor, LLStyleConstSP style,
LLTextEditor& editor); LLTextEditor& editor);
void insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor );
bool mLoaded; bool mLoaded;
LLSD mSyntax; LLSD mSyntax;
word_token_map_t mWordTokenMap; word_token_map_t mWordTokenMap;

View File

@ -1783,7 +1783,8 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
mNeedsArrange(FALSE), mNeedsArrange(FALSE),
mAlwaysShowMenu(FALSE), mAlwaysShowMenu(FALSE),
mResetScrollPositionOnShow(true), mResetScrollPositionOnShow(true),
mShortcutPad(p.shortcut_pad) mShortcutPad(p.shortcut_pad),
mFont(p.font)
{ {
typedef boost::tokenizer<boost::char_separator<char> > tokenizer; typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("_"); boost::char_separator<char> sep("_");
@ -3642,6 +3643,7 @@ BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu )
p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor");
p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor");
p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor");
p.font = menu->getFont();
LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create<LLMenuItemBranchDownGL>(p); LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create<LLMenuItemBranchDownGL>(p);
success &= branch->addToAcceleratorList(&mAccelerators); success &= branch->addToAcceleratorList(&mAccelerators);

View File

@ -562,7 +562,9 @@ public:
// add a context menu branch // add a context menu branch
BOOL appendContextSubMenu(LLMenuGL *menu); BOOL appendContextSubMenu(LLMenuGL *menu);
protected: const LLFontGL *getFont() const { return mFont; }
protected:
void createSpilloverBranch(); void createSpilloverBranch();
void cleanupSpilloverBranch(); void cleanupSpilloverBranch();
// Add the menu item to this menu. // Add the menu item to this menu.
@ -594,6 +596,9 @@ protected:
BOOL mKeepFixedSize; BOOL mKeepFixedSize;
BOOL mNeedsArrange; BOOL mNeedsArrange;
// Font for top menu items only
const LLFontGL* mFont;
private: private:

View File

@ -181,7 +181,7 @@ LLStatBar::LLStatBar(const Params& p)
mTargetMinBar(llmin(p.bar_min, p.bar_max)), mTargetMinBar(llmin(p.bar_min, p.bar_max)),
mTargetMaxBar(llmax(p.bar_max, p.bar_min)), mTargetMaxBar(llmax(p.bar_max, p.bar_min)),
mCurMaxBar(p.bar_max), mCurMaxBar(p.bar_max),
mCurMinBar(0), mCurMinBar(0),
mDecimalDigits(p.decimal_digits), mDecimalDigits(p.decimal_digits),
mNumHistoryFrames(p.num_frames), mNumHistoryFrames(p.num_frames),
mNumShortHistoryFrames(p.num_frames_short), mNumShortHistoryFrames(p.num_frames_short),
@ -222,9 +222,6 @@ BOOL LLStatBar::handleHover(S32 x, S32 y, MASK mask)
case STAT_SAMPLE: case STAT_SAMPLE:
LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.sampleStatp->getDescription()).sticky_rect(calcScreenRect())); LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.sampleStatp->getDescription()).sticky_rect(calcScreenRect()));
break; break;
case STAT_MEM:
LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.memStatp->getDescription()).sticky_rect(calcScreenRect()));
break;
default: default:
break; break;
} }
@ -373,18 +370,6 @@ void LLStatBar::draw()
} }
} }
break; break;
case STAT_MEM:
{
const LLTrace::StatType<LLTrace::MemAccumulator>& mem_stat = *mStat.memStatp;
unit_label = mUnitLabel.empty() ? mem_stat.getUnitLabel() : mUnitLabel;
current = last_frame_recording.getLastValue(mem_stat).value();
min = frame_recording.getPeriodMin(mem_stat, num_frames).value();
max = frame_recording.getPeriodMax(mem_stat, num_frames).value();
mean = frame_recording.getPeriodMean(mem_stat, num_frames).value();
display_value = current;
}
break;
default: default:
break; break;
} }
@ -500,11 +485,6 @@ void LLStatBar::draw()
max_value = recording.getMax(*mStat.sampleStatp); max_value = recording.getMax(*mStat.sampleStatp);
num_samples = recording.getSampleCount(*mStat.sampleStatp); num_samples = recording.getSampleCount(*mStat.sampleStatp);
break; break;
case STAT_MEM:
min_value = recording.getMin(*mStat.memStatp).value();
max_value = recording.getMax(*mStat.memStatp).value();
num_samples = 1;
break;
default: default:
break; break;
} }
@ -583,14 +563,8 @@ void LLStatBar::setStat(const std::string& stat_name)
mStat.sampleStatp = sample_stat.get(); mStat.sampleStatp = sample_stat.get();
mStatType = STAT_SAMPLE; mStatType = STAT_SAMPLE;
} }
else if (auto mem_stat = StatType<MemAccumulator>::getInstance(stat_name))
{
mStat.memStatp = mem_stat.get();
mStatType = STAT_MEM;
}
} }
void LLStatBar::setRange(F32 bar_min, F32 bar_max) void LLStatBar::setRange(F32 bar_min, F32 bar_max)
{ {
mTargetMinBar = llmin(bar_min, bar_max); mTargetMinBar = llmin(bar_min, bar_max);

View File

@ -95,17 +95,15 @@ private:
STAT_NONE, STAT_NONE,
STAT_COUNT, STAT_COUNT,
STAT_EVENT, STAT_EVENT,
STAT_SAMPLE, STAT_SAMPLE
STAT_MEM
} mStatType; } mStatType;
union union
{ {
void* valid; void* valid;
const LLTrace::StatType<LLTrace::CountAccumulator>* countStatp; const LLTrace::StatType<LLTrace::CountAccumulator>* countStatp;
const LLTrace::StatType<LLTrace::EventAccumulator>* eventStatp; const LLTrace::StatType<LLTrace::EventAccumulator>* eventStatp;
const LLTrace::StatType<LLTrace::SampleAccumulator>* sampleStatp; const LLTrace::StatType<LLTrace::SampleAccumulator>* sampleStatp;
const LLTrace::StatType<LLTrace::MemAccumulator>* memStatp;
} mStat; } mStat;
LLUIString mLabel; LLUIString mLabel;

View File

@ -58,10 +58,7 @@ LLStatView::~LLStatView()
} }
} }
static StatViewRegistry::Register<LLStatBar> r1("stat_bar"); static StatViewRegistry::Register<LLStatBar> r1("stat_bar");
static StatViewRegistry::Register<LLStatView> r2("stat_view"); static StatViewRegistry::Register<LLStatView> r2("stat_view");
// stat_view can be a child of panels/etc. // stat_view can be a child of panels/etc.
static LLDefaultChildRegistry::Register<LLStatView> r3("stat_view"); static LLDefaultChildRegistry::Register<LLStatView> r3("stat_view");

View File

@ -63,7 +63,7 @@ protected:
friend class LLUICtrlFactory; friend class LLUICtrlFactory;
protected: protected:
std::string mSetting; const std::string mSetting;
}; };
#endif // LL_STATVIEW_ #endif // LL_STATVIEW_

View File

@ -1516,25 +1516,23 @@ BOOL LLTabContainer::selectTab(S32 which)
LLTabTuple* selected_tuple = getTab(which); LLTabTuple* selected_tuple = getTab(which);
if (!selected_tuple) if (!selected_tuple)
{
return FALSE; return FALSE;
}
LLSD cbdata; LLSD cbdata;
if (selected_tuple->mTabPanel) if (selected_tuple->mTabPanel)
cbdata = selected_tuple->mTabPanel->getName(); cbdata = selected_tuple->mTabPanel->getName();
BOOL res = FALSE; BOOL result = FALSE;
if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) ) if (!mValidateSignal || (*mValidateSignal)(this, cbdata))
{ {
res = setTab(which); result = setTab(which);
if (res && mCommitSignal) if (result && mCommitSignal)
{ {
(*mCommitSignal)(this, cbdata); (*mCommitSignal)(this, cbdata);
} }
} }
return res; return result;
} }
// private // private

View File

@ -1550,7 +1550,13 @@ S32 LLTextBase::getLeftOffset(S32 width)
case LLFontGL::HCENTER: case LLFontGL::HCENTER:
return mHPad + llmax(0, (mVisibleTextRect.getWidth() - width - mHPad) / 2); return mHPad + llmax(0, (mVisibleTextRect.getWidth() - width - mHPad) / 2);
case LLFontGL::RIGHT: case LLFontGL::RIGHT:
return mVisibleTextRect.getWidth() - width; {
// Font's rendering rounds string size, if value gets rounded
// down last symbol might not have enough space to render,
// compensate by adding an extra pixel as padding
const S32 right_padding = 1;
return llmax(mHPad, mVisibleTextRect.getWidth() - width - right_padding);
}
default: default:
return mHPad; return mHPad;
} }
@ -3431,7 +3437,7 @@ BOOL LLNormalTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
if (mToken && !mToken->getToolTip().empty()) if (mToken && !mToken->getToolTip().empty())
{ {
const LLWString& wmsg = mToken->getToolTip(); const LLWString& wmsg = mToken->getToolTip();
LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg)); LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg), (mToken->getType() == LLKeywordToken::TT_FUNCTION));
return TRUE; return TRUE;
} }
// or do we have an explicitly set tooltip (e.g., for Urls) // or do we have an explicitly set tooltip (e.g., for Urls)

View File

@ -1779,7 +1779,8 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
else else
{ {
if (mEnableTooltipPaste && if (mEnableTooltipPaste &&
LLToolTipMgr::instance().toolTipVisible() && LLToolTipMgr::instance().toolTipVisible() &&
LLToolTipMgr::instance().isTooltipPastable() &&
KEY_TAB == key) KEY_TAB == key)
{ // Paste the first line of a tooltip into the editor { // Paste the first line of a tooltip into the editor
std::string message; std::string message;

View File

@ -154,7 +154,8 @@ LLToolTip::Params::Params()
text_color("text_color"), text_color("text_color"),
time_based_media("time_based_media", false), time_based_media("time_based_media", false),
web_based_media("web_based_media", false), web_based_media("web_based_media", false),
media_playing("media_playing", false) media_playing("media_playing", false),
allow_paste_tooltip("allow_paste_tooltip", false)
{ {
changeDefault(chrome, true); changeDefault(chrome, true);
} }
@ -167,7 +168,8 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
mTextBox(NULL), mTextBox(NULL),
mInfoButton(NULL), mInfoButton(NULL),
mPlayMediaButton(NULL), mPlayMediaButton(NULL),
mHomePageButton(NULL) mHomePageButton(NULL),
mIsTooltipPastable(p.allow_paste_tooltip)
{ {
LLTextBox::Params params; LLTextBox::Params params;
params.name = params.initial_value().asString(); params.name = params.initial_value().asString();
@ -289,6 +291,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
mTextBox->setText(p.message()); mTextBox->setText(p.message());
} }
mIsTooltipPastable = p.allow_paste_tooltip;
updateTextBox(); updateTextBox();
snapToChildren(); snapToChildren();
} }
@ -483,9 +487,9 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params)
} }
void LLToolTipMgr::show(const std::string& msg) void LLToolTipMgr::show(const std::string& msg, bool allow_paste_tooltip)
{ {
show(LLToolTip::Params().message(msg)); show(LLToolTip::Params().message(msg).allow_paste_tooltip(allow_paste_tooltip));
} }
void LLToolTipMgr::show(const LLToolTip::Params& params) void LLToolTipMgr::show(const LLToolTip::Params& params)
@ -626,5 +630,13 @@ void LLToolTipMgr::getToolTipMessage(std::string & message)
} }
} }
bool LLToolTipMgr::isTooltipPastable()
{
if (toolTipVisible())
{
return mToolTip->isTooltipPastable();
}
return false;
}
// EOF // EOF

View File

@ -94,6 +94,8 @@ public:
padding; padding;
Optional<bool> wrap; Optional<bool> wrap;
Optional<bool> allow_paste_tooltip;
Params(); Params();
}; };
/*virtual*/ void draw(); /*virtual*/ void draw();
@ -109,6 +111,7 @@ public:
virtual void initFromParams(const LLToolTip::Params& params); virtual void initFromParams(const LLToolTip::Params& params);
void getToolTipMessage(std::string & message); void getToolTipMessage(std::string & message);
bool isTooltipPastable() { return mIsTooltipPastable; }
protected: protected:
void updateTextBox(); void updateTextBox();
@ -125,6 +128,8 @@ protected:
bool mHasClickCallback; bool mHasClickCallback;
S32 mPadding; // pixels S32 mPadding; // pixels
S32 mMaxWidth; S32 mMaxWidth;
bool mIsTooltipPastable;
}; };
// used for the inspector tooltips which need different background images etc. // used for the inspector tooltips which need different background images etc.
@ -142,7 +147,7 @@ class LLToolTipMgr : public LLSingleton<LLToolTipMgr>
public: public:
void show(const LLToolTip::Params& params); void show(const LLToolTip::Params& params);
void show(const std::string& message); void show(const std::string& message, bool allow_paste_tooltip = false);
void unblockToolTips(); void unblockToolTips();
void blockToolTips(); void blockToolTips();
@ -154,6 +159,7 @@ public:
void updateToolTipVisibility(); void updateToolTipVisibility();
void getToolTipMessage(std::string & message); void getToolTipMessage(std::string & message);
bool isTooltipPastable();
private: private:
void createToolTip(const LLToolTip::Params& params); void createToolTip(const LLToolTip::Params& params);

View File

@ -5420,6 +5420,17 @@
<key>Value</key> <key>Value</key>
<string>http://wiki.secondlife.com/wiki/[LSL_STRING]</string> <string>http://wiki.secondlife.com/wiki/[LSL_STRING]</string>
</map> </map>
<key>LSLFontSizeName</key>
<map>
<key>Comment</key>
<string>Text font size in LSL editor</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>Monospace</string>
</map>
<key>GridStatusRSS</key> <key>GridStatusRSS</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -7496,10 +7507,21 @@
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>OpenDebugStatBasic</key>
<map>
<key>Comment</key>
<string>Expand Basic performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatAdvanced</key> <key>OpenDebugStatAdvanced</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Expand advanced performance stats display</string> <string>Expand Advanced performance stats display</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@ -7507,43 +7529,10 @@
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>OpenDebugStatBasic</key>
<map>
<key>Comment</key>
<string>Expand basic performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatNet</key>
<map>
<key>Comment</key>
<string>Expand network stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatRender</key> <key>OpenDebugStatRender</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Expand render stats display</string> <string>Expand Render performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatSim</key>
<map>
<key>Comment</key>
<string>Expand simulator performance stats display</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@ -7562,6 +7551,39 @@
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>OpenDebugStatMemory</key>
<map>
<key>Comment</key>
<string>Expand Memory Usage stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatNet</key>
<map>
<key>Comment</key>
<string>Expand Network performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatSim</key>
<map>
<key>Comment</key>
<string>Expand Simulator performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>OpenDebugStatPhysicsDetails</key> <key>OpenDebugStatPhysicsDetails</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -7573,6 +7595,17 @@
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>OpenDebugStatPathfinding</key>
<map>
<key>Comment</key>
<string>Expand Pathfinding performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>OpenDebugStatSimTime</key> <key>OpenDebugStatSimTime</key>
<map> <map>
<key>Comment</key> <key>Comment</key>

View File

@ -100,6 +100,12 @@ const F32 GROUND_TO_AIR_CAMERA_TRANSITION_START_TIME = 0.5f;
const F32 OBJECT_EXTENTS_PADDING = 0.5f; const F32 OBJECT_EXTENTS_PADDING = 0.5f;
static bool isDisableCameraConstraints()
{
static LLCachedControl<bool> sDisableCameraConstraints(gSavedSettings, "DisableCameraConstraints", false);
return sDisableCameraConstraints;
}
// The agent instance. // The agent instance.
LLAgentCamera gAgentCamera; LLAgentCamera gAgentCamera;
@ -570,9 +576,9 @@ BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance)
{ {
BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars)
if (!mFocusObject || mFocusObject->isDead() || if (!mFocusObject || mFocusObject->isDead() ||
mFocusObject->isMesh() || mFocusObject->isMesh() ||
gSavedSettings.getBOOL("DisableCameraConstraints")) isDisableCameraConstraints())
{ {
obj_min_distance = 0.f; obj_min_distance = 0.f;
return TRUE; return TRUE;
@ -742,39 +748,44 @@ F32 LLAgentCamera::getCameraZoomFraction(bool get_third_person)
// already [0,1] // already [0,1]
return mHUDTargetZoom; return mHUDTargetZoom;
} }
else if (get_third_person || (mFocusOnAvatar && cameraThirdPerson()))
if (isDisableCameraConstraints())
{
return mCameraZoomFraction;
}
if (get_third_person || (mFocusOnAvatar && cameraThirdPerson()))
{ {
return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f); return clamp_rescale(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION, 1.f, 0.f);
} }
else if (cameraCustomizeAvatar())
if (cameraCustomizeAvatar())
{ {
F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f ); return clamp_rescale(distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM, 1.f, 0.f );
} }
else
{
F32 min_zoom;
F32 max_zoom = getCameraMaxZoomDistance();
F32 distance = (F32)mCameraFocusOffsetTarget.magVec(); F32 min_zoom;
if (mFocusObject.notNull()) F32 max_zoom = getCameraMaxZoomDistance();
F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
if (mFocusObject.notNull())
{
if (mFocusObject->isAvatar())
{ {
if (mFocusObject->isAvatar()) min_zoom = AVATAR_MIN_ZOOM;
{
min_zoom = AVATAR_MIN_ZOOM;
}
else
{
min_zoom = OBJECT_MIN_ZOOM;
}
} }
else else
{ {
min_zoom = LAND_MIN_ZOOM; min_zoom = OBJECT_MIN_ZOOM;
} }
return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f);
} }
else
{
min_zoom = LAND_MIN_ZOOM;
}
return clamp_rescale(distance, min_zoom, max_zoom, 1.f, 0.f);
} }
void LLAgentCamera::setCameraZoomFraction(F32 fraction) void LLAgentCamera::setCameraZoomFraction(F32 fraction)
@ -787,6 +798,10 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction)
{ {
mHUDTargetZoom = fraction; mHUDTargetZoom = fraction;
} }
else if (isDisableCameraConstraints())
{
mCameraZoomFraction = fraction;
}
else if (mFocusOnAvatar && cameraThirdPerson()) else if (mFocusOnAvatar && cameraThirdPerson())
{ {
mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION); mCameraZoomFraction = rescale(fraction, 0.f, 1.f, MAX_ZOOM_FRACTION, MIN_ZOOM_FRACTION);
@ -821,6 +836,7 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction)
camera_offset_dir.normalize(); camera_offset_dir.normalize();
mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom); mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom);
} }
startCameraAnimation(); startCameraAnimation();
} }
@ -925,51 +941,42 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)
return; return;
} }
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 min_zoom = LAND_MIN_ZOOM;
F32 current_distance = (F32)camera_offset_unit.normalize(); F32 current_distance = (F32)camera_offset_unit.normalize();
F32 new_distance = current_distance * fraction; F32 new_distance = current_distance * fraction;
// Don't move through focus point // Unless camera is unlocked
if (mFocusObject) if (!isDisableCameraConstraints())
{ {
LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]); F32 min_zoom = LAND_MIN_ZOOM;
if (mFocusObject->isAvatar()) // Don't move through focus point
if (mFocusObject)
{ {
calcCameraMinDistance(min_zoom); LLVector3 camera_offset_dir((F32)camera_offset_unit.mdV[VX], (F32)camera_offset_unit.mdV[VY], (F32)camera_offset_unit.mdV[VZ]);
if (mFocusObject->isAvatar())
{
calcCameraMinDistance(min_zoom);
}
else
{
min_zoom = OBJECT_MIN_ZOOM;
}
} }
else
new_distance = llmax(new_distance, min_zoom);
F32 max_distance = getCameraMaxZoomDistance();
max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154
new_distance = llmin(new_distance, max_distance);
if (cameraCustomizeAvatar())
{ {
min_zoom = OBJECT_MIN_ZOOM; new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM);
} }
} }
new_distance = llmax(new_distance, min_zoom);
F32 max_distance = getCameraMaxZoomDistance();
max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154
if (new_distance > max_distance)
{
new_distance = max_distance;
/*
// Unless camera is unlocked
if (!LLViewerCamera::sDisableCameraConstraints)
{
return;
}
*/
}
if(cameraCustomizeAvatar())
{
new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
}
mCameraFocusOffsetTarget = new_distance * camera_offset_unit; mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
} }
@ -990,53 +997,52 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters)
changeCameraToMouselook(FALSE); changeCameraToMouselook(FALSE);
} }
mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION); if (!isDisableCameraConstraints())
{
mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION);
}
} }
else else
{ {
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget); LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 current_distance = (F32)camera_offset_unit.normalize(); F32 current_distance = (F32)camera_offset_unit.normalize();
F32 new_distance = current_distance - meters; F32 new_distance = current_distance - meters;
F32 min_zoom = LAND_MIN_ZOOM;
// Unless camera is unlocked
// Don't move through focus point if (!isDisableCameraConstraints())
if (mFocusObject.notNull())
{ {
if (mFocusObject->isAvatar()) F32 min_zoom = LAND_MIN_ZOOM;
// Don't move through focus point
if (mFocusObject.notNull())
{ {
min_zoom = AVATAR_MIN_ZOOM; if (mFocusObject->isAvatar())
{
min_zoom = AVATAR_MIN_ZOOM;
}
else
{
min_zoom = OBJECT_MIN_ZOOM;
}
} }
else
new_distance = llmax(new_distance, min_zoom);
F32 max_distance = getCameraMaxZoomDistance();
new_distance = llmin(new_distance, max_distance);
if (CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode())
{ {
min_zoom = OBJECT_MIN_ZOOM; new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM);
} }
} }
new_distance = llmax(new_distance, min_zoom);
F32 max_distance = getCameraMaxZoomDistance();
if (new_distance > max_distance)
{
// Unless camera is unlocked
if (!gSavedSettings.getBOOL("DisableCameraConstraints"))
{
return;
}
}
if( CAMERA_MODE_CUSTOMIZE_AVATAR == getCameraMode() )
{
new_distance = llclamp( new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM );
}
// Compute new camera offset // Compute new camera offset
mCameraFocusOffsetTarget = new_distance * camera_offset_unit; mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
cameraZoomIn(1.f); cameraZoomIn(1.f);
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// cameraPanIn() // cameraPanIn()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1841,7 +1847,8 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset ); local_camera_offset = gAgent.getFrameAgent().rotateToAbsolute( local_camera_offset );
} }
if (!mCameraCollidePlane.isExactlyZero() && (!isAgentAvatarValid() || !gAgentAvatarp->isSitting())) if (!isDisableCameraConstraints() && !mCameraCollidePlane.isExactlyZero() &&
(!isAgentAvatarValid() || !gAgentAvatarp->isSitting()))
{ {
LLVector3 plane_normal; LLVector3 plane_normal;
plane_normal.setVec(mCameraCollidePlane.mV); plane_normal.setVec(mCameraCollidePlane.mV);
@ -1960,7 +1967,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
camera_position_global = focusPosGlobal + mCameraFocusOffset; camera_position_global = focusPosGlobal + mCameraFocusOffset;
} }
if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike()) if (!isDisableCameraConstraints() && !gAgent.isGodlike())
{ {
LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global); LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global);
bool constrain = true; bool constrain = true;
@ -2131,17 +2138,13 @@ F32 LLAgentCamera::getCameraMinOffGround()
{ {
return 0.f; return 0.f;
} }
else
if (isDisableCameraConstraints())
{ {
if (gSavedSettings.getBOOL("DisableCameraConstraints")) return -1000.f;
{
return -1000.f;
}
else
{
return 0.5f;
}
} }
return 0.5f;
} }

View File

@ -2943,13 +2943,14 @@ bool LLAppViewer::initConfiguration()
if (mSecondInstance) if (mSecondInstance)
{ {
// This is the second instance of SL. Turn off voice support, // This is the second instance of SL. Mute voice,
// but make sure the setting is *not* persisted. // but make sure the setting is *not* persisted.
LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); // Also see LLVivoxVoiceClient::voiceEnabled()
if(disable_voice) LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat");
if(enable_voice)
{ {
const BOOL DO_NOT_PERSIST = FALSE; const BOOL DO_NOT_PERSIST = FALSE;
disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST);
} }
} }
@ -5420,9 +5421,18 @@ void LLAppViewer::forceErrorBadMemoryAccess()
void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorInfiniteLoop()
{ {
LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL; LL_WARNS() << "Forcing a deliberate infinite loop" << LL_ENDL;
// Loop is intentionally complicated to fool basic loop detection
LLTimer timer_total;
LLTimer timer_expiry;
const S32 report_frequency = 10;
timer_expiry.setTimerExpirySec(report_frequency);
while(true) while(true)
{ {
; if (timer_expiry.hasExpired())
{
LL_INFOS() << "Infinite loop time : " << timer_total.getElapsedSeconds() << LL_ENDL;
timer_expiry.setTimerExpirySec(report_frequency);
}
} }
return; return;
} }

View File

@ -379,6 +379,7 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
void LLControlAvatar::markDead() void LLControlAvatar::markDead()
{ {
mRootVolp = NULL;
super::markDead(); super::markDead();
mControlAVBridge = NULL; mControlAVBridge = NULL;
} }

View File

@ -90,6 +90,8 @@ LLConversationItem::~LLConversationItem()
{ {
mAvatarNameCacheConnection.disconnect(); mAvatarNameCacheConnection.disconnect();
} }
clearChildren();
} }
//virtual //virtual
@ -254,6 +256,11 @@ LLConversationItemSession::LLConversationItemSession(const LLUUID& uuid, LLFolde
mConvType = CONV_SESSION_UNKNOWN; mConvType = CONV_SESSION_UNKNOWN;
} }
LLConversationItemSession::~LLConversationItemSession()
{
clearAndDeparentModels();
}
bool LLConversationItemSession::hasChildren() const bool LLConversationItemSession::hasChildren() const
{ {
return getChildrenCount() > 0; return getChildrenCount() > 0;

View File

@ -157,6 +157,7 @@ class LLConversationItemSession : public LLConversationItem
public: public:
LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model);
LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model); LLConversationItemSession(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model);
~LLConversationItemSession();
/*virtual*/ bool hasChildren() const; /*virtual*/ bool hasChildren() const;
LLPointer<LLUIImage> getIcon() const { return NULL; } LLPointer<LLUIImage> getIcon() const { return NULL; }

View File

@ -760,19 +760,6 @@ void LLDrawable::movePartition()
if (part) if (part)
{ {
part->move(this, getSpatialGroup()); part->move(this, getSpatialGroup());
// SL-18251 "On-screen animesh characters using pelvis offset animations
// disappear when root goes off-screen"
//
// Update extents of the root node when Control Avatar changes it's bounds
if (mRenderType == LLPipeline::RENDER_TYPE_CONTROL_AV && isRoot())
{
LLControlAvatar* controlAvatar = dynamic_cast<LLControlAvatar*>(getVObj().get());
if (controlAvatar && controlAvatar->mControlAVBridge)
{
((LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0))->setState(LLViewerOctreeGroup::DIRTY);
}
}
} }
} }

View File

@ -320,6 +320,7 @@ public:
if (item) if (item)
{ {
LLFavoritesBarCtrl::sWaitingForCallabck = 0.f;
LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField);
item->setComplete(TRUE); item->setComplete(TRUE);
@ -365,6 +366,9 @@ struct LLFavoritesSort
} }
}; };
F64 LLFavoritesBarCtrl::sWaitingForCallabck = 0.f;
LLFavoritesBarCtrl::Params::Params() LLFavoritesBarCtrl::Params::Params()
: image_drag_indication("image_drag_indication"), : image_drag_indication("image_drag_indication"),
more_button("more_button"), more_button("more_button"),
@ -381,7 +385,7 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mShowDragMarker(FALSE), mShowDragMarker(FALSE),
mLandingTab(NULL), mLandingTab(NULL),
mLastTab(NULL), mLastTab(NULL),
mTabsHighlightEnabled(TRUE), mItemsListDirty(false),
mUpdateDropDownItems(true), mUpdateDropDownItems(true),
mRestoreOverflowMenu(false), mRestoreOverflowMenu(false),
mGetPrevItems(true), mGetPrevItems(true),
@ -618,6 +622,9 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
int sortField = 0; int sortField = 0;
LLPointer<LLItemCopiedCallback> cb; LLPointer<LLItemCopiedCallback> cb;
const F64 CALLBACK_WAIT_TIME = 30.f;
sWaitingForCallabck = LLTimer::getTotalSeconds() + CALLBACK_WAIT_TIME;
// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i)
{ {
@ -691,16 +698,22 @@ void LLFavoritesBarCtrl::changed(U32 mask)
LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID()); LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());
} }
updateButtons(); if (sWaitingForCallabck < LLTimer::getTotalSeconds())
if (!mItemsChangedTimer.getStarted()) {
{ updateButtons();
mItemsChangedTimer.start(); if (!mItemsChangedTimer.getStarted())
} {
else mItemsChangedTimer.start();
{ }
mItemsChangedTimer.reset(); else
} {
mItemsChangedTimer.reset();
}
}
else
{
mItemsListDirty = true;
}
} }
} }
@ -754,6 +767,18 @@ void LLFavoritesBarCtrl::draw()
mItemsChangedTimer.start(); mItemsChangedTimer.start();
} }
if (mItemsListDirty && sWaitingForCallabck < LLTimer::getTotalSeconds())
{
updateButtons();
if (!mItemsChangedTimer.getStarted())
{
mItemsChangedTimer.start();
}
else
{
mItemsChangedTimer.reset();
}
}
} }
const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()
@ -782,6 +807,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
return; return;
} }
mItemsListDirty = false;
mItems.clear(); mItems.clear();
if (!collectFavoriteItems(mItems)) if (!collectFavoriteItems(mItems))

View File

@ -53,6 +53,7 @@ public:
protected: protected:
LLFavoritesBarCtrl(const Params&); LLFavoritesBarCtrl(const Params&);
friend class LLUICtrlFactory; friend class LLUICtrlFactory;
friend class LLItemCopiedCallback;
public: public:
virtual ~LLFavoritesBarCtrl(); virtual ~LLFavoritesBarCtrl();
@ -84,7 +85,6 @@ protected:
void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask); void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask);
void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
void onOverflowMenuItemMouseDown(LLUUID id, LLUICtrl* item, S32 x, S32 y, MASK mask);
void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
void onEndDrag(); void onEndDrag();
@ -164,7 +164,8 @@ private:
BOOL mStartDrag; BOOL mStartDrag;
LLInventoryModel::item_array_t mItems; LLInventoryModel::item_array_t mItems;
BOOL mTabsHighlightEnabled; static F64 sWaitingForCallabck;
bool mItemsListDirty;
S32 mMouseX; S32 mMouseX;
S32 mMouseY; S32 mMouseY;

View File

@ -522,6 +522,8 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg,
// errors in separate window. // errors in separate window.
if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG)
{ {
if (LLFloater::isQuitRequested()) return;
if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
return; return;

View File

@ -113,6 +113,7 @@
#include "llpresetsmanager.h" #include "llpresetsmanager.h"
#include "llviewercontrol.h" #include "llviewercontrol.h"
#include "llpresetsmanager.h" #include "llpresetsmanager.h"
#include "llinventoryfunctions.h"
#include "llsearchableui.h" #include "llsearchableui.h"
#include "llperfstats.h" #include "llperfstats.h"
@ -1590,25 +1591,6 @@ void LLFloaterPreference::onChangeMaturity()
getChild<LLIconCtrl>("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT); getChild<LLIconCtrl>("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT);
} }
std::string get_category_path(LLUUID cat_id)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
std::string localized_cat_name;
if (!LLTrans::findString(localized_cat_name, "InvFolder " + cat->getName()))
{
localized_cat_name = cat->getName();
}
if (cat->getParentUUID().notNull())
{
return get_category_path(cat->getParentUUID()) + " > " + localized_cat_name;
}
else
{
return localized_cat_name;
}
}
std::string get_category_path(LLFolderType::EType cat_type) std::string get_category_path(LLFolderType::EType cat_type)
{ {
LLUUID cat_id = gInventory.findUserDefinedCategoryUUIDForType(cat_type); LLUUID cat_id = gInventory.findUserDefinedCategoryUUIDForType(cat_type);

View File

@ -144,7 +144,7 @@ public:
const LLUUID& invoice, const LLUUID& invoice,
const sparam_t& strings); const sparam_t& strings);
LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); static LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count );
}; };
@ -2450,11 +2450,12 @@ bool LLDispatchSetEstateAccess::operator()(
return true; return true;
} }
// static
LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ) LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count )
{ {
LLSD idList = LLSD::emptyArray(); LLSD idList = LLSD::emptyArray();
LLUUID id; LLUUID id;
while(count--> 0) while (count-- > 0 && it < end)
{ {
memcpy(id.mData, (*(it++)).data(), UUID_BYTES); memcpy(id.mData, (*(it++)).data(), UUID_BYTES);
idList.append(id); idList.append(id);
@ -2468,7 +2469,7 @@ LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_
// strings[2] = str(num blocked) // strings[2] = str(num blocked)
// strings[3] = str(num trusted) // strings[3] = str(num trusted)
// strings[4] = str(num allowed) // strings[4] = str(num allowed)
// strings[8] = bin(uuid) ... // strings[5] = bin(uuid) ...
// ... // ...
bool LLDispatchSetEstateExperience::operator()( bool LLDispatchSetEstateExperience::operator()(
const LLDispatcher* dispatcher, const LLDispatcher* dispatcher,
@ -2477,23 +2478,30 @@ bool LLDispatchSetEstateExperience::operator()(
const sparam_t& strings) const sparam_t& strings)
{ {
LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences();
if (!panel) return true; if (!panel)
return true;
const sparam_t::size_type MIN_SIZE = 5;
if (strings.size() < MIN_SIZE)
return true;
// Skip 2 parameters
sparam_t::const_iterator it = strings.begin(); sparam_t::const_iterator it = strings.begin();
++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10); ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10);
++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10); ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10);
// Read 3 parameters
LLUUID id; LLUUID id;
S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10); S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10);
S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10); S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10);
S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10); S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10);
LLSD ids = LLSD::emptyMap() LLSD ids = LLSD::emptyMap()
.with("blocked", getIDs(it, strings.end(), num_blocked)) .with("blocked", getIDs(it, strings.end(), num_blocked))
.with("trusted", getIDs(it + (num_blocked), strings.end(), num_trusted)) .with("trusted", getIDs(it + num_blocked, strings.end(), num_trusted))
.with("allowed", getIDs(it + (num_blocked+num_trusted), strings.end(), num_allowed)); .with("allowed", getIDs(it + num_blocked + num_trusted, strings.end(), num_allowed));
panel->processResponse(ids); panel->processResponse(ids);
return true; return true;
} }

View File

@ -67,14 +67,14 @@ void LLFloaterSidePanelContainer::closeFloater(bool app_quitting)
if (parent == this ) if (parent == this )
{ {
LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance")); LLSidepanelAppearance* panel_appearance = dynamic_cast<LLSidepanelAppearance*>(getPanel("appearance"));
if ( panel_appearance ) if (panel_appearance)
{ {
LLPanelEditWearable *edit_wearable_ptr = panel_appearance->getWearable(); LLPanelEditWearable *edit_wearable_ptr = panel_appearance->getWearable();
if (edit_wearable_ptr) if (edit_wearable_ptr)
{ {
edit_wearable_ptr->onClose(); edit_wearable_ptr->onClose();
} }
if(!app_quitting) if (!app_quitting)
{ {
panel_appearance->showOutfitsInventoryPanel(); panel_appearance->showOutfitsInventoryPanel();
} }
@ -116,11 +116,16 @@ LLFloater* LLFloaterSidePanelContainer::getTopmostInventoryFloater()
LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params)
{ {
LLView* view = findChildView(panel_name, true); LLView* view = findChildView(panel_name, true);
if (!view) return NULL; if (!view)
return NULL;
if (!getVisible()) if (!getVisible())
{ {
openFloater(); openFloater();
}
else if (!hasFocus())
{
setFocus(TRUE);
} }
LLPanel* panel = NULL; LLPanel* panel = NULL;

View File

@ -897,6 +897,15 @@ void LLHUDNameTag::shift(const LLVector3& offset)
mPositionAgent += offset; mPositionAgent += offset;
} }
F32 LLHUDNameTag::getWorldHeight() const
{
const LLViewerCamera* camera = LLViewerCamera::getInstance();
F32 height_meters = mLastDistance * (F32)tan(camera->getView() / 2.f);
F32 height_pixels = camera->getViewHeightInPixels() / 2.f;
F32 meters_per_pixel = height_meters / height_pixels;
return mHeight * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY];
}
//static //static
void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list) void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)
{ {

View File

@ -127,11 +127,12 @@ public:
/*virtual*/ void markDead(); /*virtual*/ void markDead();
friend class LLHUDObject; friend class LLHUDObject;
/*virtual*/ F32 getDistance() const { return mLastDistance; } /*virtual*/ F32 getDistance() const { return mLastDistance; }
S32 getLOD() { return mLOD; } S32 getLOD() const { return mLOD; }
BOOL getVisible() { return mVisible; } BOOL getVisible() const { return mVisible; }
BOOL getHidden() const { return mHidden; } BOOL getHidden() const { return mHidden; }
void setHidden( BOOL hide ) { mHidden = hide; } void setHidden( BOOL hide ) { mHidden = hide; }
void shift(const LLVector3& offset); void shift(const LLVector3& offset);
F32 getWorldHeight() const;
BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a& intersection, BOOL debug_render = FALSE); BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a& intersection, BOOL debug_render = FALSE);

View File

@ -1778,7 +1778,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
} }
else if ("show_in_main_panel" == action) else if ("show_in_main_panel" == action)
{ {
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE); LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true);
return; return;
} }
else if ("cut" == action) else if ("cut" == action)
@ -3409,7 +3409,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
} }
else if ("show_in_main_panel" == action) else if ("show_in_main_panel" == action)
{ {
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE); LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true);
return; return;
} }
else if ("cut" == action) else if ("cut" == action)

View File

@ -2151,6 +2151,24 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st
gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func); gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func);
} }
std::string get_category_path(LLUUID cat_id)
{
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
std::string localized_cat_name;
if (!LLTrans::findString(localized_cat_name, "InvFolder " + cat->getName()))
{
localized_cat_name = cat->getName();
}
if (cat->getParentUUID().notNull())
{
return get_category_path(cat->getParentUUID()) + " > " + localized_cat_name;
}
else
{
return localized_cat_name;
}
}
// Returns true if the item can be moved to Current Outfit or any outfit folder. // Returns true if the item can be moved to Current Outfit or any outfit folder.
bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit) bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit)
{ {

View File

@ -106,6 +106,7 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st
void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids); void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids);
bool is_only_cats_selected(const uuid_vec_t& selected_uuids); bool is_only_cats_selected(const uuid_vec_t& selected_uuids);
bool is_only_items_selected(const uuid_vec_t& selected_uuids); bool is_only_items_selected(const uuid_vec_t& selected_uuids);
std::string get_category_path(LLUUID cat_id);
bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); bool can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit);
bool can_move_to_landmarks(LLInventoryItem* inv_item); bool can_move_to_landmarks(LLInventoryItem* inv_item);

View File

@ -240,7 +240,7 @@ void LLInventoryItemsList::refresh()
case REFRESH_LIST_SORT: case REFRESH_LIST_SORT:
{ {
// Filter, sort, rearrange and notify parent about shape changes // Filter, sort, rearrange and notify parent about shape changes
filterItems(); filterItems(true, true);
if (mAddedItems.size() == 0) if (mAddedItems.size() == 0)
{ {

View File

@ -51,20 +51,20 @@ public:
/** /**
* Let list know items need to be refreshed in next doIdle() * Let list know items need to be refreshed in next doIdle()
*/ */
void setNeedsRefresh(bool needs_refresh){ mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; } void setNeedsRefresh(bool needs_refresh) { mRefreshState = needs_refresh ? REFRESH_ALL : REFRESH_COMPLETE; }
U32 getNeedsRefresh(){ return mRefreshState; } U32 getNeedsRefresh() { return mRefreshState; }
/** /**
* Sets the flag indicating that the list needs to be refreshed even if it is * Sets the flag indicating that the list needs to be refreshed even if it is
* not currently visible. * not currently visible.
*/ */
void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; } void setForceRefresh(bool force_refresh) { mForceRefresh = force_refresh; }
/** /**
* If refreshes when invisible. * If refreshes when invisible.
*/ */
bool getForceRefresh(){ return mForceRefresh; } bool getForceRefresh() { return mForceRefresh; }
virtual bool selectItemByValue(const LLSD& value, bool select = true); virtual bool selectItemByValue(const LLSD& value, bool select = true);

View File

@ -1887,46 +1887,52 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
} }
//static //static
void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id, BOOL use_main_panel, BOOL take_keyboard_focus, BOOL reset_filter) void LLInventoryPanel::openInventoryPanelAndSetSelection(bool auto_open, const LLUUID& obj_id,
bool use_main_panel, bool take_keyboard_focus, bool reset_filter)
{ {
LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
sidepanel_inventory->showInventoryPanel(); sidepanel_inventory->showInventoryPanel();
bool in_inbox = (gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX))); LLUUID cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX);
bool in_inbox = gInventory.isObjectDescendentOf(obj_id, cat_id);
if (!in_inbox && (use_main_panel || !sidepanel_inventory->getMainInventoryPanel()->isRecentItemsPanelSelected())) if (!in_inbox && use_main_panel)
{ {
sidepanel_inventory->selectAllItemsPanel(); sidepanel_inventory->selectAllItemsPanel();
} }
LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater(); if (!auto_open)
if(!auto_open && inventory_floater && inventory_floater->getVisible())
{ {
LLSidepanelInventory *inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel"); LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater();
LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel(); if (inventory_floater && inventory_floater->getVisible())
if(main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode())
{ {
LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL; LLSidepanelInventory *inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel");
main_panel->setGallerySelection(obj_id); LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel();
return; if (main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode())
{
LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL;
main_panel->setGallerySelection(obj_id);
return;
}
} }
} }
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel(); if (use_main_panel)
if (main_inventory && main_inventory->isSingleFolderMode()
&& use_main_panel)
{ {
const LLInventoryObject *obj = gInventory.getObject(obj_id); LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
if (obj) if (main_inventory && main_inventory->isSingleFolderMode())
{ {
LL_DEBUGS("Inventory") << "Opening main inventory panel for item" << obj_id << LL_ENDL; const LLInventoryObject *obj = gInventory.getObject(obj_id);
main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false); if (obj)
main_inventory->setGallerySelection(obj_id); {
return; LL_DEBUGS("Inventory") << "Opening main inventory panel for item" << obj_id << LL_ENDL;
main_inventory->setSingleFolderViewRoot(obj->getParentUUID(), false);
main_inventory->setGallerySelection(obj_id);
return;
}
} }
} }
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open); LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open);
if (active_panel) if (active_panel)
{ {
LL_DEBUGS("Messaging", "Inventory") << "Highlighting" << obj_id << LL_ENDL; LL_DEBUGS("Messaging", "Inventory") << "Highlighting" << obj_id << LL_ENDL;
@ -1938,11 +1944,8 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
if (in_inbox) if (in_inbox)
{ {
LLInventoryPanel * inventory_panel = NULL;
sidepanel_inventory->openInbox(); sidepanel_inventory->openInbox();
inventory_panel = sidepanel_inventory->getInboxPanel(); LLInventoryPanel* inventory_panel = sidepanel_inventory->getInboxPanel();
if (inventory_panel) if (inventory_panel)
{ {
inventory_panel->setSelection(obj_id, take_keyboard_focus); inventory_panel->setSelection(obj_id, take_keyboard_focus);
@ -1967,7 +1970,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
void LLInventoryPanel::setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id) void LLInventoryPanel::setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id)
{ {
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
{ {

View File

@ -244,12 +244,12 @@ public:
// "Auto_open" determines if we open an inventory panel if none are open. // "Auto_open" determines if we open an inventory panel if none are open.
static LLInventoryPanel *getActiveInventoryPanel(BOOL auto_open = TRUE); static LLInventoryPanel *getActiveInventoryPanel(BOOL auto_open = TRUE);
static void openInventoryPanelAndSetSelection(BOOL auto_open, static void openInventoryPanelAndSetSelection(bool auto_open,
const LLUUID& obj_id, const LLUUID& obj_id,
BOOL use_main_panel = FALSE, bool use_main_panel = false,
BOOL take_keyboard_focus = TAKE_FOCUS_YES, bool take_keyboard_focus = true,
BOOL reset_filter = FALSE); bool reset_filter = false);
static void setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id); static void setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id);
void addItemID(const LLUUID& id, LLFolderViewItem* itemp); void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
void removeItemID(const LLUUID& id); void removeItemID(const LLUUID& id);
LLFolderViewItem* getItemByID(const LLUUID& id); LLFolderViewItem* getItemByID(const LLUUID& id);

View File

@ -1081,6 +1081,13 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename)
LLImageDimensionsInfo image_info; LLImageDimensionsInfo image_info;
if (!image_info.load(filename,codec)) if (!image_info.load(filename,codec))
{ {
LLSD args;
args["NAME"] = gDirUtilp->getBaseFileName(filename);
if (!image_info.getWarningName().empty())
{
args["REASON"] = LLTrans::getString(image_info.getWarningName());
}
LLNotificationsUtil::add("CannotUploadTexture", args);
return false; return false;
} }
@ -1096,6 +1103,7 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename)
LLSD notif_args; LLSD notif_args;
notif_args["REASON"] = mImageLoadError; notif_args["REASON"] = mImageLoadError;
notif_args["NAME"] = gDirUtilp->getBaseFileName(filename);
LLNotificationsUtil::add("CannotUploadTexture", notif_args); LLNotificationsUtil::add("CannotUploadTexture", notif_args);
return false; return false;

View File

@ -5503,7 +5503,7 @@ void on_new_single_inventory_upload_complete(
} }
else else
{ {
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, server_response["new_inventory_item"].asUUID(), TRUE, TAKE_FOCUS_NO, TRUE); LLInventoryPanel::openInventoryPanelAndSetSelection(true, server_response["new_inventory_item"].asUUID(), true, false, true);
} }
// restore keyboard focus // restore keyboard focus

View File

@ -249,7 +249,7 @@ void LLModelPreview::updateDimentionsAndOffsets()
{ {
accounted.insert(instance.mModel); accounted.insert(instance.mModel);
//update instance skin info for each lods pelvisZoffset // update instance skin info for each lods pelvisZoffset
for (int j = 0; j<LLModel::NUM_LODS; ++j) for (int j = 0; j<LLModel::NUM_LODS; ++j)
{ {
if (instance.mLOD[j]) if (instance.mLOD[j])
@ -271,6 +271,7 @@ void LLModelPreview::rebuildUploadData()
{ {
assert_main_thread(); assert_main_thread();
mDefaultPhysicsShapeP = NULL;
mUploadData.clear(); mUploadData.clear();
mTextureSet.clear(); mTextureSet.clear();
@ -310,7 +311,7 @@ void LLModelPreview::rebuildUploadData()
mat *= scale_mat; mat *= scale_mat;
for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();) for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();)
{ //for each instance with said transform applied { // for each instance with said transform applied
LLModelInstance instance = *model_iter++; LLModelInstance instance = *model_iter++;
LLModel* base_model = instance.mModel; LLModel* base_model = instance.mModel;
@ -573,7 +574,7 @@ void LLModelPreview::rebuildUploadData()
else if (getLoadState() == LLModelLoader::ERROR_MATERIALS else if (getLoadState() == LLModelLoader::ERROR_MATERIALS
|| getLoadState() == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION) || getLoadState() == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION)
{ {
// This is only valid for these two error types because they are // This is only valid for these two error types because they are
// only used inside rebuildUploadData() and updateStatusMessages() // only used inside rebuildUploadData() and updateStatusMessages()
// updateStatusMessages() is called after rebuildUploadData() // updateStatusMessages() is called after rebuildUploadData()
setLoadState(LLModelLoader::DONE); setLoadState(LLModelLoader::DONE);
@ -798,7 +799,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
// it tends to force the UI into strange checkbox options // it tends to force the UI into strange checkbox options
// which cannot be altered. // which cannot be altered.
//only try to load from slm if viewer is configured to do so and this is the //only try to load from slm if viewer is configured to do so and this is the
//initial model load (not an LoD or physics shape) //initial model load (not an LoD or physics shape)
mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty(); mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty();
} }
@ -884,12 +885,13 @@ void LLModelPreview::clearIncompatible(S32 lod)
// Check if already started // Check if already started
bool subscribe_for_generation = mLodsQuery.empty(); bool subscribe_for_generation = mLodsQuery.empty();
// Remove previously scheduled work // Remove previously scheduled work
mLodsQuery.clear(); mLodsQuery.clear();
LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
if (!fmp) return; if (!fmp)
return;
// Schedule new work // Schedule new work
for (S32 i = LLModel::LOD_HIGH; i >= 0; --i) for (S32 i = LLModel::LOD_HIGH; i >= 0; --i)
@ -1719,7 +1721,7 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
ll_aligned_free_16(output_indices); ll_aligned_free_16(output_indices);
ll_aligned_free_16(shadow_indices); ll_aligned_free_16(shadow_indices);
if (size_new_indices < 3) if (size_new_indices < 3)
{ {
// At least one triangle is needed // At least one triangle is needed
@ -1912,7 +1914,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
{ {
precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS); precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_UVS);
} }
if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator)) if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
{ {
// Try sloppy variant if normal one failed to simplify model enough. // Try sloppy variant if normal one failed to simplify model enough.

View File

@ -433,8 +433,7 @@ bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)
} }
void LLOutfitGallery::reArrangeRows(S32 row_diff) void LLOutfitGallery::reArrangeRows(S32 row_diff)
{ {
std::vector<LLOutfitGalleryItem*> buf_items = mItems; std::vector<LLOutfitGalleryItem*> buf_items = mItems;
for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) for (std::vector<LLOutfitGalleryItem*>::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it)
{ {
@ -446,16 +445,24 @@ void LLOutfitGallery::reArrangeRows(S32 row_diff)
} }
mHiddenItems.clear(); mHiddenItems.clear();
mItemsInRow+= row_diff; mItemsInRow += row_diff;
updateGalleryWidth(); updateGalleryWidth();
std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem);
std::string cur_filter = getFilterSubString();
LLStringUtil::toUpper(cur_filter);
for (std::vector<LLOutfitGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) for (std::vector<LLOutfitGalleryItem*>::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it)
{ {
(*it)->setHidden(false); std::string outfit_name = (*it)->getItemName();
applyFilter(*it,sFilterSubString); LLStringUtil::toUpper(outfit_name);
bool hidden = (std::string::npos == outfit_name.find(cur_filter));
(*it)->setHidden(hidden);
addToGallery(*it); addToGallery(*it);
} }
updateMessageVisibility(); updateMessageVisibility();
} }
@ -725,9 +732,9 @@ LLOutfitGallery::~LLOutfitGallery()
} }
} }
void LLOutfitGallery::setFilterSubString(const std::string& string) // virtual
void LLOutfitGallery::onFilterSubStringChanged(const std::string& new_string, const std::string& old_string)
{ {
sFilterSubString = string;
reArrangeRows(); reArrangeRows();
} }
@ -743,20 +750,6 @@ void LLOutfitGallery::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id)
} }
} }
void LLOutfitGallery::applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring)
{
if (!item) return;
std::string outfit_name = item->getItemName();
LLStringUtil::toUpper(outfit_name);
std::string cur_filter = filter_substring;
LLStringUtil::toUpper(cur_filter);
bool hidden = (std::string::npos == outfit_name.find(cur_filter));
item->setHidden(hidden);
}
void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid) void LLOutfitGallery::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
{ {
} }
@ -904,11 +897,11 @@ bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id)
void LLOutfitGallery::updateMessageVisibility() void LLOutfitGallery::updateMessageVisibility()
{ {
if(mItems.empty()) if (mItems.empty())
{ {
mMessageTextBox->setVisible(TRUE); mMessageTextBox->setVisible(TRUE);
mScrollPanel->setVisible(FALSE); mScrollPanel->setVisible(FALSE);
std::string message = sFilterSubString.empty()? getString("no_outfits_msg") : getString("no_matched_outfits_msg"); std::string message = getString(getFilterSubString().empty() ? "no_outfits_msg" : "no_matched_outfits_msg");
mMessageTextBox->setValue(message); mMessageTextBox->setValue(message);
} }
else else

View File

@ -90,7 +90,7 @@ public:
void wearSelectedOutfit(); void wearSelectedOutfit();
/*virtual*/ void setFilterSubString(const std::string& string); /*virtual*/ void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string);
/*virtual*/ void getCurrentCategories(uuid_vec_t& vcur); /*virtual*/ void getCurrentCategories(uuid_vec_t& vcur);
/*virtual*/ void updateAddedCategory(LLUUID cat_id); /*virtual*/ void updateAddedCategory(LLUUID cat_id);
@ -117,8 +117,6 @@ protected:
/*virtual*/ void onExpandAllFolders() {} /*virtual*/ void onExpandAllFolders() {}
/*virtual*/ LLOutfitListGearMenuBase* createGearMenu(); /*virtual*/ LLOutfitListGearMenuBase* createGearMenu();
void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring);
private: private:
LLUUID getPhotoAssetId(const LLUUID& outfit_id); LLUUID getPhotoAssetId(const LLUUID& outfit_id);
LLUUID getDefaultPhoto(); LLUUID getDefaultPhoto();

View File

@ -188,7 +188,7 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1)); list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1));
// Setting list refresh callback to apply filter on list change. // Setting list refresh callback to apply filter on list change.
list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onFilteredWearableItemsListRefresh, this, _1)); list->setRefreshCompleteCallback(boost::bind(&LLOutfitsList::onRefreshComplete, this, _1));
list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3)); list->setRightMouseDownCallback(boost::bind(&LLOutfitsList::onWearableItemsListRightClick, this, _1, _2, _3));
@ -199,19 +199,17 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
// Further list updates will be triggered by the category observer. // Further list updates will be triggered by the category observer.
list->updateList(cat_id); list->updateList(cat_id);
// If filter is currently applied we store the initial tab state and // If filter is currently applied we store the initial tab state.
// open it to show matched items if any. if (!getFilterSubString().empty())
if (!sFilterSubString.empty())
{ {
tab->notifyChildren(LLSD().with("action", "store_state")); tab->notifyChildren(LLSD().with("action", "store_state"));
tab->setDisplayChildren(true);
// Setting mForceRefresh flag will make the list refresh its contents // Setting mForceRefresh flag will make the list refresh its contents
// even if it is not currently visible. This is required to apply the // even if it is not currently visible. This is required to apply the
// filter to the newly added list. // filter to the newly added list.
list->setForceRefresh(true); list->setForceRefresh(true);
list->setFilterSubString(sFilterSubString); list->setFilterSubString(getFilterSubString(), false);
} }
} }
@ -313,14 +311,6 @@ void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
} }
} }
// virtual
void LLOutfitsList::setFilterSubString(const std::string& string)
{
applyFilter(string);
sFilterSubString = string;
}
// virtual // virtual
bool LLOutfitListBase::isActionEnabled(const LLSD& userdata) bool LLOutfitListBase::isActionEnabled(const LLSD& userdata)
{ {
@ -494,9 +484,9 @@ void LLOutfitsList::restoreOutfitSelection(LLAccordionCtrlTab* tab, const LLUUID
} }
} }
void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) void LLOutfitsList::onRefreshComplete(LLUICtrl* ctrl)
{ {
if (!ctrl || sFilterSubString.empty()) if (!ctrl || getFilterSubString().empty())
return; return;
for (outfits_map_t::iterator for (outfits_map_t::iterator
@ -510,57 +500,50 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (list != ctrl) continue; if (list != ctrl) continue;
applyFilterToTab(iter->first, tab, sFilterSubString); applyFilterToTab(iter->first, tab, getFilterSubString());
} }
} }
void LLOutfitsList::applyFilter(const std::string& new_filter_substring) // virtual
void LLOutfitsList::onFilterSubStringChanged(const std::string& new_string, const std::string& old_string)
{ {
mAccordion->setFilterSubString(new_filter_substring); mAccordion->setFilterSubString(new_string);
for (outfits_map_t::iterator outfits_map_t::iterator iter = mOutfitsMap.begin(), iter_end = mOutfitsMap.end();
iter = mOutfitsMap.begin(), while (iter != iter_end)
iter_end = mOutfitsMap.end();
iter != iter_end; ++iter)
{ {
LLAccordionCtrlTab* tab = iter->second; const LLUUID& category_id = iter->first;
LLAccordionCtrlTab* tab = iter++->second;
if (!tab) continue; if (!tab) continue;
bool more_restrictive = sFilterSubString.size() < new_filter_substring.size() && !new_filter_substring.substr(0, sFilterSubString.size()).compare(sFilterSubString);
// Restore tab visibility in case of less restrictive filter
// to compare it with updated string if it was previously hidden.
if (!more_restrictive)
{
tab->setVisible(TRUE);
}
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (list) if (list)
{ {
list->setFilterSubString(new_filter_substring); list->setFilterSubString(new_string, tab->getDisplayChildren());
} }
if(sFilterSubString.empty() && !new_filter_substring.empty()) if (old_string.empty())
{ {
//store accordion tab state when filter is not empty // Store accordion tab state when filter is not empty
tab->notifyChildren(LLSD().with("action","store_state")); tab->notifyChildren(LLSD().with("action", "store_state"));
} }
if (!new_filter_substring.empty()) if (!new_string.empty())
{ {
applyFilterToTab(iter->first, tab, new_filter_substring); applyFilterToTab(category_id, tab, new_string);
} }
else else
{ {
// restore tab title when filter is empty tab->setVisible(TRUE);
// Restore tab title when filter is empty
tab->setTitle(tab->getTitle()); tab->setTitle(tab->getTitle());
//restore accordion state after all those accodrion tab manipulations // Restore accordion state after all those accodrion tab manipulations
tab->notifyChildren(LLSD().with("action","restore_state")); tab->notifyChildren(LLSD().with("action", "restore_state"));
// Try restoring the tab selection. // Try restoring the tab selection.
restoreOutfitSelection(tab, iter->first); restoreOutfitSelection(tab, category_id);
} }
} }
@ -586,11 +569,11 @@ void LLOutfitsList::applyFilterToTab(
if (std::string::npos == title.find(cur_filter)) if (std::string::npos == title.find(cur_filter))
{ {
// hide tab if its title doesn't pass filter // Hide tab if its title doesn't pass filter
// and it has no visible items // and it has no matched items
tab->setVisible(list->hasMatchedItems()); tab->setVisible(list->hasMatchedItems());
// remove title highlighting because it might // Remove title highlighting because it might
// have been previously highlighted by less restrictive filter // have been previously highlighted by less restrictive filter
tab->setTitle(tab->getTitle()); tab->setTitle(tab->getTitle());
@ -602,18 +585,6 @@ void LLOutfitsList::applyFilterToTab(
// Try restoring the tab selection. // Try restoring the tab selection.
restoreOutfitSelection(tab, category_id); restoreOutfitSelection(tab, category_id);
} }
if (tab->getVisible())
{
// Open tab if it has passed the filter.
tab->setDisplayChildren(true);
}
else
{
// Set force refresh flag to refresh not visible list
// when some changes occur in it.
list->setForceRefresh(true);
}
} }
bool LLOutfitsList::canWearSelected() bool LLOutfitsList::canWearSelected()
@ -698,11 +669,10 @@ void LLOutfitsList::onCOFChanged()
// These links UUIDs are not the same UUIDs that we have in each wearable items list. // These links UUIDs are not the same UUIDs that we have in each wearable items list.
// So we collect base items' UUIDs to find them or links that point to them in wearable // So we collect base items' UUIDs to find them or links that point to them in wearable
// items lists and update their worn state there. // items lists and update their worn state there.
for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); LLInventoryModel::item_array_t::const_iterator array_iter = item_array.begin(), array_end = item_array.end();
iter != item_array.end(); while (array_iter < array_end)
++iter)
{ {
vnew.push_back((*iter)->getLinkedUUID()); vnew.push_back((*(array_iter++))->getLinkedUUID());
} }
// We need to update only items that were added or removed from COF. // We need to update only items that were added or removed from COF.
@ -711,20 +681,20 @@ void LLOutfitsList::onCOFChanged()
// Store the ids of items currently linked from COF. // Store the ids of items currently linked from COF.
mCOFLinkedItems = vnew; mCOFLinkedItems = vnew;
for (outfits_map_t::iterator iter = mOutfitsMap.begin(); // Append removed ids to added ids because we should update all of them.
iter != mOutfitsMap.end(); vadded.reserve(vadded.size() + vremoved.size());
++iter) vadded.insert(vadded.end(), vremoved.begin(), vremoved.end());
vremoved.clear();
outfits_map_t::iterator map_iter = mOutfitsMap.begin(), map_end = mOutfitsMap.end();
while (map_iter != map_end)
{ {
LLAccordionCtrlTab* tab = iter->second; LLAccordionCtrlTab* tab = (map_iter++)->second;
if (!tab) continue; if (!tab) continue;
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (!list) continue; if (!list) continue;
// Append removed ids to added ids because we should update all of them.
vadded.reserve(vadded.size() + vremoved.size());
vadded.insert(vadded.end(), vremoved.begin(), vremoved.end());
// Every list updates the labels of changed items or // Every list updates the labels of changed items or
// the links that point to these items. // the links that point to these items.
list->updateChangedItems(vadded); list->updateChangedItems(vadded);
@ -835,7 +805,6 @@ void LLOutfitListBase::onOpen(const LLSD& info)
// arrive. // arrive.
category->fetch(); category->fetch();
refreshList(outfits); refreshList(outfits);
highlightBaseOutfit();
mIsInitialized = true; mIsInitialized = true;
} }
@ -843,6 +812,9 @@ void LLOutfitListBase::onOpen(const LLSD& info)
void LLOutfitListBase::refreshList(const LLUUID& category_id) void LLOutfitListBase::refreshList(const LLUUID& category_id)
{ {
bool wasNull = mRefreshListState.CategoryUUID.isNull();
mRefreshListState.CategoryUUID.setNull();
LLInventoryModel::cat_array_t cat_array; LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array; LLInventoryModel::item_array_t item_array;
@ -855,27 +827,81 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
LLInventoryModel::EXCLUDE_TRASH, LLInventoryModel::EXCLUDE_TRASH,
is_category); is_category);
uuid_vec_t vadded; // Memorize item names for each UUID
uuid_vec_t vremoved; std::map<LLUUID, std::string> names;
for (const LLPointer<LLViewerInventoryCategory>& cat : cat_array)
{
names.emplace(std::make_pair(cat->getUUID(), cat->getName()));
}
// Create added and removed items vectors. // Fill added and removed items vectors.
computeDifference(cat_array, vadded, vremoved); mRefreshListState.Added.clear();
mRefreshListState.Removed.clear();
computeDifference(cat_array, mRefreshListState.Added, mRefreshListState.Removed);
// Sort added items vector by item name.
std::sort(mRefreshListState.Added.begin(), mRefreshListState.Added.end(),
[names](const LLUUID& a, const LLUUID& b)
{
return LLStringUtil::compareDict(names.at(a), names.at(b)) < 0;
});
// Initialize iterators for added and removed items vectors.
mRefreshListState.AddedIterator = mRefreshListState.Added.begin();
mRefreshListState.RemovedIterator = mRefreshListState.Removed.begin();
LL_INFOS() << "added: " << mRefreshListState.Added.size() <<
", removed: " << mRefreshListState.Removed.size() <<
", changed: " << gInventory.getChangedIDs().size() <<
LL_ENDL;
mRefreshListState.CategoryUUID = category_id;
if (wasNull)
{
gIdleCallbacks.addFunction(onIdle, this);
}
}
// static
void LLOutfitListBase::onIdle(void* userdata)
{
LLOutfitListBase* self = (LLOutfitListBase*)userdata;
self->onIdleRefreshList();
}
void LLOutfitListBase::onIdleRefreshList()
{
if (mRefreshListState.CategoryUUID.isNull())
return;
const F64 MAX_TIME = 0.05f;
F64 curent_time = LLTimer::getTotalSeconds();
const F64 end_time = curent_time + MAX_TIME;
// Handle added tabs. // Handle added tabs.
for (uuid_vec_t::const_iterator iter = vadded.begin(); while (mRefreshListState.AddedIterator < mRefreshListState.Added.end())
iter != vadded.end();
++iter)
{ {
const LLUUID cat_id = (*iter); const LLUUID cat_id = (*mRefreshListState.AddedIterator++);
updateAddedCategory(cat_id); updateAddedCategory(cat_id);
curent_time = LLTimer::getTotalSeconds();
if (curent_time >= end_time)
return;
} }
mRefreshListState.Added.clear();
mRefreshListState.AddedIterator = mRefreshListState.Added.end();
// Handle removed tabs. // Handle removed tabs.
for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) while (mRefreshListState.RemovedIterator < mRefreshListState.Removed.end())
{ {
const LLUUID cat_id = (*iter); const LLUUID cat_id = (*mRefreshListState.RemovedIterator++);
updateRemovedCategory(cat_id); updateRemovedCategory(cat_id);
curent_time = LLTimer::getTotalSeconds();
if (curent_time >= end_time)
return;
} }
mRefreshListState.Removed.clear();
mRefreshListState.RemovedIterator = mRefreshListState.Removed.end();
// Get changed items from inventory model and update outfit tabs // Get changed items from inventory model and update outfit tabs
// which might have been renamed. // which might have been renamed.
@ -888,9 +914,9 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
if (!cat) if (!cat)
{ {
LLInventoryObject* obj = gInventory.getObject(*items_iter); LLInventoryObject* obj = gInventory.getObject(*items_iter);
if(!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY))
{ {
return; break;
} }
cat = (LLViewerInventoryCategory*)obj; cat = (LLViewerInventoryCategory*)obj;
} }
@ -900,6 +926,12 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
} }
sortOutfits(); sortOutfits();
highlightBaseOutfit();
gIdleCallbacks.deleteFunction(onIdle, this);
mRefreshListState.CategoryUUID.setNull();
LL_INFOS() << "done" << LL_ENDL;
} }
void LLOutfitListBase::computeDifference( void LLOutfitListBase::computeDifference(
@ -936,7 +968,6 @@ void LLOutfitListBase::highlightBaseOutfit()
mHighlightedOutfitUUID = base_id; mHighlightedOutfitUUID = base_id;
onHighlightBaseOutfit(base_id, prev_id); onHighlightBaseOutfit(base_id, prev_id);
} }
} }
void LLOutfitListBase::removeSelected() void LLOutfitListBase::removeSelected()

View File

@ -116,8 +116,20 @@ protected:
void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0; virtual void onChangeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id) = 0;
static void onIdle(void* userdata);
void onIdleRefreshList();
struct
{
LLUUID CategoryUUID;
uuid_vec_t Added;
uuid_vec_t Removed;
uuid_vec_t::const_iterator AddedIterator;
uuid_vec_t::const_iterator RemovedIterator;
} mRefreshListState;
bool mIsInitialized; bool mIsInitialized;
LLInventoryCategoriesObserver* mCategoriesObserver; LLInventoryCategoriesObserver* mCategoriesObserver;
LLUUID mSelectedOutfitUUID; LLUUID mSelectedOutfitUUID;
// id of currently highlited outfit // id of currently highlited outfit
LLUUID mHighlightedOutfitUUID; LLUUID mHighlightedOutfitUUID;
@ -225,7 +237,7 @@ public:
//void performAction(std::string action); //void performAction(std::string action);
/*virtual*/ void setFilterSubString(const std::string& string); /*virtual*/ void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string);
/*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const; /*virtual*/ void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const;
@ -295,12 +307,7 @@ private:
* Called upon list refresh event to update tab visibility depending on * Called upon list refresh event to update tab visibility depending on
* the results of applying filter to the title and list items of the tab. * the results of applying filter to the title and list items of the tab.
*/ */
void onFilteredWearableItemsListRefresh(LLUICtrl* ctrl); void onRefreshComplete(LLUICtrl* ctrl);
/**
* Highlights filtered items and hides tabs which haven't passed filter.
*/
void applyFilter(const std::string& new_filter_substring);
/** /**
* Applies filter to the given tab * Applies filter to the given tab

View File

@ -28,12 +28,35 @@
#include "llpanelappearancetab.h" #include "llpanelappearancetab.h"
#include "llinventoryfunctions.h" #include "llinventoryfunctions.h"
#include "llinventorymodel.h" #include "llinventorymodel.h"
#include "llviewerinventory.h" #include "llviewerinventory.h"
//virtual std::string LLPanelAppearanceTab::sRecentFilterSubString;
void LLPanelAppearanceTab::setFilterSubString(const std::string& new_string)
{
if (new_string != mFilterSubString)
{
std::string old_string = mFilterSubString;
mFilterSubString = new_string;
onFilterSubStringChanged(mFilterSubString, old_string);
}
sRecentFilterSubString = new_string;
}
void LLPanelAppearanceTab::checkFilterSubString()
{
if (sRecentFilterSubString != mFilterSubString)
{
std::string old_string = mFilterSubString;
mFilterSubString = sRecentFilterSubString;
onFilterSubStringChanged(mFilterSubString, old_string);
}
}
// virtual
bool LLPanelAppearanceTab::canTakeOffSelected() bool LLPanelAppearanceTab::canTakeOffSelected()
{ {
uuid_vec_t selected_uuids; uuid_vec_t selected_uuids;

View File

@ -35,13 +35,17 @@ public:
LLPanelAppearanceTab() : LLPanel() {} LLPanelAppearanceTab() : LLPanel() {}
virtual ~LLPanelAppearanceTab() {} virtual ~LLPanelAppearanceTab() {}
virtual void setFilterSubString(const std::string& string) = 0; void setFilterSubString(const std::string& new_string);
void checkFilterSubString();
virtual void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string) = 0;
virtual bool isActionEnabled(const LLSD& userdata) = 0; virtual bool isActionEnabled(const LLSD& userdata) = 0;
virtual void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const {} virtual void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const {}
static const std::string& getFilterSubString() { return sFilterSubString; } const std::string& getFilterSubString() { return mFilterSubString; }
protected: protected:
@ -50,7 +54,10 @@ protected:
*/ */
bool canTakeOffSelected(); bool canTakeOffSelected();
static std::string sFilterSubString; private:
std::string mFilterSubString;
static std::string sRecentFilterSubString;
}; };
#endif //LL_LLPANELAPPEARANCETAB_H #endif //LL_LLPANELAPPEARANCETAB_H

View File

@ -97,7 +97,7 @@ enum ESubpart {
SUBPART_SKIRT, SUBPART_SKIRT,
SUBPART_ALPHA, SUBPART_ALPHA,
SUBPART_TATTOO, SUBPART_TATTOO,
SUBPART_UNIVERSAL, SUBPART_UNIVERSAL,
SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_UPDOWN,
SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_INOUT,
SUBPART_PHYSICS_BREASTS_LEFTRIGHT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT,
@ -120,7 +120,7 @@ class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary>
//-------------------------------------------------------------------- //--------------------------------------------------------------------
LLSINGLETON(LLEditWearableDictionary); LLSINGLETON(LLEditWearableDictionary);
virtual ~LLEditWearableDictionary(); virtual ~LLEditWearableDictionary();
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Wearable Types // Wearable Types
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -214,7 +214,6 @@ public:
LLEditWearableDictionary::LLEditWearableDictionary() LLEditWearableDictionary::LLEditWearableDictionary()
{ {
} }
//virtual //virtual
@ -227,23 +226,23 @@ LLEditWearableDictionary::Wearables::Wearables()
// note the subpart that is listed first is treated as "default", regardless of what order is in enum. // note the subpart that is listed first is treated as "default", regardless of what order is in enum.
// Please match the order presented in XUI. -Nyx // Please match the order presented in XUI. -Nyx
// this will affect what camera angle is shown when first editing a wearable // this will affect what camera angle is shown when first editing a wearable
addEntry(LLWearableType::WT_SHAPE, new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS})); addEntry(LLWearableType::WT_SHAPE, new WearableEntry(LLWearableType::WT_SHAPE,"edit_shape_title","shape_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{SUBPART_SHAPE_WHOLE, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS}));
addEntry(LLWearableType::WT_SKIN, new WearableEntry(LLWearableType::WT_SKIN,"edit_skin_title","skin_desc_text", texture_vec_t(), texture_vec_t{TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT}, subpart_vec_t{SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL})); addEntry(LLWearableType::WT_SKIN, new WearableEntry(LLWearableType::WT_SKIN,"edit_skin_title","skin_desc_text", texture_vec_t(), texture_vec_t{TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT}, subpart_vec_t{SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL}));
addEntry(LLWearableType::WT_HAIR, new WearableEntry(LLWearableType::WT_HAIR,"edit_hair_title","hair_desc_text", texture_vec_t(), texture_vec_t{TEX_HAIR}, subpart_vec_t{SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL})); addEntry(LLWearableType::WT_HAIR, new WearableEntry(LLWearableType::WT_HAIR,"edit_hair_title","hair_desc_text", texture_vec_t(), texture_vec_t{TEX_HAIR}, subpart_vec_t{SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL}));
addEntry(LLWearableType::WT_EYES, new WearableEntry(LLWearableType::WT_EYES,"edit_eyes_title","eyes_desc_text", texture_vec_t(), texture_vec_t{TEX_EYES_IRIS}, subpart_vec_t{SUBPART_EYES})); addEntry(LLWearableType::WT_EYES, new WearableEntry(LLWearableType::WT_EYES,"edit_eyes_title","eyes_desc_text", texture_vec_t(), texture_vec_t{TEX_EYES_IRIS}, subpart_vec_t{SUBPART_EYES}));
addEntry(LLWearableType::WT_SHIRT, new WearableEntry(LLWearableType::WT_SHIRT,"edit_shirt_title","shirt_desc_text", texture_vec_t{TEX_UPPER_SHIRT}, texture_vec_t{TEX_UPPER_SHIRT}, subpart_vec_t{SUBPART_SHIRT})); addEntry(LLWearableType::WT_SHIRT, new WearableEntry(LLWearableType::WT_SHIRT,"edit_shirt_title","shirt_desc_text", texture_vec_t{TEX_UPPER_SHIRT}, texture_vec_t{TEX_UPPER_SHIRT}, subpart_vec_t{SUBPART_SHIRT}));
addEntry(LLWearableType::WT_PANTS, new WearableEntry(LLWearableType::WT_PANTS,"edit_pants_title","pants_desc_text", texture_vec_t{TEX_LOWER_PANTS}, texture_vec_t{TEX_LOWER_PANTS}, subpart_vec_t{SUBPART_PANTS})); addEntry(LLWearableType::WT_PANTS, new WearableEntry(LLWearableType::WT_PANTS,"edit_pants_title","pants_desc_text", texture_vec_t{TEX_LOWER_PANTS}, texture_vec_t{TEX_LOWER_PANTS}, subpart_vec_t{SUBPART_PANTS}));
addEntry(LLWearableType::WT_SHOES, new WearableEntry(LLWearableType::WT_SHOES,"edit_shoes_title","shoes_desc_text", texture_vec_t{TEX_LOWER_SHOES}, texture_vec_t{TEX_LOWER_SHOES}, subpart_vec_t{SUBPART_SHOES})); addEntry(LLWearableType::WT_SHOES, new WearableEntry(LLWearableType::WT_SHOES,"edit_shoes_title","shoes_desc_text", texture_vec_t{TEX_LOWER_SHOES}, texture_vec_t{TEX_LOWER_SHOES}, subpart_vec_t{SUBPART_SHOES}));
addEntry(LLWearableType::WT_SOCKS, new WearableEntry(LLWearableType::WT_SOCKS,"edit_socks_title","socks_desc_text", texture_vec_t{TEX_LOWER_SOCKS}, texture_vec_t{TEX_LOWER_SOCKS}, subpart_vec_t{SUBPART_SOCKS})); addEntry(LLWearableType::WT_SOCKS, new WearableEntry(LLWearableType::WT_SOCKS,"edit_socks_title","socks_desc_text", texture_vec_t{TEX_LOWER_SOCKS}, texture_vec_t{TEX_LOWER_SOCKS}, subpart_vec_t{SUBPART_SOCKS}));
addEntry(LLWearableType::WT_JACKET, new WearableEntry(LLWearableType::WT_JACKET,"edit_jacket_title","jacket_desc_text", texture_vec_t{TEX_UPPER_JACKET}, texture_vec_t{TEX_UPPER_JACKET, TEX_LOWER_JACKET}, subpart_vec_t{SUBPART_JACKET})); addEntry(LLWearableType::WT_JACKET, new WearableEntry(LLWearableType::WT_JACKET,"edit_jacket_title","jacket_desc_text", texture_vec_t{TEX_UPPER_JACKET}, texture_vec_t{TEX_UPPER_JACKET, TEX_LOWER_JACKET}, subpart_vec_t{SUBPART_JACKET}));
addEntry(LLWearableType::WT_GLOVES, new WearableEntry(LLWearableType::WT_GLOVES,"edit_gloves_title","gloves_desc_text", texture_vec_t{TEX_UPPER_GLOVES}, texture_vec_t{TEX_UPPER_GLOVES}, subpart_vec_t{SUBPART_GLOVES})); addEntry(LLWearableType::WT_GLOVES, new WearableEntry(LLWearableType::WT_GLOVES,"edit_gloves_title","gloves_desc_text", texture_vec_t{TEX_UPPER_GLOVES}, texture_vec_t{TEX_UPPER_GLOVES}, subpart_vec_t{SUBPART_GLOVES}));
addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(LLWearableType::WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text", texture_vec_t{TEX_UPPER_UNDERSHIRT}, texture_vec_t{TEX_UPPER_UNDERSHIRT}, subpart_vec_t{SUBPART_UNDERSHIRT})); addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(LLWearableType::WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text", texture_vec_t{TEX_UPPER_UNDERSHIRT}, texture_vec_t{TEX_UPPER_UNDERSHIRT}, subpart_vec_t{SUBPART_UNDERSHIRT}));
addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(LLWearableType::WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text", texture_vec_t{TEX_LOWER_UNDERPANTS}, texture_vec_t{TEX_LOWER_UNDERPANTS}, subpart_vec_t{SUBPART_UNDERPANTS})); addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(LLWearableType::WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text", texture_vec_t{TEX_LOWER_UNDERPANTS}, texture_vec_t{TEX_LOWER_UNDERPANTS}, subpart_vec_t{SUBPART_UNDERPANTS}));
addEntry(LLWearableType::WT_SKIRT, new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title","skirt_desc_text", texture_vec_t{TEX_SKIRT}, texture_vec_t{TEX_SKIRT}, subpart_vec_t{SUBPART_SKIRT})); addEntry(LLWearableType::WT_SKIRT, new WearableEntry(LLWearableType::WT_SKIRT,"edit_skirt_title","skirt_desc_text", texture_vec_t{TEX_SKIRT}, texture_vec_t{TEX_SKIRT}, subpart_vec_t{SUBPART_SKIRT}));
addEntry(LLWearableType::WT_ALPHA, new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title","alpha_desc_text", texture_vec_t(), texture_vec_t{TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA}, subpart_vec_t{SUBPART_ALPHA})); addEntry(LLWearableType::WT_ALPHA, new WearableEntry(LLWearableType::WT_ALPHA,"edit_alpha_title","alpha_desc_text", texture_vec_t(), texture_vec_t{TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA}, subpart_vec_t{SUBPART_ALPHA}));
addEntry(LLWearableType::WT_TATTOO, new WearableEntry(LLWearableType::WT_TATTOO,"edit_tattoo_title","tattoo_desc_text", texture_vec_t{TEX_HEAD_TATTOO}, texture_vec_t{TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO}, subpart_vec_t{SUBPART_TATTOO})); addEntry(LLWearableType::WT_TATTOO, new WearableEntry(LLWearableType::WT_TATTOO,"edit_tattoo_title","tattoo_desc_text", texture_vec_t{TEX_HEAD_TATTOO}, texture_vec_t{TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO}, subpart_vec_t{SUBPART_TATTOO}));
addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(LLWearableType::WT_UNIVERSAL, "edit_universal_title", "universal_desc_text", texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO }, texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO, TEX_UPPER_UNIVERSAL_TATTOO, TEX_LOWER_UNIVERSAL_TATTOO, TEX_SKIRT_TATTOO, TEX_HAIR_TATTOO, TEX_EYES_TATTOO, TEX_LEFT_ARM_TATTOO, TEX_LEFT_LEG_TATTOO, TEX_AUX1_TATTOO, TEX_AUX2_TATTOO, TEX_AUX3_TATTOO }, subpart_vec_t{ SUBPART_UNIVERSAL })); addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(LLWearableType::WT_UNIVERSAL, "edit_universal_title", "universal_desc_text", texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO }, texture_vec_t{ TEX_HEAD_UNIVERSAL_TATTOO, TEX_UPPER_UNIVERSAL_TATTOO, TEX_LOWER_UNIVERSAL_TATTOO, TEX_SKIRT_TATTOO, TEX_HAIR_TATTOO, TEX_EYES_TATTOO, TEX_LEFT_ARM_TATTOO, TEX_LEFT_LEG_TATTOO, TEX_AUX1_TATTOO, TEX_AUX2_TATTOO, TEX_AUX3_TATTOO }, subpart_vec_t{ SUBPART_UNIVERSAL }));
addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(LLWearableType::WT_PHYSICS,"edit_physics_title","physics_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED})); addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(LLWearableType::WT_PHYSICS, "edit_physics_title", "physics_desc_text", texture_vec_t(), texture_vec_t(), subpart_vec_t{ SUBPART_PHYSICS_BREASTS_UPDOWN, SUBPART_PHYSICS_BREASTS_INOUT, SUBPART_PHYSICS_BREASTS_LEFTRIGHT, SUBPART_PHYSICS_BELLY_UPDOWN, SUBPART_PHYSICS_BUTT_UPDOWN, SUBPART_PHYSICS_BUTT_LEFTRIGHT, SUBPART_PHYSICS_ADVANCED }));
} }
LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType type, LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType type,
@ -259,52 +258,59 @@ LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType typ
mSubparts(subparts), mSubparts(subparts),
mColorSwatchCtrls(color_swatches), mColorSwatchCtrls(color_swatches),
mTextureCtrls(texture_pickers) mTextureCtrls(texture_pickers)
{} {
}
LLEditWearableDictionary::Subparts::Subparts() LLEditWearableDictionary::Subparts::Subparts()
{ {
addEntry(SUBPART_SHAPE_WHOLE, new SubpartEntry(SUBPART_SHAPE_WHOLE, "mPelvis", "shape_body","shape_body_param_list", "shape_body_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); // WT_SHAPE
addEntry(SUBPART_SHAPE_HEAD, new SubpartEntry(SUBPART_SHAPE_HEAD, "mHead", "shape_head", "shape_head_param_list", "shape_head_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SHAPE_WHOLE, new SubpartEntry(SUBPART_SHAPE_WHOLE, "mPelvis", "shape_body","shape_body_param_list", "shape_body_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
addEntry(SUBPART_SHAPE_EYES, new SubpartEntry(SUBPART_SHAPE_EYES, "mHead", "shape_eyes", "shape_eyes_param_list", "shape_eyes_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SHAPE_HEAD, new SubpartEntry(SUBPART_SHAPE_HEAD, "mHead", "shape_head", "shape_head_param_list", "shape_head_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_EARS, new SubpartEntry(SUBPART_SHAPE_EARS, "mHead", "shape_ears", "shape_ears_param_list", "shape_ears_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SHAPE_EYES, new SubpartEntry(SUBPART_SHAPE_EYES, "mHead", "shape_eyes", "shape_eyes_param_list", "shape_eyes_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_NOSE, new SubpartEntry(SUBPART_SHAPE_NOSE, "mHead", "shape_nose", "shape_nose_param_list", "shape_nose_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SHAPE_EARS, new SubpartEntry(SUBPART_SHAPE_EARS, "mHead", "shape_ears", "shape_ears_param_list", "shape_ears_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_MOUTH, new SubpartEntry(SUBPART_SHAPE_MOUTH, "mHead", "shape_mouth", "shape_mouth_param_list", "shape_mouth_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SHAPE_NOSE, new SubpartEntry(SUBPART_SHAPE_NOSE, "mHead", "shape_nose", "shape_nose_param_list", "shape_nose_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_CHIN, new SubpartEntry(SUBPART_SHAPE_CHIN, "mHead", "shape_chin", "shape_chin_param_list", "shape_chin_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SHAPE_MOUTH, new SubpartEntry(SUBPART_SHAPE_MOUTH, "mHead", "shape_mouth", "shape_mouth_param_list", "shape_mouth_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_TORSO, new SubpartEntry(SUBPART_SHAPE_TORSO, "mTorso", "shape_torso", "shape_torso_param_list", "shape_torso_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); addEntry(SUBPART_SHAPE_CHIN, new SubpartEntry(SUBPART_SHAPE_CHIN, "mHead", "shape_chin", "shape_chin_param_list", "shape_chin_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHAPE_LEGS, new SubpartEntry(SUBPART_SHAPE_LEGS, "mPelvis", "shape_legs", "shape_legs_param_list", "shape_legs_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); addEntry(SUBPART_SHAPE_TORSO, new SubpartEntry(SUBPART_SHAPE_TORSO, "mTorso", "shape_torso", "shape_torso_param_list", "shape_torso_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
addEntry(SUBPART_SHAPE_LEGS, new SubpartEntry(SUBPART_SHAPE_LEGS, "mPelvis", "shape_legs", "shape_legs_param_list", "shape_legs_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_SKIN_COLOR, new SubpartEntry(SUBPART_SKIN_COLOR, "mHead", "skin_color", "skin_color_param_list", "skin_color_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); // WT_SKIN
addEntry(SUBPART_SKIN_COLOR, new SubpartEntry(SUBPART_SKIN_COLOR, "mHead", "skin_color", "skin_color_param_list", "skin_color_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SKIN_FACEDETAIL, new SubpartEntry(SUBPART_SKIN_FACEDETAIL, "mHead", "skin_facedetail", "skin_face_param_list", "skin_face_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SKIN_FACEDETAIL, new SubpartEntry(SUBPART_SKIN_FACEDETAIL, "mHead", "skin_facedetail", "skin_face_param_list", "skin_face_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SKIN_MAKEUP, new SubpartEntry(SUBPART_SKIN_MAKEUP, "mHead", "skin_makeup", "skin_makeup_param_list", "skin_makeup_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_SKIN_MAKEUP, new SubpartEntry(SUBPART_SKIN_MAKEUP, "mHead", "skin_makeup", "skin_makeup_param_list", "skin_makeup_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SKIN_BODYDETAIL, new SubpartEntry(SUBPART_SKIN_BODYDETAIL, "mPelvis", "skin_bodydetail", "skin_body_param_list", "skin_body_tab", LLVector3d(0.f, 0.f, -0.2f), LLVector3d(-2.5f, 0.5f, 0.5f),SEX_BOTH)); addEntry(SUBPART_SKIN_BODYDETAIL, new SubpartEntry(SUBPART_SKIN_BODYDETAIL, "mPelvis", "skin_bodydetail", "skin_body_param_list", "skin_body_tab", LLVector3d(0.f, 0.f, -0.2f), LLVector3d(-2.5f, 0.5f, 0.5f),SEX_BOTH));
addEntry(SUBPART_HAIR_COLOR, new SubpartEntry(SUBPART_HAIR_COLOR, "mHead", "hair_color", "hair_color_param_list", "hair_color_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH)); // WT_HAIR
addEntry(SUBPART_HAIR_STYLE, new SubpartEntry(SUBPART_HAIR_STYLE, "mHead", "hair_style", "hair_style_param_list", "hair_style_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH)); addEntry(SUBPART_HAIR_COLOR, new SubpartEntry(SUBPART_HAIR_COLOR, "mHead", "hair_color", "hair_color_param_list", "hair_color_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f),SEX_BOTH));
addEntry(SUBPART_HAIR_EYEBROWS, new SubpartEntry(SUBPART_HAIR_EYEBROWS, "mHead", "hair_eyebrows", "hair_eyebrows_param_list", "hair_eyebrows_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); addEntry(SUBPART_HAIR_STYLE, new SubpartEntry(SUBPART_HAIR_STYLE, "mHead", "hair_style", "hair_style_param_list", "hair_style_tab", LLVector3d(0.f, 0.f, 0.10f), LLVector3d(-0.4f, 0.05f, 0.10f), SEX_BOTH));
addEntry(SUBPART_HAIR_FACIAL, new SubpartEntry(SUBPART_HAIR_FACIAL, "mHead", "hair_facial", "hair_facial_param_list", "hair_facial_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_MALE)); addEntry(SUBPART_HAIR_EYEBROWS, new SubpartEntry(SUBPART_HAIR_EYEBROWS, "mHead", "hair_eyebrows", "hair_eyebrows_param_list", "hair_eyebrows_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_HAIR_FACIAL, new SubpartEntry(SUBPART_HAIR_FACIAL, "mHead", "hair_facial", "hair_facial_param_list", "hair_facial_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_MALE));
addEntry(SUBPART_EYES, new SubpartEntry(SUBPART_EYES, "mHead", "eyes", "eyes_main_param_list", "eyes_main_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH)); // WT_EYES
addEntry(SUBPART_EYES, new SubpartEntry(SUBPART_EYES, "mHead", "eyes", "eyes_main_param_list", "eyes_main_tab", LLVector3d(0.f, 0.f, 0.05f), LLVector3d(-0.5f, 0.05f, 0.07f),SEX_BOTH));
addEntry(SUBPART_SHIRT, new SubpartEntry(SUBPART_SHIRT, "mTorso", "shirt", "shirt_main_param_list", "shirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); // WT_SHIRT, WT_PANTS, WT_SHOES, WT_SOCKS, WT_JACKET, WT_GLOVES, WT_UNDERSHIRT, WT_UNDERPANTS, WT_SKIRT, WT_ALPHA, WT_TATTOO, WT_UNIVERSAL
addEntry(SUBPART_PANTS, new SubpartEntry(SUBPART_PANTS, "mPelvis", "pants", "pants_main_param_list", "pants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); addEntry(SUBPART_SHIRT, new SubpartEntry(SUBPART_SHIRT, "mTorso", "shirt", "shirt_main_param_list", "shirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
addEntry(SUBPART_SHOES, new SubpartEntry(SUBPART_SHOES, "mPelvis", "shoes", "shoes_main_param_list", "shoes_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); addEntry(SUBPART_PANTS, new SubpartEntry(SUBPART_PANTS, "mPelvis", "pants", "pants_main_param_list", "pants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_SOCKS, new SubpartEntry(SUBPART_SOCKS, "mPelvis", "socks", "socks_main_param_list", "socks_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); addEntry(SUBPART_SHOES, new SubpartEntry(SUBPART_SHOES, "mPelvis", "shoes", "shoes_main_param_list", "shoes_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_JACKET, new SubpartEntry(SUBPART_JACKET, "mTorso", "jacket", "jacket_main_param_list", "jacket_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-2.f, 0.1f, 0.3f),SEX_BOTH)); addEntry(SUBPART_SOCKS, new SubpartEntry(SUBPART_SOCKS, "mPelvis", "socks", "socks_main_param_list", "socks_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_SKIRT, new SubpartEntry(SUBPART_SKIRT, "mPelvis", "skirt", "skirt_main_param_list", "skirt_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); addEntry(SUBPART_JACKET, new SubpartEntry(SUBPART_JACKET, "mTorso", "jacket", "jacket_main_param_list", "jacket_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-2.f, 0.1f, 0.3f),SEX_BOTH));
addEntry(SUBPART_GLOVES, new SubpartEntry(SUBPART_GLOVES, "mTorso", "gloves", "gloves_main_param_list", "gloves_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-1.f, 0.15f, 0.f),SEX_BOTH)); addEntry(SUBPART_GLOVES, new SubpartEntry(SUBPART_GLOVES, "mTorso", "gloves", "gloves_main_param_list", "gloves_main_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(-1.f, 0.15f, 0.f),SEX_BOTH));
addEntry(SUBPART_UNDERSHIRT, new SubpartEntry(SUBPART_UNDERSHIRT, "mTorso", "undershirt", "undershirt_main_param_list", "undershirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH)); addEntry(SUBPART_UNDERSHIRT, new SubpartEntry(SUBPART_UNDERSHIRT, "mTorso", "undershirt", "undershirt_main_param_list", "undershirt_main_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(-1.f, 0.15f, 0.3f),SEX_BOTH));
addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH)); addEntry(SUBPART_UNDERPANTS, new SubpartEntry(SUBPART_UNDERPANTS, "mPelvis", "underpants", "underpants_main_param_list", "underpants_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); addEntry(SUBPART_SKIRT, new SubpartEntry(SUBPART_SKIRT, "mPelvis", "skirt", "skirt_main_param_list", "skirt_main_tab", LLVector3d(0.f, 0.f, -0.5f), LLVector3d(-1.6f, 0.15f, -0.5f),SEX_BOTH));
addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH)); addEntry(SUBPART_ALPHA, new SubpartEntry(SUBPART_ALPHA, "mPelvis", "alpha", "alpha_main_param_list", "alpha_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", "universal_main_param_list", "universal_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH)); addEntry(SUBPART_TATTOO, new SubpartEntry(SUBPART_TATTOO, "mPelvis", "tattoo", "tattoo_main_param_list", "tattoo_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f),SEX_BOTH));
addEntry(SUBPART_UNIVERSAL, new SubpartEntry(SUBPART_UNIVERSAL, "mPelvis", "universal", "universal_main_param_list", "universal_main_tab", LLVector3d(0.f, 0.f, 0.1f), LLVector3d(-2.5f, 0.5f, 0.8f), SEX_BOTH));
addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "physics_breasts_updown_param_list", "physics_breasts_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); // WT_PHYSICS
addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "physics_breasts_inout_param_list", "physics_breasts_inout_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); addEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BREASTS_UPDOWN, "mTorso", "physics_breasts_updown", "physics_breasts_updown_param_list", "physics_breasts_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f), SEX_FEMALE));
addEntry(SUBPART_PHYSICS_BREASTS_INOUT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_INOUT, "mTorso", "physics_breasts_inout", "physics_breasts_inout_param_list", "physics_breasts_inout_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE));
addEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, "mTorso", "physics_breasts_leftright", "physics_breasts_leftright_param_list", "physics_breasts_leftright_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE)); addEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BREASTS_LEFTRIGHT, "mTorso", "physics_breasts_leftright", "physics_breasts_leftright_param_list", "physics_breasts_leftright_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_FEMALE));
addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); addEntry(SUBPART_PHYSICS_BELLY_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BELLY_UPDOWN, "mTorso", "physics_belly_updown", "physics_belly_updown_param_list", "physics_belly_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); addEntry(SUBPART_PHYSICS_BUTT_UPDOWN, new SubpartEntry(SUBPART_PHYSICS_BUTT_UPDOWN, "mTorso", "physics_butt_updown", "physics_butt_updown_param_list", "physics_butt_updown_tab", LLVector3d(0.f, 0.f, 0.3f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
addEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, "mTorso", "physics_butt_leftright", "physics_butt_leftright_param_list", "physics_butt_leftright_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); addEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, new SubpartEntry(SUBPART_PHYSICS_BUTT_LEFTRIGHT, "mTorso", "physics_butt_leftright", "physics_butt_leftright_param_list", "physics_butt_leftright_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
addEntry(SUBPART_PHYSICS_ADVANCED, new SubpartEntry(SUBPART_PHYSICS_ADVANCED, "mTorso", "physics_advanced", "physics_advanced_param_list", "physics_advanced_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH)); addEntry(SUBPART_PHYSICS_ADVANCED, new SubpartEntry(SUBPART_PHYSICS_ADVANCED, "mTorso", "physics_advanced", "physics_advanced_param_list", "physics_advanced_tab", LLVector3d(0.f, 0.f, 0.f), LLVector3d(0.f, 0.f, 0.f),SEX_BOTH));
} }
LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part, LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
@ -329,55 +335,55 @@ LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls() LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls()
{ {
addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Color/Tint" )); addEntry(TEX_UPPER_SHIRT, new PickerControlEntry(TEX_UPPER_SHIRT, "Color/Tint"));
addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Color/Tint" )); addEntry(TEX_LOWER_PANTS, new PickerControlEntry(TEX_LOWER_PANTS, "Color/Tint"));
addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Color/Tint" )); addEntry(TEX_LOWER_SHOES, new PickerControlEntry(TEX_LOWER_SHOES, "Color/Tint"));
addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Color/Tint" )); addEntry(TEX_LOWER_SOCKS, new PickerControlEntry(TEX_LOWER_SOCKS, "Color/Tint"));
addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Color/Tint" )); addEntry(TEX_UPPER_JACKET, new PickerControlEntry(TEX_UPPER_JACKET, "Color/Tint"));
addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Color/Tint" )); addEntry(TEX_SKIRT, new PickerControlEntry(TEX_SKIRT, "Color/Tint"));
addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Color/Tint" )); addEntry(TEX_UPPER_GLOVES, new PickerControlEntry(TEX_UPPER_GLOVES, "Color/Tint"));
addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Color/Tint" )); addEntry(TEX_UPPER_UNDERSHIRT, new PickerControlEntry(TEX_UPPER_UNDERSHIRT, "Color/Tint"));
addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Color/Tint" )); addEntry(TEX_LOWER_UNDERPANTS, new PickerControlEntry(TEX_LOWER_UNDERPANTS, "Color/Tint"));
addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Color/Tint" )); addEntry(TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Color/Tint"));
addEntry (TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint")); addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint"));
} }
LLEditWearableDictionary::TextureCtrls::TextureCtrls() LLEditWearableDictionary::TextureCtrls::TextureCtrls()
{ {
addEntry ( TEX_HEAD_BODYPAINT, new PickerControlEntry (TEX_HEAD_BODYPAINT, "Head", LLUUID::null, TRUE )); addEntry(TEX_HEAD_BODYPAINT, new PickerControlEntry(TEX_HEAD_BODYPAINT, "Head", LLUUID::null, TRUE));
addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Body", LLUUID::null, TRUE )); addEntry(TEX_UPPER_BODYPAINT, new PickerControlEntry(TEX_UPPER_BODYPAINT, "Upper Body", LLUUID::null, TRUE));
addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Body", LLUUID::null, TRUE )); addEntry(TEX_LOWER_BODYPAINT, new PickerControlEntry(TEX_LOWER_BODYPAINT, "Lower Body", LLUUID::null, TRUE));
addEntry ( TEX_HAIR, new PickerControlEntry (TEX_HAIR, "Texture", LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ), FALSE )); addEntry(TEX_HAIR, new PickerControlEntry(TEX_HAIR, "Texture", LLUUID(gSavedSettings.getString("UIImgDefaultHairUUID")), FALSE));
addEntry ( TEX_EYES_IRIS, new PickerControlEntry (TEX_EYES_IRIS, "Iris", LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ), FALSE )); addEntry(TEX_EYES_IRIS, new PickerControlEntry(TEX_EYES_IRIS, "Iris", LLUUID(gSavedSettings.getString("UIImgDefaultEyesUUID")), FALSE));
addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ), FALSE )); addEntry(TEX_UPPER_SHIRT, new PickerControlEntry(TEX_UPPER_SHIRT, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultShirtUUID")), FALSE));
addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ), FALSE )); addEntry(TEX_LOWER_PANTS, new PickerControlEntry(TEX_LOWER_PANTS, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultPantsUUID")), FALSE));
addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ), FALSE )); addEntry(TEX_LOWER_SHOES, new PickerControlEntry(TEX_LOWER_SHOES, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultShoesUUID")), FALSE));
addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ), FALSE )); addEntry(TEX_LOWER_SOCKS, new PickerControlEntry(TEX_LOWER_SOCKS, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultSocksUUID")), FALSE));
addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Upper Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); addEntry(TEX_UPPER_JACKET, new PickerControlEntry(TEX_UPPER_JACKET, "Upper Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultJacketUUID")), FALSE));
addEntry ( TEX_LOWER_JACKET, new PickerControlEntry (TEX_LOWER_JACKET, "Lower Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); addEntry(TEX_LOWER_JACKET, new PickerControlEntry(TEX_LOWER_JACKET, "Lower Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultJacketUUID")), FALSE));
addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ), FALSE )); addEntry(TEX_SKIRT, new PickerControlEntry(TEX_SKIRT, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultSkirtUUID")), FALSE));
addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ), FALSE )); addEntry(TEX_UPPER_GLOVES, new PickerControlEntry(TEX_UPPER_GLOVES, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultGlovesUUID")), FALSE));
addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); addEntry(TEX_UPPER_UNDERSHIRT, new PickerControlEntry(TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultUnderwearUUID")), FALSE));
addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); addEntry(TEX_LOWER_UNDERPANTS, new PickerControlEntry(TEX_LOWER_UNDERPANTS, "Fabric", LLUUID(gSavedSettings.getString("UIImgDefaultUnderwearUUID")), FALSE));
addEntry ( TEX_LOWER_ALPHA, new PickerControlEntry (TEX_LOWER_ALPHA, "Lower Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); addEntry(TEX_LOWER_ALPHA, new PickerControlEntry(TEX_LOWER_ALPHA, "Lower Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE));
addEntry ( TEX_UPPER_ALPHA, new PickerControlEntry (TEX_UPPER_ALPHA, "Upper Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); addEntry(TEX_UPPER_ALPHA, new PickerControlEntry(TEX_UPPER_ALPHA, "Upper Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE));
addEntry ( TEX_HEAD_ALPHA, new PickerControlEntry (TEX_HEAD_ALPHA, "Head Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); addEntry(TEX_HEAD_ALPHA, new PickerControlEntry(TEX_HEAD_ALPHA, "Head Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE));
addEntry ( TEX_EYES_ALPHA, new PickerControlEntry (TEX_EYES_ALPHA, "Eye Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); addEntry(TEX_EYES_ALPHA, new PickerControlEntry(TEX_EYES_ALPHA, "Eye Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE));
addEntry ( TEX_HAIR_ALPHA, new PickerControlEntry (TEX_HAIR_ALPHA, "Hair Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); addEntry(TEX_HAIR_ALPHA, new PickerControlEntry(TEX_HAIR_ALPHA, "Hair Alpha", LLUUID(gSavedSettings.getString("UIImgDefaultAlphaUUID")), TRUE));
addEntry ( TEX_LOWER_TATTOO, new PickerControlEntry (TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE )); addEntry(TEX_LOWER_TATTOO, new PickerControlEntry(TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_UPPER_TATTOO, new PickerControlEntry (TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE )); addEntry(TEX_UPPER_TATTOO, new PickerControlEntry(TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry (TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE )); addEntry(TEX_HEAD_TATTOO, new PickerControlEntry(TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_LOWER_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_LOWER_UNIVERSAL_TATTOO, "Lower Universal Tattoo", LLUUID::null, TRUE)); addEntry(TEX_LOWER_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_LOWER_UNIVERSAL_TATTOO, "Lower Universal Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_UPPER_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_UPPER_UNIVERSAL_TATTOO, "Upper Universal Tattoo", LLUUID::null, TRUE)); addEntry(TEX_UPPER_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_UPPER_UNIVERSAL_TATTOO, "Upper Universal Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry( TEX_HEAD_UNIVERSAL_TATTOO, "Head Universal Tattoo", LLUUID::null, TRUE)); addEntry(TEX_HEAD_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Head Universal Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_SKIRT_TATTOO, new PickerControlEntry(TEX_SKIRT_TATTOO, "Skirt Tattoo", LLUUID::null, TRUE)); addEntry(TEX_SKIRT_TATTOO, new PickerControlEntry(TEX_SKIRT_TATTOO, "Skirt Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_HAIR_TATTOO, new PickerControlEntry(TEX_HAIR_TATTOO, "Hair Tattoo", LLUUID::null, TRUE)); addEntry(TEX_HAIR_TATTOO, new PickerControlEntry(TEX_HAIR_TATTOO, "Hair Tattoo", LLUUID::null, TRUE));
addEntry ( TEX_EYES_TATTOO, new PickerControlEntry(TEX_EYES_TATTOO, "Eyes Tattoo", LLUUID::null, TRUE)); addEntry(TEX_EYES_TATTOO, new PickerControlEntry(TEX_EYES_TATTOO, "Eyes Tattoo", LLUUID::null, TRUE));
addEntry (TEX_LEFT_ARM_TATTOO, new PickerControlEntry(TEX_LEFT_ARM_TATTOO, "Left Arm Tattoo", LLUUID::null, TRUE)); addEntry(TEX_LEFT_ARM_TATTOO, new PickerControlEntry(TEX_LEFT_ARM_TATTOO, "Left Arm Tattoo", LLUUID::null, TRUE));
addEntry (TEX_LEFT_LEG_TATTOO, new PickerControlEntry(TEX_LEFT_LEG_TATTOO, "Left Leg Tattoo", LLUUID::null, TRUE)); addEntry(TEX_LEFT_LEG_TATTOO, new PickerControlEntry(TEX_LEFT_LEG_TATTOO, "Left Leg Tattoo", LLUUID::null, TRUE));
addEntry (TEX_AUX1_TATTOO, new PickerControlEntry(TEX_AUX1_TATTOO, "Aux1 Tattoo", LLUUID::null, TRUE)); addEntry(TEX_AUX1_TATTOO, new PickerControlEntry(TEX_AUX1_TATTOO, "Aux1 Tattoo", LLUUID::null, TRUE));
addEntry (TEX_AUX2_TATTOO, new PickerControlEntry(TEX_AUX2_TATTOO, "Aux2 Tattoo", LLUUID::null, TRUE)); addEntry(TEX_AUX2_TATTOO, new PickerControlEntry(TEX_AUX2_TATTOO, "Aux2 Tattoo", LLUUID::null, TRUE));
addEntry (TEX_AUX3_TATTOO, new PickerControlEntry(TEX_AUX3_TATTOO, "Aux3 Tattoo", LLUUID::null, TRUE)); addEntry(TEX_AUX3_TATTOO, new PickerControlEntry(TEX_AUX3_TATTOO, "Aux3 Tattoo", LLUUID::null, TRUE));
} }
LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index, LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index,
@ -490,8 +496,8 @@ template <typename CtrlType, class Predicate>
const LLEditWearableDictionary::PickerControlEntry* const LLEditWearableDictionary::PickerControlEntry*
find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred) find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred)
{ {
const LLEditWearableDictionary::WearableEntry *wearable_entry const LLEditWearableDictionary::WearableEntry *wearable_entry =
= LLEditWearableDictionary::getInstance()->getWearable(type); LLEditWearableDictionary::getInstance()->getWearable(type);
if (!wearable_entry) if (!wearable_entry)
{ {
LL_WARNS() << "could not get wearable dictionary entry for wearable of type: " << type << LL_ENDL; LL_WARNS() << "could not get wearable dictionary entry for wearable of type: " << type << LL_ENDL;
@ -520,8 +526,7 @@ find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred)
} }
template <typename CtrlType> template <typename CtrlType>
void void for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_t fun)
for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_t fun)
{ {
if (!panel) if (!panel)
{ {
@ -542,14 +547,13 @@ for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_
iter != iter_end; ++iter) iter != iter_end; ++iter)
{ {
const ETextureIndex te = *iter; const ETextureIndex te = *iter;
const LLEditWearableDictionary::PickerControlEntry* entry const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry<CtrlType>(te);
= get_picker_entry<CtrlType>(te);
if (!entry) if (!entry)
{ {
LL_WARNS() << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << LL_ENDL; LL_WARNS() << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << LL_ENDL;
continue; continue;
} }
fun (panel, entry); fun(panel, entry);
} }
} }
@ -594,7 +598,7 @@ static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const
{ {
LLUUID new_id; LLUUID new_id;
LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(entry->mTextureIndex); LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(entry->mTextureIndex);
if( lto && (lto->getID() != IMG_DEFAULT_AVATAR) ) if (lto && (lto->getID() != IMG_DEFAULT_AVATAR))
{ {
new_id = lto->getID(); new_id = lto->getID();
} }
@ -644,7 +648,6 @@ LLPanelEditWearable::LLPanelEditWearable()
//virtual //virtual
LLPanelEditWearable::~LLPanelEditWearable() LLPanelEditWearable::~LLPanelEditWearable()
{ {
} }
bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value) bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value)
@ -659,7 +662,7 @@ void LLPanelEditWearable::updateMetricLayout(BOOL new_value)
LLUIString current_metric, replacment_metric; LLUIString current_metric, replacment_metric;
current_metric = new_value ? mMeters : mFeet; current_metric = new_value ? mMeters : mFeet;
replacment_metric = new_value ? mFeet : mMeters; replacment_metric = new_value ? mFeet : mMeters;
mHeigthValue.setArg( "[METRIC1]", current_metric.getString() ); mHeightValue.setArg( "[METRIC1]", current_metric.getString() );
mReplacementMetricUrl.setArg( "[URL_METRIC2]", std::string("[secondlife:///app/metricsystem ") + replacment_metric.getString() + std::string("]")); mReplacementMetricUrl.setArg( "[URL_METRIC2]", std::string("[secondlife:///app/metricsystem ") + replacment_metric.getString() + std::string("]"));
} }
@ -667,11 +670,11 @@ void LLPanelEditWearable::updateAvatarHeightLabel()
{ {
mTxtAvatarHeight->setText(LLStringUtil::null); mTxtAvatarHeight->setText(LLStringUtil::null);
LLStyle::Params param; LLStyle::Params param;
param.color = mAvatarHeigthLabelColor; param.color = mAvatarHeightLabelColor;
mTxtAvatarHeight->appendText(mHeigth, false, param); mTxtAvatarHeight->appendText(mHeight, false, param);
param.color = mAvatarHeigthValueLabelColor; param.color = mAvatarHeightValueLabelColor;
mTxtAvatarHeight->appendText(mHeigthValue, false, param); mTxtAvatarHeight->appendText(mHeightValue, false, param);
param.color = mAvatarHeigthLabelColor; // using mAvatarHeigthLabelColor for '/' separator param.color = mAvatarHeightLabelColor; // using mAvatarHeightLabelColor for '/' separator
mTxtAvatarHeight->appendText(" / ", false, param); mTxtAvatarHeight->appendText(" / ", false, param);
mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param); mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param);
} }
@ -754,7 +757,7 @@ BOOL LLPanelEditWearable::postBuild()
mPanelSkirt = getChild<LLPanel>("edit_skirt_panel"); mPanelSkirt = getChild<LLPanel>("edit_skirt_panel");
mPanelAlpha = getChild<LLPanel>("edit_alpha_panel"); mPanelAlpha = getChild<LLPanel>("edit_alpha_panel");
mPanelTattoo = getChild<LLPanel>("edit_tattoo_panel"); mPanelTattoo = getChild<LLPanel>("edit_tattoo_panel");
mPanelUniversal = getChild<LLPanel>("edit_universal_panel"); mPanelUniversal = getChild<LLPanel>("edit_universal_panel");
mPanelPhysics = getChild<LLPanel>("edit_physics_panel"); mPanelPhysics = getChild<LLPanel>("edit_physics_panel");
mTxtAvatarHeight = mPanelShape->getChild<LLTextBox>("avatar_height"); mTxtAvatarHeight = mPanelShape->getChild<LLTextBox>("avatar_height");
@ -778,29 +781,27 @@ BOOL LLPanelEditWearable::postBuild()
continue; continue;
} }
U8 num_subparts = (U8)(wearable_entry->mSubparts.size()); U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
for (U8 index = 0; index < num_subparts; ++index) for (U8 index = 0; index < num_subparts; ++index)
{ {
// dive into data structures to get the panel we need // dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index]; ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e); const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry) if (!subpart_entry)
{ {
LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL; LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL;
continue; continue;
} }
const std::string accordion_tab = subpart_entry->mAccordionTab; const std::string accordion_tab = subpart_entry->mAccordionTab;
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab); LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!tab) if (!tab)
{ {
LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL; LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL;
continue; continue;
} }
// initialize callback to ensure camera view changes appropriately. // initialize callback to ensure camera view changes appropriately.
tab->setDropDownStateChangedCallback(boost::bind(&LLPanelEditWearable::onTabExpandedCollapsed,this,_2,index)); tab->setDropDownStateChangedCallback(boost::bind(&LLPanelEditWearable::onTabExpandedCollapsed,this,_2,index));
} }
@ -813,14 +814,14 @@ BOOL LLPanelEditWearable::postBuild()
// init all strings // init all strings
mMeters = mPanelShape->getString("meters"); mMeters = mPanelShape->getString("meters");
mFeet = mPanelShape->getString("feet"); mFeet = mPanelShape->getString("feet");
mHeigth = mPanelShape->getString("height") + " "; mHeight = mPanelShape->getString("height") + " ";
mHeigthValue = "[HEIGHT] [METRIC1]"; mHeightValue = "[HEIGHT] [METRIC1]";
mReplacementMetricUrl = "[URL_METRIC2]"; mReplacementMetricUrl = "[URL_METRIC2]";
std::string color = mPanelShape->getString("heigth_label_color"); std::string color = mPanelShape->getString("height_label_color");
mAvatarHeigthLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); mAvatarHeightLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
color = mPanelShape->getString("heigth_value_label_color"); color = mPanelShape->getString("height_value_label_color");
mAvatarHeigthValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); mAvatarHeightValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2)); gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2));
updateMetricLayout(gSavedSettings.getBOOL("HeightUnits")); updateMetricLayout(gSavedSettings.getBOOL("HeightUnits"));
@ -834,14 +835,16 @@ BOOL LLPanelEditWearable::isDirty() const
BOOL isDirty = FALSE; BOOL isDirty = FALSE;
if (mWearablePtr) if (mWearablePtr)
{ {
if (mWearablePtr->isDirty() || if (mWearablePtr->isDirty() ||
( mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0 )) (mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0))
{ {
isDirty = TRUE; isDirty = TRUE;
} }
} }
return isDirty; return isDirty;
} }
//virtual //virtual
void LLPanelEditWearable::draw() void LLPanelEditWearable::draw()
{ {
@ -857,8 +860,8 @@ void LLPanelEditWearable::draw()
void LLPanelEditWearable::onClose() void LLPanelEditWearable::onClose()
{ {
// any unsaved changes should be reverted at this point // any unsaved changes should be reverted at this point
revertChanges(); revertChanges();
} }
void LLPanelEditWearable::setVisible(BOOL visible) void LLPanelEditWearable::setVisible(BOOL visible)
@ -880,11 +883,11 @@ void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_c
//static //static
void LLPanelEditWearable::onBackButtonClicked(void* userdata) void LLPanelEditWearable::onBackButtonClicked(void* userdata)
{ {
LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata; LLPanelEditWearable* panel = (LLPanelEditWearable*)userdata;
if ( panel->isDirty() ) if (panel->isDirty())
{ {
LLAppearanceMgr::instance().setOutfitDirty( true ); LLAppearanceMgr::instance().setOutfitDirty(true);
} }
} }
//static //static
@ -909,7 +912,7 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r
{ {
std::string wearable_name = response["message"].asString(); std::string wearable_name = response["message"].asString();
LLStringUtil::trim(wearable_name); LLStringUtil::trim(wearable_name);
if( !wearable_name.empty() ) if (!wearable_name.empty())
{ {
mNameEditor->setText(wearable_name); mNameEditor->setText(wearable_name);
saveChanges(true); saveChanges(true);
@ -919,24 +922,27 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r
void LLPanelEditWearable::onCommitSexChange() void LLPanelEditWearable::onCommitSexChange()
{ {
if (!isAgentAvatarValid()) return; if (!isAgentAvatarValid())
{
return;
}
LLWearableType::EType type = mWearablePtr->getType(); LLWearableType::EType type = mWearablePtr->getType();
U32 index; U32 index;
if( !gAgentWearables.getWearableIndex(mWearablePtr, index) || if (!gAgentWearables.getWearableIndex(mWearablePtr, index) ||
!gAgentWearables.isWearableModifiable(type, index)) !gAgentWearables.isWearableModifiable(type, index))
{ {
return; return;
} }
LLViewerVisualParam* param = static_cast<LLViewerVisualParam*>(gAgentAvatarp->getVisualParam( "male" )); LLViewerVisualParam* param = static_cast<LLViewerVisualParam*>(gAgentAvatarp->getVisualParam( "male" ));
if( !param ) if (!param)
{ {
return; return;
} }
bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE; bool is_new_sex_male = (gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE) == SEX_MALE;
LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index); LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index);
if (wearable) if (wearable)
{ {
wearable->setVisualParamWeight(param->getID(), is_new_sex_male); wearable->setVisualParamWeight(param->getID(), is_new_sex_male);
@ -969,23 +975,23 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
{ {
// Set the new version // Set the new version
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID()); LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID());
if( image->getID() == IMG_DEFAULT ) if (image->getID() == IMG_DEFAULT)
{ {
image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
} }
if (getWearable()) if (getWearable())
{ {
U32 index; U32 index;
if (gAgentWearables.getWearableIndex(getWearable(), index)) if (gAgentWearables.getWearableIndex(getWearable(), index))
{ {
gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
LLVisualParamHint::requestHintUpdates(); LLVisualParamHint::requestHintUpdates();
gAgentAvatarp->wearableUpdated(type); gAgentAvatarp->wearableUpdated(type);
} }
else else
{ {
LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL; LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL;
} }
} }
} }
else else
@ -1001,13 +1007,13 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl)
{ {
LLWearableType::EType type = getWearable()->getType(); LLWearableType::EType type = getWearable()->getType();
const PickerControlEntryNamePredicate name_pred(ctrl->getName()); const PickerControlEntryNamePredicate name_pred(ctrl->getName());
const LLEditWearableDictionary::PickerControlEntry* entry const LLEditWearableDictionary::PickerControlEntry* entry =
= find_picker_ctrl_entry_if<LLColorSwatchCtrl, PickerControlEntryNamePredicate>(type, name_pred); find_picker_ctrl_entry_if<LLColorSwatchCtrl, PickerControlEntryNamePredicate>(type, name_pred);
if (entry) if (entry)
{ {
const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex); const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex);
const LLColor4& new_color = LLColor4(ctrl->getValue()); const LLColor4& new_color = LLColor4(ctrl->getValue());
if( old_color != new_color ) if (old_color != new_color)
{ {
getWearable()->setClothesColor(entry->mTextureIndex, new_color); getWearable()->setClothesColor(entry->mTextureIndex, new_color);
LLVisualParamHint::requestHintUpdates(); LLVisualParamHint::requestHintUpdates();
@ -1025,11 +1031,13 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type)
{ {
LLPanel* panel = getPanel(type); LLPanel* panel = getPanel(type);
if (!panel) if (!panel)
{
return; return;
}
bool is_modifiable = false; bool is_modifiable = false;
if(mWearableItem) if (mWearableItem)
{ {
const LLPermissions& perm = mWearableItem->getPermissions(); const LLPermissions& perm = mWearableItem->getPermissions();
is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
@ -1051,7 +1059,6 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type)
void LLPanelEditWearable::incrementCofVersionLegacy() void LLPanelEditWearable::incrementCofVersionLegacy()
{ {
} }
void LLPanelEditWearable::saveChanges(bool force_save_as) void LLPanelEditWearable::saveChanges(bool force_save_as)
@ -1063,59 +1070,57 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
} }
U32 index; U32 index;
if (!gAgentWearables.getWearableIndex(mWearablePtr, index)) if (!gAgentWearables.getWearableIndex(mWearablePtr, index))
{ {
LL_WARNS() << "wearable not found" << LL_ENDL; LL_WARNS() << "wearable not found" << LL_ENDL;
return; return;
} }
std::string new_name = mNameEditor->getText(); std::string new_name = mNameEditor->getText();
// Find an existing link to this wearable's inventory item, if any, and its description field. // Find an existing link to this wearable's inventory item, if any, and its description field.
LLInventoryItem *link_item = NULL; LLInventoryItem* link_item = NULL;
std::string description; std::string description;
LLInventoryModel::item_array_t links = LLInventoryModel::item_array_t links =
LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID()); LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID());
if (links.size()>0) if (links.size() > 0)
{ {
link_item = links.at(0).get(); link_item = links.at(0).get();
if (link_item && link_item->getIsLinkType()) if (link_item && link_item->getIsLinkType())
{ {
description = link_item->getActualDescription(); description = link_item->getActualDescription();
} }
} }
if (force_save_as) if (force_save_as)
{ {
// the name of the wearable has changed, re-save wearable with new name // the name of the wearable has changed, re-save wearable with new name
LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),gAgentAvatarp->mEndCustomizeCallback); LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(), gAgentAvatarp->mEndCustomizeCallback);
gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE);
mNameEditor->setText(mWearableItem->getName()); mNameEditor->setText(mWearableItem->getName());
} }
else else
{ {
// Make another copy of this link, with the same // Make another copy of this link, with the same
// description. This is needed to bump the COF // description. This is needed to bump the COF
// version so texture baking service knows appearance has changed. // version so texture baking service knows appearance has changed.
if (link_item) if (link_item)
{ {
// Create new link // Create new link
LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID() LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
<< " removing old link at " << link_item->getUUID() << " removing old link at " << link_item->getUUID()
<< " wearable item id " << mWearablePtr->getItemID() << LL_ENDL; << " wearable item id " << mWearablePtr->getItemID() << LL_ENDL;
LLInventoryObject::const_object_list_t obj_array; LLInventoryObject::const_object_list_t obj_array;
obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item)); obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
link_inventory_array(LLAppearanceMgr::instance().getCOF(), link_inventory_array(LLAppearanceMgr::instance().getCOF(),
obj_array, obj_array,
gAgentAvatarp->mEndCustomizeCallback); gAgentAvatarp->mEndCustomizeCallback);
// Remove old link // Remove old link
remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback); remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
} }
gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name); gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name);
} }
} }
void LLPanelEditWearable::revertChanges() void LLPanelEditWearable::revertChanges()
@ -1165,15 +1170,15 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
targetPanel->setVisible(show); targetPanel->setVisible(show);
toggleTypeSpecificControls(type); toggleTypeSpecificControls(type);
// Update type controls here // Update type controls here
updateTypeSpecificControls(type); updateTypeSpecificControls(type);
if (show) if (show)
{ {
mPanelTitle->setText(title); mPanelTitle->setText(title);
mPanelTitle->setToolTip(title); mPanelTitle->setToolTip(title);
mDescTitle->setText(description_title); mDescTitle->setText(description_title);
// set name // set name
mNameEditor->setText(mWearableItem->getName()); mNameEditor->setText(mWearableItem->getName());
@ -1181,51 +1186,51 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
// clear and rebuild visual param list // clear and rebuild visual param list
U8 num_subparts = (U8)(wearable_entry->mSubparts.size()); U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
for (U8 index = 0; index < num_subparts; ++index) for (U8 index = 0; index < num_subparts; ++index)
{ {
// dive into data structures to get the panel we need // dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index]; ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e); const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry) if (!subpart_entry)
{ {
LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL; LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL;
continue; continue;
} }
const std::string scrolling_panel = subpart_entry->mParamList; const std::string scrolling_panel = subpart_entry->mParamList;
const std::string accordion_tab = subpart_entry->mAccordionTab; const std::string accordion_tab = subpart_entry->mAccordionTab;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel); LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab); LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!panel_list) if (!panel_list)
{ {
LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL; LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL;
continue; continue;
} }
if (!tab) if (!tab)
{ {
LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL; LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL;
continue; continue;
} }
// Don't show female subparts if you're not female, etc. // Don't show female subparts if you're not female, etc.
if (!(gAgentAvatarp->getSex() & subpart_entry->mSex)) if (!(gAgentAvatarp->getSex() & subpart_entry->mSex))
{ {
tab->setVisible(FALSE); tab->setVisible(FALSE);
continue; continue;
} }
else else
{ {
tab->setVisible(TRUE); tab->setVisible(TRUE);
} }
// what edit group do we want to extract params for? // what edit group do we want to extract params for?
const std::string edit_group = subpart_entry->mEditGroup; const std::string edit_group = subpart_entry->mEditGroup;
// storage for ordered list of visual params // storage for ordered list of visual params
value_map_t sorted_params; value_map_t sorted_params;
getSortedParams(sorted_params, edit_group); getSortedParams(sorted_params, edit_group);
@ -1237,9 +1242,10 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
} }
buildParamList(panel_list, sorted_params, tab, jointp); buildParamList(panel_list, sorted_params, tab, jointp);
updateScrollingPanelUI(); updateScrollingPanelUI();
} }
if (!disable_camera_switch) if (!disable_camera_switch)
{ {
showDefaultSubpart(); showDefaultSubpart();
@ -1268,17 +1274,17 @@ void LLPanelEditWearable::onTabExpandedCollapsed(const LLSD& param, U8 index)
{ {
changeCamera(index); changeCamera(index);
} }
} }
void LLPanelEditWearable::changeCamera(U8 subpart) void LLPanelEditWearable::changeCamera(U8 subpart)
{ {
// Don't change the camera if this type doesn't have a camera switch. // Don't change the camera if this type doesn't have a camera switch.
// Useful for wearables like physics that don't have an associated physical body part. // Useful for wearables like physics that don't have an associated physical body part.
if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType())) if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType()))
{ {
return; return;
} }
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(mWearablePtr->getType()); const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(mWearablePtr->getType());
if (!wearable_entry) if (!wearable_entry)
{ {
@ -1307,9 +1313,9 @@ void LLPanelEditWearable::changeCamera(U8 subpart)
gMorphView->setCameraOffset( subpart_entry->mCameraOffset ); gMorphView->setCameraOffset( subpart_entry->mCameraOffset );
if (gSavedSettings.getBOOL("AppearanceCameraMovement")) if (gSavedSettings.getBOOL("AppearanceCameraMovement"))
{ {
// Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE // Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE
gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating()); gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating());
gMorphView->updateCamera(); gMorphView->updateCamera();
} }
} }
@ -1345,7 +1351,7 @@ void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type)
} }
std::string avatar_height_str = llformat("%.2f", new_size); std::string avatar_height_str = llformat("%.2f", new_size);
mHeigthValue.setArg("[HEIGHT]", avatar_height_str); mHeightValue.setArg("[HEIGHT]", avatar_height_str);
updateAvatarHeightLabel(); updateAvatarHeightLabel();
} }
@ -1368,14 +1374,18 @@ void LLPanelEditWearable::updateScrollingPanelUI()
LLWearableType::EType type = mWearablePtr->getType(); LLWearableType::EType type = mWearablePtr->getType();
LLPanel *panel = getPanel(type); LLPanel *panel = getPanel(type);
if(panel && (mWearablePtr->getItemID().notNull())) if (panel && (mWearablePtr->getItemID().notNull()))
{ {
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type); const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
llassert(wearable_entry); llassert(wearable_entry);
if (!wearable_entry) return; if (!wearable_entry)
U8 num_subparts = (U8)(wearable_entry->mSubparts.size()); {
return;
}
LLScrollingPanelParam::sUpdateDelayFrames = 0; LLScrollingPanelParam::sUpdateDelayFrames = 0;
U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
for (U8 index = 0; index < num_subparts; ++index) for (U8 index = 0; index < num_subparts; ++index)
{ {
// dive into data structures to get the panel we need // dive into data structures to get the panel we need
@ -1385,13 +1395,13 @@ void LLPanelEditWearable::updateScrollingPanelUI()
const std::string scrolling_panel = subpart_entry->mParamList; const std::string scrolling_panel = subpart_entry->mParamList;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel); LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
if (!panel_list) if (!panel_list)
{ {
LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL; LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL;
continue; continue;
} }
panel_list->updatePanels(TRUE); panel_list->updatePanels(TRUE);
} }
} }
@ -1403,76 +1413,58 @@ LLPanel* LLPanelEditWearable::getPanel(LLWearableType::EType type)
{ {
case LLWearableType::WT_SHAPE: case LLWearableType::WT_SHAPE:
return mPanelShape; return mPanelShape;
break;
case LLWearableType::WT_SKIN: case LLWearableType::WT_SKIN:
return mPanelSkin; return mPanelSkin;
break;
case LLWearableType::WT_HAIR: case LLWearableType::WT_HAIR:
return mPanelHair; return mPanelHair;
break;
case LLWearableType::WT_EYES: case LLWearableType::WT_EYES:
return mPanelEyes; return mPanelEyes;
break;
case LLWearableType::WT_SHIRT: case LLWearableType::WT_SHIRT:
return mPanelShirt; return mPanelShirt;
break;
case LLWearableType::WT_PANTS: case LLWearableType::WT_PANTS:
return mPanelPants; return mPanelPants;
break;
case LLWearableType::WT_SHOES: case LLWearableType::WT_SHOES:
return mPanelShoes; return mPanelShoes;
break;
case LLWearableType::WT_SOCKS: case LLWearableType::WT_SOCKS:
return mPanelSocks; return mPanelSocks;
break;
case LLWearableType::WT_JACKET: case LLWearableType::WT_JACKET:
return mPanelJacket; return mPanelJacket;
break;
case LLWearableType::WT_GLOVES: case LLWearableType::WT_GLOVES:
return mPanelGloves; return mPanelGloves;
break;
case LLWearableType::WT_UNDERSHIRT: case LLWearableType::WT_UNDERSHIRT:
return mPanelUndershirt; return mPanelUndershirt;
break;
case LLWearableType::WT_UNDERPANTS: case LLWearableType::WT_UNDERPANTS:
return mPanelUnderpants; return mPanelUnderpants;
break;
case LLWearableType::WT_SKIRT: case LLWearableType::WT_SKIRT:
return mPanelSkirt; return mPanelSkirt;
break;
case LLWearableType::WT_ALPHA: case LLWearableType::WT_ALPHA:
return mPanelAlpha; return mPanelAlpha;
break;
case LLWearableType::WT_TATTOO: case LLWearableType::WT_TATTOO:
return mPanelTattoo; return mPanelTattoo;
break;
case LLWearableType::WT_UNIVERSAL:
case LLWearableType::WT_UNIVERSAL: return mPanelUniversal;
return mPanelUniversal;
break;
case LLWearableType::WT_PHYSICS: case LLWearableType::WT_PHYSICS:
return mPanelPhysics; return mPanelPhysics;
break;
default: default:
break; return NULL;
} }
return NULL;
} }
void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std::string &edit_group) void LLPanelEditWearable::getSortedParams(value_map_t &sorted_params, const std::string &edit_group)
@ -1507,11 +1499,11 @@ void LLPanelEditWearable::buildParamList(LLScrollingPanelList *panel_list, value
// sorted_params is sorted according to magnitude of effect from // sorted_params is sorted according to magnitude of effect from
// least to greatest. Adding to the front of the child list // least to greatest. Adding to the front of the child list
// reverses that order. // reverses that order.
if( panel_list ) if (panel_list)
{ {
panel_list->clearPanels(); panel_list->clearPanels();
value_map_t::iterator end = sorted_params.end(); value_map_t::iterator end = sorted_params.end();
for(value_map_t::iterator it = sorted_params.begin(); it != end; ++it) for (value_map_t::iterator it = sorted_params.begin(); it != end; ++it)
{ {
LLPanel::Params p; LLPanel::Params p;
p.name("LLScrollingPanelParam"); p.name("LLScrollingPanelParam");
@ -1534,7 +1526,7 @@ void LLPanelEditWearable::updateVerbs()
{ {
bool can_copy = false; bool can_copy = false;
if(mWearableItem) if (mWearableItem)
{ {
can_copy = mWearableItem->getPermissions().allowCopyBy(gAgentID); can_copy = mWearableItem->getPermissions().allowCopyBy(gAgentID);
} }
@ -1544,7 +1536,7 @@ void LLPanelEditWearable::updateVerbs()
mBtnRevert->setEnabled(is_dirty); mBtnRevert->setEnabled(is_dirty);
getChildView("save_as_button")->setEnabled(is_dirty && can_copy); getChildView("save_as_button")->setEnabled(is_dirty && can_copy);
if(isAgentAvatarValid()) if (isAgentAvatarValid())
{ {
// Update viewer's radio buttons (of RadioGroup with control_name="AvatarSex") of Avatar's gender // Update viewer's radio buttons (of RadioGroup with control_name="AvatarSex") of Avatar's gender
// with value from "AvatarSex" setting // with value from "AvatarSex" setting
@ -1585,17 +1577,20 @@ void LLPanelEditWearable::configureAlphaCheckbox(LLAvatarAppearanceDefines::ETex
void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te) void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te)
{ {
if (!checkbox_ctrl) return; if (!checkbox_ctrl || !getWearable())
if (!getWearable()) return; {
return;
}
LL_INFOS() << "onInvisibilityCommit, self " << this << " checkbox_ctrl " << checkbox_ctrl << LL_ENDL; LL_INFOS() << "onInvisibilityCommit, self " << this << " checkbox_ctrl " << checkbox_ctrl << LL_ENDL;
U32 index; U32 index;
if (!gAgentWearables.getWearableIndex(getWearable(),index)) if (!gAgentWearables.getWearableIndex(getWearable(), index))
{ {
LL_WARNS() << "wearable not found" << LL_ENDL; LL_WARNS() << "wearable not found" << LL_ENDL;
return; return;
} }
bool new_invis_state = checkbox_ctrl->get(); bool new_invis_state = checkbox_ctrl->get();
if (new_invis_state) if (new_invis_state)
{ {
@ -1603,8 +1598,8 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
mPreviousAlphaTexture[te] = lto->getID(); mPreviousAlphaTexture[te] = lto->getID();
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE ); LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
gAgentAvatarp->setLocalTexture(te, image, FALSE, index); gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
gAgentAvatarp->wearableUpdated(getWearable()->getType()); gAgentAvatarp->wearableUpdated(getWearable()->getType());
} }
else else
{ {
@ -1614,10 +1609,16 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
{ {
prev_id = LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ); prev_id = LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) );
} }
if (prev_id.isNull()) return; if (prev_id.isNull())
{
return;
}
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(prev_id); LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(prev_id);
if (!image) return; if (!image)
{
return;
}
gAgentAvatarp->setLocalTexture(te, image, FALSE, index); gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
gAgentAvatarp->wearableUpdated(getWearable()->getType()); gAgentAvatarp->wearableUpdated(getWearable()->getType());
@ -1628,7 +1629,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
void LLPanelEditWearable::updateAlphaCheckboxes() void LLPanelEditWearable::updateAlphaCheckboxes()
{ {
for(string_texture_index_map_t::iterator iter = mAlphaCheckbox2Index.begin(); for (string_texture_index_map_t::iterator iter = mAlphaCheckbox2Index.begin();
iter != mAlphaCheckbox2Index.end(); ++iter ) iter != mAlphaCheckbox2Index.end(); ++iter )
{ {
LLAvatarAppearanceDefines::ETextureIndex te = (LLAvatarAppearanceDefines::ETextureIndex)iter->second; LLAvatarAppearanceDefines::ETextureIndex te = (LLAvatarAppearanceDefines::ETextureIndex)iter->second;

View File

@ -135,14 +135,14 @@ private:
// localized and parameterized strings that used to build avatar_height_label // localized and parameterized strings that used to build avatar_height_label
std::string mMeters; std::string mMeters;
std::string mFeet; std::string mFeet;
std::string mHeigth; std::string mHeight;
LLUIString mHeigthValue; LLUIString mHeightValue;
LLUIString mReplacementMetricUrl; LLUIString mReplacementMetricUrl;
// color for mHeigth string // color for mHeight string
LLUIColor mAvatarHeigthLabelColor; LLUIColor mAvatarHeightLabelColor;
// color for mHeigthValue string // color for mHeightValue string
LLUIColor mAvatarHeigthValueLabelColor; LLUIColor mAvatarHeightValueLabelColor;
// This text editor reference will change each time we edit a new wearable - // This text editor reference will change each time we edit a new wearable -
// it will be grabbed from the currently visible panel // it will be grabbed from the currently visible panel

View File

@ -964,9 +964,15 @@ void LLTaskLSLBridge::openItem()
LLSD floater_key; LLSD floater_key;
floater_key["taskid"] = mPanel->getTaskUUID(); floater_key["taskid"] = mPanel->getTaskUUID();
floater_key["itemid"] = mUUID; floater_key["itemid"] = mUUID;
LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key, TAKE_FOCUS_YES); LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key, TAKE_FOCUS_YES);
if (preview) if (preview)
{ {
LLSelectNode *node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(NULL, TRUE);
if (node && node->mValid)
{
preview->setObjectName(node->mName);
}
preview->setObjectID(mPanel->getTaskUUID()); preview->setObjectID(mPanel->getTaskUUID());
} }
} }

View File

@ -733,7 +733,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string)
if (mSearchString == "") if (mSearchString == "")
{ {
mInventoryItemsPanel->setFilterSubString(LLStringUtil::null); mInventoryItemsPanel->setFilterSubString(LLStringUtil::null);
mWearableItemsList->setFilterSubString(LLStringUtil::null); mWearableItemsList->setFilterSubString(LLStringUtil::null, true);
// re-open folders that were initially open // re-open folders that were initially open
mSavedFolderState->setApply(TRUE); mSavedFolderState->setApply(TRUE);
mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
@ -763,8 +763,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string)
// set new filter string // set new filter string
mInventoryItemsPanel->setFilterSubString(mSearchString); mInventoryItemsPanel->setFilterSubString(mSearchString);
mWearableItemsList->setFilterSubString(mSearchString); mWearableItemsList->setFilterSubString(mSearchString, true);
} }
void LLPanelOutfitEdit::onPlusBtnClicked(void) void LLPanelOutfitEdit::onPlusBtnClicked(void)

View File

@ -28,19 +28,19 @@
#include "llpaneloutfitsinventory.h" #include "llpaneloutfitsinventory.h"
#include "llnotificationsutil.h" #include "llagentwearables.h"
#include "lltabcontainer.h" #include "llappearancemgr.h"
#include "llfloatersidepanelcontainer.h" #include "llfloatersidepanelcontainer.h"
#include "llinventoryfunctions.h" #include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h" #include "llinventorymodelbackgroundfetch.h"
#include "llagentwearables.h" #include "llnotificationsutil.h"
#include "llappearancemgr.h"
#include "lloutfitobserver.h"
#include "lloutfitgallery.h" #include "lloutfitgallery.h"
#include "lloutfitobserver.h"
#include "lloutfitslist.h" #include "lloutfitslist.h"
#include "llpanelappearancetab.h"
#include "llpanelwearing.h" #include "llpanelwearing.h"
#include "llsidepanelappearance.h" #include "llsidepanelappearance.h"
#include "lltabcontainer.h"
#include "llviewercontrol.h" #include "llviewercontrol.h"
#include "llviewerfoldertype.h" #include "llviewerfoldertype.h"
@ -159,25 +159,12 @@ void LLPanelOutfitsInventory::onSearchEdit(const std::string& string)
{ {
if (!mActivePanel) return; if (!mActivePanel) return;
mFilterSubString = string;
if (string == "")
{
mActivePanel->setFilterSubString(LLStringUtil::null);
}
if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted()) if (!LLInventoryModelBackgroundFetch::instance().inventoryFetchStarted())
{ {
llassert(false); // this should have been done on startup llassert(false); // this should have been done on startup
LLInventoryModelBackgroundFetch::instance().start(); LLInventoryModelBackgroundFetch::instance().start();
} }
if (mActivePanel->getFilterSubString().empty() && string.empty())
{
// current filter and new filter empty, do nothing
return;
}
// set new filter string // set new filter string
mActivePanel->setFilterSubString(string); mActivePanel->setFilterSubString(string);
} }
@ -302,6 +289,7 @@ bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
{ {
return mActivePanel && mActivePanel->isActionEnabled(userdata); return mActivePanel && mActivePanel->isActionEnabled(userdata);
} }
// List Commands // // List Commands //
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
@ -330,7 +318,7 @@ void LLPanelOutfitsInventory::onTabChange()
mActivePanel = dynamic_cast<LLPanelAppearanceTab*>(mAppearanceTabs->getCurrentPanel()); mActivePanel = dynamic_cast<LLPanelAppearanceTab*>(mAppearanceTabs->getCurrentPanel());
if (!mActivePanel) return; if (!mActivePanel) return;
mActivePanel->setFilterSubString(mFilterSubString); mActivePanel->checkFilterSubString();
mActivePanel->onOpen(LLSD()); mActivePanel->onOpen(LLSD());
updateVerbs(); updateVerbs();
@ -357,8 +345,6 @@ bool LLPanelOutfitsInventory::isOutfitsGalleryPanelActive() const
return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME; return mActivePanel->getName() == OUTFIT_GALLERY_TAB_NAME;
} }
void LLPanelOutfitsInventory::setWearablesLoading(bool val) void LLPanelOutfitsInventory::setWearablesLoading(bool val)
{ {
updateVerbs(); updateVerbs();

View File

@ -66,7 +66,6 @@ protected:
private: private:
LLTabContainer* mAppearanceTabs; LLTabContainer* mAppearanceTabs;
std::string mFilterSubString;
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// tab panels // // tab panels //

View File

@ -561,7 +561,6 @@ void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id)
{ {
mPickName->setEnabled(TRUE); mPickName->setEnabled(TRUE);
mPickDescription->setEnabled(TRUE); mPickDescription->setEnabled(TRUE);
mSetCurrentLocationButton->setVisible(TRUE);
} }
else else
{ {
@ -576,7 +575,6 @@ BOOL LLPanelProfilePick::postBuild()
mSaveButton = getChild<LLButton>("save_changes_btn"); mSaveButton = getChild<LLButton>("save_changes_btn");
mCreateButton = getChild<LLButton>("create_changes_btn"); mCreateButton = getChild<LLButton>("create_changes_btn");
mCancelButton = getChild<LLButton>("cancel_changes_btn"); mCancelButton = getChild<LLButton>("cancel_changes_btn");
mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn");
mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot"); mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot");
mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this)); mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this));
@ -587,7 +585,6 @@ BOOL LLPanelProfilePick::postBuild()
mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this));
mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this));
mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this)); mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this));
mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this));
mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL); mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL);
mPickName->setEnabled(FALSE); mPickName->setEnabled(FALSE);
@ -749,32 +746,6 @@ BOOL LLPanelProfilePick::isDirty() const
return FALSE; return FALSE;
} }
void LLPanelProfilePick::onClickSetLocation()
{
// Save location for later use.
setPosGlobal(gAgent.getPositionGlobal());
std::string parcel_name, region_name;
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (parcel)
{
mParcelId = parcel->getID();
parcel_name = parcel->getName();
}
LLViewerRegion* region = gAgent.getRegion();
if (region)
{
region_name = region->getName();
}
setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal()));
mLocationChanged = true;
enableSaveButton(TRUE);
}
void LLPanelProfilePick::onClickSave() void LLPanelProfilePick::onClickSave()
{ {
sendUpdate(); sendUpdate();

View File

@ -201,11 +201,6 @@ protected:
*/ */
void resetDirty() override; void resetDirty() override;
/**
* Callback for "Set Location" button click
*/
void onClickSetLocation();
/** /**
* Callback for "Save" and "Create" button click * Callback for "Save" and "Create" button click
*/ */
@ -228,7 +223,6 @@ protected:
LLTextureCtrl* mSnapshotCtrl; LLTextureCtrl* mSnapshotCtrl;
LLLineEditor* mPickName; LLLineEditor* mPickName;
LLTextEditor* mPickDescription; LLTextEditor* mPickDescription;
LLButton* mSetCurrentLocationButton;
LLButton* mSaveButton; LLButton* mSaveButton;
LLButton* mCreateButton; LLButton* mCreateButton;
LLButton* mCancelButton; LLButton* mCancelButton;

View File

@ -32,6 +32,7 @@
// Viewer includes // Viewer includes
#include "llcombobox.h" #include "llcombobox.h"
#include "llsliderctrl.h" #include "llsliderctrl.h"
#include "llstartup.h"
#include "llviewercontrol.h" #include "llviewercontrol.h"
#include "llvoiceclient.h" #include "llvoiceclient.h"
#include "llvoicechannel.h" #include "llvoicechannel.h"
@ -70,11 +71,14 @@ BOOL LLPanelVoiceDeviceSettings::postBuild()
mCtrlInputDevices = getChild<LLComboBox>("voice_input_device"); mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device"); mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device");
mUnmuteBtn = getChild<LLButton>("unmute_btn");
mCtrlInputDevices->setCommitCallback( mCtrlInputDevices->setCommitCallback(
boost::bind(&LLPanelVoiceDeviceSettings::onCommitInputDevice, this)); boost::bind(&LLPanelVoiceDeviceSettings::onCommitInputDevice, this));
mCtrlOutputDevices->setCommitCallback( mCtrlOutputDevices->setCommitCallback(
boost::bind(&LLPanelVoiceDeviceSettings::onCommitOutputDevice, this)); boost::bind(&LLPanelVoiceDeviceSettings::onCommitOutputDevice, this));
mUnmuteBtn->setCommitCallback(
boost::bind(&LLPanelVoiceDeviceSettings::onCommitUnmute, this));
mLocalizedDeviceNames[DEFAULT_DEVICE] = getString("default_text"); mLocalizedDeviceNames[DEFAULT_DEVICE] = getString("default_text");
mLocalizedDeviceNames["No Device"] = getString("name_no_device"); mLocalizedDeviceNames["No Device"] = getString("name_no_device");
@ -108,11 +112,27 @@ void LLPanelVoiceDeviceSettings::draw()
// let user know that volume indicator is not yet available // let user know that volume indicator is not yet available
bool is_in_tuning_mode = LLVoiceClient::getInstance()->inTuningMode(); bool is_in_tuning_mode = LLVoiceClient::getInstance()->inTuningMode();
getChildView("wait_text")->setVisible( !is_in_tuning_mode && mUseTuningMode); bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled();
if (voice_enabled)
{
getChildView("wait_text")->setVisible( !is_in_tuning_mode && mUseTuningMode);
getChildView("disabled_text")->setVisible(FALSE);
mUnmuteBtn->setVisible(FALSE);
}
else
{
getChildView("wait_text")->setVisible(FALSE);
static LLCachedControl<bool> chat_enabled(gSavedSettings, "EnableVoiceChat");
// If voice isn't enabled, it is either disabled or muted
bool voice_disabled = chat_enabled() || LLStartUp::getStartupState() <= STATE_LOGIN_WAIT;
getChildView("disabled_text")->setVisible(voice_disabled);
mUnmuteBtn->setVisible(!voice_disabled);
}
LLPanel::draw(); LLPanel::draw();
if (is_in_tuning_mode) if (is_in_tuning_mode && voice_enabled)
{ {
const S32 num_bars = 5; const S32 num_bars = 5;
F32 voice_power = LLVoiceClient::getInstance()->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL; F32 voice_power = LLVoiceClient::getInstance()->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL;
@ -339,3 +359,8 @@ void LLPanelVoiceDeviceSettings::onInputDevicesClicked()
{ {
LLVoiceClient::getInstance()->refreshDeviceLists(false); // fill in the pop up menus again if needed. LLVoiceClient::getInstance()->refreshDeviceLists(false); // fill in the pop up menus again if needed.
} }
void LLPanelVoiceDeviceSettings::onCommitUnmute()
{
gSavedSettings.setBOOL("EnableVoiceChat", TRUE);
}

View File

@ -55,12 +55,14 @@ protected:
void onCommitOutputDevice(); void onCommitOutputDevice();
void onOutputDevicesClicked(); void onOutputDevicesClicked();
void onInputDevicesClicked(); void onInputDevicesClicked();
void onCommitUnmute();
F32 mMicVolume; F32 mMicVolume;
std::string mInputDevice; std::string mInputDevice;
std::string mOutputDevice; std::string mOutputDevice;
class LLComboBox *mCtrlInputDevices; class LLComboBox *mCtrlInputDevices;
class LLComboBox *mCtrlOutputDevices; class LLComboBox *mCtrlOutputDevices;
class LLButton *mUnmuteBtn;
BOOL mDevicesUpdated; BOOL mDevicesUpdated;
bool mUseTuningMode; bool mUseTuningMode;
std::map<std::string, std::string> mLocalizedDeviceNames; std::map<std::string, std::string> mLocalizedDeviceNames;

View File

@ -50,7 +50,7 @@ LLPanelVolumePulldown::LLPanelVolumePulldown()
{ {
mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2));
mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this)); mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this));
mCommitCallbackRegistrar.add("Vol.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelVolumePulldown::updateMediaAutoPlayCheckbox, this, _1)); mCommitCallbackRegistrar.add("Vol.updateCheckbox", boost::bind(&LLPanelVolumePulldown::updateCheckbox, this, _1, _2));
mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2)); mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2));
buildFromFile( "panel_volume_pulldown.xml"); buildFromFile( "panel_volume_pulldown.xml");
} }
@ -90,19 +90,23 @@ void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data)
control->set(LLSD(FALSE)); control->set(LLSD(FALSE));
} }
void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) void LLPanelVolumePulldown::updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data)
{ {
std::string name = ctrl->getName(); std::string control_name = user_data.asString();
if (control_name == "MediaAutoPlay")
{
std::string name = ctrl->getName();
// Disable "Allow Media to auto play" only when both // Disable "Allow Media to auto play" only when both
// "Streaming Music" and "Media" are unchecked. STORM-513. // "Streaming Music" and "Media" are unchecked. STORM-513.
if ((name == "enable_music") || (name == "enable_media")) if ((name == "enable_music") || (name == "enable_media"))
{ {
bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get(); bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get(); bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled); getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled);
} }
}
} }
void LLPanelVolumePulldown::onClickSetSounds() void LLPanelVolumePulldown::onClickSetSounds()

View File

@ -43,7 +43,7 @@ class LLPanelVolumePulldown : public LLPanelPulldown
void onClickSetSounds(); void onClickSetSounds();
// Disables "Allow Media to auto play" check box only when both // Disables "Allow Media to auto play" check box only when both
// "Streaming Music" and "Media" are unchecked. Otherwise enables it. // "Streaming Music" and "Media" are unchecked. Otherwise enables it.
void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl); void updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data);
void onAdvancedButtonClick(const LLSD& user_data); void onAdvancedButtonClick(const LLSD& user_data);
}; };

View File

@ -209,8 +209,6 @@ protected:
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
std::string LLPanelAppearanceTab::sFilterSubString = LLStringUtil::null;
static LLPanelInjector<LLPanelWearing> t_panel_wearing("panel_wearing"); static LLPanelInjector<LLPanelWearing> t_panel_wearing("panel_wearing");
LLPanelWearing::LLPanelWearing() LLPanelWearing::LLPanelWearing()
@ -328,10 +326,11 @@ void LLPanelWearing::startUpdateTimer()
} }
// virtual // virtual
void LLPanelWearing::setFilterSubString(const std::string& string) void LLPanelWearing::onFilterSubStringChanged(const std::string& new_string, const std::string& old_string)
{ {
sFilterSubString = string; mCOFItemsList->setFilterSubString(new_string, true);
mCOFItemsList->setFilterSubString(sFilterSubString);
mAccordionCtrl->arrange();
} }
// virtual // virtual

View File

@ -61,7 +61,7 @@ public:
/*virtual*/ void onOpen(const LLSD& info); /*virtual*/ void onOpen(const LLSD& info);
/*virtual*/ void setFilterSubString(const std::string& string); /*virtual*/ void onFilterSubStringChanged(const std::string& new_string, const std::string& old_string);
/*virtual*/ bool isActionEnabled(const LLSD& userdata); /*virtual*/ bool isActionEnabled(const LLSD& userdata);

View File

@ -87,6 +87,9 @@
#include "llexperiencecache.h" #include "llexperiencecache.h"
#include "llfloaterexperienceprofile.h" #include "llfloaterexperienceprofile.h"
#include "llviewerassetupload.h" #include "llviewerassetupload.h"
#include "lltoggleablemenu.h"
#include "llmenubutton.h"
#include "llinventoryfunctions.h"
const std::string HELLO_LSL = const std::string HELLO_LSL =
"default\n" "default\n"
@ -322,6 +325,38 @@ void LLFloaterScriptSearch::onSearchBoxCommit()
} }
} }
/// ---------------------------------------------------------------------------
class LLScriptMovedObserver : public LLInventoryObserver
{
public:
LLScriptMovedObserver(LLPreviewLSL *floater) : mPreview(floater) { gInventory.addObserver(this); }
virtual ~LLScriptMovedObserver() { gInventory.removeObserver(this); }
virtual void changed(U32 mask);
private:
LLPreviewLSL *mPreview;
};
void LLScriptMovedObserver::changed(U32 mask)
{
const std::set<LLUUID> &mChangedItemIDs = gInventory.getChangedIDs();
std::set<LLUUID>::const_iterator it;
const LLUUID &item_id = mPreview->getScriptID();
for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++)
{
if (*it == item_id)
{
if ((mask & (LLInventoryObserver::STRUCTURE)) != 0)
{
mPreview->setDirty();
}
}
}
}
/// --------------------------------------------------------------------------- /// ---------------------------------------------------------------------------
/// LLScriptEdCore /// LLScriptEdCore
/// --------------------------------------------------------------------------- /// ---------------------------------------------------------------------------
@ -460,6 +495,13 @@ BOOL LLScriptEdCore::postBuild()
LLSyntaxIdLSL::getInstance()->initialize(); LLSyntaxIdLSL::getInstance()->initialize();
processKeywords(); processKeywords();
mCommitCallbackRegistrar.add("FontSize.Set", boost::bind(&LLScriptEdCore::onChangeFontSize, this, _2));
mEnableCallbackRegistrar.add("FontSize.Check", boost::bind(&LLScriptEdCore::isFontSizeChecked, this, _2));
LLToggleableMenu *context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_lsl_font_size.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
getChild<LLMenuButton>("font_btn")->setMenu(context_menu, LLMenuButton::MP_BOTTOM_LEFT, true);
return TRUE; return TRUE;
} }
@ -788,7 +830,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string)
LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
url_string.setArg("[LSL_STRING]", help_string); url_string.setArg("[LSL_STRING]", help_string.empty() ? HELP_LSL_PORTAL_TOPIC : help_string);
addHelpItemToHistory(help_string); addHelpItemToHistory(help_string);
@ -1288,7 +1330,21 @@ LLUUID LLScriptEdCore::getAssociatedExperience()const
return mAssociatedExperience; return mAssociatedExperience;
} }
void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids ) void LLScriptEdCore::onChangeFontSize(const LLSD &userdata)
{
const std::string font_name = userdata.asString();
gSavedSettings.setString("LSLFontSizeName", font_name);
}
bool LLScriptEdCore::isFontSizeChecked(const LLSD &userdata)
{
const std::string current_size_name = LLScriptEditor::getScriptFontSize();
const std::string size_name = userdata.asString();
return (size_name == current_size_name);
}
void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids )
{ {
mExperienceIds=experience_ids; mExperienceIds=experience_ids;
updateExperiencePanel(); updateExperiencePanel();
@ -1476,7 +1532,21 @@ bool LLScriptEdContainer::onExternalChange(const std::string& filename)
return true; return true;
} }
/// --------------------------------------------------------------------------- BOOL LLScriptEdContainer::handleKeyHere(KEY key, MASK mask)
{
if (('A' == key) && (MASK_CONTROL == (mask & MASK_MODIFIERS)))
{
mScriptEd->selectAll();
return TRUE;
}
if (!LLPreview::handleKeyHere(key, mask))
{
return mScriptEd->handleKeyHere(key, mask);
}
return TRUE;
}
/// ---------------------------------------------------------------------------
/// LLPreviewLSL /// LLPreviewLSL
/// --------------------------------------------------------------------------- /// ---------------------------------------------------------------------------
@ -1517,6 +1587,14 @@ LLPreviewLSL::LLPreviewLSL(const LLSD& key )
mPendingUploads(0) mPendingUploads(0)
{ {
mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
mItemObserver = new LLScriptMovedObserver(this);
}
LLPreviewLSL::~LLPreviewLSL()
{
delete mItemObserver;
mItemObserver = NULL;
} }
// virtual // virtual
@ -1528,10 +1606,14 @@ BOOL LLPreviewLSL::postBuild()
if (item) if (item)
{ {
getChild<LLUICtrl>("desc")->setValue(item->getDescription()); getChild<LLUICtrl>("desc")->setValue(item->getDescription());
std::string item_path = get_category_path(item->getParentUUID());
getChild<LLUICtrl>("path_txt")->setValue(item_path);
getChild<LLUICtrl>("path_txt")->setToolTip(item_path);
} }
childSetCommitCallback("desc", LLPreview::onText, this); childSetCommitCallback("desc", LLPreview::onText, this);
getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
return LLPreview::postBuild(); return LLPreview::postBuild();
} }
@ -1543,7 +1625,12 @@ void LLPreviewLSL::draw()
setTitle(LLTrans::getString("ScriptWasDeleted")); setTitle(LLTrans::getString("ScriptWasDeleted"));
mScriptEd->setItemRemoved(TRUE); mScriptEd->setItemRemoved(TRUE);
} }
else if (mDirty)
{
std::string item_path = get_category_path(item->getParentUUID());
getChild<LLUICtrl>("path_txt")->setValue(item_path);
getChild<LLUICtrl>("path_txt")->setToolTip(item_path);
}
LLPreview::draw(); LLPreview::draw();
} }
// virtual // virtual
@ -1856,7 +1943,8 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
mPendingUploads(0), mPendingUploads(0),
mIsModifiable(FALSE), mIsModifiable(FALSE),
mIsNew(false), mIsNew(false),
mIsSaving(FALSE) mIsSaving(FALSE),
mObjectName("")
{ {
mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
} }
@ -1993,6 +2081,7 @@ void LLLiveLSLEditor::loadAsset()
} }
refreshFromItem(); refreshFromItem();
getChild<LLUICtrl>("obj_name")->setValue(mObjectName);
// This is commented out, because we don't completely // This is commented out, because we don't completely
// handle script exports yet. // handle script exports yet.
/* /*

View File

@ -36,6 +36,7 @@
#include "llfloatergotoline.h" #include "llfloatergotoline.h"
#include "lllivefile.h" #include "lllivefile.h"
#include "llsyntaxid.h" #include "llsyntaxid.h"
#include "llscripteditor.h"
class LLLiveLSLFile; class LLLiveLSLFile;
class LLMessageSystem; class LLMessageSystem;
@ -52,6 +53,7 @@ class LLViewerInventoryItem;
class LLScriptEdContainer; class LLScriptEdContainer;
class LLFloaterGotoLine; class LLFloaterGotoLine;
class LLFloaterExperienceProfile; class LLFloaterExperienceProfile;
class LLScriptMovedObserver;
class LLLiveLSLFile : public LLLiveFile class LLLiveLSLFile : public LLLiveFile
{ {
@ -145,7 +147,13 @@ public:
void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; }; void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; };
LLUUID getAssetID() { return mAssetID; } LLUUID getAssetID() { return mAssetID; }
private: bool isFontSizeChecked(const LLSD &userdata);
void onChangeFontSize(const LLSD &size_name);
virtual BOOL handleKeyHere(KEY key, MASK mask);
void selectAll() { mEditor->selectAll(); }
private:
void onBtnDynamicHelp(); void onBtnDynamicHelp();
void onBtnUndoChanges(); void onBtnUndoChanges();
@ -153,8 +161,6 @@ private:
void selectFirstError(); void selectFirstError();
virtual BOOL handleKeyHere(KEY key, MASK mask);
void enableSave(BOOL b) {mEnableSave = b;} void enableSave(BOOL b) {mEnableSave = b;}
protected: protected:
@ -207,6 +213,8 @@ public:
LLScriptEdContainer(const LLSD& key); LLScriptEdContainer(const LLSD& key);
LLScriptEdContainer(const LLSD& key, const bool live); LLScriptEdContainer(const LLSD& key, const bool live);
BOOL handleKeyHere(KEY key, MASK mask);
protected: protected:
std::string getTmpFileName(const std::string& script_name); std::string getTmpFileName(const std::string& script_name);
bool onExternalChange(const std::string& filename); bool onExternalChange(const std::string& filename);
@ -220,6 +228,12 @@ class LLPreviewLSL : public LLScriptEdContainer
{ {
public: public:
LLPreviewLSL(const LLSD& key ); LLPreviewLSL(const LLSD& key );
~LLPreviewLSL();
LLUUID getScriptID() { return mItemUUID; }
void setDirty() { mDirty = true; }
virtual void callbackLSLCompileSucceeded(); virtual void callbackLSLCompileSucceeded();
virtual void callbackLSLCompileFailed(const LLSD& compile_errors); virtual void callbackLSLCompileFailed(const LLSD& compile_errors);
@ -251,6 +265,8 @@ protected:
// Can safely close only after both text and bytecode are uploaded // Can safely close only after both text and bytecode are uploaded
S32 mPendingUploads; S32 mPendingUploads;
LLScriptMovedObserver* mItemObserver;
}; };
@ -283,6 +299,8 @@ public:
void requestExperiences(); void requestExperiences();
void experienceChanged(); void experienceChanged();
void addAssociatedExperience(const LLSD& experience); void addAssociatedExperience(const LLSD& experience);
void setObjectName(std::string name) { mObjectName = name; }
private: private:
virtual BOOL canClose(); virtual BOOL canClose();
@ -341,6 +359,7 @@ private:
LLSD mExperienceIds; LLSD mExperienceIds;
LLHandle<LLFloater> mExperienceProfile; LLHandle<LLFloater> mExperienceProfile;
std::string mObjectName;
}; };
#endif // LL_LLPREVIEWSCRIPT_H #endif // LL_LLPREVIEWSCRIPT_H

View File

@ -657,19 +657,6 @@ void LLSceneMonitor::dumpToFile(const std::string &file_name)
} }
} }
typedef LLTrace::StatType<LLTrace::MemAccumulator> trace_mem;
for (auto& it : trace_mem::instance_snapshot())
{
os << it.getName() << "(KiB)";
for (S32 frame = 1; frame <= frame_count; frame++)
{
os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(it).valueInUnits<LLUnits::Kilobytes>();
}
os << '\n';
}
os.flush(); os.flush();
os.close(); os.close();
} }

View File

@ -30,19 +30,22 @@
#include "llsyntaxid.h" #include "llsyntaxid.h"
#include "lllocalcliprect.h" #include "lllocalcliprect.h"
#include "llviewercontrol.h"
const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32; const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32;
static LLDefaultChildRegistry::Register<LLScriptEditor> r("script_editor"); static LLDefaultChildRegistry::Register<LLScriptEditor> r("script_editor");
LLScriptEditor::Params::Params() LLScriptEditor::Params::Params()
: show_line_numbers("show_line_numbers", true) : show_line_numbers("show_line_numbers", true),
default_font_size("default_font_size", false)
{} {}
LLScriptEditor::LLScriptEditor(const Params& p) LLScriptEditor::LLScriptEditor(const Params& p)
: LLTextEditor(p) : LLTextEditor(p)
, mShowLineNumbers(p.show_line_numbers) , mShowLineNumbers(p.show_line_numbers),
mUseDefaultFontSize(p.default_font_size)
{ {
if (mShowLineNumbers) if (mShowLineNumbers)
{ {
@ -51,6 +54,12 @@ LLScriptEditor::LLScriptEditor(const Params& p)
} }
} }
BOOL LLScriptEditor::postBuild()
{
gSavedSettings.getControl("LSLFontSizeName")->getCommitSignal()->connect(boost::bind(&LLScriptEditor::onFontSizeChange, this));
return LLTextEditor::postBuild();
}
void LLScriptEditor::draw() void LLScriptEditor::draw()
{ {
{ {
@ -110,12 +119,11 @@ void LLScriptEditor::drawLineNumbers()
// draw the line numbers // draw the line numbers
if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop) if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop)
{ {
const LLFontGL *num_font = LLFontGL::getFontMonospace();
const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum )); const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum ));
BOOL is_cur_line = cursor_line == line.mLineNum; BOOL is_cur_line = cursor_line == line.mLineNum;
const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL; const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL;
const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor; const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor;
num_font->render( getScriptFont()->render(
ltext, // string to draw ltext, // string to draw
0, // begin offset 0, // begin offset
UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x
@ -143,8 +151,10 @@ void LLScriptEditor::loadKeywords()
LL_PROFILE_ZONE_SCOPED; LL_PROFILE_ZONE_SCOPED;
mKeywords.processTokens(); mKeywords.processTokens();
LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
segment_vec_t segment_list; segment_vec_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); mKeywords.findSegments(&segment_list, getWText(), *this, style);
mSegments.clear(); mSegments.clear();
segment_set_t::iterator insert_it = mSegments.begin(); segment_set_t::iterator insert_it = mSegments.begin();
@ -159,9 +169,12 @@ void LLScriptEditor::updateSegments()
if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly) if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly)
{ {
LL_PROFILE_ZONE_SCOPED; LL_PROFILE_ZONE_SCOPED;
LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
// HACK: No non-ascii keywords for now // HACK: No non-ascii keywords for now
segment_vec_t segment_list; segment_vec_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); mKeywords.findSegments(&segment_list, getWText(), *this, style);
clearSegments(); clearSegments();
for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
@ -211,3 +224,23 @@ void LLScriptEditor::drawSelectionBackground()
} }
} }
} }
std::string LLScriptEditor::getScriptFontSize()
{
static LLCachedControl<std::string> size_name(gSavedSettings, "LSLFontSizeName", "Monospace");
return size_name;
}
LLFontGL* LLScriptEditor::getScriptFont()
{
std::string font_size_name = mUseDefaultFontSize ? "Monospace" : getScriptFontSize();
return LLFontGL::getFont(LLFontDescriptor("Monospace", font_size_name, 0));
}
void LLScriptEditor::onFontSizeChange()
{
if (!mUseDefaultFontSize)
{
needsReflow();
}
}

View File

@ -37,7 +37,7 @@ public:
struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
{ {
Optional<bool> show_line_numbers; Optional<bool> show_line_numbers;
Optional<bool> default_font_size;
Params(); Params();
}; };
@ -45,6 +45,7 @@ public:
// LLView override // LLView override
virtual void draw(); virtual void draw();
BOOL postBuild();
void initKeywords(); void initKeywords();
void loadKeywords(); void loadKeywords();
@ -52,7 +53,11 @@ public:
LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); } LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); }
LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); } LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); }
protected: static std::string getScriptFontSize();
LLFontGL* getScriptFont();
void onFontSizeChange();
protected:
friend class LLUICtrlFactory; friend class LLUICtrlFactory;
LLScriptEditor(const Params& p); LLScriptEditor(const Params& p);
@ -65,6 +70,7 @@ private:
LLKeywords mKeywords; LLKeywords mKeywords;
bool mShowLineNumbers; bool mShowLineNumbers;
bool mUseDefaultFontSize;
}; };
#endif // LL_SCRIPTEDITOR_H #endif // LL_SCRIPTEDITOR_H

View File

@ -75,6 +75,17 @@ bool LLSearchHistory::save()
{ {
// build filename for each user // build filename for each user
std::string resolved_filename = getHistoryFilePath(); std::string resolved_filename = getHistoryFilePath();
// delete the file if it is empty or contains only empty entries
if (std::find_if(mSearchHistory.begin(), mSearchHistory.end(), [](const LLSearchHistoryItem& x)
{
return !x.search_query.empty();
}) == mSearchHistory.end())
{
remove(resolved_filename.c_str());
return true;
}
// open a file for writing // open a file for writing
llofstream file(resolved_filename.c_str()); llofstream file(resolved_filename.c_str());
if (!file.is_open()) if (!file.is_open())

View File

@ -1,4 +1,4 @@
/** /**
* @file llurlsimstring.cpp (was llsimurlstring.cpp) * @file llurlsimstring.cpp (was llsimurlstring.cpp)
* @brief Handles "SLURL fragments" like Ahern/123/45 for * @brief Handles "SLURL fragments" like Ahern/123/45 for
* startup processing, login screen, prefs, etc. * startup processing, login screen, prefs, etc.
@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2010, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; * License as published by the Free Software Foundation;
* version 2.1 of the License only. * version 2.1 of the License only.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
@ -36,7 +36,7 @@
#include "curl/curl.h" #include "curl/curl.h"
const char* LLSLURL::SLURL_HTTP_SCHEME = "http"; const char* LLSLURL::SLURL_HTTP_SCHEME = "http";
const char* LLSLURL::SLURL_HTTPS_SCHEME = "https"; const char* LLSLURL::SLURL_HTTPS_SCHEME = "https";
const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife"; const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife";
const char* LLSLURL::SLURL_SECONDLIFE_PATH = "secondlife"; const char* LLSLURL::SLURL_SECONDLIFE_PATH = "secondlife";
const char* LLSLURL::SLURL_COM = "slurl.com"; const char* LLSLURL::SLURL_COM = "slurl.com";
// For DnD - even though www.slurl.com redirects to slurl.com in a browser, you can copy and drag // For DnD - even though www.slurl.com redirects to slurl.com in a browser, you can copy and drag
@ -54,473 +54,469 @@ const char* LLSLURL::SIM_LOCATION_LAST = "last";
// resolve a simstring from a slurl // resolve a simstring from a slurl
LLSLURL::LLSLURL(const std::string& slurl) LLSLURL::LLSLURL(const std::string& slurl)
{ {
// by default we go to agni. // by default we go to agni.
mType = INVALID; mType = INVALID;
if(slurl == SIM_LOCATION_HOME) if (slurl.empty() || (slurl == SIM_LOCATION_LAST))
{ {
mType = HOME_LOCATION; mType = LAST_LOCATION;
} }
else if(slurl.empty() || (slurl == SIM_LOCATION_LAST)) else if (slurl == SIM_LOCATION_HOME)
{ {
mType = LAST_LOCATION; mType = HOME_LOCATION;
} }
else else
{ {
LLURI slurl_uri; LLURI slurl_uri;
// parse the slurl as a uri // parse the slurl as a uri
if(slurl.find(':') == std::string::npos) if (slurl.find(':') == std::string::npos)
{ {
// There may be no scheme ('secondlife:' etc.) passed in. In that case // There may be no scheme ('secondlife:' etc.) passed in. In that case
// we want to normalize the slurl by putting the appropriate scheme // we want to normalize the slurl by putting the appropriate scheme
// in front of the slurl. So, we grab the appropriate slurl base // in front of the slurl. So, we grab the appropriate slurl base
// from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or // from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or
// https://<hostname>/region/ for Standalone grid (the word region, not the region name) // https://<hostname>/region/ for Standalone grid (the word region, not the region name)
// these slurls are typically passed in from the 'starting location' box on the login panel, // these slurls are typically passed in from the 'starting location' box on the login panel,
// where the user can type in <regionname>/<x>/<y>/<z> // where the user can type in <regionname>/<x>/<y>/<z>
std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase(); std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase();
// the slurl that was passed in might have a prepended /, or not. So, // the slurl that was passed in might have a prepended /, or not. So,
// we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife/<region>/<x>/<y>/<z> // we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife/<region>/<x>/<y>/<z>
// or some such. // or some such.
if(slurl[0] == '/')
{
fixed_slurl += slurl.substr(1);
}
else
{
fixed_slurl += slurl;
}
// We then load the slurl into a LLURI form
slurl_uri = LLURI(fixed_slurl);
}
else
{
// as we did have a scheme, implying a URI style slurl, we
// simply parse it as a URI
slurl_uri = LLURI(slurl);
}
LLSD path_array = slurl_uri.pathArray();
// determine whether it's a maingrid URI or an Standalone/open style URI
// by looking at the scheme. If it's a 'secondlife:' slurl scheme or
// 'sl:' scheme, we know it's maingrid
// At the end of this if/else block, we'll have determined the grid,
// and the slurl type (APP or LOCATION)
if(slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
{
// parse a maingrid style slurl. We know the grid is maingrid
// so grab it.
// A location slurl for maingrid (with the special schemes) can be in the form
// secondlife://<regionname>/<x>/<y>/<z>
// or
// secondlife://<Grid>/secondlife/<region>/<x>/<y>/<z>
// where if grid is empty, it specifies Agni
// An app style slurl for maingrid can be
// secondlife://<Grid>/app/<app parameters>
// where an empty grid implies Agni
// we'll start by checking the top of the 'path' which will be
// either 'app', 'secondlife', or <x>.
// default to maingrid
mGrid = MAINGRID;
if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) ||
(path_array[0].asString() == LLSLURL::SLURL_APP_PATH))
{
// it's in the form secondlife://<grid>/(app|secondlife)
// so parse the grid name to derive the grid ID
if (!slurl_uri.hostName().empty())
{
mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName());
}
else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
{
// If the slurl is in the form secondlife:///secondlife/<region> form,
// then we are in fact on maingrid.
mGrid = MAINGRID;
}
else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
{
// for app style slurls, where no grid name is specified, assume the currently
// selected or logged in grid.
mGrid = LLGridManager::getInstance()->getGridId();
}
if(mGrid.empty()) if (slurl[0] == '/')
{ {
// we couldn't find the grid in the grid manager, so bail fixed_slurl += slurl.substr(1);
LL_WARNS("AppInit")<<"unable to find grid"<<LL_ENDL; }
return; else
} {
// set the type as appropriate. fixed_slurl += slurl;
if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) }
{ // We then load the slurl into a LLURI form
mType = LOCATION; slurl_uri = LLURI(fixed_slurl);
} }
else else
{ {
mType = APP; // as we did have a scheme, implying a URI style slurl, we
} // simply parse it as a URI
path_array.erase(0); slurl_uri = LLURI(slurl);
} }
else
{ LLSD path_array = slurl_uri.pathArray();
if(slurl_uri.hostName() == LLSLURL::SLURL_APP_PATH)
// determine whether it's a maingrid URI or an Standalone/open style URI
// by looking at the scheme. If it's a 'secondlife:' slurl scheme or
// 'sl:' scheme, we know it's maingrid
// At the end of this if/else block, we'll have determined the grid,
// and the slurl type (APP or LOCATION)
if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
{
if (path_array.size() == 0
&& slurl_uri.authority().empty()
&& slurl_uri.escapedQuery().empty())
{
mType = EMPTY;
// um, we need a path...
return;
}
// parse a maingrid style slurl. We know the grid is maingrid
// so grab it.
// A location slurl for maingrid (with the special schemes) can be in the form
// secondlife://<regionname>/<x>/<y>/<z>
// or
// secondlife://<Grid>/secondlife/<region>/<x>/<y>/<z>
// where if grid is empty, it specifies Agni
// An app style slurl for maingrid can be
// secondlife://<Grid>/app/<app parameters>
// where an empty grid implies Agni
// we'll start by checking the top of the 'path' which will be
// either 'app', 'secondlife', or <x>.
// default to maingrid
mGrid = MAINGRID;
if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) ||
(path_array[0].asString() == LLSLURL::SLURL_APP_PATH))
{
// it's in the form secondlife://<grid>/(app|secondlife)
// so parse the grid name to derive the grid ID
if (!slurl_uri.hostName().empty())
{
mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName());
}
else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
{
// If the slurl is in the form secondlife:///secondlife/<region> form,
// then we are in fact on maingrid.
mGrid = MAINGRID;
}
else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
{
// for app style slurls, where no grid name is specified, assume the currently
// selected or logged in grid.
mGrid = LLGridManager::getInstance()->getGridId();
}
if (mGrid.empty())
{
// we couldn't find the grid in the grid manager, so bail
LL_WARNS("AppInit")<<"unable to find grid"<<LL_ENDL;
return;
}
// set the type as appropriate.
if (path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
{
mType = LOCATION;
}
else
{
mType = APP;
}
path_array.erase(0);
}
else
{
if (slurl_uri.hostName() == LLSLURL::SLURL_APP_PATH)
{ {
mType = APP; mType = APP;
} }
else else
{ {
// it wasn't a /secondlife/<region> or /app/<params>, so it must be secondlife://<region> // it wasn't a /secondlife/<region> or /app/<params>, so it must be secondlife://<region>
// therefore the hostname will be the region name, and it's a location type // therefore the hostname will be the region name, and it's a location type
mType = LOCATION; mType = LOCATION;
// 'normalize' it so the region name is in fact the head of the path_array // 'normalize' it so the region name is in fact the head of the path_array
path_array.insert(0, slurl_uri.hostName()); path_array.insert(0, slurl_uri.hostName());
}
}
}
else if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) ||
(slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) ||
(slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME))
{
// We're dealing with either a Standalone style slurl or slurl.com slurl
if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) ||
(slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) ||
(slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM))
{
// slurl.com implies maingrid
mGrid = MAINGRID;
}
else
{
// Don't try to match any old http://<host>/ URL as a SLurl.
// SLE SLurls will have the grid hostname in the URL, so only
// match http URLs if the hostname matches the grid hostname
// (or its a slurl.com or maps.secondlife.com URL).
if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME ||
slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) &&
slurl_uri.hostName() != LLGridManager::getInstance()->getGrid())
{
return;
} }
}
}
else if((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) ||
(slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) ||
(slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME))
{
// We're dealing with either a Standalone style slurl or slurl.com slurl
if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) ||
(slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) ||
(slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM))
{
// slurl.com implies maingrid
mGrid = MAINGRID;
}
else
{
// Don't try to match any old http://<host>/ URL as a SLurl.
// SLE SLurls will have the grid hostname in the URL, so only
// match http URLs if the hostname matches the grid hostname
// (or its a slurl.com or maps.secondlife.com URL).
if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME ||
slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) &&
slurl_uri.hostName() != LLGridManager::getInstance()->getGrid())
{
return;
}
// As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style // As it's a Standalone grid/open, we will always have a hostname, as Standalone/open style
// urls are properly formed, unlike the stinky maingrid style // urls are properly formed, unlike the stinky maingrid style
mGrid = slurl_uri.hostName(); mGrid = slurl_uri.hostName();
} }
if (path_array.size() == 0) if (path_array.size() == 0)
{ {
// um, we need a path... // um, we need a path...
return; return;
} }
// we need to normalize the urls so
// the path portion starts with the 'command' that we want to do
// it can either be region or app.
if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) ||
(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH))
{
// strip off 'region' or 'secondlife'
path_array.erase(0);
// it's a location
mType = LOCATION;
}
else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
{
mType = APP;
path_array.erase(0);
// leave app appended.
}
else
{
// not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL
return;
}
}
else
{
// invalid scheme, so bail
return;
}
if(path_array.size() == 0)
{
// we gotta have some stuff after the specifier as to whether it's a region or command
return;
}
// now that we know whether it's an app slurl or a location slurl,
// parse the slurl into the proper data structures.
if(mType == APP)
{
// grab the app command type and strip it (could be a command to jump somewhere,
// or whatever )
mAppCmd = path_array[0].asString();
path_array.erase(0);
// Grab the parameters
mAppPath = path_array;
// and the query
mAppQuery = slurl_uri.query();
mAppQueryMap = slurl_uri.queryMap();
return;
}
else if(mType == LOCATION)
{
// at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z
// are collectively optional
// are optional
mRegion = LLURI::unescape(path_array[0].asString()); // we need to normalize the urls so
// the path portion starts with the 'command' that we want to do
// it can either be region or app.
if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) ||
(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH))
{
// strip off 'region' or 'secondlife'
path_array.erase(0);
// it's a location
mType = LOCATION;
}
else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
{
mType = APP;
path_array.erase(0);
// leave app appended.
}
else
{
// not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL
return;
}
}
else
{
// invalid scheme, so bail
return;
}
if(LLStringUtil::containsNonprintable(mRegion)) if (path_array.size() == 0)
{ {
LLStringUtil::stripNonprintable(mRegion); // we gotta have some stuff after the specifier as to whether it's a region or command
} return;
}
path_array.erase(0); // now that we know whether it's an app slurl or a location slurl,
// parse the slurl into the proper data structures.
// parse the x, y, and optionally z if (mType == APP)
if(path_array.size() >= 2) {
{ // grab the app command type and strip it (could be a command to jump somewhere,
// or whatever )
mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f) mAppCmd = path_array[0].asString();
if((F32(mPosition[VX]) < 0.f) || path_array.erase(0);
(mPosition[VX] > REGION_WIDTH_METERS) ||
(F32(mPosition[VY]) < 0.f) || // Grab the parameters
(mPosition[VY] > REGION_WIDTH_METERS) || mAppPath = path_array;
(F32(mPosition[VZ]) < 0.f) || // and the query
(mPosition[VZ] > REGION_HEIGHT_METERS)) mAppQuery = slurl_uri.query();
{ mAppQueryMap = slurl_uri.queryMap();
mType = INVALID; return;
return; }
} else if (mType == LOCATION)
{
} // at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z
else // are collectively optional
{ // are optional
// if x, y and z were not fully passed in, go to the middle of the region.
// teleport will adjust the actual location to make sure you're on the ground mRegion = LLURI::unescape(path_array[0].asString());
// and such
mPosition = LLVector3(REGION_WIDTH_METERS/2, REGION_WIDTH_METERS/2, 0); if (LLStringUtil::containsNonprintable(mRegion))
} {
} LLStringUtil::stripNonprintable(mRegion);
} }
path_array.erase(0);
// parse the x, y, and optionally z
if (path_array.size() >= 2)
{
mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f)
if ((F32(mPosition[VX]) < 0.f) || (mPosition[VX] > REGION_WIDTH_METERS) ||
(F32(mPosition[VY]) < 0.f) || (mPosition[VY] > REGION_WIDTH_METERS) ||
(F32(mPosition[VZ]) < 0.f) || (mPosition[VZ] > REGION_HEIGHT_METERS))
{
mType = INVALID;
return;
}
}
else
{
// if x, y and z were not fully passed in, go to the middle of the region.
// teleport will adjust the actual location to make sure you're on the ground
// and such
mPosition = LLVector3(REGION_WIDTH_METERS / 2, REGION_WIDTH_METERS / 2, 0);
}
}
}
} }
// Create a slurl for the middle of the region // Create a slurl for the middle of the region
LLSLURL::LLSLURL(const std::string& grid, LLSLURL::LLSLURL(const std::string& grid, const std::string& region)
const std::string& region)
{ {
mGrid = grid; mGrid = grid;
mRegion = region; mRegion = region;
mType = LOCATION; mType = LOCATION;
mPosition = LLVector3((F64)REGION_WIDTH_METERS/2, (F64)REGION_WIDTH_METERS/2, 0); mPosition = LLVector3((F64)REGION_WIDTH_METERS / 2, (F64)REGION_WIDTH_METERS / 2, 0);
} }
// create a slurl given the position. The position will be modded with the region // create a slurl given the position. The position will be modded with the region
// width handling global positions as well // width handling global positions as well
LLSLURL::LLSLURL(const std::string& grid, LLSLURL::LLSLURL(const std::string& grid,
const std::string& region, const std::string& region,
const LLVector3& position) const LLVector3& position)
{ {
mGrid = grid; mGrid = grid;
mRegion = region; mRegion = region;
S32 x = ll_round( (F32)fmod( position[VX], (F32)REGION_WIDTH_METERS ) ); S32 x = ll_round((F32)fmod(position[VX], (F32)REGION_WIDTH_METERS));
S32 y = ll_round( (F32)fmod( position[VY], (F32)REGION_WIDTH_METERS ) ); S32 y = ll_round((F32)fmod(position[VY], (F32)REGION_WIDTH_METERS));
S32 z = ll_round( (F32)position[VZ] ); S32 z = ll_round((F32)position[VZ]);
mType = LOCATION; mType = LOCATION;
mPosition = LLVector3(x, y, z); mPosition = LLVector3(x, y, z);
} }
// create a simstring // create a simstring
LLSLURL::LLSLURL(const std::string& region, LLSLURL::LLSLURL(const std::string& region,
const LLVector3& position) const LLVector3& position)
{ {
*this = LLSLURL(LLGridManager::getInstance()->getGridId(), *this = LLSLURL(LLGridManager::getInstance()->getGridId(), region, position);
region, position);
} }
// create a slurl from a global position // create a slurl from a global position
LLSLURL::LLSLURL(const std::string& grid, LLSLURL::LLSLURL(const std::string& grid,
const std::string& region, const std::string& region,
const LLVector3d& global_position) const LLVector3d& global_position)
{ {
*this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), *this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), region,
region, LLVector3(global_position.mdV[VX], LLVector3(global_position.mdV[VX], global_position.mdV[VY], global_position.mdV[VZ]));
global_position.mdV[VY],
global_position.mdV[VZ]));
} }
// create a slurl from a global position // create a slurl from a global position
LLSLURL::LLSLURL(const std::string& region, LLSLURL::LLSLURL(const std::string& region,
const LLVector3d& global_position) const LLVector3d& global_position)
{ {
*this = LLSLURL(LLGridManager::getInstance()->getGridId(), *this = LLSLURL(LLGridManager::getInstance()->getGridId(),
region, global_position); region, global_position);
} }
LLSLURL::LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb) LLSLURL::LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb)
{ {
mType = APP; mType = APP;
mAppCmd = command; mAppCmd = command;
mAppPath = LLSD::emptyArray(); mAppPath = LLSD::emptyArray();
mAppPath.append(LLSD(id)); mAppPath.append(LLSD(id));
mAppPath.append(LLSD(verb)); mAppPath.append(LLSD(verb));
} }
std::string LLSLURL::getSLURLString() const std::string LLSLURL::getSLURLString() const
{ {
switch(mType) switch (mType)
{ {
case HOME_LOCATION: case HOME_LOCATION:
return SIM_LOCATION_HOME; return SIM_LOCATION_HOME;
case LAST_LOCATION: case LAST_LOCATION:
return SIM_LOCATION_LAST; return SIM_LOCATION_LAST;
case LOCATION: case LOCATION:
{ {
// lookup the grid // lookup the grid
S32 x = ll_round( (F32)mPosition[VX] ); S32 x = ll_round((F32)mPosition[VX]);
S32 y = ll_round( (F32)mPosition[VY] ); S32 y = ll_round((F32)mPosition[VY]);
S32 z = ll_round( (F32)mPosition[VZ] ); S32 z = ll_round((F32)mPosition[VZ]);
return LLGridManager::getInstance()->getSLURLBase(mGrid) + return LLGridManager::getInstance()->getSLURLBase(mGrid) +
LLURI::escape(mRegion) + llformat("/%d/%d/%d",x,y,z); LLURI::escape(mRegion) + llformat("/%d/%d/%d", x, y, z);
} }
case APP: case APP:
{ {
std::ostringstream app_url; std::ostringstream app_url;
app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd; app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd;
for(LLSD::array_const_iterator i = mAppPath.beginArray(); for (LLSD::array_const_iterator i = mAppPath.beginArray();
i != mAppPath.endArray(); i != mAppPath.endArray();
i++) i++)
{ {
app_url << "/" << i->asString(); app_url << "/" << i->asString();
} }
if(mAppQuery.length() > 0) if (mAppQuery.length() > 0)
{ {
app_url << "?" << mAppQuery; app_url << "?" << mAppQuery;
} }
return app_url.str(); return app_url.str();
} }
default: default:
LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL; LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL;
return std::string(); return std::string();
} }
} }
std::string LLSLURL::getLoginString() const std::string LLSLURL::getLoginString() const
{ {
std::stringstream unescaped_start;
std::stringstream unescaped_start; switch (mType)
switch(mType) {
{ case LOCATION:
case LOCATION: unescaped_start << "uri:"
unescaped_start << "uri:" << mRegion << "&"
<< mRegion << "&" << ll_round(mPosition[0]) << "&"
<< ll_round(mPosition[0]) << "&" << ll_round(mPosition[1]) << "&"
<< ll_round(mPosition[1]) << "&" << ll_round(mPosition[2]);
<< ll_round(mPosition[2]); break;
break; case HOME_LOCATION:
case HOME_LOCATION: unescaped_start << "home";
unescaped_start << "home"; break;
break; case LAST_LOCATION:
case LAST_LOCATION: unescaped_start << "last";
unescaped_start << "last"; break;
break; default:
default: LL_WARNS("AppInit") << "Unexpected SLURL type (" << (int)mType << ")for login string" << LL_ENDL;
LL_WARNS("AppInit") << "Unexpected SLURL type ("<<(int)mType <<")for login string"<< LL_ENDL; break;
break; }
} return xml_escape_string(unescaped_start.str());
return xml_escape_string(unescaped_start.str());
} }
bool LLSLURL::operator==(const LLSLURL& rhs) bool LLSLURL::operator ==(const LLSLURL& rhs)
{ {
if(rhs.mType != mType) return false; if (rhs.mType != mType)
switch(mType) return false;
{
case LOCATION: switch (mType)
return ((mGrid == rhs.mGrid) && {
(mRegion == rhs.mRegion) && case LOCATION:
(mPosition == rhs.mPosition)); return (mGrid == rhs.mGrid) &&
case APP: (mRegion == rhs.mRegion) &&
return getSLURLString() == rhs.getSLURLString(); (mPosition == rhs.mPosition);
case HOME_LOCATION: case APP:
case LAST_LOCATION: return getSLURLString() == rhs.getSLURLString();
return true;
default: case HOME_LOCATION:
return false; case LAST_LOCATION:
} return true;
default:
return false;
}
} }
bool LLSLURL::operator !=(const LLSLURL& rhs) bool LLSLURL::operator !=(const LLSLURL& rhs)
{ {
return !(*this == rhs); return !(*this == rhs);
} }
std::string LLSLURL::getLocationString() const std::string LLSLURL::getLocationString() const
{ {
return llformat("%s/%d/%d/%d", return llformat("%s/%d/%d/%d",
mRegion.c_str(), mRegion.c_str(),
(int)ll_round(mPosition[0]), (int)ll_round(mPosition[0]),
(int)ll_round(mPosition[1]), (int)ll_round(mPosition[1]),
(int)ll_round(mPosition[2])); (int)ll_round(mPosition[2]));
} }
// static // static
const std::string LLSLURL::typeName[NUM_SLURL_TYPES] = const std::string LLSLURL::typeName[NUM_SLURL_TYPES] =
{ {
"INVALID", "INVALID",
"LOCATION", "LOCATION",
"HOME_LOCATION", "HOME_LOCATION",
"LAST_LOCATION", "LAST_LOCATION",
"APP", "APP",
"HELP" "HELP",
"EMPTY"
}; };
std::string LLSLURL::getTypeString(SLURL_TYPE type) std::string LLSLURL::getTypeString(SLURL_TYPE type)
{ {
std::string name; std::string name;
if ( type >= INVALID && type < NUM_SLURL_TYPES ) if (type >= INVALID && type < NUM_SLURL_TYPES)
{ {
name = LLSLURL::typeName[type]; name = LLSLURL::typeName[type];
} }
else else
{ {
name = llformat("Out of Range (%d)",type); name = llformat("Out of Range (%d)", type);
} }
return name; return name;
} }
std::string LLSLURL::asString() const std::string LLSLURL::asString() const
{ {
std::ostringstream result; std::ostringstream result;
result result
<< " mType: " << LLSLURL::getTypeString(mType) << " mType: " << LLSLURL::getTypeString(mType)
<< " mGrid: " + getGrid() << " mGrid: " + getGrid()
<< " mRegion: " + getRegion() << " mRegion: " + getRegion()
<< " mPosition: " << mPosition << " mPosition: " << mPosition
<< " mAppCmd:" << getAppCmd() << " mAppCmd:" << getAppCmd()
<< " mAppPath:" + getAppPath().asString() << " mAppPath:" + getAppPath().asString()
<< " mAppQueryMap:" + getAppQueryMap().asString() << " mAppQueryMap:" + getAppQueryMap().asString()
<< " mAppQuery: " + getAppQuery() << " mAppQuery: " + getAppQuery()
; ;
return result.str(); return result.str();
} }

View File

@ -52,13 +52,14 @@ public:
static const char* SLURL_REGION_PATH; static const char* SLURL_REGION_PATH;
// if you modify this enumeration, update typeName as well // if you modify this enumeration, update typeName as well
enum SLURL_TYPE { enum SLURL_TYPE {
INVALID, INVALID,
LOCATION, LOCATION,
HOME_LOCATION, HOME_LOCATION,
LAST_LOCATION, LAST_LOCATION,
APP, APP,
HELP, HELP,
EMPTY,
NUM_SLURL_TYPES // must be last NUM_SLURL_TYPES // must be last
}; };

View File

@ -830,6 +830,41 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
assert_states_valid(this); assert_states_valid(this);
} }
//virtual
void LLSpatialGroup::rebound()
{
if (!isDirty())
return;
super::rebound();
if (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_CONTROL_AV)
{
llassert(mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_CONTROL_AV);
LLSpatialBridge* bridge = getSpatialPartition()->asBridge();
if (bridge &&
bridge->mDrawable &&
bridge->mDrawable->getVObj() &&
bridge->mDrawable->getVObj()->isRoot())
{
LLControlAvatar* controlAvatar = bridge->mDrawable->getVObj()->getControlAvatar();
if (controlAvatar &&
controlAvatar->mDrawable &&
controlAvatar->mControlAVBridge &&
controlAvatar->mControlAVBridge->mOctree)
{
LLSpatialGroup* root = (LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0);
if (this == root)
{
const LLVector4a* addingExtents = controlAvatar->mDrawable->getSpatialExtents();
const LLXformMatrix* currentTransform = bridge->mDrawable->getXform();
expandExtents(addingExtents, *currentTransform);
}
}
}
}
}
void LLSpatialGroup::destroyGLState(bool keep_occlusion) void LLSpatialGroup::destroyGLState(bool keep_occlusion)
{ {
@ -1283,17 +1318,8 @@ void drawBox(const LLVector4a& c, const LLVector4a& r)
void drawBoxOutline(const LLVector3& pos, const LLVector3& size) void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
{ {
if (!pos.isFinite() || !size.isFinite())
llassert(pos.isFinite()); return;
llassert(size.isFinite());
llassert(!llisnan(pos.mV[0]));
llassert(!llisnan(pos.mV[1]));
llassert(!llisnan(pos.mV[2]));
llassert(!llisnan(size.mV[0]));
llassert(!llisnan(size.mV[1]));
llassert(!llisnan(size.mV[2]));
LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));

View File

@ -201,6 +201,7 @@ public:
LL_ALIGN_PREFIX(16) LL_ALIGN_PREFIX(16)
class LLSpatialGroup : public LLOcclusionCullingGroup class LLSpatialGroup : public LLOcclusionCullingGroup
{ {
using super = LLOcclusionCullingGroup;
friend class LLSpatialPartition; friend class LLSpatialPartition;
friend class LLOctreeStateCheck; friend class LLOctreeStateCheck;
public: public:
@ -333,6 +334,9 @@ public:
virtual void handleDestruction(const TreeNode* node); virtual void handleDestruction(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
// LLViewerOctreeGroup
virtual void rebound();
public: public:
LL_ALIGN_16(LLVector4a mViewAngle); LL_ALIGN_16(LLVector4a mViewAngle);
LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); LL_ALIGN_16(LLVector4a mLastUpdateViewAngle);

View File

@ -2480,6 +2480,34 @@ void login_callback(S32 option, void *userdata)
} }
} }
void release_notes_coro(const std::string url)
{
if (url.empty())
{
return;
}
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("releaseNotesCoro", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
httpOpts->setHeadersOnly(true); // only making sure it isn't 404 or something like that
LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (!status)
{
return;
}
LLWeb::loadURLInternal(url);
}
/** /**
* Check if user is running a new version of the viewer. * Check if user is running a new version of the viewer.
* Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting. * Display the Release Notes if it's not overriden by the "UpdaterShowReleaseNotes" setting.
@ -2512,7 +2540,8 @@ void show_release_notes_if_required()
LLEventPumps::instance().obtain("relnotes").listen( LLEventPumps::instance().obtain("relnotes").listen(
"showrelnotes", "showrelnotes",
[](const LLSD& url) { [](const LLSD& url) {
LLWeb::loadURLInternal(url.asString()); LLCoros::instance().launch("releaseNotesCoro",
boost::bind(&release_notes_coro, url.asString()));
return false; return false;
}); });
} }
@ -2520,7 +2549,9 @@ void show_release_notes_if_required()
#endif // LL_RELEASE_FOR_DOWNLOAD #endif // LL_RELEASE_FOR_DOWNLOAD
{ {
LLSD info(LLAppViewer::instance()->getViewerInfo()); LLSD info(LLAppViewer::instance()->getViewerInfo());
LLWeb::loadURLInternal(info["VIEWER_RELEASE_NOTES_URL"]); std::string url = info["VIEWER_RELEASE_NOTES_URL"].asString();
LLCoros::instance().launch("releaseNotesCoro",
boost::bind(&release_notes_coro, url));
} }
release_notes_shown = true; release_notes_shown = true;
} }

View File

@ -190,6 +190,13 @@ BOOL LLStatusBar::postBuild()
LLHints::getInstance()->registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle()); LLHints::getInstance()->registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle());
gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2)); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2));
gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&LLStatusBar::onVoiceChanged, this, _2));
if (!gSavedSettings.getBOOL("EnableVoiceChat") && LLAppViewer::instance()->isSecondInstance())
{
// Indicate that second instance started without sound
mBtnVolume->setImageUnselected(LLUI::getUIImage("VoiceMute_Off"));
}
// Adding Net Stat Graph // Adding Net Stat Graph
S32 x = getRect().getWidth() - 2; S32 x = getRect().getWidth() - 2;
@ -640,6 +647,16 @@ void LLStatusBar::onVolumeChanged(const LLSD& newvalue)
refresh(); refresh();
} }
void LLStatusBar::onVoiceChanged(const LLSD& newvalue)
{
if (newvalue.asBoolean())
{
// Second instance starts with "VoiceMute_Off" icon, fix it
mBtnVolume->setImageUnselected(LLUI::getUIImage("Audio_Off"));
}
refresh();
}
void LLStatusBar::onUpdateFilterTerm() void LLStatusBar::onUpdateFilterTerm()
{ {
LLWString searchValue = utf8str_to_wstring( mFilterEdit->getValue() ); LLWString searchValue = utf8str_to_wstring( mFilterEdit->getValue() );

Some files were not shown because too many files have changed in this diff Show More