Merge 2025.06 into develop

Merge 2025.06 into develop
master
Andrey Kleshchev 2025-08-14 11:17:35 +03:00 committed by GitHub
commit 6f072c2121
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
237 changed files with 6168 additions and 2244 deletions

View File

@ -2332,59 +2332,33 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
</map> </map>
<key>threejs</key> <key>threejs</key>
<map> <map>
<key>platforms</key> <key>copyright</key>
<map> <string>Copyright © 2010-2021 three.js authors</string>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>cfed00d8ea7265c035c2d86a234b28efb0b23756</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-darwin64-b8f6746.tar.zst</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>9de1295b157c9913c28be81ff933c73493ecc132</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-linux64-b8f6746.tar.zst</string>
</map>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>4141710fccbd1ea2b3b53d00e189bdfa2ee9d441</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-windows64-b8f6746.tar.zst</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>license</key> <key>license</key>
<string>MIT</string> <string>MIT</string>
<key>license_file</key> <key>license_file</key>
<string>LICENSES/THREEJS_LICENSE.txt</string> <string>LICENSES/THREEJS_LICENSE.txt</string>
<key>copyright</key>
<string>Copyright © 2010-2021 three.js authors</string>
<key>version</key>
<string>0.132.2</string>
<key>name</key> <key>name</key>
<string>threejs</string> <string>threejs</string>
<key>platforms</key>
<map>
<key>common</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>982c0fa427458082ea9e3cb9603904210732b64e</string>
<key>hash_algorithm</key>
<string>sha1</string>
<key>url</key>
<string>https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-5da28d9/threejs-0.132.2-common-8454371083.tar.zst</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
<string>0.132.2</string>
</map> </map>
<key>tinygltf</key> <key>tinygltf</key>
<map> <map>

View File

@ -119,6 +119,8 @@ public:
virtual void addDebugText( const std::string& text ) = 0; virtual void addDebugText( const std::string& text ) = 0;
virtual std::string getDebugName() const { return getID().asString(); }
virtual const LLUUID& getID() const = 0; virtual const LLUUID& getID() const = 0;
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// End Interface // End Interface

View File

@ -29,6 +29,7 @@
#include "llassettype.h" #include "llassettype.h"
#include "lldictionary.h" #include "lldictionary.h"
#include "llmemory.h" #include "llmemory.h"
#include "llsd.h"
#include "llsingleton.h" #include "llsingleton.h"
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
@ -246,3 +247,19 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type)
} }
return false; return false;
} }
LLSD LLAssetType::getTypeNames()
{
LLSD type_names;
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
for (S32 type = AT_TEXTURE; type < AT_COUNT; ++type)
{
const AssetEntry *entry = dict->lookup((LLAssetType::EType) type);
// skip llassettype_bad_lookup
if (entry)
{
type_names.append(entry->mTypeName);
}
}
return type_names;
}

View File

@ -165,6 +165,8 @@ public:
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
static LLSD getTypeNames();
static const std::string BADLOOKUP; static const std::string BADLOOKUP;
protected: protected:

View File

@ -638,6 +638,14 @@ public:
{ {
getCPUIDInfo(); getCPUIDInfo();
uint64_t frequency = getSysctlInt64("hw.cpufrequency"); uint64_t frequency = getSysctlInt64("hw.cpufrequency");
if (!frequency)
{
auto tbfrequency = getSysctlInt64("hw.tbfrequency");
struct clockinfo clockrate;
auto clockrate_len = sizeof(clockrate);
if (!sysctlbyname("kern.clockrate", &clockrate, &clockrate_len, NULL, 0))
frequency = tbfrequency * clockrate.hz;
}
setInfo(eFrequency, (F64)frequency / (F64)1000000); setInfo(eFrequency, (F64)frequency / (F64)1000000);
} }

View File

@ -553,6 +553,45 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
} // namespace llsd } // namespace llsd
/*****************************************************************************
* LLSDParam<std::vector<T>>
*****************************************************************************/
// Given an LLSD array, return a const std::vector<T>&, where T is a type
// supported by LLSDParam. Bonus: if the LLSD value is actually a scalar,
// return a single-element vector containing the converted value.
template <typename T>
class LLSDParam<std::vector<T>>: public LLSDParamBase
{
public:
LLSDParam(const LLSD& array)
{
// treat undefined "array" as empty vector
if (array.isDefined())
{
// what if it's a scalar?
if (! array.isArray())
{
v.push_back(LLSDParam<T>(array));
}
else // really is an array
{
// reserve space for the array entries
v.reserve(array.size());
for (const auto& item : llsd::inArray(array))
{
v.push_back(LLSDParam<T>(item));
}
}
}
}
operator const std::vector<T>&() const { return v; }
private:
std::vector<T> v;
};
/***************************************************************************** /*****************************************************************************
* toArray(), toMap() * toArray(), toMap()
*****************************************************************************/ *****************************************************************************/

View File

@ -55,7 +55,7 @@ namespace LL
* ThreadPool listens for application shutdown messages on the "LLApp" * ThreadPool listens for application shutdown messages on the "LLApp"
* LLEventPump. Call close() to shut down this ThreadPool early. * LLEventPump. Call close() to shut down this ThreadPool early.
*/ */
virtual void close(); void close();
std::string getName() const { return mName; } std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); } size_t getWidth() const { return mThreads.size(); }
@ -122,7 +122,7 @@ namespace LL
size_t threads=1, size_t threads=1,
size_t capacity=1024*1024, size_t capacity=1024*1024,
bool auto_shutdown = true): bool auto_shutdown = true):
ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown) ThreadPoolBase(name, threads, new queue_t(name, capacity, false), auto_shutdown)
{} {}
~ThreadPoolUsing() override {} ~ThreadPoolUsing() override {}

View File

@ -21,6 +21,7 @@
#include "llcoros.h" #include "llcoros.h"
#include LLCOROS_MUTEX_HEADER #include LLCOROS_MUTEX_HEADER
#include "llerror.h" #include "llerror.h"
#include "llevents.h"
#include "llexception.h" #include "llexception.h"
#include "stringize.h" #include "stringize.h"
@ -30,11 +31,38 @@ using Lock = LLCoros::LockType;
/***************************************************************************** /*****************************************************************************
* WorkQueueBase * WorkQueueBase
*****************************************************************************/ *****************************************************************************/
LL::WorkQueueBase::WorkQueueBase(const std::string& name): LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown)
super(makeName(name)) : super(makeName(name))
{ {
// TODO: register for "LLApp" events so we can implicitly close() on if (auto_shutdown)
// viewer shutdown. {
// Register for "LLApp" events so we can implicitly close() on viewer shutdown
std::string listener_name = "WorkQueue:" + getKey();
LLEventPumps::instance().obtain("LLApp").listen(
listener_name,
[this](const LLSD& stat)
{
std::string status(stat["status"]);
if (status != "running")
{
// Viewer is shutting down, close this queue
LL_DEBUGS("WorkQueue") << getKey() << " closing on app shutdown" << LL_ENDL;
close();
}
return false;
});
// Store the listener name so we can unregister in the destructor
mListenerName = listener_name;
}
}
LL::WorkQueueBase::~WorkQueueBase()
{
if (!mListenerName.empty() && !LLEventPumps::wasDeleted())
{
LLEventPumps::instance().obtain("LLApp").stopListening(mListenerName);
}
} }
void LL::WorkQueueBase::runUntilClose() void LL::WorkQueueBase::runUntilClose()
@ -220,8 +248,8 @@ void LL::WorkQueueBase::checkCoroutine(const std::string& method)
/***************************************************************************** /*****************************************************************************
* WorkQueue * WorkQueue
*****************************************************************************/ *****************************************************************************/
LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity): LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity, bool auto_shutdown):
super(name), super(name, auto_shutdown),
mQueue(capacity) mQueue(capacity)
{ {
} }
@ -269,8 +297,8 @@ bool LL::WorkQueue::tryPop_(Work& work)
/***************************************************************************** /*****************************************************************************
* WorkSchedule * WorkSchedule
*****************************************************************************/ *****************************************************************************/
LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity): LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity, bool auto_shutdown):
super(name), super(name, auto_shutdown),
mQueue(capacity) mQueue(capacity)
{ {
} }

View File

@ -51,7 +51,9 @@ namespace LL
* You may omit the WorkQueueBase name, in which case a unique name is * You may omit the WorkQueueBase name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous. * synthesized; for practical purposes that makes it anonymous.
*/ */
WorkQueueBase(const std::string& name); WorkQueueBase(const std::string& name, bool auto_shutdown);
virtual ~WorkQueueBase();
/** /**
* Since the point of WorkQueue is to pass work to some other worker * Since the point of WorkQueue is to pass work to some other worker
@ -197,6 +199,9 @@ namespace LL
private: private:
virtual Work pop_() = 0; virtual Work pop_() = 0;
virtual bool tryPop_(Work&) = 0; virtual bool tryPop_(Work&) = 0;
// Name used for the LLApp event listener (empty if not registered)
std::string mListenerName;
}; };
/***************************************************************************** /*****************************************************************************
@ -212,7 +217,7 @@ namespace LL
* You may omit the WorkQueue name, in which case a unique name is * You may omit the WorkQueue name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous. * synthesized; for practical purposes that makes it anonymous.
*/ */
WorkQueue(const std::string& name = std::string(), size_t capacity=1024); WorkQueue(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/** /**
* Since the point of WorkQueue is to pass work to some other worker * Since the point of WorkQueue is to pass work to some other worker
@ -282,7 +287,7 @@ namespace LL
* You may omit the WorkSchedule name, in which case a unique name is * You may omit the WorkSchedule name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous. * synthesized; for practical purposes that makes it anonymous.
*/ */
WorkSchedule(const std::string& name = std::string(), size_t capacity=1024); WorkSchedule(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/** /**
* Since the point of WorkSchedule is to pass work to some other worker * Since the point of WorkSchedule is to pass work to some other worker

View File

@ -558,6 +558,12 @@ bool LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
LL_INFOS() << "Dropping alpha information during BMP encoding" << LL_ENDL; LL_INFOS() << "Dropping alpha information during BMP encoding" << LL_ENDL;
} }
if (raw_image->isBufferInvalid())
{
setLastError("Invalid input, no buffer");
return false;
}
setSize(raw_image->getWidth(), raw_image->getHeight(), dst_components); setSize(raw_image->getWidth(), raw_image->getHeight(), dst_components);
U8 magic[14]; U8 magic[14];

View File

@ -329,6 +329,12 @@ bool LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_
{ {
llassert_always(raw_image); llassert_always(raw_image);
if (raw_image->isBufferInvalid())
{
setLastError("Invalid input, no buffer");
return false;
}
S32 ncomponents = raw_image->getComponents(); S32 ncomponents = raw_image->getComponents();
EFileFormat format; EFileFormat format;
switch (ncomponents) switch (ncomponents)

View File

@ -491,6 +491,12 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
resetLastError(); resetLastError();
if (raw_image->isBufferInvalid())
{
setLastError("Invalid input, no buffer");
return false;
}
LLImageDataSharedLock lockIn(raw_image); LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this); LLImageDataLock lockOut(this);

View File

@ -897,6 +897,12 @@ bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible) bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
{ {
if (raw_image.isBufferInvalid())
{
base.setLastError("Invalid input, no buffer");
return false;
}
JPEG2KEncode encode(comment_text, reversible); JPEG2KEncode encode(comment_text, reversible);
bool encoded = encode.encode(raw_image, base); bool encoded = encode.encode(raw_image, base);
if (!encoded) if (!encoded)

View File

@ -29,6 +29,7 @@
#include "llfoldertype.h" #include "llfoldertype.h"
#include "lldictionary.h" #include "lldictionary.h"
#include "llmemory.h" #include "llmemory.h"
#include "llsd.h"
#include "llsingleton.h" #include "llsingleton.h"
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
@ -220,3 +221,21 @@ const std::string &LLFolderType::badLookup()
static const std::string sBadLookup = "llfoldertype_bad_lookup"; static const std::string sBadLookup = "llfoldertype_bad_lookup";
return sBadLookup; return sBadLookup;
} }
LLSD LLFolderType::getTypeNames()
{
LLSD type_names;
for (S32 type = FT_TEXTURE; type < FT_COUNT; ++type)
{
if (lookupIsEnsembleType((LLFolderType::EType)type))
continue;
const FolderEntry* entry = LLFolderDictionary::getInstance()->lookup((LLFolderType::EType)type);
// skip llfoldertype_bad_lookup
if (entry)
{
type_names.append(entry->mName);
}
}
return type_names;
}

View File

@ -115,6 +115,8 @@ public:
static const std::string& badLookup(); // error string when a lookup fails static const std::string& badLookup(); // error string when a lookup fails
static LLSD getTypeNames();
protected: protected:
LLFolderType() {} LLFolderType() {}
~LLFolderType() {} ~LLFolderType() {}

View File

@ -46,6 +46,7 @@ static const std::string INV_ITEM_ID_LABEL("item_id");
static const std::string INV_FOLDER_ID_LABEL("cat_id"); static const std::string INV_FOLDER_ID_LABEL("cat_id");
static const std::string INV_PARENT_ID_LABEL("parent_id"); static const std::string INV_PARENT_ID_LABEL("parent_id");
static const std::string INV_THUMBNAIL_LABEL("thumbnail"); static const std::string INV_THUMBNAIL_LABEL("thumbnail");
static const std::string INV_FAVORITE_LABEL("favorite");
static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id"); static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id");
static const std::string INV_ASSET_TYPE_LABEL("type"); static const std::string INV_ASSET_TYPE_LABEL("type");
static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type"); static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
@ -59,6 +60,7 @@ static const std::string INV_LINKED_ID_LABEL("linked_id");
static const std::string INV_SALE_INFO_LABEL("sale_info"); static const std::string INV_SALE_INFO_LABEL("sale_info");
static const std::string INV_FLAGS_LABEL("flags"); static const std::string INV_FLAGS_LABEL("flags");
static const std::string INV_CREATION_DATE_LABEL("created_at"); static const std::string INV_CREATION_DATE_LABEL("created_at");
static const std::string INV_TOGGLED_LABEL("toggled");
// key used by agent-inventory-service // key used by agent-inventory-service
static const std::string INV_ASSET_TYPE_LABEL_WS("type_default"); static const std::string INV_ASSET_TYPE_LABEL_WS("type_default");
@ -82,14 +84,16 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
mParentUUID(parent_uuid), mParentUUID(parent_uuid),
mType(type), mType(type),
mName(name), mName(name),
mCreationDate(0) mCreationDate(0),
mFavorite(false)
{ {
correctInventoryName(mName); correctInventoryName(mName);
} }
LLInventoryObject::LLInventoryObject() LLInventoryObject::LLInventoryObject()
: mType(LLAssetType::AT_NONE), : mType(LLAssetType::AT_NONE),
mCreationDate(0) mCreationDate(0),
mFavorite(false)
{ {
} }
@ -104,6 +108,7 @@ void LLInventoryObject::copyObject(const LLInventoryObject* other)
mType = other->mType; mType = other->mType;
mName = other->mName; mName = other->mName;
mThumbnailUUID = other->mThumbnailUUID; mThumbnailUUID = other->mThumbnailUUID;
mFavorite = other->mFavorite;
} }
const LLUUID& LLInventoryObject::getUUID() const const LLUUID& LLInventoryObject::getUUID() const
@ -121,6 +126,11 @@ const LLUUID& LLInventoryObject::getThumbnailUUID() const
return mThumbnailUUID; return mThumbnailUUID;
} }
bool LLInventoryObject::getIsFavorite() const
{
return mFavorite;
}
const std::string& LLInventoryObject::getName() const const std::string& LLInventoryObject::getName() const
{ {
return mName; return mName;
@ -175,6 +185,11 @@ void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid)
mThumbnailUUID = thumbnail_uuid; mThumbnailUUID = thumbnail_uuid;
} }
void LLInventoryObject::setFavorite(bool favorite)
{
mFavorite = favorite;
}
void LLInventoryObject::setType(LLAssetType::EType type) void LLInventoryObject::setType(LLAssetType::EType type)
{ {
mType = type; mType = type;
@ -247,6 +262,23 @@ bool LLInventoryObject::importLegacyStream(std::istream& input_stream)
{ {
setThumbnailUUID(LLUUID::null); setThumbnailUUID(LLUUID::null);
} }
if (metadata.has("favorite"))
{
const LLSD& favorite = metadata["favorite"];
if (favorite.has("toggled"))
{
setFavorite(favorite["toggled"].asBoolean());
}
else
{
setFavorite(false);
}
}
else
{
setFavorite(false);
}
} }
else if(0 == strcmp("name", keyword)) else if(0 == strcmp("name", keyword))
{ {
@ -735,6 +767,23 @@ bool LLInventoryItem::importLegacyStream(std::istream& input_stream)
{ {
setThumbnailUUID(LLUUID::null); setThumbnailUUID(LLUUID::null);
} }
if (metadata.has("favorite"))
{
const LLSD& favorite = metadata["favorite"];
if (favorite.has("toggled"))
{
setFavorite(favorite["toggled"].asBoolean());
}
else
{
setFavorite(false);
}
}
else
{
setFavorite(false);
}
} }
else if(0 == strcmp("inv_type", keyword)) else if(0 == strcmp("inv_type", keyword))
{ {
@ -879,7 +928,7 @@ bool LLInventoryItem::exportLegacyStream(std::ostream& output_stream, bool inclu
LLSD LLInventoryItem::asLLSD() const LLSD LLInventoryItem::asLLSD() const
{ {
LLSD sd = LLSD(); LLSD sd;
asLLSD(sd); asLLSD(sd);
return sd; return sd;
} }
@ -888,13 +937,18 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
{ {
sd[INV_ITEM_ID_LABEL] = mUUID; sd[INV_ITEM_ID_LABEL] = mUUID;
sd[INV_PARENT_ID_LABEL] = mParentUUID; sd[INV_PARENT_ID_LABEL] = mParentUUID;
sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions); ll_fill_sd_from_permissions(sd[INV_PERMISSIONS_LABEL], mPermissions);
if (mThumbnailUUID.notNull()) if (mThumbnailUUID.notNull())
{ {
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
} }
if (mFavorite)
{
sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
}
U32 mask = mPermissions.getMaskBase(); U32 mask = mPermissions.getMaskBase();
if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|| (mAssetUUID.isNull())) || (mAssetUUID.isNull()))
@ -909,19 +963,22 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
cipher.encrypt(shadow_id.mData, UUID_BYTES); cipher.encrypt(shadow_id.mData, UUID_BYTES);
sd[INV_SHADOW_ID_LABEL] = shadow_id; sd[INV_SHADOW_ID_LABEL] = shadow_id;
} }
sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); sd[INV_ASSET_TYPE_LABEL] = std::string(LLAssetType::lookup(mType));
sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
if(!inv_type_str.empty()) if(!inv_type_str.empty())
{ {
sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str; sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
} }
else
{
sd[INV_INVENTORY_TYPE_LABEL] = (LLSD::Integer)mInventoryType;
}
//sd[INV_FLAGS_LABEL] = (S32)mFlags; //sd[INV_FLAGS_LABEL] = (S32)mFlags;
sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags); sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
sd[INV_SALE_INFO_LABEL] = mSaleInfo.asLLSD(); mSaleInfo.asLLSD(sd[INV_SALE_INFO_LABEL]);
sd[INV_NAME_LABEL] = mName; sd[INV_NAME_LABEL] = mName;
sd[INV_DESC_LABEL] = mDescription; sd[INV_DESC_LABEL] = mDescription;
sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate; sd[INV_CREATION_DATE_LABEL] = (LLSD::Integer)mCreationDate;
} }
bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new) bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
@ -937,6 +994,8 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
// TODO - figure out if this should be moved into the noclobber fields above // TODO - figure out if this should be moved into the noclobber fields above
mThumbnailUUID.setNull(); mThumbnailUUID.setNull();
mFavorite = false;
mPermissions.init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
// iterate as map to avoid making unnecessary temp copies of everything // iterate as map to avoid making unnecessary temp copies of everything
LLSD::map_const_iterator i, end; LLSD::map_const_iterator i, end;
@ -982,9 +1041,20 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
continue; continue;
} }
if (i->first == INV_FAVORITE_LABEL)
{
const LLSD& favorite_map = i->second;
const std::string w = INV_TOGGLED_LABEL;
if (favorite_map.has(w))
{
mFavorite = favorite_map[w].asBoolean();
}
continue;
}
if (i->first == INV_PERMISSIONS_LABEL) if (i->first == INV_PERMISSIONS_LABEL)
{ {
mPermissions = ll_permissions_from_sd(i->second); mPermissions.importLLSD(i->second);
continue; continue;
} }
@ -1177,6 +1247,11 @@ LLSD LLInventoryCategory::asLLSD() const
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
} }
if (mFavorite)
{
sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
}
return sd; return sd;
} }
@ -1188,11 +1263,17 @@ LLSD LLInventoryCategory::asAISCreateCatLLSD() const
S8 type = static_cast<S8>(mPreferredType); S8 type = static_cast<S8>(mPreferredType);
sd[INV_ASSET_TYPE_LABEL_WS] = type; sd[INV_ASSET_TYPE_LABEL_WS] = type;
sd[INV_NAME_LABEL] = mName; sd[INV_NAME_LABEL] = mName;
if (mThumbnailUUID.notNull()) if (mThumbnailUUID.notNull())
{ {
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
} }
if (mFavorite)
{
sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
}
return sd; return sd;
} }
@ -1240,6 +1321,17 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
mThumbnailUUID = sd[w]; mThumbnailUUID = sd[w];
} }
} }
mFavorite = false;
w = INV_FAVORITE_LABEL;
if (sd.has(w))
{
const LLSD& favorite_map = sd[w];
w = INV_TOGGLED_LABEL;
if (favorite_map.has(w))
{
mFavorite = favorite_map[w].asBoolean();
}
}
w = INV_ASSET_TYPE_LABEL; w = INV_ASSET_TYPE_LABEL;
if (sd.has(w)) if (sd.has(w))
{ {
@ -1362,6 +1454,23 @@ bool LLInventoryCategory::importLegacyStream(std::istream& input_stream)
{ {
setThumbnailUUID(LLUUID::null); setThumbnailUUID(LLUUID::null);
} }
if (metadata.has("favorite"))
{
const LLSD& favorite = metadata["favorite"];
if (favorite.has("toggled"))
{
setFavorite(favorite["toggled"].asBoolean());
}
else
{
setFavorite(false);
}
}
else
{
setFavorite(false);
}
} }
else else
{ {
@ -1396,12 +1505,11 @@ bool LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, bool)
return true; return true;
} }
LLSD LLInventoryCategory::exportLLSD() const void LLInventoryCategory::exportLLSD(LLSD& cat_data) const
{ {
LLSD cat_data;
cat_data[INV_FOLDER_ID_LABEL] = mUUID; cat_data[INV_FOLDER_ID_LABEL] = mUUID;
cat_data[INV_PARENT_ID_LABEL] = mParentUUID; cat_data[INV_PARENT_ID_LABEL] = mParentUUID;
cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); cat_data[INV_ASSET_TYPE_LABEL] = std::string(LLAssetType::lookup(mType));
cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType); cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
cat_data[INV_NAME_LABEL] = mName; cat_data[INV_NAME_LABEL] = mName;
@ -1409,49 +1517,76 @@ LLSD LLInventoryCategory::exportLLSD() const
{ {
cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID); cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
} }
if (mFavorite)
return cat_data; {
cat_data[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
}
} }
bool LLInventoryCategory::importLLSD(const LLSD& cat_data) bool LLInventoryCategory::importLLSDMap(const LLSD& cat_data)
{ {
if (cat_data.has(INV_FOLDER_ID_LABEL)) LLSD::map_const_iterator i, end;
end = cat_data.endMap();
for ( i = cat_data.beginMap(); i != end; ++i)
{ {
setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID()); importLLSD(i->first, i->second);
} }
if (cat_data.has(INV_PARENT_ID_LABEL))
{
setParent(cat_data[INV_PARENT_ID_LABEL].asUUID());
}
if (cat_data.has(INV_ASSET_TYPE_LABEL))
{
setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString()));
}
if (cat_data.has(INV_PREFERRED_TYPE_LABEL))
{
setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
}
if (cat_data.has(INV_THUMBNAIL_LABEL))
{
LLUUID thumbnail_uuid;
const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
if (thumbnail_data.has(INV_ASSET_ID_LABEL))
{
thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
}
setThumbnailUUID(thumbnail_uuid);
}
if (cat_data.has(INV_NAME_LABEL))
{
mName = cat_data[INV_NAME_LABEL].asString();
LLStringUtil::replaceNonstandardASCII(mName, ' ');
LLStringUtil::replaceChar(mName, '|', ' ');
}
return true; return true;
} }
bool LLInventoryCategory::importLLSD(const std::string& label, const LLSD& value)
{
if (label == INV_FOLDER_ID_LABEL)
{
setUUID(value.asUUID());
return true;
}
else if (label == INV_PARENT_ID_LABEL)
{
setParent(value.asUUID());
return true;
}
else if (label == INV_ASSET_TYPE_LABEL)
{
setType(LLAssetType::lookup(value.asString()));
return true;
}
else if (label == INV_PREFERRED_TYPE_LABEL)
{
setPreferredType(LLFolderType::lookup(value.asString()));
return true;
}
else if (label == INV_THUMBNAIL_LABEL)
{
LLUUID thumbnail_uuid;
if (value.has(INV_ASSET_ID_LABEL))
{
thumbnail_uuid = value[INV_ASSET_ID_LABEL].asUUID();
}
setThumbnailUUID(thumbnail_uuid);
return true;
}
if (label == INV_FAVORITE_LABEL)
{
bool favorite = false;
if (value.has(INV_TOGGLED_LABEL))
{
favorite = value[INV_TOGGLED_LABEL].asBoolean();
}
setFavorite(favorite);
}
else if (label == INV_NAME_LABEL)
{
mName = value.asString();
LLStringUtil::replaceNonstandardASCII(mName, ' ');
LLStringUtil::replaceChar(mName, '|', ' ');
return true;
}
return false;
}
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
/// Local function definitions /// Local function definitions for testing purposes
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item) LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item)

View File

@ -71,6 +71,7 @@ public:
virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID
const LLUUID& getParentUUID() const; const LLUUID& getParentUUID() const;
virtual const LLUUID& getThumbnailUUID() const; virtual const LLUUID& getThumbnailUUID() const;
virtual bool getIsFavorite() const;
virtual const std::string& getName() const; virtual const std::string& getName() const;
virtual LLAssetType::EType getType() const; virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@ -86,6 +87,7 @@ public:
virtual void rename(const std::string& new_name); virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent); void setParent(const LLUUID& new_parent);
virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid); virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid);
virtual void setFavorite(bool favorite);
void setType(LLAssetType::EType type); void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items virtual void setCreationDate(time_t creation_date_utc); // only stored for items
@ -111,6 +113,7 @@ protected:
LLUUID mUUID; LLUUID mUUID;
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL. LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
LLUUID mThumbnailUUID; LLUUID mThumbnailUUID;
bool mFavorite;
LLAssetType::EType mType; LLAssetType::EType mType;
std::string mName; std::string mName;
time_t mCreationDate; // seconds from 1/1/1970, UTC time_t mCreationDate; // seconds from 1/1/1970, UTC
@ -270,8 +273,9 @@ public:
virtual bool importLegacyStream(std::istream& input_stream); virtual bool importLegacyStream(std::istream& input_stream);
virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const; virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const;
LLSD exportLLSD() const; virtual void exportLLSD(LLSD& sd) const;
bool importLLSD(const LLSD& cat_data); bool importLLSDMap(const LLSD& cat_data);
virtual bool importLLSD(const std::string& label, const LLSD& value);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Member Variables // Member Variables
//-------------------------------------------------------------------- //--------------------------------------------------------------------
@ -285,6 +289,7 @@ protected:
// //
// These functions convert between structured data and an inventory // These functions convert between structured data and an inventory
// item, appropriate for serialization. // item, appropriate for serialization.
// Not up to date (no favorites, nor thumbnails), for testing purposes
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item); LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item);
LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat); LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat);

View File

@ -704,6 +704,79 @@ bool LLPermissions::exportLegacyStream(std::ostream& output_stream) const
return true; return true;
} }
static const std::string PERM_CREATOR_ID_LABEL("creator_id");
static const std::string PERM_OWNER_ID_LABEL("owner_id");
static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
static const std::string PERM_GROUP_ID_LABEL("group_id");
static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
static const std::string PERM_BASE_MASK_LABEL("base_mask");
static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
static const std::string PERM_GROUP_MASK_LABEL("group_mask");
static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
void LLPermissions::importLLSD(const LLSD& sd_perm)
{
LLSD::map_const_iterator i, end;
end = sd_perm.endMap();
for (i = sd_perm.beginMap(); i != end; ++i)
{
const std::string& label = i->first;
if (label == PERM_CREATOR_ID_LABEL)
{
mCreator = i->second.asUUID();
continue;
}
if (label == PERM_OWNER_ID_LABEL)
{
mOwner = i->second.asUUID();
continue;
}
if (label == PERM_LAST_OWNER_ID_LABEL)
{
mLastOwner = i->second.asUUID();
continue;
}
if (label == PERM_GROUP_ID_LABEL)
{
mGroup = i->second.asUUID();
continue;
}
if (label == PERM_BASE_MASK_LABEL)
{
PermissionMask mask = i->second.asInteger();
mMaskBase = mask;
continue;
}
if (label == PERM_OWNER_MASK_LABEL)
{
PermissionMask mask = i->second.asInteger();
mMaskOwner = mask;
continue;
}
if (label == PERM_EVERYONE_MASK_LABEL)
{
PermissionMask mask = i->second.asInteger();
mMaskEveryone = mask;
continue;
}
if (label == PERM_GROUP_MASK_LABEL)
{
PermissionMask mask = i->second.asInteger();
mMaskGroup = mask;
continue;
}
if (label == PERM_NEXT_OWNER_MASK_LABEL)
{
PermissionMask mask = i->second.asInteger();
mMaskNextOwner = mask;
continue;
}
}
fix();
}
bool LLPermissions::operator==(const LLPermissions &rhs) const bool LLPermissions::operator==(const LLPermissions &rhs) const
{ {
return return
@ -998,55 +1071,30 @@ std::string mask_to_string(U32 mask)
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
/// exported functions /// exported functions
///---------------------------------------------------------------------------- ///----------------------------------------------------------------------------
static const std::string PERM_CREATOR_ID_LABEL("creator_id");
static const std::string PERM_OWNER_ID_LABEL("owner_id");
static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
static const std::string PERM_GROUP_ID_LABEL("group_id");
static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
static const std::string PERM_BASE_MASK_LABEL("base_mask");
static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
static const std::string PERM_GROUP_MASK_LABEL("group_mask");
static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
LLSD ll_create_sd_from_permissions(const LLPermissions& perm) LLSD ll_create_sd_from_permissions(const LLPermissions& perm)
{ {
LLSD rv; LLSD rv;
ll_fill_sd_from_permissions(rv, perm);
return rv;
}
void ll_fill_sd_from_permissions(LLSD& rv, const LLPermissions& perm)
{
rv[PERM_CREATOR_ID_LABEL] = perm.getCreator(); rv[PERM_CREATOR_ID_LABEL] = perm.getCreator();
rv[PERM_OWNER_ID_LABEL] = perm.getOwner(); rv[PERM_OWNER_ID_LABEL] = perm.getOwner();
rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner(); rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner();
rv[PERM_GROUP_ID_LABEL] = perm.getGroup(); rv[PERM_GROUP_ID_LABEL] = perm.getGroup();
rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned(); rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned();
rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase(); rv[PERM_BASE_MASK_LABEL] = (LLSD::Integer)perm.getMaskBase();
rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner(); rv[PERM_OWNER_MASK_LABEL] = (LLSD::Integer)perm.getMaskOwner();
rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup(); rv[PERM_GROUP_MASK_LABEL] = (LLSD::Integer)perm.getMaskGroup();
rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone(); rv[PERM_EVERYONE_MASK_LABEL] = (LLSD::Integer)perm.getMaskEveryone();
rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner(); rv[PERM_NEXT_OWNER_MASK_LABEL] = (LLSD::Integer)perm.getMaskNextOwner();
return rv;
} }
LLPermissions ll_permissions_from_sd(const LLSD& sd_perm) LLPermissions ll_permissions_from_sd(const LLSD& sd_perm)
{ {
LLPermissions rv; LLPermissions rv;
rv.init( rv.importLLSD(sd_perm);
sd_perm[PERM_CREATOR_ID_LABEL].asUUID(),
sd_perm[PERM_OWNER_ID_LABEL].asUUID(),
sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(),
sd_perm[PERM_GROUP_ID_LABEL].asUUID());
// We do a cast to U32 here since LLSD does not attempt to
// represent unsigned ints.
PermissionMask mask;
mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger());
rv.setMaskBase(mask);
mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger());
rv.setMaskOwner(mask);
mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger());
rv.setMaskEveryone(mask);
mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger());
rv.setMaskGroup(mask);
mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger());
rv.setMaskNext(mask);
rv.fix();
return rv; return rv;
} }

View File

@ -299,6 +299,8 @@ public:
bool importLegacyStream(std::istream& input_stream); bool importLegacyStream(std::istream& input_stream);
bool exportLegacyStream(std::ostream& output_stream) const; bool exportLegacyStream(std::ostream& output_stream) const;
void importLLSD(const LLSD& sd_perm);
bool operator==(const LLPermissions &rhs) const; bool operator==(const LLPermissions &rhs) const;
bool operator!=(const LLPermissions &rhs) const; bool operator!=(const LLPermissions &rhs) const;
@ -435,6 +437,7 @@ protected:
// like 'creator_id', 'owner_id', etc, with the value copied from the // like 'creator_id', 'owner_id', etc, with the value copied from the
// permission object. // permission object.
LLSD ll_create_sd_from_permissions(const LLPermissions& perm); LLSD ll_create_sd_from_permissions(const LLPermissions& perm);
void ll_fill_sd_from_permissions(LLSD& rv, const LLPermissions& perm);
LLPermissions ll_permissions_from_sd(const LLSD& sd_perm); LLPermissions ll_permissions_from_sd(const LLSD& sd_perm);
#endif #endif

View File

@ -90,15 +90,20 @@ bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
LLSD LLSaleInfo::asLLSD() const LLSD LLSaleInfo::asLLSD() const
{ {
LLSD sd; LLSD sd;
asLLSD(sd);
return sd;
}
void LLSaleInfo::asLLSD(LLSD& sd) const
{
const char* type = lookup(mSaleType); const char* type = lookup(mSaleType);
if (!type) if (!type)
{ {
LL_WARNS_ONCE() << "Unknown sale type: " << mSaleType << LL_ENDL; LL_WARNS_ONCE() << "Unknown sale type: " << mSaleType << LL_ENDL;
type = lookup(LLSaleInfo::FS_NOT); type = lookup(LLSaleInfo::FS_NOT);
} }
sd["sale_type"] = type; sd["sale_type"] = std::string(type);
sd["sale_price"] = mSalePrice; sd["sale_price"] = mSalePrice;
return sd;
} }
bool LLSaleInfo::fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask) bool LLSaleInfo::fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask)

View File

@ -86,6 +86,7 @@ public:
bool exportLegacyStream(std::ostream& output_stream) const; bool exportLegacyStream(std::ostream& output_stream) const;
LLSD asLLSD() const; LLSD asLLSD() const;
void asLLSD(LLSD &sd) const;
operator LLSD() const { return asLLSD(); } operator LLSD() const { return asLLSD(); }
bool fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask); bool fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask);
bool importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask); bool importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask);

View File

@ -39,6 +39,34 @@
#pragma warning(disable: 4702) #pragma warning(disable: 4702)
#endif #endif
void set_random_inventory_metadata(LLInventoryObject* obj)
{
S32 extra = rand() % 4;
switch (extra)
{
case 0:
{
LLUUID thumbnail_id;
thumbnail_id.generate();
obj->setThumbnailUUID(thumbnail_id);
break;
}
case 1:
obj->setFavorite(true);
break;
case 2:
{
LLUUID thumbnail_id;
thumbnail_id.generate();
obj->setThumbnailUUID(thumbnail_id);
obj->setFavorite(true);
break;
}
default:
break;
}
}
LLPointer<LLInventoryItem> create_random_inventory_item() LLPointer<LLInventoryItem> create_random_inventory_item()
{ {
LLUUID item_id; LLUUID item_id;
@ -75,6 +103,7 @@ LLPointer<LLInventoryItem> create_random_inventory_item()
sale_info, sale_info,
flags, flags,
creation); creation);
set_random_inventory_metadata(item);
return item; return item;
} }
@ -90,6 +119,7 @@ LLPointer<LLInventoryCategory> create_random_inventory_cat()
parent_id, parent_id,
LLFolderType::FT_NONE, LLFolderType::FT_NONE,
std::string("Sample category")); std::string("Sample category"));
set_random_inventory_metadata(cat);
return cat; return cat;
} }
@ -290,6 +320,7 @@ namespace tut
src->setCreationDate(new_creation); src->setCreationDate(new_creation);
// test a save/load cycle to LLSD and back again // test a save/load cycle to LLSD and back again
// Note: ll_create_sd_from_inventory_item does not support metadata
LLSD sd = ll_create_sd_from_inventory_item(src); LLSD sd = ll_create_sd_from_inventory_item(src);
LLPointer<LLInventoryItem> dst = new LLInventoryItem; LLPointer<LLInventoryItem> dst = new LLInventoryItem;
bool successful_parse = dst->fromLLSD(sd); bool successful_parse = dst->fromLLSD(sd);
@ -329,7 +360,9 @@ namespace tut
} }
LLPointer<LLInventoryItem> src1 = create_random_inventory_item(); LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->asLLSD()) << std::endl; LLSD sd;
src1->asLLSD(sd);
fileXML << LLSDOStreamer<LLSDNotationFormatter>(sd) << std::endl;
fileXML.close(); fileXML.close();
@ -364,13 +397,13 @@ namespace tut
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName()); ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription()); ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
ensure_equals("14.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
} }
template<> template<> template<> template<>
void inventory_object::test<8>() void inventory_object::test<8>()
{ {
LLPointer<LLInventoryItem> src1 = create_random_inventory_item(); LLPointer<LLInventoryItem> src1 = create_random_inventory_item();
std::ostringstream ostream; std::ostringstream ostream;
@ -390,8 +423,8 @@ namespace tut
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName()); ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription()); ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
ensure_equals("11.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
ensure_equals("12.favorites::getIsFavorite() failed", false, src2->getIsFavorite()); // not supposed to carry over
} }
template<> template<> template<> template<>
@ -421,6 +454,8 @@ namespace tut
ensure_equals("10.name::getName() failed", src1->getName(), src2->getName()); ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription()); ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate()); ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
ensure_equals("14.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
} }
//******class LLInventoryCategory*******// //******class LLInventoryCategory*******//
@ -458,7 +493,9 @@ namespace tut
} }
LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat(); LLPointer<LLInventoryCategory> src1 = create_random_inventory_cat();
fileXML << LLSDOStreamer<LLSDNotationFormatter>(src1->exportLLSD()) << std::endl; LLSD sd;
src1->exportLLSD(sd);
fileXML << LLSDOStreamer<LLSDNotationFormatter>(sd) << std::endl;
fileXML.close(); fileXML.close();
llifstream file(filename.c_str()); llifstream file(filename.c_str());
@ -481,13 +518,15 @@ namespace tut
file.close(); file.close();
LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory(); LLPointer<LLInventoryCategory> src2 = new LLInventoryCategory();
src2->importLLSD(s_item); src2->importLLSDMap(s_item);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID()); ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID()); ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType()); ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType()); ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName()); ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("6.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
ensure_equals("7.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
} }
template<> template<> template<> template<>
@ -507,6 +546,7 @@ namespace tut
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType()); ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType()); ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName()); ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
ensure_equals("14.favorites::getIsFavorite() failed", false, src2->getIsFavorite()); // currently not supposed to carry over
} }
} }

View File

@ -662,6 +662,12 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
bool vflip = true; bool vflip = true;
bool hflip = false; bool hflip = false;
if (raw_image.isBufferInvalid())
{
base.setLastError("Invalid input, no buffer");
return false;
}
try try
{ {
// Set up input image files // Set up input image files

View File

@ -328,28 +328,30 @@ void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix)
} }
// Rotate 2 normalized orthogonal vectors in direction from `source` to `target`
static void rotate2(LLVector3& source, LLVector3& target, F32 angle)
{
F32 sx = source[VX], sy = source[VY], sz = source[VZ];
F32 tx = target[VX], ty = target[VY], tz = target[VZ];
F32 c = cosf(angle), s = sinf(angle);
source.set(sx * c + tx * s, sy * c + ty * s, sz * c + tz * s);
target.set(tx * c - sx * s, ty * c - sy * s, tz * c - sz * s);
}
void LLCoordFrame::roll(F32 angle) void LLCoordFrame::roll(F32 angle)
{ {
LLQuaternion q(angle, mXAxis); rotate2(mYAxis, mZAxis, angle);
LLMatrix3 rotation_matrix(q);
rotate(rotation_matrix);
CHECK_FINITE_OBJ();
} }
void LLCoordFrame::pitch(F32 angle) void LLCoordFrame::pitch(F32 angle)
{ {
LLQuaternion q(angle, mYAxis); rotate2(mZAxis, mXAxis, angle);
LLMatrix3 rotation_matrix(q);
rotate(rotation_matrix);
CHECK_FINITE_OBJ();
} }
void LLCoordFrame::yaw(F32 angle) void LLCoordFrame::yaw(F32 angle)
{ {
LLQuaternion q(angle, mZAxis); rotate2(mXAxis, mYAxis, angle);
LLMatrix3 rotation_matrix(q);
rotate(rotation_matrix);
CHECK_FINITE_OBJ();
} }
// get*() routines // get*() routines

View File

@ -65,7 +65,7 @@ constexpr F32 DEG_TO_RAD = 0.017453292519943295769236907684886f;
constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f; constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f;
constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f; constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f;
constexpr F32 F_LN10 = 2.3025850929940456840179914546844f; constexpr F32 F_LN10 = 2.3025850929940456840179914546844f;
constexpr F32 OO_LN10 = 0.43429448190325182765112891891661; constexpr F32 OO_LN10 = 0.43429448190325182765112891891661f;
constexpr F32 F_LN2 = 0.69314718056f; constexpr F32 F_LN2 = 0.69314718056f;
constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f; constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f;

View File

@ -57,7 +57,7 @@ LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec) LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
{ {
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); F32 mag = vec.length();
if (mag > FP_MAG_THRESHOLD) if (mag > FP_MAG_THRESHOLD)
{ {
angle *= 0.5; angle *= 0.5;
@ -76,7 +76,7 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec) LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
{ {
F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]); F32 mag = vec.length();
if (mag > FP_MAG_THRESHOLD) if (mag > FP_MAG_THRESHOLD)
{ {
angle *= 0.5; angle *= 0.5;

View File

@ -5711,7 +5711,15 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
S32 vert_count = 0; S32 vert_count = 0;
if (!data.p.empty()) if (!data.p.empty())
{ {
vert_count = static_cast<S32>(meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count)); try
{
vert_count = static_cast<S32>(meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count));
}
catch (std::bad_alloc&)
{
LLError::LLUserWarningMsg::showOutOfMemory();
LL_ERRS("LLCoros") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL;
}
} }
if (vert_count < 65535 && vert_count != 0) if (vert_count < 65535 && vert_count != 0)

View File

@ -66,6 +66,13 @@ F32 angle_between(const LLVector2& a, const LLVector2& b)
return angle; return angle;
} }
F32 signed_angle_between(const LLVector2& a, const LLVector2& b)
{
F32 angle = angle_between(a, b);
F32 rhombus_square = a[VX] * b[VY] - b[VX] * a[VY];
return rhombus_square < 0 ? -angle : angle;
}
bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon) bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon)
{ {
LLVector2 an = a; LLVector2 an = a;

View File

@ -107,13 +107,14 @@ class LLVector2
friend LLVector2 operator-(const LLVector2 &a); // Return vector -a friend LLVector2 operator-(const LLVector2 &a); // Return vector -a
friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a
}; };
// Non-member functions // Non-member functions
F32 angle_between(const LLVector2& a, const LLVector2& b); // Returns angle (radians) between a and b F32 angle_between(const LLVector2& a, const LLVector2& b); // Returns angle (radians) between a and b
F32 signed_angle_between(const LLVector2& a, const LLVector2& b); // Returns signed angle (radians) between a and b
bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel
F32 dist_vec(const LLVector2& a, const LLVector2& b); // Returns distance between a and b F32 dist_vec(const LLVector2& a, const LLVector2& b); // Returns distance between a and b
F32 dist_vec_squared(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b F32 dist_vec_squared(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b
@ -124,26 +125,22 @@ LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u); // Returns a vect
inline LLVector2::LLVector2() inline LLVector2::LLVector2()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
} }
inline LLVector2::LLVector2(F32 x, F32 y) inline LLVector2::LLVector2(F32 x, F32 y)
{ {
mV[VX] = x; set(x, y);
mV[VY] = y;
} }
inline LLVector2::LLVector2(const F32 *vec) inline LLVector2::LLVector2(const F32 *vec)
{ {
mV[VX] = vec[VX]; set(vec);
mV[VY] = vec[VY];
} }
inline LLVector2::LLVector2(const LLVector3 &vec) inline LLVector2::LLVector2(const LLVector3 &vec)
{ {
mV[VX] = vec.mV[VX]; set(vec.mV);
mV[VY] = vec.mV[VY];
} }
inline LLVector2::LLVector2(const LLSD &sd) inline LLVector2::LLVector2(const LLSD &sd)
@ -155,28 +152,24 @@ inline LLVector2::LLVector2(const LLSD &sd)
inline void LLVector2::clear() inline void LLVector2::clear()
{ {
mV[VX] = 0.f; mV[VX] = mV[VY] = 0.f;
mV[VY] = 0.f;
} }
inline void LLVector2::setZero() inline void LLVector2::setZero()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
} }
// deprecated // deprecated
inline void LLVector2::clearVec() inline void LLVector2::clearVec()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
} }
// deprecated // deprecated
inline void LLVector2::zeroVec() inline void LLVector2::zeroVec()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
} }
inline void LLVector2::set(F32 x, F32 y) inline void LLVector2::set(F32 x, F32 y)
@ -187,36 +180,31 @@ inline void LLVector2::set(F32 x, F32 y)
inline void LLVector2::set(const LLVector2 &vec) inline void LLVector2::set(const LLVector2 &vec)
{ {
mV[VX] = vec.mV[VX]; set(vec.mV);
mV[VY] = vec.mV[VY];
} }
inline void LLVector2::set(const F32 *vec) inline void LLVector2::set(const F32 *vec)
{ {
mV[VX] = vec[VX]; set(vec[VX], vec[VY]);
mV[VY] = vec[VY];
} }
// deprecated // deprecated
inline void LLVector2::setVec(F32 x, F32 y) inline void LLVector2::setVec(F32 x, F32 y)
{ {
mV[VX] = x; set(x, y);
mV[VY] = y;
} }
// deprecated // deprecated
inline void LLVector2::setVec(const LLVector2 &vec) inline void LLVector2::setVec(const LLVector2 &vec)
{ {
mV[VX] = vec.mV[VX]; set(vec);
mV[VY] = vec.mV[VY];
} }
// deprecated // deprecated
inline void LLVector2::setVec(const F32 *vec) inline void LLVector2::setVec(const F32 *vec)
{ {
mV[VX] = vec[VX]; set(vec);
mV[VY] = vec[VY];
} }
@ -224,7 +212,7 @@ inline void LLVector2::setVec(const F32 *vec)
inline F32 LLVector2::length() const inline F32 LLVector2::length() const
{ {
return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); return sqrt(lengthSquared());
} }
inline F32 LLVector2::lengthSquared() const inline F32 LLVector2::lengthSquared() const
@ -234,61 +222,42 @@ inline F32 LLVector2::lengthSquared() const
inline F32 LLVector2::normalize() inline F32 LLVector2::normalize()
{ {
F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); F32 mag = length();
F32 oomag;
if (mag > FP_MAG_THRESHOLD) if (mag > FP_MAG_THRESHOLD)
{ {
oomag = 1.f/mag; *this /= mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
} }
else else
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mag = 0; mag = 0;
} }
return (mag); return mag;
} }
// checker // checker
inline bool LLVector2::isFinite() const inline bool LLVector2::isFinite() const
{ {
return (llfinite(mV[VX]) && llfinite(mV[VY])); return llfinite(mV[VX]) && llfinite(mV[VY]);
} }
// deprecated // deprecated
inline F32 LLVector2::magVec() const inline F32 LLVector2::magVec() const
{ {
return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); return length();
} }
// deprecated // deprecated
inline F32 LLVector2::magVecSquared() const inline F32 LLVector2::magVecSquared() const
{ {
return mV[VX]*mV[VX] + mV[VY]*mV[VY]; return lengthSquared();
} }
// deprecated // deprecated
inline F32 LLVector2::normVec() inline F32 LLVector2::normVec()
{ {
F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY]); return normalize();
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
}
else
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mag = 0;
}
return (mag);
} }
inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec) inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
@ -301,11 +270,7 @@ inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
inline bool LLVector2::isNull() const inline bool LLVector2::isNull() const
{ {
if (F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY]) return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY];
{
return true;
}
return false;
} }
@ -405,10 +370,7 @@ inline const LLVector2& operator*=(LLVector2& a, F32 k)
inline const LLVector2& operator/=(LLVector2& a, F32 k) inline const LLVector2& operator/=(LLVector2& a, F32 k)
{ {
F32 t = 1.f / k; return a *= 1.f / k;
a.mV[VX] *= t;
a.mV[VY] *= t;
return a;
} }
inline LLVector2 operator-(const LLVector2& a) inline LLVector2 operator-(const LLVector2& a)

View File

@ -112,24 +112,24 @@ class LLVector3
const LLVector3& setVec(const LLVector4 &vec); // deprecated const LLVector3& setVec(const LLVector4 &vec); // deprecated
const LLVector3& setVec(const LLVector3d &vec); // deprecated const LLVector3& setVec(const LLVector3d &vec); // deprecated
F32 length() const; // Returns magnitude of LLVector3 F32 length() const; // Returns magnitude of LLVector3
F32 lengthSquared() const; // Returns magnitude squared of LLVector3 F32 lengthSquared() const; // Returns magnitude squared of LLVector3
F32 magVec() const; // deprecated F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated F32 magVecSquared() const; // deprecated
inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3 inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
inline F32 normVec(); // deprecated inline F32 normVec(); // deprecated
inline bool inRange( F32 min, F32 max ) const; // Returns true if all values of the vector are between min and max inline bool inRange(F32 min, F32 max) const; // Returns true if all values of the vector are between min and max
const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians
const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v) const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec
LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec
bool isNull() const; // Returns true if vector has a _very_small_ length bool isNull() const; // Returns true if vector has a _very_small_ length
bool isExactlyZero() const { return !mV[VX] && !mV[VY] && !mV[VZ]; } bool isExactlyZero() const { return !mV[VX] && !mV[VY] && !mV[VZ]; }
@ -183,23 +183,17 @@ bool box_valid_and_non_zero(const LLVector3* box);
inline LLVector3::LLVector3() inline LLVector3::LLVector3()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
} }
inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z) inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z)
{ {
mV[VX] = x; set(x, y, z);
mV[VY] = y;
mV[VZ] = z;
} }
inline LLVector3::LLVector3(const F32 *vec) inline LLVector3::LLVector3(const F32 *vec)
{ {
mV[VX] = vec[VX]; set(vec);
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
} }
inline LLVector3::LLVector3(const glm::vec3& vec) inline LLVector3::LLVector3(const glm::vec3& vec)
@ -230,7 +224,7 @@ inline LLVector3::LLVector3(const LLVector3 &copy)
// checker // checker
inline bool LLVector3::isFinite() const inline bool LLVector3::isFinite() const
{ {
return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ])); return llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]);
} }
@ -238,30 +232,22 @@ inline bool LLVector3::isFinite() const
inline void LLVector3::clear() inline void LLVector3::clear()
{ {
mV[VX] = 0.f; set(0.f, 0.f, 0.f);
mV[VY] = 0.f;
mV[VZ] = 0.f;
} }
inline void LLVector3::setZero() inline void LLVector3::setZero()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
} }
inline void LLVector3::clearVec() inline void LLVector3::clearVec()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
} }
inline void LLVector3::zeroVec() inline void LLVector3::zeroVec()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
} }
inline void LLVector3::set(F32 x, F32 y, F32 z) inline void LLVector3::set(F32 x, F32 y, F32 z)
@ -273,16 +259,12 @@ inline void LLVector3::set(F32 x, F32 y, F32 z)
inline void LLVector3::set(const LLVector3& vec) inline void LLVector3::set(const LLVector3& vec)
{ {
mV[VX] = vec.mV[VX]; set(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
} }
inline void LLVector3::set(const F32* vec) inline void LLVector3::set(const F32* vec)
{ {
mV[VX] = vec[VX]; set(vec[VX], vec[VY], vec[VZ]);
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
} }
inline void LLVector3::set(const glm::vec4& vec) inline void LLVector3::set(const glm::vec4& vec)
@ -302,95 +284,66 @@ inline void LLVector3::set(const glm::vec3& vec)
// deprecated // deprecated
inline void LLVector3::setVec(F32 x, F32 y, F32 z) inline void LLVector3::setVec(F32 x, F32 y, F32 z)
{ {
mV[VX] = x; set(x, y, z);
mV[VY] = y;
mV[VZ] = z;
} }
// deprecated // deprecated
inline void LLVector3::setVec(const LLVector3& vec) inline void LLVector3::setVec(const LLVector3& vec)
{ {
mV[VX] = vec.mV[VX]; set(vec);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
} }
// deprecated // deprecated
inline void LLVector3::setVec(const F32* vec) inline void LLVector3::setVec(const F32* vec)
{ {
mV[VX] = vec[0]; set(vec);
mV[VY] = vec[1];
mV[VZ] = vec[2];
} }
inline F32 LLVector3::normalize() inline F32 LLVector3::normalize()
{ {
F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD) if (mag > FP_MAG_THRESHOLD)
{ {
oomag = 1.f/mag; *this /= mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
mV[VZ] *= oomag;
} }
else else
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
mag = 0; mag = 0;
} }
return (mag); return mag;
} }
// deprecated // deprecated
inline F32 LLVector3::normVec() inline F32 LLVector3::normVec()
{ {
F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); return normalize();
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
mV[VZ] *= oomag;
}
else
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VZ] = 0.f;
mag = 0;
}
return (mag);
} }
// LLVector3 Magnitude and Normalization Functions // LLVector3 Magnitude and Normalization Functions
inline F32 LLVector3::length() const inline F32 LLVector3::length() const
{ {
return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); return sqrt(lengthSquared());
} }
inline F32 LLVector3::lengthSquared() const inline F32 LLVector3::lengthSquared() const
{ {
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
} }
inline F32 LLVector3::magVec() const inline F32 LLVector3::magVec() const
{ {
return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); return length();
} }
inline F32 LLVector3::magVecSquared() const inline F32 LLVector3::magVecSquared() const
{ {
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; return lengthSquared();
} }
inline bool LLVector3::inRange( F32 min, F32 max ) const inline bool LLVector3::inRange(F32 min, F32 max) const
{ {
return mV[VX] >= min && mV[VX] <= max && return mV[VX] >= min && mV[VX] <= max &&
mV[VY] >= min && mV[VY] <= max && mV[VY] >= min && mV[VY] <= max &&
@ -416,7 +369,7 @@ inline F32 operator*(const LLVector3& a, const LLVector3& b)
inline LLVector3 operator%(const LLVector3& a, const LLVector3& b) inline LLVector3 operator%(const LLVector3& a, const LLVector3& b)
{ {
return LLVector3( a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY] ); return LLVector3(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
} }
inline LLVector3 operator/(const LLVector3& a, F32 k) inline LLVector3 operator/(const LLVector3& a, F32 k)
@ -476,7 +429,7 @@ inline const LLVector3& operator-=(LLVector3& a, const LLVector3& b)
inline const LLVector3& operator%=(LLVector3& a, const LLVector3& b) inline const LLVector3& operator%=(LLVector3& a, const LLVector3& b)
{ {
LLVector3 ret( a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]); LLVector3 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
a = ret; a = ret;
return a; return a;
} }
@ -499,9 +452,7 @@ inline const LLVector3& operator*=(LLVector3& a, const LLVector3& b)
inline const LLVector3& operator/=(LLVector3& a, F32 k) inline const LLVector3& operator/=(LLVector3& a, F32 k)
{ {
a.mV[VX] /= k; a *= 1.f / k;
a.mV[VY] /= k;
a.mV[VZ] /= k;
return a; return a;
} }
@ -526,7 +477,7 @@ inline F32 dist_vec(const LLVector3& a, const LLVector3& b)
F32 x = a.mV[VX] - b.mV[VX]; F32 x = a.mV[VX] - b.mV[VX];
F32 y = a.mV[VY] - b.mV[VY]; F32 y = a.mV[VY] - b.mV[VY];
F32 z = a.mV[VZ] - b.mV[VZ]; F32 z = a.mV[VZ] - b.mV[VZ];
return sqrt( x*x + y*y + z*z ); return sqrt(x*x + y*y + z*z);
} }
inline F32 dist_vec_squared(const LLVector3& a, const LLVector3& b) inline F32 dist_vec_squared(const LLVector3& a, const LLVector3& b)
@ -551,10 +502,7 @@ inline LLVector3 projected_vec(const LLVector3& a, const LLVector3& b)
{ {
return ((a * b) / bb) * b; return ((a * b) / bb) * b;
} }
else return b.zero;
{
return b.zero;
}
} }
inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b) inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
@ -591,11 +539,7 @@ inline LLVector3 lerp(const LLVector3& a, const LLVector3& b, F32 u)
inline bool LLVector3::isNull() const inline bool LLVector3::isNull() const
{ {
if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ] ) return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
{
return true;
}
return false;
} }
inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos) inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos)
@ -636,7 +580,7 @@ inline F32 angle_between(const LLVector3& a, const LLVector3& b)
ab = 0.0f; // get rid of negative zero ab = 0.0f; // get rid of negative zero
} }
LLVector3 c = a % b; // crossproduct LLVector3 c = a % b; // crossproduct
return atan2f(sqrtf(c * c), ab); // return the angle return atan2f(c.length(), ab); // return the angle
} }
inline bool are_parallel(const LLVector3& a, const LLVector3& b, F32 epsilon) inline bool are_parallel(const LLVector3& a, const LLVector3& b, F32 epsilon)
@ -646,7 +590,7 @@ inline bool are_parallel(const LLVector3& a, const LLVector3& b, F32 epsilon)
an.normalize(); an.normalize();
bn.normalize(); bn.normalize();
F32 dot = an * bn; F32 dot = an * bn;
if ( (1.0f - fabs(dot)) < epsilon) if (1.0f - fabs(dot) < epsilon)
{ {
return true; return true;
} }

View File

@ -107,9 +107,9 @@ public:
F32 lengthSquared() const; // Returns magnitude squared of LLVector4 F32 lengthSquared() const; // Returns magnitude squared of LLVector4
F32 normalize(); // Normalizes and returns the magnitude of LLVector4 F32 normalize(); // Normalizes and returns the magnitude of LLVector4
F32 magVec() const; // deprecated F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated F32 magVecSquared() const; // deprecated
F32 normVec(); // deprecated F32 normVec(); // deprecated
// Sets all values to absolute value of their original values // Sets all values to absolute value of their original values
// Returns true if data changed // Returns true if data changed
@ -118,8 +118,8 @@ public:
bool isExactlyClear() const { return (mV[VW] == 1.0f) && !mV[VX] && !mV[VY] && !mV[VZ]; } bool isExactlyClear() const { return (mV[VW] == 1.0f) && !mV[VX] && !mV[VY] && !mV[VZ]; }
bool isExactlyZero() const { return !mV[VW] && !mV[VX] && !mV[VY] && !mV[VZ]; } bool isExactlyZero() const { return !mV[VW] && !mV[VX] && !mV[VY] && !mV[VZ]; }
const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat
const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q
const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec
@ -159,34 +159,22 @@ LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u); // Returns a vect
inline LLVector4::LLVector4(void) inline LLVector4::LLVector4(void)
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 1.f;
} }
inline LLVector4::LLVector4(F32 x, F32 y, F32 z) inline LLVector4::LLVector4(F32 x, F32 y, F32 z)
{ {
mV[VX] = x; set(x, y, z, 1.f);
mV[VY] = y;
mV[VZ] = z;
mV[VW] = 1.f;
} }
inline LLVector4::LLVector4(F32 x, F32 y, F32 z, F32 w) inline LLVector4::LLVector4(F32 x, F32 y, F32 z, F32 w)
{ {
mV[VX] = x; set(x, y, z, w);
mV[VY] = y;
mV[VZ] = z;
mV[VW] = w;
} }
inline LLVector4::LLVector4(const F32 *vec) inline LLVector4::LLVector4(const F32 *vec)
{ {
mV[VX] = vec[VX]; set(vec);
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
mV[VW] = vec[VW];
} }
inline LLVector4::LLVector4(const F64 *vec) inline LLVector4::LLVector4(const F64 *vec)
@ -215,18 +203,12 @@ inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w)
inline LLVector4::LLVector4(const LLVector3 &vec) inline LLVector4::LLVector4(const LLVector3 &vec)
{ {
mV[VX] = vec.mV[VX]; set(vec, 1.f);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = 1.f;
} }
inline LLVector4::LLVector4(const LLVector3 &vec, F32 w) inline LLVector4::LLVector4(const LLVector3 &vec, F32 w)
{ {
mV[VX] = vec.mV[VX]; set(vec, w);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = w;
} }
inline LLVector4::LLVector4(const LLSD &sd) inline LLVector4::LLVector4(const LLSD &sd)
@ -252,43 +234,31 @@ inline LLVector4::LLVector4(const glm::vec4& vec)
inline bool LLVector4::isFinite() const inline bool LLVector4::isFinite() const
{ {
return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW])); return llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]) && llfinite(mV[VW]);
} }
// Clear and Assignment Functions // Clear and Assignment Functions
inline void LLVector4::clear() inline void LLVector4::clear()
{ {
mV[VX] = 0.f; set(0.f, 0.f, 0.f, 1.f);
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 1.f;
} }
// deprecated // deprecated
inline void LLVector4::clearVec() inline void LLVector4::clearVec()
{ {
mV[VX] = 0.f; clear();
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 1.f;
} }
// deprecated // deprecated
inline void LLVector4::zeroVec() inline void LLVector4::zeroVec()
{ {
mV[VX] = 0.f; set(0.f, 0.f, 0.f, 0.f);
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 0.f;
} }
inline void LLVector4::set(F32 x, F32 y, F32 z) inline void LLVector4::set(F32 x, F32 y, F32 z)
{ {
mV[VX] = x; set(x, y, z, 1.f);
mV[VY] = y;
mV[VZ] = z;
mV[VW] = 1.f;
} }
inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w) inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w)
@ -301,10 +271,7 @@ inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w)
inline void LLVector4::set(const LLVector4& vec) inline void LLVector4::set(const LLVector4& vec)
{ {
mV[VX] = vec.mV[VX]; set(vec.mV);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = vec.mV[VW];
} }
inline void LLVector4::set(const LLVector3& vec, F32 w) inline void LLVector4::set(const LLVector3& vec, F32 w)
@ -322,7 +289,6 @@ inline void LLVector4::set(const F32* vec)
mV[VZ] = vec[VZ]; mV[VZ] = vec[VZ];
mV[VW] = vec[VW]; mV[VW] = vec[VW];
} }
inline void LLVector4::set(const glm::vec4& vec) inline void LLVector4::set(const glm::vec4& vec)
{ {
mV[VX] = vec.x; mV[VX] = vec.x;
@ -342,68 +308,53 @@ inline void LLVector4::set(const glm::vec3& vec, F32 w)
// deprecated // deprecated
inline void LLVector4::setVec(F32 x, F32 y, F32 z) inline void LLVector4::setVec(F32 x, F32 y, F32 z)
{ {
mV[VX] = x; set(x, y, z);
mV[VY] = y;
mV[VZ] = z;
mV[VW] = 1.f;
} }
// deprecated // deprecated
inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w) inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w)
{ {
mV[VX] = x; set(x, y, z, w);
mV[VY] = y;
mV[VZ] = z;
mV[VW] = w;
} }
// deprecated // deprecated
inline void LLVector4::setVec(const LLVector4& vec) inline void LLVector4::setVec(const LLVector4& vec)
{ {
mV[VX] = vec.mV[VX]; set(vec);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = vec.mV[VW];
} }
// deprecated // deprecated
inline void LLVector4::setVec(const LLVector3& vec, F32 w) inline void LLVector4::setVec(const LLVector3& vec, F32 w)
{ {
mV[VX] = vec.mV[VX]; set(vec, w);
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = w;
} }
// deprecated // deprecated
inline void LLVector4::setVec(const F32* vec) inline void LLVector4::setVec(const F32* vec)
{ {
mV[VX] = vec[VX]; set(vec);
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
mV[VW] = vec[VW];
} }
// LLVector4 Magnitude and Normalization Functions // LLVector4 Magnitude and Normalization Functions
inline F32 LLVector4::length() const inline F32 LLVector4::length() const
{ {
return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); return sqrt(lengthSquared());
} }
inline F32 LLVector4::lengthSquared() const inline F32 LLVector4::lengthSquared() const
{ {
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
} }
inline F32 LLVector4::magVec() const inline F32 LLVector4::magVec() const
{ {
return sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); return length();
} }
inline F32 LLVector4::magVecSquared() const inline F32 LLVector4::magVecSquared() const
{ {
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]; return lengthSquared();
} }
// LLVector4 Operators // LLVector4 Operators
@ -422,7 +373,7 @@ inline LLVector4 operator-(const LLVector4& a, const LLVector4& b)
inline F32 operator*(const LLVector4& a, const LLVector4& b) inline F32 operator*(const LLVector4& a, const LLVector4& b)
{ {
return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]); return a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ];
} }
inline LLVector4 operator%(const LLVector4& a, const LLVector4& b) inline LLVector4 operator%(const LLVector4& a, const LLVector4& b)
@ -495,11 +446,7 @@ inline const LLVector4& operator*=(LLVector4& a, F32 k)
inline const LLVector4& operator/=(LLVector4& a, F32 k) inline const LLVector4& operator/=(LLVector4& a, F32 k)
{ {
F32 t = 1.f / k; return a *= 1.f / k;
a.mV[VX] *= t;
a.mV[VY] *= t;
a.mV[VZ] *= t;
return a;
} }
inline LLVector4 operator-(const LLVector4& a) inline LLVector4 operator-(const LLVector4& a)
@ -517,16 +464,16 @@ inline LLVector4::operator glm::vec4() const
return glm::make_vec4(mV); return glm::make_vec4(mV);
} }
inline F32 dist_vec(const LLVector4& a, const LLVector4& b) inline F32 dist_vec(const LLVector4& a, const LLVector4& b)
{ {
LLVector4 vec = a - b; LLVector4 vec = a - b;
return (vec.length()); return vec.length();
} }
inline F32 dist_vec_squared(const LLVector4& a, const LLVector4& b) inline F32 dist_vec_squared(const LLVector4& a, const LLVector4& b)
{ {
LLVector4 vec = a - b; LLVector4 vec = a - b;
return (vec.lengthSquared()); return vec.lengthSquared();
} }
inline LLVector4 lerp(const LLVector4& a, const LLVector4& b, F32 u) inline LLVector4 lerp(const LLVector4& a, const LLVector4& b, F32 u)
@ -538,17 +485,13 @@ inline LLVector4 lerp(const LLVector4& a, const LLVector4& b, F32 u)
a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u);
} }
inline F32 LLVector4::normalize() inline F32 LLVector4::normalize()
{ {
F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD) if (mag > FP_MAG_THRESHOLD)
{ {
oomag = 1.f/mag; *this /= mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
mV[VZ] *= oomag;
} }
else else
{ {
@ -557,30 +500,13 @@ inline F32 LLVector4::normalize()
mV[VZ] = 0.f; mV[VZ] = 0.f;
mag = 0.f; mag = 0.f;
} }
return (mag); return mag;
} }
// deprecated // deprecated
inline F32 LLVector4::normVec() inline F32 LLVector4::normVec()
{ {
F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); return normalize();
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
mV[VZ] *= oomag;
}
else
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VZ] = 0.f;
mag = 0.f;
}
return (mag);
} }
// Because apparently some parts of the viewer use this for color info. // Because apparently some parts of the viewer use this for color info.

View File

@ -66,7 +66,12 @@ LLModel::~LLModel()
{ {
if (mDecompID >= 0) if (mDecompID >= 0)
{ {
LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID); // can be null on shutdown
LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
if (decomp)
{
decomp->deleteDecomposition(mDecompID);
}
} }
mPhysics.mMesh.clear(); mPhysics.mMesh.clear();
} }

View File

@ -140,7 +140,7 @@ public:
S32 notify(const LLSD& info); S32 notify(const LLSD& info);
bool notifyChildren(const LLSD& info); bool notifyChildren(const LLSD& info);
void draw(); virtual void draw();
void storeOpenCloseState(); void storeOpenCloseState();
void restoreOpenCloseState(); void restoreOpenCloseState();

View File

@ -1346,9 +1346,17 @@ bool LLFlatListViewEx::getForceShowingUnmatchedItems() const
return mForceShowingUnmatchedItems; return mForceShowingUnmatchedItems;
} }
void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show) void LLFlatListViewEx::setForceShowingUnmatchedItems(bool show, bool notify_parent)
{
if (mForceShowingUnmatchedItems != show)
{ {
mForceShowingUnmatchedItems = show; mForceShowingUnmatchedItems = show;
if (!mFilterSubString.empty())
{
updateNoItemsMessage(mFilterSubString);
filterItems(false, true);
}
}
} }
void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent) void LLFlatListViewEx::setFilterSubString(const std::string& filter_str, bool notify_parent)
@ -1416,6 +1424,7 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)
if (visibility_changed && notify_parent) if (visibility_changed && notify_parent)
{ {
rearrangeItems();
notifyParentItemsRectChanged(); notifyParentItemsRectChanged();
} }
} }

View File

@ -484,7 +484,11 @@ public:
bool getForceShowingUnmatchedItems() const; bool getForceShowingUnmatchedItems() const;
void setForceShowingUnmatchedItems(bool show); /**
* Sets filtered out items to stay visible. Can result in rect changes,
* so can notify_parent if rect changes
*/
void setForceShowingUnmatchedItems(bool show, bool notify_parent);
/** /**
* Sets up new filter string and filters the list. * Sets up new filter string and filters the list.

View File

@ -221,6 +221,7 @@ public:
void scrollToShowSelection(); void scrollToShowSelection();
void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect); void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);
void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; } void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; }
LLScrollContainer* getScrollContainer() { return mScrollContainer; }
LLRect getVisibleRect(); LLRect getVisibleRect();
bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward); bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward);

View File

@ -31,11 +31,12 @@
#include "llfolderviewitem.h" #include "llfolderviewitem.h"
#include "llfolderview.h" #include "llfolderview.h"
#include "llfolderviewmodel.h" #include "llfolderviewmodel.h"
#include "llpanel.h"
#include "llcallbacklist.h" #include "llcallbacklist.h"
#include "llcriticaldamp.h" #include "llcriticaldamp.h"
#include "llclipboard.h" #include "llclipboard.h"
#include "llfocusmgr.h" // gFocusMgr #include "llfocusmgr.h" // gFocusMgr
#include "llnotificationsutil.h"
#include "llpanel.h"
#include "lltrans.h" #include "lltrans.h"
#include "llwindow.h" #include "llwindow.h"
@ -60,7 +61,11 @@ LLUIColor LLFolderViewItem::sSearchStatusColor;
S32 LLFolderViewItem::sTopPad = 0; S32 LLFolderViewItem::sTopPad = 0;
LLUIImagePtr LLFolderViewItem::sFolderArrowImg; LLUIImagePtr LLFolderViewItem::sFolderArrowImg;
LLUIImagePtr LLFolderViewItem::sSelectionImg; LLUIImagePtr LLFolderViewItem::sSelectionImg;
LLUIImagePtr LLFolderViewItem::sFavoriteImg;
LLUIImagePtr LLFolderViewItem::sFavoriteContentImg;
LLFontGL* LLFolderViewItem::sSuffixFont = nullptr; LLFontGL* LLFolderViewItem::sSuffixFont = nullptr;
LLUIColor LLFolderViewItem::sFavoriteColor;
bool LLFolderViewItem::sColorSetInitialized = false;
// only integers can be initialized in header // only integers can be initialized in header
const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f; const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
@ -68,6 +73,9 @@ const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f;
const LLColor4U DEFAULT_WHITE(255, 255, 255); const LLColor4U DEFAULT_WHITE(255, 255, 255);
constexpr S32 FAVORITE_IMAGE_SIZE = 14;
constexpr S32 FAVORITE_IMAGE_PAD = 3;
//static //static
LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
@ -102,6 +110,8 @@ void LLFolderViewItem::initClass()
sTopPad = default_params.item_top_pad; sTopPad = default_params.item_top_pad;
sFolderArrowImg = default_params.folder_arrow_image; sFolderArrowImg = default_params.folder_arrow_image;
sSelectionImg = default_params.selection_image; sSelectionImg = default_params.selection_image;
sFavoriteImg = default_params.favorite_image;
sFavoriteContentImg = default_params.favorite_content_image;
sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL); sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL);
sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE); sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
@ -121,6 +131,8 @@ void LLFolderViewItem::cleanupClass()
sFonts.clear(); sFonts.clear();
sFolderArrowImg = nullptr; sFolderArrowImg = nullptr;
sSelectionImg = nullptr; sSelectionImg = nullptr;
sFavoriteImg = nullptr;
sFavoriteContentImg = nullptr;
sSuffixFont = nullptr; sSuffixFont = nullptr;
} }
@ -129,13 +141,15 @@ void LLFolderViewItem::cleanupClass()
LLFolderViewItem::Params::Params() LLFolderViewItem::Params::Params()
: root(), : root(),
listener(), listener(),
favorite_image("favorite_image"),
favorite_content_image("favorite_content_image"),
folder_arrow_image("folder_arrow_image"), folder_arrow_image("folder_arrow_image"),
folder_indentation("folder_indentation"), folder_indentation("folder_indentation"),
selection_image("selection_image"), selection_image("selection_image"),
item_height("item_height"), item_height("item_height"),
item_top_pad("item_top_pad"), item_top_pad("item_top_pad"),
creation_date(), creation_date(),
allow_wear("allow_wear", true), marketplace_item("marketplace_item", false),
allow_drop("allow_drop", true), allow_drop("allow_drop", true),
font_color("font_color"), font_color("font_color"),
font_highlight_color("font_highlight_color"), font_highlight_color("font_highlight_color"),
@ -155,6 +169,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
: LLView(p), : LLView(p),
mLabelWidth(0), mLabelWidth(0),
mLabelWidthDirty(false), mLabelWidthDirty(false),
mIsFavorite(false),
mHasFavorites(false),
mSuffixNeedsRefresh(false), mSuffixNeedsRefresh(false),
mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT), mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT),
mParentFolder( NULL ), mParentFolder( NULL ),
@ -175,7 +191,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mRoot(p.root), mRoot(p.root),
mViewModelItem(p.listener), mViewModelItem(p.listener),
mIsMouseOverTitle(false), mIsMouseOverTitle(false),
mAllowWear(p.allow_wear), mMarketplaceItem(p.marketplace_item),
mAllowDrop(p.allow_drop), mAllowDrop(p.allow_drop),
mFontColor(p.font_color), mFontColor(p.font_color),
mFontHighlightColor(p.font_highlight_color), mFontHighlightColor(p.font_highlight_color),
@ -189,6 +205,21 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mMaxFolderItemOverlap(p.max_folder_item_overlap), mMaxFolderItemOverlap(p.max_folder_item_overlap),
mDoubleClickOverride(p.double_click_override) mDoubleClickOverride(p.double_click_override)
{ {
if (!sColorSetInitialized)
{
sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
sFlashBgColor = LLUIColorTable::instance().getColor("MenuItemFlashBgColor", DEFAULT_WHITE);
sFocusOutlineColor = LLUIColorTable::instance().getColor("InventoryFocusOutlineColor", DEFAULT_WHITE);
sMouseOverColor = LLUIColorTable::instance().getColor("InventoryMouseOverColor", DEFAULT_WHITE);
sFilterBGColor = LLUIColorTable::instance().getColor("FilterBackgroundColor", DEFAULT_WHITE);
sFilterTextColor = LLUIColorTable::instance().getColor("FilterTextColor", DEFAULT_WHITE);
sSuffixColor = LLUIColorTable::instance().getColor("InventoryItemLinkColor", DEFAULT_WHITE);
sSearchStatusColor = LLUIColorTable::instance().getColor("InventorySearchStatusColor", DEFAULT_WHITE);
sFavoriteColor = LLUIColorTable::instance().getColor("InventoryFavoriteColor", DEFAULT_WHITE);
sColorSetInitialized = true;
}
if (mViewModelItem) if (mViewModelItem)
{ {
mViewModelItem->setFolderViewItem(this); mViewModelItem->setFolderViewItem(this);
@ -211,6 +242,7 @@ bool LLFolderViewItem::postBuild()
// getDisplayName() is expensive (due to internal getLabelSuffix() and name building) // getDisplayName() is expensive (due to internal getLabelSuffix() and name building)
// it also sets search strings so it requires a filter reset // it also sets search strings so it requires a filter reset
mLabel = utf8str_to_wstring(vmi->getDisplayName()); mLabel = utf8str_to_wstring(vmi->getDisplayName());
mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
setToolTip(vmi->getName()); setToolTip(vmi->getName());
// Dirty the filter flag of the model from the view (CHUI-849) // Dirty the filter flag of the model from the view (CHUI-849)
@ -325,6 +357,7 @@ void LLFolderViewItem::refresh()
mLabel = utf8str_to_wstring(vmi.getDisplayName()); mLabel = utf8str_to_wstring(vmi.getDisplayName());
mLabelFontBuffer.reset(); mLabelFontBuffer.reset();
mIsFavorite = vmi.isFavorite() && !vmi.isItemInTrash();
setToolTip(vmi.getName()); setToolTip(vmi.getName());
// icons are slightly expensive to get, can be optimized // icons are slightly expensive to get, can be optimized
// see LLInventoryIcon::getIcon() // see LLInventoryIcon::getIcon()
@ -359,6 +392,8 @@ void LLFolderViewItem::refreshSuffix()
mIconOpen = vmi->getIconOpen(); mIconOpen = vmi->getIconOpen();
mIconOverlay = vmi->getIconOverlay(); mIconOverlay = vmi->getIconOverlay();
mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
if (mRoot->useLabelSuffix()) if (mRoot->useLabelSuffix())
{ {
// Very Expensive! // Very Expensive!
@ -428,6 +463,10 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
} }
mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel.c_str()) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix.c_str()) + mLabelPaddingRight; mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel.c_str()) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix.c_str()) + mLabelPaddingRight;
mLabelWidthDirty = false; mLabelWidthDirty = false;
if (mIsFavorite)
{
mLabelWidth += FAVORITE_IMAGE_SIZE + FAVORITE_IMAGE_PAD;
}
} }
*width = llmax(*width, mLabelWidth); *width = llmax(*width, mLabelWidth);
@ -554,10 +593,15 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)
void LLFolderViewItem::openItem( void ) void LLFolderViewItem::openItem( void )
{ {
if (mAllowWear || !getViewModelItem()->isItemWearable()) if (!mMarketplaceItem || !getViewModelItem()->isItemWearable())
{ {
getViewModelItem()->openItem(); getViewModelItem()->openItem();
} }
else if (mMarketplaceItem)
{
// Wearing an object from any listing, active or not, is verbotten
LLNotificationsUtil::add("AlertMerchantListingCannotWear");
}
} }
void LLFolderViewItem::rename(const std::string& new_name) void LLFolderViewItem::rename(const std::string& new_name)
@ -771,6 +815,45 @@ void LLFolderViewItem::drawOpenFolderArrow()
} }
} }
void LLFolderViewItem::drawFavoriteIcon()
{
static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true);
static LLUICachedControl<bool> draw_hollow_star("InventoryFavoritesUseHollowStar", true);
LLUIImage* favorite_image = nullptr;
if (draw_star && mIsFavorite)
{
favorite_image = sFavoriteImg;
}
else if (draw_hollow_star && mHasFavorites && !isOpen())
{
favorite_image = sFavoriteContentImg;
}
if (favorite_image)
{
S32 x_offset = 0;
LLScrollContainer* scroll = mRoot->getScrollContainer();
if (scroll)
{
S32 width = scroll->getVisibleContentRect().getWidth();
S32 offset = scroll->getDocPosHorizontal();
x_offset = width + offset;
}
else
{
x_offset = getRect().getWidth();
}
gl_draw_scaled_image(
x_offset - FAVORITE_IMAGE_SIZE - FAVORITE_IMAGE_PAD,
getRect().getHeight() - mItemHeight + FAVORITE_IMAGE_PAD,
FAVORITE_IMAGE_SIZE,
FAVORITE_IMAGE_SIZE,
favorite_image->getImage(),
sFgColor);
}
}
/*virtual*/ bool LLFolderViewItem::isHighlightAllowed() /*virtual*/ bool LLFolderViewItem::isHighlightAllowed()
{ {
return mIsSelected; return mIsSelected;
@ -928,6 +1011,7 @@ void LLFolderViewItem::draw()
{ {
drawOpenFolderArrow(); drawOpenFolderArrow();
} }
drawFavoriteIcon();
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor); drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
@ -999,7 +1083,20 @@ void LLFolderViewItem::draw()
} }
} }
LLColor4 color = (mIsSelected && filled) ? mFontHighlightColor : mFontColor; static LLUICachedControl<bool> highlight_color("InventoryFavoritesColorText", true);
LLColor4 color;
if (mIsSelected && filled)
{
color = mFontHighlightColor;
}
else if (mIsFavorite && highlight_color)
{
color = sFavoriteColor;
}
else
{
color = mFontColor;
}
if (isFadeItem()) if (isFadeItem())
{ {
@ -1093,7 +1190,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mIsFolderComplete(false), // folder might have children that are not loaded yet. mIsFolderComplete(false), // folder might have children that are not loaded yet.
mAreChildrenInited(false), // folder might have children that are not built yet. mAreChildrenInited(false), // folder might have children that are not built yet.
mLastArrangeGeneration( -1 ), mLastArrangeGeneration( -1 ),
mLastCalculatedWidth(0) mLastCalculatedWidth(0),
mFavoritesDirtyFlags(0)
{ {
} }
@ -1119,6 +1217,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
// The LLView base class takes care of object destruction. make sure that we // The LLView base class takes care of object destruction. make sure that we
// don't have mouse or keyboard focus // don't have mouse or keyboard focus
gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
if (mFavoritesDirtyFlags)
{
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this);
}
} }
// addToFolder() returns true if it succeeds. false otherwise // addToFolder() returns true if it succeeds. false otherwise
@ -1762,6 +1865,140 @@ bool LLFolderViewFolder::isMovable()
return true; return true;
} }
void LLFolderViewFolder::updateHasFavorites(bool new_childs_value)
{
if (mFavoritesDirtyFlags == 0)
{
gIdleCallbacks.addFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this);
}
if (new_childs_value)
{
mFavoritesDirtyFlags |= FAVORITE_ADDED;
}
else
{
mFavoritesDirtyFlags |= FAVORITE_REMOVED;
}
}
void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
{
LLFolderViewFolder* self = reinterpret_cast<LLFolderViewFolder*>(data);
if (self->mFavoritesDirtyFlags == 0)
{
// already processed either on previous run or by a different callback
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
return;
}
if (self->getViewModelItem()->isItemInTrash())
{
// do not display favorite-stars in trash
self->mFavoritesDirtyFlags = 0;
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
return;
}
if (self->mFavoritesDirtyFlags == FAVORITE_ADDED)
{
if (!self->mHasFavorites)
{
// propagate up, exclude root
LLFolderViewFolder* parent = self;
while (parent
&& (!parent->hasFavorites() || parent->mFavoritesDirtyFlags)
&& !parent->getViewModelItem()->isAgentInventoryRoot())
{
parent->setHasFavorites(true);
if (parent->mFavoritesDirtyFlags)
{
// Parent will remove onIdleUpdateFavorites later, don't remove now,
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
// but removing 'parent' can invalidate following iterator
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
}
}
else
{
// already up to date
self->mFavoritesDirtyFlags = 0;
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
}
}
else if (self->mFavoritesDirtyFlags > FAVORITE_ADDED)
{
// full check
LLFolderViewFolder* parent = self;
while (parent && !parent->getViewModelItem()->isAgentInventoryRoot())
{
bool has_favorites = false;
for (items_t::iterator iter = parent->mItems.begin();
iter != parent->mItems.end();)
{
items_t::iterator iit = iter++;
if ((*iit)->isFavorite())
{
has_favorites = true;
break;
}
}
for (folders_t::iterator iter = parent->mFolders.begin();
iter != parent->mFolders.end() && !has_favorites;)
{
folders_t::iterator fit = iter++;
if ((*fit)->isFavorite() || (*fit)->hasFavorites())
{
has_favorites = true;
break;
}
}
if (!has_favorites)
{
if (parent->hasFavorites())
{
parent->setHasFavorites(false);
}
else
{
// Nothing changed
break;
}
}
else
{
// propagate up, exclude root
while (parent
&& (!parent->hasFavorites() || parent->mFavoritesDirtyFlags)
&& !parent->getViewModelItem()->isAgentInventoryRoot())
{
parent->setHasFavorites(true);
if (parent->mFavoritesDirtyFlags)
{
// Parent will remove onIdleUpdateFavorites later, don't remove now,
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
// but removing 'parent' can invalidate following iterator
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
}
break;
}
if (parent->mFavoritesDirtyFlags)
{
// Parent will remove onIdleUpdateFavorites later, don't remove now.
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
// but removing 'parent' can invalidate following iterator
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
}
}
}
bool LLFolderViewFolder::isRemovable() bool LLFolderViewFolder::isRemovable()
{ {

View File

@ -50,7 +50,9 @@ class LLFolderViewItem : public LLView
public: public:
struct Params : public LLInitParam::Block<Params, LLView::Params> struct Params : public LLInitParam::Block<Params, LLView::Params>
{ {
Optional<LLUIImage*> folder_arrow_image, Optional<LLUIImage*> favorite_image,
favorite_content_image,
folder_arrow_image,
selection_image; selection_image;
Mandatory<LLFolderView*> root; Mandatory<LLFolderView*> root;
Mandatory<LLFolderViewModelItem*> listener; Mandatory<LLFolderViewModelItem*> listener;
@ -60,7 +62,7 @@ public:
item_top_pad; item_top_pad;
Optional<time_t> creation_date; Optional<time_t> creation_date;
Optional<bool> allow_wear; Optional<bool> marketplace_item;
Optional<bool> allow_drop; Optional<bool> allow_drop;
Optional<LLUIColor> font_color; Optional<LLUIColor> font_color;
@ -93,6 +95,8 @@ protected:
LLWString mLabel; LLWString mLabel;
S32 mLabelWidth; S32 mLabelWidth;
bool mLabelWidthDirty; bool mLabelWidthDirty;
bool mIsFavorite;
bool mHasFavorites;
S32 mLabelPaddingRight; S32 mLabelPaddingRight;
LLFolderViewFolder* mParentFolder; LLFolderViewFolder* mParentFolder;
LLPointer<LLFolderViewModelItem> mViewModelItem; LLPointer<LLFolderViewModelItem> mViewModelItem;
@ -122,7 +126,7 @@ protected:
mIsCurSelection, mIsCurSelection,
mDragAndDropTarget, mDragAndDropTarget,
mIsMouseOverTitle, mIsMouseOverTitle,
mAllowWear, mMarketplaceItem,
mAllowDrop, mAllowDrop,
mSingleFolderMode, mSingleFolderMode,
mDoubleClickOverride, mDoubleClickOverride,
@ -133,6 +137,7 @@ protected:
LLUIColor mFontColor; LLUIColor mFontColor;
LLUIColor mFontHighlightColor; LLUIColor mFontHighlightColor;
static bool sColorSetInitialized;
// For now assuming all colors are the same in derived classes. // For now assuming all colors are the same in derived classes.
static LLUIColor sFgColor; static LLUIColor sFgColor;
@ -145,6 +150,8 @@ protected:
static LLUIColor sFilterTextColor; static LLUIColor sFilterTextColor;
static LLUIColor sSuffixColor; static LLUIColor sSuffixColor;
static LLUIColor sSearchStatusColor; static LLUIColor sSearchStatusColor;
static LLUIColor sFavoriteColor;
// this is an internal method used for adding items to folders. A // this is an internal method used for adding items to folders. A
// no-op at this level, but reimplemented in derived classes. // no-op at this level, but reimplemented in derived classes.
@ -208,6 +215,8 @@ public:
// Returns true is this object and all of its children can be moved // Returns true is this object and all of its children can be moved
virtual bool isMovable(); virtual bool isMovable();
bool isFavorite() const { return mIsFavorite; }
// destroys this item recursively // destroys this item recursively
virtual void destroyView(); virtual void destroyView();
@ -298,6 +307,7 @@ public:
// virtual void handleDropped(); // virtual void handleDropped();
virtual void draw(); virtual void draw();
void drawOpenFolderArrow(); void drawOpenFolderArrow();
void drawFavoriteIcon();
void drawHighlight(bool showContent, bool hasKeyboardFocus, const LLUIColor& selectColor, const LLUIColor& flashColor, const LLUIColor& outlineColor, const LLUIColor& mouseOverColor); void drawHighlight(bool showContent, bool hasKeyboardFocus, const LLUIColor& selectColor, const LLUIColor& flashColor, const LLUIColor& outlineColor, const LLUIColor& mouseOverColor);
void drawLabel(const LLFontGL* font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x); void drawLabel(const LLFontGL* font, const F32 x, const F32 y, const LLColor4& color, F32 &right_x);
virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
@ -311,6 +321,8 @@ private:
static S32 sTopPad; static S32 sTopPad;
static LLUIImagePtr sFolderArrowImg; static LLUIImagePtr sFolderArrowImg;
static LLUIImagePtr sSelectionImg; static LLUIImagePtr sSelectionImg;
static LLUIImagePtr sFavoriteImg;
static LLUIImagePtr sFavoriteContentImg;
static LLFontGL* sSuffixFont; static LLFontGL* sSuffixFont;
LLFontVertexBuffer mLabelFontBuffer; LLFontVertexBuffer mLabelFontBuffer;
@ -400,6 +412,18 @@ public:
// Returns true is this object and all of its children can be moved // Returns true is this object and all of its children can be moved
virtual bool isMovable(); virtual bool isMovable();
bool isFavorite() const { return mIsFavorite; }
bool hasFavorites() const { return mHasFavorites; }
void setHasFavorites(bool val) { mHasFavorites = val; }
void updateHasFavorites(bool new_childs_value);
private:
static void onIdleUpdateFavorites(void* data);
constexpr static S32 FAVORITE_ADDED = 1;
constexpr static S32 FAVORITE_REMOVED = 2;
S32 mFavoritesDirtyFlags { 0 };
public:
// destroys this folder, and all children // destroys this folder, and all children
virtual void destroyView(); virtual void destroyView();
void destroyRoot(); void destroyRoot();

View File

@ -162,6 +162,7 @@ public:
virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0; virtual void navigateToFolder(bool new_window = false, bool change_mode = false) = 0;
virtual bool isFavorite() const = 0;
virtual bool isItemWearable() const { return false; } virtual bool isItemWearable() const { return false; }
virtual bool isItemRenameable() const = 0; virtual bool isItemRenameable() const = 0;
@ -170,7 +171,8 @@ public:
virtual bool isItemMovable( void ) const = 0; // Can be moved to another folder virtual bool isItemMovable( void ) const = 0; // Can be moved to another folder
virtual void move( LLFolderViewModelItem* parent_listener ) = 0; virtual void move( LLFolderViewModelItem* parent_listener ) = 0;
virtual bool isItemRemovable( bool check_worn = true ) const = 0; // Can be destroyed virtual bool isItemRemovable( bool check_worn = true) const = 0; // Can be destroyed
virtual bool isItemInTrash(void) const = 0;
virtual bool removeItem() = 0; virtual bool removeItem() = 0;
virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0;
@ -183,6 +185,9 @@ public:
virtual void pasteFromClipboard() = 0; virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0; virtual void pasteLinkFromClipboard() = 0;
virtual bool isAgentInventory() const = 0;
virtual bool isAgentInventoryRoot() const = 0;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet? virtual bool potentiallyVisible() = 0; // is the item definitely visible or we haven't made up our minds yet?
@ -219,6 +224,7 @@ public:
virtual S32 getSortVersion() = 0; virtual S32 getSortVersion() = 0;
virtual void setSortVersion(S32 version) = 0; virtual void setSortVersion(S32 version) = 0;
virtual void setParent(LLFolderViewModelItem* parent) = 0; virtual void setParent(LLFolderViewModelItem* parent) = 0;
virtual const LLFolderViewModelItem* getParent() = 0;
virtual bool hasParent() = 0; virtual bool hasParent() = 0;
protected: protected:
@ -249,14 +255,14 @@ public:
mChildren.clear(); mChildren.clear();
} }
void requestSort() { mSortVersion = -1; } void requestSort() override { mSortVersion = -1; }
S32 getSortVersion() { return mSortVersion; } S32 getSortVersion() override { return mSortVersion; }
void setSortVersion(S32 version) { mSortVersion = version;} void setSortVersion(S32 version) override { mSortVersion = version;}
S32 getLastFilterGeneration() const { return mLastFilterGeneration; } S32 getLastFilterGeneration() const override { return mLastFilterGeneration; }
S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; } S32 getLastFolderFilterGeneration() const { return mLastFolderFilterGeneration; }
S32 getMarkedDirtyGeneration() const { return mMarkedDirtyGeneration; } S32 getMarkedDirtyGeneration() const override { return mMarkedDirtyGeneration; }
void dirtyFilter() void dirtyFilter() override
{ {
if(mMarkedDirtyGeneration < 0) if(mMarkedDirtyGeneration < 0)
{ {
@ -271,7 +277,7 @@ public:
mParent->dirtyFilter(); mParent->dirtyFilter();
} }
} }
void dirtyDescendantsFilter() void dirtyDescendantsFilter() override
{ {
mMostFilteredDescendantGeneration = -1; mMostFilteredDescendantGeneration = -1;
if (mParent) if (mParent)
@ -279,13 +285,13 @@ public:
mParent->dirtyDescendantsFilter(); mParent->dirtyDescendantsFilter();
} }
} }
bool hasFilterStringMatch(); bool hasFilterStringMatch() override;
std::string::size_type getFilterStringOffset(); std::string::size_type getFilterStringOffset() override;
std::string::size_type getFilterStringSize(); std::string::size_type getFilterStringSize() override;
typedef std::list<LLFolderViewModelItem*> child_list_t; typedef std::list<LLPointer<LLFolderViewModelItem> > child_list_t;
virtual void addChild(LLFolderViewModelItem* child) virtual void addChild(LLFolderViewModelItem* child) override
{ {
mChildren.push_back(child); mChildren.push_back(child);
child->setParent(this); child->setParent(this);
@ -293,15 +299,15 @@ public:
requestSort(); requestSort();
} }
virtual void removeChild(LLFolderViewModelItem* child) virtual void removeChild(LLFolderViewModelItem* child) override final
{ {
mChildren.remove(child);
child->setParent(NULL); child->setParent(NULL);
mChildren.remove(child);
dirtyDescendantsFilter(); dirtyDescendantsFilter();
dirtyFilter(); dirtyFilter();
} }
virtual void clearChildren() virtual void clearChildren() override
{ {
// We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest // We are working with models that belong to views as LLPointers, clean the list, let poiters handle the rest
std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); }); std::for_each(mChildren.begin(), mChildren.end(), [](LLFolderViewModelItem* c) {c->setParent(NULL); });
@ -314,7 +320,7 @@ public:
child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); } child_list_t::const_iterator getChildrenEnd() const { return mChildren.end(); }
child_list_t::size_type getChildrenCount() const { return mChildren.size(); } child_list_t::size_type getChildrenCount() const { return mChildren.size(); }
void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) void setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0) override
{ {
mPassedFilter = passed; mPassedFilter = passed;
mLastFilterGeneration = filter_generation; mLastFilterGeneration = filter_generation;
@ -323,20 +329,20 @@ public:
mMarkedDirtyGeneration = -1; mMarkedDirtyGeneration = -1;
} }
void setPassedFolderFilter(bool passed, S32 filter_generation) void setPassedFolderFilter(bool passed, S32 filter_generation) override
{ {
mPassedFolderFilter = passed; mPassedFolderFilter = passed;
mLastFolderFilterGeneration = filter_generation; mLastFolderFilterGeneration = filter_generation;
} }
virtual bool potentiallyVisible() virtual bool potentiallyVisible() override
{ {
return passedFilter() // we've passed the filter return passedFilter() // we've passed the filter
|| (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet
|| descendantsPassedFilter(); || descendantsPassedFilter();
} }
virtual bool passedFilter(S32 filter_generation = -1) virtual bool passedFilter(S32 filter_generation = -1) override
{ {
if (filter_generation < 0) if (filter_generation < 0)
{ {
@ -347,7 +353,7 @@ public:
return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation)); return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));
} }
virtual bool descendantsPassedFilter(S32 filter_generation = -1) virtual bool descendantsPassedFilter(S32 filter_generation = -1) override
{ {
if (filter_generation < 0) if (filter_generation < 0)
{ {
@ -356,10 +362,10 @@ public:
return mMostFilteredDescendantGeneration >= filter_generation; return mMostFilteredDescendantGeneration >= filter_generation;
} }
protected: protected:
virtual void setParent(LLFolderViewModelItem* parent) { mParent = parent; } virtual void setParent(LLFolderViewModelItem* parent) override final { mParent = parent; }
virtual bool hasParent() { return mParent != NULL; } virtual const LLFolderViewModelItem* getParent() override { return mParent; };
virtual bool hasParent() override { return mParent != NULL; }
S32 mSortVersion; S32 mSortVersion;
bool mPassedFilter; bool mPassedFilter;
@ -376,7 +382,7 @@ protected:
LLFolderViewModelItem* mParent; LLFolderViewModelItem* mParent;
LLFolderViewModelInterface& mRootViewModel; LLFolderViewModelInterface& mRootViewModel;
void setFolderViewItem(LLFolderViewItem* folder_view_item) { mFolderViewItem = folder_view_item;} void setFolderViewItem(LLFolderViewItem* folder_view_item) override { mFolderViewItem = folder_view_item;}
LLFolderViewItem* mFolderViewItem; LLFolderViewItem* mFolderViewItem;
}; };
@ -390,15 +396,15 @@ public:
mFolderView(NULL) mFolderView(NULL)
{} {}
virtual void requestSortAll() virtual void requestSortAll() override
{ {
// sort everything // sort everything
mTargetSortVersion++; mTargetSortVersion++;
} }
virtual std::string getStatusText(bool is_empty_folder = false); virtual std::string getStatusText(bool is_empty_folder = false) override;
virtual void filter(); virtual void filter() override;
void setFolderView(LLFolderView* folder_view) { mFolderView = folder_view;} void setFolderView(LLFolderView* folder_view) override { mFolderView = folder_view;}
protected: protected:
bool needsSort(class LLFolderViewModelItem* item); bool needsSort(class LLFolderViewModelItem* item);
@ -428,14 +434,14 @@ public:
virtual const SortType& getSorter() const { return *mSorter; } virtual const SortType& getSorter() const { return *mSorter; }
virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); } virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); }
virtual FilterType& getFilter() { return *mFilter; } virtual FilterType& getFilter() override { return *mFilter; }
virtual const FilterType& getFilter() const { return *mFilter; } virtual const FilterType& getFilter() const override { return *mFilter; }
virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); } virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); }
// By default, we assume the content is available. If a network fetch mechanism is implemented for the model, // By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
// this method needs to be overloaded and return the relevant fetch status. // this method needs to be overloaded and return the relevant fetch status.
virtual bool contentsReady() { return true; } virtual bool contentsReady() override { return true; }
virtual bool isFolderComplete(LLFolderViewFolder* folder) { return true; } virtual bool isFolderComplete(LLFolderViewFolder* folder) override { return true; }
struct ViewModelCompare struct ViewModelCompare
{ {
@ -456,7 +462,7 @@ public:
const SortType& mSorter; const SortType& mSorter;
}; };
void sort(LLFolderViewFolder* folder) void sort(LLFolderViewFolder* folder) override
{ {
if (needsSort(folder->getViewModelItem())) if (needsSort(folder->getViewModelItem()))
{ {

View File

@ -46,6 +46,7 @@
#include "llfocusmgr.h" #include "llfocusmgr.h"
#include "llcoord.h" #include "llcoord.h"
#include "llwindow.h" #include "llwindow.h"
#include "llemojihelper.h"
#include "llcriticaldamp.h" #include "llcriticaldamp.h"
#include "lluictrlfactory.h" #include "lluictrlfactory.h"
@ -1411,6 +1412,7 @@ void LLMenuItemBranchDownGL::openMenu( void )
} }
else else
{ {
LLEmojiHelper::instance().hideHelper(nullptr, true);
if (branch->getTornOff()) if (branch->getTornOff())
{ {
LLFloater * branch_parent = dynamic_cast<LLFloater *>(branch->getParent()); LLFloater * branch_parent = dynamic_cast<LLFloater *>(branch->getParent());

View File

@ -28,6 +28,7 @@
#include "llmodaldialog.h" #include "llmodaldialog.h"
#include "llemojihelper.h"
#include "llfocusmgr.h" #include "llfocusmgr.h"
#include "v4color.h" #include "v4color.h"
#include "v2math.h" #include "v2math.h"
@ -35,6 +36,7 @@
#include "llwindow.h" #include "llwindow.h"
#include "llkeyboard.h" #include "llkeyboard.h"
#include "llmenugl.h" #include "llmenugl.h"
// static // static
std::list<LLModalDialog*> LLModalDialog::sModalStack; std::list<LLModalDialog*> LLModalDialog::sModalStack;
@ -98,7 +100,7 @@ void LLModalDialog::onOpen(const LLSD& key)
{ {
if (mModal) if (mModal)
{ {
// If Modal, Hide the active modal dialog // If Modal, hide the active modal dialog
if (!sModalStack.empty()) if (!sModalStack.empty())
{ {
LLModalDialog* front = sModalStack.front(); LLModalDialog* front = sModalStack.front();
@ -155,6 +157,12 @@ void LLModalDialog::setVisible( bool visible )
{ {
if( visible ) if( visible )
{ {
// Hide all menus currently shown
LLMenuGL::sMenuContainer->hideMenus();
// Hide EmojiPicker if it is shown
LLEmojiHelper::instance().hideHelper(nullptr, true);
// This is a modal dialog. It sucks up all mouse and keyboard operations. // This is a modal dialog. It sucks up all mouse and keyboard operations.
gFocusMgr.setMouseCapture( this ); gFocusMgr.setMouseCapture( this );
@ -301,7 +309,6 @@ void LLModalDialog::centerOnScreen()
centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY]))); centerWithin(LLRect(0, 0, ll_round(window_size.mV[VX]), ll_round(window_size.mV[VY])));
} }
// static // static
void LLModalDialog::onAppFocusLost() void LLModalDialog::onAppFocusLost()
{ {
@ -333,6 +340,7 @@ void LLModalDialog::onAppFocusGained()
} }
} }
// static
void LLModalDialog::shutdownModals() void LLModalDialog::shutdownModals()
{ {
// This method is only for use during app shutdown. ~LLModalDialog() // This method is only for use during app shutdown. ~LLModalDialog()

View File

@ -274,7 +274,9 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mShowChatMentionPicker(false), mShowChatMentionPicker(false),
mEnableTooltipPaste(p.enable_tooltip_paste), mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(false), mPassDelete(false),
mKeepSelectionOnReturn(false) mKeepSelectionOnReturn(false),
mSelectAllOnFocusReceived(false),
mSelectedOnFocusReceived(false)
{ {
mSourceID.generate(); mSourceID.generate();
@ -398,6 +400,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen
setCursorPos(loc); setCursorPos(loc);
mIsSelecting = true; mIsSelecting = true;
mSelectedOnFocusReceived = false;
mSelectionEnd = mCursorPos; mSelectionEnd = mCursorPos;
mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size())); mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
} }
@ -677,6 +680,13 @@ bool LLTextEditor::canSelectAll() const
return true; return true;
} }
//virtual
void LLTextEditor::deselect()
{
LLTextBase::deselect();
mSelectedOnFocusReceived = false;
}
// virtual // virtual
void LLTextEditor::selectAll() void LLTextEditor::selectAll()
{ {
@ -694,6 +704,11 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p
endSelection(); endSelection();
} }
void LLTextEditor::setSelectAllOnFocusReceived(bool b)
{
mSelectAllOnFocusReceived = b;
}
void LLTextEditor::insertEmoji(llwchar emoji) void LLTextEditor::insertEmoji(llwchar emoji)
{ {
LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL; LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
@ -795,8 +810,16 @@ bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
// Delay cursor flashing // Delay cursor flashing
resetCursorBlink(); resetCursorBlink();
mSelectedOnFocusReceived = false;
if (handled && !gFocusMgr.getMouseCapture()) if (handled && !gFocusMgr.getMouseCapture())
{ {
if (!mask && mSelectAllOnFocusReceived)
{
mIsSelecting = false;
mSelectionStart = getLength();
mSelectionEnd = 0;
mSelectedOnFocusReceived = true;
}
gFocusMgr.setMouseCapture( this ); gFocusMgr.setMouseCapture( this );
} }
return handled; return handled;
@ -2200,6 +2223,11 @@ void LLTextEditor::focusLostHelper()
gEditMenuHandler = NULL; gEditMenuHandler = NULL;
} }
if (mSelectedOnFocusReceived)
{
deselect();
}
if (mCommitOnFocusLost) if (mCommitOnFocusLost)
{ {
onCommit(); onCommit();

View File

@ -144,8 +144,10 @@ public:
virtual bool canDoDelete() const; virtual bool canDoDelete() const;
virtual void selectAll(); virtual void selectAll();
virtual bool canSelectAll() const; virtual bool canSelectAll() const;
virtual void deselect();
void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos); void selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_pos);
void setSelectAllOnFocusReceived(bool b);
virtual bool canLoadOrSaveToFile(); virtual bool canLoadOrSaveToFile();
@ -336,6 +338,8 @@ private:
bool mEnableTooltipPaste; bool mEnableTooltipPaste;
bool mPassDelete; bool mPassDelete;
bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
bool mSelectAllOnFocusReceived;
bool mSelectedOnFocusReceived;
LLUUID mSourceID; LLUUID mSourceID;

View File

@ -170,6 +170,16 @@ void LLUrlAction::copyLabelToClipboard(std::string url)
} }
} }
std::string LLUrlAction::getURLLabel(std::string url)
{
LLUrlMatch match;
if (LLUrlRegistry::instance().findUrl(url, match))
{
return match.getLabel();
}
return "";
}
void LLUrlAction::showProfile(std::string url) void LLUrlAction::showProfile(std::string url)
{ {
// Get id from 'secondlife:///app/{cmd}/{id}/{action}' // Get id from 'secondlife:///app/{cmd}/{id}/{action}'

View File

@ -78,6 +78,8 @@ public:
/// copy a Url to the clipboard /// copy a Url to the clipboard
static void copyURLToClipboard(std::string url); static void copyURLToClipboard(std::string url);
static std::string getURLLabel(std::string url);
/// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile
static void showProfile(std::string url); static void showProfile(std::string url);
static std::string getUserID(std::string url); static std::string getUserID(std::string url);

View File

@ -43,8 +43,6 @@
#include "llexperiencecache.h" #include "llexperiencecache.h"
#include "v3dmath.h" #include "v3dmath.h"
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
// Utility functions // Utility functions
std::string localize_slapp_label(const std::string& url, const std::string& full_name); std::string localize_slapp_label(const std::string& url, const std::string& full_name);

View File

@ -43,6 +43,8 @@
class LLAvatarName; class LLAvatarName;
class LLVector3d; class LLVector3d;
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
typedef boost::signals2::signal<void (const std::string& url, typedef boost::signals2::signal<void (const std::string& url,
const std::string& label, const std::string& label,
const std::string& icon)> LLUrlLabelSignal; const std::string& icon)> LLUrlLabelSignal;

View File

@ -904,12 +904,12 @@ void LLWebRTCPeerConnectionImpl::enableSenderTracks(bool enable)
// set_enabled shouldn't be done on the worker thread. // set_enabled shouldn't be done on the worker thread.
if (mPeerConnection) if (mPeerConnection)
{ {
mPeerConnection->SetAudioRecording(enable);
auto senders = mPeerConnection->GetSenders(); auto senders = mPeerConnection->GetSenders();
for (auto &sender : senders) for (auto &sender : senders)
{ {
sender->track()->set_enabled(enable); sender->track()->set_enabled(enable);
} }
mPeerConnection->SetAudioRecording(enable);
} }
} }
@ -964,6 +964,9 @@ void LLWebRTCPeerConnectionImpl::setMute(bool mute)
{ {
if (mPeerConnection) if (mPeerConnection)
{ {
// SetAudioRecording must be called before enabling/disabling tracks.
mPeerConnection->SetAudioRecording(enable);
auto senders = mPeerConnection->GetSenders(); auto senders = mPeerConnection->GetSenders();
RTC_LOG(LS_INFO) << __FUNCTION__ << (mMute ? "disabling" : "enabling") << " streams count " << senders.size(); RTC_LOG(LS_INFO) << __FUNCTION__ << (mMute ? "disabling" : "enabling") << " streams count " << senders.size();
@ -982,7 +985,6 @@ void LLWebRTCPeerConnectionImpl::setMute(bool mute)
track->set_enabled(enable); track->set_enabled(enable);
} }
} }
mPeerConnection->SetAudioRecording(enable);
} }
}); });
} }

View File

@ -371,10 +371,14 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
LLWindowWin32Thread(); LLWindowWin32Thread();
void run() override; void run() override;
void close() override;
// closes queue, wakes thread, waits until thread closes // Detroys handles and window
void wakeAndDestroy(); // Either post to or call from window thread
void destroyWindow();
// Closes queue, wakes thread, waits until thread closes.
// Call from main thread
bool wakeAndDestroy();
void glReady() void glReady()
{ {
@ -431,6 +435,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18 // until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
bool mGLReady = false; bool mGLReady = false;
bool mGotGLBuffer = false; bool mGotGLBuffer = false;
LLAtomicBool mDeleteOnExit = false;
}; };
@ -874,6 +879,7 @@ LLWindowWin32::~LLWindowWin32()
} }
delete mDragDrop; delete mDragDrop;
mDragDrop = NULL;
delete [] mWindowTitle; delete [] mWindowTitle;
mWindowTitle = NULL; mWindowTitle = NULL;
@ -885,6 +891,7 @@ LLWindowWin32::~LLWindowWin32()
mWindowClassName = NULL; mWindowClassName = NULL;
delete mWindowThread; delete mWindowThread;
mWindowThread = NULL;
} }
void LLWindowWin32::show() void LLWindowWin32::show()
@ -993,7 +1000,7 @@ void LLWindowWin32::close()
// Restore gamma to the system values. // Restore gamma to the system values.
restoreGamma(); restoreGamma();
LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL; LL_INFOS("Window") << "Destroying Window Thread" << LL_ENDL;
if (sWindowHandleForMessageBox == mWindowHandle) if (sWindowHandleForMessageBox == mWindowHandle)
{ {
@ -1003,7 +1010,11 @@ void LLWindowWin32::close()
mhDC = NULL; mhDC = NULL;
mWindowHandle = NULL; mWindowHandle = NULL;
mWindowThread->wakeAndDestroy(); if (mWindowThread->wakeAndDestroy())
{
// thread will delete itselfs once done
mWindowThread = NULL;
}
} }
bool LLWindowWin32::isValid() bool LLWindowWin32::isValid()
@ -3134,10 +3145,14 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break; break;
} }
} }
else else // (NULL == window_imp)
{ {
// (NULL == window_imp)
LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL; LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
if (u_msg == WM_DESTROY)
{
PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0
return 0;
}
} }
// pass unhandled messages down to Windows // pass unhandled messages down to Windows
@ -4607,25 +4622,11 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
#endif // LL_WINDOWS #endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
: LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, true /*should be false, temporary workaround for SL-18721*/) : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
{ {
LL::ThreadPool::start(); LL::ThreadPool::start();
} }
void LLWindowWin32::LLWindowWin32Thread::close()
{
if (!mQueue->isClosed())
{
LL_WARNS() << "Closing window thread without using destroy_window_handler" << LL_ENDL;
LL::ThreadPool::close();
// Workaround for SL-18721 in case window closes too early and abruptly
LLSplashScreen::show();
LLSplashScreen::update("..."); // will be updated later
}
}
/** /**
* LogChange is to log changes in status while trying to avoid spamming the * LogChange is to log changes in status while trying to avoid spamming the
* log with repeated messages, especially in a tight loop. It refuses to log * log with repeated messages, especially in a tight loop. It refuses to log
@ -4849,108 +4850,110 @@ void LLWindowWin32::LLWindowWin32Thread::run()
} }
#endif #endif
} }
destroyWindow();
if (mDeleteOnExit)
{
delete this;
}
} }
void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy() void LLWindowWin32::LLWindowWin32Thread::destroyWindow()
{
if (mWindowHandleThrd != NULL && IsWindow(mWindowHandleThrd))
{
if (mhDCThrd)
{
if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
{
LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
}
mhDCThrd = NULL;
}
// This causes WM_DESTROY to be sent *immediately*
if (!destroy_window_handler(mWindowHandleThrd))
{
LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
}
}
else
{
// Something killed the window while we were busy destroying gl or handle somehow got broken
LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
}
mWindowHandleThrd = NULL;
mhDCThrd = NULL;
}
bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
{ {
if (mQueue->isClosed()) if (mQueue->isClosed())
{ {
LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL; LL_WARNS("Window") << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
return; return false;
} }
// Make sure we don't leave a blank toolbar button. // Hide the window immediately to prevent user interaction during shutdown
// Also hiding window now prevents user from suspending it if (mWindowHandleThrd)
// via some action (like dragging it around) {
ShowWindow(mWindowHandleThrd, SW_HIDE); ShowWindow(mWindowHandleThrd, SW_HIDE);
}
else
{
LL_WARNS("Window") << "Tried to hide window, but Win32 window handle is NULL." << LL_ENDL;
return false;
}
// Schedule destruction mGLReady = false;
// Capture current handle before we lose it
HWND old_handle = mWindowHandleThrd; HWND old_handle = mWindowHandleThrd;
post([this]()
{
if (IsWindow(mWindowHandleThrd))
{
if (mhDCThrd)
{
if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
{
LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
}
mhDCThrd = NULL;
}
// This causes WM_DESTROY to be sent *immediately* // Clear the user data to prevent callbacks from finding us
if (!destroy_window_handler(mWindowHandleThrd)) if (old_handle)
{ {
LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL; SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL);
} }
}
else
{
// Something killed the window while we were busy destroying gl or handle somehow got broken
LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
}
mWindowHandleThrd = NULL;
mhDCThrd = NULL;
mGLReady = false;
});
// Signal thread to clean up when done
mDeleteOnExit = true;
// Close the queue first
LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL; LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
mQueue->close(); mQueue->close();
// Post a nonsense user message to wake up the thread in // Wake up the thread if it's stuck in GetMessage()
// case it is waiting for a getMessage()
if (old_handle) if (old_handle)
{ {
WPARAM wparam{ 0xB0B0 }; WPARAM wparam{ 0xB0B0 };
LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle
<< ", " << WM_DUMMY_ << ", " << WM_DUMMY_
<< ", " << wparam << ")" << std::dec << LL_ENDL; << ", " << wparam << ")" << std::dec << LL_ENDL;
// Use PostMessage to signal thread to wake up
PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337); PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
} }
// There are cases where window will refuse to close, // Cleanly detach threads instead of joining them to avoid blocking the main thread
// can't wait forever on join, check state instead // This is acceptable since the thread will self-delete with mDeleteOnExit
LLTimer timeout; for (auto& pair : mThreads)
timeout.setTimerExpirySec(2.0);
while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd)
{ {
ms_sleep(100); try {
// Only detach if the thread is joinable
if (pair.second.joinable())
{
pair.second.detach();
}
}
catch (const std::system_error& e) {
LL_WARNS("Window") << "Exception detaching thread: " << e.what() << LL_ENDL;
}
} }
if (getQueue().done() || mWindowHandleThrd == NULL)
{
// Window is closed, started closing or is cleaning up
// now wait for our single thread to die.
if (mWindowHandleThrd)
{
LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
}
else
{
LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
}
for (auto& pair : mThreads)
{
pair.second.join();
}
}
else
{
// Something suspended window thread, can't afford to wait forever
// so kill thread instead
// Ex: This can happen if user starts dragging window arround (if it
// was visible) or a modal notification pops up
LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL;
for (auto& pair : mThreads)
{
// very unsafe
TerminateThread(pair.second.native_handle(), 0);
pair.second.detach();
}
}
LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL; LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
return true;
} }
void LLWindowWin32::post(const std::function<void()>& func) void LLWindowWin32::post(const std::function<void()>& func)

View File

@ -157,6 +157,9 @@ LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
{ {
if ((persist != PERSIST_NO) && mComment.empty()) if ((persist != PERSIST_NO) && mComment.empty())
{ {
// File isn't actually missing, but something is wrong with it
// so the main point is to warn user to reinstall
LLError::LLUserWarningMsg::showMissingFiles();
LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL; LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL;
} }
//Push back versus setValue'ing here, since we don't want to call a signal yet //Push back versus setValue'ing here, since we don't want to call a signal yet

View File

@ -342,6 +342,7 @@ set(viewer_SOURCE_FILES
llhudeffectpointat.cpp llhudeffectpointat.cpp
llhudeffecttrail.cpp llhudeffecttrail.cpp
llhudeffectblob.cpp llhudeffectblob.cpp
llhudeffectresetskeleton.cpp
llhudicon.cpp llhudicon.cpp
llhudmanager.cpp llhudmanager.cpp
llhudnametag.cpp llhudnametag.cpp
@ -367,6 +368,7 @@ set(viewer_SOURCE_FILES
llinventorygallerymenu.cpp llinventorygallerymenu.cpp
llinventoryicon.cpp llinventoryicon.cpp
llinventoryitemslist.cpp llinventoryitemslist.cpp
llinventorylistener.cpp
llinventorylistitem.cpp llinventorylistitem.cpp
llinventorymodel.cpp llinventorymodel.cpp
llinventorymodelbackgroundfetch.cpp llinventorymodelbackgroundfetch.cpp
@ -1016,6 +1018,7 @@ set(viewer_HEADER_FILES
llhudeffectpointat.h llhudeffectpointat.h
llhudeffecttrail.h llhudeffecttrail.h
llhudeffectblob.h llhudeffectblob.h
llhudeffectresetskeleton.h
llhudicon.h llhudicon.h
llhudmanager.h llhudmanager.h
llhudnametag.h llhudnametag.h
@ -1040,6 +1043,7 @@ set(viewer_HEADER_FILES
llinventorygallerymenu.h llinventorygallerymenu.h
llinventoryicon.h llinventoryicon.h
llinventoryitemslist.h llinventoryitemslist.h
llinventorylistener.h
llinventorylistitem.h llinventorylistitem.h
llinventorymodel.h llinventorymodel.h
llinventorymodelbackgroundfetch.h llinventorymodelbackgroundfetch.h

View File

@ -1 +1 @@
7.2.0 7.2.1

View File

@ -102,7 +102,7 @@
<key>Type</key> <key>Type</key>
<string>S32</string> <string>S32</string>
<key>Value</key> <key>Value</key>
<real>300.0</real> <real>300</real>
</map> </map>
<key>AckCollectTime</key> <key>AckCollectTime</key>
<map> <map>
@ -1908,6 +1908,17 @@
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>DebugSelectionLODs</key>
<map>
<key>Comment</key>
<string>Force selection to show specific LOD, -1 for off, 0 - lowest, 4 - high.</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>-1</integer>
</map>
<key>AnimatedObjectsAllowLeftClick</key> <key>AnimatedObjectsAllowLeftClick</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -14295,10 +14306,32 @@
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>OutfitGallerySortByName</key> <key>OutfitGallerySortOrder</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Always sort outfits by name in Outfit Gallery</string> <string>Gallery sorting: 0 - sort outfits by name, 1 - images frst, 2 - favorites first</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>OutfitListSortOrder</key>
<map>
<key>Comment</key>
<string>How outfit list in Avatar's floater is sorted. 0 - by name 1 - favorites to top</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>OutfitListFilterFullList</key>
<map>
<key>Comment</key>
<string> 0 - show only matches. 1 - show all items in outfit as long as outfit or item inside matches.</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
@ -16179,6 +16212,50 @@
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>InventoryFavoritesUseStar</key>
<map>
<key>Comment</key>
<string>Show star near favorited items in inventory</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>InventoryFavoritesUseHollowStar</key>
<map>
<key>Comment</key>
<string>Show star near folders that contain favorites</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>InventoryFavoritesColorText</key>
<map>
<key>Comment</key>
<string>render favorite items using InventoryFavoriteText as color</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>InventoryAddAttachmentBehavior</key>
<map>
<key>Comment</key>
<string>Defines behavior when hitting return on an inventory item</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>StatsReportMaxDuration</key> <key>StatsReportMaxDuration</key>
<map> <map>
<key>Comment</key> <key>Comment</key>

View File

@ -329,7 +329,7 @@
<key>KeepConversationLogTranscripts</key> <key>KeepConversationLogTranscripts</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Keep a conversation log and transcripts</string> <string>Keep a conversation log and transcripts 2 - both, 1 - logs, 0 - none</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>

View File

@ -220,6 +220,7 @@ void GLTFSceneManager::uploadSelection()
LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost, expected_upload_cost,
LLUUID::null,
false, false,
finish, finish,
failure)); failure));
@ -283,6 +284,7 @@ void GLTFSceneManager::uploadSelection()
LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost, expected_upload_cost,
LLUUID::null,
false, false,
finish, finish,
failure)); failure));
@ -559,6 +561,7 @@ void GLTFSceneManager::update()
LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost, expected_upload_cost,
LLUUID::null,
false, false,
finish, finish,
failure)); failure));

View File

@ -121,8 +121,8 @@ const F32 MIN_FIDGET_TIME = 8.f; // seconds
const F32 MAX_FIDGET_TIME = 20.f; // seconds const F32 MAX_FIDGET_TIME = 20.f; // seconds
const S32 UI_FEATURE_VERSION = 1; const S32 UI_FEATURE_VERSION = 1;
// For version 1: 1 - inventory, 2 - gltf // For version 1, flag holds: 1 - inventory thumbnails, 2 - gltf, 4 - inventory favorites
const S32 UI_FEATURE_FLAGS = 3; const S32 UI_FEATURE_FLAGS = 7;
// The agent instance. // The agent instance.
LLAgent gAgent; LLAgent gAgent;
@ -223,7 +223,6 @@ private:
LLVector3d mPosGlobal; LLVector3d mPosGlobal;
}; };
class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation
{ {
public: public:
@ -604,7 +603,7 @@ void LLAgent::getFeatureVersionAndFlags(S32& version, S32& flags)
if (feature_version.isInteger()) if (feature_version.isInteger())
{ {
version = feature_version.asInteger(); version = feature_version.asInteger();
flags = 1; // inventory flag flags = 3; // show 'favorites' notification
} }
else if (feature_version.isMap()) else if (feature_version.isMap())
{ {
@ -630,13 +629,8 @@ void LLAgent::showLatestFeatureNotification(const std::string key)
if (key == "inventory") if (key == "inventory")
{ {
// Notify user about new thumbnail support // Notify user about new favorites support
flag = 1; flag = 4;
}
if (key == "gltf")
{
flag = 2;
} }
if ((flags & flag) == 0) if ((flags & flag) == 0)
@ -843,7 +837,6 @@ void LLAgent::movePitch(F32 mag)
} }
} }
// Does this parcel allow you to fly? // Does this parcel allow you to fly?
bool LLAgent::canFly() bool LLAgent::canFly()
{ {
@ -923,7 +916,6 @@ void LLAgent::setFlying(bool fly, bool fail_sound)
LLFloaterMove::setFlyingMode(fly); LLFloaterMove::setFlyingMode(fly);
} }
// UI based mechanism of setting fly state // UI based mechanism of setting fly state
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// toggleFlying() // toggleFlying()
@ -1002,7 +994,6 @@ void LLAgent::capabilityReceivedCallback(const LLUUID &region_id, LLViewerRegion
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// setRegion() // setRegion()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1108,7 +1099,6 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
mRegionChangedSignal(); mRegionChangedSignal();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getRegion() // getRegion()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1117,7 +1107,6 @@ LLViewerRegion *LLAgent::getRegion() const
return mRegionp; return mRegionp;
} }
LLHost LLAgent::getRegionHost() const LLHost LLAgent::getRegionHost() const
{ {
if (mRegionp) if (mRegionp)
@ -1148,7 +1137,6 @@ bool LLAgent::inPrelude()
return mRegionp && mRegionp->isPrelude(); return mRegionp && mRegionp->isPrelude();
} }
std::string LLAgent::getRegionCapability(const std::string &name) std::string LLAgent::getRegionCapability(const std::string &name)
{ {
if (!mRegionp) if (!mRegionp)
@ -1157,7 +1145,6 @@ std::string LLAgent::getRegionCapability(const std::string &name)
return mRegionp->getCapability(name); return mRegionp->getCapability(name);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// canManageEstate() // canManageEstate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1185,7 +1172,6 @@ void LLAgent::sendMessage()
gMessageSystem->sendMessage(mRegionp->getHost()); gMessageSystem->sendMessage(mRegionp->getHost());
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// sendReliableMessage() // sendReliableMessage()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1219,7 +1205,6 @@ LLVector3 LLAgent::getVelocity() const
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// setPositionAgent() // setPositionAgent()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1293,7 +1278,6 @@ const LLVector3 &LLAgent::getPositionAgent()
} }
} }
return mFrameAgent.getOrigin(); return mFrameAgent.getOrigin();
} }
@ -1302,7 +1286,6 @@ boost::signals2::connection LLAgent::whenPositionChanged(position_signal_t::slot
return mOnPositionChanged.connect(fn); return mOnPositionChanged.connect(fn);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getRegionsVisited() // getRegionsVisited()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1319,7 +1302,6 @@ F64 LLAgent::getDistanceTraveled() const
return mDistanceTraveled; return mDistanceTraveled;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getPosAgentFromGlobal() // getPosAgentFromGlobal()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1330,7 +1312,6 @@ LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const
return pos_agent; return pos_agent;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getPosGlobalFromAgent() // getPosGlobalFromAgent()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1346,7 +1327,6 @@ void LLAgent::sitDown()
setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// resetAxes() // resetAxes()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1355,7 +1335,6 @@ void LLAgent::resetAxes()
mFrameAgent.resetAxes(); mFrameAgent.resetAxes();
} }
// Copied from LLCamera::setOriginAndLookAt // Copied from LLCamera::setOriginAndLookAt
// Look_at must be unit vector // Look_at must be unit vector
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1384,7 +1363,6 @@ void LLAgent::resetAxes(const LLVector3 &look_at)
mFrameAgent.setAxes(look_at, left, up); mFrameAgent.setAxes(look_at, left, up);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// rotate() // rotate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1393,7 +1371,6 @@ void LLAgent::rotate(F32 angle, const LLVector3 &axis)
mFrameAgent.rotate(angle, axis); mFrameAgent.rotate(angle, axis);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// rotate() // rotate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1402,7 +1379,6 @@ void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z)
mFrameAgent.rotate(angle, x, y, z); mFrameAgent.rotate(angle, x, y, z);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// rotate() // rotate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1411,7 +1387,6 @@ void LLAgent::rotate(const LLMatrix3 &matrix)
mFrameAgent.rotate(matrix); mFrameAgent.rotate(matrix);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// rotate() // rotate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1420,7 +1395,6 @@ void LLAgent::rotate(const LLQuaternion &quaternion)
mFrameAgent.rotate(quaternion); mFrameAgent.rotate(quaternion);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getReferenceUpVector() // getReferenceUpVector()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1449,7 +1423,6 @@ LLVector3 LLAgent::getReferenceUpVector()
return up_vector; return up_vector;
} }
// Radians, positive is forward into ground // Radians, positive is forward into ground
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// pitch() // pitch()
@ -1493,7 +1466,6 @@ void LLAgent::pitch(F32 angle)
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// roll() // roll()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1502,7 +1474,6 @@ void LLAgent::roll(F32 angle)
mFrameAgent.roll(angle); mFrameAgent.roll(angle);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// yaw() // yaw()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1514,7 +1485,6 @@ void LLAgent::yaw(F32 angle)
} }
} }
// Returns a quat that represents the rotation of the agent in the absolute frame // Returns a quat that represents the rotation of the agent in the absolute frame
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getQuat() // getQuat()
@ -1540,7 +1510,6 @@ void LLAgent::setControlFlags(U32 mask)
mControlFlags |= mask; mControlFlags |= mask;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// clearControlFlags() // clearControlFlags()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1628,7 +1597,6 @@ bool LLAgent::isDoNotDisturb() const
return mIsDoNotDisturb; return mIsDoNotDisturb;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// startAutoPilotGlobal() // startAutoPilotGlobal()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1734,7 +1702,6 @@ void LLAgent::startAutoPilotGlobal(
mAutoPilotNoProgressFrameCount = 0; mAutoPilotNoProgressFrameCount = 0;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// setAutoPilotTargetGlobal // setAutoPilotTargetGlobal
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1788,7 +1755,6 @@ void LLAgent::startFollowPilot(const LLUUID &leader_id, bool allow_flying, F32 s
allow_flying); allow_flying);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// stopAutoPilot() // stopAutoPilot()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1830,7 +1796,6 @@ void LLAgent::stopAutoPilot(bool user_cancel)
} }
} }
// Returns necessary agent pitch and yaw changes, radians. // Returns necessary agent pitch and yaw changes, radians.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// autoPilot() // autoPilot()
@ -2019,7 +1984,6 @@ void LLAgent::autoPilot(F32 *delta_yaw)
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// propagate() // propagate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2040,18 +2004,19 @@ void LLAgent::propagate(const F32 dt)
} }
// handle rotation based on keyboard levels // handle rotation based on keyboard levels
constexpr F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second if (fabs(dt) > 1e-6)
F32 angle = YAW_RATE * gAgentCamera.getYawKey() * dt;
if (fabs(angle) > 0.0f)
{ {
yaw(angle); if (fabs(gAgentCamera.getYawKey()) > 1e-6)
} {
static const F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second
yaw(YAW_RATE * gAgentCamera.getYawKey() * dt);
}
constexpr F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second if (fabs(gAgentCamera.getPitchKey()) > 1e-6)
angle = PITCH_RATE * gAgentCamera.getPitchKey() * dt; {
if (fabs(angle) > 0.0f) static const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second
{ pitch(PITCH_RATE * gAgentCamera.getPitchKey() * dt);
pitch(angle); }
} }
// handle auto-land behavior // handle auto-land behavior
@ -2213,7 +2178,6 @@ void LLAgent::clearRenderState(U8 clearstate)
mRenderState &= ~clearstate; mRenderState &= ~clearstate;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// getRenderState() // getRenderState()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2255,6 +2219,7 @@ void LLAgent::endAnimationUpdateUI()
{ {
return; return;
} }
if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode()) if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode())
{ {
// We're already done endAnimationUpdateUI for this transition. // We're already done endAnimationUpdateUI for this transition.
@ -2320,7 +2285,6 @@ void LLAgent::endAnimationUpdateUI()
mViewsPushed = false; mViewsPushed = false;
} }
gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
if( gMorphView ) if( gMorphView )
{ {
@ -2952,7 +2916,6 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
} }
} }
void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity) void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity)
{ {
U8 maturity = SIM_ACCESS_MIN; U8 maturity = SIM_ACCESS_MIN;
@ -3022,7 +2985,6 @@ void LLAgent::changeInterestListMode(const std::string &new_mode)
} }
} }
bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure) bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure)
{ {
if (getRegion()) if (getRegion())
@ -3349,7 +3311,6 @@ void LLAgent::sendAnimationStateReset()
sendReliableMessage(); sendReliableMessage();
} }
// Send a message to the region to revoke sepecified permissions on ALL scripts in the region // Send a message to the region to revoke sepecified permissions on ALL scripts in the region
// If the target is an object in the region, permissions in scripts on that object are cleared. // If the target is an object in the region, permissions in scripts on that object are cleared.
// If it is the region ID, all scripts clear the permissions for this agent // If it is the region ID, all scripts clear the permissions for this agent
@ -4279,7 +4240,6 @@ void LLAgent::onCapabilitiesReceivedAfterTeleport()
check_merchant_status(); check_merchant_status();
} }
void LLAgent::teleportRequest( void LLAgent::teleportRequest(
const U64& region_handle, const U64& region_handle,
const LLVector3& pos_local, const LLVector3& pos_local,
@ -4393,7 +4353,6 @@ void LLAgent::doTeleportViaLure(const LLUUID& lure_id, bool godlike)
} }
} }
// James Cook, July 28, 2005 // James Cook, July 28, 2005
void LLAgent::teleportCancel() void LLAgent::teleportCancel()
{ {
@ -4518,7 +4477,6 @@ LLAgent::ETeleportState LLAgent::getTeleportState() const
TELEPORT_NONE : mTeleportState; TELEPORT_NONE : mTeleportState;
} }
void LLAgent::setTeleportState(ETeleportState state) void LLAgent::setTeleportState(ETeleportState state)
{ {
if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed)) if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed))
@ -4563,7 +4521,6 @@ void LLAgent::setTeleportState(ETeleportState state)
} }
} }
void LLAgent::stopCurrentAnimations() void LLAgent::stopCurrentAnimations()
{ {
LL_DEBUGS("Avatar") << "Stopping current animations" << LL_ENDL; LL_DEBUGS("Avatar") << "Stopping current animations" << LL_ENDL;
@ -4678,7 +4635,6 @@ void LLAgent::stopFidget()
gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP); gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP);
} }
void LLAgent::requestEnterGodMode() void LLAgent::requestEnterGodMode()
{ {
LLMessageSystem* msg = gMessageSystem; LLMessageSystem* msg = gMessageSystem;
@ -4799,7 +4755,6 @@ void LLAgent::sendAgentUpdateUserInfo(const std::string& directory_visibility)
} }
} }
void LLAgent::updateAgentUserInfoCoro(std::string capurl, std::string directory_visibility) void LLAgent::updateAgentUserInfoCoro(std::string capurl, std::string directory_visibility)
{ {
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);

View File

@ -1462,13 +1462,12 @@ void LLAgentCamera::updateCamera()
// LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL; // LL_INFOS() << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << LL_ENDL;
LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal); LLVector3 focus_agent = gAgent.getPosAgentFromGlobal(mFocusGlobal);
LLVector3 position_agent = gAgent.getPosAgentFromGlobal(camera_pos_global);
mCameraPositionAgent = gAgent.getPosAgentFromGlobal(camera_pos_global); // Try to move the camera
// Move the camera if (!LLViewerCamera::getInstance()->updateCameraLocation(position_agent, mCameraUpVector, focus_agent))
return;
LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent);
//LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent);
// Change FOV // Change FOV
LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor)); LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor));
@ -1476,7 +1475,7 @@ void LLAgentCamera::updateCamera()
// follow camera when in customize mode // follow camera when in customize mode
if (cameraCustomizeAvatar()) if (cameraCustomizeAvatar())
{ {
setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent); setLookAt(LOOKAT_TARGET_FOCUS, NULL, position_agent);
} }
// update the travel distance stat // update the travel distance stat
@ -1495,8 +1494,8 @@ void LLAgentCamera::updateCamera()
LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() + LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() +
LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() + LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() +
LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation(); LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation();
LLVector3 diff = mCameraPositionAgent - head_pos; LLVector3 diff = position_agent - head_pos;
diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation(); diff *= ~gAgentAvatarp->mRoot->getWorldRotation();
LLJoint* torso_joint = gAgentAvatarp->mTorsop; LLJoint* torso_joint = gAgentAvatarp->mTorsop;
LLJoint* chest_joint = gAgentAvatarp->mChestp; LLJoint* chest_joint = gAgentAvatarp->mChestp;
@ -2256,7 +2255,8 @@ void LLAgentCamera::changeCameraToFollow(bool animate)
mCameraMode = CAMERA_MODE_FOLLOW; mCameraMode = CAMERA_MODE_FOLLOW;
// bang-in the current focus, position, and up vector of the follow cam // bang-in the current focus, position, and up vector of the follow cam
mFollowCam.reset(mCameraPositionAgent, LLViewerCamera::getInstance()->getPointOfInterest(), LLVector3::z_axis); const LLViewerCamera& camera = LLViewerCamera::instance();
mFollowCam.reset(camera.getOrigin(), camera.getPointOfInterest(), LLVector3::z_axis);
if (gBasicToolset) if (gBasicToolset)
{ {

View File

@ -112,6 +112,7 @@ private:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
public: public:
void switchCameraPreset(ECameraPreset preset); void switchCameraPreset(ECameraPreset preset);
ECameraPreset getCameraPreset() const { return mCameraPreset; }
/** Determines default camera offset depending on the current camera preset */ /** Determines default camera offset depending on the current camera preset */
LLVector3 getCameraOffsetInitial(); LLVector3 getCameraOffsetInitial();
/** Determines default focus offset depending on the current camera preset */ /** Determines default focus offset depending on the current camera preset */
@ -138,13 +139,14 @@ private:
//-------------------------------------------------------------------- //--------------------------------------------------------------------
public: public:
LLVector3d getCameraPositionGlobal() const; LLVector3d getCameraPositionGlobal() const;
const LLVector3 &getCameraPositionAgent() const; const LLVector3& getCameraPositionAgent() const;
LLVector3d calcCameraPositionTargetGlobal(bool *hit_limit = NULL); // Calculate the camera position target LLVector3d calcCameraPositionTargetGlobal(bool *hit_limit = NULL); // Calculate the camera position target
F32 getCameraMinOffGround(); // Minimum height off ground for this mode, meters F32 getCameraMinOffGround(); // Minimum height off ground for this mode, meters
void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; } void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; }
bool calcCameraMinDistance(F32 &obj_min_distance); bool calcCameraMinDistance(F32 &obj_min_distance);
F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); } F32 getCurrentCameraBuildOffset() const { return (F32)mCameraFocusOffset.length(); }
void clearCameraLag() { mCameraLag.clearVec(); } void clearCameraLag() { mCameraLag.clearVec(); }
const LLVector3& getCameraUpVector() const { return mCameraUpVector; }
private: private:
LLVector3 getAvatarRootPosition(); LLVector3 getAvatarRootPosition();
@ -154,7 +156,6 @@ private:
F32 mCameraCurrentFOVZoomFactor; // Interpolated fov zoom F32 mCameraCurrentFOVZoomFactor; // Interpolated fov zoom
LLVector4 mCameraCollidePlane; // Colliding plane for camera LLVector4 mCameraCollidePlane; // Colliding plane for camera
F32 mCameraZoomFraction; // Mousewheel driven fraction of zoom F32 mCameraZoomFraction; // Mousewheel driven fraction of zoom
LLVector3 mCameraPositionAgent; // Camera position in agent coordinates
LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom LLVector3 mCameraVirtualPositionAgent; // Camera virtual position (target) before performing FOV zoom
LLVector3d mCameraSmoothingLastPositionGlobal; LLVector3d mCameraSmoothingLastPositionGlobal;
LLVector3d mCameraSmoothingLastPositionAgent; LLVector3d mCameraSmoothingLastPositionAgent;
@ -278,7 +279,7 @@ public:
F32 getAgentHUDTargetZoom(); F32 getAgentHUDTargetZoom();
void resetCameraZoomFraction(); void resetCameraZoomFraction();
F32 getCurrentCameraZoomFraction() { return mCameraZoomFraction; } F32 getCurrentCameraZoomFraction() const { return mCameraZoomFraction; }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Pan // Pan

View File

@ -322,9 +322,7 @@ void LLAgentPilot::moveCamera()
LLViewerCamera::getInstance()->setView(view); LLViewerCamera::getInstance()->setView(view);
LLViewerCamera::getInstance()->setOrigin(origin); LLViewerCamera::getInstance()->setOrigin(origin);
LLViewerCamera::getInstance()->mXAxis = LLVector3(mat.mMatrix[0]); LLViewerCamera::getInstance()->setAxes(mat);
LLViewerCamera::getInstance()->mYAxis = LLVector3(mat.mMatrix[1]);
LLViewerCamera::getInstance()->mZAxis = LLVector3(mat.mMatrix[2]);
} }
} }

View File

@ -839,7 +839,7 @@ void AISAPI::onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD&
if ( (type == UPDATECATEGORY || type == UPDATEITEM) if ( (type == UPDATECATEGORY || type == UPDATEITEM)
&& gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) && gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{ {
dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); dump_sequential_xml(gAgentAvatarp->getDebugName() + "_ais_update", update);
} }
AISUpdate ais_update(update, type, request_body); AISUpdate ais_update(update, type, request_body);

View File

@ -2045,7 +2045,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
} }
// Moved from LLWearableList::ContextMenu for wider utility. // Moved from LLWearableList::ContextMenu for wider utility.
bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) const bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids, bool warn_on_type_mismatch) const
{ {
// TODO: investigate wearables may not be loaded at this point EXT-8231 // TODO: investigate wearables may not be loaded at this point EXT-8231
@ -2075,7 +2075,10 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) const
} }
else else
{ {
if (warn_on_type_mismatch)
{
LL_WARNS() << "Unexpected wearable type" << LL_ENDL; LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
}
return false; return false;
} }
} }
@ -2266,7 +2269,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
} }
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{ {
dump_sequential_xml(gAgentAvatarp->getFullname() + "_slam_request", contents); dump_sequential_xml(gAgentAvatarp->getDebugName() + "_slam_request", contents);
} }
slam_inventory_folder(getCOF(), contents, link_waiter); slam_inventory_folder(getCOF(), contents, link_waiter);
@ -3959,7 +3962,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL; LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{ {
dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result); dump_sequential_xml(gAgentAvatarp->getDebugName() + "_appearance_request_ok", result);
} }
} while (bRetry); } while (bRetry);
@ -3968,7 +3971,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
/*static*/ /*static*/
void LLAppearanceMgr::debugAppearanceUpdateCOF(const LLSD& content) void LLAppearanceMgr::debugAppearanceUpdateCOF(const LLSD& content)
{ {
dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_error", content); dump_sequential_xml(gAgentAvatarp->getDebugName() + "_appearance_request_error", content);
LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger() LL_INFOS("Avatar") << "AIS COF, version received: " << content["expected"].asInteger()
<< " ================================= " << LL_ENDL; << " ================================= " << LL_ENDL;

View File

@ -103,7 +103,7 @@ public:
bool getCanReplaceCOF(const LLUUID& outfit_cat_id); bool getCanReplaceCOF(const LLUUID& outfit_cat_id);
// Can we add all referenced items to the avatar? // Can we add all referenced items to the avatar?
bool canAddWearables(const uuid_vec_t& item_ids) const; bool canAddWearables(const uuid_vec_t& item_ids, bool warn_on_type_mismatch = true) const;
// Copy all items in a category. // Copy all items in a category.
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,

View File

@ -453,13 +453,28 @@ static bool app_metrics_qa_mode = false;
void idle_afk_check() void idle_afk_check()
{ {
// Don't check AFK status during startup states
if (LLStartUp::getStartupState() < STATE_STARTED)
{
return;
}
// check idle timers // check idle timers
F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32(); F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300); static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300);
if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK()) if (afk_timeout() && (current_idle > afk_timeout()))
{ {
LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL; if (!gAgent.getAFK())
gAgent.setAFK(); {
LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
gAgent.setAFK();
}
else
{
// Refresh timer so that random one click or hover won't clear the status.
// But expanding the window still should lift afk status
gAwayTimer.reset();
}
} }
} }
@ -1852,36 +1867,6 @@ bool LLAppViewer::cleanup()
// Clean up before GL is shut down because we might be holding on to objects with texture references // Clean up before GL is shut down because we might be holding on to objects with texture references
LLSelectMgr::cleanupGlobals(); LLSelectMgr::cleanupGlobals();
LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
// Shut down OpenGL
if( gViewerWindow)
{
gViewerWindow->shutdownGL();
// Destroy window, and make sure we're not fullscreen
// This may generate window reshape and activation events.
// Therefore must do this before destroying the message system.
delete gViewerWindow;
gViewerWindow = NULL;
LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
}
LLSplashScreen::show();
LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
delete gKeyboard;
gKeyboard = NULL;
if (LLViewerJoystick::instanceExists())
{
// Turn off Space Navigator and similar devices
LLViewerJoystick::getInstance()->terminate();
}
LL_INFOS() << "Cleaning up Objects" << LL_ENDL; LL_INFOS() << "Cleaning up Objects" << LL_ENDL;
LLViewerObject::cleanupVOClasses(); LLViewerObject::cleanupVOClasses();
@ -2042,6 +2027,36 @@ bool LLAppViewer::cleanup()
sTextureFetch->shutDownTextureCacheThread() ; sTextureFetch->shutDownTextureCacheThread() ;
LLLFSThread::sLocal->shutdown(); LLLFSThread::sLocal->shutdown();
LL_INFOS() << "Shutting down OpenGL" << LL_ENDL;
// Shut down OpenGL
if (gViewerWindow)
{
gViewerWindow->shutdownGL();
// Destroy window, and make sure we're not fullscreen
// This may generate window reshape and activation events.
// Therefore must do this before destroying the message system.
delete gViewerWindow;
gViewerWindow = NULL;
LL_INFOS() << "ViewerWindow deleted" << LL_ENDL;
}
LLSplashScreen::show();
LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
LL_INFOS() << "Cleaning up Keyboard & Joystick" << LL_ENDL;
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
delete gKeyboard;
gKeyboard = NULL;
if (LLViewerJoystick::instanceExists())
{
// Turn off Space Navigator and similar devices
LLViewerJoystick::getInstance()->terminate();
}
LL_INFOS() << "Shutting down message system" << LL_ENDL; LL_INFOS() << "Shutting down message system" << LL_ENDL;
end_messaging_system(); end_messaging_system();

View File

@ -536,11 +536,12 @@ LLAutoReplaceSettings::AddListResult LLAutoReplaceSettings::replaceList(const LL
S32 search_index; S32 search_index;
LLSD targetList; LLSD targetList;
// The following is working around the fact that LLSD arrays containing maps also seem to have undefined entries... see LLSD-30 // The following is working around the fact that LLSD arrays containing maps also seem to have undefined entries... see LLSD-30
for ( search_index = 0, targetList = mLists[0]; for ( search_index = 0;
!listFound && search_index < mLists.size(); !listFound && search_index < mLists.size();
search_index += 1, targetList = mLists[search_index] search_index += 1
) )
{ {
targetList = mLists[search_index];
if ( targetList.isMap() ) if ( targetList.isMap() )
{ {
if ( listNameMatches( targetList, listName) ) if ( listNameMatches( targetList, listName) )

View File

@ -952,7 +952,7 @@ protected:
menu->setItemEnabled("Voice Call", false); menu->setItemEnabled("Voice Call", false);
menu->setItemEnabled("Chat History", false); menu->setItemEnabled("Chat History", false);
menu->setItemEnabled("Invite Group", false); menu->setItemEnabled("Invite Group", false);
menu->setItemEnabled("Zoom In", false); menu->setItemEnabled("Zoom In", true);
menu->setItemEnabled("Share", false); menu->setItemEnabled("Share", false);
menu->setItemEnabled("Pay", false); menu->setItemEnabled("Pay", false);
menu->setItemEnabled("Block Unblock", false); menu->setItemEnabled("Block Unblock", false);

View File

@ -129,14 +129,14 @@ void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_
{ {
LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents); LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents);
F32 offset_dist = pos_box_offset.length(); F32 offset_dist = pos_box_offset.length();
if (offset_dist > MAX_LEGAL_OFFSET && offset_dist > 0.f) if (offset_dist > max_legal_offset && offset_dist > 0.f)
{ {
F32 target_dist = (offset_dist - MAX_LEGAL_OFFSET); F32 target_dist = (offset_dist - max_legal_offset);
new_pos_fixup = (target_dist/offset_dist)*pos_box_offset; new_pos_fixup = (target_dist/offset_dist)*pos_box_offset;
} }
if (new_pos_fixup != mPositionConstraintFixup) if (new_pos_fixup != mPositionConstraintFixup)
{ {
LL_DEBUGS("ConstraintFix") << getFullname() << " pos fix, offset_dist " << offset_dist << " pos fixup " LL_DEBUGS("ConstraintFix") << getDebugName() << " pos fix, offset_dist " << offset_dist << " pos fixup "
<< new_pos_fixup << " was " << mPositionConstraintFixup << LL_ENDL; << new_pos_fixup << " was " << mPositionConstraintFixup << LL_ENDL;
LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << LL_ENDL; LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << LL_ENDL;
LL_DEBUGS("ConstraintFix") << "extents " << extents[0] << " " << extents[1] << LL_ENDL; LL_DEBUGS("ConstraintFix") << "extents " << extents[0] << " " << extents[1] << LL_ENDL;
@ -144,11 +144,11 @@ void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_
} }
} }
if (box_size/mScaleConstraintFixup > MAX_LEGAL_SIZE) if (box_size/mScaleConstraintFixup > max_legal_size)
{ {
new_scale_fixup = mScaleConstraintFixup* MAX_LEGAL_SIZE /box_size; new_scale_fixup = mScaleConstraintFixup*max_legal_size/box_size;
LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup " LL_DEBUGS("ConstraintFix") << getDebugName() << " scale fix, box_size " << box_size << " fixup "
<< mScaleConstraintFixup << " max legal " << MAX_LEGAL_SIZE << mScaleConstraintFixup << " max legal " << max_legal_size
<< " -> new scale " << new_scale_fixup << LL_ENDL; << " -> new scale " << new_scale_fixup << LL_ENDL;
} }
} }
@ -231,7 +231,7 @@ void LLControlAvatar::matchVolumeTransform()
const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo(); const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo();
if (skin_info) if (skin_info)
{ {
LL_DEBUGS("BindShape") << getFullname() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL; LL_DEBUGS("BindShape") << getDebugName() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL;
bind_rot = LLSkinningUtil::getUnscaledQuaternion(LLMatrix4(skin_info->mBindShapeMatrix)); bind_rot = LLSkinningUtil::getUnscaledQuaternion(LLMatrix4(skin_info->mBindShapeMatrix));
} }
#endif #endif

View File

@ -663,7 +663,7 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD&
{ {
mConversations.clear(); mConversations.clear();
notifyObservers(); notifyObservers();
cache(); saveToFile(getFileName());
deleteBackupLogs(); deleteBackupLogs();
} }
} }

View File

@ -300,7 +300,7 @@ void LLConversationItemSession::updateName(LLConversationItemParticipant* partic
for (auto itemp : mChildren) for (auto itemp : mChildren)
{ {
LLConversationItem* current_participant = dynamic_cast<LLConversationItem*>(itemp); LLConversationItem* current_participant = dynamic_cast<LLConversationItem*>(itemp.get());
// Add the avatar uuid to the list (except if it's the own agent uuid) // Add the avatar uuid to the list (except if it's the own agent uuid)
if (current_participant->getUUID() != gAgentID) if (current_participant->getUUID() != gAgentID)
{ {
@ -329,6 +329,7 @@ void LLConversationItemSession::updateName(LLConversationItemParticipant* partic
void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant) void LLConversationItemSession::removeParticipant(LLConversationItemParticipant* participant)
{ {
LLPointer<LLFolderViewModelItem> holder(participant);
removeChild(participant); removeChild(participant);
mNeedsRefresh = true; mNeedsRefresh = true;
updateName(participant); updateName(participant);
@ -360,15 +361,10 @@ void LLConversationItemSession::clearAndDeparentModels()
for (child_list_t::iterator it = mChildren.begin(); it != mChildren.end();) for (child_list_t::iterator it = mChildren.begin(); it != mChildren.end();)
{ {
LLFolderViewModelItem* child = *it; LLFolderViewModelItem* child = *it;
if (child->getNumRefs() == 0) // Note that model might still be assigned to some view/widget
// and have a different parent
if (child->getParent() == this)
{ {
// LLConversationItemParticipant can be created but not assigned to any view,
// it was waiting for an "add_participant" event to be processed
delete child;
}
else
{
// Model is still assigned to some view/widget
child->setParent(NULL); child->setParent(NULL);
} }
it = mChildren.erase(it); it = mChildren.erase(it);
@ -383,7 +379,7 @@ LLConversationItemParticipant* LLConversationItemSession::findParticipant(const
child_list_t::iterator iter; child_list_t::iterator iter;
for (iter = mChildren.begin(); iter != mChildren.end(); iter++) for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
{ {
participant = dynamic_cast<LLConversationItemParticipant*>(*iter); participant = dynamic_cast<LLConversationItemParticipant*>((*iter).get());
if (participant && participant->hasSameValue(participant_id)) if (participant && participant->hasSameValue(participant_id))
{ {
break; break;
@ -493,7 +489,7 @@ const bool LLConversationItemSession::getTime(F64& time) const
child_list_t::const_iterator iter; child_list_t::const_iterator iter;
for (iter = mChildren.begin(); iter != mChildren.end(); iter++) for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
{ {
participant = dynamic_cast<LLConversationItemParticipant*>(*iter); participant = dynamic_cast<LLConversationItemParticipant*>((*iter).get());
F64 participant_time; F64 participant_time;
if (participant && participant->getTime(participant_time)) if (participant && participant->getTime(participant_time))
{ {
@ -517,7 +513,7 @@ void LLConversationItemSession::dumpDebugData(bool dump_children)
{ {
for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); iter++) for (child_list_t::iterator iter = mChildren.begin(); iter != mChildren.end(); iter++)
{ {
LLConversationItemParticipant* participant = dynamic_cast<LLConversationItemParticipant*>(*iter); LLConversationItemParticipant* participant = dynamic_cast<LLConversationItemParticipant*>((*iter).get());
if (participant) if (participant)
{ {
participant->dumpDebugData(); participant->dumpDebugData();

View File

@ -79,6 +79,9 @@ public:
virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); }
virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }
virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
virtual bool isFavorite() const { return false; }
virtual bool isAgentInventory() const { return false; }
virtual bool isAgentInventoryRoot() const { return false; }
virtual bool isItemRenameable() const { return true; } virtual bool isItemRenameable() const { return true; }
virtual bool renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return true; } virtual bool renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return true; }
virtual bool isItemMovable( void ) const { return false; } virtual bool isItemMovable( void ) const { return false; }

View File

@ -422,7 +422,13 @@ bool LLFloaterAutoReplaceSettings::callbackNewListName(const LLSD& notification,
LLSD newList = notification["payload"]["list"]; LLSD newList = notification["payload"]["list"];
if ( response.has("listname") && response["listname"].isString() ) S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option != 1) // Must also match RenameAutoReplaceList
{
// user cancelled
return false;
}
else if (response.has("listname") && response["listname"].isString() )
{ {
std::string newName = response["listname"].asString(); std::string newName = response["listname"].asString();
LLAutoReplaceSettings::setListName(newList, newName); LLAutoReplaceSettings::setListName(newList, newName);
@ -508,12 +514,53 @@ bool LLFloaterAutoReplaceSettings::callbackListNameConflict(const LLSD& notifica
return false; return false;
} }
bool LLFloaterAutoReplaceSettings::callbackRemoveList(const LLSD& notification, const LLSD& response)
{
std::string listName = notification["payload"]["list"];
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
switch (option)
{
case 1:
if (mSettings.removeReplacementList(listName))
{
LL_INFOS("AutoReplace") << "deleted list '" << listName << "'" << LL_ENDL;
mReplacementsList->deleteSelectedItems(); // remove from the scrolling list
mSelectedListName.clear();
updateListNames();
updateListNamesControls();
updateReplacementsList();
}
break;
case 0:
break;
default:
LL_ERRS("AutoReplace") << "invalid selected option " << option << LL_ENDL;
}
return false;
}
void LLFloaterAutoReplaceSettings::onDeleteList() void LLFloaterAutoReplaceSettings::onDeleteList()
{ {
std::string listName = mListNames->getSelectedValue().asString(); std::string listName = mListNames->getSelectedValue().asString();
if ( ! listName.empty() ) if ( ! listName.empty() )
{ {
if ( mSettings.removeReplacementList(listName) ) const LLSD* mappings = mSettings.getListEntries(mSelectedListName);
if (mappings->size() > 0)
{
LLSD payload;
payload["list"] = listName;
LLSD args;
args["MAP_SIZE"] = llformat("%d",mappings->size());
args["LIST_NAME"] = listName;
LLNotificationsUtil::add("RemoveAutoReplaceList", args, payload,
boost::bind(&LLFloaterAutoReplaceSettings::callbackRemoveList, this, _1, _2));
}
else if ( mSettings.removeReplacementList(listName) )
{ {
LL_INFOS("AutoReplace")<<"deleted list '"<<listName<<"'"<<LL_ENDL; LL_INFOS("AutoReplace")<<"deleted list '"<<listName<<"'"<<LL_ENDL;
mReplacementsList->deleteSelectedItems(); // remove from the scrolling list mReplacementsList->deleteSelectedItems(); // remove from the scrolling list

View File

@ -105,6 +105,8 @@ private:
bool callbackNewListName(const LLSD& notification, const LLSD& response); bool callbackNewListName(const LLSD& notification, const LLSD& response);
/// called from the RenameAutoReplaceList notification dialog /// called from the RenameAutoReplaceList notification dialog
bool callbackListNameConflict(const LLSD& notification, const LLSD& response); bool callbackListNameConflict(const LLSD& notification, const LLSD& response);
/// called from the RemoveAutoReplaceList notification dialog
bool callbackRemoveList(const LLSD& notification, const LLSD& response);
bool selectedListIsFirst(); bool selectedListIsFirst();
bool selectedListIsLast(); bool selectedListIsLast();

View File

@ -118,8 +118,8 @@ std::string STATUS[] =
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// LLFloaterBvhPreview() // LLFloaterBvhPreview()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename) : LLFloaterBvhPreview::LLFloaterBvhPreview(const LLSD& args) :
LLFloaterNameDesc(filename) LLFloaterNameDesc(args)
{ {
mLastMouseX = 0; mLastMouseX = 0;
mLastMouseY = 0; mLastMouseY = 0;
@ -1028,7 +1028,8 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata)
LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getNextOwnerPerms("Uploads"),
LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost)); expected_upload_cost,
floaterp->mDestinationFolderId));
upload_new_resource(assetUploadInfo); upload_new_resource(assetUploadInfo);
} }

View File

@ -70,7 +70,7 @@ protected:
class LLFloaterBvhPreview : public LLFloaterNameDesc class LLFloaterBvhPreview : public LLFloaterNameDesc
{ {
public: public:
LLFloaterBvhPreview(const std::string& filename); LLFloaterBvhPreview(const LLSD& args);
virtual ~LLFloaterBvhPreview(); virtual ~LLFloaterBvhPreview();
bool postBuild(); bool postBuild();

View File

@ -88,7 +88,7 @@ uuid_vec_t LLFloaterChatMentionPicker::getParticipantIds()
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd();
while (current_participant_model != end_participant_model) while (current_participant_model != end_participant_model)
{ {
LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>((*current_participant_model).get());
if (participant_model) if (participant_model)
{ {
avatar_ids.push_back(participant_model->getUUID()); avatar_ids.push_back(participant_model->getUUID());

View File

@ -133,7 +133,8 @@ protected:
LLSettingsEditPanel() : LLSettingsEditPanel() :
LLPanel(), LLPanel(),
mIsDirty(false), mIsDirty(false),
mOnDirtyChanged() mOnDirtyChanged(),
mCanEdit(false)
{} {}
private: private:

View File

@ -78,8 +78,8 @@ const S32 PREVIEW_TEXTURE_HEIGHT = 320;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// LLFloaterImagePreview() // LLFloaterImagePreview()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) : LLFloaterImagePreview::LLFloaterImagePreview(const LLSD& args) :
LLFloaterNameDesc(filename), LLFloaterNameDesc(args),
mAvatarPreview(NULL), mAvatarPreview(NULL),
mSculptedPreview(NULL), mSculptedPreview(NULL),
@ -288,7 +288,9 @@ void LLFloaterImagePreview::onBtnOK()
} }
else else
{ {
LLNotificationsUtil::add("ErrorEncodingImage"); LLSD args;
args["REASON"] = LLImage::getLastThreadError();
LLNotificationsUtil::add("ErrorEncodingImage", args);
LL_WARNS() << "Error encoding image" << LL_ENDL; LL_WARNS() << "Error encoding image" << LL_ENDL;
} }
} }
@ -423,6 +425,18 @@ bool LLFloaterImagePreview::loadImage(const std::string& src_filename)
return false; return false;
} }
// raw image is limited to 256MB so need at least some upper limit that fits into that
constexpr S32 MAX_IMAGE_AREA = 8096 * 8096;
if (image_info.getWidth() * image_info.getHeight() > MAX_IMAGE_AREA)
{
LLStringUtil::format_map_t args;
args["PIXELS"] = llformat("%dM", (S32)(MAX_IMAGE_AREA / 1000000));
mImageLoadError = LLTrans::getString("texture_load_dimensions_error", args);
return false;
}
// Load the image // Load the image
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec);
if (image.isNull()) if (image.isNull())

View File

@ -110,7 +110,7 @@ protected:
class LLFloaterImagePreview : public LLFloaterNameDesc class LLFloaterImagePreview : public LLFloaterNameDesc
{ {
public: public:
LLFloaterImagePreview(const std::string& filename); LLFloaterImagePreview(const LLSD& args);
virtual ~LLFloaterImagePreview(); virtual ~LLFloaterImagePreview();
bool postBuild() override; bool postBuild() override;

View File

@ -460,7 +460,7 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate()
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = session_model->getChildrenEnd();
while (current_participant_model != end_participant_model) while (current_participant_model != end_participant_model)
{ {
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get());
if (participant_model) if (participant_model)
{ {
// Get the avatar name for this participant id from the cache and update the model // Get the avatar name for this participant id from the cache and update the model
@ -511,7 +511,7 @@ void LLFloaterIMContainer::idleUpdate()
bool can_ban = haveAbilityToBan(); bool can_ban = haveAbilityToBan();
while (current_participant_model != end_participant_model) while (current_participant_model != end_participant_model)
{ {
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get());
if (participant_model) if (participant_model)
{ {
participant_model->setModeratorOptionsVisible(is_moderator); participant_model->setModeratorOptionsVisible(is_moderator);
@ -1540,6 +1540,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v
// Beyond that point, if only the user agent is selected, everything is disabled // Beyond that point, if only the user agent is selected, everything is disabled
if (is_single_select && (single_id == gAgentID)) if (is_single_select && (single_id == gAgentID))
{ {
if ("can_zoom_in" == item)
{
return true;
}
if (is_moderator_option) if (is_moderator_option)
{ {
return enableModerateContextMenuItem(item, true); return enableModerateContextMenuItem(item, true);
@ -1874,7 +1878,7 @@ LLConversationItem* LLFloaterIMContainer::addConversationListItem(const LLUUID&
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd();
while (current_participant_model != end_participant_model) while (current_participant_model != end_participant_model)
{ {
LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>((*current_participant_model).get());
LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model); LLConversationViewParticipant* participant_view = createConversationViewParticipant(participant_model);
participant_view->addToFolder(widget); participant_view->addToFolder(widget);
current_participant_model++; current_participant_model++;

View File

@ -107,26 +107,6 @@ LLFloaterIMSessionTab::~LLFloaterIMSessionTab()
delete mRefreshTimer; delete mRefreshTimer;
LLIMMgr::instance().removeSessionObserver(this); LLIMMgr::instance().removeSessionObserver(this);
mEmojiCloseConn.disconnect(); mEmojiCloseConn.disconnect();
LLFloaterIMContainer* im_container = LLFloaterIMContainer::findInstance();
if (im_container)
{
LLParticipantList* session = dynamic_cast<LLParticipantList*>(im_container->getSessionModel(mSessionID));
if (session)
{
for (const conversations_widgets_map::value_type& widget_pair : mConversationsWidgets)
{
LLFolderViewItem* widget = widget_pair.second;
LLFolderViewModelItem* item_vmi = widget->getViewModelItem();
if (item_vmi && item_vmi->getNumRefs() == 1)
{
// This is the last pointer, remove participant from session
// before participant gets deleted on destroyView.
session->removeChild(item_vmi);
}
}
}
}
} }
// static // static
@ -730,7 +710,7 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd(); LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = item->getChildrenEnd();
while (current_participant_model != end_participant_model) while (current_participant_model != end_participant_model)
{ {
LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model); LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>((*current_participant_model).get());
if (participant_model) if (participant_model)
{ {
addConversationViewParticipant(participant_model); addConversationViewParticipant(participant_model);
@ -774,27 +754,6 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id); LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,participant_id);
if (widget) if (widget)
{ {
LLFolderViewModelItem* item_vmi = widget->getViewModelItem();
if (item_vmi && item_vmi->getNumRefs() == 1)
{
// This is the last pointer, remove participant from session
// before participant gets deleted on destroyView.
//
// Floater (widget) and participant's view can simultaneously
// co-own the model, in which case view is responsible for
// the deletion and floater is free to clear and recreate
// the list, yet there are cases where only widget owns
// the pointer so it should do the cleanup.
// See "add_participant".
//
// Todo: If it keeps causing issues turn participants
// into LLPointers in the session
LLParticipantList* session = getParticipantList();
if (session)
{
session->removeChild(item_vmi);
}
}
widget->destroyView(); widget->destroyView();
} }
mConversationsWidgets.erase(participant_id); mConversationsWidgets.erase(participant_id);
@ -860,7 +819,7 @@ void LLFloaterIMSessionTab::refreshConversation()
LLIMSpeakerMgr *speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); LLIMSpeakerMgr *speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID);
while (current_participant_model != end_participant_model) while (current_participant_model != end_participant_model)
{ {
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model); LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>((*current_participant_model).get());
if (speaker_mgr && participant_model) if (speaker_mgr && participant_model)
{ {
LLSpeaker *participant_speaker = speaker_mgr->findSpeaker(participant_model->getUUID()); LLSpeaker *participant_speaker = speaker_mgr->findSpeaker(participant_model->getUUID());

View File

@ -28,9 +28,14 @@
#include "llfloaterinventorysettings.h" #include "llfloaterinventorysettings.h"
#include "llcolorswatch.h"
#include "llviewercontrol.h"
LLFloaterInventorySettings::LLFloaterInventorySettings(const LLSD& key) LLFloaterInventorySettings::LLFloaterInventorySettings(const LLSD& key)
: LLFloater(key) : LLFloater(key)
{ {
mCommitCallbackRegistrar.add("ScriptPref.applyUIColor", boost::bind(&LLFloaterInventorySettings::applyUIColor, this, _1, _2));
mCommitCallbackRegistrar.add("ScriptPref.getUIColor", boost::bind(&LLFloaterInventorySettings::getUIColor, this, _1, _2));
} }
LLFloaterInventorySettings::~LLFloaterInventorySettings() LLFloaterInventorySettings::~LLFloaterInventorySettings()
@ -39,6 +44,29 @@ LLFloaterInventorySettings::~LLFloaterInventorySettings()
bool LLFloaterInventorySettings::postBuild() bool LLFloaterInventorySettings::postBuild()
{ {
getChild<LLButton>("ok_btn")->setCommitCallback(boost::bind(&LLFloater::closeFloater, this, false)); getChild<LLButton>("ok_btn")->setCommitCallback(boost::bind(&LLFloater::closeFloater, this, false));
getChild<LLUICtrl>("favorites_color")->setCommitCallback(boost::bind(&LLFloaterInventorySettings::updateColorSwatch, this));
bool enable_color = gSavedSettings.getBOOL("InventoryFavoritesColorText");
getChild<LLUICtrl>("favorites_swatch")->setEnabled(enable_color);
return true; return true;
} }
void LLFloaterInventorySettings::updateColorSwatch()
{
bool val = getChild<LLUICtrl>("favorites_color")->getValue();
getChild<LLUICtrl>("favorites_swatch")->setEnabled(val);
}
void LLFloaterInventorySettings::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
{
LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue()));
}
void LLFloaterInventorySettings::getUIColor(LLUICtrl* ctrl, const LLSD& param)
{
LLColorSwatchCtrl* color_swatch = (LLColorSwatchCtrl*)ctrl;
color_swatch->setOriginal(LLUIColorTable::instance().getColor(param.asString()));
}

View File

@ -40,6 +40,11 @@ public:
private: private:
LLFloaterInventorySettings(const LLSD& key); LLFloaterInventorySettings(const LLSD& key);
~LLFloaterInventorySettings(); ~LLFloaterInventorySettings();
void updateColorSwatch();
void applyUIColor(LLUICtrl* ctrl, const LLSD& param);
void getUIColor(LLUICtrl* ctrl, const LLSD& param);
}; };
#endif #endif

View File

@ -165,7 +165,7 @@ bool LLFloaterModelPreview::postBuild()
for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod)
{ {
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]); LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
lod_source_combo->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLoDSourceCommit, this, lod, true)); lod_source_combo->setCommitCallback(boost::bind(&LLFloaterModelPreview::onLoDSourceCommit, this, lod));
lod_source_combo->setCurrentByIndex(mLODMode[lod]); lod_source_combo->setCurrentByIndex(mLODMode[lod]);
getChild<LLButton>("lod_browse_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onBrowseLOD, this, lod)); getChild<LLButton>("lod_browse_" + lod_name[lod])->setCommitCallback(boost::bind(&LLFloaterModelPreview::onBrowseLOD, this, lod));
@ -350,14 +350,14 @@ void LLFloaterModelPreview::initModelPreview()
} }
//static //static
bool LLFloaterModelPreview::showModelPreview() void LLFloaterModelPreview::showModelPreview(const LLUUID& dest_folder)
{ {
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)LLFloaterReg::getInstance("upload_model"); LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)LLFloaterReg::getInstance("upload_model");
if (fmp && !fmp->isModelLoading()) if (fmp && !fmp->isModelLoading())
{ {
fmp->setUploadDestination(dest_folder);
fmp->loadHighLodModel(); fmp->loadHighLodModel();
} }
return true;
} }
void LLFloaterModelPreview::onUploadOptionChecked(LLUICtrl* ctrl) void LLFloaterModelPreview::onUploadOptionChecked(LLUICtrl* ctrl)
@ -506,7 +506,7 @@ void LLFloaterModelPreview::onClickCalculateBtn()
gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale,
childGetValue("upload_textures").asBoolean(), childGetValue("upload_textures").asBoolean(),
upload_skinweights, upload_joint_positions, lock_scale_if_joint_position, upload_skinweights, upload_joint_positions, lock_scale_if_joint_position,
mUploadModelUrl, false, mUploadModelUrl, mDestinationFolderId, false,
getWholeModelFeeObserverHandle()); getWholeModelFeeObserverHandle());
toggleCalculateButton(false); toggleCalculateButton(false);
@ -766,7 +766,7 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[i]); LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[i]);
if (lod_source_combo->getCurrentIndex() == LLModelPreview::USE_LOD_ABOVE) if (lod_source_combo->getCurrentIndex() == LLModelPreview::USE_LOD_ABOVE)
{ {
onLoDSourceCommit(i, false); onLoDSourceCommit(i);
} }
else else
{ {
@ -1659,7 +1659,7 @@ void LLFloaterModelPreview::onUpload(void* user_data)
gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale, gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale,
mp->childGetValue("upload_textures").asBoolean(), mp->childGetValue("upload_textures").asBoolean(),
upload_skinweights, upload_joint_positions, lock_scale_if_joint_position, upload_skinweights, upload_joint_positions, lock_scale_if_joint_position,
mp->mUploadModelUrl, mp->mUploadModelUrl, mp->mDestinationFolderId,
true, LLHandle<LLWholeModelFeeObserver>(), mp->getWholeModelUploadObserverHandle()); true, LLHandle<LLWholeModelFeeObserver>(), mp->getWholeModelUploadObserverHandle());
} }
@ -1760,7 +1760,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
} }
} }
void LLFloaterModelPreview::onLoDSourceCommit(S32 lod, bool refresh_ui) void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
{ {
mModelPreview->updateLodControls(lod); mModelPreview->updateLodControls(lod);
@ -1773,12 +1773,10 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod, bool refresh_ui)
// rebuild LoD to update triangle counts // rebuild LoD to update triangle counts
onLODParamCommit(lod, true); onLODParamCommit(lod, true);
} }
else if (refresh_ui && index == LLModelPreview::USE_LOD_ABOVE) if (index == LLModelPreview::USE_LOD_ABOVE)
{ {
// Update mUploadData for updateStatusMessages // refresh to pick triangle counts
mModelPreview->rebuildUploadData(); mModelPreview->mDirty = true;
// Update UI with new triangle values
mModelPreview->updateStatusMessages();
} }
} }

View File

@ -73,7 +73,8 @@ public:
/*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true); /*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true);
void initModelPreview(); void initModelPreview();
static bool showModelPreview(); void setUploadDestination(const LLUUID& dest_folder) { mDestinationFolderId = dest_folder; }
static void showModelPreview(const LLUUID& dest_folder = LLUUID::null);
bool handleMouseDown(S32 x, S32 y, MASK mask); bool handleMouseDown(S32 x, S32 y, MASK mask);
bool handleMouseUp(S32 x, S32 y, MASK mask); bool handleMouseUp(S32 x, S32 y, MASK mask);
@ -164,9 +165,6 @@ protected:
static void onPhysicsBrowse(LLUICtrl* ctrl, void* userdata); static void onPhysicsBrowse(LLUICtrl* ctrl, void* userdata);
static void onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata); static void onPhysicsUseLOD(LLUICtrl* ctrl, void* userdata);
static void onPhysicsOptimize(LLUICtrl* ctrl, void* userdata);
static void onPhysicsDecomposeBack(LLUICtrl* ctrl, void* userdata);
static void onPhysicsSimplifyBack(LLUICtrl* ctrl, void* userdata);
void draw(); void draw();
@ -208,7 +206,7 @@ private:
void onClickCalculateBtn(); void onClickCalculateBtn();
void onJointListSelection(); void onJointListSelection();
void onLoDSourceCommit(S32 lod, bool refresh_ui); void onLoDSourceCommit(S32 lod);
void modelUpdated(bool calculate_visible); void modelUpdated(bool calculate_visible);
@ -225,6 +223,7 @@ private:
void createSmoothComboBox(LLComboBox* combo_box, float min, float max); void createSmoothComboBox(LLComboBox* combo_box, float min, float max);
LLUUID mDestinationFolderId;
LLButton* mUploadBtn; LLButton* mUploadBtn;
LLButton* mCalculateBtn; LLButton* mCalculateBtn;
LLViewerTextEditor* mUploadLogText; LLViewerTextEditor* mUploadLogText;

View File

@ -38,7 +38,9 @@
#include "llcheckboxctrl.h" #include "llcheckboxctrl.h"
#include "llviewerinventory.h" #include "llviewerinventory.h"
#include "llenvironment.h" #include "llenvironment.h"
#include "llnotificationsutil.h"
#include "llparcel.h" #include "llparcel.h"
#include "lltrans.h"
#include "llviewerparcelmgr.h" #include "llviewerparcelmgr.h"
//========================================================================= //=========================================================================
@ -223,16 +225,13 @@ void LLFloaterMyEnvironment::onFilterEdit(const std::string& search_string)
mInventoryList->setFilterSubString(search_string); mInventoryList->setFilterSubString(search_string);
} }
void LLFloaterMyEnvironment::onDeleteSelected() void LLFloaterMyEnvironment::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, uuid_vec_t item_ids)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{ {
uuid_vec_t selected;
getSelectedIds(selected);
if (selected.empty())
return;
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
for (const LLUUID& itemid: selected) for (const LLUUID& itemid : item_ids)
{ {
LLInventoryItem* inv_item = gInventory.getItem(itemid); LLInventoryItem* inv_item = gInventory.getItem(itemid);
@ -253,6 +252,27 @@ void LLFloaterMyEnvironment::onDeleteSelected()
} }
gInventory.notifyObservers(); gInventory.notifyObservers();
} }
}
void LLFloaterMyEnvironment::onDeleteSelected()
{
uuid_vec_t selected;
getSelectedIds(selected);
if (selected.empty())
return;
LLSD args;
args["QUESTION"] = LLTrans::getString(selected.size() > 1 ? "DeleteItems" : "DeleteItem");
LLNotificationsUtil::add(
"DeleteItems",
args,
LLSD(),
[this, selected](const LLSD& notification, const LLSD& response)
{
onItemsRemovalConfirmation(notification, response, selected);
});
}
void LLFloaterMyEnvironment::onDoCreate(const LLSD &data) void LLFloaterMyEnvironment::onDoCreate(const LLSD &data)
@ -318,13 +338,13 @@ bool LLFloaterMyEnvironment::canAction(const std::string &context)
if (context == PARAMETER_EDIT) if (context == PARAMETER_EDIT)
{ {
return (selected.size() == 1) && isSettingSelected(selected.front()); return (selected.size() == 1) && isSettingId(selected.front());
} }
else if (context == PARAMETER_COPY) else if (context == PARAMETER_COPY)
{ {
for (std::vector<LLUUID>::iterator it = selected.begin(); it != selected.end(); it++) for (std::vector<LLUUID>::iterator it = selected.begin(); it != selected.end(); it++)
{ {
if(!isSettingSelected(*it)) if(!isSettingId(*it))
{ {
return false; return false;
} }
@ -342,7 +362,7 @@ bool LLFloaterMyEnvironment::canAction(const std::string &context)
LLClipboard::instance().pasteFromClipboard(ids); LLClipboard::instance().pasteFromClipboard(ids);
for (std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++) for (std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
{ {
if (!isSettingSelected(*it)) if (!isSettingId(*it))
{ {
return false; return false;
} }
@ -351,7 +371,7 @@ bool LLFloaterMyEnvironment::canAction(const std::string &context)
} }
else if (context == PARAMETER_COPYUUID) else if (context == PARAMETER_COPYUUID)
{ {
return (selected.size() == 1) && isSettingSelected(selected.front()); return (selected.size() == 1) && isSettingId(selected.front());
} }
return false; return false;
@ -367,16 +387,42 @@ bool LLFloaterMyEnvironment::canApply(const std::string &context)
if (context == PARAMETER_REGION) if (context == PARAMETER_REGION)
{ {
return LLEnvironment::instance().canAgentUpdateRegionEnvironment(); return isSettingId(selected.front()) && LLEnvironment::instance().canAgentUpdateRegionEnvironment();
} }
else if (context == PARAMETER_PARCEL) else if (context == PARAMETER_PARCEL)
{ {
return LLEnvironment::instance().canAgentUpdateParcelEnvironment(); return isSettingId(selected.front()) && LLEnvironment::instance().canAgentUpdateParcelEnvironment();
} }
else else if (context == PARAMETER_LOCAL)
{ {
return (context == PARAMETER_LOCAL); return isSettingId(selected.front());
} }
return false;
}
bool can_delete(const LLUUID& id)
{
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if (id == trash_id || gInventory.isObjectDescendentOf(id, trash_id))
{
return false;
}
LLViewerInventoryCategory* cat = gInventory.getCategory(id);
if (cat)
{
if (!get_is_category_removable(&gInventory, id))
{
return false;
}
}
else if (!get_is_item_removable(&gInventory, id, false))
{
return false;
}
return true;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -389,7 +435,14 @@ void LLFloaterMyEnvironment::refreshButtonStates()
getChild<LLUICtrl>(BUTTON_GEAR)->setEnabled(settings_ok); getChild<LLUICtrl>(BUTTON_GEAR)->setEnabled(settings_ok);
getChild<LLUICtrl>(BUTTON_NEWSETTINGS)->setEnabled(true); getChild<LLUICtrl>(BUTTON_NEWSETTINGS)->setEnabled(true);
getChild<LLUICtrl>(BUTTON_DELETE)->setEnabled(settings_ok && !selected.empty());
bool enable_delete = false;
if(settings_ok && !selected.empty())
{
enable_delete = can_delete(selected.front());
}
getChild<LLUICtrl>(BUTTON_DELETE)->setEnabled(enable_delete);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -438,7 +491,7 @@ LLUUID LLFloaterMyEnvironment::findItemByAssetId(LLUUID asset_id, bool copyable_
return LLUUID::null; return LLUUID::null;
} }
bool LLFloaterMyEnvironment::isSettingSelected(LLUUID item_id) bool LLFloaterMyEnvironment::isSettingId(const LLUUID& item_id)
{ {
LLInventoryItem* itemp = gInventory.getItem(item_id); LLInventoryItem* itemp = gInventory.getItem(item_id);

View File

@ -60,6 +60,7 @@ private:
void onFilterCheckChange(); void onFilterCheckChange();
void onFilterEdit(const std::string& search_string); void onFilterEdit(const std::string& search_string);
void onSelectionChange(); void onSelectionChange();
void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, uuid_vec_t item_ids);
void onDeleteSelected(); void onDeleteSelected();
void onDoCreate(const LLSD &data); void onDoCreate(const LLSD &data);
void onDoApply(const std::string &context); void onDoApply(const std::string &context);
@ -69,7 +70,7 @@ private:
void getSelectedIds(uuid_vec_t& ids) const; void getSelectedIds(uuid_vec_t& ids) const;
void refreshButtonStates(); void refreshButtonStates();
bool isSettingSelected(LLUUID item_id); static bool isSettingId(const LLUUID &item_id);
static LLUUID findItemByAssetId(LLUUID asset_id, bool copyable_only, bool ignore_library); static LLUUID findItemByAssetId(LLUUID asset_id, bool copyable_only, bool ignore_library);
}; };

View File

@ -62,11 +62,20 @@ const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// LLFloaterNameDesc() // LLFloaterNameDesc()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLFloaterNameDesc::LLFloaterNameDesc(const LLSD& filename ) LLFloaterNameDesc::LLFloaterNameDesc(const LLSD& args)
: LLFloater(filename), : LLFloater(args)
mIsAudio(false) , mIsAudio(false)
, mIsText(false)
{ {
mFilenameAndPath = filename.asString(); if (args.isString())
{
mFilenameAndPath = args.asString();
}
else
{
mFilenameAndPath = args["filename"].asString();
mDestinationFolderId = args["dest"].asUUID();
}
mFilename = gDirUtilp->getBaseFileName(mFilenameAndPath, false); mFilename = gDirUtilp->getBaseFileName(mFilenameAndPath, false);
} }
@ -203,7 +212,8 @@ void LLFloaterNameDesc::onBtnOK( )
LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getNextOwnerPerms("Uploads"),
LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost)); expected_upload_cost,
mDestinationFolderId));
upload_new_resource(uploadInfo, callback, nruserdata); upload_new_resource(uploadInfo, callback, nruserdata);
} }
@ -230,8 +240,8 @@ void LLFloaterNameDesc::onBtnCancel()
// LLFloaterSoundPreview() // LLFloaterSoundPreview()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLFloaterSoundPreview::LLFloaterSoundPreview(const LLSD& filename ) LLFloaterSoundPreview::LLFloaterSoundPreview(const LLSD& args )
: LLFloaterNameDesc(filename) : LLFloaterNameDesc(args)
{ {
mIsAudio = true; mIsAudio = true;
} }
@ -251,8 +261,8 @@ bool LLFloaterSoundPreview::postBuild()
// LLFloaterAnimPreview() // LLFloaterAnimPreview()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& filename ) LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& args )
: LLFloaterNameDesc(filename) : LLFloaterNameDesc(args)
{ {
} }
@ -270,8 +280,8 @@ bool LLFloaterAnimPreview::postBuild()
// LLFloaterScriptPreview() // LLFloaterScriptPreview()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLFloaterScriptPreview::LLFloaterScriptPreview(const LLSD& filename ) LLFloaterScriptPreview::LLFloaterScriptPreview(const LLSD& args )
: LLFloaterNameDesc(filename) : LLFloaterNameDesc(args)
{ {
mIsText = true; mIsText = true;
} }

View File

@ -39,7 +39,7 @@ class LLRadioGroup;
class LLFloaterNameDesc : public LLFloater class LLFloaterNameDesc : public LLFloater
{ {
public: public:
LLFloaterNameDesc(const LLSD& filename); LLFloaterNameDesc(const LLSD& args);
virtual ~LLFloaterNameDesc(); virtual ~LLFloaterNameDesc();
bool postBuild() override; bool postBuild() override;
@ -58,6 +58,7 @@ protected:
std::string mFilenameAndPath; std::string mFilenameAndPath;
std::string mFilename; std::string mFilename;
LLUUID mDestinationFolderId;
}; };
class LLFloaterSoundPreview : public LLFloaterNameDesc class LLFloaterSoundPreview : public LLFloaterNameDesc

View File

@ -36,6 +36,14 @@
#include "llviewerparcelmgr.h" #include "llviewerparcelmgr.h"
#include "llviewerregion.h" #include "llviewerregion.h"
static const std::string lod_strings[4] =
{
"lowest_lod",
"low_lod",
"medium_lod",
"high_lod",
};
// virtual // virtual
bool LLCrossParcelFunctor::apply(LLViewerObject* obj) bool LLCrossParcelFunctor::apply(LLViewerObject* obj)
{ {
@ -75,7 +83,10 @@ LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
mSelectedOnLand(NULL), mSelectedOnLand(NULL),
mRezzedOnLand(NULL), mRezzedOnLand(NULL),
mRemainingCapacity(NULL), mRemainingCapacity(NULL),
mTotalCapacity(NULL) mTotalCapacity(NULL),
mLodLevel(nullptr),
mTrianglesShown(nullptr),
mPixelArea(nullptr)
{ {
} }
@ -99,6 +110,10 @@ bool LLFloaterObjectWeights::postBuild()
mRemainingCapacity = getChild<LLTextBox>("remaining_capacity"); mRemainingCapacity = getChild<LLTextBox>("remaining_capacity");
mTotalCapacity = getChild<LLTextBox>("total_capacity"); mTotalCapacity = getChild<LLTextBox>("total_capacity");
mLodLevel = getChild<LLTextBox>("lod_level");
mTrianglesShown = getChild<LLTextBox>("triangles_shown");
mPixelArea = getChild<LLTextBox>("pixel_area");
return true; return true;
} }
@ -135,6 +150,69 @@ void LLFloaterObjectWeights::setErrorStatus(S32 status, const std::string& reaso
toggleWeightsLoadingIndicators(false); toggleWeightsLoadingIndicators(false);
} }
void LLFloaterObjectWeights::draw()
{
// Normally it's a bad idea to set text and visibility inside draw
// since it can cause rect updates go to different, already drawn elements,
// but floater is very simple and these elements are supposed to be isolated
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
if (selection->isEmpty())
{
const std::string text = getString("nothing_selected");
mLodLevel->setText(text);
mTrianglesShown->setText(text);
mPixelArea->setText(text);
toggleRenderLoadingIndicators(false);
}
else
{
S32 object_lod = -1;
bool multiple_lods = false;
S32 total_tris = 0;
F32 pixel_area = 0;
for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin();
iter != selection->valid_root_end(); ++iter)
{
LLViewerObject* object = (*iter)->getObject();
S32 lod = object->getLOD();
if (object_lod < 0)
{
object_lod = lod;
}
else if (object_lod != lod)
{
multiple_lods = true;
}
if (object->isRootEdit())
{
total_tris += object->recursiveGetTriangleCount();
pixel_area += object->getPixelArea();
}
}
if (multiple_lods)
{
mLodLevel->setText(getString("multiple_lods"));
toggleRenderLoadingIndicators(false);
}
else if (object_lod < 0)
{
// nodes are waiting for data
toggleRenderLoadingIndicators(true);
}
else
{
mLodLevel->setText(getString(lod_strings[object_lod]));
toggleRenderLoadingIndicators(false);
}
mTrianglesShown->setText(llformat("%d", total_tris));
mPixelArea->setText(llformat("%d", pixel_area));
}
LLFloater::draw();
}
void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel) void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel)
{ {
if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty()) if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty())
@ -252,6 +330,17 @@ void LLFloaterObjectWeights::toggleLandImpactsLoadingIndicators(bool visible)
mTotalCapacity->setVisible(!visible); mTotalCapacity->setVisible(!visible);
} }
void LLFloaterObjectWeights::toggleRenderLoadingIndicators(bool visible)
{
childSetVisible("lod_level_loading_indicator", visible);
childSetVisible("triangles_shown_loading_indicator", visible);
childSetVisible("pixel_area_loading_indicator", visible);
mLodLevel->setVisible(!visible);
mTrianglesShown->setVisible(!visible);
mPixelArea->setVisible(!visible);
}
void LLFloaterObjectWeights::updateIfNothingSelected() void LLFloaterObjectWeights::updateIfNothingSelected()
{ {
const std::string text = getString("nothing_selected"); const std::string text = getString("nothing_selected");
@ -269,6 +358,11 @@ void LLFloaterObjectWeights::updateIfNothingSelected()
mRemainingCapacity->setText(text); mRemainingCapacity->setText(text);
mTotalCapacity->setText(text); mTotalCapacity->setText(text);
mLodLevel->setText(text);
mTrianglesShown->setText(text);
mPixelArea->setText(text);
toggleWeightsLoadingIndicators(false); toggleWeightsLoadingIndicators(false);
toggleLandImpactsLoadingIndicators(false); toggleLandImpactsLoadingIndicators(false);
toggleRenderLoadingIndicators(false);
} }

View File

@ -58,21 +58,24 @@ public:
LLFloaterObjectWeights(const LLSD& key); LLFloaterObjectWeights(const LLSD& key);
~LLFloaterObjectWeights(); ~LLFloaterObjectWeights();
/*virtual*/ bool postBuild(); bool postBuild() override;
/*virtual*/ void onOpen(const LLSD& key); void onOpen(const LLSD& key) override;
/*virtual*/ void onWeightsUpdate(const SelectionCost& selection_cost); void onWeightsUpdate(const SelectionCost& selection_cost) override;
/*virtual*/ void setErrorStatus(S32 status, const std::string& reason); void setErrorStatus(S32 status, const std::string& reason) override;
void draw() override;
void updateLandImpacts(const LLParcel* parcel); void updateLandImpacts(const LLParcel* parcel);
void refresh(); void refresh() override;
private: private:
/*virtual*/ void generateTransactionID(); void generateTransactionID() override;
void toggleWeightsLoadingIndicators(bool visible); void toggleWeightsLoadingIndicators(bool visible);
void toggleLandImpactsLoadingIndicators(bool visible); void toggleLandImpactsLoadingIndicators(bool visible);
void toggleRenderLoadingIndicators(bool visible);
void updateIfNothingSelected(); void updateIfNothingSelected();
@ -88,6 +91,10 @@ private:
LLTextBox *mRezzedOnLand; LLTextBox *mRezzedOnLand;
LLTextBox *mRemainingCapacity; LLTextBox *mRemainingCapacity;
LLTextBox *mTotalCapacity; LLTextBox *mTotalCapacity;
LLTextBox *mLodLevel;
LLTextBox *mTrianglesShown;
LLTextBox *mPixelArea;
}; };
#endif //LL_LLFLOATEROBJECTWEIGHTS_H #endif //LL_LLFLOATEROBJECTWEIGHTS_H

View File

@ -529,7 +529,8 @@ bool LLFloaterPreference::postBuild()
} }
#ifndef LL_DISCORD #ifndef LL_DISCORD
getChild<LLTabContainer>("privacy_tab_container")->childDisable("privacy_preferences_discord"); LLPanel* panel = getChild<LLPanel>("privacy_preferences_discord");
getChild<LLTabContainer>("privacy_tab_container")->removeTabPanel(panel);
#endif #endif
return true; return true;
@ -1977,7 +1978,21 @@ void LLFloaterPreference::selectChatPanel()
void LLFloaterPreference::changed() void LLFloaterPreference::changed()
{ {
if (LLConversationLog::instance().getIsLoggingEnabled())
{
getChild<LLButton>("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0); getChild<LLButton>("clear_log")->setEnabled(LLConversationLog::instance().getConversations().size() > 0);
}
else
{
// onClearLog clears list, then notifies changed() and only then clears file,
// so check presence of conversations before checking file, file will cleared later.
llstat st;
bool has_logs = LLConversationLog::instance().getConversations().size() > 0
&& LLFile::stat(LLConversationLog::instance().getFileName(), &st) == 0
&& S_ISREG(st.st_mode)
&& st.st_size > 0;
getChild<LLButton>("clear_log")->setEnabled(has_logs);
}
// set 'enable' property for 'Delete transcripts...' button // set 'enable' property for 'Delete transcripts...' button
updateDeleteTranscriptsButton(); updateDeleteTranscriptsButton();

View File

@ -68,9 +68,10 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
if (!folder->areChildrenInited() || !needsSort(folder->getViewModelItem())) return; if (!folder->areChildrenInited() || !needsSort(folder->getViewModelItem())) return;
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); LLFolderViewModelItemInventory* sort_modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem());
if (modelp->getUUID().isNull()) return; if (!sort_modelp->canSortContent()) return;
bool has_favorites = false;
for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd();
it != end_it; it != end_it;
++it) ++it)
@ -79,11 +80,14 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
LLFolderViewFolder* child_folderp = *it; LLFolderViewFolder* child_folderp = *it;
sort(child_folderp); sort(child_folderp);
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem());
has_favorites |= child_folderp->isFavorite() || child_folderp->hasFavorites();
if (child_folderp->getFoldersCount() > 0) if (child_folderp->getFoldersCount() > 0)
{ {
time_t most_recent_folder_time = LLFolderViewModelItemInventory* folderp = static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem());
static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); time_t most_recent_folder_time = folderp->getCreationDate();
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem());
if (most_recent_folder_time > modelp->getCreationDate()) if (most_recent_folder_time > modelp->getCreationDate())
{ {
modelp->setCreationDate(most_recent_folder_time); modelp->setCreationDate(most_recent_folder_time);
@ -91,16 +95,26 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
} }
if (child_folderp->getItemsCount() > 0) if (child_folderp->getItemsCount() > 0)
{ {
time_t most_recent_item_time = LLFolderViewModelItemInventory* itemp = static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem());
static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); time_t most_recent_item_time = itemp->getCreationDate();
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem());
if (most_recent_item_time > modelp->getCreationDate()) if (most_recent_item_time > modelp->getCreationDate())
{ {
modelp->setCreationDate(most_recent_item_time); modelp->setCreationDate(most_recent_item_time);
} }
} }
} }
for (std::list<LLFolderViewItem*>::const_iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd();
it != end_it && !has_favorites;
++it)
{
LLFolderViewItem* child_itemp = *it;
has_favorites |= child_itemp->isFavorite();
}
if (has_favorites)
{
folder->updateHasFavorites(true);
}
base_t::sort(folder); base_t::sort(folder);
} }

View File

@ -48,6 +48,7 @@ public:
virtual bool isItemInTrash( void) const { return false; } // TODO: make into pure virtual. virtual bool isItemInTrash( void) const { return false; } // TODO: make into pure virtual.
virtual bool isItemInOutfits() const { return false; } virtual bool isItemInOutfits() const { return false; }
virtual bool isAgentInventory() const { return false; } virtual bool isAgentInventory() const { return false; }
virtual bool isAgentInventoryRoot() const { return false; }
virtual bool isUpToDate() const = 0; virtual bool isUpToDate() const = 0;
virtual void addChild(LLFolderViewModelItem* child); virtual void addChild(LLFolderViewModelItem* child);
virtual bool hasChildren() const = 0; virtual bool hasChildren() const = 0;
@ -58,6 +59,7 @@ public:
virtual EInventorySortGroup getSortGroup() const = 0; virtual EInventorySortGroup getSortGroup() const = 0;
virtual LLInventoryObject* getInventoryObject() const = 0; virtual LLInventoryObject* getInventoryObject() const = 0;
virtual void requestSort(); virtual void requestSort();
virtual bool canSortContent() const { return getUUID().notNull(); }
virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0); virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0);
virtual bool filter( LLFolderViewFilter& filter); virtual bool filter( LLFolderViewFilter& filter);
virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter); virtual bool filterChildItem( LLFolderViewModelItem* item, LLFolderViewFilter& filter);

View File

@ -114,6 +114,11 @@ public:
EType getType() const { return mItemType; } EType getType() const { return mItemType; }
S32 getItemId() const { return mItemId; } S32 getItemId() const { return mItemId; }
bool isFavorite() const override { return false; }
bool isItemInTrash() const override { return false; }
bool isAgentInventory() const override { return false; }
bool isAgentInventoryRoot() const override { return false; }
private: private:
LLUIImagePtr pIcon; LLUIImagePtr pIcon;
std::string mName; std::string mName;

View File

@ -0,0 +1,211 @@
/**
* @file llhudeffectresetskeleton.cpp
* @brief LLHUDEffectResetSkeleton class implementation
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2024, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llhudeffectresetskeleton.h"
#include "llagent.h"
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
#include "message.h"
// packet layout
const S32 TARGET_OBJECT = 0; // This is to allow for targetting owned animesh
const S32 RESET_ANIMATIONS = 16; //This can also be a flags if needed
const S32 PKT_SIZE = 17;
//-----------------------------------------------------------------------------
// LLHUDEffectResetSkeleton()
//-----------------------------------------------------------------------------
LLHUDEffectResetSkeleton::LLHUDEffectResetSkeleton(const U8 type) :
LLHUDEffect(type)
{
}
//-----------------------------------------------------------------------------
// ~LLHUDEffectResetSkeleton()
//-----------------------------------------------------------------------------
LLHUDEffectResetSkeleton::~LLHUDEffectResetSkeleton()
{
}
//-----------------------------------------------------------------------------
// packData()
//-----------------------------------------------------------------------------
void LLHUDEffectResetSkeleton::packData(LLMessageSystem *mesgsys)
{
// Pack the default data
LLHUDEffect::packData(mesgsys);
// Pack the type-specific data. Uses a fun packed binary format. Whee!
U8 packed_data[PKT_SIZE];
memset(packed_data, 0, PKT_SIZE);
// pack both target object and position
// position interpreted as offset if target object is non-null
if (mTargetObject)
{
htolememcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
}
else
{
htolememcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
}
U8 resetAnimations = (U8)mResetAnimations;
htolememcpy(&(packed_data[RESET_ANIMATIONS]), &resetAnimations, MVT_U8, 1);
mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
}
//-----------------------------------------------------------------------------
// unpackData()
//-----------------------------------------------------------------------------
void LLHUDEffectResetSkeleton::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
{
LLVector3d new_target;
U8 packed_data[PKT_SIZE];
LLHUDEffect::unpackData(mesgsys, blocknum);
LLUUID source_id;
mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_AgentID, source_id, blocknum);
LLViewerObject *objp = gObjectList.findObject(source_id);
if (objp && objp->isAvatar())
{
setSourceObject(objp);
}
else
{
//LL_WARNS() << "Could not find source avatar for ResetSkeleton effect" << LL_ENDL;
return;
}
S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
if (size != PKT_SIZE)
{
LL_WARNS() << "ResetSkeleton effect with bad size " << size << LL_ENDL;
return;
}
mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
LLUUID target_id;
htolememcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
// The purpose for having a target ID is if we want to reset animesh, or
// other things in the future.
// I implemented this, but due to issues regarding various permission
// checks, I scrapped it for now. --Chaser Zaks
// See https://github.com/secondlife/viewer/pull/1212 for additional info
if (target_id.isNull())
{
target_id = source_id;
}
objp = gObjectList.findObject(target_id);
if (objp)
{
setTargetObject(objp);
}
U8 resetAnimations = 0;
htolememcpy(&resetAnimations, &(packed_data[RESET_ANIMATIONS]), MVT_U8, 1);
// Pre-emptively assume this is going to be flags in the future.
// It isn't needed now, but this will assure that only bit 1 is set
mResetAnimations = resetAnimations & 1;
update();
}
//-----------------------------------------------------------------------------
// setTargetObjectAndOffset()
//-----------------------------------------------------------------------------
void LLHUDEffectResetSkeleton::setTargetObject(LLViewerObject *objp)
{
mTargetObject = objp;
}
//-----------------------------------------------------------------------------
// markDead()
//-----------------------------------------------------------------------------
void LLHUDEffectResetSkeleton::markDead()
{
LLHUDEffect::markDead();
}
void LLHUDEffectResetSkeleton::setSourceObject(LLViewerObject* objectp)
{
// restrict source objects to avatars
if (objectp && objectp->isAvatar())
{
LLHUDEffect::setSourceObject(objectp);
}
}
//-----------------------------------------------------------------------------
// update()
//-----------------------------------------------------------------------------
void LLHUDEffectResetSkeleton::update()
{
// If the target object is dead, set the target object to NULL
if (mTargetObject.isNull() || mTargetObject->isDead())
{
markDead();
return;
}
if (mSourceObject.isNull() || mSourceObject->isDead())
{
markDead();
return;
}
if (mTargetObject->isAvatar())
{
// Only the owner of a avatar can reset their skeleton like this
// Also allow reset if we created the effect (Local resetting)
if (mSourceObject->getID() == mTargetObject->getID() || getOriginatedHere())
{
LLVOAvatar* avatar = mTargetObject->asAvatar();
avatar->resetSkeleton(mResetAnimations);
}
}
else
{
LL_WARNS() << mSourceObject->getID() << " attempted to reset skeleton on "
<< mTargetObject->getID() << ", but it is not a avatar!" << LL_ENDL;
}
markDead();
}

View File

@ -0,0 +1,59 @@
/**
* @file llhudeffectresetskeleton.h
* @brief LLHUDEffectResetSkeleton class definition
*
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2024, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLHUDEFFECTRESETSKELETON_H
#define LL_LLHUDEFFECTRESETSKELETON_H
#include "llhudeffect.h"
class LLViewerObject;
class LLVOAvatar;
class LLHUDEffectResetSkeleton final : public LLHUDEffect
{
public:
friend class LLHUDObject;
/*virtual*/ void markDead();
/*virtual*/ void setSourceObject(LLViewerObject* objectp);
void setTargetObject(LLViewerObject *objp);
void setResetAnimations(bool enable){ mResetAnimations = enable; };
protected:
LLHUDEffectResetSkeleton(const U8 type);
~LLHUDEffectResetSkeleton();
/*virtual*/ void packData(LLMessageSystem *mesgsys);
/*virtual*/ void unpackData(LLMessageSystem *mesgsys, S32 blocknum);
void update();
private:
bool mResetAnimations;
};
#endif // LL_LLHUDEFFECTRESETSKELETON_H

View File

@ -36,6 +36,7 @@
#include "llhudeffecttrail.h" #include "llhudeffecttrail.h"
#include "llhudeffectlookat.h" #include "llhudeffectlookat.h"
#include "llhudeffectpointat.h" #include "llhudeffectpointat.h"
#include "llhudeffectresetskeleton.h"
#include "llhudnametag.h" #include "llhudnametag.h"
#include "llvoicevisualizer.h" #include "llvoicevisualizer.h"
@ -241,6 +242,9 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)
case LL_HUD_EFFECT_BLOB: case LL_HUD_EFFECT_BLOB:
hud_objectp = new LLHUDEffectBlob(type); hud_objectp = new LLHUDEffectBlob(type);
break; break;
case LL_HUD_EFFECT_RESET_SKELETON:
hud_objectp = new LLHUDEffectResetSkeleton(type);
break;
default: default:
LL_WARNS() << "Unknown type of hud effect:" << (U32) type << LL_ENDL; LL_WARNS() << "Unknown type of hud effect:" << (U32) type << LL_ENDL;
} }

View File

@ -96,7 +96,8 @@ public:
LL_HUD_EFFECT_POINTAT, LL_HUD_EFFECT_POINTAT,
LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella
LL_HUD_NAME_TAG, LL_HUD_NAME_TAG,
LL_HUD_EFFECT_BLOB LL_HUD_EFFECT_BLOB,
LL_HUD_EFFECT_RESET_SKELETON
}; };
protected: protected:
static void sortObjects(); static void sortObjects();

View File

@ -1700,6 +1700,8 @@ bool LLIMModel::logToFile(const std::string& file_name, const std::string& from,
} }
else else
{ {
// will check KeepConversationLogTranscripts on its own
LLConversationLog::instance().cache();
return false; return false;
} }
} }

View File

@ -115,7 +115,6 @@ public:
protected: protected:
LLPointer<LLViewerFetchedTexture> m_Image; LLPointer<LLViewerFetchedTexture> m_Image;
S32 mImageBoostLevel = LLGLTexture::BOOST_NONE;
std::string mLoadingText; std::string mLoadingText;
}; };
@ -128,12 +127,8 @@ LLTexturePreviewView::LLTexturePreviewView(const LLView::Params& p)
LLTexturePreviewView::~LLTexturePreviewView() LLTexturePreviewView::~LLTexturePreviewView()
{ {
if (m_Image)
{
m_Image->setBoostLevel(mImageBoostLevel);
m_Image = nullptr; m_Image = nullptr;
} }
}
void LLTexturePreviewView::draw() void LLTexturePreviewView::draw()
{ {
@ -153,18 +148,18 @@ void LLTexturePreviewView::draw()
bool isLoading = (!m_Image->isFullyLoaded()) && (m_Image->getDiscardLevel() > 0); bool isLoading = (!m_Image->isFullyLoaded()) && (m_Image->getDiscardLevel() > 0);
if (isLoading) if (isLoading)
LLFontGL::getFontSansSerif()->renderUTF8(mLoadingText, 0, rctClient.mLeft + 3, rctClient.mTop - 25, LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW); LLFontGL::getFontSansSerif()->renderUTF8(mLoadingText, 0, rctClient.mLeft + 3, rctClient.mTop - 25, LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
m_Image->addTextureStats((isLoading) ? MAX_IMAGE_AREA : (F32)(rctClient.getWidth() * rctClient.getHeight()));
m_Image->setKnownDrawSize(MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);
} }
} }
void LLTexturePreviewView::setImageFromAssetId(const LLUUID& idAsset) void LLTexturePreviewView::setImageFromAssetId(const LLUUID& idAsset)
{ {
m_Image = LLViewerTextureManager::getFetchedTexture(idAsset, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); m_Image = LLViewerTextureManager::getFetchedTexture(idAsset, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_THUMBNAIL);
if (m_Image) if (m_Image)
{ {
mImageBoostLevel = m_Image->getBoostLevel();
m_Image->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
m_Image->forceToSaveRawImage(0); m_Image->forceToSaveRawImage(0);
m_Image->setKnownDrawSize(MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);
if ( (!m_Image->isFullyLoaded()) && (!m_Image->hasFetcher()) ) if ( (!m_Image->isFullyLoaded()) && (!m_Image->hasFetcher()) )
{ {
if (m_Image->isInFastCacheList()) if (m_Image->isInFastCacheList())

View File

@ -829,6 +829,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{ {
const LLInventoryObject *obj = getInventoryObject(); const LLInventoryObject *obj = getInventoryObject();
bool single_folder_root = (mRoot == NULL); bool single_folder_root = (mRoot == NULL);
bool is_cof = isCOFFolder();
bool is_inbox = isInboxFolder();
if (obj) if (obj)
{ {
@ -843,7 +845,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Copy")); disabled_items.push_back(std::string("Copy"));
} }
if (isAgentInventory() && !single_folder_root && !isMarketplaceListingsFolder()) bool is_agent_inventory = isAgentInventory();
if (is_agent_inventory && !single_folder_root && !is_cof && !is_inbox)
{ {
items.push_back(std::string("New folder from selected")); items.push_back(std::string("New folder from selected"));
items.push_back(std::string("Subfolder Separator")); items.push_back(std::string("Subfolder Separator"));
@ -856,6 +859,19 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
} }
} }
if (isFavorite())
{
items.push_back(std::string("Remove from Favorites"));
}
else if (is_agent_inventory && !gInventory.isObjectDescendentOf(mUUID, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)))
{
items.push_back(std::string("Add to Favorites"));
if (gInventory.getRootFolderID() == mUUID)
{
disabled_items.push_back(std::string("Add to Favorites"));
}
}
if (obj->getIsLinkType()) if (obj->getIsLinkType())
{ {
items.push_back(std::string("Find Original")); items.push_back(std::string("Find Original"));
@ -868,6 +884,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (!isItemMovable() || !canMenuCut()) if (!isItemMovable() || !canMenuCut())
{ {
disabled_items.push_back(std::string("Cut")); disabled_items.push_back(std::string("Cut"));
disabled_items.push_back(std::string("New folder from selected"));
} }
} }
else else
@ -877,7 +894,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
items.push_back(std::string("Find Links")); items.push_back(std::string("Find Links"));
} }
if (!isInboxFolder() && !single_folder_root) if (!is_inbox && !single_folder_root)
{ {
items.push_back(std::string("Rename")); items.push_back(std::string("Rename"));
if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0)) if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0))
@ -917,6 +934,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (!isItemMovable() || !canMenuCut()) if (!isItemMovable() || !canMenuCut())
{ {
disabled_items.push_back(std::string("Cut")); disabled_items.push_back(std::string("Cut"));
disabled_items.push_back(std::string("New folder from selected"));
} }
if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder()) if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder())
@ -939,7 +957,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
} }
// Don't allow items to be pasted directly into the COF or the inbox // Don't allow items to be pasted directly into the COF or the inbox
if (!isCOFFolder() && !isInboxFolder()) if (!is_cof && !is_inbox)
{ {
items.push_back(std::string("Paste")); items.push_back(std::string("Paste"));
} }
@ -1333,6 +1351,13 @@ bool LLInvFVBridge::isAgentInventory() const
return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
} }
bool LLInvFVBridge::isAgentInventoryRoot() const
{
const LLInventoryModel* model = getInventoryModel();
if(!model) return false;
return gInventory.getRootFolderID() == mUUID;
}
bool LLInvFVBridge::isCOFFolder() const bool LLInvFVBridge::isCOFFolder() const
{ {
return LLAppearanceMgr::instance().getIsInCOF(mUUID); return LLAppearanceMgr::instance().getIsInCOF(mUUID);
@ -2280,7 +2305,21 @@ const LLUUID& LLItemBridge::getThumbnailUUID() const
return LLUUID::null; return LLUUID::null;
} }
// virtual bool LLItemBridge::isFavorite() const
{
LLViewerInventoryItem* item = NULL;
LLInventoryModel* model = getInventoryModel();
if (model)
{
item = model->getItem(mUUID);
}
if (item)
{
return get_is_favorite(item);
}
return false;
}
bool LLItemBridge::isItemPermissive() const bool LLItemBridge::isItemPermissive() const
{ {
if (LLViewerInventoryItem* item = getItem()) if (LLViewerInventoryItem* item = getItem())
@ -2425,6 +2464,16 @@ const LLUUID& LLFolderBridge::getThumbnailUUID() const
return LLUUID::null; return LLUUID::null;
} }
bool LLFolderBridge::isFavorite() const
{
LLViewerInventoryCategory* cat = getCategory();
if (cat)
{
return cat->getIsFavorite();
}
return false;
}
void LLFolderBridge::update() void LLFolderBridge::update()
{ {
// we know we have children but haven't fetched them (doesn't obey filter) // we know we have children but haven't fetched them (doesn't obey filter)
@ -4420,6 +4469,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
} }
disabled_items.push_back(std::string("New Folder")); disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("upload_options"));
disabled_items.push_back(std::string("upload_def")); disabled_items.push_back(std::string("upload_def"));
disabled_items.push_back(std::string("create_new")); disabled_items.push_back(std::string("create_new"));
} }
@ -4445,6 +4495,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
{ {
disabled_items.push_back(std::string("New Folder")); disabled_items.push_back(std::string("New Folder"));
disabled_items.push_back(std::string("New Listing Folder")); disabled_items.push_back(std::string("New Listing Folder"));
disabled_items.push_back(std::string("upload_options"));
disabled_items.push_back(std::string("upload_def")); disabled_items.push_back(std::string("upload_def"));
disabled_items.push_back(std::string("create_new")); disabled_items.push_back(std::string("create_new"));
} }
@ -4504,6 +4555,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.push_back(std::string("Rename")); items.push_back(std::string("Rename"));
items.push_back(std::string("thumbnail")); items.push_back(std::string("thumbnail"));
addInventoryFavoritesMenuOptions(items);
addDeleteContextMenuOptions(items, disabled_items); addDeleteContextMenuOptions(items, disabled_items);
// EXT-4030: disallow deletion of currently worn outfit // EXT-4030: disallow deletion of currently worn outfit
const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
@ -4521,6 +4573,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id); EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id);
if (in_my_outfits != MY_OUTFITS_NO) if (in_my_outfits != MY_OUTFITS_NO)
{ {
// Either an outfit or a subfolder inside MY_OUTFITS
if (in_my_outfits == MY_OUTFITS_SUBFOLDER) if (in_my_outfits == MY_OUTFITS_SUBFOLDER)
{ {
// Not inside an outfit, but inside 'my outfits' // Not inside an outfit, but inside 'my outfits'
@ -4530,6 +4583,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.push_back(std::string("Rename")); items.push_back(std::string("Rename"));
items.push_back(std::string("thumbnail")); items.push_back(std::string("thumbnail"));
addInventoryFavoritesMenuOptions(items);
addDeleteContextMenuOptions(items, disabled_items); addDeleteContextMenuOptions(items, disabled_items);
} }
else else
@ -4546,6 +4600,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
} }
if (!isMarketplaceListingsFolder()) if (!isMarketplaceListingsFolder())
{ {
items.push_back(std::string("upload_options"));
items.push_back(std::string("upload_def")); items.push_back(std::string("upload_def"));
items.push_back(std::string("create_new")); items.push_back(std::string("create_new"));
items.push_back(std::string("New Script")); items.push_back(std::string("New Script"));
@ -4577,6 +4632,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID) if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID)
{ {
items.push_back(std::string("Copy outfit list to clipboard")); items.push_back(std::string("Copy outfit list to clipboard"));
addInventoryFavoritesMenuOptions(items);
addOpenFolderMenuOptions(flags, items); addOpenFolderMenuOptions(flags, items);
} }
@ -4835,6 +4892,18 @@ void LLFolderBridge::addOpenFolderMenuOptions(U32 flags, menuentry_vec_t& items)
} }
} }
void LLFolderBridge::addInventoryFavoritesMenuOptions(menuentry_vec_t& items)
{
if (isFavorite())
{
items.push_back(std::string("Remove from Favorites"));
}
else
{
items.push_back(std::string("Add to Favorites"));
}
}
bool LLFolderBridge::hasChildren() const bool LLFolderBridge::hasChildren() const
{ {
LLInventoryModel* model = getInventoryModel(); LLInventoryModel* model = getInventoryModel();
@ -7089,12 +7158,13 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
item = (LLViewerInventoryItem*)gInventory.getItem(object_id); item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
{ {
rez_attachment(item, NULL, true); // Replace if "Wear"ing. static LLCachedControl<bool> replace_item(gSavedSettings, "InventoryAddAttachmentBehavior", false);
rez_attachment(item, NULL, ("attach" == action) ? replace_item() : true); // Replace if "Wear"ing.
} }
else if(item && item->isFinished()) else if(item && item->isFinished())
{ {
// must be in library. copy it to our inventory and put it on. // must be in library. copy it to our inventory and put it on.
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0)); LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0, true));
copy_inventory_item( copy_inventory_item(
gAgent.getID(), gAgent.getID(),
item->getPermissions().getOwner(), item->getPermissions().getOwner(),
@ -8219,7 +8289,8 @@ void LLObjectBridgeAction::attachOrDetach()
} }
else else
{ {
LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, false); // Don't replace if adding. static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryAddAttachmentBehavior", false);
LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, inventory_linking()); // Don't replace if adding.
} }
} }
@ -8410,6 +8481,7 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
buildContextMenuOptions(flags, items, disabled_items); buildContextMenuOptions(flags, items, disabled_items);
items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
items.erase(std::remove(items.begin(), items.end(), std::string("New folder from selected")), items.end());
hide_context_entries(menu, items, disabled_items); hide_context_entries(menu, items, disabled_items);
} }
@ -8444,6 +8516,51 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
return new_listener; return new_listener;
} }
/************************************************************************/
/* Favorites Inventory Panel related classes */
/************************************************************************/
void LLFavoritesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
// todo: consider things that should be disabled
menuentry_vec_t disabled_items, items;
buildContextMenuOptions(flags, items, disabled_items);
items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end());
items.erase(std::remove(items.begin(), items.end(), std::string("New folder from selected")), items.end());
hide_context_entries(menu, items, disabled_items);
}
LLInvFVBridge* LLFavoritesInventoryBridgeBuilder::createBridge(
LLAssetType::EType asset_type,
LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
LLFolderViewModelInventory* view_model,
LLFolderView* root,
const LLUUID& uuid,
U32 flags /*= 0x00*/) const
{
LLInvFVBridge* new_listener = NULL;
if (asset_type == LLAssetType::AT_CATEGORY
&& actual_asset_type != LLAssetType::AT_LINK_FOLDER)
{
new_listener = new LLFavoritesFolderBridge(inv_type, inventory, root, uuid);
}
else
{
new_listener = LLInventoryFolderViewModelBuilder::createBridge(asset_type,
actual_asset_type,
inv_type,
inventory,
view_model,
root,
uuid,
flags);
}
return new_listener;
}
LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge() LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge()
{ {
} }
@ -8454,7 +8571,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
menuentry_vec_t disabled_items; menuentry_vec_t disabled_items;
if (get_selection_item_uuids(selected_items, ids)) if (get_selection_item_uuids(selected_items, ids))
{ {
if (!LLAppearanceMgr::instance().canAddWearables(ids) && canWearSelected(ids)) if (!LLAppearanceMgr::instance().canAddWearables(ids, false) && canWearSelected(ids))
{ {
disabled_items.push_back(std::string("Wearable And Object Wear")); disabled_items.push_back(std::string("Wearable And Object Wear"));
disabled_items.push_back(std::string("Wearable Add")); disabled_items.push_back(std::string("Wearable Add"));

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