Merge remote-tracking branch 'lirusaito/VoiceUpdate'
This commit is contained in:
@@ -718,7 +718,14 @@
|
||||
|
||||
<key>UploadBakedTexture</key>
|
||||
<boolean>true</boolean>
|
||||
</map>
|
||||
|
||||
<key>ObjectMedia</key>
|
||||
<boolean>false</boolean>
|
||||
|
||||
<key>ObjectMediaNavigate</key>
|
||||
<boolean>false</boolean>
|
||||
|
||||
</map>
|
||||
|
||||
<key>messageBans</key>
|
||||
<map>
|
||||
|
||||
@@ -126,7 +126,7 @@ bool LLAudioEngine::init(const S32 num_channels, void* userdata)
|
||||
// Initialize the decode manager
|
||||
gAudioDecodeMgrp = new LLAudioDecodeMgr;
|
||||
|
||||
llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
|
||||
LL_INFOS("AudioEngine") << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -228,6 +228,28 @@ std::string LLAudioEngine::getInternetStreamURL()
|
||||
else return std::string();
|
||||
}
|
||||
|
||||
void LLAudioEngine::checkStates()
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
for (S32 i = 0; i < MAX_BUFFERS; i++)
|
||||
{
|
||||
if (mBuffers[i])
|
||||
{
|
||||
bool buf_has_ref = false;
|
||||
for (S32 j = 0; j < MAX_CHANNELS; j++)
|
||||
{
|
||||
if (mChannels[j])
|
||||
{
|
||||
if(mChannels[j]->mCurrentBufferp == mBuffers[i])
|
||||
buf_has_ref = true;
|
||||
}
|
||||
}
|
||||
if(buf_has_ref)
|
||||
llassert(mBuffers[i]->mInUse);
|
||||
}
|
||||
}
|
||||
#endif //SHOW_ASSERT
|
||||
}
|
||||
|
||||
void LLAudioEngine::updateChannels()
|
||||
{
|
||||
@@ -239,8 +261,31 @@ void LLAudioEngine::updateChannels()
|
||||
mChannels[i]->updateBuffer();
|
||||
mChannels[i]->update3DPosition();
|
||||
mChannels[i]->updateLoop();
|
||||
#ifdef SHOW_ASSERT
|
||||
if(mChannels[i]->getSource())
|
||||
llassert(mChannels[i]->mCurrentBufferp == mChannels[i]->getSource()->getCurrentBuffer());
|
||||
if(mChannels[i]->mCurrentBufferp)
|
||||
{
|
||||
bool found_buffer = false;
|
||||
for (S32 j = 0; j < MAX_BUFFERS; j++)
|
||||
{
|
||||
if (mBuffers[j])
|
||||
{
|
||||
if(mChannels[i]->mCurrentBufferp == mBuffers[j])
|
||||
found_buffer = true;
|
||||
}
|
||||
}
|
||||
llassert(found_buffer);
|
||||
if(!mChannels[i]->mCurrentBufferp->mInUse)
|
||||
{
|
||||
llassert(!mChannels[i]->isPlaying());
|
||||
llassert(!mChannels[i]->isWaiting());
|
||||
}
|
||||
}
|
||||
#endif //SHOW_ASSERT
|
||||
}
|
||||
}
|
||||
checkStates();
|
||||
}
|
||||
|
||||
static const F32 default_max_decode_time = .002f; // 2 ms
|
||||
@@ -311,9 +356,15 @@ void LLAudioEngine::idle(F32 max_decode_time)
|
||||
LLAudioChannel *channelp = getFreeChannel(max_priority);
|
||||
if (channelp)
|
||||
{
|
||||
//llinfos << "Replacing source in channel due to priority!" << llendl;
|
||||
max_sourcep->setChannel(channelp);
|
||||
LL_DEBUGS("AudioEngine") << "Replacing source in channel due to priority!" << llendl;
|
||||
llassert(max_sourcep->getChannel() == NULL);
|
||||
|
||||
llassert(channelp->mCurrentBufferp == NULL);
|
||||
channelp->setSource(max_sourcep);
|
||||
|
||||
llassert(max_sourcep == channelp->getSource());
|
||||
llassert(channelp->mCurrentBufferp == max_sourcep->getCurrentBuffer());
|
||||
|
||||
if (max_sourcep->isSyncSlave())
|
||||
{
|
||||
// A sync slave, it doesn't start playing until it's synced up with the master.
|
||||
@@ -348,18 +399,22 @@ void LLAudioEngine::idle(F32 max_decode_time)
|
||||
}
|
||||
|
||||
LLAudioChannel *channelp = sourcep->getChannel();
|
||||
if (!channelp)
|
||||
bool is_stopped = channelp && channelp->isPlaying();
|
||||
if (is_stopped || (sourcep->isLoop() && channelp->mLoopedThisFrame))
|
||||
{
|
||||
// This sound isn't playing, so we just process move the queue
|
||||
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
|
||||
sourcep->mQueuedDatap = NULL;
|
||||
|
||||
// Reset the timer so the source doesn't die.
|
||||
sourcep->mAgeTimer.reset();
|
||||
// Make sure we have the buffer set up if we just decoded the data
|
||||
if (sourcep->mCurrentDatap)
|
||||
if(is_stopped)
|
||||
{
|
||||
updateBufferForData(sourcep->mCurrentDatap);
|
||||
// Reset the timer so the source doesn't die.
|
||||
sourcep->mAgeTimer.reset();
|
||||
// Make sure we have the buffer set up if we just decoded the data
|
||||
if (sourcep->mCurrentDatap)
|
||||
{
|
||||
updateBufferForData(sourcep->mCurrentDatap);
|
||||
}
|
||||
}
|
||||
|
||||
// Actually play the associated data.
|
||||
@@ -372,52 +427,6 @@ void LLAudioEngine::idle(F32 max_decode_time)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check to see if the current sound is done playing, or looped.
|
||||
if (!channelp->isPlaying())
|
||||
{
|
||||
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
|
||||
sourcep->mQueuedDatap = NULL;
|
||||
|
||||
// Reset the timer so the source doesn't die.
|
||||
sourcep->mAgeTimer.reset();
|
||||
|
||||
// Make sure we have the buffer set up if we just decoded the data
|
||||
if (sourcep->mCurrentDatap)
|
||||
{
|
||||
updateBufferForData(sourcep->mCurrentDatap);
|
||||
}
|
||||
|
||||
// Actually play the associated data.
|
||||
sourcep->setupChannel();
|
||||
channelp = sourcep->getChannel();
|
||||
if (channelp)
|
||||
{
|
||||
channelp->updateBuffer();
|
||||
channelp->play();
|
||||
}
|
||||
}
|
||||
else if (sourcep->isLoop())
|
||||
{
|
||||
// It's a loop, we need to check and see if we're done with it.
|
||||
if (channelp->mLoopedThisFrame)
|
||||
{
|
||||
sourcep->mCurrentDatap = sourcep->mQueuedDatap;
|
||||
sourcep->mQueuedDatap = NULL;
|
||||
|
||||
// Actually, should do a time sync so if we're a loop master/slave
|
||||
// we don't drift away.
|
||||
sourcep->setupChannel();
|
||||
channelp = sourcep->getChannel();
|
||||
if (channelp)
|
||||
{
|
||||
channelp->updateBuffer();
|
||||
channelp->play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lame, update the channels AGAIN.
|
||||
@@ -491,7 +500,7 @@ void LLAudioEngine::idle(F32 max_decode_time)
|
||||
{
|
||||
if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
|
||||
{
|
||||
//llinfos << "Flushing unused buffer!" << llendl;
|
||||
LL_DEBUGS("AudioEngine") << "Flushing unused buffer!" << llendl;
|
||||
mBuffers[i]->mAudioDatap->mBufferp = NULL;
|
||||
delete mBuffers[i];
|
||||
mBuffers[i] = NULL;
|
||||
@@ -572,6 +581,8 @@ void LLAudioEngine::enableWind(bool enable)
|
||||
|
||||
LLAudioBuffer * LLAudioEngine::getFreeBuffer()
|
||||
{
|
||||
//checkStates(); //Fails
|
||||
|
||||
S32 i;
|
||||
for (i = 0; i < MAX_BUFFERS; i++)
|
||||
{
|
||||
@@ -582,6 +593,7 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
//checkStates(); // Fails
|
||||
|
||||
// Grab the oldest unused buffer
|
||||
F32 max_age = -1.f;
|
||||
@@ -601,10 +613,11 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()
|
||||
}
|
||||
}
|
||||
|
||||
//checkStates(); //Fails
|
||||
|
||||
if (buffer_id >= 0)
|
||||
{
|
||||
lldebugs << "Taking over unused buffer " << buffer_id << llendl;
|
||||
//llinfos << "Flushing unused buffer!" << llendl;
|
||||
LL_DEBUGS("AudioEngine") << "Taking over unused buffer! max_age=" << max_age << llendl;
|
||||
mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL;
|
||||
for (U32 i = 0; i < MAX_CHANNELS; i++)
|
||||
{
|
||||
@@ -612,12 +625,15 @@ LLAudioBuffer * LLAudioEngine::getFreeBuffer()
|
||||
if(channelp && channelp->mCurrentBufferp == mBuffers[buffer_id])
|
||||
{
|
||||
channelp->cleanup();
|
||||
llassert(channelp->mCurrentBufferp == NULL);
|
||||
}
|
||||
}
|
||||
delete mBuffers[buffer_id];
|
||||
mBuffers[buffer_id] = createBuffer();
|
||||
return mBuffers[buffer_id];
|
||||
}
|
||||
|
||||
//checkStates(); //Fails
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -638,6 +654,7 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
|
||||
// Channel is allocated but not playing right now, use it.
|
||||
if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting())
|
||||
{
|
||||
LL_DEBUGS("AudioEngine") << "Replacing unused channel" << llendl;
|
||||
mChannels[i]->cleanup();
|
||||
if (mChannels[i]->getSource())
|
||||
{
|
||||
@@ -670,9 +687,9 @@ LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("AudioEngine") << "Flushing min channel" << llendl;
|
||||
// Flush the minimum priority channel, and return it.
|
||||
min_channelp->cleanup();
|
||||
min_channelp->getSource()->setChannel(NULL);
|
||||
return min_channelp;
|
||||
}
|
||||
|
||||
@@ -1006,10 +1023,13 @@ LLAudioData * LLAudioEngine::getAudioData(const LLUUID &audio_uuid)
|
||||
if( sourcep && sourcep->getCurrentData() && sourcep->getCurrentData()->getID() == audio_uuid )
|
||||
{
|
||||
LLAudioChannel* chan=sourcep->getChannel();
|
||||
delete sourcep;
|
||||
if(chan)
|
||||
{
|
||||
LL_DEBUGS("AudioEngine") << "removeAudioData" << llendl;
|
||||
chan->cleanup();
|
||||
mAllSources.erase(iter2++);
|
||||
}
|
||||
delete sourcep;
|
||||
mAllSources.erase(iter2++);
|
||||
}
|
||||
else
|
||||
++iter2;
|
||||
@@ -1043,7 +1063,7 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
|
||||
iter = mAllSources.find(asp->getID());
|
||||
if (iter == mAllSources.end())
|
||||
{
|
||||
llwarns << "Cleaning up unknown audio source!" << llendl;
|
||||
LL_WARNS("AudioEngine") << "Cleaning up unknown audio source!" << llendl;
|
||||
return;
|
||||
}
|
||||
delete asp;
|
||||
@@ -1264,7 +1284,7 @@ void LLAudioEngine::startNextTransfer()
|
||||
|
||||
if (asset_id.notNull())
|
||||
{
|
||||
llinfos << "Getting asset data for: " << asset_id << llendl;
|
||||
LL_DEBUGS("AudioEngine") << "Getting asset data for: " << asset_id << llendl;
|
||||
gAudiop->mCurrentTransfer = asset_id;
|
||||
gAudiop->mCurrentTransferTimer.reset();
|
||||
gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
|
||||
@@ -1282,7 +1302,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
|
||||
{
|
||||
if (result_code)
|
||||
{
|
||||
llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
|
||||
LL_INFOS("AudioEngine") << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
|
||||
// Need to mark data as bad to avoid constant rerequests.
|
||||
LLAudioData *adp = gAudiop->getAudioData(uuid);
|
||||
if (adp)
|
||||
@@ -1299,7 +1319,7 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
|
||||
if (!adp)
|
||||
{
|
||||
// Should never happen
|
||||
llwarns << "Got asset callback without audio data for " << uuid << llendl;
|
||||
LL_WARNS("AudioEngine") << "Got asset callback without audio data for " << uuid << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1360,8 +1380,7 @@ LLAudioSource::~LLAudioSource()
|
||||
if (mChannelp)
|
||||
{
|
||||
// Stop playback of this sound
|
||||
mChannelp->setSource(NULL);
|
||||
setChannel(NULL);
|
||||
mChannelp->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1404,7 +1423,7 @@ void LLAudioSource::update()
|
||||
}
|
||||
else if (adp->hasCompletedDecode()) // Only mark corrupted after decode is done
|
||||
{
|
||||
llwarns << "Marking LLAudioSource corrupted for " << adp->getID() << llendl;
|
||||
LL_WARNS("AudioEngine") << "Marking LLAudioSource corrupted for " << adp->getID() << llendl;
|
||||
mCorrupted = true ;
|
||||
}
|
||||
}
|
||||
@@ -1463,6 +1482,8 @@ bool LLAudioSource::setupChannel()
|
||||
}
|
||||
|
||||
mChannelp->setSource(this);
|
||||
llassert(this == mChannelp->getSource());
|
||||
llassert(mChannelp->mCurrentBufferp == getCurrentBuffer());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1474,8 +1495,8 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
|
||||
{
|
||||
if (getChannel())
|
||||
{
|
||||
llassert(this == getChannel()->getSource());
|
||||
getChannel()->setSource(NULL);
|
||||
setChannel(NULL);
|
||||
if (!isMuted())
|
||||
{
|
||||
mCurrentDatap = NULL;
|
||||
@@ -1727,13 +1748,20 @@ LLAudioChannel::LLAudioChannel() :
|
||||
|
||||
LLAudioChannel::~LLAudioChannel()
|
||||
{
|
||||
llassert(mCurrentBufferp == NULL);
|
||||
|
||||
// Need to disconnect any sources which are using this channel.
|
||||
//llinfos << "Cleaning up audio channel" << llendl;
|
||||
if (mCurrentSourcep)
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void LLAudioChannel::cleanup()
|
||||
{
|
||||
if(mCurrentSourcep)
|
||||
mCurrentSourcep->setChannel(NULL);
|
||||
}
|
||||
mCurrentBufferp = NULL;
|
||||
mCurrentSourcep = NULL;
|
||||
mWaiting = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1744,22 +1772,21 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
|
||||
if (!sourcep)
|
||||
{
|
||||
// Clearing the source for this channel, don't need to do anything.
|
||||
//llinfos << "Clearing source for channel" << llendl;
|
||||
LL_DEBUGS("AudioEngine") << "Clearing source for channel" << llendl;
|
||||
cleanup();
|
||||
mCurrentSourcep = NULL;
|
||||
mWaiting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sourcep == mCurrentSourcep)
|
||||
{
|
||||
// Don't reallocate the channel, this will make FMOD goofy.
|
||||
//llinfos << "Calling setSource with same source!" << llendl;
|
||||
LL_DEBUGS("AudioEngine") << "Calling setSource with same source!" << llendl;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
mCurrentSourcep = sourcep;
|
||||
|
||||
|
||||
mCurrentSourcep->setChannel(this);
|
||||
|
||||
updateBuffer();
|
||||
update3DPosition();
|
||||
}
|
||||
@@ -1796,7 +1823,12 @@ bool LLAudioChannel::updateBuffer()
|
||||
// The source changed what buffer it's playing. We need to clean up
|
||||
// the existing channel
|
||||
//
|
||||
LLAudioSource* source = mCurrentSourcep;
|
||||
cleanup();
|
||||
mCurrentSourcep = source;
|
||||
mCurrentSourcep->setChannel(this);
|
||||
|
||||
llassert(mCurrentBufferp == NULL);
|
||||
|
||||
mCurrentBufferp = bufferp;
|
||||
if (bufferp)
|
||||
@@ -1856,7 +1888,7 @@ bool LLAudioData::load()
|
||||
if (mBufferp)
|
||||
{
|
||||
// We already have this sound in a buffer, don't do anything.
|
||||
llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl;
|
||||
LL_INFOS("AudioEngine") << "Already have a buffer for this sound, don't bother loading!" << llendl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1864,7 +1896,7 @@ bool LLAudioData::load()
|
||||
if (!mBufferp)
|
||||
{
|
||||
// No free buffers, abort.
|
||||
lldebugs << "Not able to allocate a new audio buffer, aborting." << llendl;
|
||||
LL_DEBUGS("AudioEngine") << "Not able to allocate a new audio buffer, aborting." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,8 @@ public:
|
||||
static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status);
|
||||
|
||||
friend class LLPipeline; // For debugging
|
||||
|
||||
void checkStates();
|
||||
public:
|
||||
F32 mMaxWindGain; // Hack. Public to set before fade in?
|
||||
|
||||
@@ -447,7 +449,7 @@ public:
|
||||
protected:
|
||||
virtual void play() = 0;
|
||||
virtual void playSynced(LLAudioChannel *channelp) = 0;
|
||||
virtual void cleanup() = 0;
|
||||
virtual void cleanup();
|
||||
void setWaiting(bool waiting) { mWaiting = waiting; }
|
||||
|
||||
public:
|
||||
|
||||
@@ -576,6 +576,7 @@ void LLAudioChannelFMOD::updateLoop()
|
||||
|
||||
void LLAudioChannelFMOD::cleanup()
|
||||
{
|
||||
LLAudioChannel::cleanup();
|
||||
if (!mChannelID)
|
||||
{
|
||||
//llinfos << "Aborting cleanup with no channelID." << llendl;
|
||||
@@ -588,7 +589,6 @@ void LLAudioChannelFMOD::cleanup()
|
||||
LL_DEBUGS("FMOD") << "LLAudioChannelFMOD::cleanup error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
|
||||
}
|
||||
|
||||
mCurrentBufferp = NULL;
|
||||
mChannelID = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -70,12 +70,172 @@ bool attemptDelayLoad()
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool sVerboseDebugging = false;
|
||||
|
||||
FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
|
||||
|
||||
FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0};
|
||||
|
||||
LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler)
|
||||
//This class is designed to keep track of all sound<->channel assocations.
|
||||
//Used to verify validity of sound and channel pointers, as well as catch cases were sounds
|
||||
//are released with active channels still attached.
|
||||
class CFMODSoundChecks
|
||||
{
|
||||
typedef std::map<FMOD::Sound*,std::set<FMOD::Channel*> > active_sounds_t;
|
||||
typedef std::set<FMOD::Sound*> dead_sounds_t;
|
||||
typedef std::map<FMOD::Channel*,FMOD::Sound*> active_channels_t;
|
||||
typedef std::map<FMOD::Channel*,FMOD::Sound*> dead_channels_t;
|
||||
|
||||
active_sounds_t mActiveSounds;
|
||||
dead_sounds_t mDeadSounds;
|
||||
active_channels_t mActiveChannels;
|
||||
dead_channels_t mDeadChannels;
|
||||
public:
|
||||
enum STATUS
|
||||
{
|
||||
ACTIVE,
|
||||
DEAD,
|
||||
UNKNOWN
|
||||
};
|
||||
STATUS getPtrStatus(LLAudioChannelFMODEX* channel)
|
||||
{
|
||||
if(!channel)
|
||||
return UNKNOWN;
|
||||
return getPtrStatus(channel->mChannelp);
|
||||
}
|
||||
STATUS getPtrStatus(LLAudioBufferFMODEX* sound)
|
||||
{
|
||||
if(!sound)
|
||||
return UNKNOWN;
|
||||
return getPtrStatus(sound->mSoundp);
|
||||
}
|
||||
STATUS getPtrStatus(FMOD::Channel* channel)
|
||||
{
|
||||
if(!channel)
|
||||
return UNKNOWN;
|
||||
else if(mActiveChannels.find(channel) != mActiveChannels.end())
|
||||
return ACTIVE;
|
||||
else if(mDeadChannels.find(channel) != mDeadChannels.end())
|
||||
return DEAD;
|
||||
return UNKNOWN;
|
||||
}
|
||||
STATUS getPtrStatus(FMOD::Sound* sound)
|
||||
{
|
||||
if(!sound)
|
||||
return UNKNOWN;
|
||||
if(mActiveSounds.find(sound) != mActiveSounds.end())
|
||||
return ACTIVE;
|
||||
else if(mDeadSounds.find(sound) != mDeadSounds.end())
|
||||
return DEAD;
|
||||
return UNKNOWN;
|
||||
}
|
||||
void addNewSound(FMOD::Sound* sound)
|
||||
{
|
||||
llassert(getPtrStatus(sound) != ACTIVE);
|
||||
|
||||
mDeadSounds.erase(sound);
|
||||
mActiveSounds.insert(std::make_pair(sound,std::set<FMOD::Channel*>()));
|
||||
}
|
||||
void removeSound(FMOD::Sound* sound)
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
STATUS status = getPtrStatus(sound);
|
||||
llassert(status != DEAD);
|
||||
llassert(status != UNKNOWN);
|
||||
#endif
|
||||
|
||||
active_sounds_t::const_iterator it = mActiveSounds.find(sound);
|
||||
llassert(it != mActiveSounds.end());
|
||||
if(it != mActiveSounds.end())
|
||||
{
|
||||
if(!it->second.empty())
|
||||
{
|
||||
#ifdef LL_RELEASE_FOR_DOWNLOAD
|
||||
LL_WARNS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n";
|
||||
#else
|
||||
LL_ERRS("AudioImpl") << "Removing sound " << sound << " with attached channels: \n";
|
||||
#endif
|
||||
for(std::set<FMOD::Channel*>::iterator it2 = it->second.begin(); it2 != it->second.end();++it2)
|
||||
{
|
||||
switch(getPtrStatus(*it2))
|
||||
{
|
||||
case ACTIVE:
|
||||
llcont << " Channel " << *it2 << " ACTIVE\n";
|
||||
break;
|
||||
case DEAD:
|
||||
llcont << " Channel " << *it2 << " DEAD\n";
|
||||
break;
|
||||
default:
|
||||
llcont << " Channel " << *it2 << " UNKNOWN\n";
|
||||
}
|
||||
}
|
||||
llcont << llendl;
|
||||
}
|
||||
mDeadSounds.insert(sound);
|
||||
mActiveSounds.erase(sound);
|
||||
}
|
||||
}
|
||||
void addNewChannelToSound(FMOD::Sound* sound,FMOD::Channel* channel)
|
||||
{
|
||||
STATUS status = getPtrStatus(sound);
|
||||
llassert(status != DEAD);
|
||||
llassert(status != UNKNOWN);
|
||||
status = getPtrStatus(channel);
|
||||
llassert(status != ACTIVE);
|
||||
|
||||
mActiveSounds[sound].insert(channel);
|
||||
mActiveChannels.insert(std::make_pair(channel,sound));
|
||||
}
|
||||
void removeChannel(FMOD::Channel* channel)
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
STATUS status = getPtrStatus(channel);
|
||||
llassert(status != DEAD);
|
||||
llassert(status != UNKNOWN);
|
||||
#endif
|
||||
|
||||
active_channels_t::const_iterator it = mActiveChannels.find(channel);
|
||||
llassert(it != mActiveChannels.end());
|
||||
if(it != mActiveChannels.end())
|
||||
{
|
||||
#ifdef SHOW_ASSERT
|
||||
STATUS status = getPtrStatus(it->second);
|
||||
llassert(status != DEAD);
|
||||
llassert(status != UNKNOWN);
|
||||
#endif
|
||||
|
||||
active_sounds_t::iterator it2 = mActiveSounds.find(it->second);
|
||||
llassert(it2 != mActiveSounds.end());
|
||||
if(it2 != mActiveSounds.end())
|
||||
{
|
||||
it2->second.erase(channel);
|
||||
}
|
||||
mDeadChannels.insert(*it);
|
||||
mActiveChannels.erase(channel);
|
||||
}
|
||||
}
|
||||
} gSoundCheck;
|
||||
|
||||
bool isActive(LLAudioChannel* channel)
|
||||
{
|
||||
return gSoundCheck.getPtrStatus(dynamic_cast<LLAudioChannelFMODEX*>(channel)) == CFMODSoundChecks::ACTIVE;
|
||||
}
|
||||
bool isActive(LLAudioBuffer* sound)
|
||||
{
|
||||
return gSoundCheck.getPtrStatus(dynamic_cast<LLAudioBufferFMODEX*>(sound)) == CFMODSoundChecks::ACTIVE;
|
||||
}
|
||||
|
||||
#define CHECK_PTR(ptr) \
|
||||
if(sVerboseDebugging){\
|
||||
CFMODSoundChecks::STATUS chan = gSoundCheck.getPtrStatus(ptr); \
|
||||
if(chan == CFMODSoundChecks::DEAD) \
|
||||
LL_DEBUGS("AudioImpl") << __FUNCTION__ << ": Using dead " << typeid(ptr).name() << " " << ptr << llendl; \
|
||||
else if(chan == CFMODSoundChecks::UNKNOWN) \
|
||||
LL_DEBUGS("AudioImpl") << __FUNCTION__ << ": Using unknown " << typeid(ptr).name() << " " << ptr << llendl;} \
|
||||
|
||||
LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging)
|
||||
{
|
||||
sVerboseDebugging = verbose_debugging;
|
||||
mInited = false;
|
||||
mWindGen = NULL;
|
||||
mWindDSP = NULL;
|
||||
@@ -93,7 +253,7 @@ inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string)
|
||||
{
|
||||
if(result == FMOD_OK)
|
||||
return false;
|
||||
llwarns << string << " Error: " << FMOD_ErrorString(result) << llendl;
|
||||
LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << llendl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,11 +261,11 @@ void* F_STDCALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type, const cha
|
||||
{
|
||||
if(type & FMOD_MEMORY_STREAM_DECODE)
|
||||
{
|
||||
llinfos << "Decode buffer size: " << size << llendl;
|
||||
LL_INFOS("AudioImpl") << "Decode buffer size: " << size << llendl;
|
||||
}
|
||||
else if(type & FMOD_MEMORY_STREAM_FILE)
|
||||
{
|
||||
llinfos << "Strean buffer size: " << size << llendl;
|
||||
LL_INFOS("AudioImpl") << "Stream buffer size: " << size << llendl;
|
||||
}
|
||||
return new char[size];
|
||||
}
|
||||
@@ -344,7 +504,7 @@ void LLAudioEngine_FMODEX::allocateListener(void)
|
||||
mListenerp = (LLListener *) new LLListener_FMODEX(mSystem);
|
||||
if (!mListenerp)
|
||||
{
|
||||
llwarns << "Listener creation failed" << llendl;
|
||||
LL_WARNS("AudioImpl") << "Listener creation failed" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,13 +513,16 @@ void LLAudioEngine_FMODEX::shutdown()
|
||||
{
|
||||
stopInternetStream();
|
||||
|
||||
llinfos << "About to LLAudioEngine::shutdown()" << llendl;
|
||||
LL_INFOS("AudioImpl") << "About to LLAudioEngine::shutdown()" << llendl;
|
||||
LLAudioEngine::shutdown();
|
||||
|
||||
llinfos << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl;
|
||||
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() closing FMOD Ex" << llendl;
|
||||
if ( mSystem ) // speculative fix for MAINT-2657
|
||||
{
|
||||
mSystem->close();
|
||||
mSystem->release();
|
||||
llinfos << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl;
|
||||
}
|
||||
LL_INFOS("AudioImpl") << "LLAudioEngine_FMODEX::shutdown() done closing FMOD Ex" << llendl;
|
||||
|
||||
delete mListenerp;
|
||||
mListenerp = NULL;
|
||||
@@ -490,6 +653,34 @@ LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChanne
|
||||
|
||||
LLAudioChannelFMODEX::~LLAudioChannelFMODEX()
|
||||
{
|
||||
if(sVerboseDebugging)
|
||||
LL_DEBUGS("AudioImpl") << "Destructing Audio Channel. mChannelp = " << mChannelp << llendl;
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
static FMOD_RESULT F_CALLBACK channel_callback(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2)
|
||||
{
|
||||
if(type == FMOD_CHANNEL_CALLBACKTYPE_END)
|
||||
{
|
||||
FMOD::Channel* chan = reinterpret_cast<FMOD::Channel*>(channel);
|
||||
LLAudioChannelFMODEX* audio_channel = NULL;
|
||||
chan->getUserData((void**)&audio_channel);
|
||||
if(audio_channel)
|
||||
{
|
||||
audio_channel->onRelease();
|
||||
}
|
||||
}
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
void LLAudioChannelFMODEX::onRelease()
|
||||
{
|
||||
llassert(mChannelp);
|
||||
if(sVerboseDebugging)
|
||||
LL_DEBUGS("AudioImpl") << "Fmod signaled channel release for channel " << mChannelp << llendl;
|
||||
gSoundCheck.removeChannel(mChannelp);
|
||||
mChannelp = NULL; //Null out channel here so cleanup doesn't try to redundantly stop it.
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@@ -502,13 +693,16 @@ bool LLAudioChannelFMODEX::updateBuffer()
|
||||
|
||||
LLAudioBufferFMODEX *bufferp = (LLAudioBufferFMODEX *)mCurrentSourcep->getCurrentBuffer();
|
||||
|
||||
llassert(mCurrentBufferp != NULL);
|
||||
llassert(mCurrentBufferp == bufferp);
|
||||
|
||||
// Grab the FMOD sample associated with the buffer
|
||||
FMOD::Sound *soundp = bufferp->getSound();
|
||||
if (!soundp)
|
||||
{
|
||||
// This is bad, there should ALWAYS be a sound associated with a legit
|
||||
// buffer.
|
||||
llerrs << "No FMOD sound!" << llendl;
|
||||
LL_ERRS("AudioImpl") << "No FMOD sound!" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -517,11 +711,21 @@ bool LLAudioChannelFMODEX::updateBuffer()
|
||||
// setup.
|
||||
if(!mChannelp)
|
||||
{
|
||||
llassert(!isActive(this));
|
||||
|
||||
FMOD_RESULT result = getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp);
|
||||
Check_FMOD_Error(result, "FMOD::System::playSound");
|
||||
}
|
||||
if(result == FMOD_OK)
|
||||
{
|
||||
if(sVerboseDebugging)
|
||||
LL_DEBUGS("AudioImpl") << "Created channel " << mChannelp << " for sound " << soundp << llendl;
|
||||
|
||||
//llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
|
||||
gSoundCheck.addNewChannelToSound(soundp,mChannelp);
|
||||
mChannelp->setCallback(&channel_callback);
|
||||
mChannelp->setUserData(this);
|
||||
llassert(isActive(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a source for the channel, we need to update its gain.
|
||||
@@ -530,18 +734,12 @@ bool LLAudioChannelFMODEX::updateBuffer()
|
||||
// SJB: warnings can spam and hurt framerate, disabling
|
||||
FMOD_RESULT result;
|
||||
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
result = mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain());
|
||||
Check_FMOD_Error(result, "FMOD::Channel::setVolume");
|
||||
result = mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
|
||||
Check_FMOD_Error(result, "FMOD::Channel::setMode");
|
||||
/*if(Check_FMOD_Error(result, "FMOD::Channel::setMode"))
|
||||
{
|
||||
S32 index;
|
||||
mChannelp->getIndex(&index);
|
||||
llwarns << "Channel " << index << "Source ID: " << mCurrentSourcep->getID()
|
||||
<< " at " << mCurrentSourcep->getPositionGlobal() << llendl;
|
||||
}*/
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -564,6 +762,8 @@ void LLAudioChannelFMODEX::update3DPosition()
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
if (mCurrentSourcep->isAmbient())
|
||||
{
|
||||
// Ambient sound, don't need to do any positional updates.
|
||||
@@ -590,6 +790,8 @@ void LLAudioChannelFMODEX::updateLoop()
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
//
|
||||
// Hack: We keep track of whether we looped or not by seeing when the
|
||||
// sample position looks like it's going backwards. Not reliable; may
|
||||
@@ -608,17 +810,30 @@ void LLAudioChannelFMODEX::updateLoop()
|
||||
|
||||
void LLAudioChannelFMODEX::cleanup()
|
||||
{
|
||||
LLAudioChannel::cleanup();
|
||||
|
||||
if (!mChannelp)
|
||||
{
|
||||
llassert(!isActive(this));
|
||||
llassert(mCurrentBufferp == NULL);
|
||||
//llinfos << "Aborting cleanup with no channel handle." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
//llinfos << "Cleaning up channel: " << mChannelID << llendl;
|
||||
Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop");
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
if(sVerboseDebugging)
|
||||
LL_DEBUGS("AudioImpl") << "Stopping channel " << mChannelp << llendl;
|
||||
|
||||
mChannelp->setCallback(NULL);
|
||||
if(!Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"))
|
||||
{
|
||||
gSoundCheck.removeChannel(mChannelp);
|
||||
}
|
||||
|
||||
mCurrentBufferp = NULL;
|
||||
mChannelp = NULL;
|
||||
llassert(!isActive(this));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -626,12 +841,19 @@ void LLAudioChannelFMODEX::play()
|
||||
{
|
||||
if (!mChannelp)
|
||||
{
|
||||
llwarns << "Playing without a channel handle, aborting" << llendl;
|
||||
LL_WARNS("AudioImpl") << "Playing without a channel handle, aborting" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
llassert(isActive(this));
|
||||
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
|
||||
if(sVerboseDebugging)
|
||||
LL_DEBUGS("AudioImpl") << "Playing channel " << mChannelp << llendl;
|
||||
|
||||
getSource()->setPlayedOnce(true);
|
||||
|
||||
if(LLAudioEngine_FMODEX::mChannelGroups[getSource()->getType()])
|
||||
@@ -648,6 +870,8 @@ void LLAudioChannelFMODEX::playSynced(LLAudioChannel *channelp)
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
U32 cur_pos;
|
||||
if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position"))
|
||||
return;
|
||||
@@ -669,6 +893,8 @@ bool LLAudioChannelFMODEX::isPlaying()
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
bool paused, playing;
|
||||
Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused");
|
||||
Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying");
|
||||
@@ -690,7 +916,12 @@ LLAudioBufferFMODEX::~LLAudioBufferFMODEX()
|
||||
{
|
||||
if(mSoundp)
|
||||
{
|
||||
if(sVerboseDebugging)
|
||||
LL_DEBUGS("AudioImpl") << "Release sound " << mSoundp << llendl;
|
||||
|
||||
CHECK_PTR(mSoundp);
|
||||
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release");
|
||||
gSoundCheck.removeSound(mSoundp);
|
||||
mSoundp = NULL;
|
||||
}
|
||||
}
|
||||
@@ -714,8 +945,10 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
|
||||
|
||||
if (mSoundp)
|
||||
{
|
||||
CHECK_PTR(mSoundp);
|
||||
// If there's already something loaded in this buffer, clean it up.
|
||||
Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release");
|
||||
gSoundCheck.removeSound(mSoundp);
|
||||
mSoundp = NULL;
|
||||
}
|
||||
|
||||
@@ -734,7 +967,7 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
// We failed to load the file for some reason.
|
||||
llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl;
|
||||
LL_WARNS("AudioImpl") << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl;
|
||||
|
||||
//
|
||||
// If we EVER want to load wav files provided by end users, we need
|
||||
@@ -745,6 +978,8 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
gSoundCheck.addNewSound(mSoundp);
|
||||
|
||||
// Everything went well, return true
|
||||
return true;
|
||||
}
|
||||
@@ -757,6 +992,7 @@ U32 LLAudioBufferFMODEX::getLength()
|
||||
return 0;
|
||||
}
|
||||
|
||||
CHECK_PTR(mSoundp);
|
||||
U32 length;
|
||||
Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength");
|
||||
return length;
|
||||
@@ -765,6 +1001,8 @@ U32 LLAudioBufferFMODEX::getLength()
|
||||
|
||||
void LLAudioChannelFMODEX::set3DMode(bool use3d)
|
||||
{
|
||||
CHECK_PTR(mChannelp);
|
||||
|
||||
FMOD_MODE current_mode;
|
||||
if(Check_FMOD_Error(mChannelp->getMode(¤t_mode),"FMOD::Channel::getMode"))
|
||||
return;
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace FMOD
|
||||
class LLAudioEngine_FMODEX : public LLAudioEngine
|
||||
{
|
||||
public:
|
||||
LLAudioEngine_FMODEX(bool enable_profiler);
|
||||
LLAudioEngine_FMODEX(bool enable_profiler, bool verbose_debugging);
|
||||
virtual ~LLAudioEngine_FMODEX();
|
||||
|
||||
// initialization/startup/shutdown
|
||||
@@ -95,7 +95,7 @@ class LLAudioChannelFMODEX : public LLAudioChannel
|
||||
public:
|
||||
LLAudioChannelFMODEX(FMOD::System *audioengine);
|
||||
virtual ~LLAudioChannelFMODEX();
|
||||
|
||||
void onRelease();
|
||||
protected:
|
||||
/*virtual*/ void play();
|
||||
/*virtual*/ void playSynced(LLAudioChannel *channelp);
|
||||
@@ -112,6 +112,8 @@ protected:
|
||||
FMOD::System *mSystemp;
|
||||
FMOD::Channel *mChannelp;
|
||||
S32 mLastSamplePos;
|
||||
|
||||
friend class CFMODSoundChecks;
|
||||
};
|
||||
|
||||
|
||||
@@ -129,6 +131,8 @@ protected:
|
||||
FMOD::System *mSystemp;
|
||||
FMOD::Sound *getSound() const{ return mSoundp; }
|
||||
FMOD::Sound *mSoundp;
|
||||
|
||||
friend class CFMODSoundChecks;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -186,10 +186,9 @@ LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
|
||||
|
||||
void LLAudioChannelOpenAL::cleanup()
|
||||
{
|
||||
LLAudioChannel::cleanup();
|
||||
alSourceStop(mALSource);
|
||||
alSourcei(mALSource, AL_BUFFER, AL_NONE);
|
||||
|
||||
mCurrentBufferp = NULL;
|
||||
}
|
||||
|
||||
void LLAudioChannelOpenAL::play()
|
||||
|
||||
@@ -76,6 +76,7 @@ set(llcommon_SOURCE_FILES
|
||||
llrun.cpp
|
||||
llscopedvolatileaprpool.h
|
||||
llsd.cpp
|
||||
llsdparam.cpp
|
||||
llsdserialize.cpp
|
||||
llsdserialize_xml.cpp
|
||||
llsdutil.cpp
|
||||
@@ -204,10 +205,11 @@ set(llcommon_HEADER_FILES
|
||||
llqueuedthread.h
|
||||
llrand.h
|
||||
llrefcount.h
|
||||
llrefcount.h
|
||||
llregistry.h
|
||||
llrun.h
|
||||
llsafehandle.h
|
||||
llsd.h
|
||||
llsdparam.h
|
||||
llsdserialize.h
|
||||
llsdserialize_xml.h
|
||||
llsdutil.h
|
||||
|
||||
358
indra/llcommon/llregistry.h
Normal file
358
indra/llcommon/llregistry.h
Normal file
@@ -0,0 +1,358 @@
|
||||
/**
|
||||
* @file llregistry.h
|
||||
* @brief template classes for registering name, value pairs in nested scopes, statically, etc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLREGISTRY_H
|
||||
#define LL_LLREGISTRY_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <boost/type_traits.hpp>
|
||||
#include "llsingleton.h"
|
||||
#include "llstl.h"
|
||||
|
||||
template <typename T>
|
||||
struct LLRegistryDefaultComparator
|
||||
{
|
||||
bool operator()(const T& lhs, const T& rhs) const
|
||||
{
|
||||
using std::less;
|
||||
return less<T>()(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
|
||||
class LLRegistry
|
||||
{
|
||||
public:
|
||||
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
|
||||
typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t;
|
||||
typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t;
|
||||
typedef typename boost::add_reference<VALUE>::type ref_value_t;
|
||||
typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t;
|
||||
typedef typename boost::add_pointer<VALUE>::type ptr_value_t;
|
||||
|
||||
class Registrar
|
||||
{
|
||||
friend class LLRegistry<KEY, VALUE, COMPARATOR>;
|
||||
public:
|
||||
typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
|
||||
|
||||
bool add(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
if (mMap.insert(std::make_pair(key, value)).second == false)
|
||||
{
|
||||
llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void remove(ref_const_key_t key)
|
||||
{
|
||||
mMap.erase(key);
|
||||
}
|
||||
|
||||
void replace(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
mMap[key] = value;
|
||||
}
|
||||
|
||||
typename registry_map_t::const_iterator beginItems() const
|
||||
{
|
||||
return mMap.begin();
|
||||
}
|
||||
|
||||
typename registry_map_t::const_iterator endItems() const
|
||||
{
|
||||
return mMap.end();
|
||||
}
|
||||
|
||||
protected:
|
||||
ptr_value_t getValue(ref_const_key_t key)
|
||||
{
|
||||
typename registry_map_t::iterator found_it = mMap.find(key);
|
||||
if (found_it != mMap.end())
|
||||
{
|
||||
return &(found_it->second);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr_const_value_t getValue(ref_const_key_t key) const
|
||||
{
|
||||
typename registry_map_t::const_iterator found_it = mMap.find(key);
|
||||
if (found_it != mMap.end())
|
||||
{
|
||||
return &(found_it->second);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if the registry is used to store pointers, and null values are valid entries
|
||||
// then use this function to check the existence of an entry
|
||||
bool exists(ref_const_key_t key) const
|
||||
{
|
||||
return mMap.find(key) != mMap.end();
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return mMap.empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
// use currentRegistrar() or defaultRegistrar()
|
||||
Registrar() {}
|
||||
~Registrar() {}
|
||||
|
||||
private:
|
||||
registry_map_t mMap;
|
||||
};
|
||||
|
||||
typedef typename std::list<Registrar*> scope_list_t;
|
||||
typedef typename std::list<Registrar*>::iterator scope_list_iterator_t;
|
||||
typedef typename std::list<Registrar*>::const_iterator scope_list_const_iterator_t;
|
||||
|
||||
LLRegistry()
|
||||
{}
|
||||
|
||||
~LLRegistry() {}
|
||||
|
||||
ptr_value_t getValue(ref_const_key_t key)
|
||||
{
|
||||
for(scope_list_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
ptr_value_t valuep = (*it)->getValue(key);
|
||||
if (valuep != NULL) return valuep;
|
||||
}
|
||||
return mDefaultRegistrar.getValue(key);
|
||||
}
|
||||
|
||||
ptr_const_value_t getValue(ref_const_key_t key) const
|
||||
{
|
||||
for(scope_list_const_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
ptr_value_t valuep = (*it)->getValue(key);
|
||||
if (valuep != NULL) return valuep;
|
||||
}
|
||||
return mDefaultRegistrar.getValue(key);
|
||||
}
|
||||
|
||||
bool exists(ref_const_key_t key) const
|
||||
{
|
||||
for(scope_list_const_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
if ((*it)->exists(key)) return true;
|
||||
}
|
||||
|
||||
return mDefaultRegistrar.exists(key);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
for(scope_list_const_iterator_t it = mActiveScopes.begin();
|
||||
it != mActiveScopes.end();
|
||||
++it)
|
||||
{
|
||||
if (!(*it)->empty()) return false;
|
||||
}
|
||||
|
||||
return mDefaultRegistrar.empty();
|
||||
}
|
||||
|
||||
|
||||
Registrar& defaultRegistrar()
|
||||
{
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
const Registrar& defaultRegistrar() const
|
||||
{
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
|
||||
Registrar& currentRegistrar()
|
||||
{
|
||||
if (!mActiveScopes.empty())
|
||||
{
|
||||
return *mActiveScopes.front();
|
||||
}
|
||||
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
const Registrar& currentRegistrar() const
|
||||
{
|
||||
if (!mActiveScopes.empty())
|
||||
{
|
||||
return *mActiveScopes.front();
|
||||
}
|
||||
|
||||
return mDefaultRegistrar;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
void addScope(Registrar* scope)
|
||||
{
|
||||
// newer scopes go up front
|
||||
mActiveScopes.insert(mActiveScopes.begin(), scope);
|
||||
}
|
||||
|
||||
void removeScope(Registrar* scope)
|
||||
{
|
||||
// O(N) but should be near the beggining and N should be small and this is safer than storing iterators
|
||||
scope_list_iterator_t iter = std::find(mActiveScopes.begin(), mActiveScopes.end(), scope);
|
||||
if (iter != mActiveScopes.end())
|
||||
{
|
||||
mActiveScopes.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
scope_list_t mActiveScopes;
|
||||
Registrar mDefaultRegistrar;
|
||||
};
|
||||
|
||||
template <typename KEY, typename VALUE, typename DERIVED_TYPE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
|
||||
class LLRegistrySingleton
|
||||
: public LLRegistry<KEY, VALUE, COMPARATOR>,
|
||||
public LLSingleton<DERIVED_TYPE>
|
||||
{
|
||||
friend class LLSingleton<DERIVED_TYPE>;
|
||||
public:
|
||||
typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
|
||||
typedef const KEY& ref_const_key_t;
|
||||
typedef const VALUE& ref_const_value_t;
|
||||
typedef VALUE* ptr_value_t;
|
||||
typedef const VALUE* ptr_const_value_t;
|
||||
typedef LLSingleton<DERIVED_TYPE> singleton_t;
|
||||
|
||||
class ScopedRegistrar : public registry_t::Registrar
|
||||
{
|
||||
public:
|
||||
ScopedRegistrar(bool push_scope = true)
|
||||
{
|
||||
if (push_scope)
|
||||
{
|
||||
pushScope();
|
||||
}
|
||||
}
|
||||
|
||||
~ScopedRegistrar()
|
||||
{
|
||||
if (!singleton_t::destroyed())
|
||||
{
|
||||
popScope();
|
||||
}
|
||||
}
|
||||
|
||||
void pushScope()
|
||||
{
|
||||
singleton_t::instance().addScope(this);
|
||||
}
|
||||
|
||||
void popScope()
|
||||
{
|
||||
singleton_t::instance().removeScope(this);
|
||||
}
|
||||
|
||||
ptr_value_t getValueFromScope(ref_const_key_t key)
|
||||
{
|
||||
return getValue(key);
|
||||
}
|
||||
|
||||
ptr_const_value_t getValueFromScope(ref_const_key_t key) const
|
||||
{
|
||||
return getValue(key);
|
||||
}
|
||||
|
||||
private:
|
||||
typename std::list<typename registry_t::Registrar*>::iterator mListIt;
|
||||
};
|
||||
|
||||
class StaticRegistrar : public registry_t::Registrar
|
||||
{
|
||||
public:
|
||||
virtual ~StaticRegistrar() {}
|
||||
StaticRegistrar(ref_const_key_t key, ref_const_value_t value)
|
||||
{
|
||||
if(!singleton_t::instance().mStaticScope)
|
||||
mStaticScope = new ScopedRegistrar();
|
||||
singleton_t::instance().mStaticScope->add(key, value);
|
||||
}
|
||||
};
|
||||
|
||||
// convenience functions
|
||||
typedef typename LLRegistry<KEY, VALUE, COMPARATOR>::Registrar& ref_registrar_t;
|
||||
static ref_registrar_t currentRegistrar()
|
||||
{
|
||||
return singleton_t::instance().registry_t::currentRegistrar();
|
||||
}
|
||||
|
||||
static ref_registrar_t defaultRegistrar()
|
||||
{
|
||||
return singleton_t::instance().registry_t::defaultRegistrar();
|
||||
}
|
||||
|
||||
static ptr_value_t getValue(ref_const_key_t key)
|
||||
{
|
||||
return singleton_t::instance().registry_t::getValue(key);
|
||||
}
|
||||
|
||||
protected:
|
||||
// DERIVED_TYPE needs to derive from LLRegistrySingleton
|
||||
LLRegistrySingleton()
|
||||
: mStaticScope(NULL)
|
||||
{}
|
||||
|
||||
virtual void initSingleton()
|
||||
{
|
||||
//mStaticScope = new ScopedRegistrar();
|
||||
}
|
||||
|
||||
virtual ~LLRegistrySingleton()
|
||||
{
|
||||
delete mStaticScope;
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedRegistrar* mStaticScope;
|
||||
};
|
||||
|
||||
// helper macro for doing static registration
|
||||
#define GLUED_TOKEN(x, y) x ## y
|
||||
#define GLUE_TOKENS(x, y) GLUED_TOKEN(x, y)
|
||||
#define LLREGISTER_STATIC(REGISTRY, KEY, VALUE) static REGISTRY::StaticRegistrar GLUE_TOKENS(reg, __LINE__)(KEY, VALUE);
|
||||
|
||||
#endif
|
||||
342
indra/llcommon/llsdparam.cpp
Normal file
342
indra/llcommon/llsdparam.cpp
Normal file
@@ -0,0 +1,342 @@
|
||||
/**
|
||||
* @file llsdparam.cpp
|
||||
* @brief parameter block abstraction for creating complex objects and
|
||||
* parsing construction parameters from xml and LLSD
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
// Project includes
|
||||
#include "llsdparam.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
|
||||
static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
|
||||
static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
|
||||
static const LLSD NO_VALUE_MARKER;
|
||||
|
||||
LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
|
||||
|
||||
//
|
||||
// LLParamSDParser
|
||||
//
|
||||
LLParamSDParser::LLParamSDParser()
|
||||
: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
|
||||
{
|
||||
using boost::bind;
|
||||
|
||||
if (sReadFuncs.empty())
|
||||
{
|
||||
registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
|
||||
registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
|
||||
registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
|
||||
registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
|
||||
registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
|
||||
registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
|
||||
registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
|
||||
registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
|
||||
registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
|
||||
registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
|
||||
registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
|
||||
}
|
||||
}
|
||||
|
||||
// special case handling of U32 due to ambiguous LLSD::assign overload
|
||||
bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
|
||||
{
|
||||
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
|
||||
if (!sdparser.mWriteRootSD) return false;
|
||||
|
||||
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
|
||||
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
|
||||
sd_to_write.assign((S32)*((const U32*)val_ptr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
|
||||
{
|
||||
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
|
||||
if (!sdparser.mWriteRootSD) return false;
|
||||
|
||||
parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
|
||||
LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
|
||||
{
|
||||
mCurReadSD = &sd;
|
||||
block.submitValue(name_stack, *this);
|
||||
}
|
||||
|
||||
void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
|
||||
{
|
||||
mCurReadSD = NULL;
|
||||
mNameStack.clear();
|
||||
setParseSilently(silent);
|
||||
|
||||
LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
|
||||
//readSDValues(sd, block);
|
||||
}
|
||||
|
||||
void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
|
||||
{
|
||||
mNameStack.clear();
|
||||
mWriteRootSD = &sd;
|
||||
|
||||
name_stack_t name_stack;
|
||||
block.serializeBlock(*this, name_stack);
|
||||
}
|
||||
|
||||
/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
|
||||
{
|
||||
std::string full_name = "sd";
|
||||
for (name_stack_t::iterator it = mNameStack.begin();
|
||||
it != mNameStack.end();
|
||||
++it)
|
||||
{
|
||||
full_name += llformat("[%s]", it->first.c_str());
|
||||
}
|
||||
|
||||
return full_name;
|
||||
}
|
||||
|
||||
|
||||
bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
return self.mCurReadSD == &NO_VALUE_MARKER;
|
||||
}
|
||||
|
||||
|
||||
bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((S32*)val_ptr) = self.mCurReadSD->asInteger();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((U32*)val_ptr) = self.mCurReadSD->asInteger();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((F32*)val_ptr) = self.mCurReadSD->asReal();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((F64*)val_ptr) = self.mCurReadSD->asReal();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((bool*)val_ptr) = self.mCurReadSD->asBoolean();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((std::string*)val_ptr) = self.mCurReadSD->asString();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
|
||||
{
|
||||
LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
|
||||
|
||||
*((LLSD*)val_ptr) = *self.mCurReadSD;
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
|
||||
{
|
||||
LLSD* sd_to_write = &input;
|
||||
|
||||
for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
|
||||
it != name_stack_range.second;
|
||||
++it)
|
||||
{
|
||||
bool new_traversal = it->second;
|
||||
|
||||
LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
|
||||
|
||||
if (child_sd->isArray())
|
||||
{
|
||||
if (new_traversal)
|
||||
{
|
||||
// write to new element at end
|
||||
sd_to_write = &(*child_sd)[child_sd->size()];
|
||||
}
|
||||
else
|
||||
{
|
||||
// write to last of existing elements, or first element if empty
|
||||
sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (new_traversal
|
||||
&& child_sd->isDefined()
|
||||
&& !child_sd->isArray())
|
||||
{
|
||||
// copy child contents into first element of an array
|
||||
LLSD new_array = LLSD::emptyArray();
|
||||
new_array.append(*child_sd);
|
||||
// assign array to slot that previously held the single value
|
||||
*child_sd = new_array;
|
||||
// return next element in that array
|
||||
sd_to_write = &((*child_sd)[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sd_to_write = child_sd;
|
||||
}
|
||||
}
|
||||
it->second = false;
|
||||
}
|
||||
|
||||
return *sd_to_write;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
|
||||
{
|
||||
if (sd.isMap())
|
||||
{
|
||||
for (LLSD::map_const_iterator it = sd.beginMap();
|
||||
it != sd.endMap();
|
||||
++it)
|
||||
{
|
||||
stack.push_back(make_pair(it->first, true));
|
||||
readSDValues(cb, it->second, stack);
|
||||
stack.pop_back();
|
||||
}
|
||||
}
|
||||
else if (sd.isArray())
|
||||
{
|
||||
for (LLSD::array_const_iterator it = sd.beginArray();
|
||||
it != sd.endArray();
|
||||
++it)
|
||||
{
|
||||
stack.back().second = true;
|
||||
readSDValues(cb, *it, stack);
|
||||
}
|
||||
}
|
||||
else if (sd.isUndefined())
|
||||
{
|
||||
if (!cb.empty())
|
||||
{
|
||||
cb(NO_VALUE_MARKER, stack);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!cb.empty())
|
||||
{
|
||||
cb(sd, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
|
||||
{
|
||||
LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
|
||||
readSDValues(cb, sd, stack);
|
||||
}
|
||||
namespace LLInitParam
|
||||
{
|
||||
// LLSD specialization
|
||||
// block param interface
|
||||
bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
|
||||
{
|
||||
LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
|
||||
|
||||
LLSD::String string;
|
||||
|
||||
if (p.readValue<LLSD::String>(string))
|
||||
{
|
||||
sd = string;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
|
||||
{
|
||||
p.writeValue<LLSD::String>(sd.asString(), name_stack);
|
||||
}
|
||||
|
||||
void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
|
||||
{
|
||||
// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
|
||||
Parser::name_stack_t stack;
|
||||
LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
|
||||
}
|
||||
}
|
||||
126
indra/llcommon/llsdparam.h
Normal file
126
indra/llcommon/llsdparam.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* @file llsdparam.h
|
||||
* @brief parameter block abstraction for creating complex objects and
|
||||
* parsing construction parameters from xml and LLSD
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLSDPARAM_H
|
||||
#define LL_LLSDPARAM_H
|
||||
|
||||
#include "llinitparam.h"
|
||||
#include "boost/function.hpp"
|
||||
|
||||
struct LL_COMMON_API LLParamSDParserUtilities
|
||||
{
|
||||
static LLSD& getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range);
|
||||
|
||||
typedef boost::function<void (const LLSD&, LLInitParam::Parser::name_stack_t&)> read_sd_cb_t;
|
||||
static void readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack);
|
||||
static void readSDValues(read_sd_cb_t cb, const LLSD& sd);
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLParamSDParser
|
||||
: public LLInitParam::Parser
|
||||
{
|
||||
LOG_CLASS(LLParamSDParser);
|
||||
|
||||
typedef LLInitParam::Parser parser_t;
|
||||
|
||||
public:
|
||||
LLParamSDParser();
|
||||
void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
|
||||
void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
|
||||
|
||||
/*virtual*/ std::string getCurrentElementName();
|
||||
|
||||
private:
|
||||
void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
|
||||
|
||||
template<typename T>
|
||||
static bool writeTypedValue(Parser& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
|
||||
{
|
||||
LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
|
||||
if (!sdparser.mWriteRootSD) return false;
|
||||
|
||||
LLInitParam::Parser::name_stack_range_t range(name_stack.begin(), name_stack.end());
|
||||
LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
|
||||
|
||||
sd_to_write.assign(*((const T*)val_ptr));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool writeU32Param(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
|
||||
static bool writeFlag(Parser& parser, const void* value_ptr, parser_t::name_stack_t& name_stack);
|
||||
|
||||
static bool readFlag(Parser& parser, void* val_ptr);
|
||||
static bool readS32(Parser& parser, void* val_ptr);
|
||||
static bool readU32(Parser& parser, void* val_ptr);
|
||||
static bool readF32(Parser& parser, void* val_ptr);
|
||||
static bool readF64(Parser& parser, void* val_ptr);
|
||||
static bool readBool(Parser& parser, void* val_ptr);
|
||||
static bool readString(Parser& parser, void* val_ptr);
|
||||
static bool readUUID(Parser& parser, void* val_ptr);
|
||||
static bool readDate(Parser& parser, void* val_ptr);
|
||||
static bool readURI(Parser& parser, void* val_ptr);
|
||||
static bool readSD(Parser& parser, void* val_ptr);
|
||||
|
||||
Parser::name_stack_t mNameStack;
|
||||
const LLSD* mCurReadSD;
|
||||
LLSD* mWriteRootSD;
|
||||
LLSD* mCurWriteSD;
|
||||
};
|
||||
|
||||
|
||||
extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
|
||||
template<typename T>
|
||||
class LLSDParamAdapter : public T
|
||||
{
|
||||
public:
|
||||
LLSDParamAdapter() {}
|
||||
LLSDParamAdapter(const LLSD& sd)
|
||||
{
|
||||
LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
|
||||
LLParamSDParser parser;
|
||||
// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
|
||||
bool parse_silently = true;
|
||||
parser.readSD(sd, *this, parse_silently);
|
||||
}
|
||||
|
||||
operator LLSD() const
|
||||
{
|
||||
LLParamSDParser parser;
|
||||
LLSD sd;
|
||||
parser.writeSD(sd, *this);
|
||||
return sd;
|
||||
}
|
||||
|
||||
LLSDParamAdapter(const T& val)
|
||||
: T(val)
|
||||
{
|
||||
T::operator=(val);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LL_LLSDPARAM_H
|
||||
|
||||
@@ -45,44 +45,49 @@ const std::string AUCTION_URL (
|
||||
const std::string EVENTS_URL (
|
||||
"http://secondlife.com/events/");
|
||||
|
||||
/*
|
||||
const std::string TIER_UP_URL (
|
||||
"http://secondlife.com/app/landtier");
|
||||
|
||||
const std::string LAND_URL (
|
||||
"http://secondlife.com/app/landtier");
|
||||
|
||||
const std::string UPGRADE_TO_PREMIUM_URL (
|
||||
"http://secondlife.com/app/upgrade/");
|
||||
"http://secondlife.com/app/landtier"); // *TODO: NOT USED
|
||||
*/
|
||||
|
||||
const std::string DIRECTX_9_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
/*
|
||||
const std::string LAND_URL (
|
||||
"http://secondlife.com/app/landtier"); // *TODO: NOT USED
|
||||
|
||||
const std::string UPGRADE_TO_PREMIUM_URL (
|
||||
"http://secondlife.com/app/upgrade/"); // *TODO: NOT USED
|
||||
|
||||
const std::string AMD_AGP_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string VIA_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string SUPPORT_URL (
|
||||
"http://secondlife.com/support/");
|
||||
|
||||
const std::string INTEL_CHIPSET_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string SIS_CHIPSET_URL (
|
||||
"http://secondlife.com/support/");
|
||||
"http://secondlife.com/support/"); // *TODO: NOT USED
|
||||
|
||||
const std::string BLOGS_URL (
|
||||
"http://blog.secondlife.com/");
|
||||
"http://blog.secondlife.com/"); // *TODO: NOT USED
|
||||
*/
|
||||
|
||||
const std::string BUY_CURRENCY_URL (
|
||||
"http://secondlife.com/app/currency/");
|
||||
|
||||
/*
|
||||
const std::string LSL_DOC_URL (
|
||||
"http://secondlife.com/app/lsldoc/");
|
||||
"http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED
|
||||
|
||||
const std::string SL_KB_URL (
|
||||
"http://secondlife.com/knowledgebase/");
|
||||
"http://secondlife.com/knowledgebase/"); // *TODO: NOT USED
|
||||
|
||||
const std::string RELEASE_NOTES_BASE_URL (
|
||||
"http://ascent.balseraph.org/?");
|
||||
"http://secondlife.com/app/releasenotes/");
|
||||
*/
|
||||
|
||||
@@ -43,18 +43,22 @@ LL_COMMON_API extern const std::string AUCTION_URL;
|
||||
|
||||
LL_COMMON_API extern const std::string EVENTS_URL;
|
||||
|
||||
/*
|
||||
// Tier up to a new land level.
|
||||
LL_COMMON_API extern const std::string TIER_UP_URL;
|
||||
|
||||
// Tier up to a new land level.
|
||||
LL_COMMON_API extern const std::string LAND_URL;
|
||||
|
||||
// Upgrade from basic membership to premium membership
|
||||
LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
|
||||
*/
|
||||
|
||||
// How to get DirectX 9
|
||||
LL_COMMON_API extern const std::string DIRECTX_9_URL;
|
||||
|
||||
/*
|
||||
// Upgrade from basic membership to premium membership
|
||||
LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
|
||||
|
||||
|
||||
// Out of date VIA chipset
|
||||
LL_COMMON_API extern const std::string VIA_URL;
|
||||
|
||||
@@ -63,10 +67,12 @@ LL_COMMON_API extern const std::string SUPPORT_URL;
|
||||
|
||||
// Linden Blogs page
|
||||
LL_COMMON_API extern const std::string BLOGS_URL;
|
||||
*/
|
||||
|
||||
// Currency page
|
||||
LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
|
||||
|
||||
/*
|
||||
// LSL script wiki
|
||||
LL_COMMON_API extern const std::string LSL_DOC_URL;
|
||||
|
||||
@@ -75,5 +81,5 @@ LL_COMMON_API extern const std::string SL_KB_URL;
|
||||
|
||||
// Release Notes Redirect URL for Server and Viewer
|
||||
LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
|
||||
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -917,6 +917,7 @@ P(MPImportGetResponder);
|
||||
P(MPImportPostResponder);
|
||||
P(mapLayerResponder);
|
||||
P2(maturityPreferences, transfer_30s);
|
||||
P(mediaDataClientResponder);
|
||||
P(mediaTypeResponder);
|
||||
P(meshDecompositionResponder);
|
||||
P(meshHeaderResponder);
|
||||
|
||||
@@ -56,6 +56,7 @@ bool LLPluginClassMedia::init_impl(void)
|
||||
{
|
||||
// Queue up the media init message -- it will be sent after all the currently queued messages.
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init");
|
||||
message.setValue("target", mTarget);
|
||||
sendMessage(message);
|
||||
|
||||
return true;
|
||||
@@ -127,7 +128,7 @@ void LLPluginClassMedia::reset_impl(void)
|
||||
|
||||
void LLPluginClassMedia::idle_impl(void)
|
||||
{
|
||||
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()))
|
||||
if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL))
|
||||
{
|
||||
// Can't process a size change at this time
|
||||
}
|
||||
@@ -246,16 +247,18 @@ unsigned char* LLPluginClassMedia::getBitsData()
|
||||
|
||||
void LLPluginClassMedia::setSize(int width, int height)
|
||||
{
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
width = height = -1;
|
||||
}
|
||||
if (mSetMediaWidth != width || mSetMediaHeight != height)
|
||||
if((width > 0) && (height > 0))
|
||||
{
|
||||
mSetMediaWidth = width;
|
||||
mSetMediaHeight = height;
|
||||
setSizeInternal();
|
||||
}
|
||||
else
|
||||
{
|
||||
mSetMediaWidth = -1;
|
||||
mSetMediaHeight = -1;
|
||||
}
|
||||
|
||||
setSizeInternal();
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::setSizeInternal(void)
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
#include "llrect.h"
|
||||
#include "v4color.h"
|
||||
|
||||
class LLPluginClassMedia : public LLPluginClassBasic
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
class LLPluginClassMedia : public LLPluginClassBasic, public boost::signals2::trackable
|
||||
{
|
||||
LOG_CLASS(LLPluginClassMedia);
|
||||
|
||||
|
||||
@@ -26,13 +26,30 @@
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "lluuid.h"
|
||||
#include "llmediaentry.h"
|
||||
#include "lltextureentry.h"
|
||||
#include "llsdutil_math.h"
|
||||
#include "v4color.h"
|
||||
|
||||
const U8 DEFAULT_BUMP_CODE = 0; // no bump or shininess
|
||||
|
||||
const LLTextureEntry LLTextureEntry::null;
|
||||
|
||||
// Some LLSD keys. Do not change these!
|
||||
#define OBJECT_ID_KEY_STR "object_id"
|
||||
#define TEXTURE_INDEX_KEY_STR "texture_index"
|
||||
#define OBJECT_MEDIA_VERSION_KEY_STR "object_media_version"
|
||||
#define OBJECT_MEDIA_DATA_KEY_STR "object_media_data"
|
||||
#define TEXTURE_MEDIA_DATA_KEY_STR "media_data"
|
||||
|
||||
/*static*/ const char* LLTextureEntry::OBJECT_ID_KEY = OBJECT_ID_KEY_STR;
|
||||
/*static*/ const char* LLTextureEntry::OBJECT_MEDIA_DATA_KEY = OBJECT_MEDIA_DATA_KEY_STR;
|
||||
/*static*/ const char* LLTextureEntry::MEDIA_VERSION_KEY = OBJECT_MEDIA_VERSION_KEY_STR;
|
||||
/*static*/ const char* LLTextureEntry::TEXTURE_INDEX_KEY = TEXTURE_INDEX_KEY_STR;
|
||||
/*static*/ const char* LLTextureEntry::TEXTURE_MEDIA_DATA_KEY = TEXTURE_MEDIA_DATA_KEY_STR;
|
||||
|
||||
static const std::string MEDIA_VERSION_STRING_PREFIX = "x-mv:";
|
||||
|
||||
// static
|
||||
LLTextureEntry* LLTextureEntry::newTextureEntry()
|
||||
@@ -42,16 +59,19 @@ LLTextureEntry* LLTextureEntry::newTextureEntry()
|
||||
|
||||
//===============================================================
|
||||
LLTextureEntry::LLTextureEntry()
|
||||
: mMediaEntry(NULL)
|
||||
{
|
||||
init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
|
||||
}
|
||||
|
||||
LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
|
||||
: mMediaEntry(NULL)
|
||||
{
|
||||
init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
|
||||
}
|
||||
|
||||
LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
|
||||
: mMediaEntry(NULL)
|
||||
{
|
||||
mID = rhs.mID;
|
||||
mScaleS = rhs.mScaleS;
|
||||
@@ -63,6 +83,10 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
|
||||
mBump = rhs.mBump;
|
||||
mMediaFlags = rhs.mMediaFlags;
|
||||
mGlow = rhs.mGlow;
|
||||
if (rhs.mMediaEntry != NULL) {
|
||||
// Make a copy
|
||||
mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
|
||||
}
|
||||
}
|
||||
|
||||
LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
|
||||
@@ -79,6 +103,16 @@ LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
|
||||
mBump = rhs.mBump;
|
||||
mMediaFlags = rhs.mMediaFlags;
|
||||
mGlow = rhs.mGlow;
|
||||
if (mMediaEntry != NULL) {
|
||||
delete mMediaEntry;
|
||||
}
|
||||
if (rhs.mMediaEntry != NULL) {
|
||||
// Make a copy
|
||||
mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
|
||||
}
|
||||
else {
|
||||
mMediaEntry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -98,10 +132,19 @@ void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 of
|
||||
mGlow = 0;
|
||||
|
||||
setColor(LLColor4(1.f, 1.f, 1.f, 1.f));
|
||||
if (mMediaEntry != NULL) {
|
||||
delete mMediaEntry;
|
||||
}
|
||||
mMediaEntry = NULL;
|
||||
}
|
||||
|
||||
LLTextureEntry::~LLTextureEntry()
|
||||
{
|
||||
if(mMediaEntry)
|
||||
{
|
||||
delete mMediaEntry;
|
||||
mMediaEntry = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const
|
||||
@@ -153,6 +196,13 @@ void LLTextureEntry::asLLSD(LLSD& sd) const
|
||||
sd["bump"] = getBumpShiny();
|
||||
sd["fullbright"] = getFullbright();
|
||||
sd["media_flags"] = mMediaFlags;
|
||||
if (hasMedia()) {
|
||||
LLSD mediaData;
|
||||
if (NULL != getMediaData()) {
|
||||
getMediaData()->asLLSD(mediaData);
|
||||
}
|
||||
sd[TEXTURE_MEDIA_DATA_KEY] = mediaData;
|
||||
}
|
||||
sd["glow"] = mGlow;
|
||||
}
|
||||
|
||||
@@ -201,6 +251,17 @@ bool LLTextureEntry::fromLLSD(const LLSD& sd)
|
||||
{
|
||||
setMediaTexGen( sd[w].asInteger() );
|
||||
} else goto fail;
|
||||
// If the "has media" flag doesn't match the fact that
|
||||
// media data exists, updateMediaData will "fix" it
|
||||
// by either clearing or setting the flag
|
||||
w = TEXTURE_MEDIA_DATA_KEY;
|
||||
if (hasMedia() != sd.has(w))
|
||||
{
|
||||
llwarns << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() <<
|
||||
") does not match presence of media_data (" << sd.has(w) << "). Fixing." << llendl;
|
||||
}
|
||||
updateMediaData(sd[w]);
|
||||
|
||||
w = "glow";
|
||||
if (sd.has(w))
|
||||
{
|
||||
@@ -362,12 +423,10 @@ S32 LLTextureEntry::setBumpShinyFullbright(U8 bump)
|
||||
|
||||
S32 LLTextureEntry::setMediaTexGen(U8 media)
|
||||
{
|
||||
if (mMediaFlags != media)
|
||||
{
|
||||
mMediaFlags = media;
|
||||
return TEM_CHANGE_MEDIA;
|
||||
}
|
||||
return TEM_CHANGE_NONE;
|
||||
S32 result = TEM_CHANGE_NONE;
|
||||
result |= setTexGen(media & TEM_TEX_GEN_MASK);
|
||||
result |= setMediaFlags(media & TEM_MEDIA_MASK);
|
||||
return result;
|
||||
}
|
||||
|
||||
S32 LLTextureEntry::setBumpmap(U8 bump)
|
||||
@@ -425,6 +484,18 @@ S32 LLTextureEntry::setMediaFlags(U8 media_flags)
|
||||
{
|
||||
mMediaFlags &= ~TEM_MEDIA_MASK;
|
||||
mMediaFlags |= media_flags;
|
||||
|
||||
// Special code for media handling
|
||||
if( hasMedia() && mMediaEntry == NULL)
|
||||
{
|
||||
mMediaEntry = new LLMediaEntry;
|
||||
}
|
||||
else if ( ! hasMedia() && mMediaEntry != NULL)
|
||||
{
|
||||
delete mMediaEntry;
|
||||
mMediaEntry = NULL;
|
||||
}
|
||||
|
||||
return TEM_CHANGE_MEDIA;
|
||||
}
|
||||
return TEM_CHANGE_NONE;
|
||||
@@ -452,4 +523,112 @@ S32 LLTextureEntry::setGlow(F32 glow)
|
||||
return TEM_CHANGE_NONE;
|
||||
}
|
||||
|
||||
void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry)
|
||||
{
|
||||
mMediaFlags |= MF_HAS_MEDIA;
|
||||
if (NULL != mMediaEntry)
|
||||
{
|
||||
delete mMediaEntry;
|
||||
}
|
||||
mMediaEntry = new LLMediaEntry(media_entry);
|
||||
}
|
||||
|
||||
bool LLTextureEntry::updateMediaData(const LLSD& media_data)
|
||||
{
|
||||
if (media_data.isUndefined())
|
||||
{
|
||||
// clear the media data
|
||||
clearMediaData();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
mMediaFlags |= MF_HAS_MEDIA;
|
||||
if (mMediaEntry == NULL)
|
||||
{
|
||||
mMediaEntry = new LLMediaEntry;
|
||||
}
|
||||
// *NOTE: this will *clobber* all of the fields in mMediaEntry
|
||||
// with whatever fields are present (or not present) in media_data!
|
||||
mMediaEntry->fromLLSD(media_data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void LLTextureEntry::clearMediaData()
|
||||
{
|
||||
mMediaFlags &= ~MF_HAS_MEDIA;
|
||||
if (mMediaEntry != NULL) {
|
||||
delete mMediaEntry;
|
||||
}
|
||||
mMediaEntry = NULL;
|
||||
}
|
||||
|
||||
void LLTextureEntry::mergeIntoMediaData(const LLSD& media_fields)
|
||||
{
|
||||
mMediaFlags |= MF_HAS_MEDIA;
|
||||
if (mMediaEntry == NULL)
|
||||
{
|
||||
mMediaEntry = new LLMediaEntry;
|
||||
}
|
||||
// *NOTE: this will *merge* the data in media_fields
|
||||
// with the data in our media entry
|
||||
mMediaEntry->mergeFromLLSD(media_fields);
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLTextureEntry::touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id)
|
||||
{
|
||||
// XXX TODO: make media version string binary (base64-encoded?)
|
||||
// Media "URL" is a representation of a version and the last-touched agent
|
||||
// x-mv:nnnnn/agent-id
|
||||
// where "nnnnn" is version number
|
||||
// *NOTE: not the most efficient code in the world...
|
||||
U32 current_version = getVersionFromMediaVersionString(in_version) + 1;
|
||||
const size_t MAX_VERSION_LEN = 10; // 2^32 fits in 10 decimal digits
|
||||
char buf[MAX_VERSION_LEN+1];
|
||||
snprintf(buf, (int)MAX_VERSION_LEN+1, "%0*u", (int)MAX_VERSION_LEN, current_version); // added int cast to fix warning/breakage on mac.
|
||||
return MEDIA_VERSION_STRING_PREFIX + buf + "/" + agent_id.asString();
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_string)
|
||||
{
|
||||
U32 version = 0;
|
||||
if (!version_string.empty())
|
||||
{
|
||||
size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
found = version_string.find_first_of("/", found);
|
||||
std::string v = version_string.substr(MEDIA_VERSION_STRING_PREFIX.length(), found);
|
||||
version = strtoul(v.c_str(),NULL,10);
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
//static
|
||||
LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &version_string)
|
||||
{
|
||||
LLUUID id;
|
||||
if (!version_string.empty())
|
||||
{
|
||||
size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
found = version_string.find_first_of("/", found);
|
||||
if (found != std::string::npos)
|
||||
{
|
||||
std::string v = version_string.substr(found + 1);
|
||||
id.set(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
//static
|
||||
bool LLTextureEntry::isMediaVersionString(const std::string &version_string)
|
||||
{
|
||||
return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ const S32 TEM_MEDIA_MASK = 0x01;
|
||||
const S32 TEM_TEX_GEN_MASK = 0x06;
|
||||
const S32 TEM_TEX_GEN_SHIFT = 1;
|
||||
|
||||
// forward declarations
|
||||
class LLMediaEntry;
|
||||
|
||||
class LLTextureEntry
|
||||
{
|
||||
@@ -137,6 +139,34 @@ public:
|
||||
U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; }
|
||||
U8 getMediaTexGen() const { return mMediaFlags; }
|
||||
F32 getGlow() const { return mGlow; }
|
||||
|
||||
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
|
||||
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
|
||||
// to NOT return NULL.
|
||||
bool hasMedia() const { return (bool)(mMediaFlags & MF_HAS_MEDIA); }
|
||||
LLMediaEntry* getMediaData() const { return mMediaEntry; }
|
||||
|
||||
// Completely change the media data on this texture entry.
|
||||
void setMediaData(const LLMediaEntry &media_entry);
|
||||
// Returns true if media data was updated, false if it was cleared
|
||||
bool updateMediaData(const LLSD& media_data);
|
||||
// Clears media data, and sets the media flags bit to 0
|
||||
void clearMediaData();
|
||||
// Merges the given LLSD of media fields with this media entry.
|
||||
// Only those fields that are set that match the keys in
|
||||
// LLMediaEntry will be affected. If no fields are set or if
|
||||
// the LLSD is undefined, this is a no-op.
|
||||
void mergeIntoMediaData(const LLSD& media_fields);
|
||||
|
||||
// Takes a media version string (an empty string or a previously-returned string)
|
||||
// and returns a "touched" string, touched by agent_id
|
||||
static std::string touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id);
|
||||
// Given a media version string, return the version
|
||||
static U32 getVersionFromMediaVersionString(const std::string &version_string);
|
||||
// Given a media version string, return the UUID of the agent
|
||||
static LLUUID getAgentIDFromMediaVersionString(const std::string &version_string);
|
||||
// Return whether or not the given string is actually a media version
|
||||
static bool isMediaVersionString(const std::string &version_string);
|
||||
|
||||
// Media flags
|
||||
enum { MF_NONE = 0x0, MF_HAS_MEDIA = 0x1 };
|
||||
@@ -149,6 +179,14 @@ public:
|
||||
F32 mRotation; // anti-clockwise rotation in rad about the bottom left corner
|
||||
|
||||
static const LLTextureEntry null;
|
||||
|
||||
// LLSD key defines
|
||||
static const char* OBJECT_ID_KEY;
|
||||
static const char* OBJECT_MEDIA_DATA_KEY;
|
||||
static const char* MEDIA_VERSION_KEY;
|
||||
static const char* TEXTURE_INDEX_KEY;
|
||||
static const char* TEXTURE_MEDIA_DATA_KEY;
|
||||
|
||||
protected:
|
||||
LLUUID mID; // Texture GUID
|
||||
LLColor4 mColor;
|
||||
@@ -156,6 +194,9 @@ protected:
|
||||
U8 mMediaFlags; // replace with web page, movie, etc.
|
||||
F32 mGlow;
|
||||
|
||||
// Note the media data is not sent via the same message structure as the rest of the TE
|
||||
LLMediaEntry* mMediaEntry; // The media data for the face
|
||||
|
||||
// NOTE: when adding new data to this class, in addition to adding it to the serializers asLLSD/fromLLSD and the
|
||||
// message packers (e.g. LLPrimitive::packTEMessage) you must also implement its copy in LLPrimitive::copyTEs()
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ set(llui_SOURCE_FILES
|
||||
llfunctorregistry.cpp
|
||||
lliconctrl.cpp
|
||||
llkeywords.cpp
|
||||
lllayoutstack.cpp
|
||||
lllineeditor.cpp
|
||||
lllocalcliprect.cpp
|
||||
llmenugl.cpp
|
||||
@@ -78,6 +79,10 @@ set(llui_SOURCE_FILES
|
||||
lluictrlfactory.cpp
|
||||
lluistring.cpp
|
||||
llundo.cpp
|
||||
llurlaction.cpp
|
||||
llurlentry.cpp
|
||||
llurlmatch.cpp
|
||||
llurlregistry.cpp
|
||||
llview.cpp
|
||||
llviewborder.cpp
|
||||
llviewmodel.cpp
|
||||
@@ -105,6 +110,7 @@ set(llui_HEADER_FILES
|
||||
llhtmlhelp.h
|
||||
lliconctrl.h
|
||||
llkeywords.h
|
||||
lllayoutstack.h
|
||||
lllineeditor.h
|
||||
lllocalcliprect.h
|
||||
llmemberlistener.h
|
||||
@@ -150,6 +156,10 @@ set(llui_HEADER_FILES
|
||||
lluistring.h
|
||||
lluixmltags.h
|
||||
llundo.h
|
||||
llurlaction.h
|
||||
llurlentry.h
|
||||
llurlmatch.h
|
||||
llurlregistry.h
|
||||
llview.h
|
||||
llviewborder.h
|
||||
llviewmodel.h
|
||||
|
||||
@@ -520,7 +520,7 @@ void LLAlertDialog::onButtonPressed( LLUICtrl* ctrl, const std::string url )
|
||||
// If we declared a URL and chose the URL option, go to the url
|
||||
if (!url.empty() && sURLLoader != NULL)
|
||||
{
|
||||
sURLLoader->load(url);
|
||||
sURLLoader->load(url, false);
|
||||
}
|
||||
|
||||
mNote->respond(response); // new notification reponse
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
class URLLoader
|
||||
{
|
||||
public:
|
||||
virtual void load(const std::string& url) = 0;
|
||||
virtual void load(const std::string& url, bool force_open_externally) = 0;
|
||||
virtual ~URLLoader() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -544,7 +544,7 @@ void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height)
|
||||
// virtual
|
||||
void LLButton::draw()
|
||||
{
|
||||
F32 alpha = mAlpha;
|
||||
F32 alpha = mAlpha * getDrawContext().mAlpha;
|
||||
bool flash = FALSE;
|
||||
if( mFlashing )
|
||||
{
|
||||
|
||||
@@ -307,9 +307,6 @@ LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("checkbox");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
std::string label("");
|
||||
node->getAttributeString("label", label);
|
||||
|
||||
@@ -326,7 +323,7 @@ LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl(name,
|
||||
LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl("checkbox",
|
||||
rect,
|
||||
label,
|
||||
font,
|
||||
|
||||
@@ -149,9 +149,6 @@ LLXMLNodePtr LLComboBox::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("combo_box");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
std::string label("");
|
||||
node->getAttributeString("label", label);
|
||||
|
||||
@@ -164,7 +161,7 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
|
||||
S32 max_chars = 20;
|
||||
node->getAttributeS32("max_chars", max_chars);
|
||||
|
||||
LLComboBox* combo_box = new LLComboBox(name,
|
||||
LLComboBox* combo_box = new LLComboBox("combo_box",
|
||||
rect,
|
||||
label);
|
||||
combo_box->setAllowTextEntry(allow_text_entry, max_chars);
|
||||
@@ -1245,16 +1242,13 @@ LLXMLNodePtr LLFlyoutButton::getXML(bool save_children) const
|
||||
//static
|
||||
LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name = "flyout_button";
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
std::string label("");
|
||||
node->getAttributeString("label", label);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
LLFlyoutButton* flyout_button = new LLFlyoutButton(name,
|
||||
LLFlyoutButton* flyout_button = new LLFlyoutButton("flyout_button",
|
||||
rect,
|
||||
label);
|
||||
|
||||
|
||||
@@ -52,9 +52,6 @@ void LLFilterEditor::handleKeystroke()
|
||||
// static
|
||||
LLView* LLFilterEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("filter_editor");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -63,7 +60,7 @@ LLView* LLFilterEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
|
||||
|
||||
std::string text = node->getValue().substr(0, max_text_length - 1);
|
||||
|
||||
LLFilterEditor* search_editor = new LLFilterEditor(name,
|
||||
LLFilterEditor* search_editor = new LLFilterEditor("filter_editor",
|
||||
rect,
|
||||
max_text_length);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "v2math.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "airecursive.h"
|
||||
#include "llnotifications.h"
|
||||
|
||||
const S32 MINIMIZED_WIDTH = 160;
|
||||
const S32 CLOSE_BOX_FROM_TOP = 1;
|
||||
@@ -1411,6 +1412,10 @@ void LLFloater::closeFocusedFloater()
|
||||
}
|
||||
}
|
||||
|
||||
LLNotificationPtr LLFloater::addContextualNotification(const std::string& name, const LLSD& substitutions)
|
||||
{
|
||||
return LLNotifications::instance().add(LLNotification::Params(name).context(mNotificationContext).substitutions(substitutions));
|
||||
}
|
||||
|
||||
void LLFloater::onClickClose()
|
||||
{
|
||||
@@ -2488,8 +2493,13 @@ LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f
|
||||
|
||||
if (filename.empty())
|
||||
{
|
||||
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
|
||||
floaterp->getCommitCallbackRegistrar().pushScope();
|
||||
floaterp->getEnableCallbackRegistrar().pushScope();
|
||||
// Load from node
|
||||
floaterp->initFloaterXML(node, parent, factory);
|
||||
floaterp->getCommitCallbackRegistrar().popScope();
|
||||
floaterp->getEnableCallbackRegistrar().popScope();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
#include "llpanel.h"
|
||||
#include "lluuid.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationcontext.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include <set>
|
||||
|
||||
class LLDragHandle;
|
||||
@@ -232,10 +233,7 @@ public:
|
||||
// handle refocusing.
|
||||
static void closeFocusedFloater();
|
||||
|
||||
LLNotification::Params contextualNotification(const std::string& name)
|
||||
{
|
||||
return LLNotification::Params(name).context(mNotificationContext);
|
||||
}
|
||||
LLNotificationPtr addContextualNotification(const std::string& name, const LLSD& substitutions = LLSD());
|
||||
|
||||
void onClickClose();
|
||||
void onClickMinimize();
|
||||
|
||||
@@ -106,7 +106,8 @@ void LLIconCtrl::draw()
|
||||
{
|
||||
if( mImagep.notNull() )
|
||||
{
|
||||
mImagep->draw(getLocalRect(), mColor );
|
||||
const F32 alpha = getDrawContext().mAlpha;
|
||||
mImagep->draw(getLocalRect(), mColor % alpha );
|
||||
}
|
||||
|
||||
LLUICtrl::draw();
|
||||
@@ -157,9 +158,6 @@ LLXMLNodePtr LLIconCtrl::getXML(bool save_children) const
|
||||
|
||||
LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("icon");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -172,7 +170,7 @@ LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
|
||||
LLColor4 color(LLColor4::white);
|
||||
LLUICtrlFactory::getAttributeColor(node,"color", color);
|
||||
|
||||
LLIconCtrl* icon = new LLIconCtrl(name, rect, image_name);
|
||||
LLIconCtrl* icon = new LLIconCtrl("icon", rect, image_name);
|
||||
|
||||
icon->setColor(color);
|
||||
|
||||
|
||||
1038
indra/llui/lllayoutstack.cpp
Normal file
1038
indra/llui/lllayoutstack.cpp
Normal file
File diff suppressed because it is too large
Load Diff
179
indra/llui/lllayoutstack.h
Normal file
179
indra/llui/lllayoutstack.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* @file lllayoutstack.h
|
||||
* @author Richard Nelson
|
||||
* @brief LLLayout class - dynamic stacking of UI elements
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Reshasearch, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLLAYOUTSTACK_H
|
||||
#define LL_LLLAYOUTSTACK_H
|
||||
|
||||
#include "llpanel.h"
|
||||
#include "llresizebar.h"
|
||||
|
||||
|
||||
class LLLayoutPanel;
|
||||
|
||||
|
||||
class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
|
||||
{
|
||||
public:
|
||||
typedef enum e_layout_orientation
|
||||
{
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
} ELayoutOrientation;
|
||||
|
||||
LLLayoutStack(ELayoutOrientation orientation, S32 border_size, bool animate, bool clip, F32 open_time_constant, F32 close_time_constant, F32 resize_bar_overlap);
|
||||
virtual ~LLLayoutStack();
|
||||
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void removeChild(LLView*);
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ bool addChild(LLView* child, S32 tab_groupdatefractuiona = 0);
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
|
||||
|
||||
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
|
||||
typedef enum e_animate
|
||||
{
|
||||
NO_ANIMATE,
|
||||
ANIMATE
|
||||
} EAnimate;
|
||||
|
||||
void addPanel(LLLayoutPanel* panel, EAnimate animate = NO_ANIMATE);
|
||||
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
|
||||
S32 getNumPanels() { return mPanels.size(); }
|
||||
|
||||
void updateLayout();
|
||||
|
||||
S32 getPanelSpacing() const { return mPanelSpacing; }
|
||||
|
||||
static void updateClass();
|
||||
|
||||
protected:
|
||||
LLLayoutStack(const Params&);
|
||||
friend class LLUICtrlFactory;
|
||||
friend class LLLayoutPanel;
|
||||
|
||||
private:
|
||||
void updateResizeBarLimits();
|
||||
bool animatePanels();
|
||||
void createResizeBar(LLLayoutPanel* panel);
|
||||
|
||||
const ELayoutOrientation mOrientation;
|
||||
|
||||
typedef std::vector<LLLayoutPanel*> e_panel_list_t;
|
||||
e_panel_list_t mPanels;
|
||||
|
||||
LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;
|
||||
LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;
|
||||
void updateFractionalSizes();
|
||||
void normalizeFractionalSizes();
|
||||
void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect );
|
||||
|
||||
S32 mPanelSpacing;
|
||||
|
||||
// true if we already applied animation this frame
|
||||
bool mAnimatedThisFrame;
|
||||
bool mAnimate;
|
||||
bool mClip;
|
||||
F32 mOpenTimeConstant;
|
||||
F32 mCloseTimeConstant;
|
||||
bool mNeedsLayout;
|
||||
S32 mResizeBarOverlap;
|
||||
}; // end class LLLayoutStack
|
||||
|
||||
|
||||
class LLLayoutPanel : public LLPanel
|
||||
{
|
||||
friend class LLLayoutStack;
|
||||
friend class LLUICtrlFactory;
|
||||
public:
|
||||
~LLLayoutPanel();
|
||||
|
||||
void initFromParams(const Params& p);
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *factory);
|
||||
|
||||
void handleReshape(const LLRect& new_rect, bool by_user);
|
||||
|
||||
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
|
||||
|
||||
|
||||
void setVisible(BOOL visible);
|
||||
|
||||
S32 getLayoutDim() const;
|
||||
S32 getTargetDim() const;
|
||||
void setTargetDim(S32 value);
|
||||
S32 getMinDim() const { return llmax(0, mMinDim); }
|
||||
void setMinDim(S32 value) { mMinDim = value; }
|
||||
|
||||
S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); }
|
||||
void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }
|
||||
|
||||
S32 getRelevantMinDim() const
|
||||
{
|
||||
S32 min_dim = mMinDim;
|
||||
|
||||
if (!mCollapsed)
|
||||
{
|
||||
min_dim = getExpandedMinDim();
|
||||
}
|
||||
|
||||
return min_dim;
|
||||
}
|
||||
|
||||
F32 getAutoResizeFactor() const;
|
||||
F32 getVisibleAmount() const;
|
||||
S32 getVisibleDim() const;
|
||||
LLResizeBar* getResizeBar() { return mResizeBar; }
|
||||
|
||||
bool isCollapsed() const { return mCollapsed;}
|
||||
|
||||
void setOrientation(LLLayoutStack::ELayoutOrientation orientation);
|
||||
void storeOriginalDim();
|
||||
|
||||
void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; }
|
||||
|
||||
protected:
|
||||
LLLayoutPanel(S32 min_dim=-1, BOOL auto_resize=TRUE, BOOL user_resize=TRUE, LLRect rect = LLRect());
|
||||
/*virtual*/ BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
|
||||
bool mAutoResize;
|
||||
bool mUserResize;
|
||||
|
||||
S32 mExpandedMinDim;
|
||||
S32 mMinDim;
|
||||
bool mCollapsed;
|
||||
F32 mVisibleAmt;
|
||||
F32 mCollapseAmt;
|
||||
F32 mFractionalSize;
|
||||
S32 mTargetDim;
|
||||
bool mIgnoreReshape;
|
||||
LLLayoutStack::ELayoutOrientation mOrientation;
|
||||
class LLResizeBar* mResizeBar;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1702,6 +1702,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
|
||||
|
||||
if (glggHunSpell->getSpellCheckHighlight())
|
||||
{
|
||||
F32 alpha = getDrawContext().mAlpha;
|
||||
for (int i =0; i<(int)misspellLocations.size(); i++)
|
||||
{
|
||||
S32 wstart =findPixelNearestPos( misspellLocations[i]-getCursor());
|
||||
@@ -1716,7 +1717,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
|
||||
{
|
||||
wstart = maxw;
|
||||
}
|
||||
gGL.color4ub(255,0,0,200);
|
||||
gGL.color4ub(255,0,0,200*alpha);
|
||||
//3 line zig zags..
|
||||
while (wstart < wend)
|
||||
{
|
||||
@@ -1733,6 +1734,7 @@ void LLLineEditor::drawMisspelled(LLRect background)
|
||||
|
||||
void LLLineEditor::draw()
|
||||
{
|
||||
F32 alpha = getDrawContext().mAlpha;
|
||||
S32 text_len = mText.length();
|
||||
|
||||
std::string saved_text;
|
||||
@@ -1776,7 +1778,7 @@ void LLLineEditor::draw()
|
||||
bg_color = mWriteableBgColor;
|
||||
}
|
||||
}
|
||||
gl_rect_2d(background, bg_color);
|
||||
gl_rect_2d(background, bg_color % alpha);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1801,7 +1803,9 @@ void LLLineEditor::draw()
|
||||
{
|
||||
text_color = mReadOnlyFgColor;
|
||||
}
|
||||
LLColor4 label_color = mTentativeFgColor;
|
||||
|
||||
text_color %= alpha;
|
||||
LLColor4 label_color = mTentativeFgColor % alpha;
|
||||
|
||||
if (hasPreeditString())
|
||||
{
|
||||
@@ -1824,7 +1828,7 @@ void LLLineEditor::draw()
|
||||
background.mBottom + PREEDIT_STANDOUT_POSITION,
|
||||
preedit_pixels_right - PREEDIT_STANDOUT_GAP - 1,
|
||||
background.mBottom + PREEDIT_STANDOUT_POSITION - PREEDIT_STANDOUT_THICKNESS,
|
||||
(text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(1.0f));
|
||||
(text_color * PREEDIT_STANDOUT_BRIGHTNESS + bg_color * (1 - PREEDIT_STANDOUT_BRIGHTNESS)).setAlpha(alpha));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1832,7 +1836,7 @@ void LLLineEditor::draw()
|
||||
background.mBottom + PREEDIT_MARKER_POSITION,
|
||||
preedit_pixels_right - PREEDIT_MARKER_GAP - 1,
|
||||
background.mBottom + PREEDIT_MARKER_POSITION - PREEDIT_MARKER_THICKNESS,
|
||||
(text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(1.0f));
|
||||
(text_color * PREEDIT_MARKER_BRIGHTNESS + bg_color * (1 - PREEDIT_MARKER_BRIGHTNESS)).setAlpha(alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1874,7 +1878,7 @@ void LLLineEditor::draw()
|
||||
|
||||
if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
|
||||
{
|
||||
LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], 1.f);
|
||||
LLColor4 color(1.f - bg_color.mV[0], 1.f - bg_color.mV[1], 1.f - bg_color.mV[2], alpha );
|
||||
// selected middle
|
||||
S32 width = mGLFont->getWidth(mText.getWString().c_str(), mScrollHPos + rendered_text, select_right - mScrollHPos - rendered_text);
|
||||
width = llmin(width, mMaxHPixels - llround(rendered_pixels_right));
|
||||
@@ -1883,7 +1887,7 @@ void LLLineEditor::draw()
|
||||
rendered_text += mGLFont->render(
|
||||
mText, mScrollHPos + rendered_text,
|
||||
rendered_pixels_right, text_bottom,
|
||||
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
|
||||
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ),
|
||||
LLFontGL::LEFT, LLFontGL::BOTTOM,
|
||||
LLFontGL::NORMAL,
|
||||
LLFontGL::NO_SHADOW,
|
||||
@@ -1953,7 +1957,7 @@ void LLLineEditor::draw()
|
||||
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
|
||||
{
|
||||
mGLFont->render(mText, getCursor(), (F32)(cursor_left + UI_LINEEDITOR_CURSOR_THICKNESS / 2), text_bottom,
|
||||
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], 1 ),
|
||||
LLColor4( 1.f - text_color.mV[0], 1.f - text_color.mV[1], 1.f - text_color.mV[2], alpha ),
|
||||
LLFontGL::LEFT, LLFontGL::BOTTOM,
|
||||
LLFontGL::NORMAL,
|
||||
LLFontGL::NO_SHADOW,
|
||||
@@ -2551,9 +2555,6 @@ LLXMLNodePtr LLLineEditor::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("line_editor");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -2580,7 +2581,7 @@ LLView* LLLineEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
|
||||
S32 border_thickness = 1;
|
||||
node->getAttributeS32("border_thickness", border_thickness);
|
||||
|
||||
LLLineEditor* line_editor = new LLLineEditor(name,
|
||||
LLLineEditor* line_editor = new LLLineEditor("line_editor",
|
||||
rect,
|
||||
text,
|
||||
font,
|
||||
|
||||
@@ -1928,6 +1928,7 @@ LLXMLNodePtr LLMenuGL::getXML(bool save_children) const
|
||||
|
||||
void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name(child->getName()->mString);
|
||||
if (child->hasName(LL_MENU_GL_TAG))
|
||||
{
|
||||
// SUBMENU
|
||||
@@ -2025,7 +2026,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
|
||||
|
||||
for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling())
|
||||
{
|
||||
if (call_child->hasName("on_check"))
|
||||
if (call_child->hasName("on_check") || call_child->hasName(name+".on_check"))
|
||||
{
|
||||
std::string callback_name;
|
||||
std::string control_name;
|
||||
@@ -2083,7 +2084,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
|
||||
|
||||
for (call_child = child->getFirstChild(); call_child.notNull(); call_child = call_child->getNextSibling())
|
||||
{
|
||||
if (call_child->hasName("on_click"))
|
||||
if (call_child->hasName("on_click") || call_child->hasName(name+".on_click"))
|
||||
{
|
||||
std::string callback_name;
|
||||
call_child->getAttributeString("function", callback_name);
|
||||
@@ -2104,7 +2105,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
|
||||
|
||||
new_item->addListener(callback, "on_click", callback_data);
|
||||
}
|
||||
if (call_child->hasName("on_enable"))
|
||||
if (call_child->hasName("on_enable") || call_child->hasName(name+".on_enable"))
|
||||
{
|
||||
std::string callback_name;
|
||||
std::string control_name;
|
||||
@@ -2148,7 +2149,7 @@ void LLMenuGL::parseChildXML(LLXMLNodePtr child, LLView *parent, LLUICtrlFactory
|
||||
}
|
||||
new_item->setEnabledControl(control_name, parent);
|
||||
}
|
||||
if (call_child->hasName("on_visible"))
|
||||
if (call_child->hasName("on_visible") || call_child->hasName(name+".on_visible"))
|
||||
{
|
||||
std::string callback_name;
|
||||
std::string control_name;
|
||||
@@ -2322,7 +2323,7 @@ LLView* LLMenuGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *fa
|
||||
++token_count;
|
||||
}
|
||||
|
||||
BOOL opaque = FALSE;
|
||||
BOOL opaque = TRUE;
|
||||
node->getAttributeBOOL("opaque", opaque);
|
||||
|
||||
LLMenuGL *menu = new LLMenuGL(name, new_menu_label);
|
||||
@@ -4150,13 +4151,10 @@ LLXMLNodePtr LLMenuBarGL::getXML(bool save_children) const
|
||||
|
||||
LLView* LLMenuBarGL::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("menu");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
BOOL opaque = FALSE;
|
||||
node->getAttributeBOOL("opaque", opaque);
|
||||
|
||||
LLMenuBarGL *menubar = new LLMenuBarGL(name);
|
||||
LLMenuBarGL *menubar = new LLMenuBarGL("menu");
|
||||
|
||||
LLHandle<LLFloater> parent_handle;
|
||||
LLFloater* parent_floater = dynamic_cast<LLFloater*>(parent);
|
||||
|
||||
@@ -624,9 +624,6 @@ LLXMLNodePtr LLMultiSlider::getXML(bool save_children) const
|
||||
//static
|
||||
LLView* LLMultiSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("multi_slider_bar");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -654,7 +651,7 @@ LLView* LLMultiSlider::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor
|
||||
BOOL use_triangle = FALSE;
|
||||
node->getAttributeBOOL("use_triangle", use_triangle);
|
||||
|
||||
LLMultiSlider* multiSlider = new LLMultiSlider(name,
|
||||
LLMultiSlider* multiSlider = new LLMultiSlider("multi_slider_bar",
|
||||
rect,
|
||||
NULL,
|
||||
initial_value,
|
||||
|
||||
@@ -470,9 +470,6 @@ LLXMLNodePtr LLMultiSliderCtrl::getXML(bool save_children) const
|
||||
|
||||
LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("multi_slider");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
std::string label;
|
||||
node->getAttributeString("label", label);
|
||||
|
||||
@@ -556,7 +553,7 @@ LLView* LLMultiSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFa
|
||||
label.assign(node->getTextContents());
|
||||
}
|
||||
|
||||
LLMultiSliderCtrl* slider = new LLMultiSliderCtrl(name,
|
||||
LLMultiSliderCtrl* slider = new LLMultiSliderCtrl("multi_slider",
|
||||
rect,
|
||||
label,
|
||||
font,
|
||||
|
||||
59
indra/llui/llnotificationcontext.h
Normal file
59
indra/llui/llnotificationcontext.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file llnotifications.h
|
||||
* @brief Notification context class, pulled out of llnotifications.h to avoid including said file in llfloater.h. (Needed, as llnotifications.h includes llevents.h, which causes issues)
|
||||
* @author Q (with assistance from Richard and Coco)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-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_LLNOTIFICATION_CONTEX
|
||||
#define LL_LLNOTIFICATION_CONTEX
|
||||
|
||||
// context data that can be looked up via a notification's payload by the display logic
|
||||
// derive from this class to implement specific contexts
|
||||
class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
|
||||
{
|
||||
public:
|
||||
LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~LLNotificationContext() {}
|
||||
|
||||
LLSD asLLSD() const
|
||||
{
|
||||
return getKey();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif //LL_LLNOTIFICATION_CONTEX
|
||||
|
||||
@@ -1562,4 +1562,3 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
|
||||
s << notification.summarize();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -100,11 +100,13 @@
|
||||
#include "llinstancetracker.h"
|
||||
|
||||
// and we need this to manage the notification callbacks
|
||||
#include "llavatarname.h"
|
||||
#include "llevents.h"
|
||||
#include "llfunctorregistry.h"
|
||||
#include "llui.h"
|
||||
#include "llxmlnode.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include "llnotificationcontext.h"
|
||||
|
||||
typedef enum e_notification_priority
|
||||
{
|
||||
@@ -120,26 +122,6 @@ typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder
|
||||
typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
|
||||
typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
|
||||
|
||||
// context data that can be looked up via a notification's payload by the display logic
|
||||
// derive from this class to implement specific contexts
|
||||
class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
|
||||
{
|
||||
public:
|
||||
LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~LLNotificationContext() {}
|
||||
|
||||
LLSD asLLSD() const
|
||||
{
|
||||
return getKey();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
// Contains notification form data, such as buttons and text fields along with
|
||||
// manipulator functions
|
||||
class LLNotificationForm
|
||||
@@ -791,7 +773,5 @@ private:
|
||||
|
||||
LLNotificationMap mUniqueNotifications;
|
||||
};
|
||||
|
||||
|
||||
#endif//LL_LLNOTIFICATIONS_H
|
||||
|
||||
|
||||
@@ -58,13 +58,12 @@
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llfasttimer.h"
|
||||
|
||||
#include "llnotifications.h"
|
||||
|
||||
// LLLayoutStack
|
||||
#include "llresizebar.h"
|
||||
#include "llcriticaldamp.h"
|
||||
|
||||
const S32 RESIZE_BAR_OVERLAP = 1;
|
||||
const S32 RESIZE_BAR_HEIGHT = 3;
|
||||
|
||||
static LLRegisterWidget<LLPanel> r1("panel");
|
||||
|
||||
void LLPanel::init()
|
||||
@@ -84,7 +83,9 @@ void LLPanel::init()
|
||||
}
|
||||
|
||||
LLPanel::LLPanel()
|
||||
: mRectControl()
|
||||
: mRectControl(),
|
||||
mCommitCallbackRegistrar(false),
|
||||
mEnableCallbackRegistrar(false)
|
||||
{
|
||||
init();
|
||||
setName(std::string("panel"));
|
||||
@@ -92,7 +93,9 @@ LLPanel::LLPanel()
|
||||
|
||||
LLPanel::LLPanel(const std::string& name)
|
||||
: LLUICtrl(name),
|
||||
mRectControl()
|
||||
mRectControl(),
|
||||
mCommitCallbackRegistrar(false),
|
||||
mEnableCallbackRegistrar(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -100,7 +103,9 @@ LLPanel::LLPanel(const std::string& name)
|
||||
|
||||
LLPanel::LLPanel(const std::string& name, const LLRect& rect, BOOL bordered)
|
||||
: LLUICtrl(name,rect),
|
||||
mRectControl()
|
||||
mRectControl(),
|
||||
mCommitCallbackRegistrar(false),
|
||||
mEnableCallbackRegistrar(false)
|
||||
{
|
||||
init();
|
||||
if (bordered)
|
||||
@@ -112,7 +117,9 @@ LLPanel::LLPanel(const std::string& name, const LLRect& rect, BOOL bordered)
|
||||
|
||||
LLPanel::LLPanel(const std::string& name, const std::string& rect_control, BOOL bordered)
|
||||
: LLUICtrl(name, LLUI::sConfigGroup->getRect(rect_control)),
|
||||
mRectControl( rect_control )
|
||||
mRectControl( rect_control ),
|
||||
mCommitCallbackRegistrar(false),
|
||||
mEnableCallbackRegistrar(false)
|
||||
{
|
||||
init();
|
||||
if (bordered)
|
||||
@@ -459,7 +466,12 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
|
||||
createRect(node, rect, parent, LLRect());
|
||||
// create a new panel without a border, by default
|
||||
panelp = new LLPanel(name, rect, FALSE);
|
||||
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
|
||||
panelp->mCommitCallbackRegistrar.pushScope();
|
||||
panelp->mEnableCallbackRegistrar.pushScope();
|
||||
panelp->initPanelXML(node, parent, factory);
|
||||
panelp->mCommitCallbackRegistrar.popScope();
|
||||
panelp->mEnableCallbackRegistrar.popScope();
|
||||
// preserve panel's width and height, but override the location
|
||||
const LLRect& panelrect = panelp->getRect();
|
||||
S32 w = panelrect.getWidth();
|
||||
@@ -470,7 +482,14 @@ LLView* LLPanel::fromXML(LLXMLNodePtr node, LLView* parent, LLUICtrlFactory *fac
|
||||
else
|
||||
{
|
||||
if(!factory->builtPanel(panelp))
|
||||
{
|
||||
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
|
||||
panelp->mCommitCallbackRegistrar.pushScope();
|
||||
panelp->mEnableCallbackRegistrar.pushScope();
|
||||
panelp->initPanelXML(node, parent, factory);
|
||||
panelp->mCommitCallbackRegistrar.popScope();
|
||||
panelp->mEnableCallbackRegistrar.popScope();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLRect new_rect = panelp->getRect();
|
||||
@@ -1020,651 +1039,3 @@ void LLPanel::storeRectControl()
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// LLLayoutStack
|
||||
//
|
||||
struct LLLayoutStack::LLEmbeddedPanel
|
||||
{
|
||||
LLEmbeddedPanel(LLPanel* panelp, eLayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) :
|
||||
mPanel(panelp),
|
||||
mMinWidth(min_width),
|
||||
mMinHeight(min_height),
|
||||
mAutoResize(auto_resize),
|
||||
mUserResize(user_resize),
|
||||
mOrientation(orientation),
|
||||
mCollapsed(FALSE),
|
||||
mCollapseAmt(0.f),
|
||||
mVisibleAmt(1.f) // default to fully visible
|
||||
{
|
||||
LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
|
||||
|
||||
S32 min_dim;
|
||||
if (orientation == HORIZONTAL)
|
||||
{
|
||||
min_dim = mMinHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_dim = mMinWidth;
|
||||
}
|
||||
LLResizeBar::Params p;
|
||||
p.name = "resizer";
|
||||
p.resizing_view = mPanel;
|
||||
p.min_size = min_dim;
|
||||
p.max_size = S32_MAX;
|
||||
p.side = side;
|
||||
mResizeBar = LLUICtrlFactory::create<LLResizeBar>(p);
|
||||
mResizeBar->setEnableSnapping(FALSE);
|
||||
// panels initialized as hidden should not start out partially visible
|
||||
if (!mPanel->getVisible())
|
||||
{
|
||||
mVisibleAmt = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
~LLEmbeddedPanel()
|
||||
{
|
||||
// probably not necessary, but...
|
||||
delete mResizeBar;
|
||||
mResizeBar = NULL;
|
||||
}
|
||||
|
||||
F32 getCollapseFactor()
|
||||
{
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
F32 collapse_amt =
|
||||
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth()));
|
||||
return mVisibleAmt * collapse_amt;
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 collapse_amt =
|
||||
clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight())));
|
||||
return mVisibleAmt * collapse_amt;
|
||||
}
|
||||
}
|
||||
|
||||
LLPanel* mPanel;
|
||||
S32 mMinWidth;
|
||||
S32 mMinHeight;
|
||||
BOOL mAutoResize;
|
||||
BOOL mUserResize;
|
||||
BOOL mCollapsed;
|
||||
LLResizeBar* mResizeBar;
|
||||
eLayoutOrientation mOrientation;
|
||||
F32 mVisibleAmt;
|
||||
F32 mCollapseAmt;
|
||||
};
|
||||
|
||||
static LLRegisterWidget<LLLayoutStack> r2("layout_stack");
|
||||
|
||||
LLLayoutStack::LLLayoutStack(eLayoutOrientation orientation) :
|
||||
mOrientation(orientation),
|
||||
mMinWidth(0),
|
||||
mMinHeight(0),
|
||||
mPanelSpacing(RESIZE_BAR_HEIGHT)
|
||||
{
|
||||
}
|
||||
|
||||
LLLayoutStack::~LLLayoutStack()
|
||||
{
|
||||
std::for_each(mPanels.begin(), mPanels.end(), DeletePointer());
|
||||
}
|
||||
|
||||
void LLLayoutStack::draw()
|
||||
{
|
||||
updateLayout();
|
||||
|
||||
e_panel_list_t::iterator panel_it;
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
// clip to layout rectangle, not bounding rectangle
|
||||
LLRect clip_rect = (*panel_it)->mPanel->getRect();
|
||||
// scale clipping rectangle by visible amount
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
|
||||
}
|
||||
else
|
||||
{
|
||||
clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
|
||||
}
|
||||
|
||||
LLPanel* panelp = (*panel_it)->mPanel;
|
||||
|
||||
LLLocalClipRect clip(clip_rect);
|
||||
// only force drawing invisible children if visible amount is non-zero
|
||||
drawChild(panelp, 0, 0, clip_rect.notEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
void LLLayoutStack::removeChild(LLView* ctrl)
|
||||
{
|
||||
LLView::removeChild(ctrl);
|
||||
LLPanel* panel = dynamic_cast<LLPanel*>(ctrl);
|
||||
if(!panel)
|
||||
return;
|
||||
LLEmbeddedPanel* embedded_panelp = findEmbeddedPanel(panel);
|
||||
|
||||
if (embedded_panelp)
|
||||
{
|
||||
mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
|
||||
delete embedded_panelp;
|
||||
}
|
||||
|
||||
// need to update resizebars
|
||||
|
||||
calcMinExtents();
|
||||
}
|
||||
|
||||
LLXMLNodePtr LLLayoutStack::getXML(bool save_children) const
|
||||
{
|
||||
LLXMLNodePtr node = LLView::getXML();
|
||||
node->setName(LL_LAYOUT_STACK_TAG);
|
||||
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
node->createChild("orientation", TRUE)->setStringValue("horizontal");
|
||||
}
|
||||
else
|
||||
{
|
||||
node->createChild("orientation", TRUE)->setStringValue("vertical");
|
||||
}
|
||||
|
||||
if (save_children)
|
||||
{
|
||||
LLView::child_list_const_reverse_iter_t rit;
|
||||
for (rit = getChildList()->rbegin(); rit != getChildList()->rend(); ++rit)
|
||||
{
|
||||
LLView* childp = *rit;
|
||||
|
||||
if (childp->getSaveToXML())
|
||||
{
|
||||
LLXMLNodePtr xml_node = childp->getXML();
|
||||
|
||||
if (xml_node->hasName(LL_PANEL_TAG))
|
||||
{
|
||||
xml_node->setName(LL_LAYOUT_PANEL_TAG);
|
||||
}
|
||||
|
||||
node->addChild(xml_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
//static
|
||||
LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string orientation_string("vertical");
|
||||
node->getAttributeString("orientation", orientation_string);
|
||||
|
||||
eLayoutOrientation orientation = VERTICAL;
|
||||
|
||||
if (orientation_string == "horizontal")
|
||||
{
|
||||
orientation = HORIZONTAL;
|
||||
}
|
||||
else if (orientation_string == "vertical")
|
||||
{
|
||||
orientation = VERTICAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Unknown orientation " << orientation_string << ", using vertical" << llendl;
|
||||
}
|
||||
|
||||
LLLayoutStack* layout_stackp = new LLLayoutStack(orientation);
|
||||
|
||||
node->getAttributeS32("border_size", layout_stackp->mPanelSpacing);
|
||||
// don't allow negative spacing values
|
||||
layout_stackp->mPanelSpacing = llmax(layout_stackp->mPanelSpacing, 0);
|
||||
|
||||
std::string name("stack");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
layout_stackp->setName(name);
|
||||
layout_stackp->initFromXML(node, parent);
|
||||
|
||||
LLXMLNodePtr child;
|
||||
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
|
||||
{
|
||||
S32 min_width = 0;
|
||||
S32 min_height = 0;
|
||||
BOOL auto_resize = TRUE;
|
||||
|
||||
child->getAttributeS32("min_width", min_width);
|
||||
child->getAttributeS32("min_height", min_height);
|
||||
child->getAttributeBOOL("auto_resize", auto_resize);
|
||||
|
||||
if (child->hasName("layout_panel"))
|
||||
{
|
||||
BOOL user_resize = TRUE;
|
||||
child->getAttributeBOOL("user_resize", user_resize);
|
||||
LLPanel* panelp = (LLPanel*)LLPanel::fromXML(child, layout_stackp, factory);
|
||||
if (panelp)
|
||||
{
|
||||
panelp->setFollowsNone();
|
||||
layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL user_resize = FALSE;
|
||||
child->getAttributeBOOL("user_resize", user_resize);
|
||||
|
||||
LLPanel* panelp = new LLPanel(std::string("auto_panel"));
|
||||
LLView* new_child = factory->createWidget(panelp, child);
|
||||
if (new_child)
|
||||
{
|
||||
// put child in new embedded panel
|
||||
layout_stackp->addPanel(panelp, min_width, min_height, auto_resize, user_resize);
|
||||
// resize panel to contain widget and move widget to be contained in panel
|
||||
panelp->setRect(new_child->getRect());
|
||||
new_child->setOrigin(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
panelp->die();
|
||||
}
|
||||
}
|
||||
}
|
||||
layout_stackp->updateLayout();
|
||||
|
||||
return layout_stackp;
|
||||
}
|
||||
|
||||
S32 LLLayoutStack::getDefaultHeight(S32 cur_height)
|
||||
{
|
||||
// if we are spanning our children (crude upward propagation of size)
|
||||
// then don't enforce our size on our children
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
cur_height = llmax(mMinHeight, getRect().getHeight());
|
||||
}
|
||||
|
||||
return cur_height;
|
||||
}
|
||||
|
||||
S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
|
||||
{
|
||||
// if we are spanning our children (crude upward propagation of size)
|
||||
// then don't enforce our size on our children
|
||||
if (mOrientation == VERTICAL)
|
||||
{
|
||||
cur_width = llmax(mMinWidth, getRect().getWidth());
|
||||
}
|
||||
|
||||
return cur_width;
|
||||
}
|
||||
|
||||
void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
|
||||
{
|
||||
// panel starts off invisible (collapsed)
|
||||
if (animate == ANIMATE)
|
||||
{
|
||||
panel->setVisible(FALSE);
|
||||
}
|
||||
LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
|
||||
|
||||
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
|
||||
|
||||
addChild(panel);
|
||||
addChild(embedded_panel->mResizeBar);
|
||||
|
||||
// bring all resize bars to the front so that they are clickable even over the panels
|
||||
// with a bit of overlap
|
||||
for (e_panel_list_t::iterator panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
LLResizeBar* resize_barp = (*panel_it)->mResizeBar;
|
||||
sendChildToFront(resize_barp);
|
||||
}
|
||||
|
||||
// start expanding panel animation
|
||||
if (animate == ANIMATE)
|
||||
{
|
||||
panel->setVisible(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLLayoutStack::removePanel(LLPanel* panel)
|
||||
{
|
||||
removeChild(panel);
|
||||
}
|
||||
|
||||
void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
|
||||
{
|
||||
LLEmbeddedPanel* panel_container = findEmbeddedPanel(panel);
|
||||
if (!panel_container) return;
|
||||
|
||||
panel_container->mCollapsed = collapsed;
|
||||
}
|
||||
|
||||
void LLLayoutStack::updateLayout(BOOL force_resize)
|
||||
{
|
||||
calcMinExtents();
|
||||
|
||||
// calculate current extents
|
||||
S32 total_width = 0;
|
||||
S32 total_height = 0;
|
||||
|
||||
const F32 ANIM_OPEN_TIME = 0.02f;
|
||||
const F32 ANIM_CLOSE_TIME = 0.03f;
|
||||
|
||||
e_panel_list_t::iterator panel_it;
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
LLPanel* panelp = (*panel_it)->mPanel;
|
||||
if (panelp->getVisible())
|
||||
{
|
||||
(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_OPEN_TIME));
|
||||
if ((*panel_it)->mVisibleAmt > 0.99f)
|
||||
{
|
||||
(*panel_it)->mVisibleAmt = 1.f;
|
||||
}
|
||||
}
|
||||
else // not visible
|
||||
{
|
||||
(*panel_it)->mVisibleAmt = lerp((*panel_it)->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
|
||||
if ((*panel_it)->mVisibleAmt < 0.001f)
|
||||
{
|
||||
(*panel_it)->mVisibleAmt = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*panel_it)->mCollapsed)
|
||||
{
|
||||
(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
|
||||
}
|
||||
else
|
||||
{
|
||||
(*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
|
||||
}
|
||||
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
// enforce minimize size constraint by default
|
||||
if (panelp->getRect().getWidth() < (*panel_it)->mMinWidth)
|
||||
{
|
||||
panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
|
||||
}
|
||||
total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
|
||||
// want n-1 panel gaps for n panels
|
||||
if (panel_it != mPanels.begin())
|
||||
{
|
||||
total_width += mPanelSpacing;
|
||||
}
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
// enforce minimize size constraint by default
|
||||
if (panelp->getRect().getHeight() < (*panel_it)->mMinHeight)
|
||||
{
|
||||
panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
|
||||
}
|
||||
total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
|
||||
if (panel_it != mPanels.begin())
|
||||
{
|
||||
total_height += mPanelSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32 num_resizable_panels = 0;
|
||||
S32 shrink_headroom_available = 0;
|
||||
S32 shrink_headroom_total = 0;
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
// panels that are not fully visible do not count towards shrink headroom
|
||||
if ((*panel_it)->getCollapseFactor() < 1.f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if currently resizing a panel or the panel is flagged as not automatically resizing
|
||||
// only track total available headroom, but don't use it for automatic resize logic
|
||||
if ((*panel_it)->mResizeBar->hasMouseCapture()
|
||||
|| (!(*panel_it)->mAutoResize
|
||||
&& !force_resize))
|
||||
{
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num_resizable_panels++;
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
shrink_headroom_available += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
|
||||
shrink_headroom_total += (*panel_it)->mPanel->getRect().getWidth() - (*panel_it)->mMinWidth;
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
shrink_headroom_available += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
|
||||
shrink_headroom_total += (*panel_it)->mPanel->getRect().getHeight() - (*panel_it)->mMinHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate how many pixels need to be distributed among layout panels
|
||||
// positive means panels need to grow, negative means shrink
|
||||
S32 pixels_to_distribute;
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
pixels_to_distribute = getRect().getWidth() - total_width;
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
pixels_to_distribute = getRect().getHeight() - total_height;
|
||||
}
|
||||
|
||||
// now we distribute the pixels...
|
||||
S32 cur_x = 0;
|
||||
S32 cur_y = getRect().getHeight();
|
||||
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
LLPanel* panelp = (*panel_it)->mPanel;
|
||||
|
||||
S32 cur_width = panelp->getRect().getWidth();
|
||||
S32 cur_height = panelp->getRect().getHeight();
|
||||
S32 new_width = llmax((*panel_it)->mMinWidth, cur_width);
|
||||
S32 new_height = llmax((*panel_it)->mMinHeight, cur_height);
|
||||
|
||||
S32 delta_size = 0;
|
||||
|
||||
// if panel can automatically resize (not animating, and resize flag set)...
|
||||
if ((*panel_it)->getCollapseFactor() == 1.f
|
||||
&& (force_resize || (*panel_it)->mAutoResize)
|
||||
&& !(*panel_it)->mResizeBar->hasMouseCapture())
|
||||
{
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
// if we're shrinking
|
||||
if (pixels_to_distribute < 0)
|
||||
{
|
||||
// shrink proportionally to amount over minimum
|
||||
// so we can do this in one pass
|
||||
delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_width - (*panel_it)->mMinWidth) / (F32)shrink_headroom_available)) : 0;
|
||||
shrink_headroom_available -= (cur_width - (*panel_it)->mMinWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
// grow all elements equally
|
||||
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
|
||||
num_resizable_panels--;
|
||||
}
|
||||
pixels_to_distribute -= delta_size;
|
||||
new_width = llmax((*panel_it)->mMinWidth, cur_width + delta_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_width = getDefaultWidth(new_width);
|
||||
}
|
||||
|
||||
if (mOrientation == VERTICAL)
|
||||
{
|
||||
if (pixels_to_distribute < 0)
|
||||
{
|
||||
// shrink proportionally to amount over minimum
|
||||
// so we can do this in one pass
|
||||
delta_size = (shrink_headroom_available > 0) ? llround((F32)pixels_to_distribute * ((F32)(cur_height - (*panel_it)->mMinHeight) / (F32)shrink_headroom_available)) : 0;
|
||||
shrink_headroom_available -= (cur_height - (*panel_it)->mMinHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
delta_size = llround((F32)pixels_to_distribute / (F32)num_resizable_panels);
|
||||
num_resizable_panels--;
|
||||
}
|
||||
pixels_to_distribute -= delta_size;
|
||||
new_height = llmax((*panel_it)->mMinHeight, cur_height + delta_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_height = getDefaultHeight(new_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
new_height = getDefaultHeight(new_height);
|
||||
}
|
||||
else // VERTICAL
|
||||
{
|
||||
new_width = getDefaultWidth(new_width);
|
||||
}
|
||||
}
|
||||
|
||||
// adjust running headroom count based on new sizes
|
||||
shrink_headroom_total += delta_size;
|
||||
|
||||
panelp->reshape(new_width, new_height);
|
||||
panelp->setOrigin(cur_x, cur_y - new_height);
|
||||
|
||||
LLRect panel_rect = panelp->getRect();
|
||||
LLRect resize_bar_rect = panel_rect;
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
resize_bar_rect.mLeft = panel_rect.mRight - RESIZE_BAR_OVERLAP;
|
||||
resize_bar_rect.mRight = panel_rect.mRight + mPanelSpacing + RESIZE_BAR_OVERLAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
resize_bar_rect.mTop = panel_rect.mBottom + RESIZE_BAR_OVERLAP;
|
||||
resize_bar_rect.mBottom = panel_rect.mBottom - mPanelSpacing - RESIZE_BAR_OVERLAP;
|
||||
}
|
||||
(*panel_it)->mResizeBar->setRect(resize_bar_rect);
|
||||
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
// update resize bars with new limits
|
||||
LLResizeBar* last_resize_bar = NULL;
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
LLPanel* panelp = (*panel_it)->mPanel;
|
||||
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
(*panel_it)->mResizeBar->setResizeLimits(
|
||||
(*panel_it)->mMinWidth,
|
||||
(*panel_it)->mMinWidth + shrink_headroom_total);
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
(*panel_it)->mResizeBar->setResizeLimits(
|
||||
(*panel_it)->mMinHeight,
|
||||
(*panel_it)->mMinHeight + shrink_headroom_total);
|
||||
}
|
||||
|
||||
// toggle resize bars based on panel visibility, resizability, etc
|
||||
BOOL resize_bar_enabled = panelp->getVisible() && (*panel_it)->mUserResize;
|
||||
(*panel_it)->mResizeBar->setVisible(resize_bar_enabled);
|
||||
|
||||
if (resize_bar_enabled)
|
||||
{
|
||||
last_resize_bar = (*panel_it)->mResizeBar;
|
||||
}
|
||||
}
|
||||
|
||||
// hide last resize bar as there is nothing past it
|
||||
// resize bars need to be in between two resizable panels
|
||||
if (last_resize_bar)
|
||||
{
|
||||
last_resize_bar->setVisible(FALSE);
|
||||
}
|
||||
|
||||
// not enough room to fit existing contents
|
||||
if (force_resize == FALSE
|
||||
// layout did not complete by reaching target position
|
||||
&& ((mOrientation == VERTICAL && cur_y != -mPanelSpacing)
|
||||
|| (mOrientation == HORIZONTAL && cur_x != getRect().getWidth() + mPanelSpacing)))
|
||||
{
|
||||
// do another layout pass with all stacked elements contributing
|
||||
// even those that don't usually resize
|
||||
llassert_always(force_resize == FALSE);
|
||||
updateLayout(TRUE);
|
||||
}
|
||||
} // end LLLayoutStack::updateLayout
|
||||
|
||||
|
||||
LLLayoutStack::LLEmbeddedPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) const
|
||||
{
|
||||
e_panel_list_t::const_iterator panel_it;
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
if ((*panel_it)->mPanel == panelp)
|
||||
{
|
||||
return *panel_it;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LLLayoutStack::calcMinExtents()
|
||||
{
|
||||
mMinWidth = 0;
|
||||
mMinHeight = 0;
|
||||
|
||||
e_panel_list_t::iterator panel_it;
|
||||
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
|
||||
{
|
||||
if (mOrientation == HORIZONTAL)
|
||||
{
|
||||
mMinHeight = llmax( mMinHeight,
|
||||
(*panel_it)->mMinHeight);
|
||||
mMinWidth += (*panel_it)->mMinWidth;
|
||||
if (panel_it != mPanels.begin())
|
||||
{
|
||||
mMinWidth += mPanelSpacing;
|
||||
}
|
||||
}
|
||||
else //VERTICAL
|
||||
{
|
||||
mMinWidth = llmax( mMinWidth,
|
||||
(*panel_it)->mMinWidth);
|
||||
mMinHeight += (*panel_it)->mMinHeight;
|
||||
if (panel_it != mPanels.begin())
|
||||
{
|
||||
mMinHeight += mPanelSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,9 @@ public:
|
||||
|
||||
const LLCallbackMap::map_t& getFactoryMap() const { return mFactoryMap; }
|
||||
|
||||
BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
CommitCallbackRegistry::ScopedRegistrar& getCommitCallbackRegistrar() { return mCommitCallbackRegistrar; }
|
||||
EnableCallbackRegistry::ScopedRegistrar& getEnableCallbackRegistrar() { return mEnableCallbackRegistrar; }
|
||||
virtual BOOL initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
void initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory);
|
||||
void setPanelParameters(LLXMLNodePtr node, LLView *parentp);
|
||||
|
||||
@@ -230,6 +232,8 @@ protected:
|
||||
// Override to set not found list
|
||||
LLButton* getDefaultButton() { return mDefaultBtn; }
|
||||
LLCallbackMap::map_t mFactoryMap;
|
||||
CommitCallbackRegistry::ScopedRegistrar mCommitCallbackRegistrar;
|
||||
EnableCallbackRegistry::ScopedRegistrar mEnableCallbackRegistrar;
|
||||
|
||||
commit_signal_t* mVisibleSignal; // Called when visibility changes, passes new visibility as LLSD()
|
||||
private:
|
||||
@@ -258,56 +262,4 @@ private:
|
||||
|
||||
}; // end class LLPanel
|
||||
|
||||
|
||||
class LLLayoutStack : public LLView
|
||||
{
|
||||
public:
|
||||
typedef enum e_layout_orientation
|
||||
{
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
} eLayoutOrientation;
|
||||
|
||||
LLLayoutStack(eLayoutOrientation orientation);
|
||||
virtual ~LLLayoutStack();
|
||||
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
/*virtual*/ void removeChild(LLView* ctrl);
|
||||
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
|
||||
S32 getMinWidth() const { return mMinWidth; }
|
||||
S32 getMinHeight() const { return mMinHeight; }
|
||||
|
||||
typedef enum e_animate
|
||||
{
|
||||
NO_ANIMATE,
|
||||
ANIMATE
|
||||
} EAnimate;
|
||||
|
||||
void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
|
||||
void removePanel(LLPanel* panel);
|
||||
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
|
||||
S32 getNumPanels() { return mPanels.size(); }
|
||||
|
||||
private:
|
||||
struct LLEmbeddedPanel;
|
||||
|
||||
void updateLayout(BOOL force_resize = FALSE);
|
||||
void calcMinExtents();
|
||||
S32 getDefaultHeight(S32 cur_height);
|
||||
S32 getDefaultWidth(S32 cur_width);
|
||||
|
||||
const eLayoutOrientation mOrientation;
|
||||
|
||||
typedef std::vector<LLEmbeddedPanel*> e_panel_list_t;
|
||||
e_panel_list_t mPanels;
|
||||
LLEmbeddedPanel* findEmbeddedPanel(LLPanel* panelp) const;
|
||||
|
||||
S32 mMinWidth;
|
||||
S32 mMinHeight;
|
||||
S32 mPanelSpacing;
|
||||
}; // end class LLLayoutStack
|
||||
|
||||
#endif
|
||||
|
||||
@@ -73,19 +73,19 @@ LLProgressBar::~LLProgressBar()
|
||||
void LLProgressBar::draw()
|
||||
{
|
||||
static LLTimer timer;
|
||||
|
||||
LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
|
||||
F32 alpha = getDrawContext().mAlpha;
|
||||
|
||||
//LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga");
|
||||
LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga");
|
||||
LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga");
|
||||
LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga");
|
||||
//LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga");
|
||||
LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor");
|
||||
|
||||
bar_bg_imagep->draw(getLocalRect(),
|
||||
background_color);
|
||||
bar_bg_imagep->draw(getLocalRect(), background_color % alpha);
|
||||
|
||||
LLRect progress_rect = getLocalRect();
|
||||
progress_rect.mRight = llround(getRect().getWidth() * (mPercentDone / 100.f));
|
||||
bar_fg_imagep->draw(progress_rect);
|
||||
bar_fg_imagep->draw(progress_rect, LLColor4::white % alpha);
|
||||
}
|
||||
|
||||
void LLProgressBar::setPercent(const F32 percent)
|
||||
|
||||
@@ -352,9 +352,6 @@ LLXMLNodePtr LLRadioGroup::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("radio_group");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
U32 initial_value = 0;
|
||||
node->getAttributeU32("initial_value", initial_value);
|
||||
|
||||
@@ -364,7 +361,7 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
LLRadioGroup* radio_group = new LLRadioGroup(name,
|
||||
LLRadioGroup* radio_group = new LLRadioGroup("radio_group",
|
||||
rect,
|
||||
initial_value,
|
||||
NULL,
|
||||
@@ -408,10 +405,8 @@ LLView* LLRadioGroup::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
|
||||
LLRect item_rect;
|
||||
createRect(child, item_rect, radio_group, rect);
|
||||
|
||||
std::string radioname("radio");
|
||||
child->getAttributeString("name", radioname);
|
||||
std::string item_label = child->getTextContents();
|
||||
LLRadioCtrl* radio = radio_group->addRadioButton(radioname, item_label, item_rect, font);
|
||||
LLRadioCtrl* radio = radio_group->addRadioButton("radio", item_label, item_rect, font);
|
||||
|
||||
radio->initFromXML(child, radio_group);
|
||||
}
|
||||
|
||||
@@ -152,13 +152,10 @@ LLXMLNodePtr LLScrollingPanelList::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLScrollingPanelList::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("scrolling_panel_list");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
LLScrollingPanelList* scrolling_panel_list = new LLScrollingPanelList(name, rect);
|
||||
LLScrollingPanelList* scrolling_panel_list = new LLScrollingPanelList("scrolling_panel_list", rect);
|
||||
scrolling_panel_list->initFromXML(node, parent);
|
||||
return scrolling_panel_list;
|
||||
}
|
||||
|
||||
@@ -3104,9 +3104,6 @@ void LLScrollListCtrl::setScrollListParameters(LLXMLNodePtr node)
|
||||
// static
|
||||
LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("scroll_list");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -3132,7 +3129,7 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
|
||||
node->getAttributeBOOL("mouse_wheel_opaque", mouse_wheel_opaque);
|
||||
|
||||
LLScrollListCtrl* scroll_list = new LLScrollListCtrl(
|
||||
name,
|
||||
"scroll_list",
|
||||
rect,
|
||||
NULL,
|
||||
multi_select,
|
||||
|
||||
@@ -147,9 +147,6 @@ void LLSearchEditor::handleKeystroke()
|
||||
// static
|
||||
LLView* LLSearchEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("search_editor");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -158,7 +155,7 @@ LLView* LLSearchEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
|
||||
|
||||
std::string text = node->getValue().substr(0, max_text_length - 1);
|
||||
|
||||
LLSearchEditor* search_editor = new LLSearchEditor(name,
|
||||
LLSearchEditor* search_editor = new LLSearchEditor("search_editor",
|
||||
rect,
|
||||
max_text_length);
|
||||
|
||||
|
||||
@@ -250,6 +250,8 @@ BOOL LLSlider::handleKeyHere(KEY key, MASK mask)
|
||||
|
||||
void LLSlider::draw()
|
||||
{
|
||||
F32 alpha = getDrawContext().mAlpha;
|
||||
|
||||
// since thumb image might still be decoding, need thumb to accomodate image size
|
||||
updateThumbRect();
|
||||
|
||||
@@ -258,31 +260,47 @@ void LLSlider::draw()
|
||||
// drawing solids requires texturing be disabled
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
F32 opacity = getEnabled() ? 1.f : 0.3f;
|
||||
LLColor4 center_color = (mThumbCenterColor % opacity);
|
||||
|
||||
// Track
|
||||
LLRect track_rect(mThumbImage->getWidth() / 2,
|
||||
getLocalRect().getCenterY() + (mTrackImage->getHeight() / 2),
|
||||
getRect().getWidth() - mThumbImage->getWidth() / 2,
|
||||
getLocalRect().getCenterY() - (mTrackImage->getHeight() / 2) );
|
||||
LLRect highlight_rect(track_rect.mLeft, track_rect.mTop, mThumbRect.getCenterX(), track_rect.mBottom);
|
||||
mTrackImage->draw(track_rect);
|
||||
mTrackHighlightImage->draw(highlight_rect);
|
||||
mTrackImage->draw(track_rect, LLColor4::white % alpha);
|
||||
mTrackHighlightImage->draw(highlight_rect, LLColor4::white % alpha);
|
||||
|
||||
// Thumb
|
||||
if( hasMouseCapture() )
|
||||
{
|
||||
// Show ghost where thumb was before dragging began.
|
||||
mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor % 0.3f);
|
||||
}
|
||||
if (hasFocus())
|
||||
{
|
||||
// Draw focus highlighting.
|
||||
mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
|
||||
mThumbImage->drawBorder(mThumbRect, gFocusMgr.getFocusColor() % alpha, gFocusMgr.getFocusFlashWidth());
|
||||
}
|
||||
|
||||
if( hasMouseCapture() )
|
||||
{
|
||||
// Show ghost where thumb was before dragging began.
|
||||
if (mThumbImage.notNull())
|
||||
{
|
||||
mThumbImage->draw(mDragStartThumbRect, mThumbCenterColor % (0.3f * alpha));
|
||||
mThumbImage->draw(mThumbRect, mThumbOutlineColor % alpha);
|
||||
}
|
||||
}
|
||||
else if(!getEnabled())
|
||||
{
|
||||
if (mThumbImage.notNull())
|
||||
{
|
||||
mThumbImage->draw(mThumbRect, mThumbCenterColor % (0.3f * alpha));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mThumbImage.notNull())
|
||||
{
|
||||
mThumbImage->draw(mThumbRect, mThumbCenterColor % alpha);
|
||||
}
|
||||
}
|
||||
// Fill in the thumb.
|
||||
mThumbImage->draw(mThumbRect, hasMouseCapture() ? mThumbOutlineColor : center_color);
|
||||
|
||||
|
||||
LLUICtrl::draw();
|
||||
}
|
||||
@@ -325,9 +343,6 @@ boost::signals2::connection LLSlider::setMouseUpCallback( const commit_signal_t:
|
||||
//static
|
||||
LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("slider_bar");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -346,7 +361,7 @@ LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFacto
|
||||
BOOL volume = node->hasName("volume_slider") ? TRUE : FALSE;
|
||||
node->getAttributeBOOL("volume", volume);
|
||||
|
||||
LLSlider* slider = new LLSlider(name,
|
||||
LLSlider* slider = new LLSlider("slider_bar",
|
||||
rect,
|
||||
NULL,
|
||||
initial_value,
|
||||
|
||||
@@ -96,9 +96,9 @@ private:
|
||||
S32 mMouseOffset;
|
||||
LLRect mDragStartThumbRect;
|
||||
|
||||
LLUIImage* mThumbImage;
|
||||
LLUIImage* mTrackImage;
|
||||
LLUIImage* mTrackHighlightImage;
|
||||
LLPointer<LLUIImage> mThumbImage;
|
||||
LLPointer<LLUIImage> mTrackImage;
|
||||
LLPointer<LLUIImage> mTrackHighlightImage;
|
||||
|
||||
LLRect mThumbRect;
|
||||
LLColor4 mTrackColor;
|
||||
|
||||
@@ -401,9 +401,6 @@ LLXMLNodePtr LLSliderCtrl::getXML(bool save_children) const
|
||||
|
||||
LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("slider");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
std::string label;
|
||||
node->getAttributeString("label", label);
|
||||
|
||||
@@ -478,7 +475,7 @@ LLView* LLSliderCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
|
||||
label.assign(node->getTextContents());
|
||||
}
|
||||
|
||||
LLSliderCtrl* slider = new LLSliderCtrl(name,
|
||||
LLSliderCtrl* slider = new LLSliderCtrl("slider",
|
||||
rect,
|
||||
label,
|
||||
font,
|
||||
|
||||
@@ -515,9 +515,6 @@ LLXMLNodePtr LLSpinCtrl::getXML(bool save_children) const
|
||||
|
||||
LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("spinner");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
std::string label;
|
||||
node->getAttributeString("label", label);
|
||||
|
||||
@@ -552,7 +549,7 @@ LLView* LLSpinCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
|
||||
label.assign( node->getValue() );
|
||||
}
|
||||
|
||||
LLSpinCtrl* spinner = new LLSpinCtrl(name,
|
||||
LLSpinCtrl* spinner = new LLSpinCtrl("spinner",
|
||||
rect,
|
||||
label,
|
||||
font,
|
||||
|
||||
@@ -197,12 +197,16 @@ void LLTextBox::setWrappedText(const LLStringExplicit& in_text, F32 max_width)
|
||||
{
|
||||
max_width = (F32)getRect().getWidth();
|
||||
}
|
||||
if(max_width <= 0.0f)
|
||||
{
|
||||
return; //It makes no sense to try to wrap text to fit zero-width columns. (In fact, it causes infinite recursion in the following while loop!)
|
||||
}
|
||||
|
||||
LLWString wtext = utf8str_to_wstring(in_text);
|
||||
LLWString final_wtext;
|
||||
|
||||
LLWString::size_type cur = 0;;
|
||||
LLWString::size_type len = wtext.size();
|
||||
LLWString::size_type len = wtext.length();
|
||||
|
||||
while (cur < len)
|
||||
{
|
||||
@@ -282,6 +286,7 @@ BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text
|
||||
|
||||
void LLTextBox::draw()
|
||||
{
|
||||
F32 alpha = getDrawContext().mAlpha;
|
||||
if (mBorderVisible)
|
||||
{
|
||||
gl_rect_2d_offset_local(getLocalRect(), 2, FALSE);
|
||||
@@ -292,12 +297,12 @@ void LLTextBox::draw()
|
||||
static LLColor4 color_drop_shadow = LLUI::sColorsGroup->getColor("ColorDropShadow");
|
||||
static S32 drop_shadow_tooltip = LLUI::sConfigGroup->getS32("DropShadowTooltip");
|
||||
gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0,
|
||||
color_drop_shadow, drop_shadow_tooltip);
|
||||
color_drop_shadow % alpha, drop_shadow_tooltip);
|
||||
}
|
||||
|
||||
if (mBackgroundVisible)
|
||||
{
|
||||
gl_rect_2d( getLocalRect(), mBackgroundColor );
|
||||
gl_rect_2d( getLocalRect(), mBackgroundColor % alpha );
|
||||
}
|
||||
|
||||
S32 text_x = 0;
|
||||
@@ -320,16 +325,16 @@ void LLTextBox::draw()
|
||||
{
|
||||
if(mHasHover)
|
||||
{
|
||||
drawText( text_x, text_y, mHoverColor );
|
||||
drawText( text_x, text_y, mHoverColor % alpha );
|
||||
}
|
||||
else
|
||||
{
|
||||
drawText( text_x, text_y, mTextColor );
|
||||
drawText( text_x, text_y, mTextColor % alpha );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
drawText( text_x, text_y, mDisabledColor );
|
||||
drawText( text_x, text_y, mDisabledColor % alpha );
|
||||
}
|
||||
|
||||
if (sDebugRects)
|
||||
@@ -382,6 +387,69 @@ void LLTextBox::reshapeToFitText()
|
||||
reshape( width + 2 * mHPad, height + 2 * mVPad );
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLTextBox::initFromXML(LLXMLNodePtr node, LLView* parent)
|
||||
{
|
||||
LLUICtrl::initFromXML(node, parent);
|
||||
|
||||
LLFontGL* font = LLView::selectFont(node);
|
||||
if(font)
|
||||
mFontGL = font;
|
||||
|
||||
setText(node->getTextContents());
|
||||
|
||||
LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
|
||||
setHAlign(halign);
|
||||
|
||||
node->getAttributeS32("line_spacing", mLineSpacing);
|
||||
|
||||
std::string font_style;
|
||||
if (node->getAttributeString("font-style", font_style))
|
||||
{
|
||||
mFontStyle = LLFontGL::getStyleFromString(font_style);
|
||||
}
|
||||
|
||||
if (node->getAttributeString("font-shadow", font_style))
|
||||
{
|
||||
if(font_style == "soft")
|
||||
mFontShadow = LLFontGL::DROP_SHADOW_SOFT;
|
||||
else if(font_style == "hard")
|
||||
mFontShadow = LLFontGL::DROP_SHADOW;
|
||||
else
|
||||
mFontShadow = LLFontGL::NO_SHADOW;
|
||||
}
|
||||
|
||||
BOOL mouse_opaque = getMouseOpaque();
|
||||
if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
|
||||
{
|
||||
setMouseOpaque(mouse_opaque);
|
||||
}
|
||||
|
||||
if(node->hasAttribute("text_color"))
|
||||
{
|
||||
LLColor4 color;
|
||||
LLUICtrlFactory::getAttributeColor(node, "text_color", color);
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
if(node->hasAttribute("hover_color"))
|
||||
{
|
||||
LLColor4 color;
|
||||
LLUICtrlFactory::getAttributeColor(node, "hover_color", color);
|
||||
setHoverColor(color);
|
||||
setHoverActive(true);
|
||||
}
|
||||
|
||||
BOOL hover_active = FALSE;
|
||||
if(node->getAttributeBOOL("hover", hover_active))
|
||||
{
|
||||
setHoverActive(hover_active);
|
||||
}
|
||||
|
||||
node->getAttributeBOOL("use_ellipses", mUseEllipses);
|
||||
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLXMLNodePtr LLTextBox::getXML(bool save_children) const
|
||||
{
|
||||
@@ -411,68 +479,8 @@ LLXMLNodePtr LLTextBox::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLTextBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("text_box");
|
||||
node->getAttributeString("name", name);
|
||||
LLFontGL* font = LLView::selectFont(node);
|
||||
|
||||
std::string text = node->getTextContents();
|
||||
|
||||
LLTextBox* text_box = new LLTextBox(name,
|
||||
LLRect(),
|
||||
text,
|
||||
font,
|
||||
FALSE);
|
||||
|
||||
|
||||
LLFontGL::HAlign halign = LLView::selectFontHAlign(node);
|
||||
text_box->setHAlign(halign);
|
||||
|
||||
LLTextBox* text_box = new LLTextBox("text_box", LLRect(), "" , NULL, FALSE);
|
||||
text_box->initFromXML(node, parent);
|
||||
|
||||
node->getAttributeS32("line_spacing", text_box->mLineSpacing);
|
||||
|
||||
std::string font_style;
|
||||
if (node->getAttributeString("font-style", font_style))
|
||||
{
|
||||
text_box->mFontStyle = LLFontGL::getStyleFromString(font_style);
|
||||
}
|
||||
|
||||
if (node->getAttributeString("font-shadow", font_style))
|
||||
{
|
||||
if(font_style == "soft")
|
||||
text_box->mFontShadow = LLFontGL::DROP_SHADOW_SOFT;
|
||||
else if(font_style == "hard")
|
||||
text_box->mFontShadow = LLFontGL::DROP_SHADOW;
|
||||
else
|
||||
text_box->mFontShadow = LLFontGL::NO_SHADOW;
|
||||
}
|
||||
|
||||
BOOL mouse_opaque = text_box->getMouseOpaque();
|
||||
if (node->getAttributeBOOL("mouse_opaque", mouse_opaque))
|
||||
{
|
||||
text_box->setMouseOpaque(mouse_opaque);
|
||||
}
|
||||
|
||||
if(node->hasAttribute("text_color"))
|
||||
{
|
||||
LLColor4 color;
|
||||
LLUICtrlFactory::getAttributeColor(node, "text_color", color);
|
||||
text_box->setColor(color);
|
||||
}
|
||||
|
||||
if(node->hasAttribute("hover_color"))
|
||||
{
|
||||
LLColor4 color;
|
||||
LLUICtrlFactory::getAttributeColor(node, "hover_color", color);
|
||||
text_box->setHoverColor(color);
|
||||
text_box->setHoverActive(true);
|
||||
}
|
||||
|
||||
BOOL hover_active = FALSE;
|
||||
if(node->getAttributeBOOL("hover", hover_active))
|
||||
{
|
||||
text_box->setHoverActive(hover_active);
|
||||
}
|
||||
|
||||
return text_box;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
|
||||
virtual ~LLTextBox() {}
|
||||
|
||||
virtual void initFromXML(LLXMLNodePtr node, LLView* parent);
|
||||
virtual LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory);
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "llui.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "lluiimage.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llrect.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "lltimer.h"
|
||||
@@ -96,10 +97,6 @@ const S32 PREEDIT_STANDOUT_THICKNESS = 2;
|
||||
|
||||
|
||||
LLColor4 LLTextEditor::mLinkColor = LLColor4::blue;
|
||||
void (* LLTextEditor::mURLcallback)(const std::string&) = NULL;
|
||||
bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
|
||||
bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4350,11 +4347,15 @@ void LLTextEditor::loadKeywords(const std::string& filename,
|
||||
std::string name = utf8str_trim(funcs[i]);
|
||||
mKeywords.addToken(LLKeywordToken::WORD, name, color, tooltips[i] );
|
||||
}
|
||||
segment_list_t segment_list;
|
||||
mKeywords.findSegments(&segment_list, getWText(), mDefaultColor);
|
||||
|
||||
mKeywords.findSegments( &mSegments, mWText, mDefaultColor );
|
||||
|
||||
llassert( mSegments.front()->getStart() == 0 );
|
||||
llassert( mSegments.back()->getEnd() == getLength() );
|
||||
mSegments.clear();
|
||||
segment_list_t::iterator insert_it = mSegments.begin();
|
||||
for (segment_list_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it)
|
||||
{
|
||||
insert_it = mSegments.insert(insert_it, *list_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4493,11 +4494,7 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask)
|
||||
// and launch it if we did.
|
||||
if (mParseHTML && mHTML.length() > 0)
|
||||
{
|
||||
//Special handling for slurls
|
||||
if ( (mSecondlifeURLcallback!=NULL) && !(*mSecondlifeURLcallback)(mHTML) )
|
||||
{
|
||||
if (mURLcallback!=NULL) (*mURLcallback)(mHTML);
|
||||
}
|
||||
LLUrlAction::clickAction(mHTML);
|
||||
mHTML.clear();
|
||||
}
|
||||
}
|
||||
@@ -4751,9 +4748,6 @@ LLXMLNodePtr LLTextEditor::getXML(bool save_children) const
|
||||
// static
|
||||
LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("text_editor");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLRect rect;
|
||||
createRect(node, rect, parent, LLRect());
|
||||
|
||||
@@ -4767,7 +4761,7 @@ LLView* LLTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory
|
||||
|
||||
std::string text = node->getTextContents().substr(0, max_text_length - 1);
|
||||
|
||||
LLTextEditor* text_editor = new LLTextEditor(name,
|
||||
LLTextEditor* text_editor = new LLTextEditor("text_editor",
|
||||
rect,
|
||||
max_text_length,
|
||||
text,
|
||||
|
||||
@@ -258,10 +258,6 @@ public:
|
||||
|
||||
// Callbacks
|
||||
static void setLinkColor(LLColor4 color) { mLinkColor = color; }
|
||||
static void setURLCallbacks(void (*callback1) (const std::string& url),
|
||||
bool (*callback2) (const std::string& url),
|
||||
bool (*callback3) (const std::string& url) )
|
||||
{ mURLcallback = callback1; mSecondlifeURLcallback = callback2; mSecondlifeURLcallbackRightClick = callback3;}
|
||||
|
||||
void setOnScrollEndCallback(void (*callback)(void*), void* userdata);
|
||||
|
||||
@@ -509,9 +505,6 @@ private:
|
||||
//
|
||||
LLKeywords mKeywords;
|
||||
static LLColor4 mLinkColor;
|
||||
static void (*mURLcallback) (const std::string& url);
|
||||
static bool (*mSecondlifeURLcallback) (const std::string& url);
|
||||
static bool (*mSecondlifeURLcallbackRightClick) (const std::string& url);
|
||||
|
||||
// Concrete LLTextCmd sub-classes used by the LLTextEditor base class
|
||||
class LLTextCmdInsert;
|
||||
|
||||
@@ -161,19 +161,15 @@ void LLUI::setMousePositionScreen(S32 x, S32 y)
|
||||
screen_x = llround((F32)x * getScaleFactor().mV[VX]);
|
||||
screen_y = llround((F32)y * getScaleFactor().mV[VY]);
|
||||
|
||||
LLCoordWindow window_point;
|
||||
LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point);
|
||||
|
||||
LLView::getWindow()->setCursorPosition(window_point);
|
||||
LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert());
|
||||
}
|
||||
|
||||
//static
|
||||
void LLUI::getMousePositionScreen(S32 *x, S32 *y)
|
||||
{
|
||||
LLCoordWindow cursor_pos_window;
|
||||
LLView::getWindow()->getCursorPosition(&cursor_pos_window);
|
||||
LLCoordGL cursor_pos_gl;
|
||||
LLView::getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
|
||||
getWindow()->getCursorPosition(&cursor_pos_window);
|
||||
LLCoordGL cursor_pos_gl(cursor_pos_window.convert());
|
||||
*x = llround((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]);
|
||||
*y = llround((F32)cursor_pos_gl.mY / getScaleFactor().mV[VX]);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "llcontrol.h"
|
||||
#include "llcoord.h"
|
||||
#include "v2math.h"
|
||||
#include "llregistry.h"
|
||||
#include "llrender2dutils.h"
|
||||
#include "llpointer.h"
|
||||
#include "lluiimage.h"
|
||||
@@ -102,6 +103,7 @@ public:
|
||||
static void glRectToScreen(const LLRect& gl, LLRect *screen);
|
||||
// Returns the control group containing the control name, or the default group
|
||||
static LLControlGroup& getControlControlGroup (const std::string& controlname);
|
||||
static LLWindow* getWindow() { return sWindow; }
|
||||
static void setHtmlHelp(LLHtmlHelp* html_help);
|
||||
|
||||
//
|
||||
|
||||
@@ -45,6 +45,8 @@ LLUICtrl::LLUICtrl() :
|
||||
mViewModel(LLViewModelPtr(new LLViewModel)),
|
||||
mCommitSignal(NULL),
|
||||
mValidateSignal(NULL),
|
||||
mMouseEnterSignal(NULL),
|
||||
mMouseLeaveSignal(NULL),
|
||||
mTentative(FALSE),
|
||||
mTabStop(TRUE),
|
||||
mIsChrome(FALSE)
|
||||
@@ -60,6 +62,8 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect rect, BOOL mouse_opaque
|
||||
mCommitSignal(NULL),
|
||||
mValidateSignal(NULL),
|
||||
mViewModel(LLViewModelPtr(new LLViewModel)),
|
||||
mMouseEnterSignal(NULL),
|
||||
mMouseLeaveSignal(NULL),
|
||||
mTentative( FALSE ),
|
||||
mTabStop( TRUE ),
|
||||
mIsChrome(FALSE)
|
||||
@@ -82,6 +86,25 @@ LLUICtrl::~LLUICtrl()
|
||||
delete mValidateSignal;
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (mMouseEnterSignal)
|
||||
{
|
||||
(*mMouseEnterSignal)(this, getValue());
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if(mMouseLeaveSignal)
|
||||
{
|
||||
(*mMouseLeaveSignal)(this, getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void LLUICtrl::onCommit()
|
||||
{
|
||||
if (mCommitSignal)
|
||||
@@ -452,11 +475,62 @@ BOOL LLUICtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect
|
||||
|
||||
void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent)
|
||||
{
|
||||
std::string name;
|
||||
if(node->getAttributeString("name", name))
|
||||
setName(name);
|
||||
|
||||
BOOL has_tab_stop = hasTabStop();
|
||||
node->getAttributeBOOL("tab_stop", has_tab_stop);
|
||||
|
||||
setTabStop(has_tab_stop);
|
||||
|
||||
std::string str = node->getName()->mString;
|
||||
std::string attrib_str;
|
||||
LLXMLNodePtr child_node;
|
||||
|
||||
//Since so many other callback 'types' piggyback off of the commitcallback registrar as well as use the same callback signature
|
||||
//we can assemble a nice little static list to iterate down instead of copy-pasting mostly similar code for each instance.
|
||||
//Validate/enable callbacks differ, as it uses its own registry/callback signature. This could be worked around with a template, but keeping
|
||||
//all the code local to this scope is more beneficial.
|
||||
typedef boost::signals2::connection (LLUICtrl::*commit_fn)( const commit_signal_t::slot_type& cb );
|
||||
static std::pair<std::string,commit_fn> sCallbackRegistryMap[3] =
|
||||
{
|
||||
std::pair<std::string,commit_fn>(".commit_callback",&LLUICtrl::setCommitCallback),
|
||||
std::pair<std::string,commit_fn>(".mouseenter_callback",&LLUICtrl::setMouseEnterCallback),
|
||||
std::pair<std::string,commit_fn>(".mouseleave_callback",&LLUICtrl::setMouseLeaveCallback)
|
||||
};
|
||||
for(S32 i= 0; i < sizeof(sCallbackRegistryMap)/sizeof(sCallbackRegistryMap[0]);++i)
|
||||
{
|
||||
if(node->getChild((str+sCallbackRegistryMap[i].first).c_str(),child_node,false))
|
||||
{
|
||||
if(child_node->getAttributeString("function",attrib_str))
|
||||
{
|
||||
commit_callback_t* func = (CommitCallbackRegistry::getValue(attrib_str));
|
||||
if (func)
|
||||
{
|
||||
if(child_node->getAttributeString("parameter",attrib_str))
|
||||
(this->*sCallbackRegistryMap[i].second)(boost::bind((*func), this, LLSD(attrib_str)));
|
||||
else
|
||||
(this->*sCallbackRegistryMap[i].second)(commit_signal_t::slot_type(*func));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(node->getChild((str+".validate_callback").c_str(),child_node,false))
|
||||
{
|
||||
if(child_node->getAttributeString("function",attrib_str))
|
||||
{
|
||||
enable_callback_t* func = (EnableCallbackRegistry::getValue(attrib_str));
|
||||
if (func)
|
||||
{
|
||||
if(child_node->getAttributeString("parameter",attrib_str))
|
||||
setValidateCallback(boost::bind((*func), this, LLSD(attrib_str)));
|
||||
else
|
||||
setValidateCallback(enable_signal_t::slot_type(*func));
|
||||
}
|
||||
}
|
||||
}
|
||||
LLView::initFromXML(node, parent);
|
||||
}
|
||||
|
||||
@@ -546,3 +620,15 @@ boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t
|
||||
if (!mValidateSignal) mValidateSignal = new enable_signal_t();
|
||||
return mValidateSignal->connect(cb);
|
||||
}
|
||||
|
||||
boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb )
|
||||
{
|
||||
if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t();
|
||||
return mMouseEnterSignal->connect(cb);
|
||||
}
|
||||
|
||||
boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb )
|
||||
{
|
||||
if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t();
|
||||
return mMouseLeaveSignal->connect(cb);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
#include "llinitparam.h"
|
||||
#include "llviewmodel.h" // *TODO move dependency to .cpp file
|
||||
|
||||
class LLUICtrl
|
||||
@@ -48,6 +49,7 @@ class LLUICtrl
|
||||
public:
|
||||
typedef boost::function<void (LLUICtrl* ctrl, const LLSD& param)> commit_callback_t;
|
||||
typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t;
|
||||
typedef boost::function<bool (LLUICtrl* ctrl, const LLSD& param)> enable_callback_t;
|
||||
typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
|
||||
|
||||
LLUICtrl();
|
||||
@@ -65,6 +67,8 @@ public:
|
||||
/*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
|
||||
/*virtual*/ BOOL isCtrl() const;
|
||||
/*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
|
||||
/*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
|
||||
|
||||
// From LLFocusableElement
|
||||
/*virtual*/ void setFocus( BOOL b );
|
||||
@@ -122,7 +126,9 @@ public:
|
||||
//Start using these!
|
||||
boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb );
|
||||
boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb );
|
||||
|
||||
|
||||
boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb );
|
||||
boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb );
|
||||
// *TODO: Deprecate; for backwards compatability only:
|
||||
boost::signals2::connection setCommitCallback( boost::function<void (LLUICtrl*,void*)> cb, void* data);
|
||||
boost::signals2::connection setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb );
|
||||
@@ -139,10 +145,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, typename DERIVED> class CallbackRegistry : public LLRegistrySingleton<std::string, F, DERIVED >
|
||||
{};
|
||||
|
||||
class CommitCallbackRegistry : public CallbackRegistry<commit_callback_t, CommitCallbackRegistry>{};
|
||||
// the enable callback registry is also used for visiblity callbacks
|
||||
class EnableCallbackRegistry : public CallbackRegistry<enable_callback_t, EnableCallbackRegistry>{};
|
||||
|
||||
protected:
|
||||
|
||||
commit_signal_t* mCommitSignal;
|
||||
enable_signal_t* mValidateSignal;
|
||||
|
||||
commit_signal_t* mMouseEnterSignal;
|
||||
commit_signal_t* mMouseLeaveSignal;
|
||||
|
||||
LLViewModelPtr mViewModel;
|
||||
|
||||
|
||||
@@ -102,11 +102,8 @@ public:
|
||||
|
||||
static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
|
||||
{
|
||||
std::string name("pad");
|
||||
node->getAttributeString("name", name);
|
||||
|
||||
LLUICtrlLocate *new_ctrl = new LLUICtrlLocate();
|
||||
new_ctrl->setName(name);
|
||||
new_ctrl->setName("pad");
|
||||
new_ctrl->initFromXML(node, parent);
|
||||
return new_ctrl;
|
||||
}
|
||||
@@ -285,8 +282,12 @@ void LLUICtrlFactory::buildFloaterInternal(LLFloater *floaterp, LLXMLNodePtr &ro
|
||||
mFactoryStack.push_front(factory_map);
|
||||
}
|
||||
|
||||
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
|
||||
floaterp->getCommitCallbackRegistrar().pushScope();
|
||||
floaterp->getEnableCallbackRegistrar().pushScope();
|
||||
floaterp->initFloaterXML(root, NULL, this, open); /* Flawfinder: ignore */
|
||||
|
||||
floaterp->getCommitCallbackRegistrar().popScope();
|
||||
floaterp->getEnableCallbackRegistrar().popScope();
|
||||
if (LLUI::sShowXUINames)
|
||||
{
|
||||
floaterp->setToolTip(filename);
|
||||
@@ -381,8 +382,13 @@ BOOL LLUICtrlFactory::buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, co
|
||||
mFactoryStack.push_front(factory_map);
|
||||
}
|
||||
|
||||
// for local registry callbacks; define in constructor, referenced in XUI or postBuild
|
||||
panelp->getCommitCallbackRegistrar().pushScope();
|
||||
panelp->getEnableCallbackRegistrar().pushScope();
|
||||
didPost = panelp->initPanelXML(root, NULL, this);
|
||||
|
||||
panelp->getCommitCallbackRegistrar().popScope();
|
||||
panelp->getEnableCallbackRegistrar().popScope();
|
||||
|
||||
if (LLUI::sShowXUINames)
|
||||
{
|
||||
panelp->setToolTip(filename);
|
||||
|
||||
159
indra/llui/llurlaction.cpp
Normal file
159
indra/llui/llurlaction.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
* @file llurlaction.cpp
|
||||
* @author Martin Reddy
|
||||
* @brief A set of actions that can performed on Urls
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llurlaction.h"
|
||||
#include "llview.h"
|
||||
#include "llwindow.h"
|
||||
#include "llurlregistry.h"
|
||||
|
||||
// global state for the callback functions
|
||||
LLUrlAction::url_callback_t LLUrlAction::sOpenURLCallback;
|
||||
LLUrlAction::url_callback_t LLUrlAction::sOpenURLInternalCallback;
|
||||
LLUrlAction::url_callback_t LLUrlAction::sOpenURLExternalCallback;
|
||||
LLUrlAction::execute_url_callback_t LLUrlAction::sExecuteSLURLCallback;
|
||||
|
||||
|
||||
void LLUrlAction::setOpenURLCallback(url_callback_t cb)
|
||||
{
|
||||
sOpenURLCallback = cb;
|
||||
}
|
||||
|
||||
void LLUrlAction::setOpenURLInternalCallback(url_callback_t cb)
|
||||
{
|
||||
sOpenURLInternalCallback = cb;
|
||||
}
|
||||
|
||||
void LLUrlAction::setOpenURLExternalCallback(url_callback_t cb)
|
||||
{
|
||||
sOpenURLExternalCallback = cb;
|
||||
}
|
||||
|
||||
void LLUrlAction::setExecuteSLURLCallback(execute_url_callback_t cb)
|
||||
{
|
||||
sExecuteSLURLCallback = cb;
|
||||
}
|
||||
|
||||
void LLUrlAction::openURL(std::string url)
|
||||
{
|
||||
if (sOpenURLCallback)
|
||||
{
|
||||
sOpenURLCallback(url);
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::openURLInternal(std::string url)
|
||||
{
|
||||
if (sOpenURLInternalCallback)
|
||||
{
|
||||
sOpenURLInternalCallback(url);
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::openURLExternal(std::string url)
|
||||
{
|
||||
if (sOpenURLExternalCallback)
|
||||
{
|
||||
sOpenURLExternalCallback(url);
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::executeSLURL(std::string url)
|
||||
{
|
||||
if (sExecuteSLURLCallback)
|
||||
{
|
||||
sExecuteSLURLCallback(url);
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::clickAction(std::string url)
|
||||
{
|
||||
// Try to handle as SLURL first, then http Url
|
||||
if ( (sExecuteSLURLCallback) && !sExecuteSLURLCallback(url) )
|
||||
{
|
||||
if (sOpenURLCallback)
|
||||
{
|
||||
sOpenURLCallback(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::teleportToLocation(std::string url)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
if (LLUrlRegistry::instance().findUrl(url, match))
|
||||
{
|
||||
if (! match.getLocation().empty())
|
||||
{
|
||||
executeSLURL("secondlife:///app/teleport/" + match.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::showLocationOnMap(std::string url)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
if (LLUrlRegistry::instance().findUrl(url, match))
|
||||
{
|
||||
if (! match.getLocation().empty())
|
||||
{
|
||||
executeSLURL("secondlife:///app/worldmap/" + match.getLocation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::copyURLToClipboard(std::string url)
|
||||
{
|
||||
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(url));
|
||||
}
|
||||
|
||||
void LLUrlAction::copyLabelToClipboard(std::string url)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
if (LLUrlRegistry::instance().findUrl(url, match))
|
||||
{
|
||||
LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(match.getLabel()));
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::showProfile(std::string url)
|
||||
{
|
||||
// Get id from 'secondlife:///app/{cmd}/{id}/{action}'
|
||||
// and show its profile
|
||||
LLURI uri(url);
|
||||
LLSD path_array = uri.pathArray();
|
||||
if (path_array.size() == 4)
|
||||
{
|
||||
std::string id_str = path_array.get(2).asString();
|
||||
if (LLUUID::validate(id_str))
|
||||
{
|
||||
std::string cmd_str = path_array.get(1).asString();
|
||||
executeSLURL("secondlife:///app/" + cmd_str + "/" + id_str + "/about");
|
||||
}
|
||||
}
|
||||
}
|
||||
98
indra/llui/llurlaction.h
Normal file
98
indra/llui/llurlaction.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file llurlaction.h
|
||||
* @author Martin Reddy
|
||||
* @brief A set of actions that can performed on Urls
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLURLACTION_H
|
||||
#define LL_LLURLACTION_H
|
||||
|
||||
#include <string>
|
||||
#include <boost/function.hpp>
|
||||
|
||||
///
|
||||
/// The LLUrlAction class provides a number of static functions that
|
||||
/// let you open Urls in web browsers, execute SLURLs, and copy Urls
|
||||
/// to the clipboard. Many of these functions are not available at
|
||||
/// the llui level, and must be supplied via a set of callbacks.
|
||||
///
|
||||
/// N.B. The action functions specifically do not use const ref
|
||||
/// strings so that a url parameter can be used into a boost::bind()
|
||||
/// call under situations when that input string is deallocated before
|
||||
/// the callback is executed.
|
||||
///
|
||||
class LLUrlAction
|
||||
{
|
||||
public:
|
||||
LLUrlAction();
|
||||
|
||||
/// load a Url in the user's preferred web browser
|
||||
static void openURL(std::string url);
|
||||
|
||||
/// load a Url in the internal Second Life web browser
|
||||
static void openURLInternal(std::string url);
|
||||
|
||||
/// load a Url in the operating system's default web browser
|
||||
static void openURLExternal(std::string url);
|
||||
|
||||
/// execute the given secondlife: SLURL
|
||||
static void executeSLURL(std::string url);
|
||||
|
||||
/// if the Url specifies an SL location, teleport there
|
||||
static void teleportToLocation(std::string url);
|
||||
|
||||
/// if the Url specifies an SL location, show it on a map
|
||||
static void showLocationOnMap(std::string url);
|
||||
|
||||
/// perform the appropriate action for left-clicking on a Url
|
||||
static void clickAction(std::string url);
|
||||
|
||||
/// copy the label for a Url to the clipboard
|
||||
static void copyLabelToClipboard(std::string url);
|
||||
|
||||
/// copy a Url to the clipboard
|
||||
static void copyURLToClipboard(std::string url);
|
||||
|
||||
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
|
||||
static void showProfile(std::string url);
|
||||
|
||||
/// specify the callbacks to enable this class's functionality
|
||||
typedef boost::function<void (const std::string&)> url_callback_t;
|
||||
typedef boost::function<bool(const std::string& url)> execute_url_callback_t;
|
||||
|
||||
static void setOpenURLCallback(url_callback_t cb);
|
||||
static void setOpenURLInternalCallback(url_callback_t cb);
|
||||
static void setOpenURLExternalCallback(url_callback_t cb);
|
||||
static void setExecuteSLURLCallback(execute_url_callback_t cb);
|
||||
|
||||
private:
|
||||
// callbacks for operations we can perform on Urls
|
||||
static url_callback_t sOpenURLCallback;
|
||||
static url_callback_t sOpenURLInternalCallback;
|
||||
static url_callback_t sOpenURLExternalCallback;
|
||||
|
||||
static execute_url_callback_t sExecuteSLURLCallback;
|
||||
};
|
||||
|
||||
#endif
|
||||
1188
indra/llui/llurlentry.cpp
Normal file
1188
indra/llui/llurlentry.cpp
Normal file
File diff suppressed because it is too large
Load Diff
429
indra/llui/llurlentry.h
Normal file
429
indra/llui/llurlentry.h
Normal file
@@ -0,0 +1,429 @@
|
||||
/**
|
||||
* @file llurlentry.h
|
||||
* @author Martin Reddy
|
||||
* @brief Describes the Url types that can be registered in LLUrlRegistry
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLURLENTRY_H
|
||||
#define LL_LLURLENTRY_H
|
||||
|
||||
#include "lluuid.h"
|
||||
#include "lluicolor.h"
|
||||
#include "llstyle.h"
|
||||
|
||||
#include "llhost.h" // for resolving parcel name by parcel id
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
class LLAvatarName;
|
||||
|
||||
typedef boost::signals2::signal<void (const std::string& url,
|
||||
const std::string& label,
|
||||
const std::string& icon)> LLUrlLabelSignal;
|
||||
typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
|
||||
|
||||
///
|
||||
/// LLUrlEntryBase is the base class of all Url types registered in the
|
||||
/// LLUrlRegistry. Each derived classes provides a regular expression
|
||||
/// to match the Url type (e.g., http://... or secondlife://...) along
|
||||
/// with an optional icon to display next to instances of the Url in
|
||||
/// a text display and a XUI file to use for any context menu popup.
|
||||
/// Functions are also provided to compute an appropriate label and
|
||||
/// tooltip/status bar text for the Url.
|
||||
///
|
||||
/// Some derived classes of LLUrlEntryBase may wish to compute an
|
||||
/// appropriate label for a Url by asking the server for information.
|
||||
/// You must therefore provide a callback method, so that you can be
|
||||
/// notified when an updated label has been received from the server.
|
||||
/// This label should then be used to replace any previous label
|
||||
/// that you received from getLabel() for the Url in question.
|
||||
///
|
||||
class LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryBase();
|
||||
virtual ~LLUrlEntryBase();
|
||||
|
||||
/// Return the regex pattern that matches this Url
|
||||
boost::regex getPattern() const { return mPattern; }
|
||||
|
||||
/// Return the url from a string that matched the regex
|
||||
virtual std::string getUrl(const std::string &string) const;
|
||||
|
||||
/// Given a matched Url, return a label for the Url
|
||||
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
|
||||
|
||||
/// Return an icon that can be displayed next to Urls of this type
|
||||
virtual std::string getIcon(const std::string &url);
|
||||
|
||||
/// Return the style to render the displayed text
|
||||
//virtual LLStyle::Params getStyle() const;
|
||||
|
||||
/// Given a matched Url, return a tooltip string for the hyperlink
|
||||
virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
|
||||
|
||||
/// Return the name of a XUI file containing the context menu items
|
||||
std::string getMenuName() const { return mMenuName; }
|
||||
|
||||
/// Return the name of a SL location described by this Url, if any
|
||||
virtual std::string getLocation(const std::string &url) const { return ""; }
|
||||
|
||||
/// Should this link text be underlined only when mouse is hovered over it?
|
||||
virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
|
||||
|
||||
virtual LLUUID getID(const std::string &string) const { return LLUUID::null; }
|
||||
|
||||
bool isLinkDisabled() const;
|
||||
|
||||
protected:
|
||||
std::string getIDStringFromUrl(const std::string &url) const;
|
||||
std::string escapeUrl(const std::string &url) const;
|
||||
std::string unescapeUrl(const std::string &url) const;
|
||||
std::string getLabelFromWikiLink(const std::string &url) const;
|
||||
std::string getUrlFromWikiLink(const std::string &string) const;
|
||||
void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
|
||||
virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon);
|
||||
|
||||
typedef struct {
|
||||
std::string url;
|
||||
LLUrlLabelSignal *signal;
|
||||
} LLUrlEntryObserver;
|
||||
|
||||
boost::regex mPattern;
|
||||
std::string mIcon;
|
||||
std::string mMenuName;
|
||||
std::string mTooltip;
|
||||
std::multimap<std::string, LLUrlEntryObserver> mObservers;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryHTTP Describes generic http: and https: Urls
|
||||
///
|
||||
class LLUrlEntryHTTP : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryHTTP();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryHTTPLabel Describes generic http: and https: Urls with custom labels
|
||||
///
|
||||
class LLUrlEntryHTTPLabel : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryHTTPLabel();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getTooltip(const std::string &string) const;
|
||||
/*virtual*/ std::string getUrl(const std::string &string) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
|
||||
///
|
||||
class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryHTTPNoProtocol();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getUrl(const std::string &string) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntrySLURL Describes http://slurl.com/... Urls
|
||||
///
|
||||
class LLUrlEntrySLURL : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySLURL();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
|
||||
class LLUrlEntryAgent : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgent();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getIcon(const std::string &url);
|
||||
/*virtual*/ std::string getTooltip(const std::string &string) const;
|
||||
//*virtual*/ LLStyle::Params getStyle() const;
|
||||
/*virtual*/ LLUUID getID(const std::string &string) const;
|
||||
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
|
||||
protected:
|
||||
/*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
|
||||
private:
|
||||
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
|
||||
/// that displays various forms of user name
|
||||
/// This is a base class for the various implementations of name display
|
||||
class LLUrlEntryAgentName : public LLUrlEntryBase, public boost::signals2::trackable
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentName();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
//*virtual*/ LLStyle::Params getStyle() const;
|
||||
protected:
|
||||
// override this to pull out relevant name fields
|
||||
virtual std::string getName(const LLAvatarName& avatar_name) = 0;
|
||||
private:
|
||||
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// LLUrlEntryAgentCompleteName Describes a Second Life agent name Url, e.g.,
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
|
||||
/// that displays the full display name + user name for an avatar
|
||||
/// such as "James Linden (james.linden)"
|
||||
class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentCompleteName();
|
||||
private:
|
||||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryAgentDisplayName Describes a Second Life agent display name Url, e.g.,
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
|
||||
/// that displays the just the display name for an avatar
|
||||
/// such as "James Linden"
|
||||
class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentDisplayName();
|
||||
private:
|
||||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryAgentUserName Describes a Second Life agent username Url, e.g.,
|
||||
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
|
||||
/// that displays the just the display name for an avatar
|
||||
/// such as "james.linden"
|
||||
class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
|
||||
{
|
||||
public:
|
||||
LLUrlEntryAgentUserName();
|
||||
private:
|
||||
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
|
||||
/// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
|
||||
///
|
||||
class LLUrlEntryGroup : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryGroup();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
//*virtual*/ LLStyle::Params getStyle() const;
|
||||
/*virtual*/ LLUUID getID(const std::string &string) const;
|
||||
private:
|
||||
void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
|
||||
/// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
|
||||
///
|
||||
class LLUrlEntryInventory : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryInventory();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
private:
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryObjectIM Describes a Second Life inspector for the object Url, e.g.,
|
||||
/// secondlife:///app/objectim/7bcd7864-da6b-e43f-4486-91d28a28d95b?name=Object&owner=3de548e1-57be-cfea-2b78-83ae3ad95998&slurl=Danger!%20Danger!/200/200/30/&groupowned=1
|
||||
///
|
||||
class LLUrlEntryObjectIM : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryObjectIM();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
private:
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryParcel Describes a Second Life parcel Url, e.g.,
|
||||
/// secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about
|
||||
///
|
||||
class LLUrlEntryParcel : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
struct LLParcelData
|
||||
{
|
||||
LLUUID parcel_id;
|
||||
std::string name;
|
||||
std::string sim_name;
|
||||
F32 global_x;
|
||||
F32 global_y;
|
||||
F32 global_z;
|
||||
};
|
||||
|
||||
LLUrlEntryParcel();
|
||||
~LLUrlEntryParcel();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
|
||||
// Sends a parcel info request to sim.
|
||||
void sendParcelInfoRequest(const LLUUID& parcel_id);
|
||||
|
||||
// Calls observers of certain parcel id providing them with parcel label.
|
||||
void onParcelInfoReceived(const std::string &id, const std::string &label);
|
||||
|
||||
// Processes parcel label and triggers notifying observers.
|
||||
static void processParcelInfo(const LLParcelData& parcel_data);
|
||||
|
||||
// Next 4 setters are used to update agent and viewer connection information
|
||||
// upon events like user login, viewer disconnect and user changing region host.
|
||||
// These setters are made public to be accessible from newview and should not be
|
||||
// used in other cases.
|
||||
static void setAgentID(const LLUUID& id) { sAgentID = id; }
|
||||
static void setSessionID(const LLUUID& id) { sSessionID = id; }
|
||||
static void setRegionHost(const LLHost& host) { sRegionHost = host; }
|
||||
static void setDisconnected(bool disconnected) { sDisconnected = disconnected; }
|
||||
|
||||
private:
|
||||
static LLUUID sAgentID;
|
||||
static LLUUID sSessionID;
|
||||
static LLHost sRegionHost;
|
||||
static bool sDisconnected;
|
||||
static std::set<LLUrlEntryParcel*> sParcelInfoObservers;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryPlace Describes a Second Life location Url, e.g.,
|
||||
/// secondlife://Ahern/50/50/50
|
||||
///
|
||||
class LLUrlEntryPlace : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryPlace();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryRegion Describes a Second Life location Url, e.g.,
|
||||
/// secondlife:///app/region/Ahern/128/128/0
|
||||
///
|
||||
class LLUrlEntryRegion : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryRegion();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
|
||||
/// secondlife:///app/teleport/Ahern/50/50/50/
|
||||
///
|
||||
class LLUrlEntryTeleport : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryTeleport();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntrySL Describes a generic SLURL, e.g., a Url that starts
|
||||
/// with secondlife:// (used as a catch-all for cases not matched above)
|
||||
///
|
||||
class LLUrlEntrySL : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySL();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntrySLLabel Describes a generic SLURL, e.g., a Url that starts
|
||||
/// with secondlife:// with the ability to specify a custom label.
|
||||
///
|
||||
class LLUrlEntrySLLabel : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntrySLLabel();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getUrl(const std::string &string) const;
|
||||
/*virtual*/ std::string getTooltip(const std::string &string) const;
|
||||
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryWorldMap Describes a Second Life worldmap Url, e.g.,
|
||||
/// secondlife:///app/worldmap/Ahern/50/50/50
|
||||
///
|
||||
class LLUrlEntryWorldMap : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryWorldMap();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getLocation(const std::string &url) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags
|
||||
///
|
||||
class LLUrlEntryNoLink : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryNoLink();
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getUrl(const std::string &string) const;
|
||||
//*virtual*/ LLStyle::Params getStyle() const;
|
||||
};
|
||||
|
||||
///
|
||||
/// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
|
||||
///
|
||||
class LLUrlEntryIcon : public LLUrlEntryBase
|
||||
{
|
||||
public:
|
||||
LLUrlEntryIcon();
|
||||
/*virtual*/ std::string getUrl(const std::string &string) const;
|
||||
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
|
||||
/*virtual*/ std::string getIcon(const std::string &url);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
62
indra/llui/llurlmatch.cpp
Normal file
62
indra/llui/llurlmatch.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @file llurlmatch.cpp
|
||||
* @author Martin Reddy
|
||||
* @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llurlmatch.h"
|
||||
|
||||
LLUrlMatch::LLUrlMatch() :
|
||||
mStart(0),
|
||||
mEnd(0),
|
||||
mUrl(""),
|
||||
mLabel(""),
|
||||
mTooltip(""),
|
||||
mIcon(""),
|
||||
mMenuName(""),
|
||||
mLocation(""),
|
||||
mUnderlineOnHoverOnly(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
|
||||
const std::string &label, const std::string &tooltip,
|
||||
const std::string &icon, /*const LLStyle::Params& style,*/
|
||||
const std::string &menu, const std::string &location,
|
||||
const LLUUID& id, bool underline_on_hover_only)
|
||||
{
|
||||
mStart = start;
|
||||
mEnd = end;
|
||||
mUrl = url;
|
||||
mLabel = label;
|
||||
mTooltip = tooltip;
|
||||
mIcon = icon;
|
||||
//mStyle = style;
|
||||
//mStyle.link_href = url;
|
||||
mMenuName = menu;
|
||||
mLocation = location;
|
||||
mID = id;
|
||||
mUnderlineOnHoverOnly = underline_on_hover_only;
|
||||
}
|
||||
105
indra/llui/llurlmatch.h
Normal file
105
indra/llui/llurlmatch.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @file llurlmatch.h
|
||||
* @author Martin Reddy
|
||||
* @brief Specifies a matched Url in a string, as returned by LLUrlRegistry
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLURLMATCH_H
|
||||
#define LL_LLURLMATCH_H
|
||||
|
||||
//#include "linden_common.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "llstyle.h"
|
||||
|
||||
///
|
||||
/// LLUrlMatch describes a single Url that was matched within a string by
|
||||
/// the LLUrlRegistry::findUrl() method. It includes the actual Url that
|
||||
/// was matched along with its first/last character offset in the string.
|
||||
/// An alternate label is also provided for creating a hyperlink, as well
|
||||
/// as tooltip/status text, an icon, and a XUI file for a context menu
|
||||
/// that can be used in a popup for a Url (e.g., Open, Copy URL, etc.)
|
||||
///
|
||||
class LLUrlMatch
|
||||
{
|
||||
public:
|
||||
LLUrlMatch();
|
||||
|
||||
/// return true if this object does not contain a valid Url match yet
|
||||
bool empty() const { return mUrl.empty(); }
|
||||
|
||||
/// return the offset in the string for the first character of the Url
|
||||
U32 getStart() const { return mStart; }
|
||||
|
||||
/// return the offset in the string for the last character of the Url
|
||||
U32 getEnd() const { return mEnd; }
|
||||
|
||||
/// return the Url that has been matched in the input string
|
||||
std::string getUrl() const { return mUrl; }
|
||||
|
||||
/// return a label that can be used for the display of this Url
|
||||
std::string getLabel() const { return mLabel; }
|
||||
|
||||
/// return a message that could be displayed in a tooltip or status bar
|
||||
std::string getTooltip() const { return mTooltip; }
|
||||
|
||||
/// return the filename for an icon that can be displayed next to this Url
|
||||
std::string getIcon() const { return mIcon; }
|
||||
|
||||
/// Return the color to render the displayed text
|
||||
//LLStyle::Params getStyle() const { return mStyle; }
|
||||
|
||||
/// Return the name of a XUI file containing the context menu items
|
||||
std::string getMenuName() const { return mMenuName; }
|
||||
|
||||
/// return the SL location that this Url describes, or "" if none.
|
||||
std::string getLocation() const { return mLocation; }
|
||||
|
||||
/// Should this link text be underlined only when mouse is hovered over it?
|
||||
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
|
||||
|
||||
/// Change the contents of this match object (used by LLUrlRegistry)
|
||||
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
|
||||
const std::string &tooltip, const std::string &icon,
|
||||
/*const LLStyle::Params& style, */const std::string &menu,
|
||||
const std::string &location, const LLUUID& id,
|
||||
bool underline_on_hover_only = false );
|
||||
|
||||
const LLUUID& getID() const { return mID; }
|
||||
private:
|
||||
U32 mStart;
|
||||
U32 mEnd;
|
||||
std::string mUrl;
|
||||
std::string mLabel;
|
||||
std::string mTooltip;
|
||||
std::string mIcon;
|
||||
std::string mMenuName;
|
||||
std::string mLocation;
|
||||
LLUUID mID;
|
||||
//LLStyle::Params mStyle;
|
||||
bool mUnderlineOnHoverOnly;
|
||||
};
|
||||
|
||||
#endif
|
||||
263
indra/llui/llurlregistry.cpp
Normal file
263
indra/llui/llurlregistry.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* @file llurlregistry.cpp
|
||||
* @author Martin Reddy
|
||||
* @brief Contains a set of Url types that can be matched in a string
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llurlregistry.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
// default dummy callback that ignores any label updates from the server
|
||||
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
|
||||
{
|
||||
}
|
||||
|
||||
LLUrlRegistry::LLUrlRegistry()
|
||||
{
|
||||
mUrlEntry.reserve(20);
|
||||
|
||||
// Urls are matched in the order that they were registered
|
||||
registerUrl(new LLUrlEntryNoLink());
|
||||
registerUrl(new LLUrlEntryIcon());
|
||||
registerUrl(new LLUrlEntrySLURL());
|
||||
registerUrl(new LLUrlEntryHTTP());
|
||||
registerUrl(new LLUrlEntryHTTPLabel());
|
||||
registerUrl(new LLUrlEntryAgentCompleteName());
|
||||
registerUrl(new LLUrlEntryAgentDisplayName());
|
||||
registerUrl(new LLUrlEntryAgentUserName());
|
||||
// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
|
||||
// LLUrlEntryAgent is a less specific (catchall for agent urls)
|
||||
registerUrl(new LLUrlEntryAgent());
|
||||
registerUrl(new LLUrlEntryGroup());
|
||||
registerUrl(new LLUrlEntryParcel());
|
||||
registerUrl(new LLUrlEntryTeleport());
|
||||
registerUrl(new LLUrlEntryRegion());
|
||||
registerUrl(new LLUrlEntryWorldMap());
|
||||
registerUrl(new LLUrlEntryObjectIM());
|
||||
registerUrl(new LLUrlEntryPlace());
|
||||
registerUrl(new LLUrlEntryInventory());
|
||||
registerUrl(new LLUrlEntryObjectIM());
|
||||
//LLUrlEntrySL and LLUrlEntrySLLabel have more common pattern,
|
||||
//so it should be registered in the end of list
|
||||
registerUrl(new LLUrlEntrySL());
|
||||
registerUrl(new LLUrlEntrySLLabel());
|
||||
// most common pattern is a URL without any protocol,
|
||||
// e.g., "secondlife.com"
|
||||
registerUrl(new LLUrlEntryHTTPNoProtocol());
|
||||
}
|
||||
|
||||
LLUrlRegistry::~LLUrlRegistry()
|
||||
{
|
||||
// free all of the LLUrlEntryBase objects we are holding
|
||||
std::vector<LLUrlEntryBase *>::iterator it;
|
||||
for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front)
|
||||
{
|
||||
if (url)
|
||||
{
|
||||
if (force_front) // IDEVO
|
||||
mUrlEntry.insert(mUrlEntry.begin(), url);
|
||||
else
|
||||
mUrlEntry.push_back(url);
|
||||
}
|
||||
}
|
||||
|
||||
static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &end)
|
||||
{
|
||||
boost::cmatch result;
|
||||
bool found;
|
||||
|
||||
// regex_search can potentially throw an exception, so check for it
|
||||
try
|
||||
{
|
||||
found = boost::regex_search(text, result, regex);
|
||||
}
|
||||
catch (std::runtime_error &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! found)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// return the first/last character offset for the matched substring
|
||||
start = static_cast<U32>(result[0].first - text);
|
||||
end = static_cast<U32>(result[0].second - text) - 1;
|
||||
|
||||
// we allow certain punctuation to terminate a Url but not match it,
|
||||
// e.g., "http://foo.com/." should just match "http://foo.com/"
|
||||
if (text[end] == '.' || text[end] == ',')
|
||||
{
|
||||
end--;
|
||||
}
|
||||
// ignore a terminating ')' when Url contains no matching '('
|
||||
// see DEV-19842 for details
|
||||
else if (text[end] == ')' && std::string(text+start, end-start).find('(') == std::string::npos)
|
||||
{
|
||||
end--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool stringHasUrl(const std::string &text)
|
||||
{
|
||||
// fast heuristic test for a URL in a string. This is used
|
||||
// to avoid lots of costly regex calls, BUT it needs to be
|
||||
// kept in sync with the LLUrlEntry regexes we support.
|
||||
return (text.find("://") != std::string::npos ||
|
||||
text.find("www.") != std::string::npos ||
|
||||
text.find(".com") != std::string::npos ||
|
||||
text.find(".net") != std::string::npos ||
|
||||
text.find(".edu") != std::string::npos ||
|
||||
text.find(".org") != std::string::npos ||
|
||||
text.find("<nolink>") != std::string::npos ||
|
||||
text.find("<icon") != std::string::npos);
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
|
||||
{
|
||||
// avoid costly regexes if there is clearly no URL in the text
|
||||
if (! stringHasUrl(text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the first matching regex from all url entries in the registry
|
||||
U32 match_start = 0, match_end = 0;
|
||||
LLUrlEntryBase *match_entry = NULL;
|
||||
|
||||
std::vector<LLUrlEntryBase *>::iterator it;
|
||||
for (it = mUrlEntry.begin(); it != mUrlEntry.end(); ++it)
|
||||
{
|
||||
LLUrlEntryBase *url_entry = *it;
|
||||
|
||||
U32 start = 0, end = 0;
|
||||
if (matchRegex(text.c_str(), url_entry->getPattern(), start, end))
|
||||
{
|
||||
// does this match occur in the string before any other match
|
||||
if (start < match_start || match_entry == NULL)
|
||||
{
|
||||
match_start = start;
|
||||
match_end = end;
|
||||
match_entry = url_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// did we find a match? if so, return its details in the match object
|
||||
if (match_entry)
|
||||
{
|
||||
// fill in the LLUrlMatch object and return it
|
||||
std::string url = text.substr(match_start, match_end - match_start + 1);
|
||||
match.setValues(match_start, match_end,
|
||||
match_entry->getUrl(url),
|
||||
match_entry->getLabel(url, cb),
|
||||
match_entry->getTooltip(url),
|
||||
match_entry->getIcon(url),
|
||||
//match_entry->getStyle(),
|
||||
match_entry->getMenuName(),
|
||||
match_entry->getLocation(url),
|
||||
match_entry->getID(url),
|
||||
match_entry->underlineOnHoverOnly(url));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
|
||||
{
|
||||
// boost::regex_search() only works on char or wchar_t
|
||||
// types, but wchar_t is only 2-bytes on Win32 (not 4).
|
||||
// So we use UTF-8 to make this work the same everywhere.
|
||||
std::string utf8_text = wstring_to_utf8str(text);
|
||||
if (findUrl(utf8_text, match, cb))
|
||||
{
|
||||
// we cannot blindly return the start/end offsets from
|
||||
// the UTF-8 string because it is a variable-length
|
||||
// character encoding, so we need to update the start
|
||||
// and end values to be correct for the wide string.
|
||||
LLWString wurl = utf8str_to_wstring(match.getUrl());
|
||||
S32 start = text.find(wurl);
|
||||
if (start == std::string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
S32 end = start + wurl.size() - 1;
|
||||
|
||||
match.setValues(start, end, match.getUrl(),
|
||||
match.getLabel(),
|
||||
match.getTooltip(),
|
||||
match.getIcon(),
|
||||
//match.getStyle(),
|
||||
match.getMenuName(),
|
||||
match.getLocation(),
|
||||
match.getID(),
|
||||
match.underlineOnHoverOnly());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::hasUrl(const std::string &text)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
return findUrl(text, match);
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::hasUrl(const LLWString &text)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
return findUrl(text, match);
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::isUrl(const std::string &text)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
if (findUrl(text, match))
|
||||
{
|
||||
return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLUrlRegistry::isUrl(const LLWString &text)
|
||||
{
|
||||
LLUrlMatch match;
|
||||
if (findUrl(text, match))
|
||||
{
|
||||
return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
97
indra/llui/llurlregistry.h
Normal file
97
indra/llui/llurlregistry.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file llurlregistry.h
|
||||
* @author Martin Reddy
|
||||
* @brief Contains a set of Url types that can be matched in a string
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLURLREGISTRY_H
|
||||
#define LL_LLURLREGISTRY_H
|
||||
|
||||
#include "llurlentry.h"
|
||||
#include "llurlmatch.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llstring.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/// This default callback for findUrl() simply ignores any label updates
|
||||
void LLUrlRegistryNullCallback(const std::string &url,
|
||||
const std::string &label,
|
||||
const std::string &icon);
|
||||
|
||||
///
|
||||
/// LLUrlRegistry is a singleton that contains a set of Url types that
|
||||
/// can be matched in string. E.g., http:// or secondlife:// Urls.
|
||||
///
|
||||
/// Clients call the findUrl() method on a string to locate the first
|
||||
/// occurence of a supported Urls in that string. If findUrl() returns
|
||||
/// true, the LLUrlMatch object will be updated to describe the Url
|
||||
/// that was matched, including a label that can be used to hyperlink
|
||||
/// the Url, an icon to display next to the Url, and a XUI menu that
|
||||
/// can be used as a popup context menu for that Url.
|
||||
///
|
||||
/// New Url types can be added to the registry with the registerUrl
|
||||
/// method. E.g., to add support for a new secondlife:///app/ Url.
|
||||
///
|
||||
/// Computing the label for a Url could involve a roundtrip request
|
||||
/// to the server (e.g., to find the actual agent or group name).
|
||||
/// As such, you can provide a callback method that will get invoked
|
||||
/// when a new label is available for one of your matched Urls.
|
||||
///
|
||||
class LLUrlRegistry : public LLSingleton<LLUrlRegistry>
|
||||
{
|
||||
public:
|
||||
~LLUrlRegistry();
|
||||
|
||||
/// add a new Url handler to the registry (will be freed on destruction)
|
||||
/// optionally force it to the front of the list, making it take
|
||||
/// priority over other regular expression matches for URLs
|
||||
void registerUrl(LLUrlEntryBase *url, bool force_front = false);
|
||||
|
||||
/// get the next Url in an input string, starting at a given character offset
|
||||
/// your callback is invoked if the matched Url's label changes in the future
|
||||
bool findUrl(const std::string &text, LLUrlMatch &match,
|
||||
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
|
||||
|
||||
/// a slightly less efficient version of findUrl for wide strings
|
||||
bool findUrl(const LLWString &text, LLUrlMatch &match,
|
||||
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
|
||||
|
||||
// return true if the given string contains a URL that findUrl would match
|
||||
bool hasUrl(const std::string &text);
|
||||
bool hasUrl(const LLWString &text);
|
||||
|
||||
// return true if the given string is a URL that findUrl would match
|
||||
bool isUrl(const std::string &text);
|
||||
bool isUrl(const LLWString &text);
|
||||
|
||||
private:
|
||||
LLUrlRegistry();
|
||||
friend class LLSingleton<LLUrlRegistry>;
|
||||
|
||||
std::vector<LLUrlEntryBase *> mUrlEntry;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -74,6 +74,7 @@ BOOL LLView::sForceReshape = FALSE;
|
||||
LLView* LLView::sEditingUIView = NULL;
|
||||
S32 LLView::sLastLeftXML = S32_MIN;
|
||||
S32 LLView::sLastBottomXML = S32_MIN;
|
||||
std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack;
|
||||
|
||||
LLView::DrilldownFunc LLView::sDrilldown =
|
||||
boost::bind(&LLView::pointInView, _1, _2, _3, HIT_TEST_USE_BOUNDING_RECT);
|
||||
@@ -677,6 +678,16 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask)
|
||||
}
|
||||
|
||||
|
||||
void LLView::onMouseEnter(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
//llinfos << "Mouse entered " << getName() << llendl;
|
||||
}
|
||||
|
||||
void LLView::onMouseLeave(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
//llinfos << "Mouse left " << getName() << llendl;
|
||||
}
|
||||
|
||||
std::string LLView::getShowNamesToolTip()
|
||||
{
|
||||
LLView* view = getParent();
|
||||
@@ -2481,6 +2492,56 @@ void LLView::parseFollowsFlags(const LLView::Params& params)
|
||||
}
|
||||
}
|
||||
|
||||
LLView::tree_iterator_t LLView::beginTreeDFS()
|
||||
{
|
||||
return tree_iterator_t(this,
|
||||
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
|
||||
boost::bind(boost::mem_fn(&LLView::endChild), _1));
|
||||
}
|
||||
|
||||
LLView::tree_iterator_t LLView::endTreeDFS()
|
||||
{
|
||||
// an empty iterator is an "end" iterator
|
||||
return tree_iterator_t();
|
||||
}
|
||||
|
||||
LLView::tree_post_iterator_t LLView::beginTreeDFSPost()
|
||||
{
|
||||
return tree_post_iterator_t(this,
|
||||
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
|
||||
boost::bind(boost::mem_fn(&LLView::endChild), _1));
|
||||
}
|
||||
|
||||
LLView::tree_post_iterator_t LLView::endTreeDFSPost()
|
||||
{
|
||||
// an empty iterator is an "end" iterator
|
||||
return tree_post_iterator_t();
|
||||
}
|
||||
|
||||
LLView::bfs_tree_iterator_t LLView::beginTreeBFS()
|
||||
{
|
||||
return bfs_tree_iterator_t(this,
|
||||
boost::bind(boost::mem_fn(&LLView::beginChild), _1),
|
||||
boost::bind(boost::mem_fn(&LLView::endChild), _1));
|
||||
}
|
||||
|
||||
LLView::bfs_tree_iterator_t LLView::endTreeBFS()
|
||||
{
|
||||
// an empty iterator is an "end" iterator
|
||||
return bfs_tree_iterator_t();
|
||||
}
|
||||
|
||||
|
||||
LLView::root_to_view_iterator_t LLView::beginRootToView()
|
||||
{
|
||||
return root_to_view_iterator_t(this, boost::bind(&LLView::getParent, _1));
|
||||
}
|
||||
|
||||
LLView::root_to_view_iterator_t LLView::endRootToView()
|
||||
{
|
||||
return root_to_view_iterator_t();
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect)
|
||||
{
|
||||
@@ -2944,6 +3005,32 @@ S32 LLView::notifyParent(const LLSD& info)
|
||||
return parent->notifyParent(info);
|
||||
return 0;
|
||||
}
|
||||
bool LLView::notifyChildren(const LLSD& info)
|
||||
{
|
||||
bool ret = false;
|
||||
BOOST_FOREACH(LLView* childp, mChildList)
|
||||
{
|
||||
ret = ret || childp->notifyChildren(info);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// convenient accessor for draw context
|
||||
const LLViewDrawContext& LLView::getDrawContext()
|
||||
{
|
||||
return LLViewDrawContext::getCurrentContext();
|
||||
}
|
||||
|
||||
const LLViewDrawContext& LLViewDrawContext::getCurrentContext()
|
||||
{
|
||||
static LLViewDrawContext default_context;
|
||||
|
||||
if (sDrawContextStack.empty())
|
||||
return default_context;
|
||||
|
||||
return *sDrawContextStack.back();
|
||||
}
|
||||
|
||||
LLView* LLView::createWidget(LLXMLNodePtr xml_node) const
|
||||
{
|
||||
// forward requests to ui ctrl factory
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "lluistring.h"
|
||||
#include "llcursortypes.h"
|
||||
#include "llinitparam.h"
|
||||
#include "lltreeiterators.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "ailist.h"
|
||||
@@ -130,6 +131,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
// maintains render state during traversal of UI tree
|
||||
class LLViewDrawContext
|
||||
{
|
||||
public:
|
||||
F32 mAlpha;
|
||||
|
||||
LLViewDrawContext(F32 alpha = 1.f)
|
||||
: mAlpha(alpha)
|
||||
{
|
||||
if (!sDrawContextStack.empty())
|
||||
{
|
||||
LLViewDrawContext* context_top = sDrawContextStack.back();
|
||||
// merge with top of stack
|
||||
mAlpha *= context_top->mAlpha;
|
||||
}
|
||||
sDrawContextStack.push_back(this);
|
||||
}
|
||||
|
||||
~LLViewDrawContext()
|
||||
{
|
||||
sDrawContextStack.pop_back();
|
||||
}
|
||||
|
||||
static const LLViewDrawContext& getCurrentContext();
|
||||
|
||||
private:
|
||||
static std::vector<LLViewDrawContext*> sDrawContextStack;
|
||||
};
|
||||
|
||||
class LLView
|
||||
: public LLMouseHandler, // handles mouse events
|
||||
public LLFocusableElement, // handles keyboard events
|
||||
@@ -378,7 +408,24 @@ public:
|
||||
BOOL hasAncestor(const LLView* parentp) const;
|
||||
BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const;
|
||||
BOOL childHasKeyboardFocus( const std::string& childname ) const;
|
||||
|
||||
// these iterators are used for collapsing various tree traversals into for loops
|
||||
typedef LLTreeDFSIter<LLView, child_list_const_iter_t> tree_iterator_t;
|
||||
tree_iterator_t beginTreeDFS();
|
||||
tree_iterator_t endTreeDFS();
|
||||
|
||||
typedef LLTreeDFSPostIter<LLView, child_list_const_iter_t> tree_post_iterator_t;
|
||||
tree_post_iterator_t beginTreeDFSPost();
|
||||
tree_post_iterator_t endTreeDFSPost();
|
||||
|
||||
typedef LLTreeBFSIter<LLView, child_list_const_iter_t> bfs_tree_iterator_t;
|
||||
bfs_tree_iterator_t beginTreeBFS();
|
||||
bfs_tree_iterator_t endTreeBFS();
|
||||
|
||||
|
||||
typedef LLTreeDownIter<LLView> root_to_view_iterator_t;
|
||||
root_to_view_iterator_t beginRootToView();
|
||||
root_to_view_iterator_t endRootToView();
|
||||
|
||||
//
|
||||
// UTILITIES
|
||||
@@ -489,6 +536,9 @@ public:
|
||||
|
||||
virtual LLView* childFromPoint(S32 x, S32 y, bool recur=false);
|
||||
|
||||
// view-specific handlers
|
||||
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
|
||||
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
|
||||
template <class T> T* findChild(const std::string& name)
|
||||
{
|
||||
return getChild<T>(name,true,false);
|
||||
@@ -607,6 +657,16 @@ public:
|
||||
|
||||
//send custom notification to LLView parent
|
||||
virtual S32 notifyParent(const LLSD& info);
|
||||
|
||||
//send custom notification to all view childrend
|
||||
// return true if _any_ children return true. otherwise false.
|
||||
virtual bool notifyChildren(const LLSD& info);
|
||||
|
||||
//send custom notification to current view
|
||||
virtual S32 notify(const LLSD& info) { return 0;};
|
||||
|
||||
static const LLViewDrawContext& getDrawContext();
|
||||
|
||||
protected:
|
||||
void drawDebugRect();
|
||||
void drawChild(LLView* childp, S32 x_offset = 0, S32 y_offset = 0, BOOL force_draw = FALSE);
|
||||
|
||||
@@ -104,6 +104,8 @@ void LLViewBorder::draw()
|
||||
|
||||
void LLViewBorder::drawOnePixelLines()
|
||||
{
|
||||
F32 alpha = getDrawContext().mAlpha;
|
||||
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
LLColor4 top_color = mHighlightLight;
|
||||
@@ -138,6 +140,9 @@ void LLViewBorder::drawOnePixelLines()
|
||||
S32 right = getRect().getWidth();
|
||||
S32 bottom = 0;
|
||||
|
||||
top_color %= alpha;
|
||||
bottom_color %= alpha;
|
||||
|
||||
gGL.color4fv( top_color.mV );
|
||||
gl_line_2d(left, bottom, left, top);
|
||||
gl_line_2d(left, top, right, top);
|
||||
|
||||
@@ -41,6 +41,17 @@
|
||||
#include "lluuid.h"
|
||||
|
||||
#include "lldiriterator.h"
|
||||
#include "stringize.h"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
using boost::assign::list_of;
|
||||
using boost::assign::map_list_of;
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "lldir_win32.h"
|
||||
@@ -86,12 +97,17 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask)
|
||||
std::string fullpath;
|
||||
S32 result;
|
||||
|
||||
// File masks starting with "/" will match nothing, so we consider them invalid.
|
||||
if (LLStringUtil::startsWith(mask, getDirDelimiter()))
|
||||
{
|
||||
llwarns << "Invalid file mask: " << mask << llendl;
|
||||
llassert(!"Invalid file mask");
|
||||
}
|
||||
|
||||
LLDirIterator iter(dirname, mask);
|
||||
while (iter.next(filename))
|
||||
{
|
||||
fullpath = dirname;
|
||||
fullpath += getDirDelimiter();
|
||||
fullpath += filename;
|
||||
fullpath = add(dirname, filename);
|
||||
|
||||
if(LLFile::isdir(fullpath))
|
||||
{
|
||||
@@ -259,12 +275,12 @@ std::string LLDir::buildSLOSCacheDir() const
|
||||
}
|
||||
else
|
||||
{
|
||||
res = getOSUserAppDir() + mDirDelimiter + "cache_sg1";
|
||||
res = add(getOSUserAppDir(), "cache_sg1");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = getOSCacheDir() + mDirDelimiter + "SingularityViewer";
|
||||
res = add(getOSCacheDir(), "SingularityViewer");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -312,6 +328,39 @@ const std::string &LLDir::getLLPluginDir() const
|
||||
return mLLPluginDir;
|
||||
}
|
||||
|
||||
static std::string ELLPathToString(ELLPath location)
|
||||
{
|
||||
typedef std::map<ELLPath, const char*> ELLPathMap;
|
||||
#define ENT(symbol) (symbol, #symbol)
|
||||
static const ELLPathMap sMap = map_list_of
|
||||
ENT(LL_PATH_NONE)
|
||||
ENT(LL_PATH_USER_SETTINGS)
|
||||
ENT(LL_PATH_APP_SETTINGS)
|
||||
ENT(LL_PATH_PER_SL_ACCOUNT) // returns/expands to blank string if we don't know the account name yet
|
||||
ENT(LL_PATH_CACHE)
|
||||
ENT(LL_PATH_CHARACTER)
|
||||
ENT(LL_PATH_HELP)
|
||||
ENT(LL_PATH_LOGS)
|
||||
ENT(LL_PATH_TEMP)
|
||||
ENT(LL_PATH_SKINS)
|
||||
ENT(LL_PATH_TOP_SKIN)
|
||||
ENT(LL_PATH_CHAT_LOGS)
|
||||
ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS)
|
||||
ENT(LL_PATH_USER_SKIN)
|
||||
ENT(LL_PATH_LOCAL_ASSETS)
|
||||
ENT(LL_PATH_EXECUTABLE)
|
||||
ENT(LL_PATH_DEFAULT_SKIN)
|
||||
ENT(LL_PATH_FONTS)
|
||||
ENT(LL_PATH_LAST)
|
||||
;
|
||||
#undef ENT
|
||||
|
||||
ELLPathMap::const_iterator found = sMap.find(location);
|
||||
if (found != sMap.end())
|
||||
return found->second;
|
||||
return STRINGIZE("Invalid ELLPath value " << location);
|
||||
}
|
||||
|
||||
std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const
|
||||
{
|
||||
return getExpandedFilename(location, "", filename);
|
||||
@@ -332,15 +381,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
|
||||
break;
|
||||
|
||||
case LL_PATH_APP_SETTINGS:
|
||||
prefix = getAppRODataDir();
|
||||
prefix += mDirDelimiter;
|
||||
prefix += "app_settings";
|
||||
prefix = add(getAppRODataDir(), "app_settings");
|
||||
break;
|
||||
|
||||
case LL_PATH_CHARACTER:
|
||||
prefix = getAppRODataDir();
|
||||
prefix += mDirDelimiter;
|
||||
prefix += "character";
|
||||
prefix = add(getAppRODataDir(), "character");
|
||||
break;
|
||||
|
||||
case LL_PATH_HELP:
|
||||
@@ -352,9 +397,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
|
||||
break;
|
||||
|
||||
case LL_PATH_USER_SETTINGS:
|
||||
prefix = getOSUserAppDir();
|
||||
prefix += mDirDelimiter;
|
||||
prefix += "user_settings";
|
||||
prefix = add(getOSUserAppDir(), "user_settings");
|
||||
break;
|
||||
|
||||
case LL_PATH_PER_SL_ACCOUNT:
|
||||
@@ -370,9 +413,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
|
||||
break;
|
||||
|
||||
case LL_PATH_LOGS:
|
||||
prefix = getOSUserAppDir();
|
||||
prefix += mDirDelimiter;
|
||||
prefix += "logs";
|
||||
prefix = add(getOSUserAppDir(), "logs");
|
||||
break;
|
||||
|
||||
case LL_PATH_TEMP:
|
||||
@@ -396,9 +437,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
|
||||
break;
|
||||
|
||||
case LL_PATH_LOCAL_ASSETS:
|
||||
prefix = getAppRODataDir();
|
||||
prefix += mDirDelimiter;
|
||||
prefix += "local_assets";
|
||||
prefix = add(getAppRODataDir(), "local_assets");
|
||||
break;
|
||||
|
||||
case LL_PATH_EXECUTABLE:
|
||||
@@ -406,56 +445,36 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
|
||||
break;
|
||||
|
||||
case LL_PATH_FONTS:
|
||||
prefix = getAppRODataDir();
|
||||
prefix += mDirDelimiter;
|
||||
prefix += "fonts";
|
||||
prefix = add(getAppRODataDir(), "fonts");
|
||||
break;
|
||||
|
||||
default:
|
||||
llassert(0);
|
||||
}
|
||||
|
||||
std::string filename = in_filename;
|
||||
if (!subdir2.empty())
|
||||
{
|
||||
filename = subdir2 + mDirDelimiter + filename;
|
||||
}
|
||||
|
||||
if (!subdir1.empty())
|
||||
{
|
||||
filename = subdir1 + mDirDelimiter + filename;
|
||||
}
|
||||
|
||||
if (prefix.empty())
|
||||
{
|
||||
llwarns << "prefix is empty, possible bad filename" << llendl;
|
||||
}
|
||||
|
||||
std::string expanded_filename;
|
||||
if (!filename.empty())
|
||||
{
|
||||
if (!prefix.empty())
|
||||
{
|
||||
expanded_filename += prefix;
|
||||
expanded_filename += mDirDelimiter;
|
||||
expanded_filename += filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
expanded_filename = filename;
|
||||
}
|
||||
}
|
||||
else if (!prefix.empty())
|
||||
{
|
||||
// Directory only, no file name.
|
||||
expanded_filename = prefix;
|
||||
}
|
||||
else
|
||||
{
|
||||
expanded_filename.assign("");
|
||||
llwarns << ELLPathToString(location)
|
||||
<< ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
|
||||
<< "': prefix is empty, possible bad filename" << llendl;
|
||||
}
|
||||
|
||||
//llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl;
|
||||
std::string expanded_filename = add(add(prefix, subdir1), subdir2);
|
||||
if (expanded_filename.empty() && in_filename.empty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
// Use explicit concatenation here instead of another add() call. Callers
|
||||
// passing in_filename as "" expect to obtain a pathname ending with
|
||||
// mDirSeparator so they can later directly concatenate with a specific
|
||||
// filename. A caller using add() doesn't care, but there's still code
|
||||
// loose in the system that uses std::string::operator+().
|
||||
expanded_filename += mDirDelimiter;
|
||||
expanded_filename += in_filename;
|
||||
|
||||
LL_DEBUGS("LLDir") << ELLPathToString(location)
|
||||
<< ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename
|
||||
<< "' => '" << expanded_filename << "'" << LL_ENDL;
|
||||
return expanded_filename;
|
||||
}
|
||||
|
||||
@@ -530,12 +549,7 @@ std::string LLDir::getTempFilename() const
|
||||
random_uuid.generate();
|
||||
random_uuid.toString(uuid_str);
|
||||
|
||||
std::string temp_filename = getTempDir();
|
||||
temp_filename += mDirDelimiter;
|
||||
temp_filename += uuid_str;
|
||||
temp_filename += ".tmp";
|
||||
|
||||
return temp_filename;
|
||||
return add(getTempDir(), uuid_str + ".tmp");
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -572,15 +586,9 @@ void LLDir::setLindenUserDir(const std::string &grid, const std::string &first,
|
||||
{
|
||||
// some platforms have case-sensitive filesystems, so be
|
||||
// utterly consistent with our firstname/lastname case.
|
||||
std::string firstlower(first);
|
||||
LLStringUtil::toLower(firstlower);
|
||||
std::string lastlower(last);
|
||||
LLStringUtil::toLower(lastlower);
|
||||
mLindenUserDir = getOSUserAppDir();
|
||||
mLindenUserDir += mDirDelimiter;
|
||||
mLindenUserDir += firstlower;
|
||||
mLindenUserDir += "_";
|
||||
mLindenUserDir += lastlower;
|
||||
std::string userlower(first+"_"+last);
|
||||
LLStringUtil::toLower(userlower);
|
||||
mLindenUserDir = add(getOSUserAppDir(), userlower);
|
||||
|
||||
if (!grid.empty())
|
||||
{
|
||||
@@ -617,16 +625,9 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
|
||||
{
|
||||
// some platforms have case-sensitive filesystems, so be
|
||||
// utterly consistent with our firstname/lastname case.
|
||||
std::string firstlower(first);
|
||||
LLStringUtil::toLower(firstlower);
|
||||
std::string lastlower(last);
|
||||
LLStringUtil::toLower(lastlower);
|
||||
mPerAccountChatLogsDir = getChatLogsDir();
|
||||
mPerAccountChatLogsDir += mDirDelimiter;
|
||||
mPerAccountChatLogsDir += firstlower;
|
||||
mPerAccountChatLogsDir += "_";
|
||||
mPerAccountChatLogsDir += lastlower;
|
||||
|
||||
std::string userlower(first+"_"+last);
|
||||
LLStringUtil::toLower(userlower);
|
||||
mPerAccountChatLogsDir = add(getChatLogsDir(), userlower);
|
||||
if (!grid.empty())
|
||||
{
|
||||
std::string gridlower(grid);
|
||||
@@ -644,22 +645,18 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string
|
||||
void LLDir::setSkinFolder(const std::string &skin_folder)
|
||||
{
|
||||
mSkinDir = getSkinBaseDir();
|
||||
mSkinDir += mDirDelimiter;
|
||||
mSkinDir += skin_folder;
|
||||
append(mSkinDir, skin_folder);
|
||||
|
||||
// user modifications to current skin
|
||||
// e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle
|
||||
mUserSkinDir = getOSUserAppDir();
|
||||
mUserSkinDir += mDirDelimiter;
|
||||
mUserSkinDir += "skins_sg1";
|
||||
mUserSkinDir += mDirDelimiter;
|
||||
mUserSkinDir += skin_folder;
|
||||
append(mUserSkinDir, "skins_sg1");
|
||||
append(mUserSkinDir, skin_folder);
|
||||
|
||||
// base skin which is used as fallback for all skinned files
|
||||
// e.g. c:\program files\secondlife\skins\default
|
||||
mDefaultSkinDir = getSkinBaseDir();
|
||||
mDefaultSkinDir += mDirDelimiter;
|
||||
mDefaultSkinDir += "default";
|
||||
append(mDefaultSkinDir, "default");
|
||||
}
|
||||
|
||||
bool LLDir::setCacheDir(const std::string &path)
|
||||
@@ -673,7 +670,7 @@ bool LLDir::setCacheDir(const std::string &path)
|
||||
else
|
||||
{
|
||||
LLFile::mkdir(path);
|
||||
std::string tempname = path + mDirDelimiter + "temp";
|
||||
std::string tempname = add(path, "temp");
|
||||
LLFILE* file = LLFile::fopen(tempname,"wt");
|
||||
if (file)
|
||||
{
|
||||
@@ -706,6 +703,57 @@ void LLDir::dumpCurrentDirectories()
|
||||
LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL;
|
||||
}
|
||||
|
||||
std::string LLDir::add(const std::string& path, const std::string& name) const
|
||||
{
|
||||
std::string destpath(path);
|
||||
append(destpath, name);
|
||||
return destpath;
|
||||
}
|
||||
|
||||
void LLDir::append(std::string& destpath, const std::string& name) const
|
||||
{
|
||||
// Delegate question of whether we need a separator to helper method.
|
||||
SepOff sepoff(needSep(destpath, name));
|
||||
if (sepoff.first) // do we need a separator?
|
||||
{
|
||||
destpath += mDirDelimiter;
|
||||
}
|
||||
// If destpath ends with a separator, AND name starts with one, skip
|
||||
// name's leading separator.
|
||||
destpath += name.substr(sepoff.second);
|
||||
}
|
||||
|
||||
LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const
|
||||
{
|
||||
if (path.empty() || name.empty())
|
||||
{
|
||||
// If either path or name are empty, we do not need a separator
|
||||
// between them.
|
||||
return SepOff(false, 0);
|
||||
}
|
||||
// Here we know path and name are both non-empty. But if path already ends
|
||||
// with a separator, or if name already starts with a separator, we need
|
||||
// not add one.
|
||||
std::string::size_type seplen(mDirDelimiter.length());
|
||||
bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter);
|
||||
bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter);
|
||||
if ((! path_ends_sep) && (! name_starts_sep))
|
||||
{
|
||||
// If neither path nor name brings a separator to the junction, then
|
||||
// we need one.
|
||||
return SepOff(true, 0);
|
||||
}
|
||||
if (path_ends_sep && name_starts_sep)
|
||||
{
|
||||
// But if BOTH path and name bring a separator, we need not add one.
|
||||
// Moreover, we should actually skip the leading separator of 'name'.
|
||||
return SepOff(false, seplen);
|
||||
}
|
||||
// Here we know that either path_ends_sep or name_starts_sep is true --
|
||||
// but not both. So don't add a separator, and don't skip any characters:
|
||||
// simple concatenation will do the trick.
|
||||
return SepOff(false, 0);
|
||||
}
|
||||
|
||||
void dir_exists_or_crash(const std::string &dir_name)
|
||||
{
|
||||
|
||||
@@ -140,7 +140,17 @@ class LLDir
|
||||
// Utility routine
|
||||
std::string buildSLOSCacheDir() const;
|
||||
|
||||
/// Append specified @a name to @a destpath, separated by getDirDelimiter()
|
||||
/// if both are non-empty.
|
||||
void append(std::string& destpath, const std::string& name) const;
|
||||
/// Append specified @a name to @a path, separated by getDirDelimiter()
|
||||
/// if both are non-empty. Return result, leaving @a path unmodified.
|
||||
std::string add(const std::string& path, const std::string& name) const;
|
||||
|
||||
protected:
|
||||
// Does an add() or append() call need a directory delimiter?
|
||||
typedef std::pair<bool, unsigned short> SepOff;
|
||||
SepOff needSep(const std::string& path, const std::string& name) const;
|
||||
std::string mAppName; // install directory under progams/ ie "SecondLife"
|
||||
std::string mExecutablePathAndName; // full path + Filename of .exe
|
||||
std::string mExecutableFilename; // Filename of .exe
|
||||
|
||||
@@ -124,10 +124,9 @@ class LLDragDropWin32Target:
|
||||
ScreenToClient( mAppWindowHandle, &pt2 );
|
||||
|
||||
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
|
||||
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
|
||||
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
|
||||
LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
|
||||
|
||||
switch (result)
|
||||
@@ -180,10 +179,9 @@ class LLDragDropWin32Target:
|
||||
ScreenToClient( mAppWindowHandle, &pt2 );
|
||||
|
||||
LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
|
||||
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
|
||||
LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,
|
||||
LLWindowCallbacks::DNDA_TRACK, mDropUrl );
|
||||
|
||||
switch (result)
|
||||
@@ -237,15 +235,13 @@ class LLDragDropWin32Target:
|
||||
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
|
||||
if ( NULL != window_imp )
|
||||
{
|
||||
LLCoordGL gl_coord( 0, 0 );
|
||||
|
||||
POINT pt_client;
|
||||
pt_client.x = pt.x;
|
||||
pt_client.y = pt.y;
|
||||
ScreenToClient( mAppWindowHandle, &pt_client );
|
||||
|
||||
LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
LLCoordGL gl_coord(cursor_coord_window.convert());
|
||||
llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
|
||||
llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl;
|
||||
llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl;
|
||||
|
||||
@@ -50,14 +50,15 @@ LLSplashScreen *gSplashScreenp = NULL;
|
||||
BOOL gDebugClicks = FALSE;
|
||||
BOOL gDebugWindowProc = FALSE;
|
||||
|
||||
const S32 gURLProtocolWhitelistCount = 3;
|
||||
const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" };
|
||||
const S32 gURLProtocolWhitelistCount = 4;
|
||||
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:"/*, "file:"*/ };
|
||||
|
||||
// CP: added a handler list - this is what's used to open the protocol and is based on registry entry
|
||||
// only meaningful difference currently is that file: protocols are opened using http:
|
||||
// since no protocol handler exists in registry for file:
|
||||
// Important - these lists should match - protocol to handler
|
||||
const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
|
||||
// Maestro: This list isn't referenced anywhere that I could find
|
||||
//const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" };
|
||||
|
||||
|
||||
S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
|
||||
@@ -112,6 +113,8 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
|
||||
mCursorHidden(FALSE),
|
||||
mBusyCount(0),
|
||||
mIsMouseClipping(FALSE),
|
||||
mMinWindowWidth(0),
|
||||
mMinWindowHeight(0),
|
||||
mSwapMethod(SWAP_METHOD_UNDEFINED),
|
||||
mHideCursorPermanent(FALSE),
|
||||
mFlags(flags),
|
||||
@@ -180,6 +183,51 @@ void *LLWindow::getMediaWindow()
|
||||
return getPlatformWindow();
|
||||
}
|
||||
|
||||
BOOL LLWindow::setSize(LLCoordScreen size)
|
||||
{
|
||||
if (!getMaximized())
|
||||
{
|
||||
size.mX = llmax(size.mX, mMinWindowWidth);
|
||||
size.mY = llmax(size.mY, mMinWindowHeight);
|
||||
}
|
||||
return setSizeImpl(size);
|
||||
}
|
||||
|
||||
BOOL LLWindow::setSize(LLCoordWindow size)
|
||||
{
|
||||
//HACK: we are inconsistently using minimum window dimensions
|
||||
// in this case, we are constraining the inner "client" rect and other times
|
||||
// we constrain the outer "window" rect
|
||||
// There doesn't seem to be a good way to do this consistently without a bunch of platform
|
||||
// specific code
|
||||
if (!getMaximized())
|
||||
{
|
||||
size.mX = llmax(size.mX, mMinWindowWidth);
|
||||
size.mY = llmax(size.mY, mMinWindowHeight);
|
||||
}
|
||||
return setSizeImpl(size);
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
void LLWindow::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
|
||||
{
|
||||
mMinWindowWidth = min_width;
|
||||
mMinWindowHeight = min_height;
|
||||
|
||||
if (enforce_immediately)
|
||||
{
|
||||
LLCoordScreen cur_size;
|
||||
if (!getMaximized() && getSize(&cur_size))
|
||||
{
|
||||
if (cur_size.mX < mMinWindowWidth || cur_size.mY < mMinWindowHeight)
|
||||
{
|
||||
setSizeImpl(LLCoordScreen(llmin(cur_size.mX, mMinWindowWidth), llmin(cur_size.mY, mMinWindowHeight)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLWindow::processMiscNativeEvents()
|
||||
{
|
||||
@@ -209,6 +257,8 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
|
||||
return LLWindowWin32::getDynamicFallbackFontList();
|
||||
#elif LL_DARWIN
|
||||
return LLWindowMacOSX::getDynamicFallbackFontList();
|
||||
#elif LL_MESA_HEADLESS
|
||||
return std::vector<std::string>();
|
||||
#elif LL_SDL
|
||||
return LLWindowSDL::getDynamicFallbackFontList();
|
||||
#else
|
||||
@@ -350,26 +400,26 @@ LLWindow* LLWindowManager::createWindow(
|
||||
#if LL_MESA_HEADLESS
|
||||
new_window = new LLWindowMesaHeadless(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
||||
fullscreen, clearBg, disable_vsync, ignore_pixel_depth);
|
||||
#elif LL_SDL
|
||||
new_window = new LLWindowSDL(callbacks,
|
||||
title, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
fullscreen, clearBg, disable_vsync, ignore_pixel_depth, fsaa_samples);
|
||||
#elif LL_WINDOWS
|
||||
new_window = new LLWindowWin32(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
fullscreen, clearBg, disable_vsync, ignore_pixel_depth, fsaa_samples);
|
||||
#elif LL_DARWIN
|
||||
new_window = new LLWindowMacOSX(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
fullscreen, clearBg, disable_vsync, ignore_pixel_depth, fsaa_samples);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
new_window = new LLWindowHeadless(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
||||
fullscreen, clearBg, disable_vsync, ignore_pixel_depth);
|
||||
}
|
||||
|
||||
if (FALSE == new_window->isValid())
|
||||
@@ -404,3 +454,42 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window)
|
||||
{
|
||||
return sWindowList.find(window) != sWindowList.end();
|
||||
}
|
||||
|
||||
//coordinate conversion utility funcs that forward to llwindow
|
||||
LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const
|
||||
{
|
||||
const LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this);
|
||||
|
||||
LLWindow* windowp = &(*LLWindow::beginInstances());
|
||||
LLCoordGL out;
|
||||
windowp->convertCoords(self, &out);
|
||||
return out.convert();
|
||||
}
|
||||
|
||||
void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from)
|
||||
{
|
||||
LLCoordWindow& self = LLCoordWindow::getTypedCoords(*this);
|
||||
|
||||
LLWindow* windowp = &(*LLWindow::beginInstances());
|
||||
LLCoordGL from_gl(from);
|
||||
windowp->convertCoords(from_gl, &self);
|
||||
}
|
||||
|
||||
LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const
|
||||
{
|
||||
const LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this);
|
||||
|
||||
LLWindow* windowp = &(*LLWindow::beginInstances());
|
||||
LLCoordGL out;
|
||||
windowp->convertCoords(self, &out);
|
||||
return out.convert();
|
||||
}
|
||||
|
||||
void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from)
|
||||
{
|
||||
LLCoordScreen& self = LLCoordScreen::getTypedCoords(*this);
|
||||
|
||||
LLWindow* windowp = &(*LLWindow::beginInstances());
|
||||
LLCoordGL from_gl(from);
|
||||
windowp->convertCoords(from_gl, &self);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ const S32 MIN_WINDOW_HEIGHT = 256;
|
||||
|
||||
// Refer to llwindow_test in test/common/llwindow for usage example
|
||||
|
||||
class LLWindow
|
||||
class LLWindow : public LLInstanceTracker<LLWindow>
|
||||
{
|
||||
public:
|
||||
struct LLWindowResolution
|
||||
@@ -79,7 +79,9 @@ public:
|
||||
virtual BOOL getSize(LLCoordScreen *size) = 0;
|
||||
virtual BOOL getSize(LLCoordWindow *size) = 0;
|
||||
virtual BOOL setPosition(LLCoordScreen position) = 0;
|
||||
virtual BOOL setSize(LLCoordScreen size) = 0;
|
||||
BOOL setSize(LLCoordScreen size);
|
||||
BOOL setSize(LLCoordWindow size);
|
||||
virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
|
||||
virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) = 0;
|
||||
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
|
||||
virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
|
||||
@@ -180,6 +182,9 @@ protected:
|
||||
// Defaults to true
|
||||
virtual BOOL canDelete();
|
||||
|
||||
virtual BOOL setSizeImpl(LLCoordScreen size) = 0;
|
||||
virtual BOOL setSizeImpl(LLCoordWindow size) = 0;
|
||||
|
||||
protected:
|
||||
LLWindowCallbacks* mCallbacks;
|
||||
|
||||
@@ -200,6 +205,8 @@ protected:
|
||||
BOOL mHideCursorPermanent;
|
||||
U32 mFlags;
|
||||
U16 mHighSurrogate;
|
||||
S32 mMinWindowWidth;
|
||||
S32 mMinWindowHeight;
|
||||
|
||||
// Handle a UTF-16 encoding unit received from keyboard.
|
||||
// Converting the series of UTF-16 encoding units to UTF-32 data,
|
||||
@@ -283,7 +290,7 @@ extern BOOL gDebugWindowProc;
|
||||
// Protocols, like "http" and "https" we support in URLs
|
||||
extern const S32 gURLProtocolWhitelistCount;
|
||||
extern const std::string gURLProtocolWhitelist[];
|
||||
extern const std::string gURLProtocolWhitelistHandler[];
|
||||
//extern const std::string gURLProtocolWhitelistHandler[];
|
||||
|
||||
void simpleEscapeString ( std::string& stringIn );
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
//
|
||||
LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
|
||||
U32 flags, BOOL fullscreen, BOOL clear_background,
|
||||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
|
||||
BOOL disable_vsync, BOOL ignore_pixel_depth)
|
||||
: LLWindow(callbacks, fullscreen, flags)
|
||||
{
|
||||
// Initialize a headless keyboard.
|
||||
|
||||
@@ -46,7 +46,8 @@ public:
|
||||
/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
|
||||
/*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;};
|
||||
/*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;};
|
||||
/*virtual*/ BOOL setSize(LLCoordScreen size) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
|
||||
@@ -95,7 +96,7 @@ public:
|
||||
S32 x, S32 y,
|
||||
S32 width, S32 height,
|
||||
U32 flags, BOOL fullscreen, BOOL clear_background,
|
||||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
|
||||
BOOL disable_vsync, BOOL ignore_pixel_depth);
|
||||
virtual ~LLWindowHeadless();
|
||||
|
||||
private:
|
||||
|
||||
@@ -3,31 +3,25 @@
|
||||
* @brief Prototypes for functions shared between llwindowmacosx.cpp
|
||||
* and llwindowmacosx-objc.mm.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,31 +3,25 @@
|
||||
* @brief Definition of functions shared between llwindowmacosx.cpp
|
||||
* and llwindowmacosx-objc.mm.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
|
||||
S32 height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL disable_vsync,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples)
|
||||
: LLWindow(NULL, fullscreen, flags)
|
||||
@@ -1256,7 +1256,7 @@ BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
|
||||
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size)
|
||||
{
|
||||
if(mWindow)
|
||||
{
|
||||
@@ -1266,6 +1266,31 @@ BOOL LLWindowMacOSX::setSize(const LLCoordScreen size)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size)
|
||||
{
|
||||
Rect client_rect;
|
||||
if (mWindow)
|
||||
{
|
||||
OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect);
|
||||
if (err == noErr)
|
||||
{
|
||||
client_rect.right = client_rect.left + size.mX;
|
||||
client_rect.bottom = client_rect.top + size.mY;
|
||||
err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect);
|
||||
}
|
||||
if (err == noErr)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "Error setting size" << err << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void LLWindowMacOSX::swapBuffers()
|
||||
{
|
||||
aglSwapBuffers(mContext);
|
||||
@@ -2546,6 +2571,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
{
|
||||
// This is where we would constrain move/resize to a particular screen
|
||||
|
||||
const S32 MIN_WIDTH = mMinWindowWidth;
|
||||
const S32 MIN_HEIGHT = mMinWindowHeight;
|
||||
|
||||
Rect currentBounds;
|
||||
Rect previousBounds;
|
||||
|
||||
@@ -2570,14 +2598,14 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
|
||||
mPreviousWindowRect = previousBounds;
|
||||
}
|
||||
|
||||
if ((currentBounds.right - currentBounds.left) < MIN_WINDOW_WIDTH)
|
||||
if ((currentBounds.right - currentBounds.left) < MIN_WIDTH)
|
||||
{
|
||||
currentBounds.right = currentBounds.left + MIN_WINDOW_WIDTH;
|
||||
currentBounds.right = currentBounds.left + MIN_WIDTH;
|
||||
}
|
||||
|
||||
if ((currentBounds.bottom - currentBounds.top) < MIN_WINDOW_HEIGHT)
|
||||
if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT)
|
||||
{
|
||||
currentBounds.bottom = currentBounds.top + MIN_WINDOW_HEIGHT;
|
||||
currentBounds.bottom = currentBounds.top + MIN_HEIGHT;
|
||||
}
|
||||
|
||||
SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds);
|
||||
|
||||
@@ -58,7 +58,8 @@ public:
|
||||
/*virtual*/ BOOL getSize(LLCoordScreen *size);
|
||||
/*virtual*/ BOOL getSize(LLCoordWindow *size);
|
||||
/*virtual*/ BOOL setPosition(LLCoordScreen position);
|
||||
/*virtual*/ BOOL setSize(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
|
||||
@@ -123,7 +124,7 @@ public:
|
||||
protected:
|
||||
LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples);
|
||||
~LLWindowMacOSX();
|
||||
|
||||
@@ -41,28 +41,25 @@ U16 *gMesaBuffer = NULL;
|
||||
LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
|
||||
U32 flags, BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
|
||||
BOOL disable_vsync, BOOL ignore_pixel_depth)
|
||||
: LLWindow(callbacks, fullscreen, flags)
|
||||
{
|
||||
if (use_gl)
|
||||
llinfos << "MESA Init" << llendl;
|
||||
mMesaContext = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL );
|
||||
|
||||
/* Allocate the image buffer */
|
||||
mMesaBuffer = new unsigned char [width * height * 4 * MESA_CHANNEL_SIZE];
|
||||
llassert(mMesaBuffer);
|
||||
|
||||
gMesaBuffer = (U16*)mMesaBuffer;
|
||||
|
||||
/* Bind the buffer to the context and make it current */
|
||||
if (!OSMesaMakeCurrent( mMesaContext, mMesaBuffer, MESA_CHANNEL_TYPE, width, height ))
|
||||
{
|
||||
llinfos << "MESA Init" << llendl;
|
||||
mMesaContext = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL );
|
||||
|
||||
/* Allocate the image buffer */
|
||||
mMesaBuffer = new unsigned char [width * height * 4 * MESA_CHANNEL_SIZE];
|
||||
llassert(mMesaBuffer);
|
||||
|
||||
gMesaBuffer = (U16*)mMesaBuffer;
|
||||
|
||||
/* Bind the buffer to the context and make it current */
|
||||
if (!OSMesaMakeCurrent( mMesaContext, mMesaBuffer, MESA_CHANNEL_TYPE, width, height ))
|
||||
{
|
||||
llerrs << "MESA: OSMesaMakeCurrent failed!" << llendl;
|
||||
}
|
||||
|
||||
llverify(gGLManager.initGL());
|
||||
llerrs << "MESA: OSMesaMakeCurrent failed!" << llendl;
|
||||
}
|
||||
|
||||
llverify(gGLManager.initGL());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,8 @@ public:
|
||||
/*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;};
|
||||
/*virtual*/ BOOL getSize(LLCoordWindow *size) {return FALSE;};
|
||||
/*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;};
|
||||
/*virtual*/ BOOL setSize(LLCoordScreen size) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
|
||||
@@ -97,7 +98,7 @@ public:
|
||||
LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
|
||||
U32 flags, BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
|
||||
BOOL disable_vsync, BOOL ignore_pixel_depth);
|
||||
~LLWindowMesaHeadless();
|
||||
|
||||
private:
|
||||
|
||||
@@ -189,7 +189,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, S32 x, S32 y, S32 width,
|
||||
S32 height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL disable_vsync,
|
||||
BOOL ignore_pixel_depth, U32 fsaa_samples)
|
||||
: LLWindow(callbacks, fullscreen, flags),
|
||||
Lock_Display(NULL),
|
||||
@@ -200,7 +200,6 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
|
||||
gKeyboard->setCallbacks(callbacks);
|
||||
// Note that we can't set up key-repeat until after SDL has init'd video
|
||||
|
||||
// Ignore use_gl for now, only used for drones on PC
|
||||
mWindow = NULL;
|
||||
mNeedsResize = FALSE;
|
||||
mOverrideAspectRatio = 0.f;
|
||||
@@ -975,7 +974,7 @@ BOOL LLWindowSDL::setPosition(const LLCoordScreen position)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::setSize(const LLCoordScreen size)
|
||||
BOOL LLWindowSDL::setSizeImpl(const LLCoordScreen size)
|
||||
{
|
||||
if(mWindow)
|
||||
{
|
||||
@@ -993,6 +992,25 @@ BOOL LLWindowSDL::setSize(const LLCoordScreen size)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::setSizeImpl(const LLCoordWindow size)
|
||||
{
|
||||
if(mWindow)
|
||||
{
|
||||
// Push a resize event onto SDL's queue - we'll handle it
|
||||
// when it comes out again.
|
||||
SDL_Event event;
|
||||
event.type = SDL_VIDEORESIZE;
|
||||
event.resize.w = size.mX;
|
||||
event.resize.h = size.mY;
|
||||
SDL_PushEvent(&event); // copied into queue
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void LLWindowSDL::swapBuffers()
|
||||
{
|
||||
if (mWindow)
|
||||
@@ -1045,6 +1063,25 @@ void LLWindowSDL::setMouseClipping( BOOL b )
|
||||
//SDL_WM_GrabInput(b ? SDL_GRAB_ON : SDL_GRAB_OFF);
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLWindowSDL::setMinSize(U32 min_width, U32 min_height, bool enforce_immediately)
|
||||
{
|
||||
LLWindow::setMinSize(min_width, min_height, enforce_immediately);
|
||||
|
||||
#if LL_X11
|
||||
// Set the minimum size limits for X11 window
|
||||
// so the window manager doesn't allow resizing below those limits.
|
||||
XSizeHints* hints = XAllocSizeHints();
|
||||
hints->flags |= PMinSize;
|
||||
hints->min_width = mMinWindowWidth;
|
||||
hints->min_height = mMinWindowHeight;
|
||||
|
||||
XSetWMNormalHints(mSDL_Display, mSDL_XWindowID, hints);
|
||||
|
||||
XFree(hints);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL LLWindowSDL::setCursorPosition(const LLCoordWindow position)
|
||||
{
|
||||
BOOL result = TRUE;
|
||||
@@ -1859,8 +1896,8 @@ void LLWindowSDL::gatherInput()
|
||||
llinfos << "Handling a resize event: " << event.resize.w <<
|
||||
"x" << event.resize.h << llendl;
|
||||
|
||||
S32 width = llmax(event.resize.w, MIN_WINDOW_WIDTH);
|
||||
S32 height = llmax(event.resize.h, MIN_WINDOW_HEIGHT);
|
||||
S32 width = llmax(event.resize.w, (S32)mMinWindowWidth);
|
||||
S32 height = llmax(event.resize.h, (S32)mMinWindowHeight);
|
||||
|
||||
if (width != mWindow->w || height != mWindow->h)
|
||||
{
|
||||
@@ -2488,6 +2525,23 @@ void exec_cmd(const std::string& cmd, const std::string& arg)
|
||||
// Must begin with protocol identifier.
|
||||
void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
|
||||
{
|
||||
bool found = false;
|
||||
S32 i;
|
||||
for (i = 0; i < gURLProtocolWhitelistCount; i++)
|
||||
{
|
||||
if (escaped_url.find(gURLProtocolWhitelist[i]) != std::string::npos)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
llwarns << "spawn_web_browser called for url with protocol not on whitelist: " << escaped_url << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
llinfos << "spawn_web_browser: " << escaped_url << llendl;
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
@@ -2623,9 +2677,9 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()
|
||||
if (sortpat)
|
||||
{
|
||||
// Sort the list of system fonts from most-to-least-desirable.
|
||||
FcResult fresult;
|
||||
FcResult result;
|
||||
fs = FcFontSort(NULL, sortpat, elide_unicode_coverage,
|
||||
NULL, &fresult);
|
||||
NULL, &result);
|
||||
FcPatternDestroy(sortpat);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,8 @@ public:
|
||||
/*virtual*/ BOOL getSize(LLCoordScreen *size);
|
||||
/*virtual*/ BOOL getSize(LLCoordWindow *size);
|
||||
/*virtual*/ BOOL setPosition(LLCoordScreen position);
|
||||
/*virtual*/ BOOL setSize(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
/*virtual*/ void captureMouse();
|
||||
/*virtual*/ void releaseMouse();
|
||||
/*virtual*/ void setMouseClipping( BOOL b );
|
||||
/*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
|
||||
|
||||
/*virtual*/ BOOL isClipboardTextAvailable();
|
||||
/*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst);
|
||||
@@ -147,7 +149,7 @@ public:
|
||||
protected:
|
||||
LLWindowSDL(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, int x, int y, int width, int height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync,
|
||||
BOOL ignore_pixel_depth, U32 fsaa_samples);
|
||||
~LLWindowSDL();
|
||||
|
||||
|
||||
@@ -363,11 +363,15 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
|
||||
S32 height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL disable_vsync,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples)
|
||||
: LLWindow(callbacks, fullscreen, flags)
|
||||
{
|
||||
|
||||
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
|
||||
LoadLibrary(L"opengl32.dll");
|
||||
|
||||
mFSAASamples = fsaa_samples;
|
||||
mIconResource = gIconResource;
|
||||
mOverrideAspectRatio = 0.f;
|
||||
@@ -860,13 +864,11 @@ BOOL LLWindowWin32::setPosition(const LLCoordScreen position)
|
||||
return FALSE;
|
||||
}
|
||||
getSize(&size);
|
||||
|
||||
moveWindow(position, size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLWindowWin32::setSize(const LLCoordScreen size)
|
||||
BOOL LLWindowWin32::setSizeImpl(const LLCoordScreen size)
|
||||
{
|
||||
LLCoordScreen position;
|
||||
|
||||
@@ -876,11 +878,30 @@ BOOL LLWindowWin32::setSize(const LLCoordScreen size)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
moveWindow(position, size);
|
||||
WINDOWPLACEMENT placement;
|
||||
placement.length = sizeof(WINDOWPLACEMENT);
|
||||
|
||||
if (!GetWindowPlacement(mWindowHandle, &placement)) return FALSE;
|
||||
|
||||
placement.showCmd = SW_RESTORE;
|
||||
|
||||
if (!SetWindowPlacement(mWindowHandle, &placement)) return FALSE;
|
||||
|
||||
moveWindow(position, size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size)
|
||||
{
|
||||
RECT window_rect = {0, 0, size.mX, size.mY };
|
||||
DWORD dw_ex_style = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
DWORD dw_style = WS_OVERLAPPEDWINDOW;
|
||||
|
||||
AdjustWindowRectEx(&window_rect, dw_style, FALSE, dw_ex_style);
|
||||
|
||||
return setSizeImpl(LLCoordScreen(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top));
|
||||
}
|
||||
|
||||
// changing fullscreen resolution
|
||||
BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
|
||||
{
|
||||
@@ -891,12 +912,12 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
||||
DWORD current_refresh;
|
||||
DWORD dw_ex_style;
|
||||
DWORD dw_style;
|
||||
RECT window_rect;
|
||||
RECT window_rect = {0, 0, 0, 0};
|
||||
S32 width = size.mX;
|
||||
S32 height = size.mY;
|
||||
BOOL auto_show = FALSE;
|
||||
|
||||
if (mhRC)
|
||||
if (mhRC)
|
||||
{
|
||||
auto_show = TRUE;
|
||||
resetDisplayResolution();
|
||||
@@ -1093,6 +1114,37 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// (EXP-1765) dump pixel data to see if there is a pattern that leads to unreproducible crash
|
||||
LL_INFOS("Window") << "--- begin pixel format dump ---" << llendl ;
|
||||
LL_INFOS("Window") << "pixel_format is " << pixel_format << llendl ;
|
||||
LL_INFOS("Window") << "pfd.nSize: " << pfd.nSize << llendl ;
|
||||
LL_INFOS("Window") << "pfd.nVersion: " << pfd.nVersion << llendl ;
|
||||
LL_INFOS("Window") << "pfd.dwFlags: 0x" << std::hex << pfd.dwFlags << std::dec << llendl ;
|
||||
LL_INFOS("Window") << "pfd.iPixelType: " << (int)pfd.iPixelType << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cColorBits: " << (int)pfd.cColorBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cRedBits: " << (int)pfd.cRedBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cRedShift: " << (int)pfd.cRedShift << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cGreenBits: " << (int)pfd.cGreenBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cGreenShift: " << (int)pfd.cGreenShift << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cBlueBits: " << (int)pfd.cBlueBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cBlueShift: " << (int)pfd.cBlueShift << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAlphaBits: " << (int)pfd.cAlphaBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAlphaShift: " << (int)pfd.cAlphaShift << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAccumBits: " << (int)pfd.cAccumBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAccumRedBits: " << (int)pfd.cAccumRedBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAccumGreenBits: " << (int)pfd.cAccumGreenBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAccumBlueBits: " << (int)pfd.cAccumBlueBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAccumAlphaBits: " << (int)pfd.cAccumAlphaBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cDepthBits: " << (int)pfd.cDepthBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cStencilBits: " << (int)pfd.cStencilBits << llendl ;
|
||||
LL_INFOS("Window") << "pfd.cAuxBuffers: " << (int)pfd.cAuxBuffers << llendl ;
|
||||
LL_INFOS("Window") << "pfd.iLayerType: " << (int)pfd.iLayerType << llendl ;
|
||||
LL_INFOS("Window") << "pfd.bReserved: " << (int)pfd.bReserved << llendl ;
|
||||
LL_INFOS("Window") << "pfd.dwLayerMask: " << pfd.dwLayerMask << llendl ;
|
||||
LL_INFOS("Window") << "pfd.dwVisibleMask: " << pfd.dwVisibleMask << llendl ;
|
||||
LL_INFOS("Window") << "pfd.dwDamageMask: " << pfd.dwDamageMask << llendl ;
|
||||
LL_INFOS("Window") << "--- end pixel format dump ---" << llendl ;
|
||||
|
||||
if (pfd.cColorBits < 32)
|
||||
{
|
||||
close();
|
||||
@@ -1564,7 +1616,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) << " context." << llendl;
|
||||
llinfos << "Created OpenGL " << llformat("%d.%d", attribs[1], attribs[3]) <<
|
||||
(LLRender::sGLCoreProfile ? " core" : " compatibility") << " context." << llendl;
|
||||
done = true;
|
||||
|
||||
if (LLRender::sGLCoreProfile)
|
||||
@@ -1675,24 +1728,15 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre
|
||||
|
||||
BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
|
||||
{
|
||||
LLCoordScreen screen_pos;
|
||||
|
||||
mMousePositionModified = TRUE;
|
||||
if (!mWindowHandle)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!convertCoords(position, &screen_pos))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Inform the application of the new mouse position (needed for per-frame
|
||||
// hover/picking to function).
|
||||
LLCoordGL gl_pos;
|
||||
convertCoords(position, &gl_pos);
|
||||
mCallbacks->handleMouseMove(this, gl_pos, (MASK)0);
|
||||
mCallbacks->handleMouseMove(this, position.convert(), (MASK)0);
|
||||
|
||||
// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.
|
||||
// Because we have preemptively notified the application of the new
|
||||
@@ -1702,24 +1746,23 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)
|
||||
while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))
|
||||
{ }
|
||||
|
||||
return SetCursorPos(screen_pos.mX, screen_pos.mY);
|
||||
LLCoordScreen screen_pos(position.convert());
|
||||
return ::SetCursorPos(screen_pos.mX, screen_pos.mY);
|
||||
}
|
||||
|
||||
BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)
|
||||
{
|
||||
POINT cursor_point;
|
||||
LLCoordScreen screen_pos;
|
||||
|
||||
if (!mWindowHandle ||
|
||||
!GetCursorPos(&cursor_point))
|
||||
if (!mWindowHandle
|
||||
|| !GetCursorPos(&cursor_point)
|
||||
|| !position)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
screen_pos.mX = cursor_point.x;
|
||||
screen_pos.mY = cursor_point.y;
|
||||
|
||||
return convertCoords(screen_pos, position);
|
||||
*position = LLCoordScreen(cursor_point.x, cursor_point.y).convert();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLWindowWin32::hideCursor()
|
||||
@@ -1880,7 +1923,7 @@ void LLWindowWin32::gatherInput()
|
||||
MSG msg;
|
||||
int msg_count = 0;
|
||||
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && msg_count < MAX_MESSAGE_PER_UPDATE)
|
||||
while ((msg_count < MAX_MESSAGE_PER_UPDATE) && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
mCallbacks->handlePingWatchdog(this, "Main:TranslateGatherInput");
|
||||
TranslateMessage(&msg);
|
||||
@@ -1936,6 +1979,10 @@ static LLFastTimer::DeclareTimer FTM_MOUSEHANDLER("Handle Mouse");
|
||||
|
||||
LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
// Ignore clicks not originated in the client area, i.e. mouse-up events not preceded with a WM_LBUTTONDOWN.
|
||||
// This helps prevent avatar walking after maximizing the window by double-clicking the title bar.
|
||||
static bool sHandleLeftMouseUp = true;
|
||||
|
||||
LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA);
|
||||
|
||||
|
||||
@@ -2282,10 +2329,20 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
window_imp->handleUnicodeUTF16((U16)w_param, gKeyboard->currentMask(FALSE));
|
||||
return 0;
|
||||
|
||||
case WM_NCLBUTTONDOWN:
|
||||
{
|
||||
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN");
|
||||
// A click in a non-client area, e.g. title bar or window border.
|
||||
sHandleLeftMouseUp = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
{
|
||||
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDOWN");
|
||||
LLFastTimer t2(FTM_MOUSEHANDLER);
|
||||
sHandleLeftMouseUp = true;
|
||||
|
||||
if (LLWinImm::isAvailable() && window_imp->mPreeditor)
|
||||
{
|
||||
window_imp->interruptLanguageTextInput();
|
||||
@@ -2296,15 +2353,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2326,15 +2383,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2350,6 +2407,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
{
|
||||
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONUP");
|
||||
LLFastTimer t2(FTM_MOUSEHANDLER);
|
||||
|
||||
if (!sHandleLeftMouseUp)
|
||||
{
|
||||
sHandleLeftMouseUp = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//if (gDebugClicks)
|
||||
//{
|
||||
// LL_INFOS("Window") << "WndProc left button up" << LL_ENDL;
|
||||
@@ -2359,15 +2423,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2394,15 +2458,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2423,15 +2487,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2458,15 +2522,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2487,15 +2551,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
// If we don't do this, many clicks could get buffered up, and if the
|
||||
// first click changes the cursor position, all subsequent clicks
|
||||
// will occur at the wrong location. JC
|
||||
LLCoordWindow cursor_coord_window;
|
||||
if (window_imp->mMousePositionModified)
|
||||
{
|
||||
LLCoordWindow cursor_coord_window;
|
||||
window_imp->getCursorPosition(&cursor_coord_window);
|
||||
window_imp->convertCoords(cursor_coord_window, &gl_coord);
|
||||
gl_coord = cursor_coord_window.convert();
|
||||
}
|
||||
else
|
||||
{
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
gl_coord = window_coord.convert();
|
||||
}
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
// generate move event to update mouse coordinates
|
||||
@@ -2567,17 +2631,16 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE");
|
||||
window_imp->convertCoords(window_coord, &gl_coord);
|
||||
MASK mask = gKeyboard->currentMask(TRUE);
|
||||
window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask);
|
||||
window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
LPMINMAXINFO min_max = (LPMINMAXINFO)l_param;
|
||||
min_max->ptMinTrackSize.x = MIN_WINDOW_WIDTH;
|
||||
min_max->ptMinTrackSize.y = MIN_WINDOW_HEIGHT;
|
||||
min_max->ptMinTrackSize.x = window_imp->mMinWindowWidth;
|
||||
min_max->ptMinTrackSize.y = window_imp->mMinWindowHeight;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3483,7 +3546,7 @@ void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )
|
||||
|
||||
LLWinImm::setCompositionWindow( himc, &ime_form );
|
||||
|
||||
sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY );
|
||||
sWinIMEWindowPosition = win_pos;
|
||||
}
|
||||
|
||||
LLWinImm::releaseContext(mWindowHandle, himc);
|
||||
|
||||
@@ -57,7 +57,8 @@ public:
|
||||
/*virtual*/ BOOL getSize(LLCoordScreen *size);
|
||||
/*virtual*/ BOOL getSize(LLCoordWindow *size);
|
||||
/*virtual*/ BOOL setPosition(LLCoordScreen position);
|
||||
/*virtual*/ BOOL setSize(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
|
||||
@@ -120,7 +121,7 @@ public:
|
||||
protected:
|
||||
LLWindowWin32(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync,
|
||||
BOOL ignore_pixel_depth, U32 fsaa_samples);
|
||||
~LLWindowWin32();
|
||||
|
||||
|
||||
@@ -1133,9 +1133,7 @@ void *updatethreadproc(void*)
|
||||
|
||||
llinfos << "Clearing cache..." << llendl;
|
||||
|
||||
char mask[LL_MAX_PATH]; /* Flawfinder: ignore */
|
||||
snprintf(mask, LL_MAX_PATH, "%s*.*", gDirUtilp->getDirDelimiter().c_str());
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),"*.*");
|
||||
|
||||
llinfos << "Clear complete." << llendl;
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ set(viewer_SOURCE_FILES
|
||||
llfloaterlandholdings.cpp
|
||||
llfloaterlandmark.cpp
|
||||
llfloatermap.cpp
|
||||
llfloatermediabrowser.cpp
|
||||
llfloatermediasettings.cpp
|
||||
llfloatermemleak.cpp
|
||||
llfloatermessagelog.cpp
|
||||
llfloatermodelpreview.cpp
|
||||
@@ -259,7 +259,10 @@ set(viewer_SOURCE_FILES
|
||||
llfloatertos.cpp
|
||||
llfloaterurldisplay.cpp
|
||||
llfloaterurlentry.cpp
|
||||
llfloatervoiceeffect.cpp
|
||||
llfloaterwater.cpp
|
||||
llfloaterwebcontent.cpp
|
||||
llfloaterwhitelistentry.cpp
|
||||
llfloaterwindlight.cpp
|
||||
llfloaterworldmap.cpp
|
||||
llfolderview.cpp
|
||||
@@ -314,6 +317,7 @@ set(viewer_SOURCE_FILES
|
||||
llmarketplacefunctions.cpp
|
||||
llmarketplacenotifications.cpp
|
||||
llmediactrl.cpp
|
||||
llmediadataclient.cpp
|
||||
llmediaremotectrl.cpp
|
||||
llmenucommands.cpp
|
||||
llmenuoptionpathfindingrebakenavmesh.cpp
|
||||
@@ -364,7 +368,10 @@ set(viewer_SOURCE_FILES
|
||||
llpanellogin.cpp
|
||||
llpanelmaininventory.cpp
|
||||
llpanelmarketplaceoutboxinventory.cpp
|
||||
llpanelmediahud.cpp
|
||||
llpanelmediasettingsgeneral.cpp
|
||||
llpanelmediasettingspermissions.cpp
|
||||
llpanelmediasettingssecurity.cpp
|
||||
llpanelnearbymedia.cpp
|
||||
llpanelmorph.cpp
|
||||
llpanelmsgs.cpp
|
||||
llpanelnetwork.cpp
|
||||
@@ -373,9 +380,11 @@ set(viewer_SOURCE_FILES
|
||||
llpanelpermissions.cpp
|
||||
llpanelpick.cpp
|
||||
llpanelplace.cpp
|
||||
llpanelprimmediacontrols.cpp
|
||||
llpanelprofile.cpp
|
||||
llpanelskins.cpp
|
||||
llpanelvoicedevicesettings.cpp
|
||||
llpanelvoiceeffect.cpp
|
||||
llpanelvolume.cpp
|
||||
llpanelweb.cpp
|
||||
llparcelselection.cpp
|
||||
@@ -414,6 +423,7 @@ set(viewer_SOURCE_FILES
|
||||
llscrollingpanelparambase.cpp
|
||||
llselectmgr.cpp
|
||||
llsky.cpp
|
||||
llslurl.cpp
|
||||
llspatialpartition.cpp
|
||||
llspeakers.cpp
|
||||
llsprite.cpp
|
||||
@@ -456,7 +466,6 @@ set(viewer_SOURCE_FILES
|
||||
llurl.cpp
|
||||
llurldispatcher.cpp
|
||||
llurlhistory.cpp
|
||||
llurlsimstring.cpp
|
||||
llurlwhitelist.cpp
|
||||
lluserauth.cpp
|
||||
llvectorperfoptions.cpp
|
||||
@@ -482,9 +491,7 @@ set(viewer_SOURCE_FILES
|
||||
llviewerlayer.cpp
|
||||
llviewermedia.cpp
|
||||
llviewermedia_streamingaudio.cpp
|
||||
llviewermediaeventemitter.cpp
|
||||
llviewermediafocus.cpp
|
||||
llviewermediaobserver.cpp
|
||||
llviewermenu.cpp
|
||||
llviewermenufile.cpp
|
||||
llviewermessage.cpp
|
||||
@@ -519,6 +526,7 @@ set(viewer_SOURCE_FILES
|
||||
llvoclouds.cpp
|
||||
llvograss.cpp
|
||||
llvoground.cpp
|
||||
llvoicecallhandler.cpp
|
||||
llvoicechannel.cpp
|
||||
llvoiceclient.cpp
|
||||
llvoiceremotectrl.cpp
|
||||
@@ -722,7 +730,7 @@ set(viewer_HEADER_FILES
|
||||
llfloaterlandholdings.h
|
||||
llfloaterlandmark.h
|
||||
llfloatermap.h
|
||||
llfloatermediabrowser.h
|
||||
llfloatermediasettings.h
|
||||
llfloatermemleak.h
|
||||
llfloatermessagelog.h
|
||||
llfloatermodelpreview.h
|
||||
@@ -761,7 +769,10 @@ set(viewer_HEADER_FILES
|
||||
llfloatertos.h
|
||||
llfloaterurldisplay.h
|
||||
llfloaterurlentry.h
|
||||
llfloatervoiceeffect.h
|
||||
llfloaterwater.h
|
||||
llfloaterwebcontent.h
|
||||
llfloaterwhitelistentry.h
|
||||
llfloaterwindlight.h
|
||||
llfloaterworldmap.h
|
||||
llfolderview.h
|
||||
@@ -816,6 +827,7 @@ set(viewer_HEADER_FILES
|
||||
llmarketplacefunctions.h
|
||||
llmarketplacenotifications.h
|
||||
llmediactrl.h
|
||||
llmediadataclient.h
|
||||
llmediaremotectrl.h
|
||||
llmenucommands.h
|
||||
llmenuoptionpathfindingrebakenavmesh.h
|
||||
@@ -866,7 +878,10 @@ set(viewer_HEADER_FILES
|
||||
llpanellogin.h
|
||||
llpanelmaininventory.h
|
||||
llpanelmarketplaceoutboxinventory.h
|
||||
llpanelmediahud.h
|
||||
llpanelmediasettingsgeneral.h
|
||||
llpanelmediasettingspermissions.h
|
||||
llpanelmediasettingssecurity.h
|
||||
llpanelnearbymedia.h
|
||||
llpanelmorph.h
|
||||
llpanelmsgs.h
|
||||
llpanelnetwork.h
|
||||
@@ -875,9 +890,11 @@ set(viewer_HEADER_FILES
|
||||
llpanelpermissions.h
|
||||
llpanelpick.h
|
||||
llpanelplace.h
|
||||
llpanelprimmediacontrols.h
|
||||
llpanelprofile.h
|
||||
llpanelskins.h
|
||||
llpanelvoicedevicesettings.h
|
||||
llpanelvoiceeffect.h
|
||||
llpanelvolume.h
|
||||
llpanelweb.h
|
||||
llparcelselection.h
|
||||
@@ -918,6 +935,7 @@ set(viewer_HEADER_FILES
|
||||
llselectmgr.h
|
||||
llsimplestat.h
|
||||
llsky.h
|
||||
llslurl.h
|
||||
llspatialpartition.h
|
||||
llspeakers.h
|
||||
llsprite.h
|
||||
@@ -963,7 +981,6 @@ set(viewer_HEADER_FILES
|
||||
llurl.h
|
||||
llurldispatcher.h
|
||||
llurlhistory.h
|
||||
llurlsimstring.h
|
||||
llurlwhitelist.h
|
||||
lluserauth.h
|
||||
llvectorperfoptions.h
|
||||
@@ -988,9 +1005,7 @@ set(viewer_HEADER_FILES
|
||||
llviewerkeyboard.h
|
||||
llviewerlayer.h
|
||||
llviewermedia.h
|
||||
llviewermediaeventemitter.h
|
||||
llviewermediafocus.h
|
||||
llviewermediaobserver.h
|
||||
llviewermenu.h
|
||||
llviewermenufile.h
|
||||
llviewermessage.h
|
||||
|
||||
@@ -425,7 +425,19 @@
|
||||
</array>
|
||||
</map>
|
||||
|
||||
<!-- Begin: AO-->
|
||||
<key>ShowNearbyMediaFloater</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show nearby media floter</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<!-- Begin: AO-->
|
||||
|
||||
<key>ShowAOSitPopup</key>
|
||||
<map>
|
||||
@@ -1158,7 +1170,7 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Comment</key>
|
||||
<string>Show Windlight popup</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
@@ -2257,6 +2269,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.075</real>
|
||||
</map>
|
||||
<key>AudioStreamingMedia</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable streaming</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AudioStreamingMusic</key>
|
||||
<map>
|
||||
@@ -2269,17 +2292,6 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>AudioStreamingVideo</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable streaming video</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>AuditTexture</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -2724,23 +2736,23 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PluginAttachDebuggerToPlugins</key>
|
||||
<key>BrowserEnableJSObject</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Opens a terminal window with a debugger and attach it, every time a new SLPlugin process is started.</string>
|
||||
<string>(WARNING: Advanced feature. Use if you are aware of the implications). Enable or disable the viewer to Javascript bridge object.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>BlockAvatarAppearanceMessages</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Ignores appearance messages (for simulating Ruth)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Ignores appearance messages (for simulating Ruth)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
@@ -3802,17 +3814,6 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<string/>
|
||||
</array>
|
||||
</map>
|
||||
<key>CmdLineRegionURI</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>URL of region to connect to through Agent Domain.</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string/>
|
||||
</map>
|
||||
<key>ColorPaletteEntry01</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -5452,6 +5453,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DisableExternalBrowser</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Disable opening an external browser.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DisableRendering</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -5463,6 +5475,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DisableTextHyperlinkActions</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Disable highlighting and linking of URLs in XUI text boxes</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DisableVerticalSync</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -6036,17 +6059,6 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FirstLoginThisInstall</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Specifies that you have not successfully logged in since you installed the latest update</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FirstName</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -6091,6 +6103,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FirstLoginThisInstall</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Specifies that you have not successfully logged in since you installed the latest update</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FixedWeather</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -7438,6 +7461,22 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>-1</integer>
|
||||
</map>
|
||||
<key>FloaterVoiceEffectRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for voice morpher floater</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>300</integer>
|
||||
<integer>360</integer>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterWorldMapRect2</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -8812,6 +8851,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LastMediaSettingsTab</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Last selected tab in media settings window</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LastRunVersion</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -9131,16 +9181,16 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>LoginLastLocation</key>
|
||||
<key>LoginLocation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Login at same location you last logged out</string>
|
||||
<string>Default Login location ('last', 'home') preference</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
<string>last</string>
|
||||
</map>
|
||||
<key>LoginPage</key>
|
||||
<map>
|
||||
@@ -9457,13 +9507,68 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MemoryFailurePreventionEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>MediaPerformanceManagerDebug</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether to show debug data for the media performance manager in the nearby media list.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<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>0</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>MemoryFailurePreventionEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>If set, the viewer will quit to avoid crash when memory failure happens</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
@@ -10448,6 +10553,86 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>PluginAttachDebuggerToPlugins</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>If true, attach a debugger session to each plugin process as it's launched.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PluginInstancesCPULimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Amount of total plugin CPU usage before inworld plugins start getting turned down to "slideshow" priority. Set to 0 to disable this check.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.9</real>
|
||||
</map>
|
||||
|
||||
<key>PlainTextChatHistory</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable/Disable plain text chat history style</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>PluginInstancesLow</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Limit on the number of inworld media plugins that will run at "low" priority</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>4</integer>
|
||||
</map>
|
||||
<key>PluginInstancesNormal</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Limit on the number of inworld media plugins that will run at "normal" or higher priority</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
<key>PluginInstancesTotal</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Hard limit on the number of plugins that will be instantiated at once for inworld media</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>8</integer>
|
||||
</map>
|
||||
|
||||
<key>PluginUseReadThread</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use a separate thread to read incoming messages from plugins</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PlayTypingSound</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -10651,6 +10836,94 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
</array>
|
||||
</map>
|
||||
|
||||
<key>PrimMediaMasterEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether or not Media on a Prim is enabled.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>PrimMediaControlsUseHoverControlSet</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether or not hovering over prim media uses minimal "hover" controls or the authored control set.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>PrimMediaDragNDrop</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable drag and drop of URLs onto prim faces</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>PrimMediaMaxRetries</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum number of retries for media queries.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>4</integer>
|
||||
</map>
|
||||
<key>PrimMediaRequestQueueDelay</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Timer delay for fetching media from the queue (in seconds).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>PrimMediaRetryTimerDelay</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Timer delay for retrying on media queries (in seconds).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>5.0</real>
|
||||
</map>
|
||||
<key>PrimMediaMaxSortedQueueSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum number of objects the viewer will load media for initially</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>100000</integer>
|
||||
</map>
|
||||
<key>PrimMediaMaxRoundRobinQueueSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum number of objects the viewer will continuously update media for</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>100000</integer>
|
||||
</map>
|
||||
<key>PreviewAnimRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -10959,6 +11232,50 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>WebContentWindowLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum number of web browser windows that can be open at once in the Web content floater (0 for no limit)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>5</integer>
|
||||
</map>
|
||||
<key>MediaRollOffRate</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Multiplier to change rate of media attenuation</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.125</real>
|
||||
</map>
|
||||
<key>MediaRollOffMin</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Adjusts the distance at which media attentuation starts</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>5.0</real>
|
||||
</map>
|
||||
<key>MediaRollOffMax</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Distance at which media volume is set to 0</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>30.0</real>
|
||||
</map>
|
||||
<key>RecentItemsSortOrder</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -16475,6 +16792,17 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<real>0.40000000596</real>
|
||||
</map>
|
||||
<key>moapbeacon</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Beacon / Highlight media on a prim sources</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>particlesbeacon</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -16573,6 +16901,28 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>SLURLDragNDrop</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable drag and drop of SLURLs onto the viewer</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>SLURLPassToOtherInstance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Pass execution to prevoius viewer instances if there is a given slurl</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>soundsbeacon</key>
|
||||
<map>
|
||||
@@ -16585,17 +16935,6 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>keepbeacons</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Keep beacons when closing floater</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>ClearBeaconAfterTeleport</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -16651,6 +16990,19 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<key>Value</key>
|
||||
<integer>180</integer>
|
||||
</map>
|
||||
|
||||
<key>SLURLTeleportDirectly</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Clicking on a slurl will teleport you directly instead of opening places panel</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>UseHTTPInventory</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -16770,6 +17122,22 @@ This should be as low as possible, but too low may break functionality</string>
|
||||
<integer>473</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>FloaterNearbyMediaRect</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Rectangle for nearby media floater.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Rect</string>
|
||||
<key>Value</key>
|
||||
<array>
|
||||
<integer>0</integer>
|
||||
<integer>0</integer>
|
||||
<integer>0</integer>
|
||||
<integer>0</integer>
|
||||
</array>
|
||||
</map>
|
||||
<key>WindEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -41,6 +41,17 @@
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SHEnableFMODEXVerboseDebugging</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable profiler tool if using FMOD Ex</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SHFMODExStreamBufferSize</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
#include "lltooldraganddrop.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llselectmgr.h"
|
||||
#include "llslurl.h"
|
||||
#include "llurlaction.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
@@ -374,7 +376,6 @@ bool cmd_line_chat(std::string revised_text, EChatType type)
|
||||
S32 agent_y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
|
||||
S32 agent_z = llround( (F32)agentPos.mdV[VZ] );
|
||||
std::string region_name = LLWeb::escapeURL(revised_text.substr(command.length()+1));
|
||||
std::string url;
|
||||
|
||||
if(!sAscentCmdLineMapToKeepPos)
|
||||
{
|
||||
@@ -383,8 +384,8 @@ bool cmd_line_chat(std::string revised_text, EChatType type)
|
||||
agent_z = 0;
|
||||
}
|
||||
|
||||
url = llformat("secondlife:///app/teleport/%s/%d/%d/%d",region_name.c_str(),agent_x,agent_y,agent_z);
|
||||
LLURLDispatcher::dispatch(url, NULL, true);
|
||||
LLSLURL slurl(region_name,LLVector3(agent_x,agent_y,agent_z));
|
||||
LLUrlAction::teleportToLocation(std::string("secondlife:///app/teleport/")+slurl.getLocationString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ void HippoGridInfo::formatFee(std::string &fee, int cost, bool showFree) const
|
||||
}
|
||||
|
||||
//static
|
||||
std::string HippoGridInfo::sanitizeGridNick(std::string &gridnick)
|
||||
std::string HippoGridInfo::sanitizeGridNick(const std::string &gridnick)
|
||||
{
|
||||
std::string tmp;
|
||||
int size = gridnick.size();
|
||||
@@ -529,7 +529,7 @@ std::string HippoGridInfo::sanitizeGridNick(std::string &gridnick)
|
||||
}
|
||||
|
||||
|
||||
std::string HippoGridInfo::getGridNick()
|
||||
std::string HippoGridInfo::getGridNick() const
|
||||
{
|
||||
if(!mGridNick.empty())
|
||||
{
|
||||
@@ -684,42 +684,57 @@ void HippoGridManager::discardAndReload()
|
||||
|
||||
HippoGridInfo* HippoGridManager::getGrid(const std::string& grid) const
|
||||
{
|
||||
if(grid.empty())
|
||||
return NULL;
|
||||
|
||||
std::map<std::string, HippoGridInfo*>::const_iterator it;
|
||||
it = mGridInfo.find(grid);
|
||||
|
||||
//The grids are keyed by 'name' which equates to something like "Second Life"
|
||||
//Try to match such first.
|
||||
if (it != mGridInfo.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
else //Fall back to nick short names. (so something like "secondlife" will work)
|
||||
{
|
||||
return 0;
|
||||
for(it = mGridInfo.begin(); it != mGridInfo.end(); ++it)
|
||||
{
|
||||
if(it->second && LLStringUtil::compareInsensitive(it->second->getGridNick(), grid)==0)
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HippoGridInfo* HippoGridManager::getCurrentGrid() const
|
||||
{
|
||||
HippoGridInfo* grid = getGrid(mCurrentGrid);
|
||||
if (grid)
|
||||
if(!grid)
|
||||
{
|
||||
return grid;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &HippoGridInfo::FALLBACK_GRIDINFO;
|
||||
grid = getGrid(mDefaultGrid);
|
||||
}
|
||||
return grid ? grid : &HippoGridInfo::FALLBACK_GRIDINFO;
|
||||
}
|
||||
|
||||
const std::string& HippoGridManager::getDefaultGridNick() const
|
||||
std::string HippoGridManager::getDefaultGridNick() const
|
||||
{
|
||||
HippoGridInfo* grid = getGrid(mDefaultGrid);
|
||||
return grid ? grid->getGridNick() : HippoGridInfo::FALLBACK_GRIDINFO.getGridNick();
|
||||
}
|
||||
|
||||
std::string HippoGridManager::getCurrentGridNick() const
|
||||
{
|
||||
return getCurrentGrid()->getGridNick();
|
||||
}
|
||||
|
||||
const std::string& HippoGridManager::getDefaultGridName() const
|
||||
{
|
||||
return mDefaultGrid;
|
||||
}
|
||||
|
||||
const std::string& HippoGridManager::getCurrentGridNick() const
|
||||
const std::string& HippoGridManager::getCurrentGridName() const
|
||||
{
|
||||
if (mCurrentGrid.empty())
|
||||
{
|
||||
return mDefaultGrid;
|
||||
}
|
||||
return mCurrentGrid;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
const std::string& getVoiceConnector() const { return mVoiceConnector; }
|
||||
std::string getSearchUrl(SearchType ty, bool is_web) const;
|
||||
bool isRenderCompat() const { return mRenderCompat; }
|
||||
std::string getGridNick();
|
||||
std::string getGridNick() const;
|
||||
int getMaxAgentGroups() const { return mMaxAgentGroups; }
|
||||
|
||||
const std::string& getCurrencySymbol() const { return mCurrencySymbol; }
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
bool retrieveGridInfo();
|
||||
|
||||
static const char* getPlatformString(Platform platform);
|
||||
static std::string sanitizeGridNick(std::string &gridnick);
|
||||
static std::string sanitizeGridNick(const std::string &gridnick);
|
||||
|
||||
static HippoGridInfo FALLBACK_GRIDINFO;
|
||||
static void initFallback();
|
||||
@@ -163,8 +163,10 @@ public:
|
||||
HippoGridInfo* getConnectedGrid() const { return mConnectedGrid ? mConnectedGrid : getCurrentGrid(); }
|
||||
|
||||
HippoGridInfo* getCurrentGrid() const;
|
||||
const std::string& getDefaultGridNick() const;
|
||||
const std::string& getCurrentGridNick() const;
|
||||
std::string getDefaultGridNick() const;
|
||||
std::string getCurrentGridNick() const;
|
||||
const std::string& getDefaultGridName() const;
|
||||
const std::string& getCurrentGridName() const;
|
||||
|
||||
void setDefaultGrid(const std::string& grid);
|
||||
void setCurrentGrid(const std::string& grid);
|
||||
|
||||
@@ -164,7 +164,7 @@ BOOL HippoPanelGridsImpl::postBuild()
|
||||
// called internally too
|
||||
void HippoPanelGridsImpl::refresh()
|
||||
{
|
||||
const std::string &defaultGrid = gHippoGridManager->getDefaultGridNick();
|
||||
const std::string &defaultGrid = gHippoGridManager->getDefaultGridName();
|
||||
|
||||
LLComboBox *grids = getChild<LLComboBox>("grid_selector");
|
||||
S32 selectIndex = -1, i = 0;
|
||||
@@ -365,7 +365,7 @@ bool HippoPanelGridsImpl::saveCurGrid()
|
||||
void HippoPanelGridsImpl::reset()
|
||||
{
|
||||
mState = NORMAL;
|
||||
mCurGrid = gHippoGridManager->getCurrentGridNick();
|
||||
mCurGrid = gHippoGridManager->getCurrentGridName();
|
||||
loadCurGrid();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "llsdmessage.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llsky.h"
|
||||
#include "llslurl.h"
|
||||
#include "llsmoothstep.h"
|
||||
#include "llspeakers.h"
|
||||
#include "llstartup.h"
|
||||
@@ -65,6 +66,8 @@
|
||||
#include "lltoolpie.h"
|
||||
#include "lltoolmgr.h"
|
||||
#include "lltrans.h"
|
||||
#include "lluictrl.h"
|
||||
#include "llurlentry.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewerdisplay.h"
|
||||
#include "llviewerjoystick.h"
|
||||
@@ -345,6 +348,7 @@ LLAgent::LLAgent() :
|
||||
mAgentAccess(new LLAgentAccess(gSavedSettings)),
|
||||
mGodLevelChangeSignal(),
|
||||
mCanEditParcel(false),
|
||||
mTeleportSourceSLURL(new LLSLURL),
|
||||
mTeleportRequest(),
|
||||
mTeleportFinishedSlot(),
|
||||
mTeleportFailedSlot(),
|
||||
@@ -485,6 +489,8 @@ LLAgent::~LLAgent()
|
||||
mAgentAccess = NULL;
|
||||
delete mEffectColor;
|
||||
mEffectColor = NULL;
|
||||
delete mTeleportSourceSLURL;
|
||||
mTeleportSourceSLURL = NULL;
|
||||
}
|
||||
|
||||
// Handle any actions that need to be performed when the main app gains focus
|
||||
@@ -949,24 +955,6 @@ const LLHost& LLAgent::getRegionHost() const
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getSLURL()
|
||||
// returns empty() if getRegion() == NULL
|
||||
//-----------------------------------------------------------------------------
|
||||
std::string LLAgent::getSLURL() const
|
||||
{
|
||||
std::string slurl;
|
||||
LLViewerRegion *regionp = getRegion();
|
||||
if (regionp)
|
||||
{
|
||||
LLVector3d agentPos = getPositionGlobal();
|
||||
S32 x = llround( (F32)fmod( agentPos.mdV[VX], (F64)REGION_WIDTH_METERS ) );
|
||||
S32 y = llround( (F32)fmod( agentPos.mdV[VY], (F64)REGION_WIDTH_METERS ) );
|
||||
S32 z = llround( (F32)agentPos.mdV[VZ] );
|
||||
slurl = LLURLDispatcher::buildSLURL(regionp->getName(), x, y, z);
|
||||
}
|
||||
return slurl;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// inPrelude()
|
||||
@@ -3916,7 +3904,7 @@ bool LLAgent::teleportCore(bool is_local)
|
||||
LLFloaterLand::hideInstance();
|
||||
|
||||
LLViewerParcelMgr::getInstance()->deselectLand();
|
||||
LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL);
|
||||
LLViewerMediaFocus::getInstance()->clearFocus();
|
||||
|
||||
// Close all pie menus, deselect land, etc.
|
||||
// Don't change the camera until we know teleport succeeded. JC
|
||||
@@ -4308,7 +4296,7 @@ void LLAgent::setTeleportState(ETeleportState state)
|
||||
|
||||
case TELEPORT_MOVING:
|
||||
// We're outa here. Save "back" slurl.
|
||||
mTeleportSourceSLURL = getSLURL();
|
||||
LLAgentUI::buildSLURL(*mTeleportSourceSLURL);
|
||||
break;
|
||||
|
||||
case TELEPORT_ARRIVING:
|
||||
@@ -4734,6 +4722,10 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename)
|
||||
}//end for (all message sets in xml file)
|
||||
}
|
||||
|
||||
const void LLAgent::getTeleportSourceSLURL(LLSLURL& slurl) const
|
||||
{
|
||||
slurl = *mTeleportSourceSLURL;
|
||||
}
|
||||
|
||||
void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility )
|
||||
{
|
||||
@@ -4787,14 +4779,13 @@ void LLAgent::renderAutoPilotTarget()
|
||||
}
|
||||
}
|
||||
|
||||
void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity)
|
||||
void LLAgent::showLureDestination(const std::string fromname, U64& handle, U32 x, U32 y, U32 z)
|
||||
{
|
||||
const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0));
|
||||
LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(posglobal);
|
||||
LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
|
||||
|
||||
if(mPendingLure)
|
||||
delete mPendingLure;
|
||||
mPendingLure = new SHLureRequest(fromname,posglobal,x,y,z);
|
||||
mPendingLure = new SHLureRequest(fromname,handle,x,y,z);
|
||||
|
||||
if(siminfo) //We already have an entry? Go right on to displaying it.
|
||||
{
|
||||
@@ -4802,8 +4793,8 @@ void LLAgent::showLureDestination(const std::string fromname, const int global_x
|
||||
}
|
||||
else
|
||||
{
|
||||
U16 grid_x = (U16)(global_x / REGION_WIDTH_UNITS);
|
||||
U16 grid_y = (U16)(global_y / REGION_WIDTH_UNITS);
|
||||
U32 grid_x, grid_y;
|
||||
grid_from_region_handle(handle,&grid_x,&grid_y);
|
||||
LLWorldMapMessage::getInstance()->sendMapBlockRequest(grid_x, grid_y, grid_x, grid_y, true); //Will call onFoundLureDestination on response
|
||||
}
|
||||
}
|
||||
@@ -4814,7 +4805,7 @@ void LLAgent::onFoundLureDestination(LLSimInfo *siminfo)
|
||||
return;
|
||||
|
||||
if(!siminfo)
|
||||
siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(mPendingLure->mPosGlobal);
|
||||
siminfo = LLWorldMap::getInstance()->simInfoFromHandle(mPendingLure->mRegionHandle);
|
||||
if(siminfo)
|
||||
{
|
||||
const std::string sim_name = siminfo->getName();
|
||||
@@ -4823,7 +4814,7 @@ void LLAgent::onFoundLureDestination(LLSimInfo *siminfo)
|
||||
llinfos << mPendingLure->mAvatarName << "'s teleport lure is to " << sim_name << " (" << maturity << ")" << llendl;
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[NAME]"] = mPendingLure->mAvatarName;
|
||||
args["[DESTINATION]"] = LLURLDispatcher::buildSLURL(sim_name, (S32)mPendingLure->mPosLocal[0], (S32)mPendingLure->mPosLocal[1], (S32)mPendingLure->mPosLocal[2] );
|
||||
args["[DESTINATION]"] = LLSLURL(sim_name,mPendingLure->mPosLocal).getSLURLString();
|
||||
std::string msg = LLTrans::getString("TeleportOfferMaturity", args);
|
||||
if (!maturity.empty())
|
||||
{
|
||||
|
||||
@@ -68,6 +68,7 @@ class LLPickInfo;
|
||||
class LLViewerObject;
|
||||
class LLAgentDropGroupViewerNode;
|
||||
class LLAgentAccess;
|
||||
class LLSLURL;
|
||||
class LLSimInfo;
|
||||
class LLTeleportRequest;
|
||||
|
||||
@@ -245,20 +246,18 @@ public:
|
||||
LLViewerRegion *getRegion() const { return mRegionp; }
|
||||
const LLHost& getRegionHost() const;
|
||||
BOOL inPrelude();
|
||||
std::string getSLURL() const; //Return uri for current region
|
||||
|
||||
|
||||
// <edit>
|
||||
struct SHLureRequest
|
||||
{
|
||||
SHLureRequest(const std::string& avatar_name, const LLVector3d& pos_global, const int x, const int y, const int z) :
|
||||
mAvatarName(avatar_name), mPosGlobal(pos_global)
|
||||
{ mPosLocal[0] = x; mPosLocal[1] = y; mPosLocal[2] = z;}
|
||||
SHLureRequest(const std::string& avatar_name, U64& handle, const U32 x, const U32 y, const U32 z) :
|
||||
mAvatarName(avatar_name), mRegionHandle(handle), mPosLocal(x,y,z) {}
|
||||
const std::string mAvatarName;
|
||||
const LLVector3d mPosGlobal;
|
||||
int mPosLocal[3];
|
||||
const U64 mRegionHandle;
|
||||
LLVector3 mPosLocal;
|
||||
};
|
||||
SHLureRequest *mPendingLure;
|
||||
void showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity);
|
||||
void showLureDestination(const std::string fromname, U64& handle, U32 x, U32 y, U32 z);
|
||||
void onFoundLureDestination(LLSimInfo *siminfo = NULL);
|
||||
// </edit>
|
||||
|
||||
@@ -584,13 +583,14 @@ public:
|
||||
|
||||
public:
|
||||
static void parseTeleportMessages(const std::string& xml_filename);
|
||||
const std::string& getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
|
||||
const void getTeleportSourceSLURL(LLSLURL& slurl) const;
|
||||
public:
|
||||
// ! TODO ! Define ERROR and PROGRESS enums here instead of exposing the mappings.
|
||||
static std::map<std::string, std::string> sTeleportErrorMessages;
|
||||
static std::map<std::string, std::string> sTeleportProgressMessages;
|
||||
public:
|
||||
std::string mTeleportSourceSLURL; // SLURL where last TP began.
|
||||
private:
|
||||
LLSLURL * mTeleportSourceSLURL; // SLURL where last TP began
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Teleport Actions
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewerparcelmgr.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llslurl.h"
|
||||
// [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d)
|
||||
#include "rlvhandler.h"
|
||||
// [/RLVa:KB]
|
||||
@@ -48,9 +49,8 @@ void LLAgentUI::buildFullname(std::string& name)
|
||||
name = gAgentAvatarp->getFullname();
|
||||
}
|
||||
|
||||
/*
|
||||
//static
|
||||
void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /= true/ )
|
||||
void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /*= true*/)
|
||||
{
|
||||
LLSLURL return_slurl;
|
||||
LLViewerRegion *regionp = gAgent.getRegion();
|
||||
@@ -59,7 +59,7 @@ void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /= true/ )
|
||||
return_slurl = LLSLURL(regionp->getName(), gAgent.getPositionGlobal());
|
||||
}
|
||||
slurl = return_slurl;
|
||||
}*/
|
||||
}
|
||||
|
||||
//static
|
||||
BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "llmodaldialog.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llmimetypes.h"
|
||||
#include "llslurl.h"
|
||||
#include "llstartup.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "llviewerjoystick.h"
|
||||
@@ -80,6 +81,7 @@
|
||||
#include "llvector4a.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llurlmatch.h"
|
||||
#include "llprogressview.h"
|
||||
#include "llvocache.h"
|
||||
#include "llvopartgroup.h"
|
||||
@@ -94,6 +96,8 @@
|
||||
#include "llimagej2c.h"
|
||||
#include "llmemory.h"
|
||||
#include "llprimitive.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llurlentry.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include <boost/bind.hpp>
|
||||
@@ -149,7 +153,6 @@
|
||||
#include "llworld.h"
|
||||
#include "llhudeffecttrail.h"
|
||||
#include "llvectorperfoptions.h"
|
||||
#include "llurlsimstring.h"
|
||||
#include "llwatchdog.h"
|
||||
|
||||
// Included so that constants/settings might be initialized
|
||||
@@ -749,9 +752,11 @@ bool LLAppViewer::init()
|
||||
|
||||
LLWeb::initClass(); // do this after LLUI
|
||||
|
||||
LLTextEditor::setURLCallbacks(&LLWeb::loadURL,
|
||||
&LLURLDispatcher::dispatchFromTextEditor,
|
||||
&LLURLDispatcher::dispatchFromTextEditor);
|
||||
// Provide the text fields with callbacks for opening Urls
|
||||
LLUrlAction::setOpenURLCallback(boost::bind(&LLWeb::loadURL, _1, LLStringUtil::null, LLStringUtil::null));
|
||||
LLUrlAction::setOpenURLInternalCallback(boost::bind(&LLWeb::loadURLInternal, _1, LLStringUtil::null, LLStringUtil::null));
|
||||
LLUrlAction::setOpenURLExternalCallback(boost::bind(&LLWeb::loadURLExternal, _1, true, LLStringUtil::null));
|
||||
LLUrlAction::setExecuteSLURLCallback(&LLURLDispatcher::dispatchFromTextEditor);
|
||||
|
||||
LLToolMgr::getInstance(); // Initialize tool manager if not already instantiated
|
||||
|
||||
@@ -969,6 +974,8 @@ bool LLAppViewer::init()
|
||||
LLEnvManagerNew::instance().usePrefs();
|
||||
|
||||
gGLActive = FALSE;
|
||||
LLViewerMedia::initClass();
|
||||
LL_INFOS("InitInfo") << "Viewer media initialized." << LL_ENDL ;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1695,8 +1702,7 @@ bool LLAppViewer::cleanup()
|
||||
if (mPurgeOnExit)
|
||||
{
|
||||
llinfos << "Purging all cache files on exit" << llendflush;
|
||||
std::string mask = gDirUtilp->getDirDelimiter() + "*.*";
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),mask);
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,""),"*.*");
|
||||
}
|
||||
|
||||
removeMarkerFile(); // Any crashes from here on we'll just have to ignore
|
||||
@@ -1773,7 +1779,6 @@ bool LLAppViewer::cleanup()
|
||||
//Note:
|
||||
//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
|
||||
//because some new image might be generated during cleaning up media. --bao
|
||||
LLViewerMediaFocus::cleanupClass();
|
||||
LLViewerMedia::cleanupClass();
|
||||
LLViewerParcelMedia::cleanupClass();
|
||||
gTextureList.shutdown(); // shutdown again in case a callback added something
|
||||
@@ -2323,30 +2328,17 @@ bool LLAppViewer::initConfiguration()
|
||||
// injection and steal passwords. Phoenix. SL-55321
|
||||
if(clp.hasOption("url"))
|
||||
{
|
||||
std::string slurl = clp.getOption("url")[0];
|
||||
if (LLURLDispatcher::isSLURLCommand(slurl))
|
||||
{
|
||||
LLStartUp::sSLURLCommand = slurl;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLURLSimString::setString(slurl);
|
||||
}
|
||||
LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
|
||||
if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION)
|
||||
{
|
||||
gHippoGridManager->setCurrentGrid(LLStartUp::getStartSLURL().getGrid());
|
||||
|
||||
}
|
||||
}
|
||||
else if(clp.hasOption("slurl"))
|
||||
{
|
||||
std::string slurl = clp.getOption("slurl")[0];
|
||||
if(LLURLDispatcher::isSLURL(slurl))
|
||||
{
|
||||
if (LLURLDispatcher::isSLURLCommand(slurl))
|
||||
{
|
||||
LLStartUp::sSLURLCommand = slurl;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLURLSimString::setString(slurl);
|
||||
}
|
||||
}
|
||||
LLSLURL start_slurl(clp.getOption("slurl")[0]);
|
||||
LLStartUp::setStartSLURL(start_slurl);
|
||||
}
|
||||
|
||||
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
|
||||
@@ -2425,18 +2417,11 @@ bool LLAppViewer::initConfiguration()
|
||||
// don't call anotherInstanceRunning() when doing URL handoff, as
|
||||
// it relies on checking a marker file which will not work when running
|
||||
// out of different directories
|
||||
std::string slurl;
|
||||
if (!LLStartUp::sSLURLCommand.empty())
|
||||
|
||||
if (LLStartUp::getStartSLURL().isValid() &&
|
||||
(gSavedSettings.getBOOL("SLURLPassToOtherInstance")))
|
||||
{
|
||||
slurl = LLStartUp::sSLURLCommand;
|
||||
}
|
||||
else if (LLURLSimString::parse())
|
||||
{
|
||||
slurl = LLURLSimString::getURL();
|
||||
}
|
||||
if (!slurl.empty())
|
||||
{
|
||||
if (sendURLToOtherInstance(slurl))
|
||||
if (sendURLToOtherInstance(LLStartUp::getStartSLURL().getSLURLString()))
|
||||
{
|
||||
// successfully handed off URL to existing instance, exit
|
||||
return false;
|
||||
@@ -2492,9 +2477,10 @@ bool LLAppViewer::initConfiguration()
|
||||
|
||||
// need to do this here - need to have initialized global settings first
|
||||
std::string nextLoginLocation = gSavedSettings.getString( "NextLoginLocation" );
|
||||
if ( nextLoginLocation.length() )
|
||||
if ( !nextLoginLocation.empty() )
|
||||
{
|
||||
LLURLSimString::setString( nextLoginLocation );
|
||||
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
|
||||
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
|
||||
}
|
||||
|
||||
gLastRunVersion = gSavedSettings.getString("LastRunVersion");
|
||||
@@ -2678,8 +2664,7 @@ void LLAppViewer::cleanupSavedSettings()
|
||||
|
||||
void LLAppViewer::removeCacheFiles(const std::string& file_mask)
|
||||
{
|
||||
std::string mask = gDirUtilp->getDirDelimiter() + file_mask;
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), mask);
|
||||
gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), file_mask);
|
||||
}
|
||||
|
||||
void LLAppViewer::writeSystemInfo()
|
||||
|
||||
@@ -459,7 +459,7 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ
|
||||
std::string url = slurl;
|
||||
LLMediaCtrl* web = NULL;
|
||||
const bool trusted_browser = false;
|
||||
if (LLURLDispatcher::dispatch(url, web, trusted_browser))
|
||||
if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))
|
||||
{
|
||||
// bring window to foreground, as it has just been "launched" from a URL
|
||||
// todo: hmm, how to get there from here?
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include "llviewernetwork.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llmd5.h"
|
||||
#include "llurlsimstring.h"
|
||||
#include "llfloaterworldmap.h"
|
||||
#include "llurldispatcher.h"
|
||||
#include <Carbon/Carbon.h>
|
||||
@@ -476,7 +475,7 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
|
||||
|
||||
LLMediaCtrl* web = NULL;
|
||||
const bool trusted_browser = false;
|
||||
LLURLDispatcher::dispatch(url, web, trusted_browser);
|
||||
LLURLDispatcher::dispatch(url, "", web, trusted_browser);
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
||||
@@ -488,7 +488,7 @@ bool LLAppViewerWin32::initHardwareTest()
|
||||
if (OSBTN_NO== button)
|
||||
{
|
||||
LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL;
|
||||
LLWeb::loadURLExternal(DIRECTX_9_URL);
|
||||
LLWeb::loadURLExternal(DIRECTX_9_URL, false);
|
||||
return false;
|
||||
}
|
||||
gSavedSettings.setWarning("AboutDirectX9", FALSE);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user