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
# easily (analogous to looking up a codeticket build page)
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
generate_release_notes: true
# the only reason we generate a GH release is to post build products

View File

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

View File

@ -104,7 +104,6 @@ BOOL LLApp::sLogInSignal = FALSE;
// Keeps track of application status
LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
LLAppErrorHandler LLApp::sErrorHandler = NULL;
BOOL LLApp::sErrorThreadRunning = FALSE;
LLApp::LLApp()
@ -787,13 +786,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
return;
}
// Flag status to ERROR, so thread_error does its work.
// Flag status to ERROR
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)
{

View File

@ -291,7 +291,6 @@ protected:
static void setStatus(EAppStatus status); // Use this to change the 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.
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;
int abortfunc(int retcode)
{
LL_WARNS("APR") << "Allocation failure in apr pool with code " << (S32)retcode << LL_ENDL;
return 0;
}
void ll_init_apr()
{
// Initialize APR and create the global pool
@ -45,7 +51,7 @@ void ll_init_apr()
if (!gAPRPoolp)
{
apr_pool_create(&gAPRPoolp, NULL);
apr_pool_create_ex(&gAPRPoolp, NULL, abortfunc, NULL);
}
if(!LLAPRFile::sAPRFilePoolp)

View File

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

View File

@ -87,11 +87,10 @@ protected:
}
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;
}
(*this)[index] = entry;
}
};

View File

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

View File

@ -529,6 +529,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
// preserve existing semantics, we promise that mAttached defaults to the
// same setting as mAutokill.
mAttached(params.attached.isProvided()? params.attached : params.autokill),
mPool(NULL),
mPipes(NSLOTS)
{
// 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;
apr_pool_create(&mPool, gAPRPoolp);
if (!mPool)
{
LLTHROW(LLProcessError(STRINGIZE("failed to create apr pool")));
}
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
// 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
// string instead of the variable names.
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
gAPRPoolp)))
mPool)))
{
LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
}
// arrange to call status_callback()
apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
gAPRPoolp);
mPool);
// and make sure we poll it once per "mainloop" tick
sProcessListener.addPoll(*this);
mStatus.mState = RUNNING;
@ -815,6 +822,12 @@ LLProcess::~LLProcess()
{
kill("destructor");
}
if (mPool)
{
apr_pool_destroy(mPool);
mPool = NULL;
}
}
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
typedef boost::ptr_vector< boost::nullable<BasePipe> > PipeVector;
PipeVector mPipes;
apr_pool_t* mPool;
};
/// for logging

View File

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

View File

@ -51,24 +51,20 @@ protected:
public:
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
{
mRef++;
validateRefCount();
}
{
llassert(mRef != LL_REFCOUNT_FREE); // object is deleted
mRef++;
llassert(mRef < gMaxRefCount); // ref count excessive, likely memory leak
}
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)
{
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;
return 0;
}
@ -82,8 +78,8 @@ public:
return mRef;
}
private:
mutable S32 mRef;
private:
mutable S32 mRef;
};
@ -106,7 +102,7 @@ protected:
public:
LLThreadSafeRefCount();
LLThreadSafeRefCount(const LLThreadSafeRefCount&);
LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
{
mRef = 0;
return *this;
@ -114,8 +110,8 @@ public:
void ref()
{
mRef++;
}
mRef++;
}
void unref()
{
@ -136,36 +132,36 @@ public:
return currentVal;
}
private:
LLAtomicS32 mRef;
private:
LLAtomicS32 mRef;
};
/**
* intrusive pointer support for LLThreadSafeRefCount
* 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();
}
inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
{
p->unref();
p->unref();
}
/**
* intrusive pointer support
* 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();
}
inline void intrusive_ptr_release(LLRefCount* p)
inline void intrusive_ptr_release(LLRefCount* p)
{
p->unref();
p->unref();
}
#endif

View File

@ -1235,9 +1235,17 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
}
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.
// If not utc or user local time, fallback to Pacific time
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;
}

View File

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

View File

@ -193,61 +193,6 @@ void add(CountStatHandle<T>& count, VALUE_T value)
#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
// specialize to cover different types
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

View File

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

View File

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

View File

@ -1,24 +1,24 @@
/**
/**
* @file lltracesampler.cpp
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2012, Linden Research, Inc.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@ -32,7 +32,7 @@
#include "lltracethreadrecorder.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);
}
@ -40,34 +40,29 @@ inline F64 lerp(F64 a, F64 b, F64 u)
namespace LLTrace
{
extern MemStatHandle gTraceMemStat;
///////////////////////////////////////////////////////////////////////
// Recording
///////////////////////////////////////////////////////////////////////
Recording::Recording(EPlayState state)
Recording::Recording(EPlayState state)
: mElapsedSeconds(0),
mActiveBuffers(NULL)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
claim_alloc(gTraceMemStat, this);
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mBuffers = new AccumulatorBufferGroup();
claim_alloc(gTraceMemStat, mBuffers);
setPlayState(state);
}
Recording::Recording( const Recording& other )
: mActiveBuffers(NULL)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
claim_alloc(gTraceMemStat, this);
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
*this = 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
setPlayState(PAUSED);
@ -85,14 +80,11 @@ Recording& Recording::operator = (const Recording& other)
return *this;
}
Recording::~Recording()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
disclaim_alloc(gTraceMemStat, this);
disclaim_alloc(gTraceMemStat, mBuffers);
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
// 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
// besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
if (isStarted() && LLTrace::get_thread_recorder() != NULL)
@ -107,14 +99,14 @@ void Recording::update()
#if LL_TRACE_ENABLED
if (isStarted())
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
// must have
llassert(mActiveBuffers != NULL
// must have
llassert(mActiveBuffers != 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();
LLTrace::get_thread_recorder()->deactivate(buffers);
@ -128,7 +120,7 @@ void Recording::update()
void Recording::handleReset()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
mBuffers.write()->reset();
@ -139,7 +131,7 @@ void Recording::handleReset()
void Recording::handleStart()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
mSamplingTimer.reset();
mBuffers.setStayUnique(true);
@ -151,7 +143,7 @@ void Recording::handleStart()
void Recording::handleStop()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
#if LL_TRACE_ENABLED
mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
// 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());
}
S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
{
update();
@ -219,7 +210,7 @@ F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
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()));
}
@ -241,144 +232,9 @@ F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& s
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)
{
update();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
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)
{
update();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
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 )
{
update();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
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 )
{
update();
update();
const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
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)
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
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 )
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
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 )
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
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 )
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
F32 t = 0.0f;
S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
if (div > 0)
{
t = active_accumulator->getSampleCount() / div;
}
F32 t = 0.0f;
S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
if (div > 0)
{
t = active_accumulator->getSampleCount() / div;
}
return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
}
else
@ -456,7 +312,7 @@ F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
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 )
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
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 )
{
update();
update();
const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
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)
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
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)
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
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 )
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
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 )
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
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 )
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
if (active_accumulator && active_accumulator->hasValue())
{
F32 t = 0.0f;
S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
if (div > 0)
{
t = active_accumulator->getSampleCount() / div;
}
S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount();
if (div > 0)
{
t = active_accumulator->getSampleCount() / div;
}
return lerp(accumulator.getMean(), active_accumulator->getMean(), t);
}
else
@ -542,7 +398,7 @@ F64 Recording::getMean( const StatType<EventAccumulator>& stat )
F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
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 )
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
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 )
{
update();
update();
const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
@ -577,7 +433,7 @@ S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
// PeriodicRecording
///////////////////////////////////////////////////////////////////////
PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
: mAutoResize(num_periods == 0),
mCurPeriod(0),
mNumRecordedPeriods(0),
@ -585,15 +441,13 @@ PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
// code in several methods.
mRecordingPeriods(num_periods ? num_periods : 1)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
setPlayState(state);
claim_alloc(gTraceMemStat, this);
}
PeriodicRecording::~PeriodicRecording()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
disclaim_alloc(gTraceMemStat, this);
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
}
void PeriodicRecording::nextPeriod()
@ -615,12 +469,11 @@ void PeriodicRecording::nextPeriod()
void PeriodicRecording::appendRecording(Recording& recording)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().appendRecording(recording);
nextPeriod();
}
void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
@ -693,16 +546,14 @@ F64Seconds PeriodicRecording::getDuration() const
return duration;
}
LLTrace::Recording PeriodicRecording::snapshotCurRecording() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
Recording recording_copy(getCurRecording());
recording_copy.stop();
return recording_copy;
}
Recording& PeriodicRecording::getLastRecording()
{
return getPrevRecording(1);
@ -737,19 +588,19 @@ const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const
void PeriodicRecording::handleStart()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().start();
}
void PeriodicRecording::handleStop()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().pause();
}
void PeriodicRecording::handleReset()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().stop();
if (mAutoResize)
@ -771,13 +622,13 @@ void PeriodicRecording::handleReset()
void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
getCurRecording().splitTo(other.getCurRecording());
}
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());
bool has_value = false;
@ -792,14 +643,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, siz
}
}
return has_value
? min_val
return has_value
? min_val
: NaN;
}
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());
bool has_value = false;
@ -814,15 +665,15 @@ F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, siz
}
}
return has_value
? max_val
return has_value
? max_val
: NaN;
}
// calculates means using aggregates per period
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());
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
: NaN;
}
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());
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()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
bool has_value = false;
@ -885,14 +736,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, si
}
}
return has_value
? min_val
return has_value
? min_val
: NaN;
}
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());
bool has_value = false;
@ -907,15 +758,15 @@ F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, siz
}
}
return has_value
? max_val
return has_value
? max_val
: NaN;
}
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());
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()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
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()*/ )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
num_periods = llmin(num_periods, getNumRecordedPeriods());
F64 period_mean = getPeriodMean(stat, num_periods);
@ -987,105 +838,13 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
: 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
///////////////////////////////////////////////////////////////////////
void ExtendableRecording::extend()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
// push the data back to accepted recording
mAcceptedRecording.appendRecording(mPotentialRecording);
// flush data, so we can start from scratch
@ -1094,76 +853,72 @@ void ExtendableRecording::extend()
void ExtendableRecording::handleStart()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.start();
}
void ExtendableRecording::handleStop()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.pause();
}
void ExtendableRecording::handleReset()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mAcceptedRecording.reset();
mPotentialRecording.reset();
}
void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.splitTo(other.mPotentialRecording);
}
///////////////////////////////////////////////////////////////////////
// ExtendablePeriodicRecording
///////////////////////////////////////////////////////////////////////
ExtendablePeriodicRecording::ExtendablePeriodicRecording()
: mAcceptedRecording(0),
ExtendablePeriodicRecording::ExtendablePeriodicRecording()
: mAcceptedRecording(0),
mPotentialRecording(0)
{}
void ExtendablePeriodicRecording::extend()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
// push the data back to accepted recording
mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
// flush data, so we can start from scratch
mPotentialRecording.reset();
}
void ExtendablePeriodicRecording::handleStart()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.start();
}
void ExtendablePeriodicRecording::handleStop()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.pause();
}
void ExtendablePeriodicRecording::handleReset()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mAcceptedRecording.reset();
mPotentialRecording.reset();
}
void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
mPotentialRecording.splitTo(other.mPotentialRecording);
}
PeriodicRecording& get_frame_recording()
{
static thread_local PeriodicRecording sRecording(200, PeriodicRecording::STARTED);
@ -1174,7 +929,7 @@ PeriodicRecording& get_frame_recording()
void LLStopWatchControlsMixinCommon::start()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState)
{
case STOPPED:
@ -1196,7 +951,7 @@ void LLStopWatchControlsMixinCommon::start()
void LLStopWatchControlsMixinCommon::stop()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState)
{
case STOPPED:
@ -1216,7 +971,7 @@ void LLStopWatchControlsMixinCommon::stop()
void LLStopWatchControlsMixinCommon::pause()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState)
{
case STOPPED:
@ -1236,7 +991,7 @@ void LLStopWatchControlsMixinCommon::pause()
void LLStopWatchControlsMixinCommon::unpause()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState)
{
case STOPPED:
@ -1256,7 +1011,7 @@ void LLStopWatchControlsMixinCommon::unpause()
void LLStopWatchControlsMixinCommon::resume()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState)
{
case STOPPED:
@ -1277,7 +1032,7 @@ void LLStopWatchControlsMixinCommon::resume()
void LLStopWatchControlsMixinCommon::restart()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch (mPlayState)
{
case STOPPED:
@ -1301,13 +1056,13 @@ void LLStopWatchControlsMixinCommon::restart()
void LLStopWatchControlsMixinCommon::reset()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
handleReset();
}
void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
switch(state)
{
case STOPPED:

View File

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

View File

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

View File

@ -46,11 +46,12 @@ namespace tut
// the real time required for each push() call. Explicitly increment
// the timestamp for each one -- but since we're passing explicit
// 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
// exactly: conversions are ambiguous.
queue.push("abc"s);
queue.push(Queue::Clock::now() + 100ms, "def");
queue.push(now + 100ms, "def");
queue.close();
auto entry = queue.pop();
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)
{
mWarning = "texture_load_empty_file";
setLastError("File is empty",src_filename);
return false;
}
@ -90,6 +91,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp()
if (signature[0] != 'B' || signature[1] != 'M')
{
LL_WARNS() << "Not a BMP" << LL_ENDL;
mWarning = "texture_load_format_error";
return false;
}
@ -140,6 +142,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng()
if (memcmp(signature, png_magic, PNG_MAGIC_SIZE) != 0)
{
LL_WARNS() << "Not a PNG" << LL_ENDL;
mWarning = "texture_load_format_error";
return false;
}
@ -183,6 +186,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0)
{
LL_WARNS() << "Not a JPEG" << LL_ENDL;
mWarning = "texture_load_format_error";
return false;
}
fseek(fp, 0, SEEK_SET); // go back to start of the file

View File

@ -55,6 +55,12 @@ public:
{
return mLastError;
}
const std::string& getWarningName()
{
return mWarning;
}
protected:
void clean()
@ -129,6 +135,7 @@ protected:
std::string mSrcFilename;
std::string mLastError;
std::string mWarning;
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 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 )
{
@ -1067,11 +1072,16 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
const F32 epsilon = 1e-5f;
weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
weight_map::iterator iter_down = iter_up;
if (iter_up != mSkinWeights.end())
{
iter_down = ++iter_up;
}
weight_map::iterator best = iter_up;
weight_map::iterator best = iter_up;
if (iter_up != mSkinWeights.end())
{
iter_down = ++iter_up;
}
else
{
// Assumes that there is at least one element
--best;
}
F32 min_dist = (iter->first - pos).magVec();

View File

@ -126,12 +126,12 @@ public:
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 canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;};
void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close; };
bool canOpenClose() const { return mCanOpenClose; };
virtual BOOL postBuild();
@ -142,8 +142,8 @@ public:
void draw();
void storeOpenCloseState ();
void restoreOpenCloseState ();
void storeOpenCloseState();
void restoreOpenCloseState();
protected:
LLAccordionCtrlTab(const LLAccordionCtrlTab::Params&);

View File

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

View File

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

View File

@ -1361,26 +1361,28 @@ void LLFlatListViewEx::setForceShowingUnmatchedItems(bool 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))
{
mFilterSubString = filter_str;
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,
// i.e. we don't hide items that don't support 'match_filter' action, separators etc.
if (0 == item->notify(action))
{
mHasMatchedItems = true;
item->setVisible(true);
}
else
{
@ -1388,34 +1390,45 @@ void LLFlatListViewEx::updateItemVisibility(LLPanel* item, const LLSD &action)
if (!mForceShowingUnmatchedItems)
{
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;
LLStringUtil::toUpper(cur_filter);
LLSD action;
action.with("match_filter", cur_filter);
item_panel_list_t items;
getItems(items);
mHasMatchedItems = false;
item_panel_list_t::iterator iter = items.begin(), iter_end = items.end();
while (iter < iter_end)
bool visibility_changed = false;
pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end();
while (iter != iter_end)
{
LLPanel* pItem = *(iter++);
updateItemVisibility(pItem, action);
LLPanel* pItem = (*(iter++))->first;
visibility_changed |= updateItemVisibility(pItem, action);
}
sort();
notifyParentItemsRectChanged();
if (re_sort)
{
sort();
}
if (visibility_changed && notify_parent)
{
notifyParentItemsRectChanged();
}
}
bool LLFlatListViewEx::hasMatchedItems()

View File

@ -300,6 +300,7 @@ public:
virtual S32 notify(const LLSD& info) ;
virtual ~LLFlatListView();
protected:
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
@ -375,7 +376,9 @@ protected:
LLRect getLastSelectedItemRect();
void ensureSelectedVisible();
void ensureSelectedVisible();
const pairs_list_t& getItemPairs() { return mItemPairs; }
private:
@ -482,14 +485,14 @@ public:
/**
* 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; }
/**
* Filters the list, rearranges and notifies parent about shape changes.
* 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
@ -513,7 +516,7 @@ protected:
* @param item - item we are changing
* @param item - action - parameters to determin visibility from
*/
void updateItemVisibility(LLPanel* item, const LLSD &action);
bool updateItemVisibility(LLPanel* item, const LLSD &action);
private:
std::string mNoFilteredItemsMsg;

View File

@ -187,14 +187,18 @@ LLFolderViewItem::~LLFolderViewItem()
BOOL LLFolderViewItem::postBuild()
{
LLFolderViewModelItem& vmi = *getViewModelItem();
// 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());
LLFolderViewModelItem* vmi = getViewModelItem();
llassert(vmi); // not supposed to happen, if happens, find out why and fix
if (vmi)
{
// 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)
vmi.dirtyFilter();
// Dirty the filter flag of the model from the view (CHUI-849)
vmi->dirtyFilter();
}
// Don't do full refresh on constructor if it is possible to avoid
// 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
// 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);
seg_list->clear();
@ -491,7 +491,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
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* cur = base;
@ -501,9 +501,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
{
if( *cur == '\n' )
{
LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(cur-base);
LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, cur-base);
text_segment->setToken( 0 );
insertSegment( *seg_list, text_segment, text_len, defaultColor, editor);
insertSegment( *seg_list, text_segment, text_len, style, editor);
cur++;
if( !*cur || *cur == '\n' )
{
@ -541,7 +541,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
S32 seg_end = cur - base;
//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.
break;
}
@ -648,7 +648,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW
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 );
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;
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;
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);
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)
{
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 );
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 );
insertSegment( seg_list, text_segment, text_len, defaultColor, editor);
insertSegment( seg_list, text_segment, text_len, style, editor);
seg_start = pos+1;
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 );
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 )
@ -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
void LLKeywords::dump()
{

View File

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

View File

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

View File

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

View File

@ -181,7 +181,7 @@ LLStatBar::LLStatBar(const Params& p)
mTargetMinBar(llmin(p.bar_min, p.bar_max)),
mTargetMaxBar(llmax(p.bar_max, p.bar_min)),
mCurMaxBar(p.bar_max),
mCurMinBar(0),
mCurMinBar(0),
mDecimalDigits(p.decimal_digits),
mNumHistoryFrames(p.num_frames),
mNumShortHistoryFrames(p.num_frames_short),
@ -222,9 +222,6 @@ BOOL LLStatBar::handleHover(S32 x, S32 y, MASK mask)
case STAT_SAMPLE:
LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.sampleStatp->getDescription()).sticky_rect(calcScreenRect()));
break;
case STAT_MEM:
LLToolTipMgr::instance().show(LLToolTip::Params().message(mStat.memStatp->getDescription()).sticky_rect(calcScreenRect()));
break;
default:
break;
}
@ -373,18 +370,6 @@ void LLStatBar::draw()
}
}
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:
break;
}
@ -500,11 +485,6 @@ void LLStatBar::draw()
max_value = recording.getMax(*mStat.sampleStatp);
num_samples = recording.getSampleCount(*mStat.sampleStatp);
break;
case STAT_MEM:
min_value = recording.getMin(*mStat.memStatp).value();
max_value = recording.getMax(*mStat.memStatp).value();
num_samples = 1;
break;
default:
break;
}
@ -583,14 +563,8 @@ void LLStatBar::setStat(const std::string& stat_name)
mStat.sampleStatp = sample_stat.get();
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)
{
mTargetMinBar = llmin(bar_min, bar_max);

View File

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

View File

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

View File

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

View File

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

View File

@ -1550,7 +1550,13 @@ S32 LLTextBase::getLeftOffset(S32 width)
case LLFontGL::HCENTER:
return mHPad + llmax(0, (mVisibleTextRect.getWidth() - width - mHPad) / 2);
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:
return mHPad;
}
@ -3431,7 +3437,7 @@ BOOL LLNormalTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
if (mToken && !mToken->getToolTip().empty())
{
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;
}
// 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
{
if (mEnableTooltipPaste &&
LLToolTipMgr::instance().toolTipVisible() &&
LLToolTipMgr::instance().toolTipVisible() &&
LLToolTipMgr::instance().isTooltipPastable() &&
KEY_TAB == key)
{ // Paste the first line of a tooltip into the editor
std::string message;

View File

@ -154,7 +154,8 @@ LLToolTip::Params::Params()
text_color("text_color"),
time_based_media("time_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);
}
@ -167,7 +168,8 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
mTextBox(NULL),
mInfoButton(NULL),
mPlayMediaButton(NULL),
mHomePageButton(NULL)
mHomePageButton(NULL),
mIsTooltipPastable(p.allow_paste_tooltip)
{
LLTextBox::Params params;
params.name = params.initial_value().asString();
@ -289,6 +291,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)
mTextBox->setText(p.message());
}
mIsTooltipPastable = p.allow_paste_tooltip;
updateTextBox();
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)
@ -626,5 +630,13 @@ void LLToolTipMgr::getToolTipMessage(std::string & message)
}
}
bool LLToolTipMgr::isTooltipPastable()
{
if (toolTipVisible())
{
return mToolTip->isTooltipPastable();
}
return false;
}
// EOF

View File

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

View File

@ -5420,6 +5420,17 @@
<key>Value</key>
<string>http://wiki.secondlife.com/wiki/[LSL_STRING]</string>
</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>
<map>
<key>Comment</key>
@ -7496,10 +7507,21 @@
<key>Value</key>
<integer>1</integer>
</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>
<map>
<key>Comment</key>
<string>Expand advanced performance stats display</string>
<string>Expand Advanced performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -7507,43 +7529,10 @@
<key>Value</key>
<integer>0</integer>
</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>
<map>
<key>Comment</key>
<string>Expand render 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>
<string>Expand Render performance stats display</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -7562,6 +7551,39 @@
<key>Value</key>
<integer>0</integer>
</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>
<map>
<key>Comment</key>
@ -7573,6 +7595,17 @@
<key>Value</key>
<integer>0</integer>
</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>
<map>
<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;
static bool isDisableCameraConstraints()
{
static LLCachedControl<bool> sDisableCameraConstraints(gSavedSettings, "DisableCameraConstraints", false);
return sDisableCameraConstraints;
}
// The agent instance.
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)
if (!mFocusObject || mFocusObject->isDead() ||
if (!mFocusObject || mFocusObject->isDead() ||
mFocusObject->isMesh() ||
gSavedSettings.getBOOL("DisableCameraConstraints"))
isDisableCameraConstraints())
{
obj_min_distance = 0.f;
return TRUE;
@ -742,39 +748,44 @@ F32 LLAgentCamera::getCameraZoomFraction(bool get_third_person)
// already [0,1]
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);
}
else if (cameraCustomizeAvatar())
if (cameraCustomizeAvatar())
{
F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
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();
if (mFocusObject.notNull())
F32 min_zoom;
F32 max_zoom = getCameraMaxZoomDistance();
F32 distance = (F32)mCameraFocusOffsetTarget.magVec();
if (mFocusObject.notNull())
{
if (mFocusObject->isAvatar())
{
if (mFocusObject->isAvatar())
{
min_zoom = AVATAR_MIN_ZOOM;
}
else
{
min_zoom = OBJECT_MIN_ZOOM;
}
min_zoom = AVATAR_MIN_ZOOM;
}
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)
@ -787,6 +798,10 @@ void LLAgentCamera::setCameraZoomFraction(F32 fraction)
{
mHUDTargetZoom = fraction;
}
else if (isDisableCameraConstraints())
{
mCameraZoomFraction = fraction;
}
else if (mFocusOnAvatar && cameraThirdPerson())
{
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();
mCameraFocusOffsetTarget = camera_offset_dir * rescale(fraction, 0.f, 1.f, max_zoom, min_zoom);
}
startCameraAnimation();
}
@ -925,51 +941,42 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction)
return;
}
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 min_zoom = LAND_MIN_ZOOM;
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 current_distance = (F32)camera_offset_unit.normalize();
F32 new_distance = current_distance * fraction;
// Don't move through focus point
if (mFocusObject)
// Unless camera is unlocked
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;
}
@ -990,53 +997,52 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters)
changeCameraToMouselook(FALSE);
}
mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION);
if (!isDisableCameraConstraints())
{
mCameraZoomFraction = llclamp(mCameraZoomFraction, MIN_ZOOM_FRACTION, MAX_ZOOM_FRACTION);
}
}
else
{
LLVector3d camera_offset_unit(mCameraFocusOffsetTarget);
F32 current_distance = (F32)camera_offset_unit.normalize();
F32 new_distance = current_distance - meters;
F32 min_zoom = LAND_MIN_ZOOM;
// Don't move through focus point
if (mFocusObject.notNull())
// Unless camera is unlocked
if (!isDisableCameraConstraints())
{
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
mCameraFocusOffsetTarget = new_distance * camera_offset_unit;
cameraZoomIn(1.f);
}
}
//-----------------------------------------------------------------------------
// cameraPanIn()
//-----------------------------------------------------------------------------
@ -1841,7 +1847,8 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
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;
plane_normal.setVec(mCameraCollidePlane.mV);
@ -1960,7 +1967,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
camera_position_global = focusPosGlobal + mCameraFocusOffset;
}
if (!gSavedSettings.getBOOL("DisableCameraConstraints") && !gAgent.isGodlike())
if (!isDisableCameraConstraints() && !gAgent.isGodlike())
{
LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global);
bool constrain = true;
@ -2131,17 +2138,13 @@ F32 LLAgentCamera::getCameraMinOffGround()
{
return 0.f;
}
else
if (isDisableCameraConstraints())
{
if (gSavedSettings.getBOOL("DisableCameraConstraints"))
{
return -1000.f;
}
else
{
return 0.5f;
}
return -1000.f;
}
return 0.5f;
}

View File

@ -2943,13 +2943,14 @@ bool LLAppViewer::initConfiguration()
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.
LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice");
if(disable_voice)
// Also see LLVivoxVoiceClient::voiceEnabled()
LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat");
if(enable_voice)
{
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()
{
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)
{
;
if (timer_expiry.hasExpired())
{
LL_INFOS() << "Infinite loop time : " << timer_total.getElapsedSeconds() << LL_ENDL;
timer_expiry.setTimerExpirySec(report_frequency);
}
}
return;
}

View File

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

View File

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

View File

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

View File

@ -760,19 +760,6 @@ void LLDrawable::movePartition()
if (part)
{
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)
{
LLFavoritesBarCtrl::sWaitingForCallabck = 0.f;
LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField);
item->setComplete(TRUE);
@ -365,6 +366,9 @@ struct LLFavoritesSort
}
};
F64 LLFavoritesBarCtrl::sWaitingForCallabck = 0.f;
LLFavoritesBarCtrl::Params::Params()
: image_drag_indication("image_drag_indication"),
more_button("more_button"),
@ -381,7 +385,7 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mShowDragMarker(FALSE),
mLandingTab(NULL),
mLastTab(NULL),
mTabsHighlightEnabled(TRUE),
mItemsListDirty(false),
mUpdateDropDownItems(true),
mRestoreOverflowMenu(false),
mGetPrevItems(true),
@ -618,6 +622,9 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
int sortField = 0;
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
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());
}
updateButtons();
if (!mItemsChangedTimer.getStarted())
{
mItemsChangedTimer.start();
}
else
{
mItemsChangedTimer.reset();
}
if (sWaitingForCallabck < LLTimer::getTotalSeconds())
{
updateButtons();
if (!mItemsChangedTimer.getStarted())
{
mItemsChangedTimer.start();
}
else
{
mItemsChangedTimer.reset();
}
}
else
{
mItemsListDirty = true;
}
}
}
@ -754,6 +767,18 @@ void LLFavoritesBarCtrl::draw()
mItemsChangedTimer.start();
}
if (mItemsListDirty && sWaitingForCallabck < LLTimer::getTotalSeconds())
{
updateButtons();
if (!mItemsChangedTimer.getStarted())
{
mItemsChangedTimer.start();
}
else
{
mItemsChangedTimer.reset();
}
}
}
const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()
@ -782,6 +807,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update)
return;
}
mItemsListDirty = false;
mItems.clear();
if (!collectFavoriteItems(mItems))

View File

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

View File

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

View File

@ -113,6 +113,7 @@
#include "llpresetsmanager.h"
#include "llviewercontrol.h"
#include "llpresetsmanager.h"
#include "llinventoryfunctions.h"
#include "llsearchableui.h"
#include "llperfstats.h"
@ -1590,25 +1591,6 @@ void LLFloaterPreference::onChangeMaturity()
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)
{
LLUUID cat_id = gInventory.findUserDefinedCategoryUUIDForType(cat_type);

View File

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

View File

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

View File

@ -897,6 +897,15 @@ void LLHUDNameTag::shift(const LLVector3& 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
void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)
{

View File

@ -127,11 +127,12 @@ public:
/*virtual*/ void markDead();
friend class LLHUDObject;
/*virtual*/ F32 getDistance() const { return mLastDistance; }
S32 getLOD() { return mLOD; }
BOOL getVisible() { return mVisible; }
S32 getLOD() const { return mLOD; }
BOOL getVisible() const { return mVisible; }
BOOL getHidden() const { return mHidden; }
void setHidden( BOOL hide ) { mHidden = hide; }
void shift(const LLVector3& offset);
F32 getWorldHeight() const;
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)
{
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE);
LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true);
return;
}
else if ("cut" == action)
@ -3409,7 +3409,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
}
else if ("show_in_main_panel" == action)
{
LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, mUUID, TRUE);
LLInventoryPanel::openInventoryPanelAndSetSelection(true, mUUID, true);
return;
}
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);
}
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.
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);
bool is_only_cats_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_landmarks(LLInventoryItem* inv_item);

View File

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

View File

@ -51,20 +51,20 @@ public:
/**
* 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
* not currently visible.
*/
void setForceRefresh(bool force_refresh){ mForceRefresh = force_refresh; }
void setForceRefresh(bool force_refresh) { mForceRefresh = force_refresh; }
/**
* If refreshes when invisible.
*/
bool getForceRefresh(){ return mForceRefresh; }
bool getForceRefresh() { return mForceRefresh; }
virtual bool selectItemByValue(const LLSD& value, bool select = true);

View File

@ -1887,46 +1887,52 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open)
}
//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");
sidepanel_inventory->showInventoryPanel();
bool in_inbox = (gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX)));
if (!in_inbox && (use_main_panel || !sidepanel_inventory->getMainInventoryPanel()->isRecentItemsPanelSelected()))
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->selectAllItemsPanel();
}
LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater();
if(!auto_open && inventory_floater && inventory_floater->getVisible())
if (!auto_open)
{
LLSidepanelInventory *inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel");
LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel();
if(main_panel->isSingleFolderMode() && main_panel->isGalleryViewMode())
LLFloater* inventory_floater = LLFloaterSidePanelContainer::getTopmostInventoryFloater();
if (inventory_floater && inventory_floater->getVisible())
{
LL_DEBUGS("Inventory") << "Opening gallery panel for item" << obj_id << LL_ENDL;
main_panel->setGallerySelection(obj_id);
return;
LLSidepanelInventory *inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel");
LLPanelMainInventory* main_panel = inventory_panel->getMainInventoryPanel();
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 (main_inventory && main_inventory->isSingleFolderMode()
&& use_main_panel)
if (use_main_panel)
{
const LLInventoryObject *obj = gInventory.getObject(obj_id);
if (obj)
LLPanelMainInventory* main_inventory = sidepanel_inventory->getMainInventoryPanel();
if (main_inventory && main_inventory->isSingleFolderMode())
{
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;
const LLInventoryObject *obj = gInventory.getObject(obj_id);
if (obj)
{
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);
if (active_panel)
{
LL_DEBUGS("Messaging", "Inventory") << "Highlighting" << obj_id << LL_ENDL;
@ -1938,11 +1944,8 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
if (in_inbox)
{
LLInventoryPanel * inventory_panel = NULL;
sidepanel_inventory->openInbox();
inventory_panel = sidepanel_inventory->getInboxPanel();
LLInventoryPanel* inventory_panel = sidepanel_inventory->getInboxPanel();
if (inventory_panel)
{
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)
{
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)
{

View File

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

View File

@ -1081,6 +1081,13 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename)
LLImageDimensionsInfo image_info;
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;
}
@ -1096,6 +1103,7 @@ bool LLLocalBitmapMgr::checkTextureDimensions(std::string filename)
LLSD notif_args;
notif_args["REASON"] = mImageLoadError;
notif_args["NAME"] = gDirUtilp->getBaseFileName(filename);
LLNotificationsUtil::add("CannotUploadTexture", notif_args);
return false;

View File

@ -5503,7 +5503,7 @@ void on_new_single_inventory_upload_complete(
}
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

View File

@ -249,7 +249,7 @@ void LLModelPreview::updateDimentionsAndOffsets()
{
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)
{
if (instance.mLOD[j])
@ -271,6 +271,7 @@ void LLModelPreview::rebuildUploadData()
{
assert_main_thread();
mDefaultPhysicsShapeP = NULL;
mUploadData.clear();
mTextureSet.clear();
@ -310,7 +311,7 @@ void LLModelPreview::rebuildUploadData()
mat *= scale_mat;
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++;
LLModel* base_model = instance.mModel;
@ -573,7 +574,7 @@ void LLModelPreview::rebuildUploadData()
else if (getLoadState() == LLModelLoader::ERROR_MATERIALS
|| 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()
// updateStatusMessages() is called after rebuildUploadData()
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
// 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)
mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty();
}
@ -884,12 +885,13 @@ void LLModelPreview::clearIncompatible(S32 lod)
// Check if already started
bool subscribe_for_generation = mLodsQuery.empty();
// Remove previously scheduled work
mLodsQuery.clear();
LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
if (!fmp) return;
if (!fmp)
return;
// Schedule new work
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(shadow_indices);
if (size_new_indices < 3)
{
// 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);
}
if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
{
// 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)
{
{
std::vector<LLOutfitGalleryItem*> buf_items = mItems;
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();
mItemsInRow+= row_diff;
mItemsInRow += row_diff;
updateGalleryWidth();
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)
{
(*it)->setHidden(false);
applyFilter(*it,sFilterSubString);
std::string outfit_name = (*it)->getItemName();
LLStringUtil::toUpper(outfit_name);
bool hidden = (std::string::npos == outfit_name.find(cur_filter));
(*it)->setHidden(hidden);
addToGallery(*it);
}
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();
}
@ -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)
{
}
@ -904,11 +897,11 @@ bool LLOutfitGallery::hasDefaultImage(const LLUUID& outfit_cat_id)
void LLOutfitGallery::updateMessageVisibility()
{
if(mItems.empty())
if (mItems.empty())
{
mMessageTextBox->setVisible(TRUE);
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);
}
else

View File

@ -90,7 +90,7 @@ public:
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 updateAddedCategory(LLUUID cat_id);
@ -117,8 +117,6 @@ protected:
/*virtual*/ void onExpandAllFolders() {}
/*virtual*/ LLOutfitListGearMenuBase* createGearMenu();
void applyFilter(LLOutfitGalleryItem* item, const std::string& filter_substring);
private:
LLUUID getPhotoAssetId(const LLUUID& outfit_id);
LLUUID getDefaultPhoto();

View File

@ -188,7 +188,7 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1));
// 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));
@ -199,19 +199,17 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
// Further list updates will be triggered by the category observer.
list->updateList(cat_id);
// If filter is currently applied we store the initial tab state and
// open it to show matched items if any.
if (!sFilterSubString.empty())
// If filter is currently applied we store the initial tab state.
if (!getFilterSubString().empty())
{
tab->notifyChildren(LLSD().with("action", "store_state"));
tab->setDisplayChildren(true);
// Setting mForceRefresh flag will make the list refresh its contents
// even if it is not currently visible. This is required to apply the
// filter to the newly added list.
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
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;
for (outfits_map_t::iterator
@ -510,57 +500,50 @@ void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl)
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
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
iter = mOutfitsMap.begin(),
iter_end = mOutfitsMap.end();
iter != iter_end; ++iter)
outfits_map_t::iterator iter = mOutfitsMap.begin(), iter_end = mOutfitsMap.end();
while (iter != iter_end)
{
LLAccordionCtrlTab* tab = iter->second;
const LLUUID& category_id = iter->first;
LLAccordionCtrlTab* tab = iter++->second;
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());
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
tab->notifyChildren(LLSD().with("action","store_state"));
// Store accordion tab state when filter is not empty
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
{
// restore tab title when filter is empty
tab->setVisible(TRUE);
// Restore tab title when filter is empty
tab->setTitle(tab->getTitle());
//restore accordion state after all those accodrion tab manipulations
tab->notifyChildren(LLSD().with("action","restore_state"));
// Restore accordion state after all those accodrion tab manipulations
tab->notifyChildren(LLSD().with("action", "restore_state"));
// 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))
{
// hide tab if its title doesn't pass filter
// and it has no visible items
// Hide tab if its title doesn't pass filter
// and it has no matched items
tab->setVisible(list->hasMatchedItems());
// remove title highlighting because it might
// Remove title highlighting because it might
// have been previously highlighted by less restrictive filter
tab->setTitle(tab->getTitle());
@ -602,18 +585,6 @@ void LLOutfitsList::applyFilterToTab(
// Try restoring the tab selection.
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()
@ -698,11 +669,10 @@ void LLOutfitsList::onCOFChanged()
// 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
// items lists and update their worn state there.
for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin();
iter != item_array.end();
++iter)
LLInventoryModel::item_array_t::const_iterator array_iter = item_array.begin(), array_end = item_array.end();
while (array_iter < array_end)
{
vnew.push_back((*iter)->getLinkedUUID());
vnew.push_back((*(array_iter++))->getLinkedUUID());
}
// 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.
mCOFLinkedItems = vnew;
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
++iter)
// 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());
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;
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
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
// the links that point to these items.
list->updateChangedItems(vadded);
@ -835,7 +805,6 @@ void LLOutfitListBase::onOpen(const LLSD& info)
// arrive.
category->fetch();
refreshList(outfits);
highlightBaseOutfit();
mIsInitialized = true;
}
@ -843,6 +812,9 @@ void LLOutfitListBase::onOpen(const LLSD& info)
void LLOutfitListBase::refreshList(const LLUUID& category_id)
{
bool wasNull = mRefreshListState.CategoryUUID.isNull();
mRefreshListState.CategoryUUID.setNull();
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
@ -855,27 +827,81 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
LLInventoryModel::EXCLUDE_TRASH,
is_category);
uuid_vec_t vadded;
uuid_vec_t vremoved;
// Memorize item names for each UUID
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.
computeDifference(cat_array, vadded, vremoved);
// Fill added and removed items vectors.
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.
for (uuid_vec_t::const_iterator iter = vadded.begin();
iter != vadded.end();
++iter)
while (mRefreshListState.AddedIterator < mRefreshListState.Added.end())
{
const LLUUID cat_id = (*iter);
const LLUUID cat_id = (*mRefreshListState.AddedIterator++);
updateAddedCategory(cat_id);
curent_time = LLTimer::getTotalSeconds();
if (curent_time >= end_time)
return;
}
mRefreshListState.Added.clear();
mRefreshListState.AddedIterator = mRefreshListState.Added.end();
// 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);
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
// which might have been renamed.
@ -888,9 +914,9 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
if (!cat)
{
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;
}
@ -900,6 +926,12 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
}
sortOutfits();
highlightBaseOutfit();
gIdleCallbacks.deleteFunction(onIdle, this);
mRefreshListState.CategoryUUID.setNull();
LL_INFOS() << "done" << LL_ENDL;
}
void LLOutfitListBase::computeDifference(
@ -936,7 +968,6 @@ void LLOutfitListBase::highlightBaseOutfit()
mHighlightedOutfitUUID = base_id;
onHighlightBaseOutfit(base_id, prev_id);
}
}
void LLOutfitListBase::removeSelected()

View File

@ -116,8 +116,20 @@ protected:
void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response);
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;
LLInventoryCategoriesObserver* mCategoriesObserver;
LLInventoryCategoriesObserver* mCategoriesObserver;
LLUUID mSelectedOutfitUUID;
// id of currently highlited outfit
LLUUID mHighlightedOutfitUUID;
@ -225,7 +237,7 @@ public:
//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;
@ -295,12 +307,7 @@ private:
* 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.
*/
void onFilteredWearableItemsListRefresh(LLUICtrl* ctrl);
/**
* Highlights filtered items and hides tabs which haven't passed filter.
*/
void applyFilter(const std::string& new_filter_substring);
void onRefreshComplete(LLUICtrl* ctrl);
/**
* Applies filter to the given tab

View File

@ -28,12 +28,35 @@
#include "llpanelappearancetab.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.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()
{
uuid_vec_t selected_uuids;

View File

@ -35,13 +35,17 @@ public:
LLPanelAppearanceTab() : LLPanel() {}
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 void getSelectedItemsUUIDs(uuid_vec_t& selected_uuids) const {}
static const std::string& getFilterSubString() { return sFilterSubString; }
const std::string& getFilterSubString() { return mFilterSubString; }
protected:
@ -50,7 +54,10 @@ protected:
*/
bool canTakeOffSelected();
static std::string sFilterSubString;
private:
std::string mFilterSubString;
static std::string sRecentFilterSubString;
};
#endif //LL_LLPANELAPPEARANCETAB_H

View File

@ -97,7 +97,7 @@ enum ESubpart {
SUBPART_SKIRT,
SUBPART_ALPHA,
SUBPART_TATTOO,
SUBPART_UNIVERSAL,
SUBPART_UNIVERSAL,
SUBPART_PHYSICS_BREASTS_UPDOWN,
SUBPART_PHYSICS_BREASTS_INOUT,
SUBPART_PHYSICS_BREASTS_LEFTRIGHT,
@ -120,7 +120,7 @@ class LLEditWearableDictionary : public LLSingleton<LLEditWearableDictionary>
//--------------------------------------------------------------------
LLSINGLETON(LLEditWearableDictionary);
virtual ~LLEditWearableDictionary();
//--------------------------------------------------------------------
// Wearable Types
//--------------------------------------------------------------------
@ -214,7 +214,6 @@ public:
LLEditWearableDictionary::LLEditWearableDictionary()
{
}
//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.
// Please match the order presented in XUI. -Nyx
// 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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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 }));
}
LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType type,
@ -259,52 +258,59 @@ LLEditWearableDictionary::WearableEntry::WearableEntry(LLWearableType::EType typ
mSubparts(subparts),
mColorSwatchCtrls(color_swatches),
mTextureCtrls(texture_pickers)
{}
{
}
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));
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_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_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_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_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_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_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));
// WT_SHAPE
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_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_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_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_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_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_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_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_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_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_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_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));
// WT_HAIR
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_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_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));
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_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_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_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_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_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_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_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));
// 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_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_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_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_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_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_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_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_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_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));
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));
// WT_PHYSICS
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_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_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_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_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));
}
LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
@ -329,55 +335,55 @@ LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part,
LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls()
{
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_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "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_SKIRT, new PickerControlEntry (TEX_SKIRT, "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_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "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_UPPER_SHIRT, new PickerControlEntry(TEX_UPPER_SHIRT, "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_SOCKS, new PickerControlEntry(TEX_LOWER_SOCKS, "Color/Tint"));
addEntry(TEX_UPPER_JACKET, new PickerControlEntry(TEX_UPPER_JACKET, "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_UNDERSHIRT, new PickerControlEntry(TEX_UPPER_UNDERSHIRT, "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_UNIVERSAL_TATTOO, new PickerControlEntry(TEX_HEAD_UNIVERSAL_TATTOO, "Color/Tint"));
}
LLEditWearableDictionary::TextureCtrls::TextureCtrls()
{
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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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_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));
}
LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index,
@ -490,8 +496,8 @@ template <typename CtrlType, class Predicate>
const LLEditWearableDictionary::PickerControlEntry*
find_picker_ctrl_entry_if(LLWearableType::EType type, const Predicate pred)
{
const LLEditWearableDictionary::WearableEntry *wearable_entry
= LLEditWearableDictionary::getInstance()->getWearable(type);
const LLEditWearableDictionary::WearableEntry *wearable_entry =
LLEditWearableDictionary::getInstance()->getWearable(type);
if (!wearable_entry)
{
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>
void
for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_t fun)
void for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_t fun)
{
if (!panel)
{
@ -542,14 +547,13 @@ for_each_picker_ctrl_entry(LLPanel* panel, LLWearableType::EType type, function_
iter != iter_end; ++iter)
{
const ETextureIndex te = *iter;
const LLEditWearableDictionary::PickerControlEntry* entry
= get_picker_entry<CtrlType>(te);
const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry<CtrlType>(te);
if (!entry)
{
LL_WARNS() << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << LL_ENDL;
continue;
}
fun (panel, entry);
fun(panel, entry);
}
}
@ -594,7 +598,7 @@ static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const
{
LLUUID new_id;
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();
}
@ -644,7 +648,6 @@ LLPanelEditWearable::LLPanelEditWearable()
//virtual
LLPanelEditWearable::~LLPanelEditWearable()
{
}
bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value)
@ -659,7 +662,7 @@ void LLPanelEditWearable::updateMetricLayout(BOOL new_value)
LLUIString current_metric, replacment_metric;
current_metric = new_value ? mMeters : mFeet;
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("]"));
}
@ -667,11 +670,11 @@ void LLPanelEditWearable::updateAvatarHeightLabel()
{
mTxtAvatarHeight->setText(LLStringUtil::null);
LLStyle::Params param;
param.color = mAvatarHeigthLabelColor;
mTxtAvatarHeight->appendText(mHeigth, false, param);
param.color = mAvatarHeigthValueLabelColor;
mTxtAvatarHeight->appendText(mHeigthValue, false, param);
param.color = mAvatarHeigthLabelColor; // using mAvatarHeigthLabelColor for '/' separator
param.color = mAvatarHeightLabelColor;
mTxtAvatarHeight->appendText(mHeight, false, param);
param.color = mAvatarHeightValueLabelColor;
mTxtAvatarHeight->appendText(mHeightValue, false, param);
param.color = mAvatarHeightLabelColor; // using mAvatarHeightLabelColor for '/' separator
mTxtAvatarHeight->appendText(" / ", false, param);
mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param);
}
@ -754,7 +757,7 @@ BOOL LLPanelEditWearable::postBuild()
mPanelSkirt = getChild<LLPanel>("edit_skirt_panel");
mPanelAlpha = getChild<LLPanel>("edit_alpha_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");
mTxtAvatarHeight = mPanelShape->getChild<LLTextBox>("avatar_height");
@ -778,29 +781,27 @@ BOOL LLPanelEditWearable::postBuild()
continue;
}
U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry)
{
LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL;
continue;
}
const std::string accordion_tab = subpart_entry->mAccordionTab;
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!tab)
{
LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL;
continue;
}
// initialize callback to ensure camera view changes appropriately.
tab->setDropDownStateChangedCallback(boost::bind(&LLPanelEditWearable::onTabExpandedCollapsed,this,_2,index));
}
@ -813,14 +814,14 @@ BOOL LLPanelEditWearable::postBuild()
// init all strings
mMeters = mPanelShape->getString("meters");
mFeet = mPanelShape->getString("feet");
mHeigth = mPanelShape->getString("height") + " ";
mHeigthValue = "[HEIGHT] [METRIC1]";
mHeight = mPanelShape->getString("height") + " ";
mHeightValue = "[HEIGHT] [METRIC1]";
mReplacementMetricUrl = "[URL_METRIC2]";
std::string color = mPanelShape->getString("heigth_label_color");
mAvatarHeigthLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
color = mPanelShape->getString("heigth_value_label_color");
mAvatarHeigthValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
std::string color = mPanelShape->getString("height_label_color");
mAvatarHeightLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
color = mPanelShape->getString("height_value_label_color");
mAvatarHeightValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green);
gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2));
updateMetricLayout(gSavedSettings.getBOOL("HeightUnits"));
@ -834,14 +835,16 @@ BOOL LLPanelEditWearable::isDirty() const
BOOL isDirty = FALSE;
if (mWearablePtr)
{
if (mWearablePtr->isDirty() ||
( mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0 ))
{
isDirty = TRUE;
}
if (mWearablePtr->isDirty() ||
(mWearableItem && mNameEditor && mWearableItem->getName().compare(mNameEditor->getText()) != 0))
{
isDirty = TRUE;
}
}
return isDirty;
}
//virtual
void LLPanelEditWearable::draw()
{
@ -857,8 +860,8 @@ void LLPanelEditWearable::draw()
void LLPanelEditWearable::onClose()
{
// any unsaved changes should be reverted at this point
revertChanges();
// any unsaved changes should be reverted at this point
revertChanges();
}
void LLPanelEditWearable::setVisible(BOOL visible)
@ -880,11 +883,11 @@ void LLPanelEditWearable::setWearable(LLViewerWearable *wearable, BOOL disable_c
//static
void LLPanelEditWearable::onBackButtonClicked(void* userdata)
{
LLPanelEditWearable *panel = (LLPanelEditWearable*) userdata;
if ( panel->isDirty() )
{
LLAppearanceMgr::instance().setOutfitDirty( true );
}
LLPanelEditWearable* panel = (LLPanelEditWearable*)userdata;
if (panel->isDirty())
{
LLAppearanceMgr::instance().setOutfitDirty(true);
}
}
//static
@ -909,7 +912,7 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r
{
std::string wearable_name = response["message"].asString();
LLStringUtil::trim(wearable_name);
if( !wearable_name.empty() )
if (!wearable_name.empty())
{
mNameEditor->setText(wearable_name);
saveChanges(true);
@ -919,24 +922,27 @@ void LLPanelEditWearable::saveAsCallback(const LLSD& notification, const LLSD& r
void LLPanelEditWearable::onCommitSexChange()
{
if (!isAgentAvatarValid()) return;
if (!isAgentAvatarValid())
{
return;
}
LLWearableType::EType type = mWearablePtr->getType();
U32 index;
if( !gAgentWearables.getWearableIndex(mWearablePtr, index) ||
!gAgentWearables.isWearableModifiable(type, index))
if (!gAgentWearables.getWearableIndex(mWearablePtr, index) ||
!gAgentWearables.isWearableModifiable(type, index))
{
return;
return;
}
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;
LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index);
LLViewerWearable* wearable = gAgentWearables.getViewerWearable(type, index);
if (wearable)
{
wearable->setVisualParamWeight(param->getID(), is_new_sex_male);
@ -969,23 +975,23 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl)
{
// Set the new version
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID());
if( image->getID() == IMG_DEFAULT )
if (image->getID() == IMG_DEFAULT)
{
image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR);
}
if (getWearable())
{
U32 index;
if (gAgentWearables.getWearableIndex(getWearable(), index))
{
gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
LLVisualParamHint::requestHintUpdates();
gAgentAvatarp->wearableUpdated(type);
}
else
{
LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL;
}
U32 index;
if (gAgentWearables.getWearableIndex(getWearable(), index))
{
gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index);
LLVisualParamHint::requestHintUpdates();
gAgentAvatarp->wearableUpdated(type);
}
else
{
LL_WARNS() << "wearable not found in gAgentWearables" << LL_ENDL;
}
}
}
else
@ -1001,13 +1007,13 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl)
{
LLWearableType::EType type = getWearable()->getType();
const PickerControlEntryNamePredicate name_pred(ctrl->getName());
const LLEditWearableDictionary::PickerControlEntry* entry
= find_picker_ctrl_entry_if<LLColorSwatchCtrl, PickerControlEntryNamePredicate>(type, name_pred);
const LLEditWearableDictionary::PickerControlEntry* entry =
find_picker_ctrl_entry_if<LLColorSwatchCtrl, PickerControlEntryNamePredicate>(type, name_pred);
if (entry)
{
const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex);
const LLColor4& new_color = LLColor4(ctrl->getValue());
if( old_color != new_color )
if (old_color != new_color)
{
getWearable()->setClothesColor(entry->mTextureIndex, new_color);
LLVisualParamHint::requestHintUpdates();
@ -1025,11 +1031,13 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type)
{
LLPanel* panel = getPanel(type);
if (!panel)
{
return;
}
bool is_modifiable = false;
if(mWearableItem)
if (mWearableItem)
{
const LLPermissions& perm = mWearableItem->getPermissions();
is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
@ -1051,7 +1059,6 @@ void LLPanelEditWearable::updatePanelPickerControls(LLWearableType::EType type)
void LLPanelEditWearable::incrementCofVersionLegacy()
{
}
void LLPanelEditWearable::saveChanges(bool force_save_as)
@ -1063,59 +1070,57 @@ void LLPanelEditWearable::saveChanges(bool force_save_as)
}
U32 index;
if (!gAgentWearables.getWearableIndex(mWearablePtr, index))
{
LL_WARNS() << "wearable not found" << LL_ENDL;
return;
}
if (!gAgentWearables.getWearableIndex(mWearablePtr, index))
{
LL_WARNS() << "wearable not found" << LL_ENDL;
return;
}
std::string new_name = mNameEditor->getText();
// Find an existing link to this wearable's inventory item, if any, and its description field.
LLInventoryItem *link_item = NULL;
std::string description;
LLInventoryModel::item_array_t links =
LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID());
if (links.size()>0)
{
link_item = links.at(0).get();
if (link_item && link_item->getIsLinkType())
{
description = link_item->getActualDescription();
}
}
// Find an existing link to this wearable's inventory item, if any, and its description field.
LLInventoryItem* link_item = NULL;
std::string description;
LLInventoryModel::item_array_t links =
LLAppearanceMgr::instance().findCOFItemLinks(mWearablePtr->getItemID());
if (links.size() > 0)
{
link_item = links.at(0).get();
if (link_item && link_item->getIsLinkType())
{
description = link_item->getActualDescription();
}
}
if (force_save_as)
{
// the name of the wearable has changed, re-save wearable with new name
LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(),gAgentAvatarp->mEndCustomizeCallback);
gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE);
mNameEditor->setText(mWearableItem->getName());
// the name of the wearable has changed, re-save wearable with new name
LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID(), gAgentAvatarp->mEndCustomizeCallback);
gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE);
mNameEditor->setText(mWearableItem->getName());
}
else
{
// Make another copy of this link, with the same
// description. This is needed to bump the COF
// version so texture baking service knows appearance has changed.
if (link_item)
{
// Create new link
LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
<< " removing old link at " << link_item->getUUID()
<< " wearable item id " << mWearablePtr->getItemID() << LL_ENDL;
// Make another copy of this link, with the same
// description. This is needed to bump the COF
// version so texture baking service knows appearance has changed.
if (link_item)
{
// Create new link
LL_DEBUGS("Avatar") << "link refresh, creating new link to " << link_item->getLinkedUUID()
<< " removing old link at " << link_item->getUUID()
<< " wearable item id " << mWearablePtr->getItemID() << LL_ENDL;
LLInventoryObject::const_object_list_t obj_array;
obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
link_inventory_array(LLAppearanceMgr::instance().getCOF(),
obj_array,
gAgentAvatarp->mEndCustomizeCallback);
// Remove old link
remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
}
gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name);
LLInventoryObject::const_object_list_t obj_array;
obj_array.push_back(LLConstPointer<LLInventoryObject>(link_item));
link_inventory_array(LLAppearanceMgr::instance().getCOF(),
obj_array,
gAgentAvatarp->mEndCustomizeCallback);
// Remove old link
remove_inventory_item(link_item->getUUID(), gAgentAvatarp->mEndCustomizeCallback);
}
gAgentWearables.saveWearable(mWearablePtr->getType(), index, new_name);
}
}
void LLPanelEditWearable::revertChanges()
@ -1165,15 +1170,15 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
targetPanel->setVisible(show);
toggleTypeSpecificControls(type);
// Update type controls here
updateTypeSpecificControls(type);
// Update type controls here
updateTypeSpecificControls(type);
if (show)
{
mPanelTitle->setText(title);
mPanelTitle->setToolTip(title);
mDescTitle->setText(description_title);
// set name
mNameEditor->setText(mWearableItem->getName());
@ -1181,51 +1186,51 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
// clear and rebuild visual param list
U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
for (U8 index = 0; index < num_subparts; ++index)
{
// dive into data structures to get the panel we need
ESubpart subpart_e = wearable_entry->mSubparts[index];
const LLEditWearableDictionary::SubpartEntry *subpart_entry = LLEditWearableDictionary::getInstance()->getSubpart(subpart_e);
if (!subpart_entry)
{
LL_WARNS() << "could not get wearable subpart dictionary entry for subpart: " << subpart_e << LL_ENDL;
continue;
}
const std::string scrolling_panel = subpart_entry->mParamList;
const std::string accordion_tab = subpart_entry->mAccordionTab;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
LLAccordionCtrlTab *tab = getChild<LLAccordionCtrlTab>(accordion_tab);
if (!panel_list)
{
LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL;
continue;
}
if (!tab)
{
LL_WARNS() << "could not get llaccordionctrltab from UI with name: " << accordion_tab << LL_ENDL;
continue;
}
// Don't show female subparts if you're not female, etc.
if (!(gAgentAvatarp->getSex() & subpart_entry->mSex))
{
tab->setVisible(FALSE);
continue;
}
else
{
tab->setVisible(TRUE);
}
// Don't show female subparts if you're not female, etc.
if (!(gAgentAvatarp->getSex() & subpart_entry->mSex))
{
tab->setVisible(FALSE);
continue;
}
else
{
tab->setVisible(TRUE);
}
// what edit group do we want to extract params for?
const std::string edit_group = subpart_entry->mEditGroup;
// storage for ordered list of visual params
value_map_t sorted_params;
getSortedParams(sorted_params, edit_group);
@ -1237,9 +1242,10 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
}
buildParamList(panel_list, sorted_params, tab, jointp);
updateScrollingPanelUI();
}
if (!disable_camera_switch)
{
showDefaultSubpart();
@ -1268,17 +1274,17 @@ void LLPanelEditWearable::onTabExpandedCollapsed(const LLSD& param, U8 index)
{
changeCamera(index);
}
}
void LLPanelEditWearable::changeCamera(U8 subpart)
{
// 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.
if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType()))
{
return;
}
// 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.
if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType()))
{
return;
}
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(mWearablePtr->getType());
if (!wearable_entry)
{
@ -1307,9 +1313,9 @@ void LLPanelEditWearable::changeCamera(U8 subpart)
gMorphView->setCameraOffset( subpart_entry->mCameraOffset );
if (gSavedSettings.getBOOL("AppearanceCameraMovement"))
{
// Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE
gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating());
gMorphView->updateCamera();
// Unlock focus from avatar but don't stop animation to not interrupt ANIM_AGENT_CUSTOMIZE
gAgentCamera.setFocusOnAvatar(FALSE, gAgentCamera.getCameraAnimating());
gMorphView->updateCamera();
}
}
@ -1345,7 +1351,7 @@ void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type)
}
std::string avatar_height_str = llformat("%.2f", new_size);
mHeigthValue.setArg("[HEIGHT]", avatar_height_str);
mHeightValue.setArg("[HEIGHT]", avatar_height_str);
updateAvatarHeightLabel();
}
@ -1368,14 +1374,18 @@ void LLPanelEditWearable::updateScrollingPanelUI()
LLWearableType::EType type = mWearablePtr->getType();
LLPanel *panel = getPanel(type);
if(panel && (mWearablePtr->getItemID().notNull()))
if (panel && (mWearablePtr->getItemID().notNull()))
{
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(type);
llassert(wearable_entry);
if (!wearable_entry) return;
U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
if (!wearable_entry)
{
return;
}
LLScrollingPanelParam::sUpdateDelayFrames = 0;
U8 num_subparts = (U8)(wearable_entry->mSubparts.size());
for (U8 index = 0; index < num_subparts; ++index)
{
// 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;
LLScrollingPanelList *panel_list = getChild<LLScrollingPanelList>(scrolling_panel);
if (!panel_list)
{
LL_WARNS() << "could not get scrolling panel list: " << scrolling_panel << LL_ENDL;
continue;
}
panel_list->updatePanels(TRUE);
}
}
@ -1403,76 +1413,58 @@ LLPanel* LLPanelEditWearable::getPanel(LLWearableType::EType type)
{
case LLWearableType::WT_SHAPE:
return mPanelShape;
break;
case LLWearableType::WT_SKIN:
return mPanelSkin;
break;
case LLWearableType::WT_HAIR:
return mPanelHair;
break;
case LLWearableType::WT_EYES:
return mPanelEyes;
break;
case LLWearableType::WT_SHIRT:
return mPanelShirt;
break;
case LLWearableType::WT_PANTS:
return mPanelPants;
break;
case LLWearableType::WT_SHOES:
return mPanelShoes;
break;
case LLWearableType::WT_SOCKS:
return mPanelSocks;
break;
case LLWearableType::WT_JACKET:
return mPanelJacket;
break;
case LLWearableType::WT_GLOVES:
return mPanelGloves;
break;
case LLWearableType::WT_UNDERSHIRT:
return mPanelUndershirt;
break;
case LLWearableType::WT_UNDERPANTS:
return mPanelUnderpants;
break;
case LLWearableType::WT_SKIRT:
return mPanelSkirt;
break;
case LLWearableType::WT_ALPHA:
return mPanelAlpha;
break;
case LLWearableType::WT_TATTOO:
return mPanelTattoo;
break;
case LLWearableType::WT_UNIVERSAL:
return mPanelUniversal;
break;
case LLWearableType::WT_UNIVERSAL:
return mPanelUniversal;
case LLWearableType::WT_PHYSICS:
return mPanelPhysics;
break;
default:
break;
return NULL;
}
return NULL;
}
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
// least to greatest. Adding to the front of the child list
// reverses that order.
if( panel_list )
if (panel_list)
{
panel_list->clearPanels();
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;
p.name("LLScrollingPanelParam");
@ -1534,7 +1526,7 @@ void LLPanelEditWearable::updateVerbs()
{
bool can_copy = false;
if(mWearableItem)
if (mWearableItem)
{
can_copy = mWearableItem->getPermissions().allowCopyBy(gAgentID);
}
@ -1544,7 +1536,7 @@ void LLPanelEditWearable::updateVerbs()
mBtnRevert->setEnabled(is_dirty);
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
// with value from "AvatarSex" setting
@ -1585,17 +1577,20 @@ void LLPanelEditWearable::configureAlphaCheckbox(LLAvatarAppearanceDefines::ETex
void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LLAvatarAppearanceDefines::ETextureIndex te)
{
if (!checkbox_ctrl) return;
if (!getWearable()) return;
if (!checkbox_ctrl || !getWearable())
{
return;
}
LL_INFOS() << "onInvisibilityCommit, self " << this << " checkbox_ctrl " << checkbox_ctrl << LL_ENDL;
U32 index;
if (!gAgentWearables.getWearableIndex(getWearable(),index))
{
LL_WARNS() << "wearable not found" << LL_ENDL;
return;
}
U32 index;
if (!gAgentWearables.getWearableIndex(getWearable(), index))
{
LL_WARNS() << "wearable not found" << LL_ENDL;
return;
}
bool new_invis_state = checkbox_ctrl->get();
if (new_invis_state)
{
@ -1603,8 +1598,8 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
mPreviousAlphaTexture[te] = lto->getID();
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_INVISIBLE );
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
gAgentAvatarp->wearableUpdated(getWearable()->getType());
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
gAgentAvatarp->wearableUpdated(getWearable()->getType());
}
else
{
@ -1614,10 +1609,16 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
{
prev_id = LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) );
}
if (prev_id.isNull()) return;
if (prev_id.isNull())
{
return;
}
LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(prev_id);
if (!image) return;
if (!image)
{
return;
}
gAgentAvatarp->setLocalTexture(te, image, FALSE, index);
gAgentAvatarp->wearableUpdated(getWearable()->getType());
@ -1628,7 +1629,7 @@ void LLPanelEditWearable::onInvisibilityCommit(LLCheckBoxCtrl* checkbox_ctrl, LL
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 )
{
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
std::string mMeters;
std::string mFeet;
std::string mHeigth;
LLUIString mHeigthValue;
std::string mHeight;
LLUIString mHeightValue;
LLUIString mReplacementMetricUrl;
// color for mHeigth string
LLUIColor mAvatarHeigthLabelColor;
// color for mHeigthValue string
LLUIColor mAvatarHeigthValueLabelColor;
// color for mHeight string
LLUIColor mAvatarHeightLabelColor;
// color for mHeightValue string
LLUIColor mAvatarHeightValueLabelColor;
// This text editor reference will change each time we edit a new wearable -
// it will be grabbed from the currently visible panel

View File

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

View File

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

View File

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

View File

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

View File

@ -561,7 +561,6 @@ void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id)
{
mPickName->setEnabled(TRUE);
mPickDescription->setEnabled(TRUE);
mSetCurrentLocationButton->setVisible(TRUE);
}
else
{
@ -576,7 +575,6 @@ BOOL LLPanelProfilePick::postBuild()
mSaveButton = getChild<LLButton>("save_changes_btn");
mCreateButton = getChild<LLButton>("create_changes_btn");
mCancelButton = getChild<LLButton>("cancel_changes_btn");
mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn");
mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot");
mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this));
@ -587,7 +585,6 @@ BOOL LLPanelProfilePick::postBuild()
mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this));
mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, 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->setEnabled(FALSE);
@ -749,32 +746,6 @@ BOOL LLPanelProfilePick::isDirty() const
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()
{
sendUpdate();

View File

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

View File

@ -32,6 +32,7 @@
// Viewer includes
#include "llcombobox.h"
#include "llsliderctrl.h"
#include "llstartup.h"
#include "llviewercontrol.h"
#include "llvoiceclient.h"
#include "llvoicechannel.h"
@ -70,11 +71,14 @@ BOOL LLPanelVoiceDeviceSettings::postBuild()
mCtrlInputDevices = getChild<LLComboBox>("voice_input_device");
mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device");
mUnmuteBtn = getChild<LLButton>("unmute_btn");
mCtrlInputDevices->setCommitCallback(
boost::bind(&LLPanelVoiceDeviceSettings::onCommitInputDevice, this));
mCtrlOutputDevices->setCommitCallback(
boost::bind(&LLPanelVoiceDeviceSettings::onCommitOutputDevice, this));
mUnmuteBtn->setCommitCallback(
boost::bind(&LLPanelVoiceDeviceSettings::onCommitUnmute, this));
mLocalizedDeviceNames[DEFAULT_DEVICE] = getString("default_text");
mLocalizedDeviceNames["No Device"] = getString("name_no_device");
@ -108,11 +112,27 @@ void LLPanelVoiceDeviceSettings::draw()
// let user know that volume indicator is not yet available
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();
if (is_in_tuning_mode)
if (is_in_tuning_mode && voice_enabled)
{
const S32 num_bars = 5;
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.
}
void LLPanelVoiceDeviceSettings::onCommitUnmute()
{
gSavedSettings.setBOOL("EnableVoiceChat", TRUE);
}

View File

@ -55,12 +55,14 @@ protected:
void onCommitOutputDevice();
void onOutputDevicesClicked();
void onInputDevicesClicked();
void onCommitUnmute();
F32 mMicVolume;
std::string mInputDevice;
std::string mOutputDevice;
class LLComboBox *mCtrlInputDevices;
class LLComboBox *mCtrlOutputDevices;
class LLButton *mUnmuteBtn;
BOOL mDevicesUpdated;
bool mUseTuningMode;
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.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));
buildFromFile( "panel_volume_pulldown.xml");
}
@ -90,19 +90,23 @@ void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data)
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
// "Streaming Music" and "Media" are unchecked. STORM-513.
if ((name == "enable_music") || (name == "enable_media"))
{
bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get();
bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get();
// Disable "Allow Media to auto play" only when both
// "Streaming Music" and "Media" are unchecked. STORM-513.
if ((name == "enable_music") || (name == "enable_media"))
{
bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->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()

View File

@ -43,7 +43,7 @@ class LLPanelVolumePulldown : public LLPanelPulldown
void onClickSetSounds();
// Disables "Allow Media to auto play" check box only when both
// "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);
};

View File

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

View File

@ -61,7 +61,7 @@ public:
/*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);

View File

@ -87,6 +87,9 @@
#include "llexperiencecache.h"
#include "llfloaterexperienceprofile.h"
#include "llviewerassetupload.h"
#include "lltoggleablemenu.h"
#include "llmenubutton.h"
#include "llinventoryfunctions.h"
const std::string HELLO_LSL =
"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
/// ---------------------------------------------------------------------------
@ -460,6 +495,13 @@ BOOL LLScriptEdCore::postBuild()
LLSyntaxIdLSL::getInstance()->initialize();
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;
}
@ -788,7 +830,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string)
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);
@ -1288,7 +1330,21 @@ LLUUID LLScriptEdCore::getAssociatedExperience()const
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;
updateExperiencePanel();
@ -1476,7 +1532,21 @@ bool LLScriptEdContainer::onExternalChange(const std::string& filename)
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
/// ---------------------------------------------------------------------------
@ -1517,6 +1587,14 @@ LLPreviewLSL::LLPreviewLSL(const LLSD& key )
mPendingUploads(0)
{
mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this);
mItemObserver = new LLScriptMovedObserver(this);
}
LLPreviewLSL::~LLPreviewLSL()
{
delete mItemObserver;
mItemObserver = NULL;
}
// virtual
@ -1528,10 +1606,14 @@ BOOL LLPreviewLSL::postBuild()
if (item)
{
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);
getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe);
return LLPreview::postBuild();
}
@ -1543,7 +1625,12 @@ void LLPreviewLSL::draw()
setTitle(LLTrans::getString("ScriptWasDeleted"));
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();
}
// virtual
@ -1856,7 +1943,8 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
mPendingUploads(0),
mIsModifiable(FALSE),
mIsNew(false),
mIsSaving(FALSE)
mIsSaving(FALSE),
mObjectName("")
{
mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
}
@ -1993,6 +2081,7 @@ void LLLiveLSLEditor::loadAsset()
}
refreshFromItem();
getChild<LLUICtrl>("obj_name")->setValue(mObjectName);
// This is commented out, because we don't completely
// handle script exports yet.
/*

View File

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

View File

@ -30,19 +30,22 @@
#include "llsyntaxid.h"
#include "lllocalcliprect.h"
#include "llviewercontrol.h"
const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32;
static LLDefaultChildRegistry::Register<LLScriptEditor> r("script_editor");
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)
: LLTextEditor(p)
, mShowLineNumbers(p.show_line_numbers)
, mShowLineNumbers(p.show_line_numbers),
mUseDefaultFontSize(p.default_font_size)
{
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()
{
{
@ -110,12 +119,11 @@ void LLScriptEditor::drawLineNumbers()
// draw the line numbers
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 ));
BOOL is_cur_line = cursor_line == line.mLineNum;
const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL;
const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor;
num_font->render(
getScriptFont()->render(
ltext, // string to draw
0, // begin offset
UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x
@ -143,8 +151,10 @@ void LLScriptEditor::loadKeywords()
LL_PROFILE_ZONE_SCOPED;
mKeywords.processTokens();
LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
segment_vec_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
mKeywords.findSegments(&segment_list, getWText(), *this, style);
mSegments.clear();
segment_set_t::iterator insert_it = mSegments.begin();
@ -159,9 +169,12 @@ void LLScriptEditor::updateSegments()
if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly)
{
LL_PROFILE_ZONE_SCOPED;
LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get()));
// HACK: No non-ascii keywords for now
segment_vec_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);
mKeywords.findSegments(&segment_list, getWText(), *this, style);
clearSegments();
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>
{
Optional<bool> show_line_numbers;
Optional<bool> default_font_size;
Params();
};
@ -45,6 +45,7 @@ public:
// LLView override
virtual void draw();
BOOL postBuild();
void initKeywords();
void loadKeywords();
@ -52,7 +53,11 @@ public:
LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); }
LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); }
protected:
static std::string getScriptFontSize();
LLFontGL* getScriptFont();
void onFontSizeChange();
protected:
friend class LLUICtrlFactory;
LLScriptEditor(const Params& p);
@ -65,6 +70,7 @@ private:
LLKeywords mKeywords;
bool mShowLineNumbers;
bool mUseDefaultFontSize;
};
#endif // LL_SCRIPTEDITOR_H

View File

@ -75,6 +75,17 @@ bool LLSearchHistory::save()
{
// build filename for each user
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
llofstream file(resolved_filename.c_str());
if (!file.is_open())

View File

@ -1,4 +1,4 @@
/**
/**
* @file llurlsimstring.cpp (was llsimurlstring.cpp)
* @brief Handles "SLURL fragments" like Ahern/123/45 for
* startup processing, login screen, prefs, etc.
@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@ -36,7 +36,7 @@
#include "curl/curl.h"
const char* LLSLURL::SLURL_HTTP_SCHEME = "http";
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_COM = "slurl.com";
// 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
LLSLURL::LLSLURL(const std::string& slurl)
{
// by default we go to agni.
mType = INVALID;
// by default we go to agni.
mType = INVALID;
if(slurl == SIM_LOCATION_HOME)
{
mType = HOME_LOCATION;
}
else if(slurl.empty() || (slurl == SIM_LOCATION_LAST))
{
mType = LAST_LOCATION;
}
else
{
LLURI slurl_uri;
// parse the slurl as a uri
if(slurl.find(':') == std::string::npos)
{
// There may be no scheme ('secondlife:' etc.) passed in. In that case
// we want to normalize the slurl by putting the appropriate scheme
// 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
// 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,
// where the user can type in <regionname>/<x>/<y>/<z>
std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase();
if (slurl.empty() || (slurl == SIM_LOCATION_LAST))
{
mType = LAST_LOCATION;
}
else if (slurl == SIM_LOCATION_HOME)
{
mType = HOME_LOCATION;
}
else
{
LLURI slurl_uri;
// parse the slurl as a uri
if (slurl.find(':') == std::string::npos)
{
// There may be no scheme ('secondlife:' etc.) passed in. In that case
// we want to normalize the slurl by putting the appropriate scheme
// 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
// 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,
// where the user can type in <regionname>/<x>/<y>/<z>
std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase();
// 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>
// 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();
}
// 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>
// or some such.
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)
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)
{
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;
}
else
{
// 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
mType = LOCATION;
// 'normalize' it so the region name is in fact the head of the path_array
path_array.insert(0, slurl_uri.hostName());
// therefore the hostname will be the region name, and it's a location type
mType = LOCATION;
// 'normalize' it so the region name is in fact the head of the path_array
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
// urls are properly formed, unlike the stinky maingrid style
mGrid = slurl_uri.hostName();
}
if (path_array.size() == 0)
{
// um, we need a path...
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
// 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
mGrid = slurl_uri.hostName();
}
if (path_array.size() == 0)
{
// um, we need a path...
return;
}
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))
{
LLStringUtil::stripNonprintable(mRegion);
}
if (path_array.size() == 0)
{
// we gotta have some stuff after the specifier as to whether it's a region or command
return;
}
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);
}
}
}
// 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());
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
LLSLURL::LLSLURL(const std::string& grid,
const std::string& region)
LLSLURL::LLSLURL(const std::string& grid, const std::string& region)
{
mGrid = grid;
mRegion = region;
mType = LOCATION;
mPosition = LLVector3((F64)REGION_WIDTH_METERS/2, (F64)REGION_WIDTH_METERS/2, 0);
mGrid = grid;
mRegion = region;
mType = LOCATION;
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
// width handling global positions as well
LLSLURL::LLSLURL(const std::string& grid,
const std::string& region,
const LLVector3& position)
LLSLURL::LLSLURL(const std::string& grid,
const std::string& region,
const LLVector3& position)
{
mGrid = grid;
mRegion = region;
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 z = ll_round( (F32)position[VZ] );
mType = LOCATION;
mPosition = LLVector3(x, y, z);
mGrid = grid;
mRegion = region;
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 z = ll_round((F32)position[VZ]);
mType = LOCATION;
mPosition = LLVector3(x, y, z);
}
// create a simstring
LLSLURL::LLSLURL(const std::string& region,
const LLVector3& position)
LLSLURL::LLSLURL(const std::string& region,
const LLVector3& position)
{
*this = LLSLURL(LLGridManager::getInstance()->getGridId(),
region, position);
*this = LLSLURL(LLGridManager::getInstance()->getGridId(), region, position);
}
// create a slurl from a global position
LLSLURL::LLSLURL(const std::string& grid,
const std::string& region,
const LLVector3d& global_position)
LLSLURL::LLSLURL(const std::string& grid,
const std::string& region,
const LLVector3d& global_position)
{
*this = LLSLURL(LLGridManager::getInstance()->getGridId(grid),
region, LLVector3(global_position.mdV[VX],
global_position.mdV[VY],
global_position.mdV[VZ]));
*this = LLSLURL(LLGridManager::getInstance()->getGridId(grid), region,
LLVector3(global_position.mdV[VX], global_position.mdV[VY], global_position.mdV[VZ]));
}
// create a slurl from a global position
LLSLURL::LLSLURL(const std::string& region,
const LLVector3d& global_position)
LLSLURL::LLSLURL(const std::string& region,
const LLVector3d& global_position)
{
*this = LLSLURL(LLGridManager::getInstance()->getGridId(),
region, global_position);
*this = LLSLURL(LLGridManager::getInstance()->getGridId(),
region, global_position);
}
LLSLURL::LLSLURL(const std::string& command, const LLUUID&id, const std::string& verb)
{
mType = APP;
mAppCmd = command;
mAppPath = LLSD::emptyArray();
mAppPath.append(LLSD(id));
mAppPath.append(LLSD(verb));
mType = APP;
mAppCmd = command;
mAppPath = LLSD::emptyArray();
mAppPath.append(LLSD(id));
mAppPath.append(LLSD(verb));
}
std::string LLSLURL::getSLURLString() const
{
switch(mType)
{
case HOME_LOCATION:
return SIM_LOCATION_HOME;
case LAST_LOCATION:
return SIM_LOCATION_LAST;
case LOCATION:
{
// lookup the grid
S32 x = ll_round( (F32)mPosition[VX] );
S32 y = ll_round( (F32)mPosition[VY] );
S32 z = ll_round( (F32)mPosition[VZ] );
return LLGridManager::getInstance()->getSLURLBase(mGrid) +
LLURI::escape(mRegion) + llformat("/%d/%d/%d",x,y,z);
}
case APP:
{
std::ostringstream app_url;
app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd;
for(LLSD::array_const_iterator i = mAppPath.beginArray();
i != mAppPath.endArray();
i++)
{
app_url << "/" << i->asString();
}
if(mAppQuery.length() > 0)
{
app_url << "?" << mAppQuery;
}
return app_url.str();
}
default:
LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL;
return std::string();
}
switch (mType)
{
case HOME_LOCATION:
return SIM_LOCATION_HOME;
case LAST_LOCATION:
return SIM_LOCATION_LAST;
case LOCATION:
{
// lookup the grid
S32 x = ll_round((F32)mPosition[VX]);
S32 y = ll_round((F32)mPosition[VY]);
S32 z = ll_round((F32)mPosition[VZ]);
return LLGridManager::getInstance()->getSLURLBase(mGrid) +
LLURI::escape(mRegion) + llformat("/%d/%d/%d", x, y, z);
}
case APP:
{
std::ostringstream app_url;
app_url << LLGridManager::getInstance()->getAppSLURLBase() << "/" << mAppCmd;
for (LLSD::array_const_iterator i = mAppPath.beginArray();
i != mAppPath.endArray();
i++)
{
app_url << "/" << i->asString();
}
if (mAppQuery.length() > 0)
{
app_url << "?" << mAppQuery;
}
return app_url.str();
}
default:
LL_WARNS("AppInit") << "Unexpected SLURL type for SLURL string" << (int)mType << LL_ENDL;
return std::string();
}
}
std::string LLSLURL::getLoginString() const
{
std::stringstream unescaped_start;
switch(mType)
{
case LOCATION:
unescaped_start << "uri:"
<< mRegion << "&"
<< ll_round(mPosition[0]) << "&"
<< ll_round(mPosition[1]) << "&"
<< ll_round(mPosition[2]);
break;
case HOME_LOCATION:
unescaped_start << "home";
break;
case LAST_LOCATION:
unescaped_start << "last";
break;
default:
LL_WARNS("AppInit") << "Unexpected SLURL type ("<<(int)mType <<")for login string"<< LL_ENDL;
break;
}
return xml_escape_string(unescaped_start.str());
std::stringstream unescaped_start;
switch (mType)
{
case LOCATION:
unescaped_start << "uri:"
<< mRegion << "&"
<< ll_round(mPosition[0]) << "&"
<< ll_round(mPosition[1]) << "&"
<< ll_round(mPosition[2]);
break;
case HOME_LOCATION:
unescaped_start << "home";
break;
case LAST_LOCATION:
unescaped_start << "last";
break;
default:
LL_WARNS("AppInit") << "Unexpected SLURL type (" << (int)mType << ")for login string" << LL_ENDL;
break;
}
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;
switch(mType)
{
case LOCATION:
return ((mGrid == rhs.mGrid) &&
(mRegion == rhs.mRegion) &&
(mPosition == rhs.mPosition));
case APP:
return getSLURLString() == rhs.getSLURLString();
case HOME_LOCATION:
case LAST_LOCATION:
return true;
default:
return false;
}
if (rhs.mType != mType)
return false;
switch (mType)
{
case LOCATION:
return (mGrid == rhs.mGrid) &&
(mRegion == rhs.mRegion) &&
(mPosition == rhs.mPosition);
case APP:
return getSLURLString() == rhs.getSLURLString();
case HOME_LOCATION:
case LAST_LOCATION:
return true;
default:
return false;
}
}
bool LLSLURL::operator !=(const LLSLURL& rhs)
{
return !(*this == rhs);
return !(*this == rhs);
}
std::string LLSLURL::getLocationString() const
{
return llformat("%s/%d/%d/%d",
mRegion.c_str(),
(int)ll_round(mPosition[0]),
(int)ll_round(mPosition[1]),
(int)ll_round(mPosition[2]));
return llformat("%s/%d/%d/%d",
mRegion.c_str(),
(int)ll_round(mPosition[0]),
(int)ll_round(mPosition[1]),
(int)ll_round(mPosition[2]));
}
// static
const std::string LLSLURL::typeName[NUM_SLURL_TYPES] =
const std::string LLSLURL::typeName[NUM_SLURL_TYPES] =
{
"INVALID",
"LOCATION",
"HOME_LOCATION",
"LAST_LOCATION",
"APP",
"HELP"
"INVALID",
"LOCATION",
"HOME_LOCATION",
"LAST_LOCATION",
"APP",
"HELP",
"EMPTY"
};
std::string LLSLURL::getTypeString(SLURL_TYPE type)
{
std::string name;
if ( type >= INVALID && type < NUM_SLURL_TYPES )
{
name = LLSLURL::typeName[type];
}
else
{
name = llformat("Out of Range (%d)",type);
}
return name;
std::string name;
if (type >= INVALID && type < NUM_SLURL_TYPES)
{
name = LLSLURL::typeName[type];
}
else
{
name = llformat("Out of Range (%d)", type);
}
return name;
}
std::string LLSLURL::asString() const
{
std::ostringstream result;
result
<< " mType: " << LLSLURL::getTypeString(mType)
<< " mGrid: " + getGrid()
<< " mRegion: " + getRegion()
<< " mPosition: " << mPosition
<< " mAppCmd:" << getAppCmd()
<< " mAppPath:" + getAppPath().asString()
<< " mAppQueryMap:" + getAppQueryMap().asString()
<< " mAppQuery: " + getAppQuery()
;
<< " mType: " << LLSLURL::getTypeString(mType)
<< " mGrid: " + getGrid()
<< " mRegion: " + getRegion()
<< " mPosition: " << mPosition
<< " mAppCmd:" << getAppCmd()
<< " mAppPath:" + getAppPath().asString()
<< " mAppQueryMap:" + getAppQueryMap().asString()
<< " mAppQuery: " + getAppQuery()
;
return result.str();
}

View File

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

View File

@ -830,6 +830,41 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
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)
{
@ -1283,17 +1318,8 @@ void drawBox(const LLVector4a& c, const LLVector4a& r)
void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
{
llassert(pos.isFinite());
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]));
if (!pos.isFinite() || !size.isFinite())
return;
LLVector3 v1 = 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)
class LLSpatialGroup : public LLOcclusionCullingGroup
{
using super = LLOcclusionCullingGroup;
friend class LLSpatialPartition;
friend class LLOctreeStateCheck;
public:
@ -333,6 +334,9 @@ public:
virtual void handleDestruction(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
// LLViewerOctreeGroup
virtual void rebound();
public:
LL_ALIGN_16(LLVector4a mViewAngle);
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.
* 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(
"showrelnotes",
[](const LLSD& url) {
LLWeb::loadURLInternal(url.asString());
LLCoros::instance().launch("releaseNotesCoro",
boost::bind(&release_notes_coro, url.asString()));
return false;
});
}
@ -2520,7 +2549,9 @@ void show_release_notes_if_required()
#endif // LL_RELEASE_FOR_DOWNLOAD
{
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;
}

View File

@ -190,6 +190,13 @@ BOOL LLStatusBar::postBuild()
LLHints::getInstance()->registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle());
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
S32 x = getRect().getWidth() - 2;
@ -640,6 +647,16 @@ void LLStatusBar::onVolumeChanged(const LLSD& newvalue)
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()
{
LLWString searchValue = utf8str_to_wstring( mFilterEdit->getValue() );

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