automated merge

Roxie Linden 2010-02-26 19:18:15 -08:00
commit a2efe4bb41
3038 changed files with 7531 additions and 194628 deletions

View File

@ -115,7 +115,7 @@ TestImageProvider gTestImageProvider;
static std::string get_xui_dir()
{
std::string delim = gDirUtilp->getDirDelimiter();
return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim;
return gDirUtilp->getSkinBaseDir() + delim + "base" + delim + "xui" + delim;
}
void init_llui()
@ -127,7 +127,7 @@ void init_llui()
const char* newview_path = "../../../newview";
#endif
gDirUtilp->initAppDirs("SecondLife", newview_path);
gDirUtilp->setSkinFolder("default");
gDirUtilp->setSkinFolder("base");
// colors are no longer stored in a LLControlGroup file
LLUIColorTable::instance().loadFromSettings();

View File

@ -77,13 +77,15 @@ def find_vc_dir():
def find_mt_path():
vc_dir = find_vc_dir()
mt_path = '\"%sbin\\mt.exe\"' % vc_dir
print "Found vc_dir: %s" % vc_dir
mt_path = '\"%s\\VC\\bin\\mt.exe\"' % vc_dir
return mt_path
def test_assembly_binding(src_filename, assembly_name, assembly_ver):
print "checking %s dependency %s..." % (src_filename, assembly_name)
(tmp_file_fd, tmp_file_name) = tempfile.mkstemp(suffix='.xml')
print tmp_file_name
tmp_file = os.fdopen(tmp_file_fd)
tmp_file.close()

View File

@ -202,12 +202,12 @@ void LLAudioEngine::updateInternetStream()
}
// virtual
int LLAudioEngine::isInternetStreamPlaying()
LLAudioEngine::LLAudioPlayState LLAudioEngine::isInternetStreamPlaying()
{
if (mStreamingAudioImpl)
return mStreamingAudioImpl->isPlaying();
return (LLAudioEngine::LLAudioPlayState) mStreamingAudioImpl->isPlaying();
return 0; // Stopped
return LLAudioEngine::AUDIO_STOPPED; // Stopped
}

View File

@ -91,6 +91,15 @@ public:
AUDIO_TYPE_COUNT = 4 // last
};
enum LLAudioPlayState
{
// isInternetStreamPlaying() returns an *int*, with
// 0 = stopped, 1 = playing, 2 = paused.
AUDIO_STOPPED = 0,
AUDIO_PLAYING = 1,
AUDIO_PAUSED = 2
};
LLAudioEngine();
virtual ~LLAudioEngine();
@ -156,7 +165,7 @@ public:
void stopInternetStream();
void pauseInternetStream(int pause);
void updateInternetStream(); // expected to be called often
int isInternetStreamPlaying();
LLAudioPlayState isInternetStreamPlaying();
// use a value from 0.0 to 1.0, inclusive
void setInternetStreamGain(F32 vol);
std::string getInternetStreamURL();

View File

@ -181,16 +181,18 @@ void LLCharacter::requestStopMotion( LLMotion* motion)
// updateMotions()
//-----------------------------------------------------------------------------
static LLFastTimer::DeclareTimer FTM_UPDATE_ANIMATION("Update Animation");
static LLFastTimer::DeclareTimer FTM_UPDATE_HIDDEN_ANIMATION("Update Hidden Anim");
void LLCharacter::updateMotions(e_update_t update_type)
{
LLFastTimer t(FTM_UPDATE_ANIMATION);
if (update_type == HIDDEN_UPDATE)
{
LLFastTimer t(FTM_UPDATE_HIDDEN_ANIMATION);
mMotionController.updateMotionsMinimal();
}
else
{
LLFastTimer t(FTM_UPDATE_ANIMATION);
// unpause if the number of outstanding pause requests has dropped to the initial one
if (mMotionController.isPaused() && mPauseRequest->getNumRefs() == 1)
{

View File

@ -221,7 +221,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
if (!target.isFinite())
{
llerrs << "Non finite target in editing motion with target distance of " << target_dist <<
" and focus point " << focus_pt << " and pointAtPt: " << *pointAtPt << llendl;
" and focus point " << focus_pt << llendl;
}
mTarget.setPosition( target + mParentJoint.getPosition());

View File

@ -50,6 +50,7 @@ set(llcommon_SOURCE_FILES
lleventdispatcher.cpp
lleventfilter.cpp
llevents.cpp
lleventtimer.cpp
llfasttimer_class.cpp
llfile.cpp
llfindlocale.cpp
@ -164,7 +165,6 @@ set(llcommon_HEADER_FILES
llhttpstatuscodes.h
llindexedqueue.h
llinstancetracker.h
llinstancetracker.h
llkeythrottle.h
lllazy.h
lllistenerwrapper.h

View File

@ -41,7 +41,7 @@
#include "lllivefile.h"
#include "llmemory.h"
#include "llstl.h" // for DeletePointer()
#include "lltimer.h"
#include "lleventtimer.h"
//
// Signal handling

View File

@ -0,0 +1,95 @@
/**
* @file lleventtimer.cpp
* @brief Cross-platform objects for doing timing
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lleventtimer.h"
#include "u64.h"
//////////////////////////////////////////////////////////////////////////////
//
// LLEventTimer Implementation
//
//////////////////////////////////////////////////////////////////////////////
LLEventTimer::LLEventTimer(F32 period)
: mEventTimer()
{
mPeriod = period;
}
LLEventTimer::LLEventTimer(const LLDate& time)
: mEventTimer()
{
mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
}
LLEventTimer::~LLEventTimer()
{
}
//static
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
{
LLInstanceTrackerScopedGuard guard;
for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); )
{
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();
if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
timer.mEventTimer.reset();
if ( timer.tick() )
{
completed_timers.push_back( &timer );
}
}
}
}
if ( completed_timers.size() > 0 )
{
for (std::list<LLEventTimer*>::iterator completed_iter = completed_timers.begin();
completed_iter != completed_timers.end();
completed_iter++ )
{
delete *completed_iter;
}
}
}

View File

@ -0,0 +1,60 @@
/**
* @file lleventtimer.h
* @brief Cross-platform objects for doing timing
*
* $LicenseInfo:firstyear=2000&license=viewergpl$
*
* Copyright (c) 2000-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_EVENTTIMER_H
#define LL_EVENTTIMER_H
#include "stdtypes.h"
#include "lldate.h"
#include "llinstancetracker.h"
#include "lltimer.h"
// class for scheduling a function to be called at a given frequency (approximate, inprecise)
class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer>
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();
//function to be called at the supplied frequency
// Normally return FALSE; TRUE will delete the timer after the function returns.
virtual BOOL tick() = 0;
static void updateClass();
protected:
LLTimer mEventTimer;
F32 mPeriod;
};
#endif //LL_EVENTTIMER_H

View File

@ -218,9 +218,10 @@ LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
// static
void LLFastTimer::DeclareTimer::updateCachedPointers()
{
DeclareTimer::LLInstanceTrackerScopedGuard guard;
// propagate frame state pointers to timer declarations
for (DeclareTimer::instance_iter it = DeclareTimer::beginInstances();
it != DeclareTimer::endInstances();
for (DeclareTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
// update cached pointer
@ -371,20 +372,23 @@ void LLFastTimer::NamedTimer::buildHierarchy()
if (sCurFrameIndex < 0 ) return;
// set up initial tree
for (instance_iter it = NamedTimer::beginInstances();
it != endInstances();
++it)
{
NamedTimer& timer = *it;
if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
// bootstrap tree construction by attaching to last timer to be on stack
// when this timer was called
if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
timer.setParent(timer.getFrameState().mLastCaller->mTimer);
// no need to push up tree on first use, flag can be set spuriously
timer.getFrameState().mMoveUpTree = false;
NamedTimer& timer = *it;
if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
// bootstrap tree construction by attaching to last timer to be on stack
// when this timer was called
if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
{
timer.setParent(timer.getFrameState().mLastCaller->mTimer);
// no need to push up tree on first use, flag can be set spuriously
timer.getFrameState().mMoveUpTree = false;
}
}
}
@ -486,18 +490,21 @@ void LLFastTimer::NamedTimer::resetFrame()
F64 total_time = 0;
LLSD sd;
for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
it != NamedTimer::endInstances();
++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
total_time = total_time + info.mSelfTimeCounter * iclock_freq;
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
total_time = total_time + info.mSelfTimeCounter * iclock_freq;
}
}
sd["Total"]["Time"] = (LLSD::Real) total_time;
@ -531,21 +538,24 @@ void LLFastTimer::NamedTimer::resetFrame()
DeclareTimer::updateCachedPointers();
// reset for next frame
for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
it != NamedTimer::endInstances();
++it)
{
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
info.mSelfTimeCounter = 0;
info.mCalls = 0;
info.mLastCaller = NULL;
info.mMoveUpTree = false;
// update parent pointer in timer state struct
if (timer.mParent)
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
info.mParent = &timer.mParent->getFrameState();
NamedTimer& timer = *it;
FrameState& info = timer.getFrameState();
info.mSelfTimeCounter = 0;
info.mCalls = 0;
info.mLastCaller = NULL;
info.mMoveUpTree = false;
// update parent pointer in timer state struct
if (timer.mParent)
{
info.mParent = &timer.mParent->getFrameState();
}
}
}
@ -575,20 +585,23 @@ void LLFastTimer::NamedTimer::reset()
}
// reset all history
for (NamedTimer::instance_iter it = NamedTimer::beginInstances();
it != NamedTimer::endInstances();
++it)
{
NamedTimer& timer = *it;
if (&timer != NamedTimerFactory::instance().getRootTimer())
NamedTimer::LLInstanceTrackerScopedGuard guard;
for (NamedTimer::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
timer.setParent(NamedTimerFactory::instance().getRootTimer());
NamedTimer& timer = *it;
if (&timer != NamedTimerFactory::instance().getRootTimer())
{
timer.setParent(NamedTimerFactory::instance().getRootTimer());
}
timer.mCountAverage = 0;
timer.mCallAverage = 0;
memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
timer.mCountAverage = 0;
timer.mCallAverage = 0;
memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
}
sLastFrameIndex = 0;

View File

@ -0,0 +1,20 @@
/**
* @file lllinstancetracker.cpp
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
* Copyright (c) 2009, Linden Research, Inc.
* $/LicenseInfo$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "llinstancetracker.h"
// STL headers
// std headers
// external library headers
// other Linden headers
// llinstancetracker.h is presently header-only. This file exists only because our CMake
// test macro ADD_BUILD_TEST requires it.
int dummy = 0;

View File

@ -98,7 +98,10 @@ private:
mKey = key;
getMap_()[key] = static_cast<T*>(this);
}
void remove_() { getMap_().erase(mKey); }
void remove_()
{
getMap_().erase(mKey);
}
static InstanceMap& getMap_()
{
@ -129,31 +132,65 @@ public:
/// for completeness of analogy with the generic implementation
static T* getInstance(T* k) { return k; }
static key_iter beginKeys() { return getSet_().begin(); }
static key_iter endKeys() { return getSet_().end(); }
static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
static instance_iter endInstances() { return instance_iter(getSet_().end()); }
static S32 instanceCount() { return getSet_().size(); }
// Instantiate this to get access to iterators for this type. It's a 'guard' in the sense
// that it treats deletes of this type as errors as long as there is an instance of
// this class alive in scope somewhere (i.e. deleting while iterating is bad).
class LLInstanceTrackerScopedGuard
{
public:
LLInstanceTrackerScopedGuard()
{
++sIterationNestDepth;
}
~LLInstanceTrackerScopedGuard()
{
--sIterationNestDepth;
}
static instance_iter beginInstances() { return instance_iter(getSet_().begin()); }
static instance_iter endInstances() { return instance_iter(getSet_().end()); }
static key_iter beginKeys() { return getSet_().begin(); }
static key_iter endKeys() { return getSet_().end(); }
};
protected:
LLInstanceTracker() { getSet_().insert(static_cast<T*>(this)); }
virtual ~LLInstanceTracker() { getSet_().erase(static_cast<T*>(this)); }
LLInstanceTracker()
{
// it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle.
//llassert(sIterationNestDepth == 0);
getSet_().insert(static_cast<T*>(this));
}
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
llassert(sIterationNestDepth == 0);
getSet_().erase(static_cast<T*>(this));
}
LLInstanceTracker(const LLInstanceTracker& other) { getSet_().insert(static_cast<T*>(this)); }
LLInstanceTracker(const LLInstanceTracker& other)
{
//llassert(sIterationNestDepth == 0);
getSet_().insert(static_cast<T*>(this));
}
static InstanceSet& getSet_() // called after getReady() but before go()
{
if (! sInstances)
{
sInstances = new InstanceSet;
}
return *sInstances;
}
static InstanceSet& getSet_()
{
if (! sInstances)
{
sInstances = new InstanceSet;
}
return *sInstances;
}
static InstanceSet* sInstances;
static S32 sIterationNestDepth;
};
template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;
template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL;
template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
#endif

View File

@ -33,7 +33,7 @@
#include "lllivefile.h"
#include "llframetimer.h"
#include "lltimer.h"
#include "lleventtimer.h"
const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f;

View File

@ -139,12 +139,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti
case LLSD::TypeBoolean:
ostr << pre << "<boolean>";
if(mBoolAlpha ||
#if( LL_WINDOWS || __GNUC__ > 2)
(ostr.flags() & std::ios::boolalpha)
#else
(ostr.flags() & 0x0100)
#endif
)
)
{
ostr << (data.asBoolean() ? "true" : "false");
}
@ -511,12 +507,7 @@ void LLSDXMLParser::Impl::reset()
mSkipping = false;
#if( LL_WINDOWS || __GNUC__ > 2)
mCurrentKey.clear();
#else
mCurrentKey = std::string();
#endif
XML_ParserReset(mParser, "utf-8");
XML_SetUserData(mParser, this);
@ -644,11 +635,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch
LLSD& newElement = map[mCurrentKey];
mStack.push_back(&newElement);
#if( LL_WINDOWS || __GNUC__ > 2)
mCurrentKey.clear();
#else
mCurrentKey = std::string();
#endif
}
else if (mStack.back()->isArray())
{

View File

@ -555,60 +555,3 @@ void secondsToTimecodeString(F32 current_time, std::string& tcstring)
}
//////////////////////////////////////////////////////////////////////////////
//
// LLEventTimer Implementation
//
//////////////////////////////////////////////////////////////////////////////
LLEventTimer::LLEventTimer(F32 period)
: mEventTimer()
{
mPeriod = period;
mBusy = false;
}
LLEventTimer::LLEventTimer(const LLDate& time)
: mEventTimer()
{
mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
mBusy = false;
}
LLEventTimer::~LLEventTimer()
{
llassert(!mBusy); // this LLEventTimer was destroyed from within its own tick() function - bad. if you want tick() to cause destruction of its own timer, make it return true.
}
//static
void LLEventTimer::updateClass()
{
std::list<LLEventTimer*> completed_timers;
for (instance_iter iter = beginInstances(); iter != endInstances(); )
{
LLEventTimer& timer = *iter++;
F32 et = timer.mEventTimer.getElapsedTimeF32();
if (timer.mEventTimer.getStarted() && et > timer.mPeriod) {
timer.mEventTimer.reset();
timer.mBusy = true;
if ( timer.tick() )
{
completed_timers.push_back( &timer );
}
timer.mBusy = false;
}
}
if ( completed_timers.size() > 0 )
{
for (std::list<LLEventTimer*>::iterator completed_iter = completed_timers.begin();
completed_iter != completed_timers.end();
completed_iter++ )
{
delete *completed_iter;
}
}
}

View File

@ -39,8 +39,6 @@
#include <limits.h>
#include "stdtypes.h"
#include "lldate.h"
#include "llinstancetracker.h"
#include <string>
#include <list>
@ -171,26 +169,6 @@ LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_dayli
LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
// class for scheduling a function to be called at a given frequency (approximate, inprecise)
class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer>
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();
//function to be called at the supplied frequency
// Normally return FALSE; TRUE will delete the timer after the function returns.
virtual BOOL tick() = 0;
static void updateClass();
protected:
LLTimer mEventTimer;
F32 mPeriod;
bool mBusy;
};
U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
#endif

View File

@ -138,23 +138,29 @@ namespace tut
keys.insert(&one);
keys.insert(&two);
keys.insert(&three);
for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys());
ki != kend; ++ki)
{
ensure_equals("spurious key", keys.erase(*ki), 1);
}
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::key_iter ki(guard.beginKeys()), kend(guard.endKeys());
ki != kend; ++ki)
{
ensure_equals("spurious key", keys.erase(*ki), 1);
}
}
ensure_equals("unreported key", keys.size(), 0);
KeySet instances;
instances.insert(&one);
instances.insert(&two);
instances.insert(&three);
for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances());
ii != iend; ++ii)
{
Unkeyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
{
Unkeyed::LLInstanceTrackerScopedGuard guard;
for (Unkeyed::instance_iter ii(guard.beginInstances()), iend(guard.endInstances());
ii != iend; ++ii)
{
Unkeyed& ref = *ii;
ensure_equals("spurious instance", instances.erase(&ref), 1);
}
}
ensure_equals("unreported instance", instances.size(), 0);
}
} // namespace tut

View File

@ -676,9 +676,6 @@ void LLImageRaw::copy(LLImageRaw* src)
LLImageRaw* dst = this; // Just for clarity.
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
llassert( (3 == dst->getComponents()) || (4 == dst->getComponents()) );
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
{
// No scaling needed

View File

@ -54,9 +54,14 @@ S32 LLImageDecodeThread::update(U32 max_time_ms)
{
creation_info& info = *iter;
ImageRequest* req = new ImageRequest(info.handle, info.image,
info.priority, info.discard, info.needs_aux,
info.responder);
addRequest(req);
info.priority, info.discard, info.needs_aux,
info.responder);
bool res = addRequest(req);
if (!res)
{
llerrs << "request added after LLLFSThread::cleanupClass()" << llendl;
}
}
mCreationList.clear();
S32 res = LLQueuedThread::update(max_time_ms);

View File

@ -3822,6 +3822,7 @@ BOOL LLVolume::cleanupTriangleData( const S32 num_input_vertices,
// Generate the vertex mapping and the list of vertices without
// duplicates. This will crash if there are no vertices.
llassert(num_input_vertices > 0); // check for no vertices!
S32 *vertex_mapping = new S32[num_input_vertices];
LLVector3 *new_vertices = new LLVector3[num_input_vertices];
LLVertexIndexPair *prev_pairp = NULL;

View File

@ -4,7 +4,7 @@
* @date 2009-02-26
* @brief Tests of llareslistener.h.
*
* $LicenseInfo:firstyear=2009&license=internal$
* $LicenseInfo:firstyear=2009&license=viewergpl$
* Copyright (c) 2009, Linden Research, Inc.
* $/LicenseInfo$
*/

View File

@ -471,7 +471,7 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int
sendMessage(message);
}
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers)
bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data)
{
bool result = true;
@ -528,6 +528,7 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie
message.setValueS32("key", key_code);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
sendMessage(message);
}
@ -546,12 +547,13 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
sendMessage(message);
}
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers)
bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD native_key_data)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "text_event");
message.setValue("text", text);
message.setValue("modifiers", translateModifiers(modifiers));
message.setValueLLSD("native_key_data", native_key_data);
sendMessage(message);
@ -682,13 +684,13 @@ LLPluginClassMedia::ETargetType getTargetTypeFromLLQtWebkit(int target_type)
// so that we don't expose the llqtwebkit header in viewer code
switch (target_type)
{
case LinkTargetType::LTT_TARGET_NONE:
case LLQtWebKit::LTT_TARGET_NONE:
return LLPluginClassMedia::TARGET_NONE;
case LinkTargetType::LTT_TARGET_BLANK:
case LLQtWebKit::LTT_TARGET_BLANK:
return LLPluginClassMedia::TARGET_BLANK;
case LinkTargetType::LTT_TARGET_EXTERNAL:
case LLQtWebKit::LTT_TARGET_EXTERNAL:
return LLPluginClassMedia::TARGET_EXTERNAL;
default:

View File

@ -114,12 +114,12 @@ public:
KEY_EVENT_REPEAT
}EKeyEventType;
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers);
bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data);
void scrollEvent(int x, int y, MASK modifiers);
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers);
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
void loadURI(const std::string &uri);

View File

@ -304,7 +304,14 @@ void LLPluginMessagePipe::processInput(void)
while((delim = mInput.find(MESSAGE_DELIMITER, start)) != std::string::npos)
{
// Let the owner process this message
mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
if (mOwner)
{
mOwner->receiveMessageRaw(mInput.substr(start, delim - start));
}
else
{
LL_WARNS("Plugin") << "!mOwner" << LL_ENDL;
}
start = delim + 1;
}

View File

@ -278,14 +278,21 @@ bool LLPluginProcessChild::isDone(void)
void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message)
{
std::string buffer = message.generate();
LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
LLTimer elapsed;
mInstance->sendMessage(buffer);
mCPUElapsed += elapsed.getElapsedTimeF64();
if (mInstance)
{
std::string buffer = message.generate();
LL_DEBUGS("Plugin") << "Sending to plugin: " << buffer << LL_ENDL;
LLTimer elapsed;
mInstance->sendMessage(buffer);
mCPUElapsed += elapsed.getElapsedTimeF64();
}
else
{
LL_WARNS("Plugin") << "mInstance == NULL" << LL_ENDL;
}
}
void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message)

View File

@ -157,14 +157,9 @@ namespace
namespace tut
{
bool llsd_equals(const LLSD& a, const LLSD& b) {
// cheesy, brute force, but it works
return std::string(ll_pretty_print_sd(a)) == std::string(ll_pretty_print_sd(b));
}
void ensure_llsd_equals(const std::string& msg, const LLSD& expected, const LLSD& actual)
{
if (!tut::llsd_equals(expected, actual))
if (!llsd_equals(expected, actual))
{
std::string message = msg;
message += ": actual: ";

View File

@ -504,8 +504,13 @@ void LLFontFreetype::resetBitmapCache()
mCharGlyphInfoMap.clear();
mFontBitmapCachep->reset();
// Add the empty glyph
addGlyphFromFont(this, 0, 0);
// Adding default glyph is skipped for fallback fonts here as well as in loadFace().
// This if was added as fix for EXT-4971.
if(!mIsFallback)
{
// Add the empty glyph
addGlyphFromFont(this, 0, 0);
}
}
void LLFontFreetype::destroyGL()

View File

@ -601,14 +601,20 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
{
llwchar wch = wchars[i];
F32 char_width = mFontFreetype->getXAdvance(wch);
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
if( scaled_max_pixels < (total_width + char_width) )
// last character uses character width, since the whole character needs to be visible
// other characters just use advance
F32 width = (i == start)
? (F32)(fgi->mWidth + fgi->mXBearing) // use actual width for last character
: fgi->mXAdvance; // use advance for all other characters
if( scaled_max_pixels < (total_width + width) )
{
break;
}
total_width += char_width;
total_width += width;
drawable_chars++;
if( max_chars >= 0 && drawable_chars >= max_chars )
@ -626,7 +632,17 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
total_width = llround(total_width);
}
return start_pos - drawable_chars;
if (drawable_chars == 0)
{
return start_pos; // just draw last character
}
else
{
// if only 1 character is drawable, we want to return start_pos as the first character to draw
// if 2 are drawable, return start_pos and character before start_pos, etc.
return start_pos + 1 - drawable_chars;
}
}
S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round) const

View File

@ -90,6 +90,7 @@ set(llui_SOURCE_FILES
lltextbox.cpp
lltexteditor.cpp
lltextparser.cpp
lltextvalidate.cpp
lltransutil.cpp
lltoggleablemenu.cpp
lltooltip.cpp
@ -182,6 +183,7 @@ set(llui_HEADER_FILES
lltextbox.h
lltexteditor.h
lltextparser.h
lltextvalidate.h
lltoggleablemenu.h
lltooltip.h
lltransutil.h

View File

@ -81,10 +81,9 @@ LLButton::Params::Params()
image_pressed_selected("image_pressed_selected"),
image_overlay("image_overlay"),
image_overlay_alignment("image_overlay_alignment", std::string("center")),
image_left_pad("image_left_pad"),
image_right_pad("image_right_pad"),
image_top_pad("image_top_pad"),
image_bottom_pad("image_bottom_pad"),
imgoverlay_label_space("imgoverlay_label_space", 1),
label_color("label_color"),
label_color_selected("label_color_selected"), // requires is_toggle true
label_color_disabled("label_color_disabled"),
@ -144,10 +143,9 @@ LLButton::LLButton(const LLButton::Params& p)
mImageOverlay(p.image_overlay()),
mImageOverlayColor(p.image_overlay_color()),
mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)),
mImageOverlayLeftPad(p.image_left_pad),
mImageOverlayRightPad(p.image_right_pad),
mImageOverlayTopPad(p.image_top_pad),
mImageOverlayBottomPad(p.image_bottom_pad),
mImgOverlayLabelSpace(p.imgoverlay_label_space),
mIsToggle(p.is_toggle),
mScaleImage(p.scale_image),
mDropShadowedText(p.label_shadow),
@ -771,12 +769,7 @@ void LLButton::draw()
center_x++;
}
S32 text_width_delta = overlay_width + 1;
// if image paddings set, they should participate in scaling process
S32 image_size_delta = mImageOverlayTopPad + mImageOverlayBottomPad;
overlay_width = overlay_width - image_size_delta;
overlay_height = overlay_height - image_size_delta;
center_y += (mImageOverlayBottomPad - mImageOverlayTopPad);
// fade out overlay images on disabled buttons
LLColor4 overlay_color = mImageOverlayColor.get();
if (!enabled)
@ -788,10 +781,9 @@ void LLButton::draw()
switch(mImageOverlayAlignment)
{
case LLFontGL::LEFT:
text_left += overlay_width + mImageOverlayRightPad + 1;
text_width -= text_width_delta;
text_left += overlay_width + mImgOverlayLabelSpace;
mImageOverlay->draw(
mLeftHPad,
mLeftHPad,
center_y - (overlay_height / 2),
overlay_width,
overlay_height,
@ -806,10 +798,9 @@ void LLButton::draw()
overlay_color);
break;
case LLFontGL::RIGHT:
text_right -= overlay_width + mImageOverlayLeftPad+ 1;
text_width -= text_width_delta;
text_right -= overlay_width + mImgOverlayLabelSpace;
mImageOverlay->draw(
getRect().getWidth() - mRightHPad - overlay_width,
getRect().getWidth() - mRightHPad - overlay_width,
center_y - (overlay_height / 2),
overlay_width,
overlay_height,

View File

@ -107,11 +107,14 @@ public:
Optional<S32> pad_bottom; // under text label
//image overlay paddings
Optional<S32> image_left_pad;
Optional<S32> image_right_pad;
Optional<S32> image_top_pad;
Optional<S32> image_bottom_pad;
/**
* Space between image_overlay and label
*/
Optional<S32> imgoverlay_label_space;
// callbacks
Optional<CommitCallbackParam> click_callback, // alias -> commit_callback
mouse_down_callback,
@ -192,10 +195,6 @@ public:
void setLeftHPad( S32 pad ) { mLeftHPad = pad; }
void setRightHPad( S32 pad ) { mRightHPad = pad; }
void setImageOverlayLeftPad( S32 pad ) { mImageOverlayLeftPad = pad; }
S32 getImageOverlayLeftPad() const { return mImageOverlayLeftPad; }
void setImageOverlayRightPad( S32 pad ) { mImageOverlayRightPad = pad; }
S32 getImageOverlayRightPad() const { return mImageOverlayRightPad; }
void setImageOverlayTopPad( S32 pad ) { mImageOverlayTopPad = pad; }
S32 getImageOverlayTopPad() const { return mImageOverlayTopPad; }
void setImageOverlayBottomPad( S32 pad ) { mImageOverlayBottomPad = pad; }
@ -328,11 +327,14 @@ private:
S32 mRightHPad;
S32 mBottomVPad; // under text label
S32 mImageOverlayLeftPad;
S32 mImageOverlayRightPad;
S32 mImageOverlayTopPad;
S32 mImageOverlayBottomPad;
/*
* Space between image_overlay and label
*/
S32 mImgOverlayLabelSpace;
F32 mHoverGlowStrength;
F32 mCurGlowStrength;

View File

@ -244,23 +244,6 @@ void LLConsole::draw()
}
}
void LLConsole::addLine(const std::string& utf8line)
{
LLWString wline = utf8str_to_wstring(utf8line);
addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f));
}
void LLConsole::addLine(const LLWString& wline)
{
addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f));
}
void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color)
{
LLWString wline = utf8str_to_wstring(utf8line);
addLine(wline, size, color);
}
//Generate highlight color segments for this paragraph. Pass in default color of paragraph.
void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color)
{
@ -383,21 +366,45 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, b
//Pass in the string and the default color for this block of text.
LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width)
: mParagraphText(str), mAddTime(add_time), mMaxWidth(-1)
: mParagraphText(str), mAddTime(add_time), mMaxWidth(-1)
{
makeParagraphColorSegments(color);
updateLines( screen_width, font );
}
void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color)
// called once per frame regardless of console visibility
// static
void LLConsole::updateClass()
{
Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() );
mParagraphs.push_back ( paragraph );
LLInstanceTrackerScopedGuard guard;
for (instance_iter it = guard.beginInstances(); it != guard.endInstances(); ++it)
{
it->update();
}
}
void LLConsole::update()
{
{
LLMutexLock lock(&mMutex);
while (!mLines.empty())
{
mParagraphs.push_back(
Paragraph( mLines.front(),
LLColor4::white,
mTimer.getElapsedTimeF32(),
mFont,
(F32)getRect().getWidth()));
mLines.pop_front();
}
}
// remove old paragraphs which can't possibly be visible any more. ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called! (i.e. the console isn't visible)
while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines)))
{
mParagraphs.pop_front();
}
while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines)))
{
mParagraphs.pop_front();
}
}

View File

@ -40,7 +40,7 @@
class LLSD;
class LLConsole : public LLFixedBuffer, public LLUICtrl
class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker<LLConsole>
{
public:
typedef enum e_font_size
@ -68,6 +68,9 @@ protected:
friend class LLUICtrlFactory;
public:
// call once per frame to pull data out of LLFixedBuffer
static void updateClass();
//A paragraph color segment defines the color of text in a line
//of text that was received for console display. It has no
//notion of line wraps, screen position, or the text it contains.
@ -139,14 +142,12 @@ public:
// -1 = monospace, 0 means small, font size = 1 means big
void setFontSize(S32 size_index);
void addLine(const std::string& utf8line, F32 size, const LLColor4 &color);
void addLine(const LLWString& wline, F32 size, const LLColor4 &color);
// Overrides
/*virtual*/ void draw();
/*virtual*/ void addLine(const std::string& utf8line);
/*virtual*/ void addLine(const LLWString& line);
private:
void update();
F32 mLinePersistTime; // Age at which to stop drawing.
F32 mFadeTime; // Age at which to start fading
const LLFontGL* mFont;

View File

@ -95,7 +95,7 @@ void LLDockableFloater::toggleInstance(const LLSD& sdname)
LLDockableFloater* instance =
dynamic_cast<LLDockableFloater*> (LLFloaterReg::findInstance(name));
// if floater closed or docked
if (instance == NULL || instance != NULL && instance->isDocked())
if (instance == NULL || (instance && instance->isDocked()))
{
LLFloaterReg::toggleInstance(name, key);
// restore button toggle state
@ -223,10 +223,10 @@ void LLDockableFloater::draw()
LLFloater::draw();
}
void LLDockableFloater::setDockControl(LLDockControl* dockControl)
void LLDockableFloater::setDockControl(LLDockControl* dockControl, bool docked /* = true */)
{
mDockControl.reset(dockControl);
setDocked(mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
setDocked(docked && mDockControl.get() != NULL && mDockControl.get()->isDockVisible());
}
const LLUIImagePtr& LLDockableFloater::getDockTongue()

View File

@ -127,7 +127,7 @@ private:
void resetInstance();
protected:
void setDockControl(LLDockControl* dockControl);
void setDockControl(LLDockControl* dockControl, bool docked = true);
const LLUIImagePtr& getDockTongue();
private:

View File

@ -162,7 +162,9 @@ bool LLDockControl::isDockVisible()
{
case LEFT: // to keep compiler happy
break;
case BOTTOM:
case TOP:
{
// check is dock inside parent rect
LLRect dockParentRect =
mDockWidget->getParent()->calcScreenRect();
@ -173,6 +175,9 @@ bool LLDockControl::isDockVisible()
}
break;
}
default:
break;
}
}
}
@ -254,6 +259,42 @@ void LLDockControl::moveDockable()
}
mDockTongueY = dockRect.mTop;
break;
case BOTTOM:
x = dockRect.getCenterX() - dockableRect.getWidth() / 2;
y = dockRect.mBottom;
// unique docking used with dock tongue, so add tongue height o the Y coordinate
if (use_tongue)
{
y -= mDockTongue->getHeight();
}
// check is dockable inside root view rect
if (x < rootRect.mLeft)
{
x = rootRect.mLeft;
}
if (x + dockableRect.getWidth() > rootRect.mRight)
{
x = rootRect.mRight - dockableRect.getWidth();
}
// calculate dock tongue position
dockParentRect = mDockWidget->getParent()->calcScreenRect();
if (dockRect.getCenterX() < dockParentRect.mLeft)
{
mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
}
else if (dockRect.getCenterX() > dockParentRect.mRight)
{
mDockTongueX = dockParentRect.mRight - mDockTongue->getWidth() / 2;;
}
else
{
mDockTongueX = dockRect.getCenterX() - mDockTongue->getWidth() / 2;
}
mDockTongueY = dockRect.mBottom - mDockTongue->getHeight();
break;
}

View File

@ -47,8 +47,9 @@ class LLDockControl
public:
enum DocAt
{
TOP
,LEFT
TOP,
LEFT,
BOTTOM
};
public:

View File

@ -816,7 +816,10 @@ void LLLayoutStack::calcMinExtents()
//static
void LLLayoutStack::updateClass()
{
for (LLLayoutStack::instance_iter it = beginInstances(); it != endInstances(); ++it)
LLInstanceTrackerScopedGuard guard;
for (LLLayoutStack::instance_iter it = guard.beginInstances();
it != guard.endInstances();
++it)
{
it->updateLayout();
}

View File

@ -55,6 +55,7 @@
#include "llui.h"
#include "lluictrlfactory.h"
#include "llclipboard.h"
#include "llmenugl.h"
//
// Imported globals
@ -82,19 +83,6 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>(
// Member functions
//
void LLLineEditor::PrevalidateNamedFuncs::declareValues()
{
declare("ascii", LLLineEditor::prevalidateASCII);
declare("float", LLLineEditor::prevalidateFloat);
declare("int", LLLineEditor::prevalidateInt);
declare("positive_s32", LLLineEditor::prevalidatePositiveS32);
declare("non_negative_s32", LLLineEditor::prevalidateNonNegativeS32);
declare("alpha_num", LLLineEditor::prevalidateAlphaNum);
declare("alpha_num_space", LLLineEditor::prevalidateAlphaNumSpace);
declare("ascii_printable_no_pipe", LLLineEditor::prevalidateASCIIPrintableNoPipe);
declare("ascii_printable_no_space", LLLineEditor::prevalidateASCIIPrintableNoSpace);
}
LLLineEditor::Params::Params()
: max_length_bytes("max_length", 254),
keystroke_callback("keystroke_callback"),
@ -164,7 +152,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mTentativeFgColor(p.text_tentative_color()),
mHighlightColor(p.highlight_color()),
mPreeditBgColor(p.preedit_bg_color()),
mGLFont(p.font)
mGLFont(p.font),
mContextMenuHandle()
{
llassert( mMaxLengthBytes > 0 );
@ -191,6 +180,12 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
setCursor(mText.length());
setPrevalidate(p.prevalidate_callback());
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
("menu_text_editor.xml",
LLMenuGL::sMenuContainer,
LLMenuHolderGL::child_registry_t::instance());
setContextMenu(menu);
}
LLLineEditor::~LLLineEditor()
@ -422,12 +417,16 @@ void LLLineEditor::setCursor( S32 pos )
S32 old_cursor_pos = getCursor();
mCursorPos = llclamp( pos, 0, mText.length());
// position of end of next character after cursor
S32 pixels_after_scroll = findPixelNearestPos();
if( pixels_after_scroll > mTextRightEdge )
{
S32 width_chars_to_left = mGLFont->getWidth(mText.getWString().c_str(), 0, mScrollHPos);
S32 last_visible_char = mGLFont->maxDrawableChars(mText.getWString().c_str(), llmax(0.f, (F32)(mTextRightEdge - mTextLeftEdge + width_chars_to_left)));
S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), getCursor());
// character immediately to left of cursor should be last one visible (SCROLL_INCREMENT_ADD will scroll in more characters)
// or first character if cursor is at beginning
S32 new_last_visible_char = llmax(0, getCursor() - 1);
S32 min_scroll = mGLFont->firstDrawableChar(mText.getWString().c_str(), (F32)(mTextRightEdge - mTextLeftEdge), mText.length(), new_last_visible_char);
if (old_cursor_pos == last_visible_char)
{
mScrollHPos = llmin(mText.length(), llmax(min_scroll, mScrollHPos + SCROLL_INCREMENT_ADD));
@ -663,6 +662,16 @@ BOOL LLLineEditor::handleMiddleMouseDown(S32 x, S32 y, MASK mask)
return TRUE;
}
BOOL LLLineEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
setFocus(TRUE);
if (!LLUICtrl::handleRightMouseDown(x, y, mask))
{
showContextMenu(x, y);
}
return TRUE;
}
BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@ -1962,51 +1971,12 @@ void LLLineEditor::setRect(const LLRect& rect)
}
}
void LLLineEditor::setPrevalidate(LLLinePrevalidateFunc func)
void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func)
{
mPrevalidateFunc = func;
updateAllowingLanguageInput();
}
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
// static
BOOL LLLineEditor::prevalidateFloat(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
// May be a comma or period, depending on the locale
llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint();
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
// static
BOOL LLLineEditor::postvalidateFloat(const std::string &str)
{
@ -2066,223 +2036,6 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str)
return success;
}
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
// static
BOOL LLLineEditor::prevalidateInt(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
// static
BOOL LLLineEditor::prevalidatePositiveS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
BOOL success = TRUE;
if(0 < len)
{
if(('-' == trimmed[0]) || ('0' == trimmed[0]))
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val <= 0)
{
success = FALSE;
}
}
return success;
}
BOOL LLLineEditor::prevalidateNonNegativeS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
BOOL success = TRUE;
if(0 < len)
{
if('-' == trimmed[0])
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val < 0)
{
success = FALSE;
}
}
return success;
}
BOOL LLLineEditor::prevalidateAlphaNum(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if( !LLStringOps::isAlnum((char)str[len]) )
{
rv = FALSE;
break;
}
}
return rv;
}
// static
BOOL LLLineEditor::prevalidateAlphaNumSpace(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len])))
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for most names of things stored on the server, due to old file-formats
// that used the pipe (|) for multiline text storage. Examples include
// inventory item names, parcel names, object names, etc.
// static
BOOL LLLineEditor::prevalidateASCIIPrintableNoPipe(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| wc == '|')
{
rv = FALSE;
break;
}
if(!(wc == ' '
|| LLStringOps::isAlnum((char)wc)
|| LLStringOps::isPunct((char)wc) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for avatar names
// static
BOOL LLLineEditor::prevalidateASCIIPrintableNoSpace(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| LLStringOps::isSpace(wc))
{
rv = FALSE;
break;
}
if( !(LLStringOps::isAlnum((char)str[len]) ||
LLStringOps::isPunct((char)str[len]) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
// static
BOOL LLLineEditor::prevalidateASCII(const LLWString &str)
{
BOOL rv = TRUE;
S32 len = str.length();
while(len--)
{
if (str[len] < 0x20 || str[len] > 0x7f)
{
rv = FALSE;
break;
}
}
return rv;
}
void LLLineEditor::onMouseCaptureLost()
{
endSelection();
@ -2560,3 +2313,25 @@ LLWString LLLineEditor::getConvertedText() const
}
return text;
}
void LLLineEditor::showContextMenu(S32 x, S32 y)
{
LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get());
if (menu)
{
gEditMenuHandler = this;
S32 screen_x, screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
menu->show(screen_x, screen_y);
}
}
void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
{
if (new_context_menu)
mContextMenuHandle = new_context_menu->getHandle();
else
mContextMenuHandle.markDead();
}

View File

@ -51,26 +51,18 @@
#include "llviewborder.h"
#include "llpreeditor.h"
#include <boost/function.hpp>
#include "lltextvalidate.h"
class LLFontGL;
class LLLineEditorRollback;
class LLButton;
typedef boost::function<BOOL (const LLWString &wstr)> LLLinePrevalidateFunc;
class LLContextMenu;
class LLLineEditor
: public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor
{
public:
struct PrevalidateNamedFuncs
: public LLInitParam::TypeValuesHelper<LLLinePrevalidateFunc, PrevalidateNamedFuncs>
{
static void declareValues();
};
typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t;
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
@ -80,7 +72,7 @@ public:
Optional<keystroke_callback_t> keystroke_callback;
Optional<LLLinePrevalidateFunc, PrevalidateNamedFuncs> prevalidate_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
Optional<LLViewBorder::Params> border;
@ -113,6 +105,7 @@ protected:
LLLineEditor(const Params&);
friend class LLUICtrlFactory;
friend class LLFloaterEditUI;
void showContextMenu(S32 x, S32 y);
public:
virtual ~LLLineEditor();
@ -122,6 +115,7 @@ public:
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleDoubleClick(S32 x,S32 y,MASK mask);
/*virtual*/ BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleKeyHere(KEY key, MASK mask );
/*virtual*/ BOOL handleUnicodeCharHere(llwchar uni_char);
/*virtual*/ void onMouseCaptureLost();
@ -204,6 +198,8 @@ public:
const LLColor4& getReadOnlyFgColor() const { return mReadOnlyFgColor.get(); }
const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); }
const LLFontGL* getFont() const { return mGLFont; }
void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; }
void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
void setPassDelete(BOOL b) { mPassDelete = b; }
@ -231,17 +227,7 @@ public:
void setTextPadding(S32 left, S32 right);
// Prevalidation controls which keystrokes can affect the editor
void setPrevalidate( LLLinePrevalidateFunc func );
static BOOL prevalidateFloat(const LLWString &str );
static BOOL prevalidateInt(const LLWString &str );
static BOOL prevalidatePositiveS32(const LLWString &str);
static BOOL prevalidateNonNegativeS32(const LLWString &str);
static BOOL prevalidateAlphaNum(const LLWString &str );
static BOOL prevalidateAlphaNumSpace(const LLWString &str );
static BOOL prevalidateASCIIPrintableNoPipe(const LLWString &str);
static BOOL prevalidateASCIIPrintableNoSpace(const LLWString &str);
static BOOL prevalidateASCII(const LLWString &str);
void setPrevalidate( LLTextValidate::validate_func_t func );
static BOOL postvalidateFloat(const std::string &str);
// line history support:
@ -249,7 +235,9 @@ public:
void updateHistory(); // stores current line in history
void setReplaceNewlinesWithSpaces(BOOL replace);
void setContextMenu(LLContextMenu* new_context_menu);
private:
// private helper methods
@ -319,7 +307,7 @@ protected:
S32 mLastSelectionStart;
S32 mLastSelectionEnd;
LLLinePrevalidateFunc mPrevalidateFunc;
LLTextValidate::validate_func_t mPrevalidateFunc;
LLFrameTimer mKeystrokeTimer;
LLTimer mTripleClickTimer;
@ -348,6 +336,8 @@ protected:
std::vector<S32> mPreeditPositions;
LLPreeditor::standouts_t mPreeditStandouts;
LLHandle<LLView> mContextMenuHandle;
private:
// Instances that by default point to the statics but can be overidden in XML.
LLPointer<LLUIImage> mBgImage;

View File

@ -3941,7 +3941,6 @@ BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)
item = LLUICtrlFactory::create<LLContextMenuBranch>(p);
LLMenuGL::sMenuContainer->addChild(item->getBranch());
item->setFont( LLFontGL::getFontSansSerif() );
return append( item );
}

View File

@ -92,14 +92,6 @@ void LLMultiFloater::draw()
}
else
{
for (S32 i = 0; i < mTabContainer->getTabCount(); i++)
{
LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i);
if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i))
{
mTabContainer->setPanelTitle(i, floaterp->getShortTitle());
}
}
LLFloater::draw();
}
}

View File

@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
params.font(p.font);
params.max_length_bytes(MAX_STRING_LENGTH);
params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
params.prevalidate_callback(&LLLineEditor::prevalidateFloat);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) );
@ -330,9 +330,14 @@ void LLMultiSliderCtrl::updateText()
// static
void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata)
{
LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
llassert(ctrl);
if (!ctrl)
return;
LLMultiSliderCtrl* self = dynamic_cast<LLMultiSliderCtrl*>(ctrl->getParent());
llassert(self);
if (!self) // cast failed - wrong type! :O
return;
BOOL success = FALSE;
F32 val = self->mCurValue;

View File

@ -397,6 +397,12 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
if (!panelp)
{
panelp = LLUICtrlFactory::getInstance()->createFactoryPanel(name);
llassert(panelp);
if (!panelp)
{
return NULL; // :(
}
}
}
@ -414,7 +420,7 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLXMLNodePtr output_
panelp->mCommitCallbackRegistrar.popScope();
panelp->mEnableCallbackRegistrar.popScope();
if (panelp && !panelp->getFactoryMap().empty())
if (!panelp->getFactoryMap().empty())
{
LLUICtrlFactory::instance().popFactoryFunctions();
}
@ -936,7 +942,7 @@ LLPanel *LLPanel::childGetVisiblePanelWithHelp()
return ::childGetVisiblePanelWithHelp(this);
}
void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
void LLPanel::childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) )
{
LLLineEditor* child = findChild<LLLineEditor>(id);
if (child)

View File

@ -226,7 +226,7 @@ public:
std::string childGetText(const std::string& id) const { return childGetValue(id).asString(); }
// LLLineEditor
void childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) );
void childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) );
// LLButton
void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value = NULL);

View File

@ -1388,6 +1388,8 @@ void LLScrollListCtrl::drawItems()
LLGLSUIDefault gls_ui;
F32 alpha = getDrawContext().mAlpha;
{
LLLocalClipRect clip(mItemListRect);
@ -1463,7 +1465,7 @@ void LLScrollListCtrl::drawItems()
bg_color = mBgReadOnlyColor.get();
}
item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding);
item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding);
cur_y -= mLineHeight;
}

View File

@ -60,6 +60,7 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
line_editor_params.keystroke_callback(boost::bind(&LLSearchEditor::handleKeystroke, this));
mSearchEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_params);
mSearchEditor->setPassDelete(TRUE);
addChild(mSearchEditor);
if (p.search_button_visible)
@ -79,10 +80,12 @@ LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
if (p.clear_button_visible)
{
// Set up clear button.
S32 clr_btn_width = getRect().getHeight(); // button is square, and as tall as search editor
LLRect clear_btn_rect(getRect().getWidth() - clr_btn_width, getRect().getHeight(), getRect().getWidth(), 0);
LLButton::Params clr_btn_params(p.clear_button);
clr_btn_params.name(std::string("clear button"));
S32 clr_btn_top = clr_btn_params.rect.bottom + clr_btn_params.rect.height;
S32 clr_btn_right = getRect().getWidth() - clr_btn_params.pad_right;
S32 clr_btn_left = clr_btn_right - clr_btn_params.rect.width;
LLRect clear_btn_rect(clr_btn_left, clr_btn_top, clr_btn_right, p.clear_button.rect.bottom);
clr_btn_params.rect(clear_btn_rect) ;
clr_btn_params.follows.flags(FOLLOWS_RIGHT|FOLLOWS_TOP);
clr_btn_params.tab_stop(false);

View File

@ -141,7 +141,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p)
line_p.rect.setIfNotProvided(text_rect);
line_p.font.setIfNotProvided(p.font);
line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit);
line_p.prevalidate_callback(&LLLineEditor::prevalidateFloat);
line_p.prevalidate_callback(&LLTextValidate::validateFloat);
mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p);
mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this ));

View File

@ -127,7 +127,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
}
params.max_length_bytes(MAX_STRING_LENGTH);
params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
params.prevalidate_callback(&LLLineEditor::prevalidateFloat);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this ));

View File

@ -35,7 +35,6 @@
#include "lltabcontainer.h"
#include "llfocusmgr.h"
#include "llbutton.h"
#include "lllocalcliprect.h"
#include "llrect.h"
#include "llresizehandle.h"
@ -96,6 +95,91 @@ public:
//----------------------------------------------------------------------------
//============================================================================
/*
* @file lltabcontainer.cpp
* @brief class implements LLButton with LLIconCtrl on it
*/
class LLCustomButtonIconCtrl : public LLButton
{
public:
struct Params
: public LLInitParam::Block<Params, LLButton::Params>
{
// LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value
Optional<S32> icon_ctrl_pad;
Params():
icon_ctrl_pad("icon_ctrl_pad", 1)
{}
};
protected:
friend class LLUICtrlFactory;
LLCustomButtonIconCtrl(const Params& p):
LLButton(p),
mIcon(NULL),
mIconAlignment(LLFontGL::HCENTER),
mIconCtrlPad(p.icon_ctrl_pad)
{}
public:
void updateLayout()
{
LLRect button_rect = getRect();
LLRect icon_rect = mIcon->getRect();
S32 icon_size = button_rect.getHeight() - 2*mIconCtrlPad;
switch(mIconAlignment)
{
case LLFontGL::LEFT:
icon_rect.setLeftTopAndSize(button_rect.mLeft + mIconCtrlPad, button_rect.mTop - mIconCtrlPad,
icon_size, icon_size);
setLeftHPad(icon_size + mIconCtrlPad * 2);
break;
case LLFontGL::HCENTER:
icon_rect.setLeftTopAndSize(button_rect.mRight - (button_rect.getWidth() + mIconCtrlPad - icon_size)/2, button_rect.mTop - mIconCtrlPad,
icon_size, icon_size);
setRightHPad(icon_size + mIconCtrlPad * 2);
break;
case LLFontGL::RIGHT:
icon_rect.setLeftTopAndSize(button_rect.mRight - mIconCtrlPad - icon_size, button_rect.mTop - mIconCtrlPad,
icon_size, icon_size);
setRightHPad(icon_size + mIconCtrlPad * 2);
break;
default:
break;
}
mIcon->setRect(icon_rect);
}
void setIcon(LLIconCtrl* icon, LLFontGL::HAlign alignment = LLFontGL::LEFT)
{
if(icon)
{
if(mIcon)
{
removeChild(mIcon);
mIcon->die();
}
mIcon = icon;
mIconAlignment = alignment;
addChild(mIcon);
updateLayout();
}
}
private:
LLIconCtrl* mIcon;
LLFontGL::HAlign mIconAlignment;
S32 mIconCtrlPad;
};
//============================================================================
struct LLPlaceHolderPanel : public LLPanel
{
// create dummy param block to register with "placeholder" nane
@ -127,7 +211,10 @@ LLTabContainer::Params::Params()
tab_padding_right("tab_padding_right"),
first_tab("first_tab"),
middle_tab("middle_tab"),
last_tab("last_tab")
last_tab("last_tab"),
use_custom_icon_ctrl("use_custom_icon_ctrl", false),
tab_icon_ctrl_pad("tab_icon_ctrl_pad", 0),
use_ellipses("use_ellipses")
{
name(std::string("tab_container"));
mouse_opaque = false;
@ -162,7 +249,10 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mFont(p.font),
mFirstTabParams(p.first_tab),
mMiddleTabParams(p.middle_tab),
mLastTabParams(p.last_tab)
mLastTabParams(p.last_tab),
mCustomIconCtrlUsed(p.use_custom_icon_ctrl),
mTabIconCtrlPad(p.tab_icon_ctrl_pad),
mUseTabEllipses(p.use_ellipses)
{
static LLUICachedControl<S32> tabcntr_vert_tab_min_width ("UITabCntrVertTabMinWidth", 0);
@ -801,6 +891,10 @@ void LLTabContainer::update_images(LLTabTuple* tuple, TabParams params, LLTabCon
void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
LLPanel* child = panel.panel();
llassert(child);
if (!child) return;
const std::string& label = panel.label.isProvided()
? panel.label()
: panel.panel()->getLabel();
@ -905,6 +999,11 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
LLTextBox* textbox = NULL;
LLButton* btn = NULL;
LLCustomButtonIconCtrl::Params custom_btn_params;
{
custom_btn_params.icon_ctrl_pad(mTabIconCtrlPad);
}
LLButton::Params normal_btn_params;
if (placeholder)
{
@ -924,7 +1023,9 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
if (mIsVertical)
{
LLButton::Params p;
LLButton::Params& p = (mCustomIconCtrlUsed)?
custom_btn_params:normal_btn_params;
p.name(std::string("vert tab button"));
p.rect(btn_rect);
p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
@ -942,11 +1043,22 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
p.pad_left(indent);
}
btn = LLUICtrlFactory::create<LLButton>(p);
if(mCustomIconCtrlUsed)
{
btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
}
else
{
btn = LLUICtrlFactory::create<LLButton>(p);
}
}
else
{
LLButton::Params p;
LLButton::Params& p = (mCustomIconCtrlUsed)?
custom_btn_params:normal_btn_params;
p.name(std::string(child->getName()) + " tab");
p.rect(btn_rect);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
@ -980,7 +1092,14 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
}
++ btn = LLUICtrlFactory::create<LLButton>(p);
if(mCustomIconCtrlUsed)
{
btn = LLUICtrlFactory::create<LLCustomButtonIconCtrl>(custom_btn_params);
}
else
{
btn = LLUICtrlFactory::create<LLButton>(p);
}
}
}
@ -1373,8 +1492,8 @@ BOOL LLTabContainer::setTab(S32 which)
{
LLTabTuple* tuple = *iter;
BOOL is_selected = ( tuple == selected_tuple );
tuple->mButton->setUseEllipses(TRUE);
tuple->mButton->setHAlign(LLFontGL::LEFT);
tuple->mButton->setUseEllipses(mUseTabEllipses);
tuple->mButton->setHAlign(mFontHalign);
tuple->mTabPanel->setVisible( is_selected );
// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
tuple->mButton->setToggleState( is_selected );
@ -1484,7 +1603,7 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
if( tuple )
{
tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color);
reshape_tuple(tuple);
reshapeTuple(tuple);
}
}
@ -1494,25 +1613,31 @@ void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const L
if( tuple )
{
tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color);
reshape_tuple(tuple);
reshapeTuple(tuple);
}
}
void LLTabContainer::reshape_tuple(LLTabTuple* tuple)
void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon)
{
LLTabTuple* tuple = getTabByPanel(child);
LLCustomButtonIconCtrl* button;
if(tuple)
{
button = dynamic_cast<LLCustomButtonIconCtrl*>(tuple->mButton);
if(button)
{
button->setIcon(icon);
}
}
}
void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
{
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
static LLUICachedControl<S32> image_left_padding ("UIButtonImageLeftPadding", 4);
static LLUICachedControl<S32> image_right_padding ("UIButtonImageRightPadding", 4);
static LLUICachedControl<S32> image_top_padding ("UIButtonImageTopPadding", 2);
static LLUICachedControl<S32> image_bottom_padding ("UIButtonImageBottomPadding", 2);
if (!mIsVertical)
{
tuple->mButton->setImageOverlayLeftPad(image_left_padding);
tuple->mButton->setImageOverlayRightPad(image_right_padding);
tuple->mButton->setImageOverlayTopPad(image_top_padding);
tuple->mButton->setImageOverlayBottomPad(image_bottom_padding);
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();

View File

@ -36,6 +36,8 @@
#include "llpanel.h"
#include "lltextbox.h"
#include "llframetimer.h"
#include "lliconctrl.h"
#include "llbutton.h"
class LLTabTuple;
@ -90,6 +92,26 @@ public:
middle_tab,
last_tab;
/**
* Tab label horizontal alignment
*/
Optional<LLFontGL::HAlign> font_halign;
/**
* Tab label ellipses
*/
Optional<bool> use_ellipses;
/**
* Use LLCustomButtonIconCtrl or LLButton in LLTabTuple
*/
Optional<bool> use_custom_icon_ctrl;
/**
* Paddings for LLIconCtrl in case of LLCustomButtonIconCtrl usage(use_custom_icon_ctrl = true)
*/
Optional<S32> tab_icon_ctrl_pad;
Params();
};
@ -173,6 +195,7 @@ public:
void setTabPanelFlashing(LLPanel* child, BOOL state);
void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
void setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);
void setTabImage(LLPanel* child, LLIconCtrl* icon);
void setTitle( const std::string& title );
const std::string getPanelTitle(S32 index);
@ -228,7 +251,7 @@ private:
// updates tab button images given the tuple, tab position and the corresponding params
void update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos);
void reshape_tuple(LLTabTuple* tuple);
void reshapeTuple(LLTabTuple* tuple);
// Variables
@ -278,6 +301,10 @@ private:
TabParams mFirstTabParams;
TabParams mMiddleTabParams;
TabParams mLastTabParams;
bool mCustomIconCtrlUsed;
S32 mTabIconCtrlPad;
bool mUseTabEllipses;
};
#endif // LL_TABCONTAINER_H

View File

@ -1137,6 +1137,7 @@ void LLTextBase::reflow()
line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare());
line_start_index = iter->mDocIndexStart;
line_count = iter->mLineNum;
cur_top = iter->mRect.mTop;
getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset);
mLineInfoList.erase(iter, mLineInfoList.end());
}
@ -1574,8 +1575,10 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
{
LLStyle::Params icon;
icon.image = image;
// HACK: fix spacing of images and remove the fixed char spacing
appendAndHighlightText(" ", prepend_newline, part, icon);
// Text will be replaced during rendering with the icon,
// but string cannot be empty or the segment won't be
// added (or drawn).
appendAndHighlightText(" ", prepend_newline, part, icon);
prepend_newline = false;
}
}
@ -2296,14 +2299,21 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec
{
if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart))
{
// ...for images, only render the image, not the underlying text,
// which is only a placeholder space
LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha;
LLUIImagePtr image = mStyle->getImage();
S32 style_image_height = image->getHeight();
S32 style_image_width = image->getWidth();
// Center the image vertically
S32 image_bottom = draw_rect.getCenterY() - (style_image_height/2);
// Text is drawn from the top of the draw_rect downward
S32 text_center = draw_rect.mTop - (mFontHeight / 2);
// Align image to center of text
S32 image_bottom = text_center - (style_image_height / 2);
image->draw(draw_rect.mLeft, image_bottom,
style_image_width, style_image_height, color);
const S32 IMAGE_HPAD = 3;
return draw_rect.mLeft + style_image_width + IMAGE_HPAD;
}
return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect);

View File

@ -237,13 +237,17 @@ private:
///////////////////////////////////////////////////////////////////
LLTextEditor::Params::Params()
: default_text("default_text"),
prevalidate_callback("prevalidate_callback"),
embedded_items("embedded_items", false),
ignore_tab("ignore_tab", true),
handle_edit_keys_directly("handle_edit_keys_directly", false),
show_line_numbers("show_line_numbers", false),
default_color("default_color"),
commit_on_focus_lost("commit_on_focus_lost", false)
{}
commit_on_focus_lost("commit_on_focus_lost", false),
show_context_menu("show_context_menu")
{
addSynonym(prevalidate_callback, "text_type");
}
LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
LLTextBase(p),
@ -258,7 +262,9 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mMouseDownX(0),
mMouseDownY(0),
mTabsToNextField(p.ignore_tab),
mContextMenu(NULL)
mPrevalidateFunc(p.prevalidate_callback()),
mContextMenu(NULL),
mShowContextMenu(p.show_context_menu)
{
mDefaultFont = p.font;
@ -318,6 +324,17 @@ LLTextEditor::~LLTextEditor()
void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params)
{
// validate incoming text if necessary
if (mPrevalidateFunc)
{
LLWString test_text = utf8str_to_wstring(utf8str);
if (!mPrevalidateFunc(test_text))
{
// not valid text, nothing to do
return;
}
}
blockUndo();
deselect();
@ -720,7 +737,7 @@ BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
}
if (!LLTextBase::handleRightMouseDown(x, y, mask))
{
if(getMouseOpaque())
if(getShowContextMenu())
{
showContextMenu(x, y);
}
@ -909,6 +926,21 @@ S32 LLTextEditor::execute( TextCmd* cmd )
// Push the new command is now on the top (front) of the undo stack.
mUndoStack.push_front(cmd);
mLastCmd = cmd;
bool need_to_rollback = mPrevalidateFunc
&& !mPrevalidateFunc(getViewModel()->getDisplay());
if (need_to_rollback)
{
// get rid of this last command and clean up undo stack
undo();
// remove any evidence of this command from redo history
mUndoStack.pop_front();
delete cmd;
// failure, nothing changed
delta = 0;
}
}
else
{
@ -1032,7 +1064,21 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc)
if (mLastCmd && mLastCmd->canExtend(pos))
{
S32 delta = 0;
if (mPrevalidateFunc)
{
// get a copy of current text contents
LLWString test_string(getViewModel()->getDisplay());
// modify text contents as if this addChar succeeded
llassert(pos <= (S32)test_string.size());
test_string.insert(pos, 1, wc);
if (!mPrevalidateFunc( test_string))
{
return 0;
}
}
mLastCmd->extendAndExecute(this, pos, wc, &delta);
return delta;
}
else
@ -2478,9 +2524,9 @@ void LLTextEditor::loadKeywords(const std::string& filename,
void LLTextEditor::updateSegments()
{
LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING);
if (mKeywords.isLoaded())
if (mReflowIndex < S32_MAX && mKeywords.isLoaded())
{
LLFastTimer ft(FTM_SYNTAX_HIGHLIGHTING);
// HACK: No non-ascii keywords for now
segment_vec_t segment_list;
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this);

View File

@ -44,6 +44,7 @@
#include "lldarray.h"
#include "llviewborder.h" // for params
#include "lltextbase.h"
#include "lltextvalidate.h"
#include "llpreeditor.h"
#include "llcontrol.h"
@ -63,12 +64,14 @@ public:
struct Params : public LLInitParam::Block<Params, LLTextBase::Params>
{
Optional<std::string> default_text;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
Optional<bool> embedded_items,
ignore_tab,
handle_edit_keys_directly,
show_line_numbers,
commit_on_focus_lost;
commit_on_focus_lost,
show_context_menu;
//colors
Optional<LLUIColor> default_color;
@ -200,6 +203,9 @@ public:
const LLTextSegmentPtr getPreviousSegment() const;
void getSelectedSegments(segment_vec_t& segments) const;
void setShowContextMenu(bool show) { mShowContextMenu = show; }
bool getShowContextMenu() const { return mShowContextMenu; }
protected:
void showContextMenu(S32 x, S32 y);
void drawPreeditMarker();
@ -319,6 +325,7 @@ private:
BOOL mTakesFocus;
BOOL mAllowEmbeddedItems;
bool mShowContextMenu;
LLUUID mSourceID;
@ -329,6 +336,7 @@ private:
LLCoordGL mLastIMEPosition; // Last position of the IME editor
keystroke_signal_t mKeystrokeSignal;
LLTextValidate::validate_func_t mPrevalidateFunc;
LLContextMenu* mContextMenu;
}; // end class LLTextEditor

View File

@ -0,0 +1,302 @@
/**
* @file lltextvalidate.cpp
* @brief Text validation helper functions
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
// Text editor widget to let users enter a single line.
#include "linden_common.h"
#include "lltextvalidate.h"
#include "llresmgr.h" // for LLLocale
namespace LLTextValidate
{
void ValidateTextNamedFuncs::declareValues()
{
declare("ascii", validateASCII);
declare("float", validateFloat);
declare("int", validateInt);
declare("positive_s32", validatePositiveS32);
declare("non_negative_s32", validateNonNegativeS32);
declare("alpha_num", validateAlphaNum);
declare("alpha_num_space", validateAlphaNumSpace);
declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe);
declare("ascii_printable_no_space", validateASCIIPrintableNoSpace);
}
// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
bool validateFloat(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
// May be a comma or period, depending on the locale
llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint();
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
// Limits what characters can be used to [1234567890-] with [-] only valid in the first position.
// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for
// the simple reasons that intermediate states may be invalid even if the final result is valid.
//
bool validateInt(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool success = TRUE;
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
if( 0 < len )
{
S32 i = 0;
// First character can be a negative sign
if( '-' == trimmed[0] )
{
i++;
}
for( ; i < len; i++ )
{
if( !LLStringOps::isDigit( trimmed[i] ) )
{
success = FALSE;
break;
}
}
}
return success;
}
bool validatePositiveS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
bool success = TRUE;
if(0 < len)
{
if(('-' == trimmed[0]) || ('0' == trimmed[0]))
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val <= 0)
{
success = FALSE;
}
}
return success;
}
bool validateNonNegativeS32(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
LLWString trimmed = str;
LLWStringUtil::trim(trimmed);
S32 len = trimmed.length();
bool success = TRUE;
if(0 < len)
{
if('-' == trimmed[0])
{
success = FALSE;
}
S32 i = 0;
while(success && (i < len))
{
if(!LLStringOps::isDigit(trimmed[i++]))
{
success = FALSE;
}
}
}
if (success)
{
S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10);
if (val < 0)
{
success = FALSE;
}
}
return success;
}
bool validateAlphaNum(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if( !LLStringOps::isAlnum((char)str[len]) )
{
rv = FALSE;
break;
}
}
return rv;
}
bool validateAlphaNumSpace(const LLWString &str)
{
LLLocale locale(LLLocale::USER_LOCALE);
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len])))
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for most names of things stored on the server, due to old file-formats
// that used the pipe (|) for multiline text storage. Examples include
// inventory item names, parcel names, object names, etc.
bool validateASCIIPrintableNoPipe(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| wc == '|')
{
rv = FALSE;
break;
}
if(!(wc == ' '
|| LLStringOps::isAlnum((char)wc)
|| LLStringOps::isPunct((char)wc) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
// Used for avatar names
bool validateASCIIPrintableNoSpace(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
if(len == 0) return rv;
while(len--)
{
llwchar wc = str[len];
if (wc < 0x20
|| wc > 0x7f
|| LLStringOps::isSpace(wc))
{
rv = FALSE;
break;
}
if( !(LLStringOps::isAlnum((char)str[len]) ||
LLStringOps::isPunct((char)str[len]) ) )
{
rv = FALSE;
break;
}
}
return rv;
}
bool validateASCII(const LLWString &str)
{
bool rv = TRUE;
S32 len = str.length();
while(len--)
{
if (str[len] < 0x20 || str[len] > 0x7f)
{
rv = FALSE;
break;
}
}
return rv;
}
}

View File

@ -0,0 +1,63 @@
/**
* @file lltextbase.h
* @author Martin Reddy
* @brief The base class of text box/editor, providing Url handling support
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
* Copyright (c) 2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLTEXTVALIDATE_H
#define LL_LLTEXTVALIDATE_H
#include "llstring.h"
#include "llinitparam.h"
#include <boost/function.hpp>
namespace LLTextValidate
{
typedef boost::function<BOOL (const LLWString &wstr)> validate_func_t;
struct ValidateTextNamedFuncs
: public LLInitParam::TypeValuesHelper<validate_func_t, ValidateTextNamedFuncs>
{
static void declareValues();
};
bool validateFloat(const LLWString &str );
bool validateInt(const LLWString &str );
bool validatePositiveS32(const LLWString &str);
bool validateNonNegativeS32(const LLWString &str);
bool validateAlphaNum(const LLWString &str );
bool validateAlphaNumSpace(const LLWString &str );
bool validateASCIIPrintableNoPipe(const LLWString &str);
bool validateASCIIPrintableNoSpace(const LLWString &str);
bool validateASCII(const LLWString &str);
}
#endif

View File

@ -129,12 +129,6 @@ BOOL LLToolTipView::handleScrollWheel( S32 x, S32 y, S32 clicks )
return FALSE;
}
void LLToolTipView::onMouseLeave(S32 x, S32 y, MASK mask)
{
LLToolTipMgr::instance().blockToolTips();
}
void LLToolTipView::drawStickyRect()
{
gl_rect_2d(LLToolTipMgr::instance().getMouseNearRect(), LLColor4::white, false);

View File

@ -56,8 +56,6 @@ public:
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
void drawStickyRect();
/*virtual*/ void draw();
@ -129,7 +127,8 @@ private:
class LLInspector : public LLToolTip
{
public:
struct Params : public LLInitParam::Block<Params, LLToolTip::Params> {};
struct Params : public LLInitParam::Block<Params, LLToolTip::Params>
{};
};
class LLToolTipMgr : public LLSingleton<LLToolTipMgr>

View File

@ -1894,7 +1894,9 @@ namespace LLInitParam
blue("blue"),
alpha("alpha"),
control("")
{}
{
setBlockFromValue();
}
void TypedParam<LLUIColor>::setValueFromBlock() const
{
@ -1939,6 +1941,7 @@ namespace LLInitParam
size("size"),
style("style")
{
setBlockFromValue();
addSynonym(name, "");
}
@ -1979,7 +1982,9 @@ namespace LLInitParam
bottom("bottom"),
width("width"),
height("height")
{}
{
setBlockFromValue();
}
void TypedParam<LLRect>::setValueFromBlock() const
{
@ -2064,6 +2069,7 @@ namespace LLInitParam
x("x"),
y("y")
{
setBlockFromValue();
}
void TypedParam<LLCoordGL>::setValueFromBlock() const

View File

@ -426,8 +426,8 @@ namespace LLInitParam
{
typedef BlockValue<const LLFontGL*> super_t;
public:
Mandatory<std::string> name;
Optional<std::string> size,
Optional<std::string> name,
size,
style;
TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count);

View File

@ -56,7 +56,7 @@ LLUIColorTable::Params::Params()
{
}
void LLUIColorTable::insertFromParams(const Params& p)
void LLUIColorTable::insertFromParams(const Params& p, string_color_map_t& table)
{
// this map will contain all color references after the following loop
typedef std::map<std::string, std::string> string_string_map_t;
@ -69,14 +69,7 @@ void LLUIColorTable::insertFromParams(const Params& p)
ColorEntryParams color_entry = *it;
if(color_entry.color.value.isChosen())
{
if(mUserSetColors.find(color_entry.name)!=mUserSetColors.end())
{
setColor(color_entry.name, color_entry.color.value);
}
else
{
setColor(color_entry.name, color_entry.color.value, mLoadedColors);
}
setColor(color_entry.name, color_entry.color.value, table);
}
else
{
@ -220,16 +213,16 @@ bool LLUIColorTable::loadFromSettings()
bool result = false;
std::string default_filename = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "colors.xml");
result |= loadFromFilename(default_filename);
result |= loadFromFilename(default_filename, mLoadedColors);
std::string current_filename = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, "colors.xml");
if(current_filename != default_filename)
{
result |= loadFromFilename(current_filename);
result |= loadFromFilename(current_filename, mLoadedColors);
}
std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml");
loadFromFilename(user_filename);
loadFromFilename(user_filename, mUserSetColors);
return result;
}
@ -299,7 +292,7 @@ void LLUIColorTable::setColor(const std::string& name, const LLColor4& color, st
}
}
bool LLUIColorTable::loadFromFilename(const std::string& filename)
bool LLUIColorTable::loadFromFilename(const std::string& filename, string_color_map_t& table)
{
LLXMLNodePtr root;
@ -320,7 +313,7 @@ bool LLUIColorTable::loadFromFilename(const std::string& filename)
if(params.validateBlock())
{
insertFromParams(params);
insertFromParams(params, table);
}
else
{
@ -330,3 +323,11 @@ bool LLUIColorTable::loadFromFilename(const std::string& filename)
return true;
}
void LLUIColorTable::insertFromParams(const Params& p)
{
insertFromParams(p, mUserSetColors);
}
// EOF

View File

@ -45,6 +45,10 @@ class LLUIColor;
class LLUIColorTable : public LLSingleton<LLUIColorTable>
{
LOG_CLASS(LLUIColorTable);
// consider using sorted vector, can be much faster
typedef std::map<std::string, LLUIColor> string_color_map_t;
public:
struct ColorParams : LLInitParam::Choice<ColorParams>
{
@ -91,10 +95,9 @@ public:
void saveUserSettings() const;
private:
bool loadFromFilename(const std::string& filename);
bool loadFromFilename(const std::string& filename, string_color_map_t& table);
// consider using sorted vector, can be much faster
typedef std::map<std::string, LLUIColor> string_color_map_t;
void insertFromParams(const Params& p, string_color_map_t& table);
void clearTable(string_color_map_t& table);
void setColor(const std::string& name, const LLColor4& color, string_color_map_t& table);

View File

@ -109,6 +109,7 @@ namespace LLInitParam
TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
: super_t(descriptor, name, value, func, min_count, max_count)
{
setBlockFromValue();
}
void setValueFromBlock() const;

View File

@ -290,7 +290,7 @@ std::string LLUrlEntrySLURL::getLabel(const std::string &url, const LLUrlLabelCa
std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
{
// return the part of the Url after slurl.com/secondlife/
const std::string search_string = "secondlife";
const std::string search_string = "/secondlife";
size_t pos = url.find(search_string);
if (pos == std::string::npos)
{

View File

@ -1720,6 +1720,7 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
LLView* childp = *child_it;
llassert(childp);
if (childp->getName() == name)
{
return childp;
@ -1731,6 +1732,7 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const
for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
{
LLView* childp = *child_it;
llassert(childp);
LLView* viewp = childp->findChildView(name, recurse);
if ( viewp )
{

View File

@ -638,7 +638,7 @@ void LLDir::setSkinFolder(const std::string &skin_folder)
// e.g. c:\program files\secondlife\skins\default
mDefaultSkinDir = getSkinBaseDir();
mDefaultSkinDir += mDirDelimiter;
mDefaultSkinDir += "default";
mDefaultSkinDir += "base";
}
bool LLDir::setCacheDir(const std::string &path)

View File

@ -113,6 +113,7 @@ if (WINDOWS)
)
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
ole32
)
endif (WINDOWS)

View File

@ -50,7 +50,8 @@ class LLDragDropWin32Target:
LLDragDropWin32Target( HWND hWnd ) :
mRefCount( 1 ),
mAppWindowHandle( hWnd ),
mAllowDrop( false)
mAllowDrop(false),
mIsSlurl(false)
{
};

View File

@ -37,6 +37,7 @@
#include "llcoord.h"
#include "llstring.h"
#include "llcursortypes.h"
#include "llsd.h"
class LLSplashScreen;
class LLPreeditor;
@ -162,6 +163,9 @@ public:
virtual void spawnWebBrowser(const std::string& escaped_url) {};
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); }
protected:
LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);

View File

@ -260,6 +260,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
mTSMScriptCode = 0;
mTSMLangCode = 0;
mPreeditor = NULL;
mRawKeyEvent = NULL;
mFSAASamples = fsaa_samples;
mForceRebuild = FALSE;
@ -2140,10 +2141,11 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
{
UInt32 modifiers = 0;
// First, process the raw event.
{
EventRef rawEvent;
EventRef rawEvent = NULL;
// Get the original event and extract the modifier keys, so we can ignore command-key events.
if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr)
{
@ -2152,6 +2154,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
// and call this function recursively to handle the raw key event.
eventHandler (myHandler, rawEvent);
// save the raw event until we're done processing the unicode input as well.
mRawKeyEvent = rawEvent;
}
}
@ -2202,6 +2207,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
delete[] buffer;
}
mRawKeyEvent = NULL;
result = err;
}
break;
@ -2276,6 +2282,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
// save the raw event so getNativeKeyData can use it.
mRawKeyEvent = event;
// printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers);
// fflush(stdout);
@ -2371,6 +2380,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
result = eventNotHandledErr;
break;
}
mRawKeyEvent = NULL;
}
break;
@ -3211,6 +3222,60 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url)
}
}
LLSD LLWindowMacOSX::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
if(mRawKeyEvent)
{
char char_code = 0;
UInt32 key_code = 0;
UInt32 modifiers = 0;
UInt32 keyboard_type = 0;
GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code);
GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code);
GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type);
result["char_code"] = (S32)char_code;
result["key_code"] = (S32)key_code;
result["modifiers"] = (S32)modifiers;
result["keyboard_type"] = (S32)keyboard_type;
#if 0
// This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc)
// cause llsd serialization to create XML that the llsd deserializer won't parse!
std::string unicode;
OSStatus err = noErr;
EventParamType actualType = typeUTF8Text;
UInt32 actualSize = 0;
char *buffer = NULL;
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL);
if(err == noErr)
{
// allocate a buffer and get the actual data.
buffer = new char[actualSize];
err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer);
if(err == noErr)
{
unicode.assign(buffer, actualSize);
}
delete[] buffer;
}
result["unicode"] = unicode;
#endif
}
lldebugs << "native key data is: " << result << llendl;
return result;
}
BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{

View File

@ -120,6 +120,10 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
// Provide native key event data
/*virtual*/ LLSD getNativeKeyData();
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
@ -218,6 +222,7 @@ protected:
friend class LLWindowManager;
static WindowRef sMediaWindow;
EventRef mRawKeyEvent;
};

View File

@ -251,6 +251,10 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
#if LL_X11
mFlashing = FALSE;
#endif // LL_X11
mKeyScanCode = 0;
mKeyVirtualKey = 0;
mKeyModifiers = KMOD_NONE;
}
static SDL_Surface *Load_BMP_Resource(const char *basename)
@ -1617,7 +1621,7 @@ void LLWindowSDL::processMiscNativeEvents()
pump_timer.setTimerExpirySec(1.0f / 15.0f);
do {
// Always do at least one non-blocking pump
gtk_main_iteration_do(0);
gtk_main_iteration_do(FALSE);
} while (gtk_events_pending() &&
!pump_timer.hasExpired());
@ -1651,24 +1655,32 @@ void LLWindowSDL::gatherInput()
}
case SDL_KEYDOWN:
gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
// part of the fix for SL-13243
if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
SDLReallyCaptureInput(TRUE);
mKeyScanCode = event.key.keysym.scancode;
mKeyVirtualKey = event.key.keysym.unicode;
mKeyModifiers = event.key.keysym.mod;
if (event.key.keysym.unicode)
{
handleUnicodeUTF16(event.key.keysym.unicode,
gKeyboard->currentMask(FALSE));
}
gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod);
// part of the fix for SL-13243
if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0)
SDLReallyCaptureInput(TRUE);
if (event.key.keysym.unicode)
{
handleUnicodeUTF16(event.key.keysym.unicode,
gKeyboard->currentMask(FALSE));
}
break;
case SDL_KEYUP:
if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
mKeyScanCode = event.key.keysym.scancode;
mKeyVirtualKey = event.key.keysym.unicode;
mKeyModifiers = event.key.keysym.mod;
gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
break;
if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0)
SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243
gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod);
break;
case SDL_MOUSEBUTTONDOWN:
{
@ -2224,6 +2236,39 @@ static void color_changed_callback(GtkWidget *widget,
gtk_color_selection_get_current_color(colorsel, colorp);
}
/*
Make the raw keyboard data available - used to poke through to LLQtWebKit so
that Qt/Webkit has access to the virtual keycodes etc. that it needs
*/
LLSD LLWindowSDL::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave!
// we go through so many levels of device abstraction that I can't really guess
// what a plugin under GDK under Qt under SL under SDL under X11 considers
// a 'native' modifier mask. this has been sort of reverse-engineered... they *appear*
// to match GDK consts, but that may be co-incidence.
modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0;
modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift
modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0;
modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0;
modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl
modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested
modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested
// *todo: test ALTs - I don't have a case for testing these. Do you?
// *todo: NUM? - I don't care enough right now (and it's not a GDK modifier).
result["scan_code"] = (S32)mKeyScanCode;
result["virtual_key"] = (S32)mKeyVirtualKey;
result["modifiers"] = (S32)modifiers;
return result;
}
BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
{
BOOL rtn = FALSE;

View File

@ -102,7 +102,7 @@ public:
/*virtual*/ void gatherInput();
/*virtual*/ void swapBuffers();
/*virtual*/ void delayInputProcessing() { };
/*virtual*/ void delayInputProcessing() { };
// handy coordinate space conversion routines
/*virtual*/ BOOL convertCoords(LLCoordScreen from, LLCoordWindow *to);
@ -155,12 +155,13 @@ protected:
BOOL ignore_pixel_depth, U32 fsaa_samples);
~LLWindowSDL();
/*virtual*/ BOOL isValid();
/*virtual*/ LLSD getNativeKeyData();
void initCursors();
void quitCursors();
BOOL isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
// Changes display resolution. Returns true if successful
BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
@ -204,12 +205,16 @@ protected:
friend class LLWindowManager;
#if LL_X11
private:
#if LL_X11
void x11_set_urgent(BOOL urgent);
BOOL mFlashing;
LLTimer mFlashTimer;
#endif //LL_X11
U32 mKeyScanCode;
U32 mKeyVirtualKey;
SDLMod mKeyModifiers;
};

View File

@ -378,6 +378,9 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mMousePositionModified = FALSE;
mInputProcessingPaused = FALSE;
mPreeditor = NULL;
mKeyCharCode = 0;
mKeyScanCode = 0;
mKeyVirtualKey = 0;
mhDC = NULL;
mhRC = NULL;
@ -1872,6 +1875,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
// allow system keys, such as ALT-F4 to be processed by Windows
eat_keystroke = FALSE;
case WM_KEYDOWN:
window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next
window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff;
window_imp->mKeyVirtualKey = w_param;
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN");
{
if (gDebugWindowProc)
@ -1891,6 +1898,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
eat_keystroke = FALSE;
case WM_KEYUP:
{
window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff;
window_imp->mKeyVirtualKey = w_param;
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP");
LLFastTimer t2(FTM_KEYHANDLER);
@ -1976,6 +1986,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
case WM_CHAR:
window_imp->mKeyCharCode = w_param;
// Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need
// to figure out how that works. - Doug
//
@ -3051,6 +3063,19 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url )
*/
}
/*
Make the raw keyboard data available - used to poke through to LLQtWebKit so
that Qt/Webkit has access to the virtual keycodes etc. that it needs
*/
LLSD LLWindowWin32::getNativeKeyData()
{
LLSD result = LLSD::emptyMap();
result["scan_code"] = (S32)mKeyScanCode;
result["virtual_key"] = (S32)mKeyVirtualKey;
return result;
}
BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b )
{

View File

@ -132,7 +132,7 @@ protected:
HCURSOR loadColorCursor(LPCTSTR name);
BOOL isValid();
void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size);
LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
@ -211,6 +211,10 @@ protected:
LLDragDropWin32* mDragDrop;
U32 mKeyCharCode;
U32 mKeyScanCode;
U32 mKeyVirtualKey;
friend class LLWindowManager;
};

View File

@ -137,7 +137,7 @@ namespace LLInitParam
}
bool BaseBlock::validateBlock(bool silent) const
bool BaseBlock::validateBlock(bool emit_errors) const
{
const BlockDescriptor& block_data = getBlockDescriptor();
for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
@ -145,7 +145,7 @@ namespace LLInitParam
const Param* param = getParamFromHandle(it->first);
if (!it->second(param))
{
if (!silent)
if (emit_errors)
{
llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
}
@ -458,7 +458,7 @@ namespace LLInitParam
// take all provided params from other and apply to self
// NOTE: this requires that "other" is of the same derived type as this
bool BaseBlock::overwriteFromImpl(BlockDescriptor& block_data, const BaseBlock& other)
bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
{
bool param_changed = false;
BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
@ -471,27 +471,7 @@ namespace LLInitParam
if (merge_func)
{
Param* paramp = getParamFromHandle(it->mParamHandle);
param_changed |= merge_func(*paramp, *other_paramp, true);
}
}
return param_changed;
}
// take all provided params that are not already provided, and apply to self
bool BaseBlock::fillFromImpl(BlockDescriptor& block_data, const BaseBlock& other)
{
bool param_changed = false;
BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
it != end_it;
++it)
{
const Param* other_paramp = other.getParamFromHandle(it->mParamHandle);
ParamDescriptor::merge_func_t merge_func = it->mMergeFunc;
if (merge_func)
{
Param* paramp = getParamFromHandle(it->mParamHandle);
param_changed |= merge_func(*paramp, *other_paramp, false);
param_changed |= merge_func(*paramp, *other_paramp, overwrite);
}
}
return param_changed;

View File

@ -407,7 +407,7 @@ namespace LLInitParam
class BaseBlock
{
public:
// "Multiple" constraint types
// "Multiple" constraint types, put here in root class to avoid ambiguity during use
struct AnyAmount
{
static U32 minCount() { return 0; }
@ -452,7 +452,7 @@ namespace LLInitParam
bool submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
param_handle_t getHandleFromParam(const Param* param) const;
bool validateBlock(bool silent = false) const;
bool validateBlock(bool emit_errors = true) const;
Param* getParamFromHandle(const param_handle_t param_handle)
{
@ -500,10 +500,7 @@ namespace LLInitParam
// take all provided params from other and apply to self
bool overwriteFromImpl(BlockDescriptor& block_data, const BaseBlock& other);
// take all provided params that are not already provided, and apply to self
bool fillFromImpl(BlockDescriptor& block_data, const BaseBlock& other);
bool merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite);
// can be updated in getters
mutable S32 mChangeVersion;
@ -805,7 +802,7 @@ namespace LLInitParam
if (Param::getProvided() && mData.mValidatedVersion < T::getLastChangeVersion())
{
// a sub-block is "provided" when it has been filled in enough to be valid
mData.mValidated = T::validateBlock(true);
mData.mValidated = T::validateBlock(false);
mData.mValidatedVersion = T::getLastChangeVersion();
}
return Param::getProvided() && mData.mValidated;
@ -1236,7 +1233,7 @@ namespace LLInitParam
it != mValues.end();
++it)
{
if(it->validateBlock(true)) count++;
if(it->validateBlock(false)) count++;
}
return count;
}
@ -1286,7 +1283,7 @@ namespace LLInitParam
bool overwriteFrom(const self_t& other)
{
mCurChoice = other.mCurChoice;
return BaseBlock::overwriteFromImpl(blockDescriptor(), other);
return BaseBlock::merge(blockDescriptor(), other, true);
}
// take all provided params that are not already provided, and apply to self
@ -1413,13 +1410,13 @@ namespace LLInitParam
// take all provided params from other and apply to self
bool overwriteFrom(const self_t& other)
{
return BaseBlock::overwriteFromImpl(blockDescriptor(), other);
return BaseBlock::merge(blockDescriptor(), other, true);
}
// take all provided params that are not already provided, and apply to self
bool fillFrom(const self_t& other)
{
return BaseBlock::fillFromImpl(blockDescriptor(), other);
return BaseBlock::merge(blockDescriptor(), other, false);
}
protected:
Block()
@ -1710,7 +1707,7 @@ namespace LLInitParam
// if cached value is stale, regenerate from params
if (Param::getProvided() && mData.mLastParamVersion < BaseBlock::getLastChangeVersion())
{
if (block_t::validateBlock(true))
if (block_t::validateBlock(false))
{
static_cast<const DERIVED*>(this)->setValueFromBlock();
// clear stale keyword associated with old value
@ -1769,7 +1766,7 @@ namespace LLInitParam
if (Param::getProvided() && (mData.mLastParamVersion < BaseBlock::getLastChangeVersion()))
{
// go ahead and issue warnings at this point if any param is invalid
if(block_t::validateBlock(false))
if(block_t::validateBlock(true))
{
static_cast<const DERIVED*>(this)->setValueFromBlock();
mData.clearKey();
@ -1797,25 +1794,23 @@ namespace LLInitParam
private:
static bool mergeWith(Param& dst, const Param& src, bool overwrite)
{
const self_t& src_param = static_cast<const self_t&>(src);
const self_t& src_typed_param = static_cast<const self_t&>(src);
self_t& dst_typed_param = static_cast<self_t&>(dst);
if (src_param.isProvided()
if (src_typed_param.isProvided()
&& (overwrite || !dst_typed_param.isProvided()))
{
// assign individual parameters
if (overwrite)
{
dst_typed_param.BaseBlock::overwriteFromImpl(block_t::blockDescriptor(), src_param);
}
else
{
dst_typed_param.BaseBlock::fillFromImpl(block_t::blockDescriptor(), src_param);
}
dst_typed_param.BaseBlock::merge(block_t::blockDescriptor(), src_typed_param, overwrite);
// then copy actual value
dst_typed_param.mData.mValue = src_param.get();
dst_typed_param.mData.mValue = src_typed_param.get();
dst_typed_param.mData.clearKey();
dst_typed_param.setProvided(true);
// Propagate value back to block params since the value was updated during this merge.
// This will result in mData.mValue and the block params being in sync.
static_cast<DERIVED&>(dst_typed_param).setBlockFromValue();
return true;
}
return false;

View File

@ -324,33 +324,33 @@ void LLXUIXSDWriter::writeXSD(const std::string& type_name, const std::string& p
// add includes for all possible children
const std::type_info* type = *LLWidgetTypeRegistry::instance().getValue(type_name);
const widget_registry_t* widget_registryp = LLChildRegistryRegistry::instance().getValue(type);
// add include declarations for all valid children
for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
it != widget_registryp->currentRegistrar().endItems();
++it)
{
std::string widget_name = it->first;
if (widget_name == type_name)
{
continue;
}
LLXMLNodePtr nodep = new LLXMLNode("xs:include", false);
nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");
// add to front of schema
mSchemaNode->addChild(nodep, mSchemaNode);
}
// add choices for valid children
if (widget_registryp)
{
// add include declarations for all valid children
for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
it != widget_registryp->currentRegistrar().endItems();
++it)
{
std::string widget_name = it->first;
if (widget_name == type_name)
{
continue;
}
LLXMLNodePtr nodep = new LLXMLNode("xs:include", false);
nodep->createChild("schemaLocation", true)->setStringValue(widget_name + ".xsd");
// add to front of schema
mSchemaNode->addChild(nodep, mSchemaNode);
}
for (widget_registry_t::Registrar::registry_map_t::const_iterator it = widget_registryp->currentRegistrar().beginItems();
it != widget_registryp->currentRegistrar().endItems();
++it)
{
std::string widget_name = it->first;
//<xs:element name="widget_name" type="widget_name">
//<xs:element name="widget_name" type="widget_name">
LLXMLNodePtr widget_node = mElementNode->createChild("xs:element", false);
widget_node->createChild("name", true)->setStringValue(widget_name);
widget_node->createChild("type", true)->setStringValue(widget_name);

View File

@ -9805,6 +9805,9 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom
break;
case LSCP_EMIT_BYTE_CODE:
{
llassert(mEventp);
if (!mEventp) return;
// order for event handler
// set jump table value
S32 jumpoffset;
@ -9818,13 +9821,11 @@ void LLScriptEventHandler::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCom
chunk->addBytes(4);
// null terminated event name and null terminated parameters
if (mEventp)
{
LLScriptByteCodeChunk *event = new LLScriptByteCodeChunk(FALSE);
mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, event, heap, stacksize, entry, entrycount, NULL);
chunk->addBytes(event->mCodeChunk, event->mCurrentOffset);
delete event;
}
LLScriptByteCodeChunk *event = new LLScriptByteCodeChunk(FALSE);
mEventp->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, event, heap, stacksize, entry, entrycount, NULL);
chunk->addBytes(event->mCodeChunk, event->mCurrentOffset);
delete event;
chunk->addBytes(1);
// now we're at the first opcode
@ -10626,6 +10627,8 @@ LLScriptScript::LLScriptScript(LLScritpGlobalStorage *globals,
}
temp = temp->mNextp;
}
mClassName[0] = '\0';
}
void LLScriptScript::setBytecodeDest(const char* dst_filename)

View File

@ -1876,7 +1876,7 @@ class LLScriptStateChange : public LLScriptStatement
{
public:
LLScriptStateChange(S32 line, S32 col, LLScriptIdentifier *identifier)
: LLScriptStatement(line, col, LSSMT_STATE_CHANGE), mIdentifier(identifier)
: LLScriptStatement(line, col, LSSMT_STATE_CHANGE), mIdentifier(identifier), mReturnType(LST_NULL)
{
}
@ -2210,7 +2210,7 @@ class LLScriptState : public LLScriptFilePosition
{
public:
LLScriptState(S32 line, S32 col, LSCRIPTStateType type, LLScriptIdentifier *identifier, LLScriptEventHandler *event)
: LLScriptFilePosition(line, col), mType(type), mIdentifier(identifier), mEvent(event), mNextp(NULL)
: LLScriptFilePosition(line, col), mType(type), mIdentifier(identifier), mEvent(event), mNextp(NULL), mStateScope(NULL)
{
}

View File

@ -9,6 +9,7 @@ include(LLPlugin)
include(LLMath)
include(LLRender)
include(LLWindow)
include(UI)
include(Linking)
include(PluginAPI)
include(MediaPluginBase)
@ -38,7 +39,7 @@ add_library(media_plugin_webkit
${media_plugin_webkit_SOURCE_FILES}
)
target_link_libraries(media_plugin_webkit
set(media_plugin_webkit_LINK_LIBRARIES
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
${LLCOMMON_LIBRARIES}
@ -46,6 +47,14 @@ target_link_libraries(media_plugin_webkit
${PLUGIN_API_WINDOWS_LIBRARIES}
)
if (LINUX)
list(APPEND media_plugin_webkit_LINK_LIBRARIES
${UI_LIBRARIES} # for glib/GTK
)
endif (LINUX)
target_link_libraries(media_plugin_webkit ${media_plugin_webkit_LINK_LIBRARIES})
add_dependencies(media_plugin_webkit
${LLPLUGIN_LIBRARIES}
${MEDIA_PLUGIN_BASE_LIBRARIES}
@ -79,4 +88,5 @@ if (DARWIN)
DEPENDS media_plugin_webkit ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libllqtwebkit.dylib
)
endif (DARWIN)
endif (DARWIN)

View File

@ -470,92 +470,96 @@ private:
return (LLQtWebKit::EKeyboardModifier)result;
}
////////////////////////////////////////////////////////////////////////////////
//
void deserializeKeyboardData( LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers )
{
native_scan_code = 0;
native_virtual_key = 0;
native_modifiers = 0;
if( native_key_data.isMap() )
{
#if LL_DARWIN
native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger());
native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger());
native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
#elif LL_WINDOWS
native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
// TODO: I don't think we need to do anything with native modifiers here -- please verify
#elif LL_LINUX
native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger());
native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger());
native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger());
#else
// Add other platforms here as needed
#endif
};
};
////////////////////////////////////////////////////////////////////////////////
//
void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers)
void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
{
int llqt_key;
// The incoming values for 'key' will be the ones from indra_constants.h
// the outgoing values are the ones from llqtwebkit.h
std::string utf8_text;
if(key < KEY_SPECIAL)
{
// Low-ascii characters need to get passed through.
utf8_text = (char)key;
}
// Any special-case handling we want to do for particular keys...
switch((KEY)key)
{
// This is the list that the llqtwebkit implementation actually maps into Qt keys.
// case KEY_XXX: llqt_key = LL_DOM_VK_CANCEL; break;
// case KEY_XXX: llqt_key = LL_DOM_VK_HELP; break;
case KEY_BACKSPACE: llqt_key = LL_DOM_VK_BACK_SPACE; break;
case KEY_TAB: llqt_key = LL_DOM_VK_TAB; break;
// case KEY_XXX: llqt_key = LL_DOM_VK_CLEAR; break;
case KEY_RETURN: llqt_key = LL_DOM_VK_RETURN; break;
case KEY_PAD_RETURN: llqt_key = LL_DOM_VK_ENTER; break;
case KEY_SHIFT: llqt_key = LL_DOM_VK_SHIFT; break;
case KEY_CONTROL: llqt_key = LL_DOM_VK_CONTROL; break;
case KEY_ALT: llqt_key = LL_DOM_VK_ALT; break;
// case KEY_XXX: llqt_key = LL_DOM_VK_PAUSE; break;
case KEY_CAPSLOCK: llqt_key = LL_DOM_VK_CAPS_LOCK; break;
case KEY_ESCAPE: llqt_key = LL_DOM_VK_ESCAPE; break;
case KEY_PAGE_UP: llqt_key = LL_DOM_VK_PAGE_UP; break;
case KEY_PAGE_DOWN: llqt_key = LL_DOM_VK_PAGE_DOWN; break;
case KEY_END: llqt_key = LL_DOM_VK_END; break;
case KEY_HOME: llqt_key = LL_DOM_VK_HOME; break;
case KEY_LEFT: llqt_key = LL_DOM_VK_LEFT; break;
case KEY_UP: llqt_key = LL_DOM_VK_UP; break;
case KEY_RIGHT: llqt_key = LL_DOM_VK_RIGHT; break;
case KEY_DOWN: llqt_key = LL_DOM_VK_DOWN; break;
// case KEY_XXX: llqt_key = LL_DOM_VK_PRINTSCREEN; break;
case KEY_INSERT: llqt_key = LL_DOM_VK_INSERT; break;
case KEY_DELETE: llqt_key = LL_DOM_VK_DELETE; break;
// case KEY_XXX: llqt_key = LL_DOM_VK_CONTEXT_MENU; break;
// ASCII codes for some standard keys
case LLQtWebKit::KEY_BACKSPACE: utf8_text = (char)8; break;
case LLQtWebKit::KEY_TAB: utf8_text = (char)9; break;
case LLQtWebKit::KEY_RETURN: utf8_text = (char)13; break;
case LLQtWebKit::KEY_PAD_RETURN: utf8_text = (char)13; break;
case LLQtWebKit::KEY_ESCAPE: utf8_text = (char)27; break;
default:
if(key < KEY_SPECIAL)
{
// Pass the incoming key through -- it should be regular ASCII, which should be correct for webkit.
llqt_key = key;
}
else
{
// Don't pass through untranslated special keys -- they'll be all wrong.
llqt_key = 0;
}
default:
break;
}
// std::cerr << "keypress, original code = 0x" << std::hex << key << ", converted code = 0x" << std::hex << llqt_key << std::dec << std::endl;
// std::cerr << "key event " << (int)key_event << ", native_key_data = " << native_key_data << std::endl;
if(llqt_key != 0)
{
LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers);
}
uint32_t native_scan_code = 0;
uint32_t native_virtual_key = 0;
uint32_t native_modifiers = 0;
deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, key_event, (uint32_t)key, utf8_text.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
checkEditState();
};
////////////////////////////////////////////////////////////////////////////////
//
void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers)
{
LLWString wstr = utf8str_to_wstring(utf8str);
void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap())
{
uint32_t key = LLQtWebKit::KEY_NONE;
unsigned int i;
for(i=0; i < wstr.size(); i++)
// std::cerr << "unicode input, native_key_data = " << native_key_data << std::endl;
if(utf8str.size() == 1)
{
// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl;
if(wstr[i] == 32)
{
// For some reason, the webkit plugin really wants the space bar to come in through the key-event path, not the unicode path.
LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, 32, modifiers);
LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, 32, modifiers);
}
else
{
LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers);
}
// The only way a utf8 string can be one byte long is if it's actually a single 7-bit ascii character.
// In this case, use it as the key value.
key = utf8str[0];
}
uint32_t native_scan_code = 0;
uint32_t native_virtual_key = 0;
uint32_t native_modifiers = 0;
deserializeKeyboardData( native_key_data, native_scan_code, native_virtual_key, native_modifiers );
LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_DOWN, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
LLQtWebKit::getInstance()->keyboardEvent( mBrowserWindowId, LLQtWebKit::KE_KEY_UP, (uint32_t)key, utf8str.c_str(), modifiers, native_scan_code, native_virtual_key, native_modifiers);
checkEditState();
};
@ -855,6 +859,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
std::string event = message_in.getValue("event");
S32 key = message_in.getValueS32("key");
std::string modifiers = message_in.getValue("modifiers");
LLSD native_key_data = message_in.getValueLLSD("native_key_data");
// Treat unknown events as key-up for safety.
LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
@ -867,14 +872,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
key_event = LLQtWebKit::KE_KEY_REPEAT;
}
keyEvent(key_event, key, decodeModifiers(modifiers));
keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
}
else if(message_name == "text_event")
{
std::string text = message_in.getValue("text");
std::string modifiers = message_in.getValue("modifiers");
LLSD native_key_data = message_in.getValueLLSD("native_key_data");
unicodeInput(text, decodeModifiers(modifiers));
unicodeInput(text, decodeModifiers(modifiers), native_key_data);
}
if(message_name == "edit_cut")
{

View File

@ -162,6 +162,7 @@ set(viewer_SOURCE_FILES
llfloatercustomize.cpp
llfloaterdaycycle.cpp
llfloaterenvsettings.cpp
llfloaterevent.cpp
llfloaterfonttest.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
@ -183,7 +184,6 @@ set(viewer_SOURCE_FILES
llfloatermediasettings.cpp
llfloatermemleak.cpp
llfloaternamedesc.cpp
llfloaternearbymedia.cpp
llfloaternotificationsconsole.cpp
llfloateropenobject.cpp
llfloaterparcel.cpp
@ -301,7 +301,6 @@ set(viewer_SOURCE_FILES
llpanelclassified.cpp
llpanelcontents.cpp
llpaneleditwearable.cpp
llpanelevent.cpp
llpanelface.cpp
llpanelgroup.cpp
llpanelgroupgeneral.cpp
@ -324,6 +323,7 @@ set(viewer_SOURCE_FILES
llpanelmediasettingspermissions.cpp
llpanelmediasettingssecurity.cpp
llpanelme.cpp
llpanelnearbymedia.cpp
llpanelobject.cpp
llpanelobjectinventory.cpp
llpaneloutfitsinventory.cpp
@ -665,6 +665,7 @@ set(viewer_HEADER_FILES
llfloatercustomize.h
llfloaterdaycycle.h
llfloaterenvsettings.h
llfloaterevent.h
llfloaterfonttest.h
llfloatergesture.h
llfloatergodtools.h
@ -686,7 +687,6 @@ set(viewer_HEADER_FILES
llfloatermediasettings.h
llfloatermemleak.h
llfloaternamedesc.h
llfloaternearbymedia.h
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
@ -799,7 +799,6 @@ set(viewer_HEADER_FILES
llpanelclassified.h
llpanelcontents.h
llpaneleditwearable.h
llpanelevent.h
llpanelface.h
llpanelgroup.h
llpanelgroupgeneral.h
@ -822,6 +821,7 @@ set(viewer_HEADER_FILES
llpanelmediasettingspermissions.h
llpanelmediasettingssecurity.h
llpanelme.h
llpanelnearbymedia.h
llpanelobject.h
llpanelobjectinventory.h
llpaneloutfitsinventory.h
@ -1218,18 +1218,18 @@ endif (WINDOWS)
# Add the xui files. This is handy for searching for xui elements
# from within the IDE.
set(viewer_XUI_FILES
skins/default/colors.xml
skins/default/textures/textures.xml
skins/base/colors.xml
skins/base/textures/textures.xml
)
file(GLOB DEFAULT_XUI_FILE_GLOB_LIST
${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/*.xml)
${CMAKE_CURRENT_SOURCE_DIR}/skins/base/xui/en/*.xml)
list(APPEND viewer_XUI_FILES ${DEFAULT_XUI_FILE_GLOB_LIST})
file(GLOB DEFAULT_WIDGET_FILE_GLOB_LIST
${CMAKE_CURRENT_SOURCE_DIR}/skins/default/xui/en/widgets/*.xml)
${CMAKE_CURRENT_SOURCE_DIR}/skins/base/xui/en/widgets/*.xml)
list(APPEND viewer_XUI_FILES ${DEFAULT_WIDGET_FILE_GLOB_LIST})
file(GLOB SILVER_XUI_FILE_GLOB_LIST

View File

@ -177,17 +177,6 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstStreamingMedia</key>
<map>
<key>Comment</key>
<string>Enables FirstStreamingMedia warning dialog</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstTeleport</key>
<map>
<key>Comment</key>

View File

@ -2839,16 +2839,16 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>HadFirstSuccessfulLogin</key>
<key>FirstRunThisInstall</key>
<map>
<key>Comment</key>
<string>Specifies whether you have successfully logged in at least once before</string>
<string>Specifies that you have not run the viewer since you installed the latest update</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<integer>1</integer>
</map>
<key>FirstSelectedDisabledPopups</key>
<map>
@ -3629,7 +3629,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://lecs.viewer-sidebar.secondlife.com.s3.amazonaws.com/sidebar.html?p=[AUTH_TOKEN]&amp;lang=[LANGUAGE]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]</string>
<string>https://viewer-sidebar.secondlife.com/sidebar.html?p=[AUTH_TOKEN]&amp;lang=[LANGUAGE]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;firstlogin=[FIRST_LOGIN]</string>
</map>
<key>SearchURL</key>
<map>
@ -4600,6 +4600,50 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>MediaShowOnOthers</key>
<map>
<key>Comment</key>
<string>Whether or not to show media on other avatars</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MediaShowOutsideParcel</key>
<map>
<key>Comment</key>
<string>Whether or not to show media from outside the current parcel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MediaShowWithinParcel</key>
<map>
<key>Comment</key>
<string>Whether or not to show media within the current parcel</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MediaTentativeAutoPlay</key>
<map>
<key>Comment</key>
<string>This is a tentative flag that may be temporarily set off by the user, until she teleports</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>MemoryLogFrequency</key>
<map>
<key>Comment</key>
@ -4655,6 +4699,17 @@
<key>Value</key>
<integer>410</integer>
</map>
<key>MePanelOpened</key>
<map>
<key>Comment</key>
<string>Indicates that Me Panel was opened at least once after Viewer was installed</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>0</real>
</map>
<key>MigrateCacheDirectory</key>
<map>
<key>Comment</key>
@ -5066,7 +5121,9 @@
<map>
<key>Comment</key>
<string>Default width of buttons in the toast.
Note if required width will be less then this one, a button will be reshaped to default size , otherwise to required</string>
Notes:
If required width will be less then this one, a button will be reshaped to default size , otherwise to required
Change of this parameter will affect the layout of buttons in notification toast.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -5325,7 +5382,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<integer>1</integer>
</map>
<key>PerAccountSettingsFile</key>
<map>
@ -8432,7 +8489,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
<integer>0</integer>
</map>
<key>ShowTangentBasis</key>
<map>
@ -8478,6 +8535,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowVoiceVisualizersInCalls</key>
<map>
<key>Comment</key>
<string>Enables in-world voice visualizers, voice gestures and lip-sync while in group or P2P calls.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>ShowVolumeSettingsPopup</key>
<map>
<key>Comment</key>
@ -9970,50 +10038,6 @@
<string>S32</string>
<key>Value</key>
<integer>15</integer>
</map>
<key>UIButtonImageLeftPadding</key>
<map>
<key>Comment</key>
<string>Button Overlay Image Left Padding</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>UIButtonImageRightPadding</key>
<map>
<key>Comment</key>
<string>Button Overlay Image Right Padding</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>4</integer>
</map>
<key>UIButtonImageTopPadding</key>
<map>
<key>Comment</key>
<string>Button Overlay Image Top Padding</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>UIButtonImageBottomPadding</key>
<map>
<key>Comment</key>
<string>Button Overlay Image Bottom Padding</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>UploadBakedTexOld</key>
<map>
@ -10435,17 +10459,6 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>VoiceDefaultInternalLevel</key>
<map>
<key>Comment</key>
<string>Internal level of voice set by default. Is equivalent to 0.5 (from 0.0-1.0 range) external voice level (internal = 400 * external^2).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>100</integer>
</map>
<key>VoiceEarLocation</key>
<map>
<key>Comment</key>

View File

@ -956,6 +956,7 @@ void LLAgent::sendMessage()
if (!mRegionp)
{
llerrs << "No region for agent yet!" << llendl;
return;
}
gMessageSystem->sendMessage(mRegionp->getHost());
}
@ -4482,7 +4483,9 @@ void LLAgent::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, const LLV
{
const F64 ANIM_METERS_PER_SECOND = 10.0;
const F64 MIN_ANIM_SECONDS = 0.5;
const F64 MAX_ANIM_SECONDS = 10.0;
F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND );
anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS );
setAnimationDuration( (F32)anim_duration );
}
@ -5024,9 +5027,9 @@ void LLAgent::buildFullnameAndTitle(std::string& name) const
}
}
BOOL LLAgent::isInGroup(const LLUUID& group_id) const
BOOL LLAgent::isInGroup(const LLUUID& group_id, BOOL ignore_god_mode /* FALSE */) const
{
if (isGodlike())
if (!ignore_god_mode && isGodlike())
return true;
S32 count = mGroups.count();

View File

@ -983,7 +983,7 @@ private:
//--------------------------------------------------------------------
public:
// Checks against all groups in the entire agent group list.
BOOL isInGroup(const LLUUID& group_id) const;
BOOL isInGroup(const LLUUID& group_id, BOOL ingnore_God_mod = FALSE) const;
protected:
// Only used for building titles.
BOOL isGroupMember() const { return !mGroupID.isNull(); }

View File

@ -149,11 +149,17 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const
sim_access_string.c_str());
break;
case LOCATION_FORMAT_NO_MATURITY:
case LOCATION_FORMAT_FULL:
buffer = llformat("%s (%d, %d, %d)",
region_name.c_str(),
pos_x, pos_y, pos_z);
break;
case LOCATION_FORMAT_FULL:
buffer = llformat("%s (%d, %d, %d)%s%s",
region_name.c_str(),
pos_x, pos_y, pos_z,
sim_access_string.empty() ? "" : " - ",
sim_access_string.c_str());
break;
}
}
else

View File

@ -299,6 +299,10 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i
{
gAgentWearables.makeNewOutfitDone(mType, mIndex);
}
if (mTodo & CALL_WEARITEM)
{
LLAppearanceManager::instance().addCOFItemLink(inv_item, true);
}
}
void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type,
@ -310,21 +314,24 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type,
return;
LLUUID old_item_id = getWearableItemID((EWearableType)type,index);
if (wearable)
{
wearable->setItemID(item_id);
if (old_item_id.notNull())
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
setWearable((EWearableType)type,index,wearable);
}
else
{
pushWearable((EWearableType)type,wearable);
}
}
if (old_item_id.notNull())
{
gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
setWearable((EWearableType)type,index,wearable);
}
else
{
pushWearable((EWearableType)type,wearable);
}
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
LLViewerInventoryItem* item = gInventory.getItem(item_id);
if (item && wearable)
{
@ -507,7 +514,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,
type,
index,
new_wearable,
addWearableToAgentInventoryCallback::CALL_UPDATE);
addWearableToAgentInventoryCallback::CALL_WEARITEM);
LLUUID category_id;
if (save_in_lost_and_found)
{
@ -761,6 +768,8 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable)
wearable->refreshName();
wearable->setLabelUpdated();
wearable->pullCrossWearableValues();
// Hack pt 2. If the wearable we just loaded has definition version 24,
// then force a re-save of this wearable after slamming the version number to 22.
// This number was incorrectly incremented for internal builds before release, and
@ -927,13 +936,6 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
if (mInitialWearablesUpdateReceived)
return;
mInitialWearablesUpdateReceived = true;
// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
// then auto-populate outfits from the library into the My Outfits folder.
if (LLInventoryModel::getIsFirstTimeInViewer2() || gSavedSettings.getBOOL("MyOutfitsAutofill"))
{
gAgentWearables.populateMyOutfitsFolder();
}
LLUUID agent_id;
gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
@ -1292,25 +1294,29 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
j,
new_wearable,
todo);
if (isWearableCopyable((EWearableType)type, j))
llassert(item);
if (item)
{
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
folder_id,
new_name,
cb);
}
else
{
move_inventory_item(
gAgent.getID(),
gAgent.getSessionID(),
item->getUUID(),
folder_id,
new_name,
cb);
if (isWearableCopyable((EWearableType)type, j))
{
copy_inventory_item(
gAgent.getID(),
item->getPermissions().getOwner(),
item->getUUID(),
folder_id,
new_name,
cb);
}
else
{
move_inventory_item(
gAgent.getID(),
gAgent.getSessionID(),
item->getUUID(),
folder_id,
new_name,
cb);
}
}
}
}
@ -1417,7 +1423,7 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name)
new_folder_name);
LLPointer<LLInventoryCallback> cb = new LLShowCreatedOutfit(folder_id);
LLAppearanceManager::instance().shallowCopyCategory(LLAppearanceManager::instance().getCOF(),folder_id, cb);
LLAppearanceManager::instance().shallowCopyCategoryContents(LLAppearanceManager::instance().getCOF(),folder_id, cb);
LLAppearanceManager::instance().createBaseOutfitLink(folder_id, cb);
return folder_id;
@ -1599,32 +1605,35 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
LLWearable* new_wearable = wearables[i];
LLPointer<LLInventoryItem> new_item = items[i];
const EWearableType type = new_wearable->getType();
wearables_to_remove[type] = FALSE;
// MULTI_WEARABLE: using 0th
LLWearable* old_wearable = getWearable(type, 0);
if (old_wearable)
{
const LLUUID& old_item_id = getWearableItemID(type, 0);
if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&
(old_item_id == new_item->getUUID()))
{
lldebugs << "No change to wearable asset and item: " << LLWearableDictionary::getInstance()->getWearableEntry(type) << llendl;
continue;
}
// Assumes existing wearables are not dirty.
if (old_wearable->isDirty())
{
llassert(0);
continue;
}
}
llassert(new_wearable);
if (new_wearable)
{
const EWearableType type = new_wearable->getType();
wearables_to_remove[type] = FALSE;
// MULTI_WEARABLE: using 0th
LLWearable* old_wearable = getWearable(type, 0);
if (old_wearable)
{
const LLUUID& old_item_id = getWearableItemID(type, 0);
if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&
(old_item_id == new_item->getUUID()))
{
lldebugs << "No change to wearable asset and item: " << LLWearableDictionary::getInstance()->getWearableEntry(type) << llendl;
continue;
}
// Assumes existing wearables are not dirty.
if (old_wearable->isDirty())
{
llassert(0);
continue;
}
}
new_wearable->setItemID(new_item->getUUID());
setWearable(type,0,new_wearable);
setWearable(type,0,new_wearable);
}
}
std::vector<LLWearable*> wearables_being_removed;
@ -1664,6 +1673,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
if (mAvatarObject)
{
mAvatarObject->updateVisualParams();
mAvatarObject->invalidateAll();
}
// Start rendering & update the server
@ -2143,6 +2153,8 @@ void LLAgentWearables::updateServer()
void LLAgentWearables::populateMyOutfitsFolder(void)
{
llinfos << "starting outfit populate" << llendl;
LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch();
// Get the complete information on the items in the inventory and
@ -2334,7 +2346,7 @@ void LLLibraryOutfitsFetch::libraryDone(void)
LLUUID folder_id = gInventory.createNewCategory(mImportedClothingID,
LLFolderType::FT_NONE,
iter->second);
LLAppearanceManager::getInstance()->shallowCopyCategory(iter->first, folder_id, copy_waiter);
LLAppearanceManager::getInstance()->shallowCopyCategoryContents(iter->first, folder_id, copy_waiter);
}
}
else

View File

@ -244,7 +244,8 @@ private:
CALL_UPDATE = 1,
CALL_RECOVERDONE = 2,
CALL_CREATESTANDARDDONE = 4,
CALL_MAKENEWOUTFITDONE = 8
CALL_MAKENEWOUTFITDONE = 8,
CALL_WEARITEM = 16
};
// MULTI-WEARABLE: index is an EWearableType - more confusing usage.

View File

@ -48,6 +48,31 @@
#include "llviewerregion.h"
#include "llwearablelist.h"
LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name)
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
LLNameCategoryCollector has_name(name);
gInventory.collectDescendentsIf(parent_id,
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH,
has_name);
if (0 == cat_array.count())
return LLUUID();
else
{
LLViewerInventoryCategory *cat = cat_array.get(0);
if (cat)
return cat->getUUID();
else
{
llwarns << "null cat" << llendl;
return LLUUID();
}
}
}
// support for secondlife:///app/appearance SLapps
class LLAppearanceHandler : public LLCommandHandler
{
@ -88,6 +113,8 @@ public:
protected:
~LLWearInventoryCategoryCallback()
{
llinfos << "done all inventory callbacks" << llendl;
// Is the destructor called by ordinary dereference, or because the app's shutting down?
// If the inventory callback manager goes away, we're shutting down, no longer want the callback.
if( LLInventoryCallbackManager::is_instantiated() )
@ -125,12 +152,15 @@ protected:
void LLOutfitObserver::done()
{
llinfos << "done 2nd stage fetch" << llendl;
gInventory.removeObserver(this);
doOnIdle(boost::bind(&LLOutfitObserver::doWearCategory,this));
}
void LLOutfitObserver::doWearCategory()
{
llinfos << "starting" << llendl;
// We now have an outfit ready to be copied to agent inventory. Do
// it, and wear that outfit normally.
if(mCopyItems)
@ -219,6 +249,8 @@ void LLOutfitFetch::done()
// What we do here is get the complete information on the items in
// the library, and set up an observer that will wait for that to
// happen.
llinfos << "done first stage fetch" << llendl;
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(mCompleteFolders.front(),
@ -279,6 +311,8 @@ public:
virtual ~LLUpdateAppearanceOnDestroy()
{
llinfos << "done update appearance on destroy" << llendl;
if (!LLApp::isExiting())
{
LLAppearanceManager::instance().updateAppearanceFromCOF();
@ -287,6 +321,7 @@ public:
/* virtual */ void fire(const LLUUID& inv_item)
{
llinfos << "callback fired" << llendl;
mFireCount++;
}
private:
@ -321,7 +356,7 @@ public:
~LLWearableHoldingPattern();
bool pollCompletion();
bool isDone();
bool isFetchCompleted();
bool isTimedOut();
typedef std::list<LLFoundData> found_list_t;
@ -330,10 +365,12 @@ public:
LLInventoryModel::item_array_t mGestItems;
S32 mResolved;
LLTimer mWaitTime;
bool mFired;
};
LLWearableHoldingPattern::LLWearableHoldingPattern():
mResolved(0)
mResolved(0),
mFired(false)
{
}
@ -341,31 +378,34 @@ LLWearableHoldingPattern::~LLWearableHoldingPattern()
{
}
bool LLWearableHoldingPattern::isDone()
bool LLWearableHoldingPattern::isFetchCompleted()
{
if (mResolved >= (S32)mFoundList.size())
return true; // have everything we were waiting for
else if (isTimedOut())
{
llwarns << "Exceeded max wait time, updating appearance based on what has arrived" << llendl;
return true;
}
return false;
return (mResolved >= (S32)mFoundList.size()); // have everything we were waiting for?
}
bool LLWearableHoldingPattern::isTimedOut()
{
static F32 max_wait_time = 15.0; // give up if wearable fetches haven't completed in max_wait_time seconds.
static F32 max_wait_time = 20.0; // give up if wearable fetches haven't completed in max_wait_time seconds.
return mWaitTime.getElapsedTimeF32() > max_wait_time;
}
bool LLWearableHoldingPattern::pollCompletion()
{
bool done = isDone();
llinfos << "polling, done status: " << done << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
bool completed = isFetchCompleted();
bool timed_out = isTimedOut();
bool done = completed || timed_out;
llinfos << "polling, done status: " << completed << " timed out? " << timed_out << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
if (done)
{
mFired = true;
if (timed_out)
{
llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
}
// Activate all gestures in this folder
if (mGestItems.count() > 0)
{
@ -397,7 +437,11 @@ bool LLWearableHoldingPattern::pollCompletion()
LLAgentWearables::userUpdateAttachments(mObjItems);
}
delete this;
if (completed)
{
// Only safe to delete if all wearable callbacks completed.
delete this;
}
}
return done;
}
@ -432,7 +476,11 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
static void onWearableAssetFetch(LLWearable* wearable, void* data)
{
LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
if (holder->mFired)
{
llwarns << "called after holder fired" << llendl;
}
if(wearable)
{
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
@ -506,8 +554,32 @@ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, boo
LLAppearanceManager::instance().updateCOF(category,append);
}
// Create a copy of src_id + contents as a subfolder of dst_id.
void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb)
{
LLInventoryCategory *src_cat = gInventory.getCategory(src_id);
if (!src_cat)
{
llwarns << "folder not found for src " << src_id.asString() << llendl;
return;
}
LLUUID parent_id = dst_id;
if(parent_id.isNull())
{
parent_id = gInventory.getRootFolderID();
}
LLUUID subfolder_id = gInventory.createNewCategory( parent_id,
LLFolderType::FT_NONE,
src_cat->getName());
shallowCopyCategoryContents(src_id, subfolder_id, cb);
gInventory.notifyObservers();
}
// Copy contents of src_id to dst_id.
void LLAppearanceManager::shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb)
{
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
@ -604,6 +676,11 @@ void LLAppearanceManager::filterWearableItems(
if (!item->isWearableType())
continue;
EWearableType type = item->getWearableType();
if(type < 0 || type >= WT_COUNT)
{
LL_WARNS("Appearance") << "Invalid wearable type. Inventory type does not match wearable flag bitfield." << LL_ENDL;
continue;
}
items_by_type[type].push_back(item);
}
@ -641,6 +718,8 @@ void LLAppearanceManager::linkAll(const LLUUID& category,
void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)
{
llinfos << "starting" << llendl;
const LLUUID cof = getCOF();
// Deactivate currently active gestures in the COF, if replacing outfit
@ -698,6 +777,7 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)
gInventory.notifyObservers();
// Create links to new COF contents.
llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl;
LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
linkAll(cof, body_items, link_waiter);
@ -710,6 +790,7 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)
{
createBaseOutfitLink(category, link_waiter);
}
llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl;
}
void LLAppearanceManager::updatePanelOutfitName(const std::string& name)
@ -781,6 +862,8 @@ void LLAppearanceManager::updateAppearanceFromCOF()
{
// update dirty flag to see if the state of the COF matches
// the saved outfit stored as a folder link
llinfos << "starting" << llendl;
updateIsDirty();
dumpCat(getCOF(),"COF, start");
@ -911,8 +994,9 @@ void LLAppearanceManager::wearInventoryCategory(LLInventoryCategory* category, b
{
if(!category) return;
lldebugs << "wearInventoryCategory( " << category->getName()
llinfos << "wearInventoryCategory( " << category->getName()
<< " )" << llendl;
// What we do here is get the complete information on the items in
// the inventory, and set up an observer that will wait for that to
// happen.
@ -941,7 +1025,8 @@ void LLAppearanceManager::wearInventoryCategoryOnAvatar( LLInventoryCategory* ca
// this up front to avoid having to deal with the case of multiple
// wearables being dirty.
if(!category) return;
lldebugs << "wearInventoryCategoryOnAvatar( " << category->getName()
llinfos << "wearInventoryCategoryOnAvatar( " << category->getName()
<< " )" << llendl;
if( gFloaterCustomize )
@ -1218,6 +1303,23 @@ void LLAppearanceManager::updateIsDirty()
}
}
void LLAppearanceManager::onFirstFullyVisible()
{
// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
// then auto-populate outfits from the library into the My Outfits folder.
llinfos << "avatar fully visible" << llendl;
static bool check_populate_my_outfits = true;
if (check_populate_my_outfits &&
(LLInventoryModel::getIsFirstTimeInViewer2()
|| gSavedSettings.getBOOL("MyOutfitsAutofill")))
{
gAgentWearables.populateMyOutfitsFolder();
}
check_populate_my_outfits = false;
}
//#define DUMP_CAT_VERBOSE
void LLAppearanceManager::dumpCat(const LLUUID& cat_id, const std::string& msg)
@ -1340,6 +1442,11 @@ BOOL LLAppearanceManager::getIsInCOF(const LLUUID& obj_id) const
BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const
{
if (!getIsInCOF(obj_id)) return FALSE;
// For now, don't allow direct deletion from the COF. Instead, force users
// to choose "Detach" or "Take Off".
return TRUE;
/*
const LLInventoryObject *obj = gInventory.getObject(obj_id);
if (!obj) return FALSE;
@ -1350,4 +1457,5 @@ BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const
if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE;
return FALSE;
*/
}

View File

@ -35,6 +35,8 @@
#include "llsingleton.h"
#include "llinventorymodel.h"
#include "llinventoryobserver.h"
#include "llviewerinventory.h"
#include "llcallbacklist.h"
class LLWearable;
@ -54,10 +56,14 @@ public:
void wearOutfitByName(const std::string& name);
void changeOutfit(bool proceed, const LLUUID& category, bool append);
// Copy all items in a category.
// Copy all items and the src category itself.
void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb);
// Copy all items in a category.
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,
LLPointer<LLInventoryCallback> cb);
// Find the Current Outfit folder.
const LLUUID getCOF() const;
@ -107,6 +113,9 @@ public:
// should only be necessary to do on initial login.
void updateIsDirty();
// Called when self avatar is first fully visible.
void onFirstFullyVisible();
protected:
LLAppearanceManager();
~LLAppearanceManager();
@ -144,6 +153,8 @@ public:
#define SUPPORT_ENSEMBLES 0
LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name);
// Shim class and template function to allow arbitrary boost::bind
// expressions to be run as one-time idle callbacks.
template <typename T>
@ -212,4 +223,103 @@ void doOnIdleRepeating(T callable)
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating<T>::onIdle,cb_functor);
}
template <class T>
class CallAfterCategoryFetchStage2: public LLInventoryFetchObserver
{
public:
CallAfterCategoryFetchStage2(T callable):
mCallable(callable)
{
}
~CallAfterCategoryFetchStage2()
{
}
virtual void done()
{
gInventory.removeObserver(this);
doOnIdle(mCallable);
delete this;
}
protected:
T mCallable;
};
template <class T>
class CallAfterCategoryFetchStage1: public LLInventoryFetchDescendentsObserver
{
public:
CallAfterCategoryFetchStage1(T callable):
mCallable(callable)
{
}
~CallAfterCategoryFetchStage1()
{
}
virtual void done()
{
// What we do here is get the complete information on the items in
// the library, and set up an observer that will wait for that to
// happen.
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(mCompleteFolders.front(),
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH);
S32 count = item_array.count();
if(!count)
{
llwarns << "Nothing fetched in category " << mCompleteFolders.front()
<< llendl;
//dec_busy_count();
gInventory.removeObserver(this);
delete this;
return;
}
CallAfterCategoryFetchStage2<T> *stage2 = new CallAfterCategoryFetchStage2<T>(mCallable);
LLInventoryFetchObserver::item_ref_t ids;
for(S32 i = 0; i < count; ++i)
{
ids.push_back(item_array.get(i)->getUUID());
}
gInventory.removeObserver(this);
// do the fetch
stage2->fetchItems(ids);
if(stage2->isEverythingComplete())
{
// everything is already here - call done.
stage2->done();
}
else
{
// it's all on it's way - add an observer, and the inventory
// will call done for us when everything is here.
gInventory.addObserver(stage2);
}
delete this;
}
protected:
T mCallable;
};
template <class T>
void callAfterCategoryFetch(const LLUUID& cat_id, T callable)
{
CallAfterCategoryFetchStage1<T> *stage1 = new CallAfterCategoryFetchStage1<T>(callable);
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
folders.push_back(cat_id);
stage1->fetchDescendents(folders);
if (stage1->isEverythingComplete())
{
stage1->done();
}
else
{
gInventory.addObserver(stage1);
}
}
#endif

View File

@ -40,6 +40,7 @@
#include "lluictrlfactory.h"
#include "lltexteditor.h"
#include "llerrorcontrol.h"
#include "lleventtimer.h"
#include "llviewertexturelist.h"
#include "llgroupmgr.h"
#include "llagent.h"
@ -586,7 +587,7 @@ bool LLAppViewer::init()
gDirUtilp->initAppDirs("SecondLife");
// set skin search path to default, will be overridden later
// this allows simple skinned file lookups to work
gDirUtilp->setSkinFolder("default");
gDirUtilp->setSkinFolder("base");
initLogging();
@ -1332,9 +1333,6 @@ bool LLAppViewer::cleanup()
llinfos << "Cache files removed" << llendflush;
cleanup_menus();
// Wait for any pending VFS IO
while (1)
{
@ -1653,7 +1651,7 @@ bool LLAppViewer::initThreads()
// Image decoding
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && false);
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
LLImage::initClass();
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
@ -1907,7 +1905,6 @@ bool LLAppViewer::initConfiguration()
// LLFirstUse::addConfigVariable("FirstSandbox");
// LLFirstUse::addConfigVariable("FirstFlexible");
// LLFirstUse::addConfigVariable("FirstDebugMenus");
// LLFirstUse::addConfigVariable("FirstStreamingMedia");
// LLFirstUse::addConfigVariable("FirstSculptedPrim");
// LLFirstUse::addConfigVariable("FirstVoice");
// LLFirstUse::addConfigVariable("FirstMedia");
@ -2114,7 +2111,7 @@ bool LLAppViewer::initConfiguration()
{
// hack to force the skin to default.
//gDirUtilp->setSkinFolder(skinfolder->getValue().asString());
gDirUtilp->setSkinFolder("default");
gDirUtilp->setSkinFolder("base");
}
mYieldTime = gSavedSettings.getS32("YieldTime");
@ -2319,9 +2316,6 @@ bool LLAppViewer::initWindow()
// store setting in a global for easy access and modification
gNoRender = gSavedSettings.getBOOL("DisableRendering");
// Hide the splash screen
LLSplashScreen::hide();
// always start windowed
BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
gViewerWindow = new LLViewerWindow(gWindowTitle,
@ -2565,7 +2559,7 @@ void LLAppViewer::handleViewerCrash()
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
gDebugInfo["HadFirstSuccessfulLogin"] = gSavedSettings.getBOOL("HadFirstSuccessfulLogin");
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
if(gLogoutInProgress)
{
@ -2964,7 +2958,7 @@ bool LLAppViewer::initCache()
// Purge cache if it belongs to an old version
else
{
static const S32 cache_version = 5;
static const S32 cache_version = 6;
if (gSavedSettings.getS32("LocalCacheVersion") != cache_version)
{
mPurgeCache = true;

View File

@ -36,6 +36,7 @@
#include "llallocator.h"
#include "llcontrol.h"
#include "llsys.h" // for LLOSInfo
#include "lltimer.h"
class LLCommandLineParser;
class LLFrameTimer;

View File

@ -181,7 +181,12 @@ void LLAvatarActions::startIM(const LLUUID& id)
return;
std::string name;
gCacheName->getFullName(id, name);
if (!gCacheName->getFullName(id, name))
{
gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::startIM, id));
return;
}
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
if (session_id != LLUUID::null)
{

View File

@ -526,21 +526,30 @@ void LLAvatarListItem::updateChildren()
LLView* LLAvatarListItem::getItemChildView(EAvatarListItemChildIndex child_view_index)
{
LLView* child_view = mAvatarName;
if (child_view_index < 0 || ALIC_COUNT <= child_view_index)
{
LL_WARNS("AvatarItemReshape") << "Child view index is out of range: " << child_view_index << LL_ENDL;
return child_view;
}
switch (child_view_index)
{
case ALIC_ICON: child_view = mAvatarIcon; break;
case ALIC_NAME: child_view = mAvatarName; break;
case ALIC_INTERACTION_TIME: child_view = mLastInteractionTime; break;
case ALIC_SPEAKER_INDICATOR: child_view = mSpeakingIndicator; break;
case ALIC_INFO_BUTTON: child_view = mInfoBtn; break;
case ALIC_PROFILE_BUTTON: child_view = mProfileBtn; break;
case ALIC_ICON:
child_view = mAvatarIcon;
break;
case ALIC_NAME:
child_view = mAvatarName;
break;
case ALIC_INTERACTION_TIME:
child_view = mLastInteractionTime;
break;
case ALIC_SPEAKER_INDICATOR:
child_view = mSpeakingIndicator;
break;
case ALIC_INFO_BUTTON:
child_view = mInfoBtn;
break;
case ALIC_PROFILE_BUTTON:
child_view = mProfileBtn;
break;
default:
LL_WARNS("AvatarItemReshape") << "Unexpected child view index is passed: " << child_view_index << LL_ENDL;
// leave child_view untouched
}
return child_view;

View File

@ -60,6 +60,27 @@ namespace
const std::string& PANEL_MOVEMENT_NAME = "movement_panel";
const std::string& PANEL_CAMERA_NAME = "cam_panel";
const std::string& PANEL_GESTURE_NAME = "gesture_panel";
S32 get_panel_min_width(LLLayoutStack* stack, LLPanel* panel)
{
S32 minimal_width = 0;
llassert(stack);
if ( stack && panel && panel->getVisible() )
{
stack->getPanelMinSize(panel->getName(), &minimal_width, NULL);
}
return minimal_width;
}
S32 get_curr_width(LLUICtrl* ctrl)
{
S32 cur_width = 0;
if ( ctrl && ctrl->getVisible() )
{
cur_width = ctrl->getRect().getWidth();
}
return cur_width;
}
}
class LLBottomTrayLite
@ -80,6 +101,14 @@ public:
{
mNearbyChatBar = getChild<LLNearbyChatBar>("chat_bar");
mGesturePanel = getChild<LLPanel>("gesture_panel");
// Hide "show_nearby_chat" button
LLLineEditor* chat_box = mNearbyChatBar->getChatBox();
LLUICtrl* show_btn = mNearbyChatBar->getChild<LLUICtrl>("show_nearby_chat");
S32 delta_width = show_btn->getRect().getWidth();
show_btn->setVisible(FALSE);
chat_box->reshape(chat_box->getRect().getWidth() + delta_width, chat_box->getRect().getHeight());
return TRUE;
}
@ -433,6 +462,8 @@ BOOL LLBottomTray::postBuild()
mObjectDefaultWidthMap[RS_BUTTON_CAMERA] = mCamPanel->getRect().getWidth();
mObjectDefaultWidthMap[RS_BUTTON_SPEAK] = mSpeakPanel->getRect().getWidth();
mNearbyChatBar->getChatBox()->setContextMenu(NULL);
return TRUE;
}
@ -1084,58 +1115,131 @@ void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool vis
if (mDummiesMap.count(shown_object_type))
{
mDummiesMap[shown_object_type]->setVisible(visible);
// Hide/show layout panel for dummy icon.
mDummiesMap[shown_object_type]->getParent()->setVisible(visible);
}
}
void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification)
{
bool can_be_set = true;
if (!setVisibleAndFitWidths(shown_object_type, visible) && visible && raise_notification)
{
LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
LLSD(),
LLSD(),
LLNotificationFunctorRegistry::instance().DONOTHING);
}
}
bool LLBottomTray::setVisibleAndFitWidths(EResizeState object_type, bool visible)
{
LLPanel* cur_panel = mStateProcessedObjectMap[object_type];
if (NULL == cur_panel)
{
lldebugs << "There is no object to process for state: " << object_type << llendl;
return false;
}
const S32 dummy_width = mDummiesMap.count(object_type)
? mDummiesMap[object_type]->getParent()->getRect().getWidth()
: 0;
bool is_set = true;
if (visible)
{
LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
if (NULL == panel)
// Assume that only chiclet panel can be auto-resized and
// don't take into account width of dummy widgets
const S32 available_width =
mChicletPanel->getParent()->getRect().getWidth() -
mChicletPanel->getMinWidth() -
dummy_width;
S32 preferred_width = mObjectDefaultWidthMap[object_type];
S32 current_width = cur_panel->getRect().getWidth();
S32 result_width = 0;
bool decrease_width = false;
// Mark this button to be shown
mResizeState |= object_type;
if (preferred_width > 0 && available_width >= preferred_width)
{
lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
return;
result_width = preferred_width;
}
else if (available_width >= current_width)
{
result_width = current_width;
}
else
{
// Calculate the possible shrunk width as difference between current and minimal widths
const S32 chatbar_shrunk_width =
mNearbyChatBar->getRect().getWidth() - mNearbyChatBar->getMinWidth();
const S32 sum_of_min_widths =
get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_CAMERA]) +
get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_MOVEMENT]) +
get_panel_min_width(mToolbarStack, mStateProcessedObjectMap[RS_BUTTON_GESTURES]) +
get_panel_min_width(mToolbarStack, mSpeakPanel);
const S32 sum_of_curr_widths =
get_curr_width(mStateProcessedObjectMap[RS_BUTTON_CAMERA]) +
get_curr_width(mStateProcessedObjectMap[RS_BUTTON_MOVEMENT]) +
get_curr_width(mStateProcessedObjectMap[RS_BUTTON_GESTURES]) +
get_curr_width(mSpeakPanel);
const S32 possible_shrunk_width =
chatbar_shrunk_width + (sum_of_curr_widths - sum_of_min_widths);
// Minimal width of current panel
S32 minimal_width = 0;
mToolbarStack->getPanelMinSize(cur_panel->getName(), &minimal_width, NULL);
if ( (available_width + possible_shrunk_width) >= minimal_width)
{
// There is enough space for minimal width, but set the result_width
// to current_width so buttons widths decreasing will be done in predefined order
result_width = current_width;
decrease_width = true;
}
else
{
// Nothing can be done, give up...
return false;
}
}
const S32 dummy_width = mDummiesMap.count(shown_object_type) ? mDummiesMap[shown_object_type]->getRect().getWidth() : 0;
const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width)
+ (chiclet_panel_width - chiclet_panel_min_width);
const S32 required_width = panel->getRect().getWidth() + dummy_width;
can_be_set = available_width >= required_width;
}
if (can_be_set)
{
setTrayButtonVisible(shown_object_type, visible);
// if we hide the button mark it NOT to show while future bottom tray extending
if (!visible)
if (result_width != current_width)
{
mResizeState &= ~shown_object_type;
cur_panel->reshape(result_width, cur_panel->getRect().getHeight());
current_width = result_width;
}
is_set = processShowButton(object_type, &current_width);
// Shrink buttons if needed
if (is_set && decrease_width)
{
processWidthDecreased( -result_width - dummy_width );
}
}
else
{
// mark this button to show it while future bottom tray extending
mResizeState |= shown_object_type;
if ( raise_notification )
LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown",
LLSD(),
LLSD(),
LLNotificationFunctorRegistry::instance().DONOTHING);
const S32 delta_width = get_curr_width(cur_panel);
setTrayButtonVisible(object_type, false);
// Mark button NOT to show while future bottom tray extending
mResizeState &= ~object_type;
// Extend other buttons if need
if (delta_width)
{
processWidthIncreased(delta_width + dummy_width);
}
}
return is_set;
}
//EOF

View File

@ -173,6 +173,14 @@ private:
*/
void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification = true);
/**
* Sets passed visibility to required button and fit widths of shown
* buttons(notice that method can shrink widths to
* allocate needed room in bottom tray).
* Returns true if visibility of required button was set.
*/
bool setVisibleAndFitWidths(EResizeState object_type, bool visible);
MASK mResizeState;
typedef std::map<EResizeState, LLPanel*> state_object_map_t;

View File

@ -301,8 +301,10 @@ void LLCallFloater::updateSession()
refreshParticipantList();
updateAgentModeratorState();
//show floater for voice calls
if (!is_local_chat)
//show floater for voice calls & only in CONNECTED to voice channel state
if (!is_local_chat &&
voice_channel &&
LLVoiceChannel::STATE_CONNECTED == voice_channel->getState())
{
LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
bool show_me = !(im_floater && im_floater->getVisible());
@ -331,6 +333,7 @@ void LLCallFloater::refreshParticipantList()
{
mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));
mParticipants->setSortOrder(LLParticipantList::E_SORT_BY_RECENT_SPEAKERS);
if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
{
@ -675,8 +678,7 @@ void LLCallFloater::resetVoiceRemoveTimers()
void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
bool delete_it = true;
mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id, delete_it);
mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
}
bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
@ -718,7 +720,15 @@ void LLCallFloater::connectToChannel(LLVoiceChannel* channel)
void LLCallFloater::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
updateState(new_state);
// check is voice operational and if it doesn't work hide VCP (EXT-4397)
if(LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking())
{
updateState(new_state);
}
else
{
closeFloater();
}
}
void LLCallFloater::updateState(const LLVoiceChannel::EState& new_state)
@ -747,18 +757,26 @@ void LLCallFloater::reset(const LLVoiceChannel::EState& new_state)
mParticipants = NULL;
mAvatarList->clear();
// "loading" is shown in parcel with disabled voice only when state is "ringing"
// to avoid showing it in nearby chat vcp all the time- "no_one_near" is now shown there (EXT-4648)
bool show_loading = LLVoiceChannel::STATE_RINGING == new_state;
if(!show_loading && !LLViewerParcelMgr::getInstance()->allowAgentVoice() && mVoiceType == VC_LOCAL_CHAT)
// These ifs were added instead of simply showing "loading" to make VCP work correctly in parcels
// with disabled voice (EXT-4648 and EXT-4649)
if (!LLViewerParcelMgr::getInstance()->allowAgentVoice() && LLVoiceChannel::STATE_HUNG_UP == new_state)
{
// hides "Leave Call" when call is ended in parcel with disabled voice- hiding usually happens in
// updateSession() which won't be called here because connect to nearby voice never happens
childSetVisible("leave_call_btn_panel", false);
// setting title to nearby chat an "no one near..." text- because in region with disabled
// voice we won't have chance to really connect to nearby, so VCP is changed here manually
setTitle(getString("title_nearby"));
mAvatarList->setNoItemsCommentText(getString("no_one_near"));
}
else
// "loading" is shown only when state is "ringing" to avoid showing it in nearby chat vcp
// of parcels with disabled voice all the time- "no_one_near" is now shown there (EXT-4648)
else if (new_state == LLVoiceChannel::STATE_RINGING)
{
// update floater to show Loading while waiting for data.
mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
}
mAvatarList->setVisible(TRUE);
mNonAvatarCaller->setVisible(FALSE);

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