Merge remote-tracking branch 'remotes/origin/DRTVWR-559' into davep/SL-19842
commit
74940194fa
|
|
@ -0,0 +1,18 @@
|
|||
name: pre-commit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [main, contribute]
|
||||
tags: [v*]
|
||||
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
- uses: pre-commit/action@v3.0.0
|
||||
|
|
@ -15,8 +15,8 @@ jobs:
|
|||
- uses: actions/stale@v6
|
||||
id: stale
|
||||
with:
|
||||
stale-pr-message: This pull request is stale because it has been open 60 days with no activity. Remove stale label or comment or it will be closed in 7 days
|
||||
days-before-stale: 60
|
||||
stale-pr-message: This pull request is stale because it has been open 30 days with no activity. Remove stale label or comment or it will be closed in 7 days
|
||||
days-before-stale: 30
|
||||
days-before-close: 7
|
||||
exempt-pr-labels: blocked,must,should,keep
|
||||
stale-pr-label: stale
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
repos:
|
||||
- repo: https://bitbucket.org/lindenlab/git-hooks.git
|
||||
rev: v1.0.0-beta2
|
||||
- repo: https://github.com/secondlife/git-hooks.git
|
||||
rev: v1.0.0
|
||||
hooks:
|
||||
- id: opensource-license
|
||||
- id: jira-issue
|
||||
- id: llsd
|
||||
- id: no-trigraphs
|
||||
- id: copyright
|
||||
|
|
@ -11,7 +10,7 @@ repos:
|
|||
files: \.(cpp|c|h|py|glsl|cmake|txt)$
|
||||
exclude: language.txt
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.5.0
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: check-xml
|
||||
- id: mixed-line-ending
|
||||
|
|
|
|||
|
|
@ -2759,9 +2759,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>9e1b5515ab59b4e9cfeef6626d65d03d</string>
|
||||
<string>8b091b1f13348eedadf66d7d81cb6bc1</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/108609/945996/viewer_manager-3.0.577252-darwin64-577252.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/116621/1003286/viewer_manager-3.0.580913-darwin64-580913.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2771,9 +2771,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>a3c599595ecc8fb987a5499fca42520a</string>
|
||||
<string>647e86470e02509b1cf89829d08dfd46</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/108610/946003/viewer_manager-3.0.577252-windows-577252.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/116623/1003293/viewer_manager-3.0.580913-windows-580913.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -2784,7 +2784,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>3.0.577252</string>
|
||||
<string>3.0.580913</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -594,6 +594,7 @@ Henri Beauchamp
|
|||
VWR-4157
|
||||
SL-15175
|
||||
SL-19110
|
||||
SL-19159
|
||||
herina Bode
|
||||
Hikkoshi Sakai
|
||||
VWR-429
|
||||
|
|
@ -932,6 +933,8 @@ Lexi Frua
|
|||
Lillie Cordeaux
|
||||
Lilly Zenovka
|
||||
Lizzy Macarthur
|
||||
Logue Takacs
|
||||
INTL-490
|
||||
Luban Yiyuan
|
||||
Luc Starsider
|
||||
Luminous Luminos
|
||||
|
|
@ -1188,6 +1191,7 @@ PanteraPolnocy
|
|||
SL-18891
|
||||
SL-18904
|
||||
SL-18937
|
||||
SL-19207
|
||||
SL-19681
|
||||
Parvati Silverweb
|
||||
Patric Mills
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
#include "llsaleinfo.h"
|
||||
#include "llwearabletype.h"
|
||||
|
||||
class LLMD5;
|
||||
class LLVisualParam;
|
||||
class LLTexGlobalColorInfo;
|
||||
class LLTexGlobalColor;
|
||||
|
|
@ -110,9 +109,6 @@ public:
|
|||
// Something happened that requires the wearable to be updated (e.g. worn/unworn).
|
||||
virtual void setUpdated() const = 0;
|
||||
|
||||
// Update the baked texture hash.
|
||||
virtual void addToBakedTextureHash(LLMD5& hash) const = 0;
|
||||
|
||||
typedef std::map<S32, LLVisualParam *> visual_param_index_map_t;
|
||||
visual_param_index_map_t mVisualParamIndexMap;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "llavatarappearance.h"
|
||||
#include "llavatarappearancedefines.h"
|
||||
#include "lldriverparam.h"
|
||||
#include "llmd5.h"
|
||||
|
||||
LLWearableData::LLWearableData() :
|
||||
mAvatarAppearance(NULL)
|
||||
|
|
@ -343,42 +342,3 @@ U32 LLWearableData::getWearableCount(const U32 tex_index) const
|
|||
const LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index);
|
||||
return getWearableCount(wearable_type);
|
||||
}
|
||||
|
||||
LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index,
|
||||
BOOL generate_valid_hash) // Set to false if you want to upload the baked texture w/o putting it in the cache
|
||||
{
|
||||
LLUUID hash_id;
|
||||
bool hash_computed = false;
|
||||
LLMD5 hash;
|
||||
const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index);
|
||||
|
||||
for (U8 i=0; i < baked_dict->mWearables.size(); i++)
|
||||
{
|
||||
const LLWearableType::EType baked_type = baked_dict->mWearables[i];
|
||||
const U32 num_wearables = getWearableCount(baked_type);
|
||||
for (U32 index = 0; index < num_wearables; ++index)
|
||||
{
|
||||
const LLWearable* wearable = getWearable(baked_type,index);
|
||||
if (wearable)
|
||||
{
|
||||
wearable->addToBakedTextureHash(hash);
|
||||
hash_computed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hash_computed)
|
||||
{
|
||||
hash.update((const unsigned char*)baked_dict->mWearablesHashID.mData, UUID_BYTES);
|
||||
|
||||
if (!generate_valid_hash)
|
||||
{
|
||||
invalidateBakedTextureHash(hash);
|
||||
}
|
||||
hash.finalize();
|
||||
hash.raw_digest(hash_id.mData);
|
||||
}
|
||||
|
||||
return hash_id;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,15 +85,6 @@ protected:
|
|||
private:
|
||||
void pullCrossWearableValues(const LLWearableType::EType type);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Server Communication
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
LLUUID computeBakedTextureHash(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index,
|
||||
BOOL generate_valid_hash = TRUE);
|
||||
protected:
|
||||
virtual void invalidateBakedTextureHash(LLMD5& hash) const {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Member variables
|
||||
//--------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -204,7 +204,8 @@ std::string LLAudioEngine::getInternetStreamURL()
|
|||
{
|
||||
if (mStreamingAudioImpl)
|
||||
return mStreamingAudioImpl->getURL();
|
||||
else return std::string();
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -345,42 +346,43 @@ void LLAudioEngine::idle()
|
|||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
||||
// Check to see if the current sound is done playing.
|
||||
if (!channelp->isPlaying())
|
||||
{
|
||||
// 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->updateBuffer();
|
||||
sourcep->getChannel()->play();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check to see if the current sound is looped.
|
||||
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;
|
||||
|
||||
// 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.
|
||||
// Actually, should do a time sync so if we're a loop master/slave
|
||||
// we don't drift away.
|
||||
sourcep->setupChannel();
|
||||
channelp->updateBuffer();
|
||||
sourcep->getChannel()->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();
|
||||
sourcep->getChannel()->play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -396,18 +398,11 @@ void LLAudioEngine::idle()
|
|||
for (source_map::value_type& src_pair : mAllSources)
|
||||
{
|
||||
LLAudioSource *sourcep = src_pair.second;
|
||||
if (sourcep->isMuted())
|
||||
if (sourcep->isMuted() && sourcep->isSyncMaster() && sourcep->getPriority() > max_sm_priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sourcep->isSyncMaster())
|
||||
{
|
||||
if (sourcep->getPriority() > max_sm_priority)
|
||||
{
|
||||
sync_masterp = sourcep;
|
||||
master_channelp = sync_masterp->getChannel();
|
||||
max_sm_priority = sourcep->getPriority();
|
||||
}
|
||||
sync_masterp = sourcep;
|
||||
master_channelp = sync_masterp->getChannel();
|
||||
max_sm_priority = sourcep->getPriority();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -737,7 +732,7 @@ F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
|
|||
}
|
||||
|
||||
return (gain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
|
||||
|
|
@ -964,11 +959,10 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
|
|||
else
|
||||
{
|
||||
LL_DEBUGS("AudioEngine") << "Cleaning up audio sources for "<< asp->getID() <<LL_ENDL;
|
||||
delete asp;
|
||||
mAllSources.erase(iter);
|
||||
delete asp;
|
||||
mAllSources.erase(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
|
||||
{
|
||||
|
|
@ -1687,19 +1681,18 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
|
|||
{
|
||||
LL_DEBUGS("AudioEngine") << "( id: " << sourcep->getID() << ")" << LL_ENDL;
|
||||
|
||||
if (sourcep == mCurrentSourcep)
|
||||
{
|
||||
// Don't reallocate the channel, this will make FMOD goofy.
|
||||
//LL_INFOS() << "Calling setSource with same source!" << LL_ENDL;
|
||||
if (sourcep == mCurrentSourcep)
|
||||
{
|
||||
// Don't reallocate the channel, this will make FMOD goofy.
|
||||
//LL_INFOS() << "Calling setSource with same source!" << LL_ENDL;
|
||||
}
|
||||
|
||||
mCurrentSourcep = sourcep;
|
||||
|
||||
updateBuffer();
|
||||
update3DPosition();
|
||||
}
|
||||
|
||||
mCurrentSourcep = sourcep;
|
||||
|
||||
updateBuffer();
|
||||
update3DPosition();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLAudioChannel::updateBuffer()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
// initialization/startup/shutdown
|
||||
virtual bool init(void *userdata, const std::string &app_title);
|
||||
virtual std::string getDriverName(bool verbose) = 0;
|
||||
virtual LLStreamingAudioInterface *createDefaultStreamingAudioImpl() const = 0;
|
||||
virtual void shutdown();
|
||||
|
||||
// Used by the mechanics of the engine
|
||||
|
|
@ -468,13 +469,13 @@ struct SoundData
|
|||
const LLUUID& owner_id,
|
||||
const F32 gain,
|
||||
const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
|
||||
const LLVector3d &pos_global = LLVector3d::zero)
|
||||
const LLVector3d &pos_global = LLVector3d::zero) :
|
||||
audio_uuid(audio_uuid),
|
||||
owner_id(owner_id),
|
||||
gain(gain),
|
||||
type(type),
|
||||
pos_global(pos_global)
|
||||
{
|
||||
this->audio_uuid = audio_uuid;
|
||||
this->owner_id = owner_id;
|
||||
this->gain = gain;
|
||||
this->type = type;
|
||||
this->pos_global = pos_global;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -208,10 +208,6 @@ bool LLAudioEngine_FMODSTUDIO::init(void* userdata, const std::string &app_title
|
|||
}
|
||||
#endif
|
||||
|
||||
// set up our favourite FMOD-native streaming audio implementation if none has already been added
|
||||
if (!getStreamingAudioImpl()) // no existing implementation added
|
||||
setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem));
|
||||
|
||||
LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL;
|
||||
|
||||
int r_numbuffers, r_samplerate, r_channels;
|
||||
|
|
@ -253,6 +249,13 @@ std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose)
|
|||
}
|
||||
|
||||
|
||||
// create our favourite FMOD-native streaming audio implementation
|
||||
LLStreamingAudioInterface *LLAudioEngine_FMODSTUDIO::createDefaultStreamingAudioImpl() const
|
||||
{
|
||||
return new LLStreamingAudio_FMODSTUDIO(mSystem);
|
||||
}
|
||||
|
||||
|
||||
void LLAudioEngine_FMODSTUDIO::allocateListener(void)
|
||||
{
|
||||
mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ public:
|
|||
// initialization/startup/shutdown
|
||||
virtual bool init(void *user_data, const std::string &app_title);
|
||||
virtual std::string getDriverName(bool verbose);
|
||||
virtual LLStreamingAudioInterface* createDefaultStreamingAudioImpl() const;
|
||||
virtual void allocateListener();
|
||||
|
||||
virtual void shutdown();
|
||||
|
|
|
|||
|
|
@ -497,13 +497,20 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
|
|||
// request asset
|
||||
mAssetStatus = ASSET_FETCHED;
|
||||
|
||||
LL_DEBUGS("Animation") << "Requesting data fetch for: " << mID << LL_ENDL;
|
||||
character_id = new LLUUID(mCharacter->getID());
|
||||
gAssetStorage->getAssetData(mID,
|
||||
LLAssetType::AT_ANIMATION,
|
||||
onLoadComplete,
|
||||
(void *)character_id,
|
||||
FALSE);
|
||||
if (mID.notNull())
|
||||
{
|
||||
LL_DEBUGS("Animation") << "Requesting data fetch for: " << mID << LL_ENDL;
|
||||
character_id = new LLUUID(mCharacter->getID());
|
||||
gAssetStorage->getAssetData(mID,
|
||||
LLAssetType::AT_ANIMATION,
|
||||
onLoadComplete,
|
||||
(void*)character_id,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("Animation") << "Attempted to fetch animation " << mName << " with null id for character " << mCharacter->getID() << LL_ENDL;
|
||||
}
|
||||
|
||||
return STATUS_HOLD;
|
||||
case ASSET_FETCHED:
|
||||
|
|
|
|||
|
|
@ -96,6 +96,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Make this class no-copy (it would be possible, with custom copy
|
||||
// operators, but it is not trivially copyable, because of the mState
|
||||
// pointer): it does not really make sense to allow copying it anyway,
|
||||
// since all we care about is the resulting digest (so you should only
|
||||
// need and care about storing/copying the digest and not a class
|
||||
// instance).
|
||||
HBXXH64(const HBXXH64&) noexcept = delete;
|
||||
HBXXH64& operator=(const HBXXH64&) noexcept = delete;
|
||||
|
||||
~HBXXH64();
|
||||
|
||||
void update(const void* buffer, size_t len);
|
||||
|
|
@ -199,6 +208,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Make this class no-copy (it would be possible, with custom copy
|
||||
// operators, but it is not trivially copyable, because of the mState
|
||||
// pointer): it does not really make sense to allow copying it anyway,
|
||||
// since all we care about is the resulting digest (so you should only
|
||||
// need and care about storing/copying the digest and not a class
|
||||
// instance).
|
||||
HBXXH128(const HBXXH128&) noexcept = delete;
|
||||
HBXXH128& operator=(const HBXXH128&) noexcept = delete;
|
||||
|
||||
~HBXXH128();
|
||||
|
||||
void update(const void* buffer, size_t len);
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ const U8 CLICK_ACTION_PLAY = 5;
|
|||
const U8 CLICK_ACTION_OPEN_MEDIA = 6;
|
||||
const U8 CLICK_ACTION_ZOOM = 7;
|
||||
const U8 CLICK_ACTION_DISABLED = 8;
|
||||
const U8 CLICK_ACTION_IGNORE = 9;
|
||||
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -167,48 +167,34 @@ const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luc
|
|||
//
|
||||
// defined for U16, U32, U64, S16, S32, S64, :
|
||||
// llclampb(a) // clamps a to [0 .. 255]
|
||||
//
|
||||
//
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline auto llmax(T1 d1, T2 d2)
|
||||
// recursion tail
|
||||
template <typename T>
|
||||
inline auto llmax(T data)
|
||||
{
|
||||
return (d1 > d2) ? d1 : d2;
|
||||
return data;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
inline auto llmax(T1 d1, T2 d2, T3 d3)
|
||||
template <typename T0, typename T1, typename... Ts>
|
||||
inline auto llmax(T0 d0, T1 d1, Ts... rest)
|
||||
{
|
||||
auto r = llmax(d1,d2);
|
||||
return llmax(r, d3);
|
||||
auto maxrest = llmax(d1, rest...);
|
||||
return (d0 > maxrest)? d0 : maxrest;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
inline auto llmax(T1 d1, T2 d2, T3 d3, T4 d4)
|
||||
// recursion tail
|
||||
template <typename T>
|
||||
inline auto llmin(T data)
|
||||
{
|
||||
auto r1 = llmax(d1,d2);
|
||||
auto r2 = llmax(d3,d4);
|
||||
return llmax(r1, r2);
|
||||
return data;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline auto llmin(T1 d1, T2 d2)
|
||||
template <typename T0, typename T1, typename... Ts>
|
||||
inline auto llmin(T0 d0, T1 d1, Ts... rest)
|
||||
{
|
||||
return (d1 < d2) ? d1 : d2;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
inline auto llmin(T1 d1, T2 d2, T3 d3)
|
||||
{
|
||||
auto r = llmin(d1,d2);
|
||||
return (r < d3 ? r : d3);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
inline auto llmin(T1 d1, T2 d2, T3 d3, T4 d4)
|
||||
{
|
||||
auto r1 = llmin(d1,d2);
|
||||
auto r2 = llmin(d3,d4);
|
||||
return llmin(r1, r2);
|
||||
auto minrest = llmin(d1, rest...);
|
||||
return (d0 < minrest) ? d0 : minrest;
|
||||
}
|
||||
|
||||
template <typename A, typename MIN, typename MAX>
|
||||
|
|
|
|||
|
|
@ -204,30 +204,35 @@ public:
|
|||
LLSD packet(LLSDMap("pump", pump)("data", data));
|
||||
|
||||
std::ostringstream buffer;
|
||||
buffer << LLSDNotationStreamer(packet);
|
||||
// SL-18330: for large data blocks, it's much faster to parse binary
|
||||
// LLSD than notation LLSD. Use serialize(LLSD_BINARY) rather than
|
||||
// directly calling LLSDBinaryFormatter because, unlike the latter,
|
||||
// serialize() prepends the relevant header, needed by a general-
|
||||
// purpose LLSD parser to distinguish binary from notation.
|
||||
LLSDSerialize::serialize(packet, buffer, LLSDSerialize::LLSD_BINARY,
|
||||
LLSDFormatter::OPTIONS_NONE);
|
||||
|
||||
/*==========================================================================*|
|
||||
// DEBUGGING ONLY: don't copy str() if we can avoid it.
|
||||
std::string strdata(buffer.str());
|
||||
if (std::size_t(buffer.tellp()) != strdata.length())
|
||||
{
|
||||
LL_ERRS("LLLeap") << "tellp() -> " << buffer.tellp() << " != "
|
||||
LL_ERRS("LLLeap") << "tellp() -> " << static_cast<U64>(buffer.tellp()) << " != "
|
||||
<< "str().length() -> " << strdata.length() << LL_ENDL;
|
||||
}
|
||||
// DEBUGGING ONLY: reading back is terribly inefficient.
|
||||
std::istringstream readback(strdata);
|
||||
LLSD echo;
|
||||
LLPointer<LLSDParser> parser(new LLSDNotationParser());
|
||||
S32 parse_status(parser->parse(readback, echo, strdata.length()));
|
||||
if (parse_status == LLSDParser::PARSE_FAILURE)
|
||||
bool parse_status(LLSDSerialize::deserialize(echo, readback, strdata.length()));
|
||||
if (! parse_status)
|
||||
{
|
||||
LL_ERRS("LLLeap") << "LLSDNotationParser() cannot parse output of "
|
||||
<< "LLSDNotationStreamer()" << LL_ENDL;
|
||||
LL_ERRS("LLLeap") << "LLSDSerialize::deserialize() cannot parse output of "
|
||||
<< "LLSDSerialize::serialize(LLSD_BINARY)" << LL_ENDL;
|
||||
}
|
||||
if (! llsd_equals(echo, packet))
|
||||
{
|
||||
LL_ERRS("LLLeap") << "LLSDNotationParser() produced different LLSD "
|
||||
<< "than passed to LLSDNotationStreamer()" << LL_ENDL;
|
||||
LL_ERRS("LLLeap") << "LLSDSerialize::deserialize() returned different LLSD "
|
||||
<< "than passed to LLSDSerialize::serialize()" << LL_ENDL;
|
||||
}
|
||||
|*==========================================================================*/
|
||||
|
||||
|
|
@ -314,9 +319,17 @@ public:
|
|||
LL_DEBUGS("LLLeap") << "needed " << mExpect << " bytes, got "
|
||||
<< childout.size() << ", parsing LLSD" << LL_ENDL;
|
||||
LLSD data;
|
||||
#if 1
|
||||
// specifically require notation LLSD from child
|
||||
LLPointer<LLSDParser> parser(new LLSDNotationParser());
|
||||
S32 parse_status(parser->parse(childout.get_istream(), data, mExpect));
|
||||
if (parse_status == LLSDParser::PARSE_FAILURE)
|
||||
#else
|
||||
// SL-18330: accept any valid LLSD serialization format from child
|
||||
// Unfortunately this runs into trouble we have not yet debugged.
|
||||
bool parse_status(LLSDSerialize::deserialize(data, childout.get_istream(), mExpect));
|
||||
if (! parse_status)
|
||||
#endif
|
||||
{
|
||||
bad_protocol("unparseable LLSD data");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ LLMD5::LLMD5()
|
|||
// operation, processing another message block, and updating the
|
||||
// context.
|
||||
|
||||
void LLMD5::update (const uint1 *input, const size_t input_length) {
|
||||
void LLMD5::update (const uint8_t *input, const size_t input_length) {
|
||||
|
||||
size_t input_index, buffer_index;
|
||||
size_t buffer_space; // how much space is left in buffer
|
||||
|
|
@ -189,7 +189,7 @@ void LLMD5::finalize (){
|
|||
|
||||
unsigned char bits[8]; /* Flawfinder: ignore */
|
||||
size_t index, padLen;
|
||||
static uint1 PADDING[64]={
|
||||
static uint8_t PADDING[64]={
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
|
|
@ -201,8 +201,8 @@ void LLMD5::finalize (){
|
|||
}
|
||||
|
||||
// Save number of bits.
|
||||
// Treat count, a uint64_t, as uint4[2].
|
||||
encode (bits, reinterpret_cast<uint4*>(&count), 8);
|
||||
// Treat count, a uint64_t, as uint32_t[2].
|
||||
encode (bits, reinterpret_cast<uint32_t*>(&count), 8);
|
||||
|
||||
// Pad out to 56 mod 64.
|
||||
index = size_t((count >> 3) & 0x3f);
|
||||
|
|
@ -412,7 +412,7 @@ Rotation is separate from addition to prevent recomputation.
|
|||
// LLMD5 basic transformation. Transforms state based on block.
|
||||
void LLMD5::transform (const U8 block[64]){
|
||||
|
||||
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
decode (x, block, 64);
|
||||
|
||||
|
|
@ -496,38 +496,38 @@ void LLMD5::transform (const U8 block[64]){
|
|||
state[3] += d;
|
||||
|
||||
// Zeroize sensitive information.
|
||||
memset ( (uint1 *) x, 0, sizeof(x));
|
||||
memset ( (uint8_t *) x, 0, sizeof(x));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Encodes input (UINT4) into output (unsigned char). Assumes len is
|
||||
// Encodes input (uint32_t) into output (unsigned char). Assumes len is
|
||||
// a multiple of 4.
|
||||
void LLMD5::encode (uint1 *output, const uint4 *input, const size_t len) {
|
||||
void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) {
|
||||
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (uint1) (input[i] & 0xff);
|
||||
output[j+1] = (uint1) ((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (uint1) ((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (uint1) ((input[i] >> 24) & 0xff);
|
||||
output[j] = (uint8_t) (input[i] & 0xff);
|
||||
output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Decodes input (unsigned char) into output (UINT4). Assumes len is
|
||||
// Decodes input (unsigned char) into output (uint32_t). Assumes len is
|
||||
// a multiple of 4.
|
||||
void LLMD5::decode (uint4 *output, const uint1 *input, const size_t len){
|
||||
void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){
|
||||
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
|
||||
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
|
||||
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
|
||||
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ documentation and/or software.
|
|||
|
||||
*/
|
||||
|
||||
#include <cstdint> // uint32_t et al.
|
||||
|
||||
// use for the raw digest output
|
||||
const int MD5RAW_BYTES = 16;
|
||||
|
||||
|
|
@ -75,18 +77,13 @@ const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null
|
|||
const int MD5HEX_STR_BYTES = 32; // message system fixed size
|
||||
|
||||
class LL_COMMON_API LLMD5 {
|
||||
// first, some types:
|
||||
typedef unsigned int uint4; // assumes integer is 4 words long
|
||||
typedef unsigned short int uint2; // assumes short integer is 2 words long
|
||||
typedef unsigned char uint1; // assumes char is 1 word long
|
||||
|
||||
// how many bytes to grab at a time when checking files
|
||||
static const int BLOCK_LEN;
|
||||
|
||||
public:
|
||||
// methods for controlled operation:
|
||||
LLMD5 (); // simple initializer
|
||||
void update (const uint1 *input, const size_t input_length);
|
||||
void update (const uint8_t *input, const size_t input_length);
|
||||
void update (std::istream& stream);
|
||||
void update (FILE *file);
|
||||
void update (const std::string& str);
|
||||
|
|
@ -109,19 +106,19 @@ private:
|
|||
|
||||
|
||||
// next, the private data:
|
||||
uint4 state[4];
|
||||
uint32_t state[4];
|
||||
uint64_t count; // number of *bits*, mod 2^64
|
||||
uint1 buffer[64]; // input buffer
|
||||
uint1 digest[16];
|
||||
uint1 finalized;
|
||||
uint8_t buffer[64]; // input buffer
|
||||
uint8_t digest[16];
|
||||
uint8_t finalized;
|
||||
|
||||
// last, the private methods, mostly static:
|
||||
void init (); // called by all constructors
|
||||
void transform (const uint1 *buffer); // does the real update work. Note
|
||||
void transform (const uint8_t *buffer); // does the real update work. Note
|
||||
// that length is implied to be 64.
|
||||
|
||||
static void encode (uint1 *dest, const uint4 *src, const size_t length);
|
||||
static void decode (uint4 *dest, const uint1 *src, const size_t length);
|
||||
static void encode (uint8_t *dest, const uint32_t *src, const size_t length);
|
||||
static void decode (uint32_t *dest, const uint8_t *src, const size_t length);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#endif
|
||||
|
||||
#include "lldate.h"
|
||||
#include "llmemorystream.h"
|
||||
#include "llsd.h"
|
||||
#include "llstring.h"
|
||||
#include "lluri.h"
|
||||
|
|
@ -64,6 +65,23 @@ const std::string LLSD_NOTATION_HEADER("llsd/notation");
|
|||
#define windowBits 15
|
||||
#define ENABLE_ZLIB_GZIP 32
|
||||
|
||||
// If we published this in llsdserialize.h, we could use it in the
|
||||
// implementation of LLSDOStreamer's operator<<().
|
||||
template <class Formatter>
|
||||
void format_using(const LLSD& data, std::ostream& ostr,
|
||||
LLSDFormatter::EFormatterOptions options=LLSDFormatter::OPTIONS_PRETTY_BINARY)
|
||||
{
|
||||
LLPointer<Formatter> f{ new Formatter };
|
||||
f->format(data, ostr, options);
|
||||
}
|
||||
|
||||
template <class Parser>
|
||||
S32 parse_using(std::istream& istr, LLSD& data, size_t max_bytes, S32 max_depth=-1)
|
||||
{
|
||||
LLPointer<Parser> p{ new Parser };
|
||||
return p->parse(istr, data, max_bytes, max_depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* LLSDSerialize
|
||||
*/
|
||||
|
|
@ -86,10 +104,10 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
|
|||
f = new LLSDXMLFormatter;
|
||||
break;
|
||||
|
||||
case LLSD_NOTATION:
|
||||
str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
|
||||
f = new LLSDNotationFormatter;
|
||||
break;
|
||||
case LLSD_NOTATION:
|
||||
str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
|
||||
f = new LLSDNotationFormatter;
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
|
||||
|
|
@ -104,18 +122,37 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
|
|||
// static
|
||||
bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
|
||||
{
|
||||
LLPointer<LLSDParser> p = NULL;
|
||||
char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
|
||||
int i;
|
||||
int inbuf = 0;
|
||||
bool legacy_no_header = false;
|
||||
bool fail_if_not_legacy = false;
|
||||
std::string header;
|
||||
|
||||
/*
|
||||
* Get the first line before anything.
|
||||
*/
|
||||
str.get(hdr_buf, MAX_HDR_LEN, '\n');
|
||||
/*
|
||||
* Get the first line before anything. Don't read more than max_bytes:
|
||||
* this get() overload reads no more than (count-1) bytes into the
|
||||
* specified buffer. In the usual case when max_bytes exceeds
|
||||
* sizeof(hdr_buf), get() will read no more than sizeof(hdr_buf)-2.
|
||||
*/
|
||||
llssize max_hdr_read = MAX_HDR_LEN;
|
||||
if (max_bytes != LLSDSerialize::SIZE_UNLIMITED)
|
||||
{
|
||||
max_hdr_read = llmin(max_bytes + 1, max_hdr_read);
|
||||
}
|
||||
str.get(hdr_buf, max_hdr_read, '\n');
|
||||
auto inbuf = str.gcount();
|
||||
|
||||
// https://en.cppreference.com/w/cpp/io/basic_istream/get
|
||||
// When the get() above sees the specified delimiter '\n', it stops there
|
||||
// without pulling it from the stream. If it turns out that the stream
|
||||
// does NOT contain a header, and the content includes meaningful '\n',
|
||||
// it's important to pull that into hdr_buf too.
|
||||
if (inbuf < max_bytes && str.get(hdr_buf[inbuf]))
|
||||
{
|
||||
// got the delimiting '\n'
|
||||
++inbuf;
|
||||
// None of the following requires that hdr_buf contain a final '\0'
|
||||
// byte. We could store one if needed, since even the incremented
|
||||
// inbuf won't exceed sizeof(hdr_buf)-1, but there's no need.
|
||||
}
|
||||
std::string header{ hdr_buf, static_cast<std::string::size_type>(inbuf) };
|
||||
if (str.fail())
|
||||
{
|
||||
str.clear();
|
||||
|
|
@ -123,79 +160,97 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes)
|
|||
}
|
||||
|
||||
if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
|
||||
{
|
||||
legacy_no_header = true;
|
||||
inbuf = (int)str.gcount();
|
||||
{ // Create a LLSD XML parser, and parse the first chunk read above.
|
||||
LLSDXMLParser x;
|
||||
x.parsePart(hdr_buf, inbuf); // Parse the first part that was already read
|
||||
auto parsed = x.parse(str, sd, max_bytes - inbuf); // Parse the rest of it
|
||||
// Formally we should probably check (parsed != PARSE_FAILURE &&
|
||||
// parsed > 0), but since PARSE_FAILURE is -1, this suffices.
|
||||
return (parsed > 0);
|
||||
}
|
||||
else
|
||||
|
||||
if (fail_if_not_legacy)
|
||||
{
|
||||
if (fail_if_not_legacy)
|
||||
goto fail;
|
||||
/*
|
||||
* Remove the newline chars
|
||||
*/
|
||||
for (i = 0; i < MAX_HDR_LEN; i++)
|
||||
{
|
||||
if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
|
||||
hdr_buf[i] == '\n')
|
||||
{
|
||||
hdr_buf[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
header = hdr_buf;
|
||||
LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string::size_type start = std::string::npos;
|
||||
std::string::size_type end = std::string::npos;
|
||||
start = header.find_first_not_of("<? ");
|
||||
if (start != std::string::npos)
|
||||
{
|
||||
end = header.find_first_of(" ?", start);
|
||||
}
|
||||
if ((start == std::string::npos) || (end == std::string::npos))
|
||||
goto fail;
|
||||
/*
|
||||
* Remove the newline chars
|
||||
*/
|
||||
std::string::size_type lastchar = header.find_last_not_of("\r\n");
|
||||
if (lastchar != std::string::npos)
|
||||
{
|
||||
// It's important that find_last_not_of() returns size_type, which is
|
||||
// why lastchar explicitly declares the type above. erase(size_type)
|
||||
// erases from that offset to the end of the string, whereas
|
||||
// erase(iterator) erases only a single character.
|
||||
header.erase(lastchar+1);
|
||||
}
|
||||
|
||||
header = header.substr(start, end - start);
|
||||
ws(str);
|
||||
// trim off the <? ... ?> header syntax
|
||||
auto start = header.find_first_not_of("<? ");
|
||||
if (start != std::string::npos)
|
||||
{
|
||||
auto end = header.find_first_of(" ?", start);
|
||||
if (end != std::string::npos)
|
||||
{
|
||||
header = header.substr(start, end - start);
|
||||
ws(str);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Create the parser as appropriate
|
||||
*/
|
||||
if (legacy_no_header)
|
||||
{ // Create a LLSD XML parser, and parse the first chunk read above
|
||||
LLSDXMLParser* x = new LLSDXMLParser();
|
||||
x->parsePart(hdr_buf, inbuf); // Parse the first part that was already read
|
||||
x->parseLines(str, sd); // Parse the rest of it
|
||||
delete x;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (header == LLSD_BINARY_HEADER)
|
||||
if (0 == LLStringUtil::compareInsensitive(header, LLSD_BINARY_HEADER))
|
||||
{
|
||||
p = new LLSDBinaryParser;
|
||||
return (parse_using<LLSDBinaryParser>(str, sd, max_bytes-inbuf) > 0);
|
||||
}
|
||||
else if (header == LLSD_XML_HEADER)
|
||||
else if (0 == LLStringUtil::compareInsensitive(header, LLSD_XML_HEADER))
|
||||
{
|
||||
p = new LLSDXMLParser;
|
||||
return (parse_using<LLSDXMLParser>(str, sd, max_bytes-inbuf) > 0);
|
||||
}
|
||||
else if (header == LLSD_NOTATION_HEADER)
|
||||
else if (0 == LLStringUtil::compareInsensitive(header, LLSD_NOTATION_HEADER))
|
||||
{
|
||||
p = new LLSDNotationParser;
|
||||
return (parse_using<LLSDNotationParser>(str, sd, max_bytes-inbuf) > 0);
|
||||
}
|
||||
else
|
||||
else // no header we recognize
|
||||
{
|
||||
LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
|
||||
LLPointer<LLSDParser> p;
|
||||
if (inbuf && hdr_buf[0] == '<')
|
||||
{
|
||||
// looks like XML
|
||||
LL_DEBUGS() << "deserialize request with no header, assuming XML" << LL_ENDL;
|
||||
p = new LLSDXMLParser;
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume notation
|
||||
LL_DEBUGS() << "deserialize request with no header, assuming notation" << LL_ENDL;
|
||||
p = new LLSDNotationParser;
|
||||
}
|
||||
// Since we've already read 'inbuf' bytes into 'hdr_buf', prepend that
|
||||
// data to whatever remains in 'str'.
|
||||
LLMemoryStreamBuf already(reinterpret_cast<const U8*>(hdr_buf), inbuf);
|
||||
cat_streambuf prebuff(&already, str.rdbuf());
|
||||
std::istream prepend(&prebuff);
|
||||
#if 1
|
||||
return (p->parse(prepend, sd, max_bytes) > 0);
|
||||
#else
|
||||
// debugging the reconstituted 'prepend' stream
|
||||
// allocate a buffer that we hope is big enough for the whole thing
|
||||
std::vector<char> wholemsg((max_bytes == size_t(SIZE_UNLIMITED))? 1024 : max_bytes);
|
||||
prepend.read(wholemsg.data(), std::min(max_bytes, wholemsg.size()));
|
||||
LLMemoryStream replay(reinterpret_cast<const U8*>(wholemsg.data()), prepend.gcount());
|
||||
auto success{ p->parse(replay, sd, prepend.gcount()) > 0 };
|
||||
{
|
||||
LL_DEBUGS() << (success? "parsed: $$" : "failed: '")
|
||||
<< std::string(wholemsg.data(), llmin(prepend.gcount(), 100)) << "$$"
|
||||
<< LL_ENDL;
|
||||
}
|
||||
return success;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p.notNull())
|
||||
{
|
||||
p->parse(str, sd, max_bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
fail:
|
||||
LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2388,7 +2443,7 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size
|
|||
return result;
|
||||
}
|
||||
|
||||
char* strip_deprecated_header(char* in, llssize& cur_size, size_t* header_size)
|
||||
char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size)
|
||||
{
|
||||
const char* deprecated_header = "<? LLSD/Binary ?>";
|
||||
constexpr size_t deprecated_header_size = 17;
|
||||
|
|
|
|||
|
|
@ -873,5 +873,5 @@ LL_COMMON_API std::string zip_llsd(LLSD& data);
|
|||
LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, size_t& outsize,std::istream& is, S32 size);
|
||||
|
||||
// returns a pointer to the array or past the array if the deprecated header exists
|
||||
LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, size_t* header_size = nullptr);
|
||||
LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size = nullptr);
|
||||
#endif // LL_LLSDSERIALIZE_H
|
||||
|
|
|
|||
|
|
@ -513,3 +513,29 @@ std::istream& operator>>(std::istream& str, const char *tocheck)
|
|||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
int cat_streambuf::underflow()
|
||||
{
|
||||
if (gptr() == egptr())
|
||||
{
|
||||
// here because our buffer is empty
|
||||
std::streamsize size = 0;
|
||||
// Until we've run out of mInputs, try reading the first of them
|
||||
// into mBuffer. If that fetches some characters, break the loop.
|
||||
while (! mInputs.empty()
|
||||
&& ! (size = mInputs.front()->sgetn(mBuffer.data(), mBuffer.size())))
|
||||
{
|
||||
// We tried to read mInputs.front() but got zero characters.
|
||||
// Discard the first streambuf and try the next one.
|
||||
mInputs.pop_front();
|
||||
}
|
||||
// Either we ran out of mInputs or we succeeded in reading some
|
||||
// characters, that is, size != 0. Tell base class what we have.
|
||||
setg(mBuffer.data(), mBuffer.data(), mBuffer.data() + size);
|
||||
}
|
||||
// If we fell out of the above loop with mBuffer still empty, return
|
||||
// eof(), otherwise return the next character.
|
||||
return (gptr() == egptr())
|
||||
? std::char_traits<char>::eof()
|
||||
: std::char_traits<char>::to_int_type(*gptr());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@
|
|||
#ifndef LL_STREAM_TOOLS_H
|
||||
#define LL_STREAM_TOOLS_H
|
||||
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// unless specifed otherwise these all return input_stream.good()
|
||||
|
||||
|
|
@ -113,6 +115,27 @@ LL_COMMON_API std::streamsize fullread(
|
|||
|
||||
LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);
|
||||
|
||||
/**
|
||||
* cat_streambuf is a std::streambuf subclass that accepts a variadic number
|
||||
* of std::streambuf* (e.g. some_istream.rdbuf()) and virtually concatenates
|
||||
* their contents.
|
||||
*/
|
||||
// derived from https://stackoverflow.com/a/49441066/5533635
|
||||
class cat_streambuf: public std::streambuf
|
||||
{
|
||||
private:
|
||||
std::deque<std::streambuf*> mInputs;
|
||||
std::vector<char> mBuffer;
|
||||
|
||||
public:
|
||||
// only valid for std::streambuf* arguments
|
||||
template <typename... Inputs>
|
||||
cat_streambuf(Inputs... inputs):
|
||||
mInputs{inputs...},
|
||||
mBuffer(1024)
|
||||
{}
|
||||
|
||||
int underflow() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -577,10 +577,12 @@ S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
|
|||
// PeriodicRecording
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state)
|
||||
PeriodicRecording::PeriodicRecording( size_t num_periods, EPlayState state)
|
||||
: mAutoResize(num_periods == 0),
|
||||
mCurPeriod(0),
|
||||
mNumRecordedPeriods(0),
|
||||
// This guarantee that mRecordingPeriods cannot be empty is essential for
|
||||
// code in several methods.
|
||||
mRecordingPeriods(num_periods ? num_periods : 1)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
|
|
@ -596,18 +598,19 @@ PeriodicRecording::~PeriodicRecording()
|
|||
|
||||
void PeriodicRecording::nextPeriod()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
if (mAutoResize)
|
||||
{
|
||||
mRecordingPeriods.push_back(Recording());
|
||||
}
|
||||
|
||||
Recording& old_recording = getCurRecording();
|
||||
mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
|
||||
inci(mCurPeriod);
|
||||
old_recording.splitTo(getCurRecording());
|
||||
|
||||
mNumRecordedPeriods = mRecordingPeriods.empty()? 0 :
|
||||
llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
|
||||
// Since mRecordingPeriods always has at least one entry, we can always
|
||||
// safely subtract 1 from its size().
|
||||
mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
|
||||
}
|
||||
|
||||
void PeriodicRecording::appendRecording(Recording& recording)
|
||||
|
|
@ -620,31 +623,29 @@ void PeriodicRecording::appendRecording(Recording& recording)
|
|||
|
||||
void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
if (other.mRecordingPeriods.empty()) return;
|
||||
|
||||
getCurRecording().update();
|
||||
other.getCurRecording().update();
|
||||
|
||||
const auto other_recording_slots = other.mRecordingPeriods.size();
|
||||
|
||||
const auto other_num_recordings = other.getNumRecordedPeriods();
|
||||
const auto other_current_recording_index = other.mCurPeriod;
|
||||
const auto other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots;
|
||||
const auto other_oldest_recording_index = other.previ(other_current_recording_index, other_num_recordings);
|
||||
|
||||
// append first recording into our current slot
|
||||
getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
|
||||
|
||||
// from now on, add new recordings for everything after the first
|
||||
auto other_index = (other_oldest_recording_index + 1) % other_recording_slots;
|
||||
auto other_index = other.nexti(other_oldest_recording_index);
|
||||
|
||||
if (mAutoResize)
|
||||
{
|
||||
// push back recordings for everything in the middle
|
||||
auto other_index = (other_oldest_recording_index + 1) % other_recording_slots;
|
||||
while (other_index != other_current_recording_index)
|
||||
{
|
||||
mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
|
||||
other_index = (other_index + 1) % other_recording_slots;
|
||||
other.inci(other_index);
|
||||
}
|
||||
|
||||
// add final recording, if it wasn't already added as the first
|
||||
|
|
@ -653,36 +654,25 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
|
|||
mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
|
||||
}
|
||||
|
||||
mCurPeriod = mRecordingPeriods.empty()? 0 : mRecordingPeriods.size() - 1;
|
||||
// mRecordingPeriods is never empty()
|
||||
mCurPeriod = mRecordingPeriods.size() - 1;
|
||||
mNumRecordedPeriods = mCurPeriod;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 num_to_copy = llmin((S32)mRecordingPeriods.size(), (S32)other_num_recordings);
|
||||
|
||||
std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
|
||||
std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod;
|
||||
|
||||
auto num_to_copy = llmin(mRecordingPeriods.size(), other_num_recordings);
|
||||
// already consumed the first recording from other, so start counting at 1
|
||||
for(S32 i = 1; i < num_to_copy; i++)
|
||||
for (size_t n = 1, srci = other_index, dsti = mCurPeriod;
|
||||
n < num_to_copy;
|
||||
++n, other.inci(srci), inci(dsti))
|
||||
{
|
||||
*dest_it = *src_it;
|
||||
|
||||
if (++src_it == other.mRecordingPeriods.end())
|
||||
{
|
||||
src_it = other.mRecordingPeriods.begin();
|
||||
}
|
||||
|
||||
if (++dest_it == mRecordingPeriods.end())
|
||||
{
|
||||
dest_it = mRecordingPeriods.begin();
|
||||
}
|
||||
mRecordingPeriods[dsti] = other.mRecordingPeriods[srci];
|
||||
}
|
||||
|
||||
|
||||
// want argument to % to be positive, otherwise result could be negative and thus out of bounds
|
||||
llassert(num_to_copy >= 1);
|
||||
// advance to last recording period copied, and make that our current period
|
||||
mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
|
||||
inci(mCurPeriod, num_to_copy - 1);
|
||||
mNumRecordedPeriods = llmin(mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
|
||||
}
|
||||
|
||||
|
|
@ -694,13 +684,11 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
|
|||
|
||||
F64Seconds PeriodicRecording::getDuration() const
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
F64Seconds duration;
|
||||
auto num_periods = mRecordingPeriods.size();
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
for (size_t n = 0; n < mRecordingPeriods.size(); ++n)
|
||||
{
|
||||
auto index = (mCurPeriod + num_periods - i) % num_periods;
|
||||
duration += mRecordingPeriods[index].getDuration();
|
||||
duration += mRecordingPeriods[nexti(mCurPeriod, n)].getDuration();
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
|
@ -737,16 +725,14 @@ const Recording& PeriodicRecording::getCurRecording() const
|
|||
|
||||
Recording& PeriodicRecording::getPrevRecording( size_t offset )
|
||||
{
|
||||
auto num_periods = mRecordingPeriods.size();
|
||||
offset = llclamp(offset, 0, num_periods - 1);
|
||||
return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
|
||||
// reuse const implementation, but return non-const reference
|
||||
return const_cast<Recording&>(
|
||||
const_cast<const PeriodicRecording*>(this)->getPrevRecording(offset));
|
||||
}
|
||||
|
||||
const Recording& PeriodicRecording::getPrevRecording( size_t offset ) const
|
||||
{
|
||||
auto num_periods = mRecordingPeriods.size();
|
||||
offset = llclamp(offset, 0, num_periods - 1);
|
||||
return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
|
||||
return mRecordingPeriods[previ(mCurPeriod, offset)];
|
||||
}
|
||||
|
||||
void PeriodicRecording::handleStart()
|
||||
|
|
@ -789,14 +775,14 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
|
|||
getCurRecording().splitTo(other.getCurRecording());
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
bool has_value = false;
|
||||
F64 min_val = std::numeric_limits<F64>::max();
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -811,14 +797,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, siz
|
|||
: NaN;
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
bool has_value = false;
|
||||
F64 max_val = std::numeric_limits<F64>::min();
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -834,7 +820,7 @@ F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, siz
|
|||
}
|
||||
|
||||
// calculates means using aggregates per period
|
||||
F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
|
@ -842,7 +828,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, si
|
|||
F64 mean = 0;
|
||||
S32 valid_period_count = 0;
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -857,7 +843,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, si
|
|||
: NaN;
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
|
@ -866,7 +852,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
|
|||
F64 sum_of_squares = 0;
|
||||
S32 valid_period_count = 0;
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -882,14 +868,14 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
|
|||
: NaN;
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
bool has_value = false;
|
||||
F64 min_val = std::numeric_limits<F64>::max();
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -904,14 +890,14 @@ F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, si
|
|||
: NaN;
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/)
|
||||
F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
bool has_value = false;
|
||||
F64 max_val = std::numeric_limits<F64>::min();
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -927,7 +913,7 @@ F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, siz
|
|||
}
|
||||
|
||||
|
||||
F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
|
@ -935,7 +921,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, s
|
|||
S32 valid_period_count = 0;
|
||||
F64 mean = 0;
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -950,13 +936,13 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, s
|
|||
: NaN;
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
std::vector<F64> buf;
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.getDuration() > (F32Seconds)0.f)
|
||||
|
|
@ -976,7 +962,7 @@ F64 PeriodicRecording::getPeriodMedian( const StatType<SampleAccumulator>& stat,
|
|||
return F64((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
|
||||
}
|
||||
|
||||
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
|
@ -985,7 +971,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
|
|||
S32 valid_period_count = 0;
|
||||
F64 sum_of_squares = 0;
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -1002,13 +988,13 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
|
|||
}
|
||||
|
||||
|
||||
F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
F64Kilobytes min_val(std::numeric_limits<F64>::max());
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
min_val = llmin(min_val, recording.getMin(stat));
|
||||
|
|
@ -1022,13 +1008,13 @@ F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t n
|
|||
return getPeriodMin(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
|
||||
}
|
||||
|
||||
F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/)
|
||||
F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
F64Kilobytes max_val(0.0);
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
max_val = llmax(max_val, recording.getMax(stat));
|
||||
|
|
@ -1042,14 +1028,14 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t n
|
|||
return getPeriodMax(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
|
||||
}
|
||||
|
||||
F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
F64Kilobytes mean(0);
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
mean += recording.getMean(stat);
|
||||
|
|
@ -1063,7 +1049,7 @@ F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t
|
|||
return getPeriodMean(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
|
||||
}
|
||||
|
||||
F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, size_t num_periods /*= S32_MAX*/ )
|
||||
F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, size_t num_periods /*= std::numeric_limits<size_t>::max()*/ )
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
|
@ -1072,7 +1058,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAc
|
|||
S32 valid_period_count = 0;
|
||||
F64 sum_of_squares = 0;
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "lltraceaccumulators.h"
|
||||
#include "llpointer.h"
|
||||
#include <limits>
|
||||
|
||||
class LLStopWatchControlsMixinCommon
|
||||
{
|
||||
|
|
@ -330,7 +331,7 @@ namespace LLTrace
|
|||
: public LLStopWatchControlsMixin<PeriodicRecording>
|
||||
{
|
||||
public:
|
||||
PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
|
||||
PeriodicRecording(size_t num_periods, EPlayState state = STOPPED);
|
||||
~PeriodicRecording();
|
||||
|
||||
void nextPeriod();
|
||||
|
|
@ -353,7 +354,7 @@ namespace LLTrace
|
|||
Recording snapshotCurRecording() const;
|
||||
|
||||
template <typename T>
|
||||
auto getSampleCount(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
auto getSampleCount(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
|
@ -373,14 +374,14 @@ namespace LLTrace
|
|||
|
||||
// catch all for stats that have a defined sum
|
||||
template <typename T>
|
||||
typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename T::value_t getPeriodMin(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
bool has_value = false;
|
||||
typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max());
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -396,39 +397,39 @@ namespace LLTrace
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMin(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMin(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
min_val = llmin(min_val, recording.getPerSec(stat));
|
||||
|
|
@ -437,7 +438,7 @@ namespace LLTrace
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
|
|
@ -449,14 +450,14 @@ namespace LLTrace
|
|||
|
||||
// catch all for stats that have a defined sum
|
||||
template <typename T>
|
||||
typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename T::value_t getPeriodMax(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
bool has_value = false;
|
||||
typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min());
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.hasValue(stat))
|
||||
|
|
@ -472,39 +473,39 @@ namespace LLTrace
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMax(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMax(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
F64 max_val = std::numeric_limits<F64>::min();
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
max_val = llmax(max_val, recording.getPerSec(stat));
|
||||
|
|
@ -513,7 +514,7 @@ namespace LLTrace
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
|
|
@ -525,14 +526,14 @@ namespace LLTrace
|
|||
|
||||
// catch all for stats that have a defined sum
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.getDuration() > (F32Seconds)0.f)
|
||||
|
|
@ -546,39 +547,39 @@ namespace LLTrace
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMean(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMean(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
|
||||
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.getDuration() > (F32Seconds)0.f)
|
||||
|
|
@ -593,64 +594,64 @@ namespace LLTrace
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodMedian( const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = S32_MAX)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.getDuration() > (F32Seconds)0.f)
|
||||
{
|
||||
buf.push_back(recording.getPerSec(stat));
|
||||
}
|
||||
}
|
||||
std::sort(buf.begin(), buf.end());
|
||||
std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
|
||||
for (size_t i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.getDuration() > (F32Seconds)0.f)
|
||||
{
|
||||
buf.push_back(recording.getPerSec(stat));
|
||||
}
|
||||
}
|
||||
std::sort(buf.begin(), buf.end());
|
||||
|
||||
return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
|
||||
}
|
||||
return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
//
|
||||
// PERIODIC STANDARD DEVIATION
|
||||
//
|
||||
|
||||
F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = S32_MAX)
|
||||
typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = std::numeric_limits<size_t>::max())
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS;
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = S32_MAX);
|
||||
F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = std::numeric_limits<size_t>::max());
|
||||
|
||||
private:
|
||||
// implementation for LLStopWatchControlsMixin
|
||||
|
|
@ -659,6 +660,35 @@ namespace LLTrace
|
|||
/*virtual*/ void handleReset();
|
||||
/*virtual*/ void handleSplitTo(PeriodicRecording& other);
|
||||
|
||||
// helper methods for wraparound ring-buffer arithmetic
|
||||
inline
|
||||
size_t wrapi(size_t i) const
|
||||
{
|
||||
return i % mRecordingPeriods.size();
|
||||
}
|
||||
|
||||
inline
|
||||
size_t nexti(size_t i, size_t offset=1) const
|
||||
{
|
||||
return wrapi(i + offset);
|
||||
}
|
||||
|
||||
inline
|
||||
size_t previ(size_t i, size_t offset=1) const
|
||||
{
|
||||
auto num_periods = mRecordingPeriods.size();
|
||||
// constrain offset
|
||||
offset = llclamp(offset, 0, num_periods - 1);
|
||||
// add size() so expression can't go (unsigned) "negative"
|
||||
return wrapi(i + num_periods - offset);
|
||||
}
|
||||
|
||||
inline
|
||||
void inci(size_t& i, size_t offset=1) const
|
||||
{
|
||||
i = nexti(i, offset);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Recording> mRecordingPeriods;
|
||||
const bool mAutoResize;
|
||||
|
|
|
|||
|
|
@ -885,7 +885,7 @@ U32 LLUUID::getRandomSeed()
|
|||
seed[7] = (unsigned char)(pid);
|
||||
getSystemTime((uuid_time_t*)(&seed[8]));
|
||||
|
||||
U64 seed64 = HBXXH64((const void*)seed, 16).digest();
|
||||
U64 seed64 = HBXXH64::digest((const void*)seed, 16);
|
||||
return U32(seed64) ^ U32(seed64 >> 32);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,14 @@ public:
|
|||
U16 getCRC16() const;
|
||||
U32 getCRC32() const;
|
||||
|
||||
// Returns a 64 bits digest of the UUID, by XORing its two 64 bits long
|
||||
// words. HB
|
||||
inline U64 getDigest64() const
|
||||
{
|
||||
U64* tmp = (U64*)mData;
|
||||
return tmp[0] ^ tmp[1];
|
||||
}
|
||||
|
||||
static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.
|
||||
|
||||
static const LLUUID null;
|
||||
|
|
@ -165,36 +173,22 @@ public:
|
|||
LLAssetID makeAssetID(const LLUUID& session) const;
|
||||
};
|
||||
|
||||
// Generate a hash of an LLUUID object using the boost hash templates.
|
||||
template <>
|
||||
struct boost::hash<LLUUID>
|
||||
{
|
||||
typedef LLUUID argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type const& s) const
|
||||
{
|
||||
result_type seed(0);
|
||||
|
||||
for (S32 i = 0; i < UUID_BYTES; ++i)
|
||||
{
|
||||
boost::hash_combine(seed, s.mData[i]);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
// Adapt boost hash to std hash
|
||||
// std::hash implementation for LLUUID
|
||||
namespace std
|
||||
{
|
||||
template<> struct hash<LLUUID>
|
||||
{
|
||||
std::size_t operator()(LLUUID const& s) const noexcept
|
||||
{
|
||||
return boost::hash<LLUUID>()(s);
|
||||
}
|
||||
};
|
||||
template<> struct hash<LLUUID>
|
||||
{
|
||||
inline size_t operator()(const LLUUID& id) const noexcept
|
||||
{
|
||||
return (size_t)id.getDigest64();
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
// For use with boost containers.
|
||||
inline size_t hash_value(const LLUUID& id) noexcept
|
||||
{
|
||||
return (size_t)id.getDigest64();
|
||||
}
|
||||
|
||||
#endif // LL_LLUUID_H
|
||||
|
|
|
|||
|
|
@ -109,7 +109,12 @@ namespace tut
|
|||
"import os\n"
|
||||
"import sys\n"
|
||||
"\n"
|
||||
"import llsd\n"
|
||||
"try:\n"
|
||||
// new freestanding llsd package
|
||||
" import llsd\n"
|
||||
"except ImportError:\n"
|
||||
// older llbase.llsd module
|
||||
" from llbase import llsd\n"
|
||||
"\n"
|
||||
"class ProtocolError(Exception):\n"
|
||||
" def __init__(self, msg, data):\n"
|
||||
|
|
@ -120,26 +125,26 @@ namespace tut
|
|||
" pass\n"
|
||||
"\n"
|
||||
"def get():\n"
|
||||
" hdr = ''\n"
|
||||
" while ':' not in hdr and len(hdr) < 20:\n"
|
||||
" hdr += sys.stdin.read(1)\n"
|
||||
" hdr = []\n"
|
||||
" while b':' not in hdr and len(hdr) < 20:\n"
|
||||
" hdr.append(sys.stdin.buffer.read(1))\n"
|
||||
" if not hdr:\n"
|
||||
" sys.exit(0)\n"
|
||||
" if not hdr.endswith(':'):\n"
|
||||
" if not hdr[-1] == b':':\n"
|
||||
" raise ProtocolError('Expected len:data, got %r' % hdr, hdr)\n"
|
||||
" try:\n"
|
||||
" length = int(hdr[:-1])\n"
|
||||
" length = int(b''.join(hdr[:-1]))\n"
|
||||
" except ValueError:\n"
|
||||
" raise ProtocolError('Non-numeric len %r' % hdr[:-1], hdr[:-1])\n"
|
||||
" parts = []\n"
|
||||
" received = 0\n"
|
||||
" while received < length:\n"
|
||||
" parts.append(sys.stdin.read(length - received))\n"
|
||||
" parts.append(sys.stdin.buffer.read(length - received))\n"
|
||||
" received += len(parts[-1])\n"
|
||||
" data = ''.join(parts)\n"
|
||||
" data = b''.join(parts)\n"
|
||||
" assert len(data) == length\n"
|
||||
" try:\n"
|
||||
" return llsd.parse(data.encode())\n"
|
||||
" return llsd.parse(data)\n"
|
||||
// Seems the old indra.base.llsd module didn't properly
|
||||
// convert IndexError (from running off end of string) to
|
||||
// LLSDParseError.
|
||||
|
|
@ -179,11 +184,11 @@ namespace tut
|
|||
" return _reply\n"
|
||||
"\n"
|
||||
"def put(req):\n"
|
||||
" sys.stdout.write(':'.join((str(len(req)), req)))\n"
|
||||
" sys.stdout.buffer.write(b'%d:%b' % (len(req), req))\n"
|
||||
" sys.stdout.flush()\n"
|
||||
"\n"
|
||||
"def send(pump, data):\n"
|
||||
" put(llsd.format_notation(dict(pump=pump, data=data)).decode())\n"
|
||||
" put(llsd.format_notation(dict(pump=pump, data=data)))\n"
|
||||
"\n"
|
||||
"def request(pump, data):\n"
|
||||
" # we expect 'data' is a dict\n"
|
||||
|
|
|
|||
|
|
@ -46,20 +46,24 @@ typedef U32 uint32_t;
|
|||
|
||||
#include "boost/range.hpp"
|
||||
#include "boost/foreach.hpp"
|
||||
#include "boost/function.hpp"
|
||||
#include "boost/bind.hpp"
|
||||
#include "boost/phoenix/bind/bind_function.hpp"
|
||||
#include "boost/phoenix/core/argument.hpp"
|
||||
using namespace boost::phoenix;
|
||||
|
||||
#include "../llsd.h"
|
||||
#include "../llsdserialize.h"
|
||||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llsdutil.h"
|
||||
#include "../llformat.h"
|
||||
#include "llformat.h"
|
||||
#include "llmemorystream.h"
|
||||
|
||||
#include "../test/lltut.h"
|
||||
#include "../test/namedtempfile.h"
|
||||
#include "stringize.h"
|
||||
#include <functional>
|
||||
|
||||
typedef std::function<void(const LLSD& data, std::ostream& str)> FormatterFunction;
|
||||
typedef std::function<bool(std::istream& istr, LLSD& data, llssize max_bytes)> ParserFunction;
|
||||
|
||||
std::vector<U8> string_to_vector(const std::string& str)
|
||||
{
|
||||
|
|
@ -112,7 +116,7 @@ namespace tut
|
|||
mSD = LLUUID::null;
|
||||
expected = "<llsd><uuid /></llsd>\n";
|
||||
xml_test("null uuid", expected);
|
||||
|
||||
|
||||
mSD = LLUUID("c96f9b1e-f589-4100-9774-d98643ce0bed");
|
||||
expected = "<llsd><uuid>c96f9b1e-f589-4100-9774-d98643ce0bed</uuid></llsd>\n";
|
||||
xml_test("uuid", expected);
|
||||
|
|
@ -136,7 +140,7 @@ namespace tut
|
|||
expected = "<llsd><binary encoding=\"base64\">aGVsbG8=</binary></llsd>\n";
|
||||
xml_test("binary", expected);
|
||||
}
|
||||
|
||||
|
||||
template<> template<>
|
||||
void sd_xml_object::test<2>()
|
||||
{
|
||||
|
|
@ -225,7 +229,7 @@ namespace tut
|
|||
expected = "<llsd><map><key>baz</key><undef /><key>foo</key><string>bar</string></map></llsd>\n";
|
||||
xml_test("2 element map", expected);
|
||||
}
|
||||
|
||||
|
||||
template<> template<>
|
||||
void sd_xml_object::test<6>()
|
||||
{
|
||||
|
|
@ -241,7 +245,7 @@ namespace tut
|
|||
expected = "<llsd><binary encoding=\"base64\">Nnw2fGFzZGZoYXBweWJveHw2MGU0NGVjNS0zMDVjLTQzYzItOWExOS1iNGI4OWIxYWUyYTZ8NjBlNDRlYzUtMzA1Yy00M2MyLTlhMTktYjRiODliMWFlMmE2fDYwZTQ0ZWM1LTMwNWMtNDNjMi05YTE5LWI0Yjg5YjFhZTJhNnwwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDB8N2ZmZmZmZmZ8N2ZmZmZmZmZ8MHwwfDgyMDAwfDQ1MGZlMzk0LTI5MDQtYzlhZC0yMTRjLWEwN2ViN2ZlZWMyOXwoTm8gRGVzY3JpcHRpb24pfDB8MTB8MA==</binary></llsd>\n";
|
||||
xml_test("binary", expected);
|
||||
}
|
||||
|
||||
|
||||
class TestLLSDSerializeData
|
||||
{
|
||||
public:
|
||||
|
|
@ -250,9 +254,34 @@ namespace tut
|
|||
|
||||
void doRoundTripTests(const std::string&);
|
||||
void checkRoundTrip(const std::string&, const LLSD& v);
|
||||
|
||||
LLPointer<LLSDFormatter> mFormatter;
|
||||
LLPointer<LLSDParser> mParser;
|
||||
|
||||
void setFormatterParser(LLPointer<LLSDFormatter> formatter, LLPointer<LLSDParser> parser)
|
||||
{
|
||||
mFormatter = [formatter](const LLSD& data, std::ostream& str)
|
||||
{
|
||||
formatter->format(data, str);
|
||||
};
|
||||
// this lambda must be mutable since otherwise the bound 'parser'
|
||||
// is assumed to point to a const LLSDParser
|
||||
mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes) mutable
|
||||
{
|
||||
// reset() call is needed since test code re-uses parser object
|
||||
parser->reset();
|
||||
return (parser->parse(istr, data, max_bytes) > 0);
|
||||
};
|
||||
}
|
||||
|
||||
void setParser(bool (*parser)(LLSD&, std::istream&, llssize))
|
||||
{
|
||||
// why does LLSDSerialize::deserialize() reverse the parse() params??
|
||||
mParser = [parser](std::istream& istr, LLSD& data, llssize max_bytes)
|
||||
{
|
||||
return parser(data, istr, max_bytes);
|
||||
};
|
||||
}
|
||||
|
||||
FormatterFunction mFormatter;
|
||||
ParserFunction mParser;
|
||||
};
|
||||
|
||||
TestLLSDSerializeData::TestLLSDSerializeData()
|
||||
|
|
@ -265,12 +294,11 @@ namespace tut
|
|||
|
||||
void TestLLSDSerializeData::checkRoundTrip(const std::string& msg, const LLSD& v)
|
||||
{
|
||||
std::stringstream stream;
|
||||
mFormatter->format(v, stream);
|
||||
std::stringstream stream;
|
||||
mFormatter(v, stream);
|
||||
//LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
|
||||
LLSD w;
|
||||
mParser->reset(); // reset() call is needed since test code re-uses mParser
|
||||
mParser->parse(stream, w, stream.str().size());
|
||||
mParser(stream, w, stream.str().size());
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -299,52 +327,52 @@ namespace tut
|
|||
fillmap(root[key], width, depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestLLSDSerializeData::doRoundTripTests(const std::string& msg)
|
||||
{
|
||||
LLSD v;
|
||||
checkRoundTrip(msg + " undefined", v);
|
||||
|
||||
|
||||
v = true;
|
||||
checkRoundTrip(msg + " true bool", v);
|
||||
|
||||
|
||||
v = false;
|
||||
checkRoundTrip(msg + " false bool", v);
|
||||
|
||||
|
||||
v = 1;
|
||||
checkRoundTrip(msg + " positive int", v);
|
||||
|
||||
|
||||
v = 0;
|
||||
checkRoundTrip(msg + " zero int", v);
|
||||
|
||||
|
||||
v = -1;
|
||||
checkRoundTrip(msg + " negative int", v);
|
||||
|
||||
|
||||
v = 1234.5f;
|
||||
checkRoundTrip(msg + " positive float", v);
|
||||
|
||||
|
||||
v = 0.0f;
|
||||
checkRoundTrip(msg + " zero float", v);
|
||||
|
||||
|
||||
v = -1234.5f;
|
||||
checkRoundTrip(msg + " negative float", v);
|
||||
|
||||
|
||||
// FIXME: need a NaN test
|
||||
|
||||
|
||||
v = LLUUID::null;
|
||||
checkRoundTrip(msg + " null uuid", v);
|
||||
|
||||
|
||||
LLUUID newUUID;
|
||||
newUUID.generate();
|
||||
v = newUUID;
|
||||
checkRoundTrip(msg + " new uuid", v);
|
||||
|
||||
|
||||
v = "";
|
||||
checkRoundTrip(msg + " empty string", v);
|
||||
|
||||
|
||||
v = "some string";
|
||||
checkRoundTrip(msg + " non-empty string", v);
|
||||
|
||||
|
||||
v =
|
||||
"Second Life is a 3-D virtual world entirely built and owned by its residents. "
|
||||
"Since opening to the public in 2003, it has grown explosively and today is "
|
||||
|
|
@ -372,7 +400,7 @@ namespace tut
|
|||
for (U32 block = 0x000000; block <= 0x10ffff; block += block_size)
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
|
||||
for (U32 c = block; c < block + block_size; ++c)
|
||||
{
|
||||
if (c <= 0x000001f
|
||||
|
|
@ -386,7 +414,7 @@ namespace tut
|
|||
if (0x00fdd0 <= c && c <= 0x00fdef) { continue; }
|
||||
if ((c & 0x00fffe) == 0x00fffe) { continue; }
|
||||
// see Unicode standard, section 15.8
|
||||
|
||||
|
||||
if (c <= 0x00007f)
|
||||
{
|
||||
out << (char)(c & 0x7f);
|
||||
|
|
@ -410,55 +438,55 @@ namespace tut
|
|||
out << (char)(0x80 | ((c >> 0) & 0x3f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
v = out.str();
|
||||
|
||||
std::ostringstream blockmsg;
|
||||
blockmsg << msg << " unicode string block 0x" << std::hex << block;
|
||||
checkRoundTrip(blockmsg.str(), v);
|
||||
}
|
||||
|
||||
|
||||
LLDate epoch;
|
||||
v = epoch;
|
||||
checkRoundTrip(msg + " epoch date", v);
|
||||
|
||||
|
||||
LLDate aDay("2002-12-07T05:07:15.00Z");
|
||||
v = aDay;
|
||||
checkRoundTrip(msg + " date", v);
|
||||
|
||||
|
||||
LLURI path("http://slurl.com/secondlife/Ambleside/57/104/26/");
|
||||
v = path;
|
||||
checkRoundTrip(msg + " url", v);
|
||||
|
||||
|
||||
const char source[] = "it must be a blue moon again";
|
||||
std::vector<U8> data;
|
||||
// note, includes terminating '\0'
|
||||
copy(&source[0], &source[sizeof(source)], back_inserter(data));
|
||||
|
||||
|
||||
v = data;
|
||||
checkRoundTrip(msg + " binary", v);
|
||||
|
||||
|
||||
v = LLSD::emptyMap();
|
||||
checkRoundTrip(msg + " empty map", v);
|
||||
|
||||
|
||||
v = LLSD::emptyMap();
|
||||
v["name"] = "luke"; //v.insert("name", "luke");
|
||||
v["age"] = 3; //v.insert("age", 3);
|
||||
checkRoundTrip(msg + " map", v);
|
||||
|
||||
|
||||
v.clear();
|
||||
v["a"]["1"] = true;
|
||||
v["b"]["0"] = false;
|
||||
checkRoundTrip(msg + " nested maps", v);
|
||||
|
||||
|
||||
v = LLSD::emptyArray();
|
||||
checkRoundTrip(msg + " empty array", v);
|
||||
|
||||
|
||||
v = LLSD::emptyArray();
|
||||
v.append("ali");
|
||||
v.append(28);
|
||||
checkRoundTrip(msg + " array", v);
|
||||
|
||||
|
||||
v.clear();
|
||||
v[0][0] = true;
|
||||
v[1][0] = false;
|
||||
|
|
@ -468,7 +496,7 @@ namespace tut
|
|||
fillmap(v, 10, 3); // 10^6 maps
|
||||
checkRoundTrip(msg + " many nested maps", v);
|
||||
}
|
||||
|
||||
|
||||
typedef tut::test_group<TestLLSDSerializeData> TestLLSDSerializeGroup;
|
||||
typedef TestLLSDSerializeGroup::object TestLLSDSerializeObject;
|
||||
TestLLSDSerializeGroup gTestLLSDSerializeGroup("llsd serialization");
|
||||
|
|
@ -476,35 +504,106 @@ namespace tut
|
|||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<1>()
|
||||
{
|
||||
mFormatter = new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY);
|
||||
mParser = new LLSDNotationParser();
|
||||
setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_PRETTY_BINARY),
|
||||
new LLSDNotationParser());
|
||||
doRoundTripTests("pretty binary notation serialization");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<2>()
|
||||
{
|
||||
mFormatter = new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE);
|
||||
mParser = new LLSDNotationParser();
|
||||
setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
|
||||
new LLSDNotationParser());
|
||||
doRoundTripTests("raw binary notation serialization");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<3>()
|
||||
{
|
||||
mFormatter = new LLSDXMLFormatter();
|
||||
mParser = new LLSDXMLParser();
|
||||
setFormatterParser(new LLSDXMLFormatter(), new LLSDXMLParser());
|
||||
doRoundTripTests("xml serialization");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<4>()
|
||||
{
|
||||
mFormatter = new LLSDBinaryFormatter();
|
||||
mParser = new LLSDBinaryParser();
|
||||
setFormatterParser(new LLSDBinaryFormatter(), new LLSDBinaryParser());
|
||||
doRoundTripTests("binary serialization");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<5>()
|
||||
{
|
||||
mFormatter = [](const LLSD& sd, std::ostream& str)
|
||||
{
|
||||
LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_BINARY);
|
||||
};
|
||||
setParser(LLSDSerialize::deserialize);
|
||||
doRoundTripTests("serialize(LLSD_BINARY)");
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<6>()
|
||||
{
|
||||
mFormatter = [](const LLSD& sd, std::ostream& str)
|
||||
{
|
||||
LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_XML);
|
||||
};
|
||||
setParser(LLSDSerialize::deserialize);
|
||||
doRoundTripTests("serialize(LLSD_XML)");
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<7>()
|
||||
{
|
||||
mFormatter = [](const LLSD& sd, std::ostream& str)
|
||||
{
|
||||
LLSDSerialize::serialize(sd, str, LLSDSerialize::LLSD_NOTATION);
|
||||
};
|
||||
setParser(LLSDSerialize::deserialize);
|
||||
// In this test, serialize(LLSD_NOTATION) emits a header recognized by
|
||||
// deserialize().
|
||||
doRoundTripTests("serialize(LLSD_NOTATION)");
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<8>()
|
||||
{
|
||||
setFormatterParser(new LLSDNotationFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
|
||||
new LLSDNotationParser());
|
||||
setParser(LLSDSerialize::deserialize);
|
||||
// This is an interesting test because LLSDNotationFormatter does not
|
||||
// emit an llsd/notation header.
|
||||
doRoundTripTests("LLSDNotationFormatter -> deserialize");
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<9>()
|
||||
{
|
||||
setFormatterParser(new LLSDXMLFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
|
||||
new LLSDXMLParser());
|
||||
setParser(LLSDSerialize::deserialize);
|
||||
// This is an interesting test because LLSDXMLFormatter does not
|
||||
// emit an LLSD/XML header.
|
||||
doRoundTripTests("LLSDXMLFormatter -> deserialize");
|
||||
};
|
||||
|
||||
/*==========================================================================*|
|
||||
// We do not expect this test to succeed. Without a header, neither
|
||||
// notation LLSD nor binary LLSD reliably start with a distinct character,
|
||||
// the way XML LLSD starts with '<'. By convention, we default to notation
|
||||
// rather than binary.
|
||||
template<> template<>
|
||||
void TestLLSDSerializeObject::test<10>()
|
||||
{
|
||||
setFormatterParser(new LLSDBinaryFormatter(false, "", LLSDFormatter::OPTIONS_NONE),
|
||||
new LLSDBinaryParser());
|
||||
setParser(LLSDSerialize::deserialize);
|
||||
// This is an interesting test because LLSDBinaryFormatter does not
|
||||
// emit an LLSD/Binary header.
|
||||
doRoundTripTests("LLSDBinaryFormatter -> deserialize");
|
||||
};
|
||||
|*==========================================================================*/
|
||||
|
||||
/**
|
||||
* @class TestLLSDParsing
|
||||
|
|
@ -555,7 +654,7 @@ namespace tut
|
|||
public:
|
||||
TestLLSDXMLParsing() {}
|
||||
};
|
||||
|
||||
|
||||
typedef tut::test_group<TestLLSDXMLParsing> TestLLSDXMLParsingGroup;
|
||||
typedef TestLLSDXMLParsingGroup::object TestLLSDXMLParsingObject;
|
||||
TestLLSDXMLParsingGroup gTestLLSDXMLParsingGroup("llsd XML parsing");
|
||||
|
|
@ -586,8 +685,8 @@ namespace tut
|
|||
LLSD(),
|
||||
LLSDParser::PARSE_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDXMLParsingObject::test<2>()
|
||||
{
|
||||
|
|
@ -596,7 +695,7 @@ namespace tut
|
|||
v["amy"] = 23;
|
||||
v["bob"] = LLSD();
|
||||
v["cam"] = 1.23;
|
||||
|
||||
|
||||
ensureParse(
|
||||
"unknown data type",
|
||||
"<llsd><map>"
|
||||
|
|
@ -607,16 +706,16 @@ namespace tut
|
|||
v,
|
||||
v.size() + 1);
|
||||
}
|
||||
|
||||
|
||||
template<> template<>
|
||||
void TestLLSDXMLParsingObject::test<3>()
|
||||
{
|
||||
// test handling of nested bad data
|
||||
|
||||
|
||||
LLSD v;
|
||||
v["amy"] = 23;
|
||||
v["cam"] = 1.23;
|
||||
|
||||
|
||||
ensureParse(
|
||||
"map with html",
|
||||
"<llsd><map>"
|
||||
|
|
@ -626,7 +725,7 @@ namespace tut
|
|||
"</map></llsd>",
|
||||
v,
|
||||
v.size() + 1);
|
||||
|
||||
|
||||
v.clear();
|
||||
v["amy"] = 23;
|
||||
v["cam"] = 1.23;
|
||||
|
|
@ -639,7 +738,7 @@ namespace tut
|
|||
"</map></llsd>",
|
||||
v,
|
||||
v.size() + 1);
|
||||
|
||||
|
||||
v.clear();
|
||||
v["amy"] = 23;
|
||||
v["bob"] = LLSD::emptyMap();
|
||||
|
|
@ -661,7 +760,7 @@ namespace tut
|
|||
v[0] = 23;
|
||||
v[1] = LLSD();
|
||||
v[2] = 1.23;
|
||||
|
||||
|
||||
ensureParse(
|
||||
"array value of html",
|
||||
"<llsd><array>"
|
||||
|
|
@ -671,7 +770,7 @@ namespace tut
|
|||
"</array></llsd>",
|
||||
v,
|
||||
v.size() + 1);
|
||||
|
||||
|
||||
v.clear();
|
||||
v[0] = 23;
|
||||
v[1] = LLSD::emptyMap();
|
||||
|
|
@ -1225,7 +1324,7 @@ namespace tut
|
|||
vec[0] = 'a'; vec[1] = 'b'; vec[2] = 'c';
|
||||
vec[3] = '3'; vec[4] = '2'; vec[5] = '1';
|
||||
LLSD value = vec;
|
||||
|
||||
|
||||
vec.resize(11);
|
||||
vec[0] = 'b'; // for binary
|
||||
vec[5] = 'a'; vec[6] = 'b'; vec[7] = 'c';
|
||||
|
|
@ -1694,85 +1793,83 @@ namespace tut
|
|||
ensureBinaryAndXML("map", test);
|
||||
}
|
||||
|
||||
struct TestPythonCompatible
|
||||
// helper for TestPythonCompatible
|
||||
static std::string import_llsd("import os.path\n"
|
||||
"import sys\n"
|
||||
"try:\n"
|
||||
// new freestanding llsd package
|
||||
" import llsd\n"
|
||||
"except ImportError:\n"
|
||||
// older llbase.llsd module
|
||||
" from llbase import llsd\n");
|
||||
|
||||
// helper for TestPythonCompatible
|
||||
template <typename CONTENT>
|
||||
void python(const std::string& desc, const CONTENT& script, int expect=0)
|
||||
{
|
||||
TestPythonCompatible():
|
||||
// Note the peculiar insertion of __FILE__ into this string. Since
|
||||
// this script is being written into a platform-dependent temp
|
||||
// directory, we can't locate indra/lib/python relative to
|
||||
// Python's __file__. Use __FILE__ instead, navigating relative
|
||||
// to this C++ source file. Use Python raw-string syntax so
|
||||
// Windows pathname backslashes won't mislead Python's string
|
||||
// scanner.
|
||||
import_llsd("import os.path\n"
|
||||
"import sys\n"
|
||||
"import llsd\n")
|
||||
{}
|
||||
~TestPythonCompatible() {}
|
||||
auto PYTHON(LLStringUtil::getenv("PYTHON"));
|
||||
ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
|
||||
|
||||
std::string import_llsd;
|
||||
|
||||
template <typename CONTENT>
|
||||
void python(const std::string& desc, const CONTENT& script, int expect=0)
|
||||
{
|
||||
auto PYTHON(LLStringUtil::getenv("PYTHON"));
|
||||
ensure("Set $PYTHON to the Python interpreter", !PYTHON.empty());
|
||||
|
||||
NamedTempFile scriptfile("py", script);
|
||||
NamedTempFile scriptfile("py", script);
|
||||
|
||||
#if LL_WINDOWS
|
||||
std::string q("\"");
|
||||
std::string qPYTHON(q + PYTHON + q);
|
||||
std::string qscript(q + scriptfile.getName() + q);
|
||||
int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL);
|
||||
if (rc == -1)
|
||||
{
|
||||
char buffer[256];
|
||||
strerror_s(buffer, errno); // C++ can infer the buffer size! :-O
|
||||
ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect);
|
||||
}
|
||||
std::string q("\"");
|
||||
std::string qPYTHON(q + PYTHON + q);
|
||||
std::string qscript(q + scriptfile.getName() + q);
|
||||
int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), NULL);
|
||||
if (rc == -1)
|
||||
{
|
||||
char buffer[256];
|
||||
strerror_s(buffer, errno); // C++ can infer the buffer size! :-O
|
||||
ensure(STRINGIZE("Couldn't run Python " << desc << "script: " << buffer), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc), rc, expect);
|
||||
}
|
||||
|
||||
#else // LL_DARWIN, LL_LINUX
|
||||
LLProcess::Params params;
|
||||
params.executable = PYTHON;
|
||||
params.args.add(scriptfile.getName());
|
||||
LLProcessPtr py(LLProcess::create(params));
|
||||
ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py));
|
||||
// Implementing timeout would mean messing with alarm() and
|
||||
// catching SIGALRM... later maybe...
|
||||
int status(0);
|
||||
if (waitpid(py->getProcessID(), &status, 0) == -1)
|
||||
LLProcess::Params params;
|
||||
params.executable = PYTHON;
|
||||
params.args.add(scriptfile.getName());
|
||||
LLProcessPtr py(LLProcess::create(params));
|
||||
ensure(STRINGIZE("Couldn't launch " << desc << " script"), bool(py));
|
||||
// Implementing timeout would mean messing with alarm() and
|
||||
// catching SIGALRM... later maybe...
|
||||
int status(0);
|
||||
if (waitpid(py->getProcessID(), &status, 0) == -1)
|
||||
{
|
||||
int waitpid_errno(errno);
|
||||
ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
|
||||
"waitpid() errno " << waitpid_errno),
|
||||
waitpid_errno, ECHILD);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
int waitpid_errno(errno);
|
||||
ensure_equals(STRINGIZE("Couldn't retrieve rc from " << desc << " script: "
|
||||
"waitpid() errno " << waitpid_errno),
|
||||
waitpid_errno, ECHILD);
|
||||
int rc(WEXITSTATUS(status));
|
||||
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc),
|
||||
rc, expect);
|
||||
}
|
||||
else if (WIFSIGNALED(status))
|
||||
{
|
||||
ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)),
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WIFEXITED(status))
|
||||
{
|
||||
int rc(WEXITSTATUS(status));
|
||||
ensure_equals(STRINGIZE(desc << " script terminated with rc " << rc),
|
||||
rc, expect);
|
||||
}
|
||||
else if (WIFSIGNALED(status))
|
||||
{
|
||||
ensure(STRINGIZE(desc << " script terminated by signal " << WTERMSIG(status)),
|
||||
false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ensure(STRINGIZE(desc << " script produced impossible status " << status),
|
||||
false);
|
||||
}
|
||||
ensure(STRINGIZE(desc << " script produced impossible status " << status),
|
||||
false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
struct TestPythonCompatible
|
||||
{
|
||||
TestPythonCompatible() {}
|
||||
~TestPythonCompatible() {}
|
||||
};
|
||||
|
||||
typedef tut::test_group<TestPythonCompatible> TestPythonCompatibleGroup;
|
||||
|
|
@ -1798,25 +1895,33 @@ namespace tut
|
|||
"print('Running on', sys.platform)\n");
|
||||
}
|
||||
|
||||
// helper for test<3>
|
||||
static void writeLLSDArray(std::ostream& out, const LLSD& array)
|
||||
// helper for test<3> - test<7>
|
||||
static void writeLLSDArray(const FormatterFunction& serialize,
|
||||
std::ostream& out, const LLSD& array)
|
||||
{
|
||||
BOOST_FOREACH(LLSD item, llsd::inArray(array))
|
||||
for (const LLSD& item : llsd::inArray(array))
|
||||
{
|
||||
LLSDSerialize::toNotation(item, out);
|
||||
// It's important to separate with newlines because Python's llsd
|
||||
// module doesn't support parsing from a file stream, only from a
|
||||
// string, so we have to know how much of the file to read into a
|
||||
// string.
|
||||
out << '\n';
|
||||
// It's important to delimit the entries in this file somehow
|
||||
// because, although Python's llsd.parse() can accept a file
|
||||
// stream, the XML parser expects EOF after a single outer element
|
||||
// -- it doesn't just stop. So we must extract a sequence of bytes
|
||||
// strings from the file. But since one of the serialization
|
||||
// formats we want to test is binary, we can't pick any single
|
||||
// byte value as a delimiter! Use a binary integer length prefix
|
||||
// instead.
|
||||
std::ostringstream buffer;
|
||||
serialize(item, buffer);
|
||||
auto buffstr{ buffer.str() };
|
||||
int bufflen{ static_cast<int>(buffstr.length()) };
|
||||
out.write(reinterpret_cast<const char*>(&bufflen), sizeof(bufflen));
|
||||
out.write(buffstr.c_str(), buffstr.length());
|
||||
}
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<3>()
|
||||
// helper for test<3> - test<7>
|
||||
static void toPythonUsing(const std::string& desc,
|
||||
const FormatterFunction& serialize)
|
||||
{
|
||||
set_test_name("verify sequence to Python");
|
||||
|
||||
LLSD cdata(llsd::array(17, 3.14,
|
||||
"This string\n"
|
||||
"has several\n"
|
||||
|
|
@ -1836,7 +1941,7 @@ namespace tut
|
|||
" except StopIteration:\n"
|
||||
" pass\n"
|
||||
" else:\n"
|
||||
" assert False, 'Too many data items'\n";
|
||||
" raise AssertionError('Too many data items')\n";
|
||||
|
||||
// Create an llsdXXXXXX file containing 'data' serialized to
|
||||
// notation.
|
||||
|
|
@ -1845,32 +1950,128 @@ namespace tut
|
|||
// takes a callable. To this callable it passes the
|
||||
// std::ostream with which it's writing the
|
||||
// NamedTempFile.
|
||||
boost::bind(writeLLSDArray, _1, cdata));
|
||||
[serialize, cdata]
|
||||
(std::ostream& out)
|
||||
{ writeLLSDArray(serialize, out, cdata); });
|
||||
|
||||
python("read C++ notation",
|
||||
python("read C++ " + desc,
|
||||
placeholders::arg1 <<
|
||||
import_llsd <<
|
||||
"def parse_each(iterable):\n"
|
||||
" for item in iterable:\n"
|
||||
" yield llsd.parse(item)\n" <<
|
||||
pydata <<
|
||||
"from functools import partial\n"
|
||||
"import io\n"
|
||||
"import struct\n"
|
||||
"lenformat = struct.Struct('i')\n"
|
||||
"def parse_each(inf):\n"
|
||||
" for rawlen in iter(partial(inf.read, lenformat.size), b''):\n"
|
||||
" len = lenformat.unpack(rawlen)[0]\n"
|
||||
// Since llsd.parse() has no max_bytes argument, instead of
|
||||
// passing the input stream directly to parse(), read the item
|
||||
// into a distinct bytes object and parse that.
|
||||
" data = inf.read(len)\n"
|
||||
" try:\n"
|
||||
" frombytes = llsd.parse(data)\n"
|
||||
" except llsd.LLSDParseError as err:\n"
|
||||
" print(f'*** {err}')\n"
|
||||
" print(f'Bad content:\\n{data!r}')\n"
|
||||
" raise\n"
|
||||
// Also try parsing from a distinct stream.
|
||||
" stream = io.BytesIO(data)\n"
|
||||
" fromstream = llsd.parse(stream)\n"
|
||||
" assert frombytes == fromstream\n"
|
||||
" yield frombytes\n"
|
||||
<< pydata <<
|
||||
// Don't forget raw-string syntax for Windows pathnames.
|
||||
"verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<3>()
|
||||
{
|
||||
set_test_name("to Python using LLSDSerialize::serialize(LLSD_XML)");
|
||||
toPythonUsing("LLSD_XML",
|
||||
[](const LLSD& sd, std::ostream& out)
|
||||
{ LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_XML); });
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<4>()
|
||||
{
|
||||
set_test_name("verify sequence from Python");
|
||||
set_test_name("to Python using LLSDSerialize::serialize(LLSD_NOTATION)");
|
||||
toPythonUsing("LLSD_NOTATION",
|
||||
[](const LLSD& sd, std::ostream& out)
|
||||
{ LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_NOTATION); });
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<5>()
|
||||
{
|
||||
set_test_name("to Python using LLSDSerialize::serialize(LLSD_BINARY)");
|
||||
toPythonUsing("LLSD_BINARY",
|
||||
[](const LLSD& sd, std::ostream& out)
|
||||
{ LLSDSerialize::serialize(sd, out, LLSDSerialize::LLSD_BINARY); });
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<6>()
|
||||
{
|
||||
set_test_name("to Python using LLSDSerialize::toXML()");
|
||||
toPythonUsing("toXML()", LLSDSerialize::toXML);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<7>()
|
||||
{
|
||||
set_test_name("to Python using LLSDSerialize::toNotation()");
|
||||
toPythonUsing("toNotation()", LLSDSerialize::toNotation);
|
||||
}
|
||||
|
||||
/*==========================================================================*|
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<8>()
|
||||
{
|
||||
set_test_name("to Python using LLSDSerialize::toBinary()");
|
||||
// We don't expect this to work because, without a header,
|
||||
// llsd.parse() will assume notation rather than binary.
|
||||
toPythonUsing("toBinary()", LLSDSerialize::toBinary);
|
||||
}
|
||||
|*==========================================================================*/
|
||||
|
||||
// helper for test<8> - test<12>
|
||||
bool itemFromStream(std::istream& istr, LLSD& item, const ParserFunction& parse)
|
||||
{
|
||||
// reset the output value for debugging clarity
|
||||
item.clear();
|
||||
// We use an int length prefix as a foolproof delimiter even for
|
||||
// binary serialized streams.
|
||||
int length{ 0 };
|
||||
istr.read(reinterpret_cast<char*>(&length), sizeof(length));
|
||||
// return parse(istr, item, length);
|
||||
// Sadly, as of 2022-12-01 it seems we can't really trust our LLSD
|
||||
// parsers to honor max_bytes: this test works better when we read
|
||||
// each item into its own distinct LLMemoryStream, instead of passing
|
||||
// the original istr with a max_bytes constraint.
|
||||
std::vector<U8> buffer(length);
|
||||
istr.read(reinterpret_cast<char*>(buffer.data()), length);
|
||||
LLMemoryStream stream(buffer.data(), length);
|
||||
return parse(stream, item, length);
|
||||
}
|
||||
|
||||
// helper for test<8> - test<12>
|
||||
void fromPythonUsing(const std::string& pyformatter,
|
||||
const ParserFunction& parse=
|
||||
[](std::istream& istr, LLSD& data, llssize max_bytes)
|
||||
{ return LLSDSerialize::deserialize(data, istr, max_bytes); })
|
||||
{
|
||||
// Create an empty data file. This is just a placeholder for our
|
||||
// script to write into. Create it to establish a unique name that
|
||||
// we know.
|
||||
NamedTempFile file("llsd", "");
|
||||
|
||||
python("write Python notation",
|
||||
python("Python " + pyformatter,
|
||||
placeholders::arg1 <<
|
||||
import_llsd <<
|
||||
"import struct\n"
|
||||
"lenformat = struct.Struct('i')\n"
|
||||
"DATA = [\n"
|
||||
" 17,\n"
|
||||
" 3.14,\n"
|
||||
|
|
@ -1881,34 +2082,87 @@ namespace tut
|
|||
"]\n"
|
||||
// Don't forget raw-string syntax for Windows pathnames.
|
||||
// N.B. Using 'print' implicitly adds newlines.
|
||||
"with open(r'" << file.getName() << "', 'w') as f:\n"
|
||||
"with open(r'" << file.getName() << "', 'wb') as f:\n"
|
||||
" for item in DATA:\n"
|
||||
" print(llsd.format_notation(item).decode(), file=f)\n");
|
||||
" serialized = llsd." << pyformatter << "(item)\n"
|
||||
" f.write(lenformat.pack(len(serialized)))\n"
|
||||
" f.write(serialized)\n");
|
||||
|
||||
std::ifstream inf(file.getName().c_str());
|
||||
LLSD item;
|
||||
// Notice that we're not doing anything special to parse out the
|
||||
// newlines: LLSDSerialize::fromNotation ignores them. While it would
|
||||
// seem they're not strictly necessary, going in this direction, we
|
||||
// want to ensure that notation-separated-by-newlines works in both
|
||||
// directions -- since in practice, a given file might be read by
|
||||
// either language.
|
||||
ensure_equals("Failed to read LLSD::Integer from Python",
|
||||
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
|
||||
1);
|
||||
ensure_equals(item.asInteger(), 17);
|
||||
ensure_equals("Failed to read LLSD::Real from Python",
|
||||
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
|
||||
1);
|
||||
ensure_approximately_equals("Bad LLSD::Real value from Python",
|
||||
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
|
||||
ensure_equals("Failed to read LLSD::String from Python",
|
||||
LLSDSerialize::fromNotation(item, inf, LLSDSerialize::SIZE_UNLIMITED),
|
||||
1);
|
||||
ensure_equals(item.asString(),
|
||||
"This string\n"
|
||||
"has several\n"
|
||||
"lines.");
|
||||
|
||||
try
|
||||
{
|
||||
ensure("Failed to read LLSD::Integer from Python",
|
||||
itemFromStream(inf, item, parse));
|
||||
ensure_equals(item.asInteger(), 17);
|
||||
ensure("Failed to read LLSD::Real from Python",
|
||||
itemFromStream(inf, item, parse));
|
||||
ensure_approximately_equals("Bad LLSD::Real value from Python",
|
||||
item.asReal(), 3.14, 7); // 7 bits ~= 0.01
|
||||
ensure("Failed to read LLSD::String from Python",
|
||||
itemFromStream(inf, item, parse));
|
||||
ensure_equals(item.asString(),
|
||||
"This string\n"
|
||||
"has several\n"
|
||||
"lines.");
|
||||
}
|
||||
catch (const tut::failure& err)
|
||||
{
|
||||
std::cout << "for " << err.what() << ", item = " << item << std::endl;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<8>()
|
||||
{
|
||||
set_test_name("from Python XML using LLSDSerialize::deserialize()");
|
||||
fromPythonUsing("format_xml");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<9>()
|
||||
{
|
||||
set_test_name("from Python notation using LLSDSerialize::deserialize()");
|
||||
fromPythonUsing("format_notation");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<10>()
|
||||
{
|
||||
set_test_name("from Python binary using LLSDSerialize::deserialize()");
|
||||
fromPythonUsing("format_binary");
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<11>()
|
||||
{
|
||||
set_test_name("from Python XML using fromXML()");
|
||||
// fromXML()'s optional 3rd param isn't max_bytes, it's emit_errors
|
||||
fromPythonUsing("format_xml",
|
||||
[](std::istream& istr, LLSD& data, llssize)
|
||||
{ return LLSDSerialize::fromXML(data, istr) > 0; });
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<12>()
|
||||
{
|
||||
set_test_name("from Python notation using fromNotation()");
|
||||
fromPythonUsing("format_notation",
|
||||
[](std::istream& istr, LLSD& data, llssize max_bytes)
|
||||
{ return LLSDSerialize::fromNotation(data, istr, max_bytes) > 0; });
|
||||
}
|
||||
|
||||
/*==========================================================================*|
|
||||
template<> template<>
|
||||
void TestPythonCompatibleObject::test<13>()
|
||||
{
|
||||
set_test_name("from Python binary using fromBinary()");
|
||||
// We don't expect this to work because format_binary() emits a
|
||||
// header, but fromBinary() won't recognize a header.
|
||||
fromPythonUsing("format_binary",
|
||||
[](std::istream& istr, LLSD& data, llssize max_bytes)
|
||||
{ return LLSDSerialize::fromBinary(data, istr, max_bytes) > 0; });
|
||||
}
|
||||
|*==========================================================================*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1329,6 +1329,48 @@ void HttpCoroutineAdapter::trivialPostCoro(std::string url, LLCore::HttpRequest:
|
|||
}
|
||||
|
||||
|
||||
/*static*/
|
||||
void HttpCoroutineAdapter::callbackHttpDel(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success,
|
||||
completionCallback_t failure)
|
||||
{
|
||||
LLCoros::instance().launch("HttpCoroutineAdapter::genericDelCoro",
|
||||
boost::bind(&HttpCoroutineAdapter::trivialDelCoro, url, policyId, success, failure));
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void HttpCoroutineAdapter::trivialDelCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success,
|
||||
completionCallback_t failure)
|
||||
{
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericDelCoro", policyId));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
|
||||
|
||||
httpOpts->setWantHeaders(true);
|
||||
|
||||
LL_INFOS("HttpCoroutineAdapter", "genericDelCoro") << "Generic DEL for " << url << LL_ENDL;
|
||||
|
||||
LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url, httpOpts);
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (failure)
|
||||
{
|
||||
failure(httpResults);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
success(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end namespace LLCoreHttpUtil
|
||||
|
||||
|
|
|
|||
|
|
@ -598,6 +598,9 @@ public:
|
|||
callbackHttpPost(url, LLCore::HttpRequest::DEFAULT_POLICY_ID, postData, success, failure);
|
||||
}
|
||||
|
||||
static void callbackHttpDel(const std::string &url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success = NULL,
|
||||
completionCallback_t failure = NULL);
|
||||
|
||||
/// Generic Get and post routines for HTTP via coroutines.
|
||||
/// These static methods do all required setup for the GET or POST operation.
|
||||
/// When the operation completes successfully they will put the success message in the log at INFO level,
|
||||
|
|
@ -659,6 +662,7 @@ private:
|
|||
|
||||
static void trivialGetCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure);
|
||||
static void trivialPostCoro(std::string url, LLCore::HttpRequest::policy_t policyId, LLSD postData, completionCallback_t success, completionCallback_t failure);
|
||||
static void trivialDelCoro(std::string url, LLCore::HttpRequest::policy_t policyId, completionCallback_t success, completionCallback_t failure);
|
||||
|
||||
void checkDefaultHeaders(LLCore::HttpHeaders::ptr_t &headers);
|
||||
|
||||
|
|
|
|||
|
|
@ -171,8 +171,9 @@ const U32 ESTATE_ACCESS_MANAGER_REMOVE = 1U << 9;
|
|||
const U32 ESTATE_ACCESS_NO_REPLY = 1U << 10;
|
||||
const U32 ESTATE_ACCESS_FAILED_BAN_ESTATE_MANAGER = 1U << 11;
|
||||
|
||||
const S32 ESTATE_MAX_MANAGERS = 15;
|
||||
const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access, banned
|
||||
const S32 ESTATE_MAX_MANAGERS = 20;
|
||||
const S32 ESTATE_MAX_ACCESS_IDS = 500; // max for access
|
||||
const S32 ESTATE_MAX_BANNED_IDS = 750; // max for banned
|
||||
const S32 ESTATE_MAX_GROUP_IDS = (S32) ESTATE_ACCESS_MAX_ENTRIES_PER_PACKET;
|
||||
|
||||
// 'Sim Wide Delete' flags
|
||||
|
|
|
|||
|
|
@ -67,6 +67,14 @@ public:
|
|||
|
||||
static const LLMaterialID null;
|
||||
|
||||
// Returns a 64 bits digest of the material Id, by XORing its two 64 bits
|
||||
// long words. HB
|
||||
inline U64 getDigest64() const
|
||||
{
|
||||
U64* tmp = (U64*)mID;
|
||||
return tmp[0] ^ tmp[1];
|
||||
}
|
||||
|
||||
private:
|
||||
void parseFromBinary(const LLSD::Binary& pMaterialID);
|
||||
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
|
||||
|
|
@ -75,5 +83,23 @@ private:
|
|||
U8 mID[MATERIAL_ID_SIZE];
|
||||
} ;
|
||||
|
||||
// std::hash implementation for LLMaterialID
|
||||
namespace std
|
||||
{
|
||||
template<> struct hash<LLMaterialID>
|
||||
{
|
||||
inline size_t operator()(const LLMaterialID& id) const noexcept
|
||||
{
|
||||
return (size_t)id.getDigest64();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// For use with boost containers.
|
||||
inline size_t hash_value(const LLMaterialID& id) noexcept
|
||||
{
|
||||
return (size_t)id.getDigest64();
|
||||
}
|
||||
|
||||
#endif // LL_LLMATERIALID_H
|
||||
|
||||
|
|
|
|||
|
|
@ -703,7 +703,7 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
|
|||
|
||||
for (U32 i = start; i <= end; ++i)
|
||||
{
|
||||
if (!v->isFinite3())
|
||||
if (!v[i].isFinite3())
|
||||
{
|
||||
LL_ERRS() << "Non-finite vertex position data detected." << LL_ENDL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ LLDragHandle::LLDragHandle(const LLDragHandle::Params& p)
|
|||
|
||||
LLDragHandle::~LLDragHandle()
|
||||
{
|
||||
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
|
||||
removeChild(mTitleBox);
|
||||
delete mTitleBox;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
|
|||
LLFolderViewItem::~LLFolderViewItem()
|
||||
{
|
||||
mViewModelItem = NULL;
|
||||
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
|
||||
}
|
||||
|
||||
BOOL LLFolderViewItem::postBuild()
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ LLLayoutPanel::~LLLayoutPanel()
|
|||
// probably not necessary, but...
|
||||
delete mResizeBar;
|
||||
mResizeBar = NULL;
|
||||
|
||||
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
|
||||
}
|
||||
|
||||
F32 LLLayoutPanel::getAutoResizeFactor() const
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@ LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p)
|
|||
}
|
||||
}
|
||||
|
||||
LLResizeHandle::~LLResizeHandle()
|
||||
{
|
||||
gFocusMgr.removeKeyboardFocusWithoutCallback(this);
|
||||
}
|
||||
|
||||
|
||||
BOOL LLResizeHandle::handleMouseDown(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
Params();
|
||||
};
|
||||
|
||||
~LLResizeHandle();
|
||||
protected:
|
||||
LLResizeHandle(const LLResizeHandle::Params&);
|
||||
friend class LLUICtrlFactory;
|
||||
|
|
|
|||
|
|
@ -209,6 +209,12 @@
|
|||
<string>NoAudio</string>
|
||||
</map>
|
||||
|
||||
<key>nofmod</key>
|
||||
<map>
|
||||
<key>map-to</key>
|
||||
<string>UseMediaPluginsForStreamingAudio</string>
|
||||
</map>
|
||||
|
||||
<key>noninteractive</key>
|
||||
<map>
|
||||
<key>desc</key>
|
||||
|
|
|
|||
|
|
@ -7099,6 +7099,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>UseMediaPluginsForStreamingAudio</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use media plugins (VLC) for streaming audio.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>NoHardwareProbe</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -11744,11 +11755,11 @@
|
|||
<key>ShowBanLines</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show in-world ban/access borders</string>
|
||||
<string>Show in-world ban/access borders, 0 - do not show, 1 - show on collision, 2 - show on proximity</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
|
|
@ -17306,17 +17317,6 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>360CaptureUseInterestListCap</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Flag if set, uses the new InterestList cap to ask the simulator for full content</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>360CaptureJPEGEncodeQuality</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -17438,5 +17438,38 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>StatsReportMaxDuration</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Maximum seconds for viewer stats file data, prevents huge file</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>300</real>
|
||||
</map>
|
||||
<key>StatsReportFileInterval</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Interval to save viewer stats file data</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.2</real>
|
||||
</map>
|
||||
<key>StatsReportSkipZeroDataSaves</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>In viewer stats data file, skip saving entry if there is no data</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
</map>
|
||||
</llsd>
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ Call un.UserSettingsFiles
|
|||
SectionEnd
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Make sure the user can install
|
||||
;; Make sure the user can install/uninstall
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
Function CheckIfAdministrator
|
||||
DetailPrint $(CheckAdministratorInstDP)
|
||||
|
|
@ -518,26 +518,8 @@ Function CheckIfAdministrator
|
|||
Quit
|
||||
lbl_is_admin:
|
||||
Return
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Make sure the user can uninstall
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
/* Unused
|
||||
Function un.CheckIfAdministrator
|
||||
DetailPrint $(CheckAdministratorUnInstDP)
|
||||
UserInfo::GetAccountType
|
||||
Pop $R0
|
||||
StrCmp $R0 "Admin" lbl_is_admin
|
||||
MessageBox MB_OK $(CheckAdministratorUnInstMB)
|
||||
Quit
|
||||
lbl_is_admin:
|
||||
Return
|
||||
|
||||
FunctionEnd
|
||||
*/
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Function CheckWillUninstallV2
|
||||
;;
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -406,6 +406,7 @@ LLAgent::LLAgent() :
|
|||
mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||
mTeleportState(TELEPORT_NONE),
|
||||
mRegionp(NULL),
|
||||
mInterestListMode(LLViewerRegion::IL_MODE_DEFAULT),
|
||||
|
||||
mAgentOriginGlobal(),
|
||||
mPositionGlobal(),
|
||||
|
|
@ -986,11 +987,19 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal
|
|||
|
||||
// static
|
||||
void LLAgent::capabilityReceivedCallback(const LLUUID ®ion_id, LLViewerRegion *regionp)
|
||||
{
|
||||
if (regionp && regionp->getRegionID() == region_id)
|
||||
{ // Changed regions and now have the region capabilities
|
||||
if (regionp)
|
||||
{
|
||||
regionp->requestSimulatorFeatures();
|
||||
LLAppViewer::instance()->updateNameLookupUrl(regionp);
|
||||
if (regionp->getRegionID() == region_id)
|
||||
{
|
||||
regionp->requestSimulatorFeatures();
|
||||
LLAppViewer::instance()->updateNameLookupUrl(regionp);
|
||||
}
|
||||
|
||||
if (gAgent.getInterestListMode() == LLViewerRegion::IL_MODE_360)
|
||||
{
|
||||
gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1450,26 +1459,21 @@ LLVector3 LLAgent::getReferenceUpVector()
|
|||
void LLAgent::pitch(F32 angle)
|
||||
{
|
||||
// don't let user pitch if pointed almost all the way down or up
|
||||
mFrameAgent.pitch(clampPitchToLimits(angle));
|
||||
}
|
||||
|
||||
|
||||
// Radians, positive is forward into ground
|
||||
//-----------------------------------------------------------------------------
|
||||
// clampPitchToLimits()
|
||||
//-----------------------------------------------------------------------------
|
||||
F32 LLAgent::clampPitchToLimits(F32 angle)
|
||||
{
|
||||
// A dot B = mag(A) * mag(B) * cos(angle between A and B)
|
||||
// so... cos(angle between A and B) = A dot B / mag(A) / mag(B)
|
||||
// = A dot B for unit vectors
|
||||
|
||||
LLVector3 skyward = getReferenceUpVector();
|
||||
|
||||
const F32 look_down_limit = 179.f * DEG_TO_RAD;;
|
||||
const F32 look_up_limit = 1.f * DEG_TO_RAD;
|
||||
// SL-19286 Avatar is upside down when viewed from below
|
||||
// after left-clicking the mouse on the avatar and dragging down
|
||||
//
|
||||
// The issue is observed on angle below 10 degrees
|
||||
const F32 look_down_limit = 179.f * DEG_TO_RAD;
|
||||
const F32 look_up_limit = 10.f * DEG_TO_RAD;
|
||||
|
||||
F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward );
|
||||
F32 angle_from_skyward = acos(mFrameAgent.getAtAxis() * skyward);
|
||||
|
||||
// clamp pitch to limits
|
||||
if ((angle >= 0.f) && (angle_from_skyward + angle > look_down_limit))
|
||||
|
|
@ -1480,8 +1484,11 @@ F32 LLAgent::clampPitchToLimits(F32 angle)
|
|||
{
|
||||
angle = look_up_limit - angle_from_skyward;
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
||||
if (fabs(angle) > 1e-4)
|
||||
{
|
||||
mFrameAgent.pitch(angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2998,39 +3005,60 @@ void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferr
|
|||
handlePreferredMaturityResult(maturity);
|
||||
}
|
||||
|
||||
// Using a new capability, tell the simulator that we want it to send everything
|
||||
// it knows about and not just what is in front of the camera, in its view
|
||||
// frustum. We need this feature so that the contents of the region that appears
|
||||
// in the 6 snapshots which we cannot see and is normally not "considered", is
|
||||
// also rendered. Typically, this is turned on when the 360 capture floater is
|
||||
// opened and turned off when it is closed.
|
||||
// Note: for this version, we do not have a way to determine when "everything"
|
||||
// has arrived and has been rendered so for now, the proposal is that users
|
||||
// will need to experiment with the low resolution version and wait for some
|
||||
// (hopefully) small period of time while the full contents resolves.
|
||||
// Pass in a flag to ask the simulator/interest list to "send everything" or
|
||||
// not (the default mode)
|
||||
void LLAgent::changeInterestListMode(const std::string &new_mode)
|
||||
{
|
||||
if (new_mode != mInterestListMode)
|
||||
{
|
||||
mInterestListMode = new_mode;
|
||||
|
||||
// Change interest list mode for all regions. If they are already set for the current mode,
|
||||
// the setting will have no effect.
|
||||
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
|
||||
iter != LLWorld::getInstance()->getRegionList().end();
|
||||
++iter)
|
||||
{
|
||||
LLViewerRegion *regionp = *iter;
|
||||
if (regionp && regionp->isAlive() && regionp->capabilitiesReceived())
|
||||
{
|
||||
regionp->setInterestListMode(mInterestListMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("360Capture") << "Agent interest list mode is already set to " << mInterestListMode << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure)
|
||||
{
|
||||
if (!getRegion())
|
||||
if (getRegion())
|
||||
{
|
||||
return false;
|
||||
return getRegion()->requestPostCapability(capName, postData, cbSuccess, cbFailure);
|
||||
}
|
||||
std::string url = getRegion()->getCapability(capName);
|
||||
|
||||
if (url.empty())
|
||||
{
|
||||
LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, mHttpPolicy, postData, cbSuccess, cbFailure);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLAgent::requestGetCapability(const std::string &capName, httpCallback_t cbSuccess, httpCallback_t cbFailure)
|
||||
{
|
||||
std::string url;
|
||||
|
||||
url = getRegionCapability(capName);
|
||||
|
||||
if (url.empty())
|
||||
if (getRegion())
|
||||
{
|
||||
LL_WARNS("Agent") << "Could not retrieve region capability \"" << capName << "\"" << LL_ENDL;
|
||||
return false;
|
||||
return getRegion()->requestGetCapability(capName, cbSuccess, cbFailure);
|
||||
}
|
||||
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(url, mHttpPolicy, cbSuccess, cbFailure);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL LLAgent::getAdminOverride() const
|
||||
|
|
|
|||
|
|
@ -299,10 +299,16 @@ public:
|
|||
boost::signals2::connection addRegionChangedCallback(const region_changed_signal_t::slot_type& cb);
|
||||
void removeRegionChangedCallback(boost::signals2::connection callback);
|
||||
|
||||
|
||||
void changeInterestListMode(const std::string & new_mode);
|
||||
const std::string & getInterestListMode() const { return mInterestListMode; }
|
||||
|
||||
private:
|
||||
LLViewerRegion *mRegionp;
|
||||
region_changed_signal_t mRegionChangedSignal;
|
||||
|
||||
std::string mInterestListMode; // How agent wants regions to send updates
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// History
|
||||
//--------------------------------------------------------------------
|
||||
|
|
@ -553,7 +559,6 @@ public:
|
|||
void roll(F32 angle);
|
||||
void yaw(F32 angle);
|
||||
LLVector3 getReferenceUpVector();
|
||||
F32 clampPitchToLimits(F32 angle);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Autopilot
|
||||
|
|
|
|||
|
|
@ -401,10 +401,15 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi
|
|||
|
||||
// if is avatar - don't do any funk heuristics to position the focal point
|
||||
// see DEV-30589
|
||||
if (object->isAvatar() || (object->isAnimatedObject() && object->getControlAvatar()))
|
||||
if ((object->isAvatar() && !object->isRoot()) || (object->isAnimatedObject() && object->getControlAvatar()))
|
||||
{
|
||||
return original_focus_point - obj_pos;
|
||||
}
|
||||
if (object->isAvatar())
|
||||
{
|
||||
LLVOAvatar* av = object->asAvatar();
|
||||
return original_focus_point - av->getCharacterPosition();
|
||||
}
|
||||
|
||||
LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation
|
||||
LLVector3 object_extents = object->getScale();
|
||||
|
|
@ -1765,13 +1770,24 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
|
|||
LL_WARNS() << "Null avatar drawable!" << LL_ENDL;
|
||||
return LLVector3d::zero;
|
||||
}
|
||||
|
||||
head_offset.clearVec();
|
||||
F32 fixup;
|
||||
if (gAgentAvatarp->hasPelvisFixup(fixup))
|
||||
{
|
||||
head_offset[VZ] -= fixup;
|
||||
}
|
||||
if (gAgentAvatarp->isSitting())
|
||||
{
|
||||
head_offset.mdV[VZ] += 0.1;
|
||||
}
|
||||
|
||||
if (gAgentAvatarp->isSitting() && gAgentAvatarp->getParent())
|
||||
{
|
||||
gAgentAvatarp->updateHeadOffset();
|
||||
head_offset.mdV[VX] = gAgentAvatarp->mHeadOffset.mV[VX];
|
||||
head_offset.mdV[VY] = gAgentAvatarp->mHeadOffset.mV[VY];
|
||||
head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ] + 0.1f;
|
||||
head_offset.mdV[VX] += gAgentAvatarp->mHeadOffset.mV[VX];
|
||||
head_offset.mdV[VY] += gAgentAvatarp->mHeadOffset.mV[VY];
|
||||
head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ];
|
||||
const LLMatrix4& mat = ((LLViewerObject*) gAgentAvatarp->getParent())->getRenderMatrix();
|
||||
camera_position_global = gAgent.getPosGlobalFromAgent
|
||||
((gAgentAvatarp->getPosition()+
|
||||
|
|
@ -1779,11 +1795,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit)
|
|||
}
|
||||
else
|
||||
{
|
||||
head_offset.mdV[VZ] = gAgentAvatarp->mHeadOffset.mV[VZ];
|
||||
if (gAgentAvatarp->isSitting())
|
||||
{
|
||||
head_offset.mdV[VZ] += 0.1;
|
||||
}
|
||||
head_offset.mdV[VZ] += gAgentAvatarp->mHeadOffset.mV[VZ];
|
||||
camera_position_global = gAgent.getPosGlobalFromAgent(gAgentAvatarp->getRenderPosition());//frame_center_global;
|
||||
head_offset = head_offset * gAgentAvatarp->getRenderRotation();
|
||||
camera_position_global = camera_position_global + head_offset;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "llcommandhandler.h"
|
||||
#include "llslurl.h"
|
||||
#include "llurldispatcher.h"
|
||||
#include "llviewernetwork.h"
|
||||
#include "llviewerobject.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerregion.h"
|
||||
|
|
@ -148,7 +149,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
|||
params.append(event_data["x"]);
|
||||
params.append(event_data["y"]);
|
||||
params.append(event_data["z"]);
|
||||
LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true);
|
||||
LLCommandDispatcher::dispatch("teleport", params, LLSD(), LLGridManager::getInstance()->getGrid(), NULL, LLCommandHandler::NAV_TYPE_CLICKED, true);
|
||||
// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
|
||||
// should we just compose LLCommandHandler and LLDispatchListener?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const
|
|||
|
||||
if (!region || !parcel) return FALSE;
|
||||
|
||||
S32 pos_x = S32(agent_pos_region.mV[VX]);
|
||||
S32 pos_y = S32(agent_pos_region.mV[VY]);
|
||||
S32 pos_z = S32(agent_pos_region.mV[VZ]);
|
||||
S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f);
|
||||
S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f);
|
||||
S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f);
|
||||
|
||||
// Round the numbers based on the velocity
|
||||
F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
#include "llinventoryobserver.h"
|
||||
#include "llinventorypanel.h"
|
||||
#include "lllocaltextureobject.h"
|
||||
#include "llmd5.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "lloutfitobserver.h"
|
||||
#include "llsidepanelappearance.h"
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@
|
|||
#include "llinventorybridge.h"
|
||||
#include "llinventoryfunctions.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llmd5.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llmd5.h"
|
||||
#include "lloutfitobserver.h"
|
||||
#include "lloutfitslist.h"
|
||||
#include "llselectmgr.h"
|
||||
|
|
@ -145,7 +147,10 @@ public:
|
|||
// requests will be throttled from a non-trusted browser
|
||||
LLAppearanceHandler() : LLCommandHandler("appearance", UNTRUSTED_THROTTLE) {}
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
// support secondlife:///app/appearance/show, but for now we just
|
||||
// make all secondlife:///app/appearance SLapps behave this way
|
||||
|
|
@ -4470,8 +4475,10 @@ public:
|
|||
// not allowed from outside the app
|
||||
LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { }
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& tokens,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
LLSD::UUID folder_uuid;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "llenvironment.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llfile.h"
|
||||
#include "llviewertexturelist.h"
|
||||
#include "llgroupmgr.h"
|
||||
#include "llagent.h"
|
||||
|
|
@ -1521,6 +1522,11 @@ bool LLAppViewer::doFrame()
|
|||
LLFloaterSimpleOutfitSnapshot::update();
|
||||
gGLActive = FALSE;
|
||||
}
|
||||
|
||||
if (LLViewerStatsRecorder::instanceExists())
|
||||
{
|
||||
LLViewerStatsRecorder::instance().idle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2973,9 +2979,33 @@ void LLAppViewer::initStrings()
|
|||
std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file);
|
||||
if (strings_path_full.empty() || !LLFile::isfile(strings_path_full))
|
||||
{
|
||||
if (strings_path_full.empty())
|
||||
{
|
||||
LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
llstat st;
|
||||
int rc = LLFile::stat(strings_path_full, &st);
|
||||
if (rc != 0)
|
||||
{
|
||||
LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL;
|
||||
}
|
||||
else if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// initial check to make sure files are there failed
|
||||
gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN);
|
||||
LL_ERRS() << "Viewer failed to find localization and UI files. Please reinstall viewer from https://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
LL_ERRS() << "Viewer failed to find localization and UI files."
|
||||
<< " Please reinstall viewer from https://secondlife.com/support/downloads"
|
||||
<< " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL;
|
||||
}
|
||||
LLTransUtil::parseStrings(strings_file, default_trans_args);
|
||||
LLTransUtil::parseLanguageStrings("language_settings.xml");
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "llagent.h"
|
||||
#include "llappearancemgr.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llstartup.h"
|
||||
#include "lltooldraganddrop.h" // pack_permissions_slam
|
||||
#include "llviewerinventory.h"
|
||||
#include "llviewerregion.h"
|
||||
|
|
@ -372,7 +373,7 @@ void LLAttachmentsMgr::onAttachmentArrived(const LLUUID& inv_item_id)
|
|||
{
|
||||
LLTimer timer;
|
||||
bool expected = mAttachmentRequests.getTime(inv_item_id, timer);
|
||||
if (!expected)
|
||||
if (!expected && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT)
|
||||
{
|
||||
LLInventoryItem *item = gInventory.getItem(inv_item_id);
|
||||
LL_WARNS() << "ATT Attachment was unexpected or arrived after " << MAX_ATTACHMENT_REQUEST_LIFETIME << " seconds: "
|
||||
|
|
@ -411,11 +412,15 @@ void LLAttachmentsMgr::onDetachCompleted(const LLUUID& inv_item_id)
|
|||
LL_DEBUGS("Avatar") << "ATT all detach requests have completed" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!LLApp::isExiting())
|
||||
{
|
||||
LL_WARNS() << "ATT unexpected detach for "
|
||||
<< (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "ATT detach on shutdown for " << (item ? item->getName() : "UNKNOWN") << " " << inv_item_id << LL_ENDL;
|
||||
}
|
||||
|
||||
LL_DEBUGS("Avatar") << "ATT detached item flagging as questionable for COF link checking "
|
||||
<< (item ? item->getName() : "UNKNOWN") << " id " << inv_item_id << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public:
|
|||
// requests will be throttled from a non-trusted browser
|
||||
LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {}
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
std::string action( "" );
|
||||
if ( params.size() >= 1 )
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public:
|
|||
// requests will be throttled from a non-trusted browser
|
||||
LLObjectIMHandler() : LLCommandHandler("objectim", UNTRUSTED_THROTTLE) {}
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class LLObjectHandler : public LLCommandHandler
|
|||
public:
|
||||
LLObjectHandler() : LLCommandHandler("object", UNTRUSTED_BLOCK) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 2) return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,10 +64,10 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const
|
|||
// But for testing, allow a caller to specify untrusted.
|
||||
trusted_browser = params["trusted"].asBoolean();
|
||||
}
|
||||
LLCommandDispatcher::dispatch(
|
||||
params["cmd"],
|
||||
LLCommandDispatcher::dispatch(params["cmd"],
|
||||
params["params"],
|
||||
params["query"],
|
||||
"",
|
||||
NULL,
|
||||
LLCommandHandler::NAV_TYPE_CLICKED,
|
||||
trusted_browser);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ public:
|
|||
bool dispatch(const std::string& cmd,
|
||||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser);
|
||||
|
|
@ -98,6 +99,7 @@ void LLCommandHandlerRegistry::add(const char* cmd,
|
|||
bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
|
||||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser)
|
||||
|
|
@ -165,7 +167,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
|
|||
}
|
||||
}
|
||||
if (!info.mHandler) return false;
|
||||
return info.mHandler->handle(params, query_map, web);
|
||||
return info.mHandler->handle(params, query_map, grid, web);
|
||||
}
|
||||
|
||||
void LLCommandHandlerRegistry::notifySlurlBlocked()
|
||||
|
|
@ -220,12 +222,13 @@ LLCommandHandler::~LLCommandHandler()
|
|||
bool LLCommandDispatcher::dispatch(const std::string& cmd,
|
||||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser)
|
||||
{
|
||||
return LLCommandHandlerRegistry::instance().dispatch(
|
||||
cmd, params, query_map, web, nav_type, trusted_browser);
|
||||
cmd, params, query_map, grid, web, nav_type, trusted_browser);
|
||||
}
|
||||
|
||||
static std::string lookup(LLCommandHandler::EUntrustedAccess value);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ public:
|
|||
LLFooHandler() : LLCommandHandler("foo", UNTRUSTED_BLOCK) { }
|
||||
|
||||
// Your code here
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (tokens.size() < 1) return false;
|
||||
|
|
@ -90,6 +90,7 @@ public:
|
|||
|
||||
virtual bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web) = 0;
|
||||
// For URL secondlife:///app/foo/bar/baz?cat=1&dog=2
|
||||
// @params - array of "bar", "baz", possibly empty
|
||||
|
|
@ -106,6 +107,7 @@ public:
|
|||
static bool dispatch(const std::string& cmd,
|
||||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewer
|
|||
mGlobalScale(1.0f),
|
||||
mMarkedForDeath(false),
|
||||
mRootVolp(NULL),
|
||||
mControlAVBridge(NULL),
|
||||
mScaleConstraintFixup(1.0),
|
||||
mRegionChanged(false)
|
||||
{
|
||||
|
|
@ -376,6 +377,12 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
|
|||
}
|
||||
}
|
||||
|
||||
void LLControlAvatar::markDead()
|
||||
{
|
||||
super::markDead();
|
||||
mControlAVBridge = NULL;
|
||||
}
|
||||
|
||||
bool LLControlAvatar::computeNeedsUpdate()
|
||||
{
|
||||
computeUpdatePeriod();
|
||||
|
|
|
|||
|
|
@ -35,9 +35,12 @@ class LLControlAvatar:
|
|||
{
|
||||
LOG_CLASS(LLControlAvatar);
|
||||
|
||||
using super = LLVOAvatar;
|
||||
|
||||
public:
|
||||
LLControlAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
|
||||
virtual void initInstance(); // Called after construction to initialize the class.
|
||||
virtual void initInstance(); // Called after construction to initialize the class.
|
||||
virtual void markDead();
|
||||
virtual ~LLControlAvatar();
|
||||
|
||||
// If this is an attachment, return the avatar it is attached to. Otherwise NULL.
|
||||
|
|
@ -88,6 +91,7 @@ public:
|
|||
F32 mGlobalScale;
|
||||
|
||||
LLVOVolume *mRootVolp;
|
||||
class LLControlAVBridge* mControlAVBridge;
|
||||
|
||||
bool mMarkedForDeath;
|
||||
|
||||
|
|
|
|||
|
|
@ -760,6 +760,19 @@ void LLDrawable::movePartition()
|
|||
if (part)
|
||||
{
|
||||
part->move(this, getSpatialGroup());
|
||||
|
||||
// SL-18251 "On-screen animesh characters using pelvis offset animations
|
||||
// disappear when root goes off-screen"
|
||||
//
|
||||
// Update extents of the root node when Control Avatar changes it's bounds
|
||||
if (mRenderType == LLPipeline::RENDER_TYPE_CONTROL_AV && isRoot())
|
||||
{
|
||||
LLControlAvatar* controlAvatar = dynamic_cast<LLControlAvatar*>(getVObj().get());
|
||||
if (controlAvatar && controlAvatar->mControlAVBridge)
|
||||
{
|
||||
((LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0))->setState(LLViewerOctreeGroup::DIRTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1206,10 +1219,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
|
|||
{
|
||||
setSpatialBridge(new LLHUDBridge(this, getRegion()));
|
||||
}
|
||||
else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
|
||||
{
|
||||
setSpatialBridge(new LLControlAVBridge(this, getRegion()));
|
||||
}
|
||||
else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
|
||||
{
|
||||
setSpatialBridge(new LLControlAVBridge(this, getRegion()));
|
||||
mVObjp->getControlAvatar()->mControlAVBridge = (LLControlAVBridge*)getSpatialBridge();
|
||||
}
|
||||
// check HUD first, because HUD is also attachment
|
||||
else if (mVObjp->isAttachment())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,8 +43,10 @@ class LLEventHandler : public LLCommandHandler
|
|||
public:
|
||||
// requires trusted browser to trigger
|
||||
LLEventHandler() : LLCommandHandler("event", UNTRUSTED_THROTTLE) { }
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1174,7 +1174,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
{
|
||||
if (gDebugGL)
|
||||
{
|
||||
llassert(false);
|
||||
LL_WARNS() << "Index buffer overflow!" << LL_ENDL;
|
||||
LL_WARNS() << "Indices Count: " << mIndicesCount
|
||||
<< " VF Num Indices: " << num_indices
|
||||
|
|
@ -1182,6 +1181,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
<< " VB Num Indices: " << mVertexBuffer->getNumIndices() << LL_ENDL;
|
||||
LL_WARNS() << " Face Index: " << f
|
||||
<< " Pool Type: " << mPoolType << LL_ENDL;
|
||||
llassert(false);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1190,8 +1190,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||
{
|
||||
if (gDebugGL)
|
||||
{
|
||||
llassert(false);
|
||||
LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL;
|
||||
llassert(false);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::st
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outfiles;
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +149,7 @@ void doLoadDialogModeless(const std::vector<std::string>* allowed_types,
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<std::string> doSaveDialog(const std::string* file,
|
||||
std::unique_ptr<std::string> doSaveDialog(const std::string* file,
|
||||
const std::string* type,
|
||||
const std::string* creator,
|
||||
const std::string* extension,
|
||||
|
|
|
|||
|
|
@ -64,12 +64,10 @@ LLFloater360Capture::LLFloater360Capture(const LLSD& key)
|
|||
// such time as we ask it not to (the dtor). If we crash or
|
||||
// otherwise, exit before this is turned off, the Simulator
|
||||
// will take care of cleaning up for us.
|
||||
if (gSavedSettings.getBOOL("360CaptureUseInterestListCap"))
|
||||
{
|
||||
// send everything to us for as long as this floater is open
|
||||
const bool send_everything = true;
|
||||
changeInterestListMode(send_everything);
|
||||
}
|
||||
mStartILMode = gAgent.getInterestListMode();
|
||||
|
||||
// send everything to us for as long as this floater is open
|
||||
gAgent.changeInterestListMode(LLViewerRegion::IL_MODE_360);
|
||||
}
|
||||
|
||||
LLFloater360Capture::~LLFloater360Capture()
|
||||
|
|
@ -81,13 +79,15 @@ LLFloater360Capture::~LLFloater360Capture()
|
|||
mWebBrowser->unloadMediaSource();
|
||||
}
|
||||
|
||||
// Tell the Simulator not to send us everything anymore
|
||||
// and revert to the regular "keyhole" frustum of interest
|
||||
// Restore interest list mode to the state when started
|
||||
// Normally LLFloater360Capture tells the Simulator send everything
|
||||
// and now reverts to the regular "keyhole" frustum of interest
|
||||
// list updates.
|
||||
if (!LLApp::isExiting() && gSavedSettings.getBOOL("360CaptureUseInterestListCap"))
|
||||
if (!LLApp::isExiting() &&
|
||||
gSavedSettings.getBOOL("360CaptureUseInterestListCap") &&
|
||||
mStartILMode != gAgent.getInterestListMode())
|
||||
{
|
||||
const bool send_everything = false;
|
||||
changeInterestListMode(send_everything);
|
||||
gAgent.changeInterestListMode(mStartILMode);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,52 +170,6 @@ void LLFloater360Capture::onChooseQualityRadioGroup()
|
|||
setSourceImageSize();
|
||||
}
|
||||
|
||||
// Using a new capability, tell the simulator that we want it to send everything
|
||||
// it knows about and not just what is in front of the camera, in its view
|
||||
// frustum. We need this feature so that the contents of the region that appears
|
||||
// in the 6 snapshots which we cannot see and is normally not "considered", is
|
||||
// also rendered. Typically, this is turned on when the 360 capture floater is
|
||||
// opened and turned off when it is closed.
|
||||
// Note: for this version, we do not have a way to determine when "everything"
|
||||
// has arrived and has been rendered so for now, the proposal is that users
|
||||
// will need to experiment with the low resolution version and wait for some
|
||||
// (hopefully) small period of time while the full contents resolves.
|
||||
// Pass in a flag to ask the simulator/interest list to "send everything" or
|
||||
// not (the default mode)
|
||||
void LLFloater360Capture::changeInterestListMode(bool send_everything)
|
||||
{
|
||||
LLSD body;
|
||||
|
||||
if (send_everything)
|
||||
{
|
||||
body["mode"] = LLSD::String("360");
|
||||
}
|
||||
else
|
||||
{
|
||||
body["mode"] = LLSD::String("default");
|
||||
}
|
||||
|
||||
if (gAgent.requestPostCapability("InterestList", body, [](const LLSD & response)
|
||||
{
|
||||
LL_INFOS("360Capture") <<
|
||||
"InterestList capability responded: \n" <<
|
||||
ll_pretty_print_sd(response) <<
|
||||
LL_ENDL;
|
||||
}))
|
||||
{
|
||||
LL_INFOS("360Capture") <<
|
||||
"Successfully posted an InterestList capability request with payload: \n" <<
|
||||
ll_pretty_print_sd(body) <<
|
||||
LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("360Capture") <<
|
||||
"Unable to post an InterestList capability request with payload: \n" <<
|
||||
ll_pretty_print_sd(body) <<
|
||||
LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
// There is is a setting (360CaptureSourceImageSize) that holds the size
|
||||
// (width == height since it's a square) of each of the 6 source snapshots.
|
||||
|
|
@ -632,11 +586,8 @@ void LLFloater360Capture::capture360Images()
|
|||
// display time to encode all 6 images. It tends to be a fairly linear
|
||||
// time for each so we don't need to worry about displaying the time
|
||||
// for each - this gives us plenty to use for optimizing
|
||||
LL_INFOS("360Capture") <<
|
||||
"Time to encode and save 6 images was " <<
|
||||
encode_time_total <<
|
||||
" seconds" <<
|
||||
LL_ENDL;
|
||||
LL_INFOS("360Capture") << "Time to encode and save 6 images was " <<
|
||||
encode_time_total << " seconds" << LL_ENDL;
|
||||
|
||||
// Write the JavaScript file footer (the bottom of the file after the
|
||||
// declarations of the actual data URLs array). The footer comprises of
|
||||
|
|
@ -668,7 +619,7 @@ void LLFloater360Capture::capture360Images()
|
|||
// as a change - only the subsequent 5 are
|
||||
if (camera_changed_times < 5)
|
||||
{
|
||||
LL_INFOS("360Capture") << "Warning: we only captured " << camera_changed_times << " images." << LL_ENDL;
|
||||
LL_WARNS("360Capture") << "360 image capture expected 5 or more images, only captured " << camera_changed_times << " images." << LL_ENDL;
|
||||
}
|
||||
|
||||
// now we have the 6 shots saved in a well specified location,
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ class LLFloater360Capture:
|
|||
void onOpen(const LLSD& key) override;
|
||||
void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override;
|
||||
|
||||
void changeInterestListMode(bool send_everything);
|
||||
|
||||
const std::string getHTMLBaseFolder();
|
||||
void capture360Images();
|
||||
|
||||
|
|
@ -93,6 +91,8 @@ class LLFloater360Capture:
|
|||
std::string mImageSaveDir;
|
||||
|
||||
LLPointer<LLImageRaw> mRawImages[6];
|
||||
|
||||
std::string mStartILMode;
|
||||
};
|
||||
|
||||
#endif // LL_FLOATER_360CAPTURE_H
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloatercamera.h"
|
||||
#include "llfloatercamerapresets.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llnotificationsutil.h"
|
||||
|
|
@ -40,7 +41,8 @@ LLFloaterCameraPresets::~LLFloaterCameraPresets()
|
|||
BOOL LLFloaterCameraPresets::postBuild()
|
||||
{
|
||||
mPresetList = getChild<LLFlatListView>("preset_list");
|
||||
|
||||
mPresetList->setCommitCallback(boost::bind(&LLFloaterCameraPresets::onSelectionChange, this));
|
||||
mPresetList->setCommitOnSelectionChange(true);
|
||||
LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCameraPresets::populateList, this));
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -58,6 +60,7 @@ void LLFloaterCameraPresets::populateList()
|
|||
std::list<std::string> preset_names;
|
||||
|
||||
presetsMgr->loadPresetNamesFromDir(PRESETS_CAMERA, preset_names, DEFAULT_BOTTOM);
|
||||
std::string active_preset = gSavedSettings.getString("PresetCameraActive");
|
||||
|
||||
for (std::list<std::string>::const_iterator it = preset_names.begin(); it != preset_names.end(); ++it)
|
||||
{
|
||||
|
|
@ -66,6 +69,19 @@ void LLFloaterCameraPresets::populateList()
|
|||
LLCameraPresetFlatItem* item = new LLCameraPresetFlatItem(name, is_default);
|
||||
item->postBuild();
|
||||
mPresetList->addItem(item);
|
||||
if(name == active_preset)
|
||||
{
|
||||
mPresetList->selectItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterCameraPresets::onSelectionChange()
|
||||
{
|
||||
LLCameraPresetFlatItem* selected_preset = dynamic_cast<LLCameraPresetFlatItem*>(mPresetList->getSelectedItem());
|
||||
if(selected_preset)
|
||||
{
|
||||
LLFloaterCamera::switchToPreset(selected_preset->getPresetName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class LLFloaterCameraPresets : public LLFloater
|
|||
virtual void onOpen(const LLSD& key);
|
||||
|
||||
void populateList();
|
||||
void onSelectionChange();
|
||||
|
||||
private:
|
||||
LLFloaterCameraPresets(const LLSD& key);
|
||||
|
|
@ -58,6 +59,8 @@ public:
|
|||
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
|
||||
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
|
||||
|
||||
std::string getPresetName() { return mPresetName; }
|
||||
|
||||
private:
|
||||
void onDeleteBtnClick();
|
||||
void onResetBtnClick();
|
||||
|
|
|
|||
|
|
@ -92,8 +92,10 @@ class LLExperienceHandler : public LLCommandHandler
|
|||
public:
|
||||
LLExperienceHandler() : LLCommandHandler("experience", UNTRUSTED_THROTTLE) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if(params.size() != 2 || params[1].asString() != "profile")
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ LLFloater* get_parent_floater(LLView* view)
|
|||
}
|
||||
|
||||
|
||||
bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, LLMediaCtrl *web)
|
||||
bool LLFloaterHandler::handle(const LLSD ¶ms, const LLSD &query_map, const std::string& grid, LLMediaCtrl *web)
|
||||
{
|
||||
if (params.size() < 1) return false;
|
||||
LLFloater* floater = NULL;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class LLFloaterHandler
|
|||
{
|
||||
public:
|
||||
LLFloaterHandler() : LLCommandHandler("floater", UNTRUSTED_BLOCK) { }
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web);
|
||||
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -903,8 +903,10 @@ public:
|
|||
LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { }
|
||||
|
||||
// Your code here
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& tokens,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
bool retval = false;
|
||||
// Need at least 2 tokens to have a valid message.
|
||||
|
|
|
|||
|
|
@ -2795,7 +2795,7 @@ BOOL LLPanelEstateAccess::postBuild()
|
|||
if (banned_name_list)
|
||||
{
|
||||
banned_name_list->setCommitOnSelectionChange(TRUE);
|
||||
banned_name_list->setMaxItemCount(ESTATE_MAX_ACCESS_IDS);
|
||||
banned_name_list->setMaxItemCount(ESTATE_MAX_BANNED_IDS);
|
||||
}
|
||||
|
||||
getChild<LLUICtrl>("banned_search_input")->setCommitCallback(boost::bind(&LLPanelEstateAccess::onBannedSearchEdit, this, _2));
|
||||
|
|
@ -2939,10 +2939,10 @@ void LLPanelEstateAccess::onClickAddBannedAgent()
|
|||
{
|
||||
LLCtrlListInterface *list = childGetListInterface("banned_avatar_name_list");
|
||||
if (!list) return;
|
||||
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
|
||||
if (list->getItemCount() >= ESTATE_MAX_BANNED_IDS)
|
||||
{
|
||||
LLSD args;
|
||||
args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
|
||||
args["MAX_BANNED"] = llformat("%d", ESTATE_MAX_BANNED_IDS);
|
||||
LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args);
|
||||
return;
|
||||
}
|
||||
|
|
@ -3180,13 +3180,13 @@ void LLPanelEstateAccess::accessAddCore3(const uuid_vec_t& ids, std::vector<LLAv
|
|||
LLNameListCtrl* name_list = panel->getChild<LLNameListCtrl>("banned_avatar_name_list");
|
||||
LLNameListCtrl* em_list = panel->getChild<LLNameListCtrl>("estate_manager_name_list");
|
||||
int currentCount = (name_list ? name_list->getItemCount() : 0);
|
||||
if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS)
|
||||
if (ids.size() + currentCount > ESTATE_MAX_BANNED_IDS)
|
||||
{
|
||||
LLSD args;
|
||||
args["NUM_ADDED"] = llformat("%d", ids.size());
|
||||
args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
|
||||
args["MAX_AGENTS"] = llformat("%d", ESTATE_MAX_BANNED_IDS);
|
||||
args["LIST_TYPE"] = LLTrans::getString("RegionInfoListTypeBannedAgents");
|
||||
args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_ACCESS_IDS);
|
||||
args["NUM_EXCESS"] = llformat("%d", (ids.size() + currentCount) - ESTATE_MAX_BANNED_IDS);
|
||||
LLNotificationsUtil::add("MaxAgentOnRegionBatch", args);
|
||||
delete change_info;
|
||||
return;
|
||||
|
|
@ -3565,7 +3565,7 @@ void LLPanelEstateAccess::requestEstateGetAccessCoro(std::string url)
|
|||
{
|
||||
LLStringUtil::format_map_t args;
|
||||
args["[BANNEDAGENTS]"] = llformat("%d", result["BannedAgents"].size());
|
||||
args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_ACCESS_IDS);
|
||||
args["[MAXBANNED]"] = llformat("%d", ESTATE_MAX_BANNED_IDS);
|
||||
std::string msg = LLTrans::getString("RegionInfoBannedResidents", args);
|
||||
panel->getChild<LLUICtrl>("ban_resident_label")->setValue(LLSD(msg));
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class LLSearchHandler : public LLCommandHandler
|
|||
public:
|
||||
// requires trusted browser to trigger
|
||||
LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "llviewerparcelmgr.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "lluictrlfactory.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llfloaterregioninfo.h"
|
||||
|
||||
|
|
@ -83,6 +84,8 @@ LLFloaterTopObjects::LLFloaterTopObjects(const LLSD& key)
|
|||
mCommitCallbackRegistrar.add("TopObjects.GetByOwnerName", boost::bind(&LLFloaterTopObjects::onGetByOwnerName, this));
|
||||
mCommitCallbackRegistrar.add("TopObjects.GetByParcelName", boost::bind(&LLFloaterTopObjects::onGetByParcelName, this));
|
||||
mCommitCallbackRegistrar.add("TopObjects.CommitObjectsList",boost::bind(&LLFloaterTopObjects::onCommitObjectsList, this));
|
||||
|
||||
mCommitCallbackRegistrar.add("TopObjects.TeleportToSelected", boost::bind(&LLFloaterTopObjects::teleportToSelectedObject, this));
|
||||
}
|
||||
|
||||
LLFloaterTopObjects::~LLFloaterTopObjects()
|
||||
|
|
@ -92,10 +95,11 @@ LLFloaterTopObjects::~LLFloaterTopObjects()
|
|||
// virtual
|
||||
BOOL LLFloaterTopObjects::postBuild()
|
||||
{
|
||||
LLScrollListCtrl *objects_list = getChild<LLScrollListCtrl>("objects_list");
|
||||
getChild<LLUICtrl>("objects_list")->setFocus(TRUE);
|
||||
objects_list->setDoubleClickCallback(onDoubleClickObjectsList, this);
|
||||
objects_list->setCommitOnSelectionChange(TRUE);
|
||||
mObjectsScrollList = getChild<LLScrollListCtrl>("objects_list");
|
||||
mObjectsScrollList->setFocus(TRUE);
|
||||
mObjectsScrollList->setDoubleClickCallback(onDoubleClickObjectsList, this);
|
||||
mObjectsScrollList->setCommitOnSelectionChange(TRUE);
|
||||
mObjectsScrollList->setCommitCallback(boost::bind(&LLFloaterTopObjects::onSelectionChanged, this));
|
||||
|
||||
setDefaultBtn("show_beacon_btn");
|
||||
|
||||
|
|
@ -421,6 +425,8 @@ void LLFloaterTopObjects::clearList()
|
|||
mObjectListData.clear();
|
||||
mObjectListIDs.clear();
|
||||
mtotalScore = 0.f;
|
||||
|
||||
onSelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -507,3 +513,38 @@ void LLFloaterTopObjects::showBeacon()
|
|||
std::string tooltip("");
|
||||
LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);
|
||||
}
|
||||
|
||||
void LLFloaterTopObjects::teleportToSelectedObject()
|
||||
{
|
||||
std::vector<LLScrollListItem*> selected_items = mObjectsScrollList->getAllSelected();
|
||||
if (selected_items.size() == 1)
|
||||
{
|
||||
LLScrollListItem* first_selected = selected_items.front();
|
||||
|
||||
LLVector3d teleport_location;
|
||||
LLViewerObject *viewer_object = gObjectList.findObject(first_selected->getUUID());
|
||||
if (viewer_object == NULL)
|
||||
{
|
||||
// If we cannot find the object in the viewer list, teleport to the last reported position
|
||||
std::string pos_string = first_selected->getColumn(3)->getValue().asString();
|
||||
|
||||
F32 x, y, z;
|
||||
S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
|
||||
if (matched != 3) return;
|
||||
|
||||
LLVector3 pos_agent(x, y, z);
|
||||
teleport_location = gAgent.getPosGlobalFromAgent(pos_agent);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we can find the object in the viewer list, teleport to the known current position
|
||||
teleport_location = viewer_object->getPositionGlobal();
|
||||
}
|
||||
gAgent.teleportViaLocationLookAt(teleport_location);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterTopObjects::onSelectionChanged()
|
||||
{
|
||||
getChildView("teleport_btn")->setEnabled(mObjectsScrollList->getNumSelected() == 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llfloater.h"
|
||||
|
||||
class LLUICtrl;
|
||||
class LLScrollListCtrl;
|
||||
|
||||
// Bits for simulator performance query flags
|
||||
enum LAND_STAT_FLAGS
|
||||
|
|
@ -75,6 +76,7 @@ private:
|
|||
void initColumns(LLCtrlListInterface *list);
|
||||
|
||||
void onCommitObjectsList();
|
||||
void onSelectionChanged();
|
||||
static void onDoubleClickObjectsList(void* data);
|
||||
void onClickShowBeacon();
|
||||
|
||||
|
|
@ -90,6 +92,7 @@ private:
|
|||
void onGetByParcelName();
|
||||
|
||||
void showBeacon();
|
||||
void teleportToSelectedObject();
|
||||
|
||||
private:
|
||||
std::string mMethod;
|
||||
|
|
@ -106,6 +109,7 @@ private:
|
|||
F32 mtotalScore;
|
||||
|
||||
static LLFloaterTopObjects* sInstance;
|
||||
LLScrollListCtrl* mObjectsScrollList;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -124,8 +124,10 @@ public:
|
|||
// requires trusted browser to trigger
|
||||
LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap"))
|
||||
{
|
||||
|
|
@ -163,7 +165,10 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableWorldMap"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -741,6 +741,12 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV
|
|||
gGL.end();
|
||||
}
|
||||
|
||||
void LLViewerParcelMgr::resetCollisionTimer()
|
||||
{
|
||||
mCollisionTimer.reset();
|
||||
mRenderCollision = TRUE;
|
||||
}
|
||||
|
||||
void draw_line_cube(F32 width, const LLVector3& center)
|
||||
{
|
||||
width = 0.5f * width;
|
||||
|
|
|
|||
|
|
@ -78,8 +78,10 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& tokens,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (LLStartUp::getStartupState() < STATE_STARTED)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1631,14 +1631,19 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
|
|||
from_group = message_data["from_group"].asString() == "Y";
|
||||
}
|
||||
|
||||
|
||||
EInstantMessage dialog = static_cast<EInstantMessage>(message_data["dialog"].asInteger());
|
||||
LLUUID session_id = message_data["transaction-id"].asUUID();
|
||||
if (session_id.isNull() && dialog == IM_FROM_TASK)
|
||||
{
|
||||
session_id = message_data["asset_id"].asUUID();
|
||||
}
|
||||
LLIMProcessing::processNewMessage(
|
||||
message_data["from_agent_id"].asUUID(),
|
||||
from_group,
|
||||
message_data["to_agent_id"].asUUID(),
|
||||
message_data.has("offline") ? static_cast<U8>(message_data["offline"].asInteger()) : IM_OFFLINE,
|
||||
static_cast<EInstantMessage>(message_data["dialog"].asInteger()),
|
||||
message_data["transaction-id"].asUUID(),
|
||||
dialog,
|
||||
session_id,
|
||||
static_cast<U32>(message_data["timestamp"].asInteger()),
|
||||
message_data["from_agent_name"].asString(),
|
||||
message_data["message"].asString(),
|
||||
|
|
|
|||
|
|
@ -213,8 +213,7 @@ bool contains_nocopy_items(const LLUUID& id)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Generates a string containing the path to the item specified by
|
||||
// item_id.
|
||||
// Generates a string containing the path to the item specified by id.
|
||||
void append_path(const LLUUID& id, std::string& path)
|
||||
{
|
||||
std::string temp;
|
||||
|
|
@ -234,6 +233,36 @@ void append_path(const LLUUID& id, std::string& path)
|
|||
path.append(temp);
|
||||
}
|
||||
|
||||
// Generates a string containing the path name of the object.
|
||||
std::string make_path(const LLInventoryObject* object)
|
||||
{
|
||||
std::string path;
|
||||
append_path(object->getUUID(), path);
|
||||
return path + "/" + object->getName();
|
||||
}
|
||||
|
||||
// Generates a string containing the path name of the object specified by id.
|
||||
std::string make_inventory_path(const LLUUID& id)
|
||||
{
|
||||
if (LLInventoryObject* object = gInventory.getObject(id))
|
||||
return make_path(object);
|
||||
return "";
|
||||
}
|
||||
|
||||
// Generates a string containing the path name and id of the object.
|
||||
std::string make_info(const LLInventoryObject* object)
|
||||
{
|
||||
return "'" + make_path(object) + "' (" + object->getUUID().asString() + ")";
|
||||
}
|
||||
|
||||
// Generates a string containing the path name and id of the object specified by id.
|
||||
std::string make_inventory_info(const LLUUID& id)
|
||||
{
|
||||
if (LLInventoryObject* object = gInventory.getObject(id))
|
||||
return make_info(object);
|
||||
return "<Inventory object not found!> (" + id.asString() + ")";
|
||||
}
|
||||
|
||||
void update_marketplace_folder_hierarchy(const LLUUID cat_id)
|
||||
{
|
||||
// When changing the marketplace status of a folder, the only thing that needs to happen is
|
||||
|
|
@ -1415,6 +1444,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
|
|||
if (copy)
|
||||
{
|
||||
// Copy the item
|
||||
LL_INFOS("SLM") << "Copy item '" << make_info(viewer_inv_item) << "' to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL;
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder));
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
|
|
@ -1426,6 +1456,7 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("SLM") << "Move item '" << make_info(viewer_inv_item) << "' to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL;
|
||||
// Reparent the item
|
||||
gInventory.changeItemParent(viewer_inv_item, dest_folder, true);
|
||||
}
|
||||
|
|
@ -1472,6 +1503,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("SLM") << "Move category " << make_info(viewer_inv_cat) << " to '" << make_inventory_path(dest_folder) << "'" << LL_ENDL;
|
||||
// Reparent the folder
|
||||
gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false);
|
||||
// Check the destination folder recursively for no copy items and promote the including folders if any
|
||||
|
|
|
|||
|
|
@ -78,9 +78,19 @@ void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory*
|
|||
|
||||
void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items);
|
||||
|
||||
// Generates a string containing the path to the item specified by item_id.
|
||||
// Generates a string containing the path to the object specified by id (not including the object name).
|
||||
void append_path(const LLUUID& id, std::string& path);
|
||||
|
||||
// Generates a string containing the path name of the object.
|
||||
std::string make_path(const LLInventoryObject* object);
|
||||
// Generates a string containing the path name of the object specified by id.
|
||||
std::string make_inventory_path(const LLUUID& id);
|
||||
|
||||
// Generates a string containing the path name and id of the object.
|
||||
std::string make_info(const LLInventoryObject* object);
|
||||
// Generates a string containing the path name and id of the object specified by id.
|
||||
std::string make_inventory_info(const LLUUID& id);
|
||||
|
||||
typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t;
|
||||
|
||||
bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@
|
|||
#include "bufferarray.h"
|
||||
#include "bufferstream.h"
|
||||
#include "llcorehttputil.h"
|
||||
#include "hbxxh.h"
|
||||
|
||||
//#define DIFF_INVENTORY_FILES
|
||||
#ifdef DIFF_INVENTORY_FILES
|
||||
|
|
@ -449,17 +450,16 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id,
|
|||
items = get_ptr_in_map(mParentChildItemTree, cat_id);
|
||||
}
|
||||
|
||||
LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
|
||||
LLInventoryModel::digest_t LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
|
||||
{
|
||||
LLInventoryModel::cat_array_t* cat_array;
|
||||
LLInventoryModel::item_array_t* item_array;
|
||||
getDirectDescendentsOf(cat_id,cat_array,item_array);
|
||||
LLMD5 item_name_hash;
|
||||
if (!item_array)
|
||||
{
|
||||
item_name_hash.finalize();
|
||||
return item_name_hash;
|
||||
return LLUUID::null;
|
||||
}
|
||||
HBXXH128 item_name_hash;
|
||||
for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin();
|
||||
iter != item_array->end();
|
||||
iter++)
|
||||
|
|
@ -469,8 +469,7 @@ LLMD5 LLInventoryModel::hashDirectDescendentNames(const LLUUID& cat_id) const
|
|||
continue;
|
||||
item_name_hash.update(item->getName());
|
||||
}
|
||||
item_name_hash.finalize();
|
||||
return item_name_hash;
|
||||
return item_name_hash.digest();
|
||||
}
|
||||
|
||||
// SJB: Added version to lock the arrays to catch potential logic bugs
|
||||
|
|
@ -676,6 +675,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
|||
const std::string& pname,
|
||||
inventory_func_type callback)
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "Create '" << pname << "' in '" << make_inventory_path(parent_id) << "'" << LL_ENDL;
|
||||
LLUUID id;
|
||||
if (!isInventoryUsable())
|
||||
{
|
||||
|
|
@ -767,6 +767,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
|
|||
cat->packMessage(msg);
|
||||
gAgent.sendReliableMessage();
|
||||
|
||||
LL_INFOS(LOG_INV) << "Created new category '" << make_inventory_path(id) << "'" << LL_ENDL;
|
||||
// return the folder id of the newly created folder
|
||||
return id;
|
||||
}
|
||||
|
|
@ -1355,6 +1356,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
|
|||
LLPointer<LLViewerInventoryCategory> cat = getCategory(object_id);
|
||||
if(cat && (cat->getParentUUID() != cat_id))
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "Move category '" << make_path(cat) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
|
||||
cat_array_t* cat_array;
|
||||
cat_array = getUnlockedCatArray(cat->getParentUUID());
|
||||
if(cat_array) vector_replace_with_last(*cat_array, cat);
|
||||
|
|
@ -1367,6 +1369,7 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
|
|||
LLPointer<LLViewerInventoryItem> item = getItem(object_id);
|
||||
if(item && (item->getParentUUID() != cat_id))
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "Move item '" << make_path(item) << "' to '" << make_inventory_path(cat_id) << "'" << LL_ENDL;
|
||||
item_array_t* item_array;
|
||||
item_array = getUnlockedItemArray(item->getParentUUID());
|
||||
if(item_array) vector_replace_with_last(*item_array, item);
|
||||
|
|
@ -1385,14 +1388,14 @@ void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item,
|
|||
{
|
||||
if (item->getParentUUID() == new_parent_id)
|
||||
{
|
||||
LL_DEBUGS(LOG_INV) << "'" << item->getName() << "' (" << item->getUUID()
|
||||
<< ") is already in folder " << new_parent_id << LL_ENDL;
|
||||
LL_DEBUGS(LOG_INV) << make_info(item) << " is already in folder " << make_inventory_info(new_parent_id) << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS(LOG_INV) << "Moving '" << item->getName() << "' (" << item->getUUID()
|
||||
<< ") from " << item->getParentUUID() << " to folder "
|
||||
<< new_parent_id << LL_ENDL;
|
||||
LL_INFOS(LOG_INV) << "Move item " << make_info(item)
|
||||
<< " from " << make_inventory_info(item->getParentUUID())
|
||||
<< " to " << make_inventory_info(new_parent_id) << LL_ENDL;
|
||||
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
|
||||
update.push_back(old_folder);
|
||||
|
|
@ -1424,6 +1427,10 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
|
|||
return;
|
||||
}
|
||||
|
||||
LL_INFOS(LOG_INV) << "Move category " << make_info(cat)
|
||||
<< " from " << make_inventory_info(cat->getParentUUID())
|
||||
<< " to " << make_inventory_info(new_parent_id) << LL_ENDL;
|
||||
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
|
||||
update.push_back(old_folder);
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include "llpermissionsflags.h"
|
||||
#include "llviewerinventory.h"
|
||||
#include "llstring.h"
|
||||
#include "llmd5.h"
|
||||
#include "httpcommon.h"
|
||||
#include "httprequest.h"
|
||||
#include "httpoptions.h"
|
||||
|
|
@ -257,8 +256,9 @@ public:
|
|||
cat_array_t*& categories,
|
||||
item_array_t*& items) const;
|
||||
|
||||
typedef LLUUID digest_t; // To clarify the actual usage of this "UUID"
|
||||
// Compute a hash of direct descendant names (for detecting child name changes)
|
||||
LLMD5 hashDirectDescendentNames(const LLUUID& cat_id) const;
|
||||
digest_t hashDirectDescendentNames(const LLUUID& cat_id) const;
|
||||
|
||||
// Starting with the object specified, add its descendants to the
|
||||
// array provided, but do not add the inventory object specified
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
|
|||
// computed, or (b) a name has changed.
|
||||
if (!cat_data.mIsNameHashInitialized || (mask & LLInventoryObserver::LABEL))
|
||||
{
|
||||
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
|
||||
digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
|
||||
if (cat_data.mItemNameHash != item_name_hash)
|
||||
{
|
||||
cat_data.mIsNameHashInitialized = true;
|
||||
|
|
@ -701,7 +701,7 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t
|
|||
{
|
||||
if(init_name_hash)
|
||||
{
|
||||
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
|
||||
digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
|
||||
mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, cb, version, current_num_known_descendents,item_name_hash)));
|
||||
}
|
||||
else
|
||||
|
|
@ -727,11 +727,10 @@ LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
|
|||
, mDescendentsCount(num_descendents)
|
||||
, mIsNameHashInitialized(false)
|
||||
{
|
||||
mItemNameHash.finalize();
|
||||
}
|
||||
|
||||
LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
|
||||
const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash)
|
||||
const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash)
|
||||
|
||||
: mCatID(cat_id)
|
||||
, mCallback(cb)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#define LL_LLINVENTORYOBSERVERS_H
|
||||
|
||||
#include "lluuid.h"
|
||||
#include "llmd5.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -271,14 +270,15 @@ public:
|
|||
void removeCategory(const LLUUID& cat_id);
|
||||
|
||||
protected:
|
||||
typedef LLUUID digest_t; // To clarify the actual usage of this "UUID"
|
||||
struct LLCategoryData
|
||||
{
|
||||
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents);
|
||||
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, LLMD5 name_hash);
|
||||
LLCategoryData(const LLUUID& cat_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash);
|
||||
callback_t mCallback;
|
||||
S32 mVersion;
|
||||
S32 mDescendentsCount;
|
||||
LLMD5 mItemNameHash;
|
||||
digest_t mItemNameHash;
|
||||
bool mIsNameHashInitialized;
|
||||
LLUUID mCatID;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ void LLLoginHandler::parse(const LLSD& queryMap)
|
|||
|
||||
bool LLLoginHandler::handle(const LLSD& tokens,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
// do nothing if we are already logged in
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class LLLoginHandler : public LLCommandHandler
|
|||
public:
|
||||
// allow from external browsers
|
||||
LLLoginHandler() : LLCommandHandler("login", UNTRUSTED_ALLOW) { }
|
||||
/*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web);
|
||||
/*virtual*/ bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web);
|
||||
|
||||
// Fill in our internal fields from a SLURL like
|
||||
// secondlife:///app/login?first=Bob&last=Dobbs
|
||||
|
|
|
|||
|
|
@ -1197,10 +1197,16 @@ bool LLMaterialEditor::saveIfNeeded()
|
|||
}
|
||||
else
|
||||
{
|
||||
//make a new inventory item
|
||||
std::string res_desc = buildMaterialDescription();
|
||||
// Make a new inventory item and set upload permissions
|
||||
LLPermissions local_permissions;
|
||||
local_permissions.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
|
||||
|
||||
U32 everyone_perm = LLFloaterPerms::getEveryonePerms("Materials");
|
||||
U32 group_perm = LLFloaterPerms::getGroupPerms("Materials");
|
||||
U32 next_owner_perm = LLFloaterPerms::getNextOwnerPerms("Materials");
|
||||
local_permissions.initMasks(PERM_ALL, PERM_ALL, everyone_perm, group_perm, next_owner_perm);
|
||||
|
||||
std::string res_desc = buildMaterialDescription();
|
||||
createInventoryItem(buffer, mMaterialName, res_desc, local_permissions);
|
||||
|
||||
// We do not update floater with uploaded asset yet, so just close it.
|
||||
|
|
@ -1947,6 +1953,32 @@ bool LLMaterialEditor::canSaveObjectsMaterial()
|
|||
return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY}), permissions, item_out);
|
||||
}
|
||||
|
||||
bool LLMaterialEditor::canClipboardObjectsMaterial()
|
||||
{
|
||||
if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct LLSelectedTEGetNullMat : public LLSelectedTEFunctor
|
||||
{
|
||||
bool apply(LLViewerObject* objectp, S32 te_index)
|
||||
{
|
||||
return objectp->getRenderMaterialID(te_index).isNull();
|
||||
}
|
||||
} null_func;
|
||||
|
||||
if (LLSelectMgr::getInstance()->getSelection()->applyToTEs(&null_func))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
LLSelectedTEGetMatData func(true);
|
||||
LLPermissions permissions;
|
||||
LLViewerInventoryItem* item_out;
|
||||
return can_use_objects_material(func, std::vector({PERM_COPY, PERM_MODIFY, PERM_TRANSFER}), permissions, item_out);
|
||||
}
|
||||
|
||||
void LLMaterialEditor::saveObjectsMaterialAs()
|
||||
{
|
||||
LLSelectedTEGetMatData func(true);
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
|
|||
|
||||
static bool canModifyObjectsMaterial();
|
||||
static bool canSaveObjectsMaterial();
|
||||
static bool canClipboardObjectsMaterial();
|
||||
static void saveObjectsMaterialAs();
|
||||
static void onCopyObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions, const LLUUID& object_id, const LLUUID& item_id);
|
||||
static void onSaveObjectsMaterialAsMsgCallback(const LLSD& notification, const LLSD& response, const LLPermissions& permissions);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,11 @@ private:
|
|||
|
||||
bool operator==(const TEMaterialPair& b) const { return (materialID == b.materialID) && (te == b.te); }
|
||||
};
|
||||
|
||||
|
||||
// definitions follow class
|
||||
friend std::hash<TEMaterialPair>;
|
||||
friend size_t hash_value(const TEMaterialPair&) noexcept;
|
||||
|
||||
friend inline bool operator<(
|
||||
const LLMaterialMgr::TEMaterialPair& lhs,
|
||||
const LLMaterialMgr::TEMaterialPair& rhs)
|
||||
|
|
@ -102,13 +106,6 @@ private:
|
|||
(lhs.materialID < rhs.materialID);
|
||||
}
|
||||
|
||||
struct TEMaterialPairHasher
|
||||
{
|
||||
enum { bucket_size = 8 };
|
||||
size_t operator()(const TEMaterialPair& key_value) const { return *((size_t*)key_value.materialID.get()); } // cheesy, but effective
|
||||
bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; }
|
||||
};
|
||||
|
||||
typedef std::set<LLMaterialID> material_queue_t;
|
||||
typedef std::map<LLUUID, material_queue_t> get_queue_t;
|
||||
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
|
||||
|
|
@ -116,7 +113,7 @@ private:
|
|||
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
|
||||
|
||||
|
||||
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
|
||||
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
|
||||
typedef std::set<LLUUID> getall_queue_t;
|
||||
typedef std::map<LLUUID, F64> getall_pending_map_t;
|
||||
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
|
||||
|
|
@ -145,5 +142,23 @@ private:
|
|||
U32 getMaxEntries(const LLViewerRegion* regionp);
|
||||
};
|
||||
|
||||
// std::hash implementation for TEMaterialPair
|
||||
namespace std
|
||||
{
|
||||
template<> struct hash<LLMaterialMgr::TEMaterialPair>
|
||||
{
|
||||
inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept
|
||||
{
|
||||
return size_t((p.te + 1) * p.materialID.getDigest64());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// For use with boost containers.
|
||||
inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept
|
||||
{
|
||||
return size_t((p.te + 1) * p.materialID.getDigest64());
|
||||
}
|
||||
|
||||
#endif // LL_LLMATERIALMGR_H
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "llviewermessage.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewerstatsrecorder.h"
|
||||
#include "llviewertexturelist.h"
|
||||
#include "llvolume.h"
|
||||
#include "llvolumemgr.h"
|
||||
|
|
@ -1861,8 +1862,8 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
|
|||
LLSD header_data;
|
||||
|
||||
LLMeshHeader header;
|
||||
|
||||
size_t header_size = 0;
|
||||
|
||||
llssize header_size = 0;
|
||||
if (data_size > 0)
|
||||
{
|
||||
llssize dsize = data_size;
|
||||
|
|
@ -4087,6 +4088,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
|
|||
}
|
||||
|
||||
mLoadingMeshes[detail].erase(obj_iter);
|
||||
|
||||
LLViewerStatsRecorder::instance().meshLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
LLOutfitObserver::LLOutfitObserver() :
|
||||
mCOFLastVersion(LLViewerInventoryCategory::VERSION_UNKNOWN)
|
||||
{
|
||||
mItemNameHash.finalize();
|
||||
gInventory.addObserver(this);
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ bool LLOutfitObserver::checkCOF()
|
|||
return false;
|
||||
|
||||
bool cof_changed = false;
|
||||
LLMD5 item_name_hash = gInventory.hashDirectDescendentNames(cof);
|
||||
LLUUID item_name_hash = gInventory.hashDirectDescendentNames(cof);
|
||||
if (item_name_hash != mItemNameHash)
|
||||
{
|
||||
cof_changed = true;
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
#define LL_OUTFITOBSERVER_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "llmd5.h"
|
||||
|
||||
/**
|
||||
* Outfit observer facade that provides simple possibility to subscribe on
|
||||
|
|
@ -78,7 +77,7 @@ protected:
|
|||
|
||||
bool mLastOutfitDirtiness;
|
||||
|
||||
LLMD5 mItemNameHash;
|
||||
LLUUID mItemNameHash;
|
||||
|
||||
private:
|
||||
signal_t mBOFReplaced;
|
||||
|
|
|
|||
|
|
@ -1664,7 +1664,7 @@ class LLMetricSystemHandler : public LLCommandHandler
|
|||
public:
|
||||
LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_CLICK_ONLY) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
// change height units TRUE for meters and FALSE for feet
|
||||
BOOL new_value = (gSavedSettings.getBOOL("HeightUnits") == FALSE) ? TRUE : FALSE;
|
||||
|
|
|
|||
|
|
@ -1975,7 +1975,8 @@ void LLPanelFace::updateCopyTexButton()
|
|||
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
|
||||
mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()
|
||||
&& !objectp->isPermanentEnforced() && !objectp->isInventoryPending()
|
||||
&& (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1));
|
||||
&& (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)
|
||||
&& LLMaterialEditor::canClipboardObjectsMaterial());
|
||||
std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options");
|
||||
mMenuClipboardTexture->setToolTip(tooltip);
|
||||
}
|
||||
|
|
@ -4147,7 +4148,8 @@ void LLPanelFace::onCopyTexture()
|
|||
|| objectp->getPCode() != LL_PCODE_VOLUME
|
||||
|| !objectp->permModify()
|
||||
|| objectp->isPermanentEnforced()
|
||||
|| selected_count > 1)
|
||||
|| selected_count > 1
|
||||
|| !LLMaterialEditor::canClipboardObjectsMaterial())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -4342,7 +4344,8 @@ void LLPanelFace::onPasteTexture()
|
|||
|| objectp->getPCode() != LL_PCODE_VOLUME
|
||||
|| !objectp->permModify()
|
||||
|| objectp->isPermanentEnforced()
|
||||
|| selected_count > 1)
|
||||
|| selected_count > 1
|
||||
|| !LLMaterialEditor::canClipboardObjectsMaterial())
|
||||
{
|
||||
// not supposed to happen
|
||||
LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class LLLoginLocationAutoHandler : public LLCommandHandler
|
|||
public:
|
||||
// don't allow from external browsers
|
||||
LLLoginLocationAutoHandler() : LLCommandHandler("location_login", UNTRUSTED_BLOCK) { }
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web)
|
||||
{
|
||||
if (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,30 +76,34 @@ std::string click_action_to_string_value( U8 action);
|
|||
|
||||
U8 string_value_to_click_action(std::string p_value)
|
||||
{
|
||||
if(p_value == "Touch")
|
||||
if (p_value == "Touch")
|
||||
{
|
||||
return CLICK_ACTION_TOUCH;
|
||||
}
|
||||
if(p_value == "Sit")
|
||||
if (p_value == "Sit")
|
||||
{
|
||||
return CLICK_ACTION_SIT;
|
||||
}
|
||||
if(p_value == "Buy")
|
||||
if (p_value == "Buy")
|
||||
{
|
||||
return CLICK_ACTION_BUY;
|
||||
}
|
||||
if(p_value == "Pay")
|
||||
if (p_value == "Pay")
|
||||
{
|
||||
return CLICK_ACTION_PAY;
|
||||
}
|
||||
if(p_value == "Open")
|
||||
if (p_value == "Open")
|
||||
{
|
||||
return CLICK_ACTION_OPEN;
|
||||
}
|
||||
if(p_value == "Zoom")
|
||||
if (p_value == "Zoom")
|
||||
{
|
||||
return CLICK_ACTION_ZOOM;
|
||||
}
|
||||
if (p_value == "Ignore")
|
||||
{
|
||||
return CLICK_ACTION_IGNORE;
|
||||
}
|
||||
if (p_value == "None")
|
||||
{
|
||||
return CLICK_ACTION_DISABLED;
|
||||
|
|
@ -130,6 +134,9 @@ std::string click_action_to_string_value( U8 action)
|
|||
case CLICK_ACTION_ZOOM:
|
||||
return "Zoom";
|
||||
break;
|
||||
case CLICK_ACTION_IGNORE:
|
||||
return "Ignore";
|
||||
break;
|
||||
case CLICK_ACTION_DISABLED:
|
||||
return "None";
|
||||
break;
|
||||
|
|
@ -274,12 +281,12 @@ void LLPanelPermissions::disableAll()
|
|||
combo_click_action->setEnabled(FALSE);
|
||||
combo_click_action->clear();
|
||||
}
|
||||
getChildView("B:")->setVisible( FALSE);
|
||||
getChildView("O:")->setVisible( FALSE);
|
||||
getChildView("G:")->setVisible( FALSE);
|
||||
getChildView("E:")->setVisible( FALSE);
|
||||
getChildView("N:")->setVisible( FALSE);
|
||||
getChildView("F:")->setVisible( FALSE);
|
||||
getChildView("B:")->setVisible(FALSE);
|
||||
getChildView("O:")->setVisible(FALSE);
|
||||
getChildView("G:")->setVisible(FALSE);
|
||||
getChildView("E:")->setVisible(FALSE);
|
||||
getChildView("N:")->setVisible(FALSE);
|
||||
getChildView("F:")->setVisible(FALSE);
|
||||
}
|
||||
|
||||
void LLPanelPermissions::refresh()
|
||||
|
|
@ -949,19 +956,19 @@ void LLPanelPermissions::refresh()
|
|||
getChild<LLUICtrl>("search_check")->setValue(include_in_search);
|
||||
getChild<LLUICtrl>("search_check")->setTentative( !all_include_in_search);
|
||||
|
||||
// Click action (touch, sit, buy)
|
||||
// Click action (touch, sit, buy, pay, open, play, open media, zoom, ignore)
|
||||
U8 click_action = 0;
|
||||
if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action))
|
||||
{
|
||||
LLComboBox* combo_click_action = getChild<LLComboBox>("clickaction");
|
||||
if(combo_click_action)
|
||||
if (combo_click_action)
|
||||
{
|
||||
const std::string combo_value = click_action_to_string_value(click_action);
|
||||
combo_click_action->setValue(LLSD(combo_value));
|
||||
}
|
||||
}
|
||||
|
||||
if(LLSelectMgr::getInstance()->getSelection()->isAttachment())
|
||||
if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
|
||||
{
|
||||
getChildView("checkbox for sale")->setEnabled(FALSE);
|
||||
getChildView("Edit Cost")->setEnabled(FALSE);
|
||||
|
|
|
|||
|
|
@ -91,8 +91,10 @@ class LLParcelHandler : public LLCommandHandler
|
|||
public:
|
||||
// requires trusted browser to trigger
|
||||
LLParcelHandler() : LLCommandHandler("parcel", UNTRUSTED_THROTTLE) { }
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -461,8 +461,10 @@ public:
|
|||
// requires trusted browser to trigger
|
||||
LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 1) return false;
|
||||
std::string agent_name = params[0];
|
||||
|
|
@ -509,8 +511,10 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map,
|
||||
LLMediaCtrl* web)
|
||||
bool handle(const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
const std::string& grid,
|
||||
LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 2) return false;
|
||||
LLUUID avatar_id;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue