Merge commit '9e24b30' into marchcat/maint-c/restore

# Conflicts:
#	indra/llmath/v2math.cpp
#	indra/llmath/v2math.h
#	indra/llmath/v3math.h
#	indra/llmath/v4math.h
#	indra/llui/llfolderviewitem.cpp
#	indra/llui/llfolderviewitem.h
#	indra/llui/llfolderviewmodel.h
#	indra/llui/llmodaldialog.cpp
#	indra/llui/lltexteditor.cpp
#	indra/llui/lltexteditor.h
#	indra/llwindow/llwindowwin32.cpp
#	indra/newview/llagent.cpp
#	indra/newview/llagentcamera.h
#	indra/newview/llavatarrenderinfoaccountant.cpp
#	indra/newview/llconversationmodel.h
#	indra/newview/llfloaterinventorysettings.cpp
#	indra/newview/llfloaternamedesc.cpp
#	indra/newview/llfloaternamedesc.h
#	indra/newview/llfloaterobjectweights.cpp
#	indra/newview/llfloaterobjectweights.h
#	indra/newview/llfolderviewmodelinventory.h
#	indra/newview/llinspecttexture.cpp
#	indra/newview/llinventorybridge.cpp
#	indra/newview/llinventorybridge.h
#	indra/newview/llinventoryfunctions.cpp
#	indra/newview/llinventorygallery.h
#	indra/newview/llinventorygallerymenu.cpp
#	indra/newview/llinventorymodel.cpp
#	indra/newview/llinventorypanel.cpp
#	indra/newview/llinventorypanel.h
#	indra/newview/llmaterialeditor.cpp
#	indra/newview/lloutfitgallery.cpp
#	indra/newview/lloutfitgallery.h
#	indra/newview/lloutfitslist.cpp
#	indra/newview/lloutfitslist.h
#	indra/newview/llpanelgroupcreate.cpp
#	indra/newview/llpanelgroupgeneral.cpp
#	indra/newview/llpanelobjectinventory.cpp
#	indra/newview/llpaneloutfitsinventory.h
#	indra/newview/llpanelprofile.cpp
#	indra/newview/llpanelwearing.cpp
#	indra/newview/llreflectionmap.cpp
#	indra/newview/llselectmgr.cpp
#	indra/newview/llsidepanelappearance.cpp
#	indra/newview/llsidepaneliteminfo.cpp
#	indra/newview/llteleporthistorystorage.cpp
#	indra/newview/lltexturectrl.cpp
#	indra/newview/lltexturectrl.h
#	indra/newview/lltexturefetch.cpp
#	indra/newview/lltexturefetch.h
#	indra/newview/llviewerassetupload.cpp
#	indra/newview/llviewercamera.cpp
#	indra/newview/llviewercamera.h
#	indra/newview/llviewermenufile.cpp
#	indra/newview/llviewerobject.h
#	indra/newview/llviewertexture.cpp
#	indra/newview/llviewerwindow.cpp
#	indra/newview/llvoavatar.cpp
#	indra/newview/llvoavatar.h
#	indra/newview/llvoavatarself.cpp
#	indra/newview/llvovolume.cpp
#	indra/newview/llvovolume.h
#	indra/newview/tests/llviewerassetstats_test.cpp
master
Andrey Lihatskiy 2025-04-10 06:01:50 +03:00
commit 5d7a5001b4
200 changed files with 4693 additions and 1756 deletions

View File

@ -2332,59 +2332,33 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
</map>
<key>threejs</key>
<map>
<key>platforms</key>
<map>
<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>copyright</key>
<string>Copyright © 2010-2021 three.js authors</string>
<key>license</key>
<string>MIT</string>
<key>license_file</key>
<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>
<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>
<key>tinygltf</key>
<map>

View File

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

View File

@ -77,6 +77,15 @@ std::string LLDate::asRFC1123() const
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
std::string LLDate::toLocalDateString (std::string fmt) const
{
LL_PROFILE_ZONE_SCOPED;
time_t locSeconds = (time_t) mSecondsSinceEpoch;
struct tm * lt = localtime (&locSeconds);
return toHTTPDateString(lt, fmt);
}
std::string LLDate::toHTTPDateString (std::string fmt) const
{
LL_PROFILE_ZONE_SCOPED;

View File

@ -77,6 +77,7 @@ public:
std::string asRFC1123() const;
void toStream(std::ostream&) const;
bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
std::string toLocalDateString (std::string fmt) const;
std::string toHTTPDateString (std::string fmt) const;
static std::string toHTTPDateString (tm * gmt, std::string fmt);
/**

View File

@ -638,6 +638,14 @@ public:
{
getCPUIDInfo();
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);
}

View File

@ -4,7 +4,7 @@
* @date 2021-10-21
* @brief ThreadPool configures a WorkQueue along with a pool of threads to
* service it.
*
*
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Copyright (c) 2021, Linden Research, Inc.
* $/LicenseInfo$
@ -55,7 +55,7 @@ namespace LL
* ThreadPool listens for application shutdown messages on the "LLApp"
* LLEventPump. Call close() to shut down this ThreadPool early.
*/
virtual void close();
void close();
std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); }

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_PARENT_ID_LABEL("parent_id");
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_ASSET_TYPE_LABEL("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_FLAGS_LABEL("flags");
static const std::string INV_CREATION_DATE_LABEL("created_at");
static const std::string INV_TOGGLED_LABEL("toggled");
// key used by agent-inventory-service
static const std::string INV_ASSET_TYPE_LABEL_WS("type_default");
@ -82,14 +84,16 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
mParentUUID(parent_uuid),
mType(type),
mName(name),
mCreationDate(0)
mCreationDate(0),
mFavorite(false)
{
correctInventoryName(mName);
}
LLInventoryObject::LLInventoryObject()
: mType(LLAssetType::AT_NONE),
mCreationDate(0)
mCreationDate(0),
mFavorite(false)
{
}
@ -104,6 +108,7 @@ void LLInventoryObject::copyObject(const LLInventoryObject* other)
mType = other->mType;
mName = other->mName;
mThumbnailUUID = other->mThumbnailUUID;
mFavorite = other->mFavorite;
}
const LLUUID& LLInventoryObject::getUUID() const
@ -121,6 +126,11 @@ const LLUUID& LLInventoryObject::getThumbnailUUID() const
return mThumbnailUUID;
}
bool LLInventoryObject::getIsFavorite() const
{
return mFavorite;
}
const std::string& LLInventoryObject::getName() const
{
return mName;
@ -175,6 +185,11 @@ void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid)
mThumbnailUUID = thumbnail_uuid;
}
void LLInventoryObject::setFavorite(bool favorite)
{
mFavorite = favorite;
}
void LLInventoryObject::setType(LLAssetType::EType type)
{
mType = type;
@ -247,6 +262,23 @@ bool LLInventoryObject::importLegacyStream(std::istream& input_stream)
{
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))
{
@ -735,6 +767,23 @@ bool LLInventoryItem::importLegacyStream(std::istream& input_stream)
{
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))
{
@ -895,6 +944,11 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
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();
if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|| (mAssetUUID.isNull()))
@ -937,6 +991,7 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
// TODO - figure out if this should be moved into the noclobber fields above
mThumbnailUUID.setNull();
mFavorite = false;
// iterate as map to avoid making unnecessary temp copies of everything
LLSD::map_const_iterator i, end;
@ -982,6 +1037,17 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
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)
{
mPermissions = ll_permissions_from_sd(i->second);
@ -1177,6 +1243,11 @@ LLSD LLInventoryCategory::asLLSD() const
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;
}
@ -1188,11 +1259,17 @@ LLSD LLInventoryCategory::asAISCreateCatLLSD() const
S8 type = static_cast<S8>(mPreferredType);
sd[INV_ASSET_TYPE_LABEL_WS] = type;
sd[INV_NAME_LABEL] = mName;
if (mThumbnailUUID.notNull())
{
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;
}
@ -1240,6 +1317,17 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
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;
if (sd.has(w))
{
@ -1362,6 +1450,23 @@ bool LLInventoryCategory::importLegacyStream(std::istream& input_stream)
{
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
{
@ -1409,6 +1514,10 @@ LLSD LLInventoryCategory::exportLLSD() const
{
cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
if (mFavorite)
{
cat_data[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
}
return cat_data;
}
@ -1441,6 +1550,16 @@ bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
}
setThumbnailUUID(thumbnail_uuid);
}
if (cat_data.has(INV_FAVORITE_LABEL))
{
bool favorite = false;
const LLSD& favorite_data = cat_data[INV_FAVORITE_LABEL];
if (favorite_data.has(INV_TOGGLED_LABEL))
{
favorite = favorite_data[INV_TOGGLED_LABEL].asBoolean();
}
setFavorite(favorite);
}
if (cat_data.has(INV_NAME_LABEL))
{
mName = cat_data[INV_NAME_LABEL].asString();

View File

@ -71,6 +71,7 @@ public:
virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID
const LLUUID& getParentUUID() const;
virtual const LLUUID& getThumbnailUUID() const;
virtual bool getIsFavorite() const;
virtual const std::string& getName() const;
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@ -86,6 +87,7 @@ public:
virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid);
virtual void setFavorite(bool favorite);
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
@ -111,6 +113,7 @@ protected:
LLUUID mUUID;
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
LLUUID mThumbnailUUID;
bool mFavorite;
LLAssetType::EType mType;
std::string mName;
time_t mCreationDate; // seconds from 1/1/1970, UTC

View File

@ -329,28 +329,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)
{
LLQuaternion q(angle, mXAxis);
LLMatrix3 rotation_matrix(q);
rotate(rotation_matrix);
CHECK_FINITE_OBJ();
rotate2(mYAxis, mZAxis, angle);
}
void LLCoordFrame::pitch(F32 angle)
{
LLQuaternion q(angle, mYAxis);
LLMatrix3 rotation_matrix(q);
rotate(rotation_matrix);
CHECK_FINITE_OBJ();
rotate2(mZAxis, mXAxis, angle);
}
void LLCoordFrame::yaw(F32 angle)
{
LLQuaternion q(angle, mZAxis);
LLMatrix3 rotation_matrix(q);
rotate(rotation_matrix);
CHECK_FINITE_OBJ();
rotate2(mXAxis, mYAxis, angle);
}
// get*() routines

View File

@ -58,7 +58,7 @@ LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
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)
{
angle *= 0.5;
@ -77,7 +77,7 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &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)
{
angle *= 0.5;

View File

@ -67,7 +67,14 @@ F32 angle_between(const LLVector2& a, const LLVector2& b)
return angle;
}
bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon)
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)
{
LLVector2 an = a;
LLVector2 bn = b;

View File

@ -107,13 +107,14 @@ class LLVector2
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
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
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
@ -124,26 +125,22 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u); // Returns a vect
inline LLVector2::LLVector2(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
clear();
}
inline LLVector2::LLVector2(F32 x, F32 y)
{
mV[VX] = x;
mV[VY] = y;
set(x, y);
}
inline LLVector2::LLVector2(const F32 *vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
set(vec);
}
inline LLVector2::LLVector2(const LLVector3 &vec)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
set(vec.mV);
}
inline LLVector2::LLVector2(const LLSD &sd)
@ -155,28 +152,24 @@ inline LLVector2::LLVector2(const LLSD &sd)
inline void LLVector2::clear(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VX] = mV[VY] = 0.f;
}
inline void LLVector2::setZero(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
clear();
}
// deprecated
inline void LLVector2::clearVec(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
clear();
}
// deprecated
inline void LLVector2::zeroVec(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
clear();
}
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)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
set(vec.mV);
}
inline void LLVector2::set(const F32 *vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
set(vec[VX], vec[VY]);
}
// deprecated
inline void LLVector2::setVec(F32 x, F32 y)
{
mV[VX] = x;
mV[VY] = y;
set(x, y);
}
// deprecated
inline void LLVector2::setVec(const LLVector2 &vec)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
set(vec);
}
// deprecated
inline void LLVector2::setVec(const F32 *vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
set(vec);
}
@ -224,7 +212,7 @@ inline void LLVector2::setVec(const F32 *vec)
inline F32 LLVector2::length(void) const
{
return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
return (F32) sqrt(lengthSquared());
}
inline F32 LLVector2::lengthSquared(void) const
@ -234,61 +222,42 @@ inline F32 LLVector2::lengthSquared(void) const
inline F32 LLVector2::normalize(void)
{
F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
F32 oomag;
F32 mag = length();
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[0] *= oomag;
mV[1] *= oomag;
*this /= mag;
}
else
{
mV[0] = 0.f;
mV[1] = 0.f;
clear();
mag = 0;
}
return (mag);
return mag;
}
// checker
inline bool LLVector2::isFinite() const
{
return (llfinite(mV[VX]) && llfinite(mV[VY]));
return llfinite(mV[VX]) && llfinite(mV[VY]);
}
// deprecated
inline F32 LLVector2::magVec(void) const
inline F32 LLVector2::magVec(void) const
{
return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
return length();
}
// deprecated
inline F32 LLVector2::magVecSquared(void) const
inline F32 LLVector2::magVecSquared(void) const
{
return mV[0]*mV[0] + mV[1]*mV[1];
return lengthSquared();
}
// deprecated
inline F32 LLVector2::normVec(void)
inline F32 LLVector2::normVec(void)
{
F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[0] *= oomag;
mV[1] *= oomag;
}
else
{
mV[0] = 0.f;
mV[1] = 0.f;
mag = 0;
}
return (mag);
return normalize();
}
inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
@ -301,11 +270,7 @@ inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
inline bool LLVector2::isNull()
{
if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] )
{
return true;
}
return false;
return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY];
}
@ -337,9 +302,9 @@ inline LLVector2 operator-(const LLVector2 &a, const LLVector2 &b)
return c -= b;
}
inline F32 operator*(const LLVector2 &a, const LLVector2 &b)
inline F32 operator*(const LLVector2 &a, const LLVector2 &b)
{
return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1]);
return a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1];
}
inline LLVector2 operator%(const LLVector2 &a, const LLVector2 &b)
@ -405,10 +370,7 @@ inline const LLVector2& operator*=(LLVector2 &a, F32 k)
inline const LLVector2& operator/=(LLVector2 &a, F32 k)
{
F32 t = 1.f / k;
a.mV[0] *= t;
a.mV[1] *= t;
return a;
return a *= 1.f / k;
}
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 LLVector3d &vec); // deprecated
F32 length() const; // Returns magnitude of LLVector3
F32 lengthSquared() const; // Returns magnitude squared of LLVector3
F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated
F32 length() const; // Returns magnitude of LLVector3
F32 lengthSquared() const; // Returns magnitude squared of LLVector3
F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated
inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
inline F32 normVec(); // deprecated
inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
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, 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 LLQuaternion &q); // Rotates by LLQuaternion q
const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
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(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
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
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
bool isNull() const; // Returns true if vector has a _very_small_ length
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(void)
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
clear();
}
inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
set(x, y, z);
}
inline LLVector3::LLVector3(const F32 *vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
set(vec);
}
inline LLVector3::LLVector3(const glm::vec3& vec)
@ -230,7 +224,7 @@ inline LLVector3::LLVector3(const LLVector3 &copy)
// checker
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(void)
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
set(0.f, 0.f, 0.f);
}
inline void LLVector3::setZero(void)
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
clear();
}
inline void LLVector3::clearVec(void)
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
clear();
}
inline void LLVector3::zeroVec(void)
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
clear();
}
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)
{
mV[0] = vec.mV[0];
mV[1] = vec.mV[1];
mV[2] = vec.mV[2];
set(vec.mV[0], vec.mV[1], vec.mV[2]);
}
inline void LLVector3::set(const F32 *vec)
{
mV[0] = vec[0];
mV[1] = vec[1];
mV[2] = vec[2];
set(vec[0], vec[1], vec[2]);
}
inline void LLVector3::set(const glm::vec4& vec)
@ -302,92 +284,63 @@ inline void LLVector3::set(const glm::vec3& vec)
// deprecated
inline void LLVector3::setVec(F32 x, F32 y, F32 z)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
set(x, y, z);
}
// deprecated
inline void LLVector3::setVec(const LLVector3 &vec)
{
mV[0] = vec.mV[0];
mV[1] = vec.mV[1];
mV[2] = vec.mV[2];
set(vec);
}
// deprecated
inline void LLVector3::setVec(const F32 *vec)
{
mV[0] = vec[0];
mV[1] = vec[1];
mV[2] = vec[2];
set(vec);
}
inline F32 LLVector3::normalize(void)
{
F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[0] *= oomag;
mV[1] *= oomag;
mV[2] *= oomag;
*this /= mag;
}
else
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
clear();
mag = 0;
}
return (mag);
return mag;
}
// deprecated
inline F32 LLVector3::normVec(void)
{
F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[0] *= oomag;
mV[1] *= oomag;
mV[2] *= oomag;
}
else
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
mag = 0;
}
return (mag);
return normalize();
}
// LLVector3 Magnitude and Normalization Functions
inline F32 LLVector3::length(void) const
inline F32 LLVector3::length(void) const
{
return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
return (F32) sqrt(lengthSquared());
}
inline F32 LLVector3::lengthSquared(void) const
inline F32 LLVector3::lengthSquared(void) const
{
return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
}
inline F32 LLVector3::magVec(void) const
inline F32 LLVector3::magVec(void) const
{
return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
return length();
}
inline F32 LLVector3::magVecSquared(void) const
inline F32 LLVector3::magVecSquared(void) const
{
return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
return lengthSquared();
}
inline bool LLVector3::inRange( F32 min, F32 max ) const
@ -411,7 +364,7 @@ inline LLVector3 operator-(const LLVector3 &a, const LLVector3 &b)
inline F32 operator*(const LLVector3 &a, const LLVector3 &b)
{
return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]);
return a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2];
}
inline LLVector3 operator%(const LLVector3 &a, const LLVector3 &b)
@ -499,10 +452,7 @@ inline const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b)
inline const LLVector3& operator/=(LLVector3 &a, F32 k)
{
F32 t = 1.f / k;
a.mV[0] *= t;
a.mV[1] *= t;
a.mV[2] *= t;
a *= 1.f / k;
return a;
}
@ -522,7 +472,7 @@ inline LLVector3::operator glm::vec4() const
return glm::vec4(mV[VX], mV[VY], mV[VZ], 1.f);
}
inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b)
inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b)
{
F32 x = a.mV[0] - b.mV[0];
F32 y = a.mV[1] - b.mV[1];
@ -530,7 +480,7 @@ inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b)
return (F32) 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)
{
F32 x = a.mV[0] - b.mV[0];
F32 y = a.mV[1] - b.mV[1];
@ -538,7 +488,7 @@ inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b)
return x*x + y*y + z*z;
}
inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b)
inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b)
{
F32 x = a.mV[0] - b.mV[0];
F32 y = a.mV[1] - b.mV[1];
@ -552,10 +502,7 @@ inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b)
{
return ((a * b) / bb) * b;
}
else
{
return b.zero;
}
return b.zero;
}
inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
@ -592,11 +539,7 @@ inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u)
inline bool LLVector3::isNull() const
{
if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ] )
{
return true;
}
return false;
return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos)
@ -637,7 +580,7 @@ inline F32 angle_between(const LLVector3& a, const LLVector3& b)
ab = 0.0f; // get rid of negative zero
}
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)
@ -647,7 +590,7 @@ inline bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
an.normalize();
bn.normalize();
F32 dot = an * bn;
if ( (1.0f - fabs(dot)) < epsilon)
if (1.0f - fabs(dot) < epsilon)
{
return true;
}

View File

@ -107,9 +107,9 @@ class LLVector4
F32 lengthSquared() const; // Returns magnitude squared of LLVector4
F32 normalize(); // Normalizes and returns the magnitude of LLVector4
F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated
F32 normVec(); // deprecated
F32 magVec() const; // deprecated
F32 magVecSquared() const; // deprecated
F32 normVec(); // deprecated
// Sets all values to absolute value of their original values
// Returns true if data changed
@ -118,8 +118,10 @@ class LLVector4
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]; }
const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat
const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q
const LLVector4& rotVec(F32 angle, const LLVector4 &vec); // Rotates about vec by angle radians
const LLVector4& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
const LLVector4& rotVec(const LLMatrix4 &mat); // Rotates by MAT4 mat
const LLVector4& rotVec(const LLQuaternion &q); // Rotates by QUAT q
const LLVector4& scaleVec(const LLVector4& vec); // Scales component-wise by vec
@ -159,34 +161,22 @@ LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u); // Returns a vect
inline LLVector4::LLVector4(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 1.f;
clear();
}
inline LLVector4::LLVector4(F32 x, F32 y, F32 z)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
mV[VW] = 1.f;
set(x, y, z, 1.f);
}
inline LLVector4::LLVector4(F32 x, F32 y, F32 z, F32 w)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
mV[VW] = w;
set(x, y, z, w);
}
inline LLVector4::LLVector4(const F32 *vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
mV[VW] = vec[VW];
set(vec);
}
inline LLVector4::LLVector4(const F64 *vec)
@ -215,18 +205,12 @@ inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w)
inline LLVector4::LLVector4(const LLVector3 &vec)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = 1.f;
set(vec, 1.f);
}
inline LLVector4::LLVector4(const LLVector3 &vec, F32 w)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = w;
set(vec, w);
}
inline LLVector4::LLVector4(const LLSD &sd)
@ -252,43 +236,31 @@ inline LLVector4::LLVector4(const glm::vec4& vec)
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
inline void LLVector4::clear(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 1.f;
set(0.f, 0.f, 0.f, 1.f);
}
// deprecated
inline void LLVector4::clearVec(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 1.f;
clear();
}
// deprecated
inline void LLVector4::zeroVec(void)
{
mV[VX] = 0.f;
mV[VY] = 0.f;
mV[VZ] = 0.f;
mV[VW] = 0.f;
set(0.f, 0.f, 0.f, 0.f);
}
inline void LLVector4::set(F32 x, F32 y, F32 z)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
mV[VW] = 1.f;
set(x, y, z, 1.f);
}
inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w)
@ -301,10 +273,7 @@ inline void LLVector4::set(F32 x, F32 y, F32 z, F32 w)
inline void LLVector4::set(const LLVector4 &vec)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = vec.mV[VW];
set(vec.mV);
}
inline void LLVector4::set(const LLVector3 &vec, F32 w)
@ -322,7 +291,6 @@ inline void LLVector4::set(const F32 *vec)
mV[VZ] = vec[VZ];
mV[VW] = vec[VW];
}
inline void LLVector4::set(const glm::vec4& vec)
{
mV[VX] = vec.x;
@ -342,68 +310,53 @@ inline void LLVector4::set(const glm::vec3& vec, F32 w)
// deprecated
inline void LLVector4::setVec(F32 x, F32 y, F32 z)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
mV[VW] = 1.f;
set(x, y, z);
}
// deprecated
inline void LLVector4::setVec(F32 x, F32 y, F32 z, F32 w)
{
mV[VX] = x;
mV[VY] = y;
mV[VZ] = z;
mV[VW] = w;
set(x, y, z, w);
}
// deprecated
inline void LLVector4::setVec(const LLVector4 &vec)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = vec.mV[VW];
set(vec);
}
// deprecated
inline void LLVector4::setVec(const LLVector3 &vec, F32 w)
{
mV[VX] = vec.mV[VX];
mV[VY] = vec.mV[VY];
mV[VZ] = vec.mV[VZ];
mV[VW] = w;
set(vec, w);
}
// deprecated
inline void LLVector4::setVec(const F32 *vec)
{
mV[VX] = vec[VX];
mV[VY] = vec[VY];
mV[VZ] = vec[VZ];
mV[VW] = vec[VW];
set(vec);
}
// LLVector4 Magnitude and Normalization Functions
inline F32 LLVector4::length(void) const
inline F32 LLVector4::length(void) const
{
return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
return (F32) sqrt(lengthSquared());
}
inline F32 LLVector4::lengthSquared(void) const
inline F32 LLVector4::lengthSquared(void) const
{
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
inline F32 LLVector4::magVec(void) const
inline F32 LLVector4::magVec(void) const
{
return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
return length();
}
inline F32 LLVector4::magVecSquared(void) const
inline F32 LLVector4::magVecSquared(void) const
{
return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
return lengthSquared();
}
// LLVector4 Operators
@ -422,7 +375,7 @@ inline LLVector4 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)
@ -495,11 +448,7 @@ inline const LLVector4& operator*=(LLVector4 &a, F32 k)
inline const LLVector4& operator/=(LLVector4 &a, F32 k)
{
F32 t = 1.f / k;
a.mV[VX] *= t;
a.mV[VY] *= t;
a.mV[VZ] *= t;
return a;
return a *= 1.f / k;
}
inline LLVector4 operator-(const LLVector4 &a)
@ -517,16 +466,16 @@ inline LLVector4::operator glm::vec4() const
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;
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;
return (vec.lengthSquared());
return vec.lengthSquared();
}
inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u)
@ -538,17 +487,13 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u)
a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u);
}
inline F32 LLVector4::normalize(void)
inline F32 LLVector4::normalize(void)
{
F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
mV[VZ] *= oomag;
*this /= mag;
}
else
{
@ -557,34 +502,18 @@ inline F32 LLVector4::normalize(void)
mV[2] = 0.f;
mag = 0;
}
return (mag);
return mag;
}
// deprecated
inline F32 LLVector4::normVec(void)
inline F32 LLVector4::normVec(void)
{
F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
F32 oomag;
if (mag > FP_MAG_THRESHOLD)
{
oomag = 1.f/mag;
mV[VX] *= oomag;
mV[VY] *= oomag;
mV[VZ] *= oomag;
}
else
{
mV[0] = 0.f;
mV[1] = 0.f;
mV[2] = 0.f;
mag = 0;
}
return (mag);
return normalize();
}
// Because apparently some parts of the viewer use this for color info.
inline const LLVector4 srgbVector4(const LLVector4 &a) {
inline const LLVector4 srgbVector4(const LLVector4 &a)
{
LLVector4 srgbColor;
srgbColor.mV[0] = linearTosRGB(a.mV[0]);

View File

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

View File

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

View File

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

View File

@ -480,7 +480,11 @@ public:
bool getForceShowingUnmatchedItems();
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.

View File

@ -31,11 +31,12 @@
#include "llfolderviewitem.h"
#include "llfolderview.h"
#include "llfolderviewmodel.h"
#include "llpanel.h"
#include "llcallbacklist.h"
#include "llcriticaldamp.h"
#include "llclipboard.h"
#include "llfocusmgr.h" // gFocusMgr
#include "llnotificationsutil.h"
#include "llpanel.h"
#include "lltrans.h"
#include "llwindow.h"
@ -61,6 +62,8 @@ S32 LLFolderViewItem::sTopPad = 0;
LLUIImagePtr LLFolderViewItem::sFolderArrowImg;
LLUIImagePtr LLFolderViewItem::sSelectionImg;
LLFontGL* LLFolderViewItem::sSuffixFont = nullptr;
LLUIColor LLFolderViewItem::sFavoriteColor;
bool LLFolderViewItem::sColorSetInitialized = false;
// only integers can be initialized in header
const F32 LLFolderViewItem::FOLDER_CLOSE_TIME_CONSTANT = 0.02f;
@ -129,13 +132,15 @@ void LLFolderViewItem::cleanupClass()
LLFolderViewItem::Params::Params()
: root(),
listener(),
favorite_image("favorite_image"),
favorite_content_image("favorite_content_image"),
folder_arrow_image("folder_arrow_image"),
folder_indentation("folder_indentation"),
selection_image("selection_image"),
item_height("item_height"),
item_top_pad("item_top_pad"),
creation_date(),
allow_wear("allow_wear", true),
marketplace_item("marketplace_item", false),
allow_drop("allow_drop", true),
font_color("font_color"),
font_highlight_color("font_highlight_color"),
@ -155,6 +160,8 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
: LLView(p),
mLabelWidth(0),
mLabelWidthDirty(false),
mIsFavorite(false),
mHasFavorites(false),
mSuffixNeedsRefresh(false),
mLabelPaddingRight(DEFAULT_LABEL_PADDING_RIGHT),
mParentFolder( NULL ),
@ -175,7 +182,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mRoot(p.root),
mViewModelItem(p.listener),
mIsMouseOverTitle(false),
mAllowWear(p.allow_wear),
mMarketplaceItem(p.marketplace_item),
mAllowDrop(p.allow_drop),
mFontColor(p.font_color),
mFontHighlightColor(p.font_highlight_color),
@ -189,6 +196,21 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mMaxFolderItemOverlap(p.max_folder_item_overlap),
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)
{
mViewModelItem->setFolderViewItem(this);
@ -211,6 +233,7 @@ bool LLFolderViewItem::postBuild()
// getDisplayName() is expensive (due to internal getLabelSuffix() and name building)
// it also sets search strings so it requires a filter reset
mLabel = utf8str_to_wstring(vmi->getDisplayName());
mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
setToolTip(vmi->getName());
// Dirty the filter flag of the model from the view (CHUI-849)
@ -325,6 +348,7 @@ void LLFolderViewItem::refresh()
mLabel = utf8str_to_wstring(vmi.getDisplayName());
mLabelFontBuffer.reset();
mIsFavorite = vmi.isFavorite() && !vmi.isItemInTrash();
setToolTip(vmi.getName());
// icons are slightly expensive to get, can be optimized
// see LLInventoryIcon::getIcon()
@ -359,6 +383,8 @@ void LLFolderViewItem::refreshSuffix()
mIconOpen = vmi->getIconOpen();
mIconOverlay = vmi->getIconOverlay();
mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
if (mRoot->useLabelSuffix())
{
// Very Expensive!
@ -554,10 +580,15 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags)
void LLFolderViewItem::openItem( void )
{
if (mAllowWear || !getViewModelItem()->isItemWearable())
if (!mMarketplaceItem || !getViewModelItem()->isItemWearable())
{
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)
@ -771,6 +802,32 @@ void LLFolderViewItem::drawOpenFolderArrow()
}
}
void LLFolderViewItem::drawFavoriteIcon(const Params& default_params, const LLUIColor& fg_color)
{
static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true);
static LLUICachedControl<bool> draw_hollow_star("InventoryFavoritesUseHollowStar", true);
LLUIImage* favorite_image = NULL;
if (draw_star && mIsFavorite)
{
favorite_image = default_params.favorite_image;
}
else if (draw_hollow_star && mHasFavorites && !isOpen())
{
favorite_image = default_params.favorite_content_image;
}
if (favorite_image)
{
const S32 PAD = 3;
const S32 image_size = 14;
gl_draw_scaled_image(
getRect().getWidth() - image_size - PAD, getRect().getHeight() - mItemHeight + PAD,
image_size, image_size, favorite_image->getImage(), fg_color);
}
}
/*virtual*/ bool LLFolderViewItem::isHighlightAllowed()
{
return mIsSelected;
@ -929,6 +986,9 @@ void LLFolderViewItem::draw()
drawOpenFolderArrow();
}
const Params& default_params = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();
drawFavoriteIcon(default_params, sFgColor);
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
//--------------------------------------------------------------------------------//
@ -999,7 +1059,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())
{
@ -1093,7 +1166,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mIsFolderComplete(false), // folder might have children that are not loaded yet.
mAreChildrenInited(false), // folder might have children that are not built yet.
mLastArrangeGeneration( -1 ),
mLastCalculatedWidth(0)
mLastCalculatedWidth(0),
mFavoritesDirtyFlags(0)
{
}
@ -1119,6 +1193,11 @@ LLFolderViewFolder::~LLFolderViewFolder( void )
// The LLView base class takes care of object destruction. make sure that we
// don't have mouse or keyboard focus
gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
if (mFavoritesDirtyFlags)
{
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, this);
}
}
// addToFolder() returns true if it succeeds. false otherwise
@ -1762,6 +1841,128 @@ bool LLFolderViewFolder::isMovable()
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)
{
LL_WARNS() << "Called onIdleUpdateFavorites without dirty flags set" << LL_ENDL;
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)
{
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, parent);
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
}
}
}
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)
{
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, parent);
parent->mFavoritesDirtyFlags = 0;
}
parent = parent->getParentFolder();
}
break;
}
if (parent->mFavoritesDirtyFlags)
{
parent->mFavoritesDirtyFlags = 0;
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, parent);
}
parent = parent->getParentFolder();
}
}
}
bool LLFolderViewFolder::isRemovable()
{

View File

@ -50,7 +50,9 @@ class LLFolderViewItem : public LLView
public:
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;
Mandatory<LLFolderView*> root;
Mandatory<LLFolderViewModelItem*> listener;
@ -60,7 +62,7 @@ public:
item_top_pad;
Optional<time_t> creation_date;
Optional<bool> allow_wear;
Optional<bool> marketplace_item;
Optional<bool> allow_drop;
Optional<LLUIColor> font_color;
@ -93,6 +95,8 @@ protected:
LLWString mLabel;
S32 mLabelWidth;
bool mLabelWidthDirty;
bool mIsFavorite;
bool mHasFavorites;
S32 mLabelPaddingRight;
LLFolderViewFolder* mParentFolder;
LLPointer<LLFolderViewModelItem> mViewModelItem;
@ -122,7 +126,7 @@ protected:
mIsCurSelection,
mDragAndDropTarget,
mIsMouseOverTitle,
mAllowWear,
mMarketplaceItem,
mAllowDrop,
mSingleFolderMode,
mDoubleClickOverride,
@ -133,6 +137,7 @@ protected:
LLUIColor mFontColor;
LLUIColor mFontHighlightColor;
static bool sColorSetInitialized;
// For now assuming all colors are the same in derived classes.
static LLUIColor sFgColor;
@ -145,6 +150,8 @@ protected:
static LLUIColor sFilterTextColor;
static LLUIColor sSuffixColor;
static LLUIColor sSearchStatusColor;
static LLUIColor sFavoriteColor;
// this is an internal method used for adding items to folders. A
// 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
virtual bool isMovable();
bool isFavorite() const { return mIsFavorite; }
// destroys this item recursively
virtual void destroyView();
@ -298,6 +307,7 @@ public:
// virtual void handleDropped();
virtual void draw();
void drawOpenFolderArrow();
void drawFavoriteIcon(const Params& default_params, const LLUIColor& fg_color);
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);
virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
@ -400,6 +410,18 @@ public:
// Returns true is this object and all of its children can be moved
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
virtual void destroyView();
void destroyRoot();

View File

@ -162,6 +162,7 @@ public:
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 isItemRenameable() const = 0;
@ -170,7 +171,8 @@ public:
virtual bool isItemMovable( void ) const = 0; // Can be moved to another folder
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 void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0;
@ -183,6 +185,9 @@ public:
virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0;
virtual bool isAgentInventory() const = 0;
virtual bool isAgentInventoryRoot() const = 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?

View File

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

View File

@ -28,6 +28,7 @@
#include "llmodaldialog.h"
#include "llemojihelper.h"
#include "llfocusmgr.h"
#include "v4color.h"
#include "v2math.h"
@ -35,6 +36,7 @@
#include "llwindow.h"
#include "llkeyboard.h"
#include "llmenugl.h"
// static
std::list<LLModalDialog*> LLModalDialog::sModalStack;
@ -98,7 +100,7 @@ void LLModalDialog::onOpen(const LLSD& key)
{
if (mModal)
{
// If Modal, Hide the active modal dialog
// If Modal, hide the active modal dialog
if (!sModalStack.empty())
{
LLModalDialog* front = sModalStack.front();
@ -155,6 +157,12 @@ void LLModalDialog::setVisible( bool 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.
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])));
}
// static
void LLModalDialog::onAppFocusLost()
{
@ -333,6 +340,7 @@ void LLModalDialog::onAppFocusGained()
}
}
// static
void LLModalDialog::shutdownModals()
{
// This method is only for use during app shutdown. ~LLModalDialog()

View File

@ -265,7 +265,9 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mShowEmojiHelper(p.show_emoji_helper),
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(false),
mKeepSelectionOnReturn(false)
mKeepSelectionOnReturn(false),
mSelectAllOnFocusReceived(false),
mSelectedOnFocusReceived(false)
{
mSourceID.generate();
@ -389,6 +391,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen
setCursorPos(loc);
mIsSelecting = true;
mSelectedOnFocusReceived = false;
mSelectionEnd = mCursorPos;
mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
}
@ -668,6 +671,13 @@ bool LLTextEditor::canSelectAll() const
return true;
}
//virtual
void LLTextEditor::deselect()
{
LLTextBase::deselect();
mSelectedOnFocusReceived = false;
}
// virtual
void LLTextEditor::selectAll()
{
@ -685,6 +695,11 @@ void LLTextEditor::selectByCursorPosition(S32 prev_cursor_pos, S32 next_cursor_p
endSelection();
}
void LLTextEditor::setSelectAllOnFocusReceived(bool b)
{
mSelectAllOnFocusReceived = b;
}
void LLTextEditor::insertEmoji(llwchar emoji)
{
LL_INFOS() << "LLTextEditor::insertEmoji(" << wchar_utf8_preview(emoji) << ")" << LL_ENDL;
@ -762,8 +777,16 @@ bool LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
// Delay cursor flashing
resetCursorBlink();
mSelectedOnFocusReceived = false;
if (handled && !gFocusMgr.getMouseCapture())
{
if (!mask && mSelectAllOnFocusReceived)
{
mIsSelecting = false;
mSelectionStart = getLength();
mSelectionEnd = 0;
mSelectedOnFocusReceived = true;
}
gFocusMgr.setMouseCapture( this );
}
return handled;
@ -2127,6 +2150,11 @@ void LLTextEditor::focusLostHelper()
gEditMenuHandler = NULL;
}
if (mSelectedOnFocusReceived)
{
deselect();
}
if (mCommitOnFocusLost)
{
onCommit();

View File

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

View File

@ -350,10 +350,10 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
LLWindowWin32Thread();
void run() override;
void close() override;
// closes queue, wakes thread, waits until thread closes
void wakeAndDestroy();
// Closes queue, wakes thread, waits until thread closes.
// Call from main thread
bool wakeAndDestroy();
void glReady()
{
@ -410,6 +410,15 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
bool mGLReady = false;
bool mGotGLBuffer = false;
LLAtomicBool mDeleteOnExit = false;
// best guess at available video memory in MB
std::atomic<U32> mAvailableVRAM;
U32 mMaxVRAM = 0; // maximum amount of vram to allow in the "budget", or 0 for no maximum (see updateVRAMUsage)
IDXGIAdapter3* mDXGIAdapter = nullptr;
LPDIRECT3D9 mD3D = nullptr;
LPDIRECT3DDEVICE9 mD3DDevice = nullptr;
};
@ -853,6 +862,7 @@ LLWindowWin32::~LLWindowWin32()
}
delete mDragDrop;
mDragDrop = NULL;
delete [] mWindowTitle;
mWindowTitle = NULL;
@ -864,6 +874,7 @@ LLWindowWin32::~LLWindowWin32()
mWindowClassName = NULL;
delete mWindowThread;
mWindowThread = NULL;
}
void LLWindowWin32::show()
@ -982,7 +993,11 @@ void LLWindowWin32::close()
mhDC = NULL;
mWindowHandle = NULL;
mWindowThread->wakeAndDestroy();
if (mWindowThread->wakeAndDestroy())
{
// thread will delete itselfs once done
mWindowThread = NULL;
}
}
bool LLWindowWin32::isValid()
@ -3104,10 +3119,14 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
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;
if (u_msg == WM_DESTROY)
{
PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0
return 0;
}
}
// pass unhandled messages down to Windows
@ -4571,25 +4590,11 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
#endif // LL_WINDOWS
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();
}
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
* log with repeated messages, especially in a tight loop. It refuses to log
@ -4804,14 +4809,19 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
#endif
}
if (mDeleteOnExit)
{
delete this;
}
}
void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
{
if (mQueue->isClosed())
{
LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
return;
return false;
}
// Make sure we don't leave a blank toolbar button.
@ -4822,33 +4832,33 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
// Schedule destruction
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;
}
{
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*
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;
mGLReady = false;
});
// 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;
mGLReady = false;
});
LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
mQueue->close();
@ -4906,6 +4916,7 @@ void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
}
}
LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
return true;
}
void LLWindowWin32::post(const std::function<void()>& func)

View File

@ -335,6 +335,7 @@ set(viewer_SOURCE_FILES
llhudeffectpointat.cpp
llhudeffecttrail.cpp
llhudeffectblob.cpp
llhudeffectresetskeleton.cpp
llhudicon.cpp
llhudmanager.cpp
llhudnametag.cpp
@ -1005,6 +1006,7 @@ set(viewer_HEADER_FILES
llhudeffectpointat.h
llhudeffecttrail.h
llhudeffectblob.h
llhudeffectresetskeleton.h
llhudicon.h
llhudmanager.h
llhudnametag.h

View File

@ -1853,6 +1853,17 @@
<key>Value</key>
<integer>0</integer>
</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>
<map>
<key>Comment</key>
@ -14119,10 +14130,32 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>OutfitGallerySortByName</key>
<key>OutfitGallerySortOrder</key>
<map>
<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>
<integer>1</integer>
<key>Type</key>
@ -16003,6 +16036,50 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>InventoryFavoritesUseStar</key>
<map>
<key>Comment</key>
<string>Show star near favorited items in inventory</string>
<key>Persist</key>
<integer>0</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>0</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>0</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>0</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>StatsReportMaxDuration</key>
<map>
<key>Comment</key>

View File

@ -329,7 +329,7 @@
<key>KeepConversationLogTranscripts</key>
<map>
<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>
<integer>1</integer>
<key>Type</key>

View File

@ -213,6 +213,7 @@ void GLTFSceneManager::uploadSelection()
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost,
LLUUID::null,
false,
finish,
failure));
@ -276,6 +277,7 @@ void GLTFSceneManager::uploadSelection()
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost,
LLUUID::null,
false,
finish,
failure));
@ -552,6 +554,7 @@ void GLTFSceneManager::update()
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost,
LLUUID::null,
false,
finish,
failure));

View File

@ -121,8 +121,8 @@ const F32 MIN_FIDGET_TIME = 8.f; // seconds
const F32 MAX_FIDGET_TIME = 20.f; // seconds
const S32 UI_FEATURE_VERSION = 1;
// For version 1: 1 - inventory, 2 - gltf
const S32 UI_FEATURE_FLAGS = 3;
// For version 1, flag holds: 1 - inventory thumbnails, 2 - gltf, 4 - inventory favorites
const S32 UI_FEATURE_FLAGS = 7;
// The agent instance.
LLAgent gAgent;
@ -223,7 +223,6 @@ private:
LLVector3d mPosGlobal;
};
class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation
{
public:
@ -604,7 +603,7 @@ void LLAgent::getFeatureVersionAndFlags(S32& version, S32& flags)
if (feature_version.isInteger())
{
version = feature_version.asInteger();
flags = 1; // inventory flag
flags = 3; // show 'favorites' notification
}
else if (feature_version.isMap())
{
@ -630,13 +629,8 @@ void LLAgent::showLatestFeatureNotification(const std::string key)
if (key == "inventory")
{
// Notify user about new thumbnail support
flag = 1;
}
if (key == "gltf")
{
flag = 2;
// Notify user about new favorites support
flag = 4;
}
if ((flags & flag) == 0)
@ -843,7 +837,6 @@ void LLAgent::movePitch(F32 mag)
}
}
// Does this parcel allow you to fly?
bool LLAgent::canFly()
{
@ -923,7 +916,6 @@ void LLAgent::setFlying(bool fly, bool fail_sound)
LLFloaterMove::setFlyingMode(fly);
}
// UI based mechanism of setting fly state
//-----------------------------------------------------------------------------
// toggleFlying()
@ -1002,7 +994,6 @@ void LLAgent::capabilityReceivedCallback(const LLUUID &region_id, LLViewerRegion
}
}
//-----------------------------------------------------------------------------
// setRegion()
//-----------------------------------------------------------------------------
@ -1108,7 +1099,6 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
mRegionChangedSignal();
}
//-----------------------------------------------------------------------------
// getRegion()
//-----------------------------------------------------------------------------
@ -1117,7 +1107,6 @@ LLViewerRegion *LLAgent::getRegion() const
return mRegionp;
}
LLHost LLAgent::getRegionHost() const
{
if (mRegionp)
@ -1148,7 +1137,6 @@ bool LLAgent::inPrelude()
return mRegionp && mRegionp->isPrelude();
}
std::string LLAgent::getRegionCapability(const std::string &name)
{
if (!mRegionp)
@ -1157,7 +1145,6 @@ std::string LLAgent::getRegionCapability(const std::string &name)
return mRegionp->getCapability(name);
}
//-----------------------------------------------------------------------------
// canManageEstate()
//-----------------------------------------------------------------------------
@ -1185,7 +1172,6 @@ void LLAgent::sendMessage()
gMessageSystem->sendMessage(mRegionp->getHost());
}
//-----------------------------------------------------------------------------
// sendReliableMessage()
//-----------------------------------------------------------------------------
@ -1219,7 +1205,6 @@ LLVector3 LLAgent::getVelocity() const
}
}
//-----------------------------------------------------------------------------
// setPositionAgent()
//-----------------------------------------------------------------------------
@ -1293,7 +1278,6 @@ const LLVector3 &LLAgent::getPositionAgent()
}
}
return mFrameAgent.getOrigin();
}
@ -1302,7 +1286,6 @@ boost::signals2::connection LLAgent::whenPositionChanged(position_signal_t::slot
return mOnPositionChanged.connect(fn);
}
//-----------------------------------------------------------------------------
// getRegionsVisited()
//-----------------------------------------------------------------------------
@ -1319,7 +1302,6 @@ F64 LLAgent::getDistanceTraveled() const
return mDistanceTraveled;
}
//-----------------------------------------------------------------------------
// getPosAgentFromGlobal()
//-----------------------------------------------------------------------------
@ -1330,7 +1312,6 @@ LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const
return pos_agent;
}
//-----------------------------------------------------------------------------
// getPosGlobalFromAgent()
//-----------------------------------------------------------------------------
@ -1346,7 +1327,6 @@ void LLAgent::sitDown()
setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
}
//-----------------------------------------------------------------------------
// resetAxes()
//-----------------------------------------------------------------------------
@ -1355,7 +1335,6 @@ void LLAgent::resetAxes()
mFrameAgent.resetAxes();
}
// Copied from LLCamera::setOriginAndLookAt
// Look_at must be unit vector
//-----------------------------------------------------------------------------
@ -1384,7 +1363,6 @@ void LLAgent::resetAxes(const LLVector3 &look_at)
mFrameAgent.setAxes(look_at, left, up);
}
//-----------------------------------------------------------------------------
// rotate()
//-----------------------------------------------------------------------------
@ -1393,7 +1371,6 @@ void LLAgent::rotate(F32 angle, const LLVector3 &axis)
mFrameAgent.rotate(angle, axis);
}
//-----------------------------------------------------------------------------
// rotate()
//-----------------------------------------------------------------------------
@ -1402,7 +1379,6 @@ void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z)
mFrameAgent.rotate(angle, x, y, z);
}
//-----------------------------------------------------------------------------
// rotate()
//-----------------------------------------------------------------------------
@ -1411,7 +1387,6 @@ void LLAgent::rotate(const LLMatrix3 &matrix)
mFrameAgent.rotate(matrix);
}
//-----------------------------------------------------------------------------
// rotate()
//-----------------------------------------------------------------------------
@ -1420,7 +1395,6 @@ void LLAgent::rotate(const LLQuaternion &quaternion)
mFrameAgent.rotate(quaternion);
}
//-----------------------------------------------------------------------------
// getReferenceUpVector()
//-----------------------------------------------------------------------------
@ -1449,7 +1423,6 @@ LLVector3 LLAgent::getReferenceUpVector()
return up_vector;
}
// Radians, positive is forward into ground
//-----------------------------------------------------------------------------
// pitch()
@ -1493,7 +1466,6 @@ void LLAgent::pitch(F32 angle)
}
}
//-----------------------------------------------------------------------------
// roll()
//-----------------------------------------------------------------------------
@ -1502,7 +1474,6 @@ void LLAgent::roll(F32 angle)
mFrameAgent.roll(angle);
}
//-----------------------------------------------------------------------------
// yaw()
//-----------------------------------------------------------------------------
@ -1514,7 +1485,6 @@ void LLAgent::yaw(F32 angle)
}
}
// Returns a quat that represents the rotation of the agent in the absolute frame
//-----------------------------------------------------------------------------
// getQuat()
@ -1540,7 +1510,6 @@ void LLAgent::setControlFlags(U32 mask)
mControlFlags |= mask;
}
//-----------------------------------------------------------------------------
// clearControlFlags()
//-----------------------------------------------------------------------------
@ -1628,7 +1597,6 @@ bool LLAgent::isDoNotDisturb() const
return mIsDoNotDisturb;
}
//-----------------------------------------------------------------------------
// startAutoPilotGlobal()
//-----------------------------------------------------------------------------
@ -1734,7 +1702,6 @@ void LLAgent::startAutoPilotGlobal(
mAutoPilotNoProgressFrameCount = 0;
}
//-----------------------------------------------------------------------------
// setAutoPilotTargetGlobal
//-----------------------------------------------------------------------------
@ -1788,7 +1755,6 @@ void LLAgent::startFollowPilot(const LLUUID &leader_id, bool allow_flying, F32 s
allow_flying);
}
//-----------------------------------------------------------------------------
// stopAutoPilot()
//-----------------------------------------------------------------------------
@ -1830,7 +1796,6 @@ void LLAgent::stopAutoPilot(bool user_cancel)
}
}
// Returns necessary agent pitch and yaw changes, radians.
//-----------------------------------------------------------------------------
// autoPilot()
@ -2019,7 +1984,6 @@ void LLAgent::autoPilot(F32 *delta_yaw)
}
}
//-----------------------------------------------------------------------------
// propagate()
//-----------------------------------------------------------------------------
@ -2040,18 +2004,19 @@ void LLAgent::propagate(const F32 dt)
}
// handle rotation based on keyboard levels
constexpr F32 YAW_RATE = 90.f * DEG_TO_RAD; // radians per second
F32 angle = YAW_RATE * gAgentCamera.getYawKey() * dt;
if (fabs(angle) > 0.0f)
if (fabs(dt) > 1e-6)
{
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
angle = PITCH_RATE * gAgentCamera.getPitchKey() * dt;
if (fabs(angle) > 0.0f)
{
pitch(angle);
if (fabs(gAgentCamera.getPitchKey()) > 1e-6)
{
static const F32 PITCH_RATE = 90.f * DEG_TO_RAD; // radians per second
pitch(PITCH_RATE * gAgentCamera.getPitchKey() * dt);
}
}
// handle auto-land behavior
@ -2213,7 +2178,6 @@ void LLAgent::clearRenderState(U8 clearstate)
mRenderState &= ~clearstate;
}
//-----------------------------------------------------------------------------
// getRenderState()
//-----------------------------------------------------------------------------
@ -2255,6 +2219,7 @@ void LLAgent::endAnimationUpdateUI()
{
return;
}
if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode())
{
// We're already done endAnimationUpdateUI for this transition.
@ -2320,7 +2285,6 @@ void LLAgent::endAnimationUpdateUI()
mViewsPushed = false;
}
gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
if( gMorphView )
{
@ -2949,7 +2913,6 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
}
}
void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity)
{
U8 maturity = SIM_ACCESS_MIN;
@ -3019,7 +2982,6 @@ void LLAgent::changeInterestListMode(const std::string &new_mode)
}
}
bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure)
{
if (getRegion())
@ -3346,7 +3308,6 @@ void LLAgent::sendAnimationStateReset()
sendReliableMessage();
}
// 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 it is the region ID, all scripts clear the permissions for this agent
@ -4276,7 +4237,6 @@ void LLAgent::onCapabilitiesReceivedAfterTeleport()
check_merchant_status();
}
void LLAgent::teleportRequest(
const U64& region_handle,
const LLVector3& pos_local,
@ -4385,7 +4345,6 @@ void LLAgent::doTeleportViaLure(const LLUUID& lure_id, bool godlike)
}
}
// James Cook, July 28, 2005
void LLAgent::teleportCancel()
{
@ -4510,7 +4469,6 @@ LLAgent::ETeleportState LLAgent::getTeleportState() const
TELEPORT_NONE : mTeleportState;
}
void LLAgent::setTeleportState(ETeleportState state)
{
if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed))
@ -4555,7 +4513,6 @@ void LLAgent::setTeleportState(ETeleportState state)
}
}
void LLAgent::stopCurrentAnimations()
{
LL_DEBUGS("Avatar") << "Stopping current animations" << LL_ENDL;
@ -4670,7 +4627,6 @@ void LLAgent::stopFidget()
gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP);
}
void LLAgent::requestEnterGodMode()
{
LLMessageSystem* msg = gMessageSystem;
@ -4791,7 +4747,6 @@ void LLAgent::sendAgentUpdateUserInfo(const std::string& directory_visibility)
}
}
void LLAgent::updateAgentUserInfoCoro(std::string capurl, std::string directory_visibility)
{
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;
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
LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, mCameraUpVector, focus_agent);
//LLViewerCamera::getInstance()->updateCameraLocation(mCameraPositionAgent, camera_skyward, focus_agent);
if (!LLViewerCamera::getInstance()->updateCameraLocation(position_agent, mCameraUpVector, focus_agent))
return;
// Change FOV
LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / (1.f + mCameraCurrentFOVZoomFactor));
@ -1476,7 +1475,7 @@ void LLAgentCamera::updateCamera()
// follow camera when in customize mode
if (cameraCustomizeAvatar())
{
setLookAt(LOOKAT_TARGET_FOCUS, NULL, mCameraPositionAgent);
setLookAt(LOOKAT_TARGET_FOCUS, NULL, position_agent);
}
// update the travel distance stat
@ -1495,8 +1494,8 @@ void LLAgentCamera::updateCamera()
LLVector3 head_pos = gAgentAvatarp->mHeadp->getWorldPosition() +
LLVector3(0.08f, 0.f, 0.05f) * gAgentAvatarp->mHeadp->getWorldRotation() +
LLVector3(0.1f, 0.f, 0.f) * gAgentAvatarp->mPelvisp->getWorldRotation();
LLVector3 diff = mCameraPositionAgent - head_pos;
diff = diff * ~gAgentAvatarp->mRoot->getWorldRotation();
LLVector3 diff = position_agent - head_pos;
diff *= ~gAgentAvatarp->mRoot->getWorldRotation();
LLJoint* torso_joint = gAgentAvatarp->mTorsop;
LLJoint* chest_joint = gAgentAvatarp->mChestp;
@ -2266,7 +2265,8 @@ void LLAgentCamera::changeCameraToFollow(bool animate)
mCameraMode = CAMERA_MODE_FOLLOW;
// 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)
{

View File

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

View File

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

View File

@ -839,7 +839,7 @@ void AISAPI::onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD&
if ( (type == UPDATECATEGORY || type == UPDATEITEM)
&& 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);

View File

@ -2042,7 +2042,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
}
// 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
@ -2072,7 +2072,10 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) const
}
else
{
if (warn_on_type_mismatch)
{
LL_WARNS() << "Unexpected wearable type" << LL_ENDL;
}
return false;
}
}
@ -2263,7 +2266,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)
}
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);
@ -3956,7 +3959,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL;
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result);
dump_sequential_xml(gAgentAvatarp->getDebugName() + "_appearance_request_ok", result);
}
} while (bRetry);
@ -3965,7 +3968,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd
/*static*/
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_ENDL;

View File

@ -102,7 +102,7 @@ public:
bool getCanReplaceCOF(const LLUUID& outfit_cat_id);
// 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.
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,

View File

@ -1848,36 +1848,6 @@ bool LLAppViewer::cleanup()
// Clean up before GL is shut down because we might be holding on to objects with texture references
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;
LLViewerObject::cleanupVOClasses();
@ -2038,6 +2008,36 @@ bool LLAppViewer::cleanup()
sTextureFetch->shutDownTextureCacheThread() ;
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;
end_messaging_system();

View File

@ -536,11 +536,12 @@ LLAutoReplaceSettings::AddListResult LLAutoReplaceSettings::replaceList(const LL
S32 search_index;
LLSD targetList;
// 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();
search_index += 1, targetList = mLists[search_index]
search_index += 1
)
{
targetList = mLists[search_index];
if ( targetList.isMap() )
{
if ( listNameMatches( targetList, listName) )

View File

@ -70,7 +70,7 @@ mLatestOverLimitPct(0.0f),
mShowOverLimitAgents(false),
mNotifyOutfitLoading(false),
mLastCofVersion(LLViewerInventoryCategory::VERSION_UNKNOWN),
mLastOutfitRezStatus(-1),
mLastOutfitRezStatus(AV_REZZED_UNKNOWN),
mLastSkeletonSerialNum(-1)
{
mPopUpDelayTimer.resetWithExpiry(OVER_LIMIT_UPDATE_DELAY);

View File

@ -33,6 +33,8 @@
class LLViewerRegion;
enum ERezzedStatus : S32;
struct LLHUDComplexity
{
LLHUDComplexity()
@ -130,7 +132,7 @@ private:
S32 mLastSkeletonSerialNum;
// Used to detect changes in voavatar's rezzed status.
// If value decreases - there were changes in outfit.
S32 mLastOutfitRezStatus;
enum ERezzedStatus mLastOutfitRezStatus;
object_complexity_list_t mObjectComplexityList;
};

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);
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;
}
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;
LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << 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;
LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup "
<< mScaleConstraintFixup << " max legal " << MAX_LEGAL_SIZE
new_scale_fixup = mScaleConstraintFixup*max_legal_size/box_size;
LL_DEBUGS("ConstraintFix") << getDebugName() << " scale fix, box_size " << box_size << " fixup "
<< mScaleConstraintFixup << " max legal " << max_legal_size
<< " -> new scale " << new_scale_fixup << LL_ENDL;
}
}
@ -231,7 +231,7 @@ void LLControlAvatar::matchVolumeTransform()
const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo();
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));
}
#endif

View File

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

View File

@ -79,6 +79,9 @@ public:
virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); }
virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; }
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 renameItem(const std::string& new_name) { mName = new_name; mNeedsRefresh = true; return true; }
virtual bool isItemMovable( void ) const { return false; }

View File

@ -33,6 +33,7 @@
#include "llagentui.h"
#include "llbase64.h"
#include "llcallbacklist.h"
#include "lldate.h"
#include "llenvironment.h"
#include "llimagejpeg.h"
#include "llmediactrl.h"
@ -863,15 +864,7 @@ const std::string LLFloater360Capture::generate_proposed_filename()
filename << "_";
// add in the current HH-MM-SS (with leading 0's) so users can easily save many shots in same folder
std::time_t cur_epoch = std::time(nullptr);
std::tm* tm_time = std::localtime(&cur_epoch);
filename << std::setfill('0') << std::setw(4) << (tm_time->tm_year + 1900);
filename << std::setfill('0') << std::setw(2) << (tm_time->tm_mon + 1);
filename << std::setfill('0') << std::setw(2) << tm_time->tm_mday;
filename << "_";
filename << std::setfill('0') << std::setw(2) << tm_time->tm_hour;
filename << std::setfill('0') << std::setw(2) << tm_time->tm_min;
filename << std::setfill('0') << std::setw(2) << tm_time->tm_sec;
filename << LLDate::now().toLocalDateString("%Y%m%d_%H%M%S");
// the unusual way we save the output image (originates in the
// embedded browser and not the C++ code) means that the system

View File

@ -422,7 +422,13 @@ bool LLFloaterAutoReplaceSettings::callbackNewListName(const LLSD& notification,
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();
LLAutoReplaceSettings::setListName(newList, newName);
@ -508,12 +514,53 @@ bool LLFloaterAutoReplaceSettings::callbackListNameConflict(const LLSD& notifica
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()
{
std::string listName = mListNames->getSelectedValue().asString();
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;
mReplacementsList->deleteSelectedItems(); // remove from the scrolling list

View File

@ -105,6 +105,8 @@ private:
bool callbackNewListName(const LLSD& notification, const LLSD& response);
/// called from the RenameAutoReplaceList notification dialog
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 selectedListIsLast();

View File

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

View File

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

View File

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

View File

@ -72,8 +72,8 @@ const S32 PREVIEW_TEXTURE_HEIGHT = 320;
//-----------------------------------------------------------------------------
// LLFloaterImagePreview()
//-----------------------------------------------------------------------------
LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) :
LLFloaterNameDesc(filename),
LLFloaterImagePreview::LLFloaterImagePreview(const LLSD& args) :
LLFloaterNameDesc(args),
mAvatarPreview(NULL),
mSculptedPreview(NULL),

View File

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

View File

@ -28,9 +28,14 @@
#include "llfloaterinventorysettings.h"
#include "llcolorswatch.h"
#include "llviewercontrol.h"
LLFloaterInventorySettings::LLFloaterInventorySettings(const LLSD& 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()
@ -39,6 +44,29 @@ LLFloaterInventorySettings::~LLFloaterInventorySettings()
bool LLFloaterInventorySettings::postBuild()
{
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;
}
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:
LLFloaterInventorySettings(const LLSD& key);
~LLFloaterInventorySettings();
void updateColorSwatch();
void applyUIColor(LLUICtrl* ctrl, const LLSD& param);
void getUIColor(LLUICtrl* ctrl, const LLSD& param);
};
#endif

View File

@ -349,14 +349,14 @@ void LLFloaterModelPreview::initModelPreview()
}
//static
bool LLFloaterModelPreview::showModelPreview()
void LLFloaterModelPreview::showModelPreview(const LLUUID& dest_folder)
{
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*)LLFloaterReg::getInstance("upload_model");
if (fmp && !fmp->isModelLoading())
{
fmp->setUploadDestination(dest_folder);
fmp->loadHighLodModel();
}
return true;
}
void LLFloaterModelPreview::onUploadOptionChecked(LLUICtrl* ctrl)
@ -505,7 +505,7 @@ void LLFloaterModelPreview::onClickCalculateBtn()
gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale,
childGetValue("upload_textures").asBoolean(),
upload_skinweights, upload_joint_positions, lock_scale_if_joint_position,
mUploadModelUrl, false,
mUploadModelUrl, mDestinationFolderId, false,
getWholeModelFeeObserverHandle());
toggleCalculateButton(false);
@ -1660,7 +1660,7 @@ void LLFloaterModelPreview::onUpload(void* user_data)
gMeshRepo.uploadModel(mp->mModelPreview->mUploadData, mp->mModelPreview->mPreviewScale,
mp->childGetValue("upload_textures").asBoolean(),
upload_skinweights, upload_joint_positions, lock_scale_if_joint_position,
mp->mUploadModelUrl,
mp->mUploadModelUrl, mp->mDestinationFolderId,
true, LLHandle<LLWholeModelFeeObserver>(), mp->getWholeModelUploadObserverHandle());
}
@ -1770,9 +1770,15 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
if (index == LLModelPreview::MESH_OPTIMIZER_AUTO
|| index == LLModelPreview::MESH_OPTIMIZER_SLOPPY
|| index == LLModelPreview::MESH_OPTIMIZER_PRECISE)
{ //rebuild LoD to update triangle counts
{
// rebuild LoD to update triangle counts
onLODParamCommit(lod, true);
}
if (index == LLModelPreview::USE_LOD_ABOVE)
{
// refresh to pick triangle counts
mModelPreview->mDirty = true;
}
}
void LLFloaterModelPreview::resetDisplayOptions()

View File

@ -73,7 +73,8 @@ public:
/*virtual*/ void reshape(S32 width, S32 height, bool called_from_parent = true);
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 handleMouseUp(S32 x, S32 y, MASK mask);
@ -164,9 +165,6 @@ protected:
static void onPhysicsBrowse(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();
@ -225,6 +223,7 @@ private:
void createSmoothComboBox(LLComboBox* combo_box, float min, float max);
LLUUID mDestinationFolderId;
LLButton* mUploadBtn;
LLButton* mCalculateBtn;
LLViewerTextEditor* mUploadLogText;

View File

@ -38,7 +38,9 @@
#include "llcheckboxctrl.h"
#include "llviewerinventory.h"
#include "llenvironment.h"
#include "llnotificationsutil.h"
#include "llparcel.h"
#include "lltrans.h"
#include "llviewerparcelmgr.h"
//=========================================================================
@ -223,16 +225,13 @@ void LLFloaterMyEnvironment::onFilterEdit(const std::string& 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);
for (const LLUUID& itemid: selected)
for (const LLUUID& itemid : item_ids)
{
LLInventoryItem* inv_item = gInventory.getItem(itemid);
@ -253,6 +252,27 @@ void LLFloaterMyEnvironment::onDeleteSelected()
}
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)
@ -318,13 +338,13 @@ bool LLFloaterMyEnvironment::canAction(const std::string &context)
if (context == PARAMETER_EDIT)
{
return (selected.size() == 1) && isSettingSelected(selected.front());
return (selected.size() == 1) && isSettingId(selected.front());
}
else if (context == PARAMETER_COPY)
{
for (std::vector<LLUUID>::iterator it = selected.begin(); it != selected.end(); it++)
{
if(!isSettingSelected(*it))
if(!isSettingId(*it))
{
return false;
}
@ -342,7 +362,7 @@ bool LLFloaterMyEnvironment::canAction(const std::string &context)
LLClipboard::instance().pasteFromClipboard(ids);
for (std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
{
if (!isSettingSelected(*it))
if (!isSettingId(*it))
{
return false;
}
@ -351,7 +371,7 @@ bool LLFloaterMyEnvironment::canAction(const std::string &context)
}
else if (context == PARAMETER_COPYUUID)
{
return (selected.size() == 1) && isSettingSelected(selected.front());
return (selected.size() == 1) && isSettingId(selected.front());
}
return false;
@ -367,16 +387,42 @@ bool LLFloaterMyEnvironment::canApply(const std::string &context)
if (context == PARAMETER_REGION)
{
return LLEnvironment::instance().canAgentUpdateRegionEnvironment();
return isSettingId(selected.front()) && LLEnvironment::instance().canAgentUpdateRegionEnvironment();
}
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_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;
}
bool LLFloaterMyEnvironment::isSettingSelected(LLUUID item_id)
bool LLFloaterMyEnvironment::isSettingId(const LLUUID& item_id)
{
LLInventoryItem* itemp = gInventory.getItem(item_id);

View File

@ -60,6 +60,7 @@ private:
void onFilterCheckChange();
void onFilterEdit(const std::string& search_string);
void onSelectionChange();
void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, uuid_vec_t item_ids);
void onDeleteSelected();
void onDoCreate(const LLSD &data);
void onDoApply(const std::string &context);
@ -69,7 +70,7 @@ private:
void getSelectedIds(uuid_vec_t& ids) const;
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);
};

View File

@ -62,11 +62,20 @@ const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
//-----------------------------------------------------------------------------
// LLFloaterNameDesc()
//-----------------------------------------------------------------------------
LLFloaterNameDesc::LLFloaterNameDesc(const LLSD& filename )
: LLFloater(filename),
mIsAudio(false)
LLFloaterNameDesc::LLFloaterNameDesc(const LLSD& args)
: LLFloater(args)
, 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);
}
@ -203,7 +212,8 @@ void LLFloaterNameDesc::onBtnOK( )
LLFloaterPerms::getNextOwnerPerms("Uploads"),
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost));
expected_upload_cost,
mDestinationFolderId));
upload_new_resource(uploadInfo, callback, nruserdata);
}
@ -230,8 +240,8 @@ void LLFloaterNameDesc::onBtnCancel()
// LLFloaterSoundPreview()
//-----------------------------------------------------------------------------
LLFloaterSoundPreview::LLFloaterSoundPreview(const LLSD& filename )
: LLFloaterNameDesc(filename)
LLFloaterSoundPreview::LLFloaterSoundPreview(const LLSD& args )
: LLFloaterNameDesc(args)
{
mIsAudio = true;
}
@ -251,8 +261,8 @@ bool LLFloaterSoundPreview::postBuild()
// LLFloaterAnimPreview()
//-----------------------------------------------------------------------------
LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& filename )
: LLFloaterNameDesc(filename)
LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& args )
: LLFloaterNameDesc(args)
{
}
@ -270,8 +280,8 @@ bool LLFloaterAnimPreview::postBuild()
// LLFloaterScriptPreview()
//-----------------------------------------------------------------------------
LLFloaterScriptPreview::LLFloaterScriptPreview(const LLSD& filename )
: LLFloaterNameDesc(filename)
LLFloaterScriptPreview::LLFloaterScriptPreview(const LLSD& args )
: LLFloaterNameDesc(args)
{
mIsText = true;
}

View File

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

View File

@ -36,6 +36,14 @@
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
static const std::string lod_strings[4] =
{
"lowest_lod",
"low_lod",
"medium_lod",
"high_lod",
};
// virtual
bool LLCrossParcelFunctor::apply(LLViewerObject* obj)
{
@ -75,7 +83,10 @@ LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
mSelectedOnLand(NULL),
mRezzedOnLand(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");
mTotalCapacity = getChild<LLTextBox>("total_capacity");
mLodLevel = getChild<LLTextBox>("lod_level");
mTrianglesShown = getChild<LLTextBox>("triangles_shown");
mPixelArea = getChild<LLTextBox>("pixel_area");
return true;
}
@ -135,6 +150,69 @@ void LLFloaterObjectWeights::setErrorStatus(S32 status, const std::string& reaso
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)
{
if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty())
@ -252,6 +330,17 @@ void LLFloaterObjectWeights::toggleLandImpactsLoadingIndicators(bool 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()
{
const std::string text = getString("nothing_selected");
@ -269,6 +358,11 @@ void LLFloaterObjectWeights::updateIfNothingSelected()
mRemainingCapacity->setText(text);
mTotalCapacity->setText(text);
mLodLevel->setText(text);
mTrianglesShown->setText(text);
mPixelArea->setText(text);
toggleWeightsLoadingIndicators(false);
toggleLandImpactsLoadingIndicators(false);
toggleRenderLoadingIndicators(false);
}

View File

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

View File

@ -1920,7 +1920,21 @@ void LLFloaterPreference::selectChatPanel()
void LLFloaterPreference::changed()
{
if (LLConversationLog::instance().getIsLoggingEnabled())
{
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
updateDeleteTranscriptsButton();

View File

@ -68,9 +68,10 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
if (!folder->areChildrenInited() || !needsSort(folder->getViewModelItem())) return;
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem());
if (modelp->getUUID().isNull()) return;
LLFolderViewModelItemInventory* sort_modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem());
if (sort_modelp->getUUID().isNull()) return;
bool has_favorites = false;
for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd();
it != end_it;
++it)
@ -79,11 +80,14 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
LLFolderViewFolder* child_folderp = *it;
sort(child_folderp);
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem());
has_favorites |= child_folderp->isFavorite() || child_folderp->hasFavorites();
if (child_folderp->getFoldersCount() > 0)
{
time_t most_recent_folder_time =
static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate();
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem());
LLFolderViewModelItemInventory* folderp = static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem());
time_t most_recent_folder_time = folderp->getCreationDate();
if (most_recent_folder_time > modelp->getCreationDate())
{
modelp->setCreationDate(most_recent_folder_time);
@ -91,16 +95,26 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
}
if (child_folderp->getItemsCount() > 0)
{
time_t most_recent_item_time =
static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate();
LLFolderViewModelItemInventory* itemp = static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem());
time_t most_recent_item_time = itemp->getCreationDate();
LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem());
if (most_recent_item_time > modelp->getCreationDate())
{
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);
}
@ -234,7 +248,7 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite
return continue_filtering;
}
bool LLFolderViewModelItemInventory::filter(LLFolderViewFilter& filter)
bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter)
{
const S32 filter_generation = filter.getCurrentGeneration();
const S32 must_pass_generation = filter.getFirstRequiredGeneration();

View File

@ -48,6 +48,7 @@ public:
virtual bool isItemInTrash( void) const { return false; } // TODO: make into pure virtual.
virtual bool isItemInOutfits() const { return false; }
virtual bool isAgentInventory() const { return false; }
virtual bool isAgentInventoryRoot() const { return false; }
virtual bool isUpToDate() const = 0;
virtual void addChild(LLFolderViewModelItem* child);
virtual bool hasChildren() const = 0;

View File

@ -114,6 +114,11 @@ public:
EType getType() const { return mItemType; }
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:
LLUIImagePtr pIcon;
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 "llhudeffectlookat.h"
#include "llhudeffectpointat.h"
#include "llhudeffectresetskeleton.h"
#include "llhudnametag.h"
#include "llvoicevisualizer.h"
@ -241,6 +242,9 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)
case LL_HUD_EFFECT_BLOB:
hud_objectp = new LLHUDEffectBlob(type);
break;
case LL_HUD_EFFECT_RESET_SKELETON:
hud_objectp = new LLHUDEffectResetSkeleton(type);
break;
default:
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_VOICE_VISUALIZER, // Ventrella
LL_HUD_NAME_TAG,
LL_HUD_EFFECT_BLOB
LL_HUD_EFFECT_BLOB,
LL_HUD_EFFECT_RESET_SKELETON
};
protected:
static void sortObjects();

View File

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

View File

@ -115,7 +115,6 @@ public:
protected:
LLPointer<LLViewerFetchedTexture> m_Image;
S32 mImageBoostLevel = LLGLTexture::BOOST_NONE;
std::string mLoadingText;
};
@ -128,12 +127,8 @@ LLTexturePreviewView::LLTexturePreviewView(const LLView::Params& p)
LLTexturePreviewView::~LLTexturePreviewView()
{
if (m_Image)
{
m_Image->setBoostLevel(mImageBoostLevel);
m_Image = nullptr;
}
}
void LLTexturePreviewView::draw()
{
@ -159,12 +154,11 @@ void LLTexturePreviewView::draw()
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)
{
mImageBoostLevel = m_Image->getBoostLevel();
m_Image->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
m_Image->forceToSaveRawImage(0);
m_Image->setKnownDrawSize(MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);
if ( (!m_Image->isFullyLoaded()) && (!m_Image->hasFetcher()) )
{
if (m_Image->isInFastCacheList())

View File

@ -830,6 +830,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
const LLInventoryObject *obj = getInventoryObject();
bool single_folder_root = (mRoot == NULL);
bool is_cof = isCOFFolder();
bool is_inbox = isInboxFolder();
if (obj)
{
@ -844,7 +846,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Copy"));
}
if (isAgentInventory() && !single_folder_root)
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("Subfolder Separator"));
@ -857,6 +860,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())
{
items.push_back(std::string("Find Original"));
@ -869,6 +885,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (!isItemMovable() || !canMenuCut())
{
disabled_items.push_back(std::string("Cut"));
disabled_items.push_back(std::string("New folder from selected"));
}
}
else
@ -878,7 +895,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
items.push_back(std::string("Find Links"));
}
if (!isInboxFolder() && !single_folder_root)
if (!is_inbox && !single_folder_root)
{
items.push_back(std::string("Rename"));
if (!isItemRenameable() || ((flags & FIRST_SELECTED_ITEM) == 0))
@ -918,6 +935,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (!isItemMovable() || !canMenuCut())
{
disabled_items.push_back(std::string("Cut"));
disabled_items.push_back(std::string("New folder from selected"));
}
if (canListOnMarketplace() && !isMarketplaceListingsFolder() && !isInboxFolder())
@ -940,7 +958,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
// 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"));
}
@ -1334,6 +1352,13 @@ bool LLInvFVBridge::isAgentInventory() const
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
{
return LLAppearanceMgr::instance().getIsInCOF(mUUID);
@ -2281,7 +2306,21 @@ const LLUUID& LLItemBridge::getThumbnailUUID() const
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
{
if (LLViewerInventoryItem* item = getItem())
@ -2426,6 +2465,16 @@ const LLUUID& LLFolderBridge::getThumbnailUUID() const
return LLUUID::null;
}
bool LLFolderBridge::isFavorite() const
{
LLViewerInventoryCategory* cat = getCategory();
if (cat)
{
return cat->getIsFavorite();
}
return false;
}
void LLFolderBridge::update()
{
// we know we have children but haven't fetched them (doesn't obey filter)
@ -4267,6 +4316,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
}
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("create_new"));
}
@ -4292,6 +4342,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 Listing Folder"));
disabled_items.push_back(std::string("upload_options"));
disabled_items.push_back(std::string("upload_def"));
disabled_items.push_back(std::string("create_new"));
}
@ -4358,6 +4409,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
}
if (!isMarketplaceListingsFolder())
{
items.push_back(std::string("upload_options"));
items.push_back(std::string("upload_def"));
items.push_back(std::string("create_new"));
items.push_back(std::string("New Script"));
@ -4391,6 +4443,15 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.push_back(std::string("Rename"));
items.push_back(std::string("thumbnail"));
if (cat->getIsFavorite())
{
items.push_back(std::string("Remove from Favorites"));
}
else
{
items.push_back(std::string("Add to Favorites"));
}
addDeleteContextMenuOptions(items, disabled_items);
// EXT-4030: disallow deletion of currently worn outfit
const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
@ -6883,7 +6944,7 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
else if(item && item->isFinished())
{
// 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(
gAgent.getID(),
item->getPermissions().getOwner(),
@ -8008,7 +8069,8 @@ void LLObjectBridgeAction::attachOrDetach()
}
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.
}
}
@ -8199,6 +8261,7 @@ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
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);
}
@ -8233,6 +8296,51 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge(
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()
{
}
@ -8243,7 +8351,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
menuentry_vec_t disabled_items;
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 Add"));

View File

@ -86,6 +86,7 @@ public:
//--------------------------------------------------------------------
virtual const LLUUID& getUUID() const { return mUUID; }
virtual const LLUUID& getThumbnailUUID() const { return LLUUID::null; }
virtual bool isFavorite() const { return false; }
virtual void clearDisplayName() { mDisplayName.clear(); }
virtual void restoreItem() {}
virtual void restoreToWorld() {}
@ -175,6 +176,7 @@ protected:
bool isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?
bool isAgentInventory() const; // false if lost or in the inventory library
bool isAgentInventoryRoot() const; // true if worn by agent
bool isCOFFolder() const; // true if COF or descendant of
bool isInboxFolder() const; // true if COF or descendant of marketplace inbox
@ -259,6 +261,7 @@ public:
LLViewerInventoryItem* getItem() const;
virtual const LLUUID& getThumbnailUUID() const;
virtual bool isFavorite() const;
protected:
bool confirmRemoveItem(const LLSD& notification, const LLSD& response);
@ -301,6 +304,7 @@ public:
virtual std::string getLabelSuffix() const;
virtual LLFontGL::StyleFlags getLabelStyle() const;
virtual const LLUUID& getThumbnailUUID() const;
virtual bool isFavorite() const;
void setShowDescendantsCount(bool show_count) {mShowDescendantsCount = show_count;}
@ -750,6 +754,45 @@ public:
U32 flags = 0x00) const;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Favorites Inventory Panel related classes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Overridden version of the Inventory-Folder-View-Bridge for Folders
class LLFavoritesFolderBridge : public LLFolderBridge
{
friend class LLInvFVBridgeAction;
public:
// Creates context menu for Folders related to Recent Inventory Panel.
// Uses base logic and than removes from visible items "New..." menu items.
LLFavoritesFolderBridge(LLInventoryType::EType type,
LLInventoryPanel* inventory,
LLFolderView* root,
const LLUUID& uuid) :
LLFolderBridge(inventory, root, uuid)
{
mInvType = type;
}
/*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags);
};
// Bridge builder to create Inventory-Folder-View-Bridge for Recent Inventory Panel
class LLFavoritesInventoryBridgeBuilder : public LLInventoryFolderViewModelBuilder
{
public:
LLFavoritesInventoryBridgeBuilder() {}
// Overrides FolderBridge for Recent Inventory Panel.
// It use base functionality for bridges other than FolderBridge.
virtual LLInvFVBridge* 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;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Marketplace Inventory Panel related classes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -777,7 +820,7 @@ private:
void rez_attachment(LLViewerInventoryItem* item,
LLViewerJointAttachment* attachment,
bool replace = false);
bool replace);
// Move items from an in-world object's "Contents" folder to a specified
// folder in agent inventory.

View File

@ -64,6 +64,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
mFilterUUID(p.uuid),
mFilterLinks(p.links),
mFilterThumbnails(p.thumbnails),
mFilterFavorites(p.favorites),
mSearchVisibility(p.search_visibility)
{
}
@ -159,6 +160,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
passed = passed && checkAgainstCreator(listener);
passed = passed && checkAgainstSearchVisibility(listener);
passed = passed && checkAgainstFilterFavorites(listener->getUUID());
passed = passed && checkAgainstFilterThumbnails(listener->getUUID());
return passed;
@ -221,6 +223,19 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
return false;
}
const LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id);
if (cat && cat->getIsFavorite())
{
if (mFilterOps.mFilterFavorites == FILTER_ONLY_FAVORITES)
{
return true;
}
if (mFilterOps.mFilterFavorites == FILTER_EXCLUDE_FAVORITES)
{
return false;
}
}
// Marketplace folder filtering
const U32 filterTypes = mFilterOps.mFilterTypes;
const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE |
@ -273,6 +288,16 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
}
}
if (filterTypes & FILTERTYPE_NO_TRASH_ITEMS)
{
const LLUUID trash_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
// If not a descendant of the marketplace listings root, then the nesting depth is -1 by definition
if (gInventory.isObjectDescendentOf(folder_id, trash_uuid))
{
return false;
}
}
// show folder links
LLViewerInventoryItem* item = gInventory.getItem(folder_id);
if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER)
@ -611,6 +636,24 @@ bool LLInventoryFilter::checkAgainstFilterThumbnails(const LLUUID& object_id) co
return true;
}
bool LLInventoryFilter::checkAgainstFilterFavorites(const LLUUID& object_id) const
{
const LLInventoryObject* object = gInventory.getObject(object_id);
if (!object) return true;
if (mFilterOps.mFilterFavorites != FILTER_INCLUDE_FAVORITES)
{
bool is_favorite = get_is_favorite(object);
if (is_favorite && (mFilterOps.mFilterFavorites == FILTER_EXCLUDE_FAVORITES))
return false;
if (!is_favorite && (mFilterOps.mFilterFavorites == FILTER_ONLY_FAVORITES))
return false;
}
return true;
}
bool LLInventoryFilter::checkAgainstCreator(const LLFolderViewModelItemInventory* listener) const
{
if (!listener)
@ -811,6 +854,32 @@ void LLInventoryFilter::setFilterThumbnails(U64 filter_thumbnails)
mFilterOps.mFilterThumbnails = filter_thumbnails;
}
void LLInventoryFilter::setFilterFavorites(U64 filter_favorites)
{
if (mFilterOps.mFilterFavorites != filter_favorites)
{
if (mFilterOps.mFilterFavorites == FILTER_EXCLUDE_FAVORITES
&& filter_favorites == FILTER_ONLY_FAVORITES)
{
setModified(FILTER_RESTART);
}
else if (mFilterOps.mFilterFavorites == FILTER_ONLY_FAVORITES
&& filter_favorites == FILTER_EXCLUDE_FAVORITES)
{
setModified(FILTER_RESTART);
}
else if (mFilterOps.mFilterFavorites == FILTER_INCLUDE_FAVORITES)
{
setModified(FILTER_MORE_RESTRICTIVE);
}
else
{
setModified(FILTER_LESS_RESTRICTIVE);
}
}
mFilterOps.mFilterFavorites = filter_favorites;
}
void LLInventoryFilter::setFilterEmptySystemFolders()
{
mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS;
@ -923,6 +992,11 @@ void LLInventoryFilter::toggleSearchVisibilityLibrary()
}
}
void LLInventoryFilter::setFilterNoTrashFolder()
{
mFilterOps.mFilterTypes |= FILTERTYPE_NO_TRASH_ITEMS;
}
void LLInventoryFilter::setFilterNoMarketplaceFolder()
{
mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS;
@ -1615,6 +1689,11 @@ U64 LLInventoryFilter::getFilterThumbnails() const
return mFilterOps.mFilterThumbnails;
}
U64 LLInventoryFilter::getFilterFavorites() const
{
return mFilterOps.mFilterFavorites;
}
bool LLInventoryFilter::hasFilterString() const
{
return mFilterSubString.size() > 0;

View File

@ -61,6 +61,7 @@ public:
FILTERTYPE_NO_MARKETPLACE_ITEMS = 0x1 << 10, // pass iff folder is not under the marketplace
FILTERTYPE_WORN = 0x1 << 11, // pass if item is worn
FILTERTYPE_SETTINGS = 0x1 << 12, // pass if the item is a settings object
FILTERTYPE_NO_TRASH_ITEMS = 0x1 << 13, // pass iff folder is not under the marketplace
};
enum EFilterDateDirection
@ -83,6 +84,13 @@ public:
FILTER_ONLY_THUMBNAILS
};
enum EFilterFavorite
{
FILTER_INCLUDE_FAVORITES,
FILTER_EXCLUDE_FAVORITES,
FILTER_ONLY_FAVORITES
};
enum ESortOrderType
{
SO_NAME = 0, // Sort inventory by name
@ -149,6 +157,7 @@ public:
Optional<PermissionMask> permissions;
Optional<EFilterCreatorType> creator_type;
Optional<EFilterThumbnail> thumbnails;
Optional<EFilterFavorite> favorites;
Params()
: types("filter_types", FILTERTYPE_OBJECT),
@ -156,6 +165,7 @@ public:
wearable_types("wearable_types", 0xffffFFFFffffFFFFULL),
settings_types("settings_types", 0xffffFFFFffffFFFFULL),
thumbnails("thumbnails", FILTER_INCLUDE_THUMBNAILS),
favorites("favorites", FILTER_INCLUDE_FAVORITES),
category_types("category_types", 0xffffFFFFffffFFFFULL),
links("links", FILTERLINK_INCLUDE_LINKS),
search_visibility("search_visibility", 0xFFFFFFFF),
@ -177,6 +187,7 @@ public:
mFilterWearableTypes,
mFilterSettingsTypes, // for _SETTINGS
mFilterThumbnails,
mFilterFavorites,
mFilterLinks,
mFilterCategoryTypes; // For _CATEGORY
LLUUID mFilterUUID; // for UUID
@ -220,6 +231,7 @@ public:
U64 getFilterSettingsTypes() const;
U64 getSearchVisibilityTypes() const;
U64 getFilterThumbnails() const;
U64 getFilterFavorites() const;
bool isFilterObjectTypesWith(LLInventoryType::EType t) const;
void setFilterObjectTypes(U64 types);
@ -233,8 +245,10 @@ public:
void setFilterMarketplaceInactiveFolders();
void setFilterMarketplaceUnassociatedFolders();
void setFilterMarketplaceListingFolders(bool select_only_listing_folders);
void setFilterNoTrashFolder();
void setFilterNoMarketplaceFolder();
void setFilterThumbnails(U64 filter_thumbnails);
void setFilterFavorites(U64 filter_favorites);
void updateFilterTypes(U64 types, U64& current_types);
void setSearchType(ESearchType type);
ESearchType getSearchType() { return mSearchType; }
@ -339,6 +353,7 @@ public:
LLInventoryFilter& operator =(const LLInventoryFilter& other);
bool checkAgainstFilterThumbnails(const LLUUID& object_id) const;
bool checkAgainstFilterFavorites(const LLUUID& object_id) const;
private:
bool areDateLimitsSet();

View File

@ -51,6 +51,7 @@
#include "lldirpicker.h"
#include "lldonotdisturbnotificationstorage.h"
#include "llfloatermarketplacelistings.h"
#include "llfloatermodelpreview.h"
#include "llfloatersidepanelcontainer.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
@ -62,6 +63,7 @@
#include "llinventorymodel.h"
#include "llinventorypanel.h"
#include "lllineeditor.h"
#include "llmaterialeditor.h"
#include "llmarketplacenotifications.h"
#include "llmarketplacefunctions.h"
#include "llmenugl.h"
@ -86,6 +88,7 @@
#include "llviewermessage.h"
#include "llviewerfoldertype.h"
#include "llviewerobjectlist.h"
#include "llviewermenufile.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llvoavatarself.h"
@ -2418,6 +2421,143 @@ void ungroup_folder_items(const LLUUID& folder_id)
gInventory.notifyObservers();
}
class LLUpdateFavorite : public LLInventoryCallback
{
public:
LLUpdateFavorite(const LLUUID& inv_item_id)
: mInvItemID(inv_item_id)
{}
/* virtual */ void fire(const LLUUID& inv_item_id) override
{
gInventory.addChangedMask(LLInventoryObserver::UPDATE_FAVORITE, mInvItemID);
LLInventoryModel::item_array_t items;
LLInventoryModel::cat_array_t cat_array;
LLLinkedItemIDMatches matches(mInvItemID);
gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
cat_array,
items,
LLInventoryModel::INCLUDE_TRASH,
matches);
std::set<LLUUID> link_ids;
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it)
{
LLPointer<LLViewerInventoryItem> item = *it;
gInventory.addChangedMask(LLInventoryObserver::UPDATE_FAVORITE, item->getUUID());
}
gInventory.notifyObservers();
}
private:
LLUUID mInvItemID;
};
void favorite_send(LLInventoryObject* obj, const LLUUID& obj_id, bool favorite)
{
LLSD updates;
if (favorite)
{
updates["favorite"] = LLSD().with("toggled", true);
}
else
{
updates["favorite"] = LLSD();
}
LLPointer<LLInventoryCallback> cb = new LLUpdateFavorite(obj_id);
LLViewerInventoryCategory* view_folder = dynamic_cast<LLViewerInventoryCategory*>(obj);
if (view_folder)
{
update_inventory_category(obj_id, updates, cb);
}
LLViewerInventoryItem* view_item = dynamic_cast<LLViewerInventoryItem*>(obj);
if (view_item)
{
update_inventory_item(obj_id, updates, cb);
}
}
bool get_is_favorite(const LLInventoryObject* object)
{
if (object->getIsLinkType())
{
LLInventoryObject* obj = gInventory.getObject(object->getLinkedUUID());
return obj && obj->getIsFavorite();
}
return object->getIsFavorite();
}
bool get_is_favorite(const LLUUID& obj_id)
{
LLInventoryObject* object = gInventory.getObject(obj_id);
if (object && object->getIsLinkType())
{
LLInventoryObject* obj = gInventory.getObject(object->getLinkedUUID());
return obj && obj->getIsFavorite();
}
return object->getIsFavorite();
}
void set_favorite(const LLUUID& obj_id, bool favorite)
{
LLInventoryObject* obj = gInventory.getObject(obj_id);
if (obj && obj->getIsLinkType())
{
if (!favorite && obj->getIsFavorite())
{
// Links currently aren't supposed to be favorites,
// instead should show state of the original
LL_INFOS("Inventory") << "Recovering proper 'favorites' state of a link " << obj_id << LL_ENDL;
favorite_send(obj, obj_id, false);
}
obj = gInventory.getObject(obj->getLinkedUUID());
}
if (obj && obj->getIsFavorite() != favorite)
{
favorite_send(obj, obj->getUUID(), favorite);
}
}
void toggle_favorite(const LLUUID& obj_id)
{
LLInventoryObject* obj = gInventory.getObject(obj_id);
if (obj && obj->getIsLinkType())
{
obj = gInventory.getObject(obj->getLinkedUUID());
}
if (obj)
{
favorite_send(obj, obj->getUUID(), !obj->getIsFavorite());
}
}
void toggle_favorites(const uuid_vec_t& ids)
{
if (ids.size() == 0)
{
return;
}
if (ids.size() == 1)
{
toggle_favorite(ids[0]);
return;
}
bool new_val = !get_is_favorite(ids.front());
for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
{
set_favorite(*it, new_val);
}
}
std::string get_searchable_description(LLInventoryModel* model, const LLUUID& item_id)
{
if (model)
@ -2713,6 +2853,20 @@ bool LLIsTypeWithPermissions::operator()(LLInventoryCategory* cat, LLInventoryIt
return false;
}
bool LLFavoritesCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
if (item && item->getIsFavorite())
{
return true;
}
if (cat && cat->getIsFavorite())
{
return true;
}
return false;
}
bool LLBuddyCollector::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
@ -3197,7 +3351,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
for (LLInventoryModel::item_array_t::value_type& item : items)
{
if (get_is_item_worn(item))
if (!item->getIsLinkType() && get_is_item_worn(item))
{
has_worn = true;
LLWearableType::EType type = item->getWearableType();
@ -3217,7 +3371,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
}
}
LLViewerInventoryItem* item = gInventory.getItem(obj_id);
if (item && get_is_item_worn(item))
if (item && !item->getIsLinkType() && get_is_item_worn(item))
{
has_worn = true;
LLWearableType::EType type = item->getWearableType();
@ -3467,6 +3621,20 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
ungroup_folder_items(*ids.begin());
}
}
else if ("add_to_favorites" == action)
{
for (const LLUUID& id : ids)
{
set_favorite(id, true);
}
}
else if ("remove_from_favorites" == action)
{
for (const LLUUID& id : ids)
{
set_favorite(id, false);
}
}
else if ("thumbnail" == action)
{
if (selected_items.size() > 0)
@ -3577,6 +3745,54 @@ void LLInventoryAction::removeItemFromDND(LLFolderView* root)
}
}
void LLInventoryAction::fileUploadLocation(const LLUUID& dest_id, const std::string& action)
{
if (action == "def_model")
{
gSavedPerAccountSettings.setString("ModelUploadFolder", dest_id.asString());
}
else if (action == "def_texture")
{
gSavedPerAccountSettings.setString("TextureUploadFolder", dest_id.asString());
}
else if (action == "def_sound")
{
gSavedPerAccountSettings.setString("SoundUploadFolder", dest_id.asString());
}
else if (action == "def_animation")
{
gSavedPerAccountSettings.setString("AnimationUploadFolder", dest_id.asString());
}
else if (action == "def_pbr_material")
{
gSavedPerAccountSettings.setString("PBRUploadFolder", dest_id.asString());
}
else if (action == "upload_texture")
{
LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2, dest_id), LLFilePicker::FFLOAD_IMAGE, false);
}
else if (action == "upload_sound")
{
LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2, dest_id), LLFilePicker::FFLOAD_WAV, false);
}
else if (action == "upload_animation")
{
LLFilePickerReplyThread::startPicker(boost::bind(&upload_single_file, _1, _2, dest_id), LLFilePicker::FFLOAD_ANIM, false);
}
else if (action == "upload_model")
{
LLFloaterModelPreview::showModelPreview(dest_id);
}
else if (action == "upload_pbr_material")
{
LLMaterialEditor::importMaterial(dest_id);
}
else if (action == "upload_bulk")
{
LLFilePickerReplyThread::startPicker(boost::bind(&upload_bulk, _1, _2, true, dest_id), LLFilePicker::FFLOAD_ALL, true);
}
}
void LLInventoryAction::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);

View File

@ -116,6 +116,11 @@ bool can_move_to_my_outfits(LLInventoryModel* model, LLInventoryCategory* inv_ca
std::string get_localized_folder_name(LLUUID cat_uuid);
void new_folder_window(const LLUUID& folder_id);
void ungroup_folder_items(const LLUUID& folder_id);
bool get_is_favorite(const LLInventoryObject* object);
bool get_is_favorite(const LLUUID& obj_id);
void set_favorite(const LLUUID& obj_id, bool favorite);
void toggle_favorite(const LLUUID& obj_id);
void toggle_favorites(const uuid_vec_t& ids);
std::string get_searchable_description(LLInventoryModel* model, const LLUUID& item_id);
std::string get_searchable_creator_name(LLInventoryModel* model, const LLUUID& item_id);
std::string get_searchable_UUID(LLInventoryModel* model, const LLUUID& item_id);
@ -343,6 +348,18 @@ protected:
LLUUID mGroupID;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFavoritesCollector
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFavoritesCollector : public LLInventoryCollectFunctor
{
public:
LLFavoritesCollector() {}
virtual ~LLFavoritesCollector() {}
virtual bool operator()(LLInventoryCategory* cat,
LLInventoryItem* item);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLBuddyCollector
//
@ -601,6 +618,7 @@ struct LLInventoryAction
static void callback_copySelected(const LLSD& notification, const LLSD& response, class LLInventoryModel* model, class LLFolderView* root, const std::string& action);
static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root);
static void removeItemFromDND(LLFolderView* root);
static void fileUploadLocation(const LLUUID& dest_id, const std::string& action);
static void saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model);

View File

@ -634,7 +634,7 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item)
mItemPanels.pop_back();
}
LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn)
LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn, bool is_favorite)
{
LLInventoryGalleryItem::Params giparams;
giparams.visible = true;
@ -645,6 +645,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L
gitem->setUUID(item_id);
gitem->setGallery(this);
gitem->setType(type, inventory_type, flags, is_link);
gitem->setFavorite(is_favorite);
gitem->setLoadImmediately(mLoadThumbnailsImmediately);
gitem->setThumbnail(thumbnail_id);
gitem->setWorn(is_worn);
@ -937,8 +938,19 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id)
}
bool res = false;
bool is_favorite = get_is_favorite(obj);
LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn);
LLInventoryGalleryItem* item = buildGalleryItem(
name,
item_id,
obj->getType(),
thumbnail_id,
inventory_type,
misc_flags,
obj->getCreationDate(),
obj->getIsLinkType(),
is_worn,
is_favorite);
mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item));
if (mGalleryCreated)
{
@ -975,7 +987,7 @@ void LLInventoryGallery::updateRemovedItem(LLUUID item_id)
mItemBuildQuery.erase(item_id);
}
void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name)
void LLInventoryGallery::updateChangedItemData(LLUUID item_id, std::string name, bool is_favorite)
{
gallery_item_map_t::iterator iter = mItemMap.find(item_id);
if (iter != mItemMap.end())
@ -984,6 +996,7 @@ void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name)
if (item)
{
item->setItemName(name);
item->setFavorite(is_favorite);
}
}
}
@ -1999,7 +2012,7 @@ void LLInventoryGallery::deleteSelection()
for (LLInventoryModel::item_array_t::value_type& item : items)
{
if (get_is_item_worn(item))
if (!item->getIsLinkType() && get_is_item_worn(item))
{
has_worn = true;
LLWearableType::EType type = item->getWearableType();
@ -2020,7 +2033,7 @@ void LLInventoryGallery::deleteSelection()
}
LLViewerInventoryItem* item = gInventory.getItem(id);
if (item && get_is_item_worn(item))
if (item && !item->getIsLinkType() && get_is_item_worn(item))
{
has_worn = true;
LLWearableType::EType type = item->getWearableType();
@ -2333,7 +2346,7 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id)
return;
}
updateChangedItemName(*items_iter, obj->getName());
updateChangedItemData(*items_iter, obj->getName(), get_is_favorite(obj));
mNeedsArrange = true;
}
@ -2849,6 +2862,14 @@ void LLInventoryGalleryItem::setType(LLAssetType::EType type, LLInventoryType::E
getChild<LLIconCtrl>("link_overlay")->setVisible(is_link);
}
void LLInventoryGalleryItem::setFavorite(bool is_favorite)
{
getChild<LLIconCtrl>("fav_icon")->setVisible(is_favorite);
static const LLUIColor text_color = LLUIColorTable::instance().getColor("LabelTextColor", LLColor4::white);
static const LLUIColor favorite_color = LLUIColorTable::instance().getColor("InventoryFavoriteColor", LLColor4::white);
mNameText->setReadOnlyColor(is_favorite ? favorite_color : text_color);
}
void LLInventoryGalleryItem::setThumbnail(LLUUID id)
{
mDefaultImage = id.isNull();

View File

@ -102,7 +102,7 @@ public:
void getCurrentCategories(uuid_vec_t& vcur);
bool updateAddedItem(LLUUID item_id); // returns true if added item is visible
void updateRemovedItem(LLUUID item_id);
void updateChangedItemName(LLUUID item_id, std::string name);
void updateChangedItemData(LLUUID item_id, std::string name, bool is_favorite);
void updateItemThumbnail(LLUUID item_id);
void updateWornItem(LLUUID item_id, bool is_worn);
@ -227,7 +227,7 @@ private:
bool updateRowsIfNeeded();
void updateGalleryWidth();
LLInventoryGalleryItem* buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn);
LLInventoryGalleryItem* buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn, bool is_favorite);
LLInventoryGalleryItem* getItem(const LLUUID& id) const;
void buildGalleryPanel(int row_count);
@ -343,6 +343,7 @@ public:
void setHidden(bool hidden) {mHidden = hidden;}
void setType(LLAssetType::EType type, LLInventoryType::EType inventory_type, U32 flags, bool is_link);
void setFavorite(bool is_favorite);
LLAssetType::EType getAssetType() { return mType; }
void setThumbnail(LLUUID id);
void setGallery(LLInventoryGallery* gallery) { mGallery = gallery; }

View File

@ -250,6 +250,20 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata)
{
ungroup_folder_items(mUUIDs.front());
}
else if ("add_to_favorites" == action)
{
for (const LLUUID& id : mUUIDs)
{
set_favorite(id, true);
}
}
else if ("remove_from_favorites" == action)
{
for (const LLUUID& id : mUUIDs)
{
set_favorite(id, false);
}
}
else if ("replaceoutfit" == action)
{
modify_outfit(false, mUUIDs.front(), &gInventory);
@ -472,22 +486,7 @@ void LLInventoryGalleryContextMenu::onRename(const LLSD& notification, const LLS
void LLInventoryGalleryContextMenu::fileUploadLocation(const LLSD& userdata)
{
const std::string param = userdata.asString();
if (param == "model")
{
gSavedPerAccountSettings.setString("ModelUploadFolder", mUUIDs.front().asString());
}
else if (param == "texture")
{
gSavedPerAccountSettings.setString("TextureUploadFolder", mUUIDs.front().asString());
}
else if (param == "sound")
{
gSavedPerAccountSettings.setString("SoundUploadFolder", mUUIDs.front().asString());
}
else if (param == "animation")
{
gSavedPerAccountSettings.setString("AnimationUploadFolder", mUUIDs.front().asString());
}
LLInventoryAction::fileUploadLocation(mUUIDs.front(), param);
}
bool LLInventoryGalleryContextMenu::canSetUploadLocation(const LLSD& userdata)
@ -766,6 +765,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
{
items.push_back(std::string("New Folder"));
}
items.push_back(std::string("upload_options"));
items.push_back(std::string("upload_def"));
}
@ -774,6 +774,18 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
items.push_back(std::string("New Outfit"));
}
if (!is_trash && !is_in_trash && gInventory.getRootFolderID() != selected_id)
{
if (get_is_favorite(obj))
{
items.push_back(std::string("Remove from Favorites"));
}
else
{
items.push_back(std::string("Add to Favorites"));
}
}
items.push_back(std::string("Subfolder Separator"));
if (!is_system_folder && !isRootFolder())
{
@ -819,6 +831,17 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
if(is_agent_inventory)
{
items.push_back(std::string("Cut"));
if (!is_in_trash)
{
if (get_is_favorite(obj))
{
items.push_back(std::string("Remove from Favorites"));
}
else
{
items.push_back(std::string("Add to Favorites"));
}
}
if (!is_link || !is_cof || !get_is_item_worn(selected_id))
{
items.push_back(std::string("Delete"));
@ -955,6 +978,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
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("create_new"));
}
@ -1005,6 +1029,15 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
disabled_items.push_back(std::string("Marketplace Move"));
}
}
if (get_is_favorite(obj))
{
items.push_back(std::string("Remove from Favorites"));
}
else if (is_agent_inventory)
{
items.push_back(std::string("Add to Favorites"));
}
}
hide_context_entries(*menu, items, disabled_items);

View File

@ -115,7 +115,7 @@ void LLInventoryItemsList::doIdle()
{
if (mRefreshState == REFRESH_COMPLETE) return;
if (isInVisibleChain() || mForceRefresh )
if (isInVisibleChain() || mForceRefresh || !getFilterSubString().empty())
{
refresh();

View File

@ -78,7 +78,7 @@
// Increment this if the inventory contents change in a non-backwards-compatible way.
// For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect.
const S32 LLInventoryModel::sCurrentInvCacheVersion = 3;
const S32 LLInventoryModel::sCurrentInvCacheVersion = 4;
bool LLInventoryModel::sFirstTimeInViewer2 = true;
S32 LLInventoryModel::sPendingSystemFolders = 0;
@ -2806,8 +2806,9 @@ bool LLInventoryModel::loadSkeleton(
cached_ids.insert(tcat->getUUID());
// At the moment download does not provide a thumbnail
// uuid, use the one from cache
// uuid or favorite, use values from cache
tcat->setThumbnailUUID(cat->getThumbnailUUID());
tcat->setFavorite(cat->getIsFavorite());
}
}

View File

@ -749,6 +749,13 @@ void LLInventoryCategoriesObserver::changed(U32 mask)
cat_changed = true;
}
bool is_favorite = category->getIsFavorite();
if (cat_data.mIsFavorite != is_favorite)
{
cat_data.mIsFavorite = is_favorite;
cat_changed = true;
}
// If anything has changed above, fire the callback.
if (cat_changed)
cat_data.mCallback();
@ -766,6 +773,7 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t
S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN;
S32 current_num_known_descendents = LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN;
bool can_be_added = true;
bool favorite = false;
LLUUID thumbnail_id;
LLViewerInventoryCategory* category = gInventory.getCategory(cat_id);
@ -779,6 +787,7 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t
// to a category have been made.
version = category->getVersion();
thumbnail_id = category->getThumbnailUUID();
favorite = category->getIsFavorite();
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
@ -804,11 +813,11 @@ bool LLInventoryCategoriesObserver::addCategory(const LLUUID& cat_id, callback_t
if(init_name_hash)
{
digest_t item_name_hash = gInventory.hashDirectDescendentNames(cat_id);
mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, thumbnail_id, cb, version, current_num_known_descendents,item_name_hash)));
mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, thumbnail_id, favorite, cb, version, current_num_known_descendents,item_name_hash)));
}
else
{
mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, thumbnail_id, cb, version, current_num_known_descendents)));
mCategoryMap.insert(category_map_value_t(cat_id,LLCategoryData(cat_id, thumbnail_id, favorite, cb, version, current_num_known_descendents)));
}
}
@ -821,25 +830,37 @@ void LLInventoryCategoriesObserver::removeCategory(const LLUUID& cat_id)
}
LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
const LLUUID& cat_id, const LLUUID& thumbnail_id, callback_t cb, S32 version, S32 num_descendents)
const LLUUID& cat_id,
const LLUUID& thumbnail_id,
bool is_favorite,
callback_t cb,
S32 version,
S32 num_descendents)
: mCatID(cat_id)
, mCallback(cb)
, mVersion(version)
, mDescendentsCount(num_descendents)
, mThumbnailId(thumbnail_id)
, mIsFavorite(is_favorite)
, mIsNameHashInitialized(false)
{
}
LLInventoryCategoriesObserver::LLCategoryData::LLCategoryData(
const LLUUID& cat_id, const LLUUID& thumbnail_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash)
const LLUUID& cat_id,
const LLUUID& thumbnail_id,
bool is_favorite,
callback_t cb, S32 version,
S32 num_descendents,
const digest_t& name_hash)
: mCatID(cat_id)
, mCallback(cb)
, mVersion(version)
, mDescendentsCount(num_descendents)
, mThumbnailId(thumbnail_id)
, mIsFavorite(is_favorite)
, mIsNameHashInitialized(true)
, mItemNameHash(name_hash)
{

View File

@ -60,6 +60,7 @@ public:
CREATE = 512, // With ADD, item has just been created.
// unfortunately a particular message is still associated with some unique semantics.
UPDATE_CREATE = 1024, // With ADD, item added via UpdateCreateInventoryItem
UPDATE_FAVORITE = 2048, // With ADD, item added via UpdateCreateInventoryItem
ALL = 0xffffffff
};
LLInventoryObserver();
@ -276,12 +277,26 @@ protected:
typedef LLUUID digest_t; // To clarify the actual usage of this "UUID"
struct LLCategoryData
{
LLCategoryData(const LLUUID& cat_id, const LLUUID& thumbnail_id, callback_t cb, S32 version, S32 num_descendents);
LLCategoryData(const LLUUID& cat_id, const LLUUID& thumbnail_id, callback_t cb, S32 version, S32 num_descendents, const digest_t& name_hash);
LLCategoryData(
const LLUUID& cat_id,
const LLUUID& thumbnail_id,
bool is_favorite,
callback_t cb,
S32 version,
S32 num_descendents);
LLCategoryData(
const LLUUID& cat_id,
const LLUUID& thumbnail_id,
bool is_favorite,
callback_t cb,
S32 version,
S32 num_descendents,
const digest_t& name_hash);
callback_t mCallback;
S32 mVersion;
S32 mDescendentsCount;
digest_t mItemNameHash;
bool mIsFavorite;
bool mIsNameHashInitialized;
LLUUID mCatID;
LLUUID mThumbnailId;

View File

@ -55,11 +55,13 @@
#include "llviewerfoldertype.h"
#include "llvoavatarself.h"
class LLInventoryFavoritesItemsPanel;
class LLInventoryRecentItemsPanel;
class LLAssetFilteredInventoryPanel;
static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
static LLDefaultChildRegistry::Register<LLInventoryRecentItemsPanel> t_recent_inventory_panel("recent_inventory_panel");
static LLDefaultChildRegistry::Register<LLInventoryFavoritesItemsPanel> t_favorites_inventory_panel("favorites_inventory_panel");
static LLDefaultChildRegistry::Register<LLAssetFilteredInventoryPanel> t_asset_filtered_inv_panel("asset_filtered_inv_panel");
const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
@ -622,6 +624,19 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
}
}
if (mask & LLInventoryObserver::UPDATE_FAVORITE)
{
if (view_item)
{
view_item->refresh();
LLFolderViewFolder* parent = view_item->getParentFolder();
if (parent)
{
parent->updateHasFavorites(get_is_favorite(model_item));
}
}
}
// We don't typically care which of these masks the item is actually flagged with, since the masks
// may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into
// Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks
@ -650,6 +665,16 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
setSelection(item_id, false);
}
updateFolderLabel(model_item->getParentUUID());
if (get_is_favorite(model_item))
{
LLFolderViewFolder* new_parent = (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());
if (new_parent)
{
new_parent->updateHasFavorites(true);
}
}
}
//////////////////////////////
@ -700,6 +725,12 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
{
old_parent_vmi->dirtyDescendantsFilter();
}
if (view_item->isFavorite())
{
old_parent->updateHasFavorites(false); // favorite was removed
new_parent->updateHasFavorites(true); // favorite was added
}
}
}
}
@ -725,6 +756,10 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
updateFolderLabel(viewmodel_folder->getUUID());
}
}
if (view_item->isFavorite())
{
parent->updateHasFavorites(false); // favorite was removed
}
}
}
}
@ -842,7 +877,23 @@ void LLInventoryPanel::idle(void* user_data)
bool in_visible_chain = panel->isInVisibleChain();
if (!panel->mBuildViewsQueue.empty())
if (!panel->mBuildRootQueue.empty())
{
const F64 max_time = in_visible_chain ? 0.006f : 0.001f; // 6 ms
F64 curent_time = LLTimer::getTotalSeconds();
panel->mBuildViewsEndTime = curent_time + max_time;
while (curent_time < panel->mBuildViewsEndTime
&& !panel->mBuildRootQueue.empty())
{
LLUUID item_id = panel->mBuildRootQueue.back();
panel->mBuildRootQueue.pop_back();
panel->findAndInitRootContent(item_id);
curent_time = LLTimer::getTotalSeconds();
}
}
else if (!panel->mBuildViewsQueue.empty())
{
const F64 max_time = in_visible_chain ? 0.006f : 0.001f; // 6 ms
F64 curent_time = LLTimer::getTotalSeconds();
@ -924,20 +975,9 @@ void LLInventoryPanel::initializeViews(F64 max_time)
mBuildViewsEndTime = curent_time + max_time;
// init everything
LLUUID root_id = getRootFolderID();
if (root_id.notNull())
{
buildNewViews(getRootFolderID());
}
else
{
// Default case: always add "My Inventory" root first, "Library" root second
// If we run out of time, this still should create root folders
buildNewViews(gInventory.getRootFolderID()); // My Inventory
buildNewViews(gInventory.getLibraryRootFolderID()); // Library
}
initRootContent();
if (mBuildViewsQueue.empty())
if (mBuildViewsQueue.empty() && mBuildRootQueue.empty())
{
mViewsInitialized = VIEWS_INITIALIZED;
}
@ -968,6 +1008,22 @@ void LLInventoryPanel::initializeViews(F64 max_time)
}
}
void LLInventoryPanel::initRootContent()
{
LLUUID root_id = getRootFolderID();
if (root_id.notNull())
{
buildNewViews(getRootFolderID());
}
else
{
// Default case: always add "My Inventory" root first, "Library" root second
// If we run out of time, this still should create root folders
buildNewViews(gInventory.getRootFolderID()); // My Inventory
buildNewViews(gInventory.getLibraryRootFolderID()); // Library
}
}
LLFolderViewFolder * LLInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge, bool allow_drop)
{
@ -1739,26 +1795,8 @@ bool LLInventoryPanel::beginIMSession()
void LLInventoryPanel::fileUploadLocation(const LLSD& userdata)
{
const std::string param = userdata.asString();
if (param == "model")
{
gSavedPerAccountSettings.setString("ModelUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
}
else if (param == "texture")
{
gSavedPerAccountSettings.setString("TextureUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
}
else if (param == "sound")
{
gSavedPerAccountSettings.setString("SoundUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
}
else if (param == "animation")
{
gSavedPerAccountSettings.setString("AnimationUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
}
else if (param == "pbr_material")
{
gSavedPerAccountSettings.setString("PBRUploadFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
}
const LLUUID dest = LLFolderBridge::sSelf.get()->getUUID();
LLInventoryAction::fileUploadLocation(dest, param);
}
void LLInventoryPanel::openSingleViewInventory(LLUUID folder_id)
@ -2206,6 +2244,247 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
}
/************************************************************************/
/* Favorites Inventory Panel related class */
/************************************************************************/
static const LLFavoritesInventoryBridgeBuilder FAVORITES_BUILDER;
class LLInventoryFavoritesItemsPanel : public LLInventoryPanel
{
public:
struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
{};
void initFromParams(const Params& p)
{
LLInventoryPanel::initFromParams(p);
// turn off trash
getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_TRASH));
getFilter().setFilterNoTrashFolder();
// turn off marketplace for favorites
getFilter().setFilterNoMarketplaceFolder();
}
void removeItemID(const LLUUID& id) override;
protected:
LLInventoryFavoritesItemsPanel(const Params&);
friend class LLUICtrlFactory;
void findAndInitRootContent(const LLUUID& folder_id) override;
void initRootContent() override;
bool removeFavorite(const LLUUID& id, const LLInventoryObject* model_item);
void itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override;
std::set<LLUUID> mRootContentIDs;
};
LLInventoryFavoritesItemsPanel::LLInventoryFavoritesItemsPanel(const Params& params)
: LLInventoryPanel(params)
{
// replace bridge builder to have necessary View bridges.
mInvFVBridgeBuilder = &FAVORITES_BUILDER;
}
void LLInventoryFavoritesItemsPanel::removeItemID(const LLUUID& id)
{
std::set<LLUUID>::iterator found = mRootContentIDs.find(id);
if (found != mRootContentIDs.end())
{
mRootContentIDs.erase(found);
// check content for favorites
mBuildRootQueue.emplace_back(id);
}
LLInventoryPanel::removeItemID(id);
}
void LLInventoryFavoritesItemsPanel::findAndInitRootContent(const LLUUID& id)
{
F64 curent_time = LLTimer::getTotalSeconds();
if (mBuildViewsEndTime < curent_time)
{
mBuildRootQueue.emplace_back(id);
return;
}
LLViewerInventoryCategory::cat_array_t* categories;
LLViewerInventoryItem::item_array_t* items;
mInventory->lockDirectDescendentArrays(id, categories, items);
if (categories)
{
S32 count = static_cast<S32>(categories->size());
for (S32 i = 0; i < count; ++i)
{
LLViewerInventoryCategory* cat = categories->at(i);
if (cat->getPreferredType() == LLFolderType::FT_TRASH)
{
continue;
}
else if (cat->getIsFavorite())
{
LLFolderViewItem* folder_view_item = getItemByID(cat->getUUID());
if (!folder_view_item)
{
const LLUUID& parent_id = cat->getParentUUID();
mRootContentIDs.emplace(cat->getUUID());
buildViewsTree(cat->getUUID(), parent_id, cat, folder_view_item, mFolderRoot.get(), BUILD_TIMELIMIT);
}
}
else
{
findAndInitRootContent(cat->getUUID());
}
}
}
if (items)
{
S32 count = static_cast<S32>(items->size());
for (S32 i = 0; i < count; ++i)
{
LLViewerInventoryItem* item = items->at(i);
const LLUUID item_id = item->getUUID();
if (item->getIsFavorite() && typedViewsFilter(item_id, item))
{
LLFolderViewItem* folder_view_item = getItemByID(id);
if (!folder_view_item)
{
const LLUUID& parent_id = item->getParentUUID();
mRootContentIDs.emplace(item_id);
buildViewsTree(item_id, parent_id, item, folder_view_item, mFolderRoot.get(), BUILD_TIMELIMIT);
}
}
}
}
}
void LLInventoryFavoritesItemsPanel::initRootContent()
{
findAndInitRootContent(gInventory.getRootFolderID()); // My Inventory
}
bool LLInventoryFavoritesItemsPanel::removeFavorite(const LLUUID& id, const LLInventoryObject* model_item)
{
std::set<LLUUID>::iterator found = mRootContentIDs.find(id);
if (found == mRootContentIDs.end())
{
return false;
}
mRootContentIDs.erase(found);
// This item is in root's content, remove item's UI.
LLFolderViewItem* view_item = getItemByID(id);
if (view_item)
{
LLFolderViewFolder* parent = view_item->getParentFolder();
LLFolderViewModelItemInventory* viewmodel_item = static_cast<LLFolderViewModelItemInventory*>(view_item->getViewModelItem());
if (viewmodel_item)
{
removeItemID(viewmodel_item->getUUID());
}
view_item->destroyView();
if (parent)
{
parent->getViewModelItem()->dirtyDescendantsFilter();
LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(parent->getViewModelItem());
if (viewmodel_folder)
{
updateFolderLabel(viewmodel_folder->getUUID());
}
if (view_item->isFavorite())
{
parent->updateHasFavorites(false); // favorite was removed
}
}
}
return true;
}
void LLInventoryFavoritesItemsPanel::itemChanged(const LLUUID& id, U32 mask, const LLInventoryObject* model_item)
{
if (!model_item && !getItemByID(id))
{
// remove operation, but item is not in panel already
return;
}
bool handled = false;
if (mask & (LLInventoryObserver::UPDATE_FAVORITE |
LLInventoryObserver::STRUCTURE |
LLInventoryObserver::ADD |
LLInventoryObserver::REMOVE))
{
// specifically exlude links and not get_is_favorite(model_item)
if (model_item && model_item->getIsFavorite())
{
LLFolderViewItem* view_item = getItemByID(id);
if (!view_item)
{
const LLViewerInventoryCategory* cat = dynamic_cast<const LLViewerInventoryCategory*>(model_item);
if (cat)
{
// New favorite folder
if (cat->getPreferredType() != LLFolderType::FT_TRASH)
{
// If any descendants were in the list, remove them
LLFavoritesCollector is_favorite;
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendentsIf(id, cat_array, item_array, FALSE, is_favorite);
for (LLInventoryModel::cat_array_t::const_iterator it = cat_array.begin(); it != cat_array.end(); ++it)
{
removeFavorite((*it)->getUUID(), *it);
}
for (LLInventoryModel::item_array_t::const_iterator it = item_array.begin(); it != item_array.end(); ++it)
{
removeFavorite((*it)->getUUID(), *it);
}
LLFolderViewItem* folder_view_item = getItemByID(cat->getUUID());
if (!folder_view_item)
{
const LLUUID& parent_id = cat->getParentUUID();
mRootContentIDs.emplace(cat->getUUID());
buildViewsTree(cat->getUUID(), parent_id, cat, folder_view_item, mFolderRoot.get(), BUILD_ONE_FOLDER);
}
}
}
else
{
// New favorite item
if (model_item->getIsFavorite() && typedViewsFilter(id, model_item))
{
const LLUUID& parent_id = model_item->getParentUUID();
mRootContentIDs.emplace(id);
buildViewsTree(id, parent_id, model_item, NULL, mFolderRoot.get(), BUILD_ONE_FOLDER);
}
}
handled = true;
}
}
else
{
handled = removeFavorite(id, model_item);
}
}
if (!handled)
{
LLInventoryPanel::itemChanged(id, mask, model_item);
}
}
/************************************************************************/
/* LLInventorySingleFolderPanel */
/************************************************************************/
static LLDefaultChildRegistry::Register<LLInventorySingleFolderPanel> t_single_folder_inventory_panel("single_folder_inventory_panel");
LLInventorySingleFolderPanel::LLInventorySingleFolderPanel(const Params& params)

View File

@ -251,7 +251,7 @@ public:
bool reset_filter = false);
static void setSFViewAndOpenFolder(const LLInventoryPanel* panel, const LLUUID& folder_id);
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
void removeItemID(const LLUUID& id);
virtual void removeItemID(const LLUUID& id);
LLFolderViewItem* getItemByID(const LLUUID& id);
LLFolderViewFolder* getFolderByID(const LLUUID& id);
void setSelectionByID(const LLUUID& obj_id, bool take_keyboard_focus);
@ -334,6 +334,8 @@ public:
protected:
// Builds the UI. Call this once the inventory is usable.
void initializeViews(F64 max_time);
virtual void initRootContent();
virtual void findAndInitRootContent(const LLUUID& root_id) {};
// Specific inventory colors
static bool sColorSetInitialized;
@ -371,7 +373,7 @@ protected:
virtual LLFolderViewItem* createFolderViewItem(LLInvFVBridge * bridge);
boost::function<void(const std::deque<LLFolderViewItem*>& items, bool user_action)> mSelectionCallback;
private:
// buildViewsTree does not include some checks and is meant
// for recursive use, use buildNewViews() for first call
LLFolderViewItem* buildViewsTree(const LLUUID& id,
@ -394,6 +396,8 @@ private:
EViewsInitializationState mViewsInitialized; // Whether views have been generated
F64 mBuildViewsEndTime; // Stop building views past this timestamp
std::deque<LLUUID> mBuildViewsQueue;
std::deque<LLUUID> mBuildRootQueue;
};

View File

@ -1414,7 +1414,7 @@ bool LLMaterialEditor::saveIfNeeded()
}
std::string res_desc = buildMaterialDescription();
createInventoryItem(buffer, mMaterialName, res_desc, local_permissions);
createInventoryItem(buffer, mMaterialName, res_desc, local_permissions, mUploadFolder);
// We do not update floater with uploaded asset yet, so just close it.
closeFloater();
@ -1584,12 +1584,12 @@ private:
std::string mNewName;
};
void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& permissions)
void LLMaterialEditor::createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& permissions, const LLUUID& upload_folder)
{
// gen a new uuid for this asset
LLTransactionID tid;
tid.generate(); // timestamp-based randomization + uniquification
LLUUID parent = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_MATERIAL);
LLUUID parent = upload_folder.isNull() ? gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_MATERIAL) : upload_folder;
const U8 subtype = NO_INV_SUBTYPE; // TODO maybe use AT_SETTINGS and LLSettingsType::ST_MATERIAL ?
LLPointer<LLObjectsMaterialItemCallback> cb = new LLObjectsMaterialItemCallback(permissions, buffer, name);
@ -1903,7 +1903,11 @@ static void pack_textures(
}
}
void LLMaterialEditor::uploadMaterialFromModel(const std::string& filename, tinygltf::Model& model_in, S32 index)
void LLMaterialEditor::uploadMaterialFromModel(
const std::string& filename,
tinygltf::Model& model_in,
S32 index,
const LLUUID& dest)
{
if (index < 0 || !LLMaterialEditor::capabilitiesAvailable())
{
@ -1926,12 +1930,13 @@ void LLMaterialEditor::uploadMaterialFromModel(const std::string& filename, tiny
// This uses 'filename' to make sure multiple bulk uploads work
// instead of fighting for a single instance.
LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", LLSD().with("filename", filename).with("index", LLSD::Integer(index)));
me->mUploadFolder = dest;
me->loadMaterial(model_in, filename, index, false);
me->saveIfNeeded();
}
void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 index)
void LLMaterialEditor::loadMaterialFromFile(const std::string& filename, S32 index, const LLUUID& dest_folder)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
@ -2431,17 +2436,17 @@ void LLMaterialEditor::onSaveObjectsMaterialAsMsgCallback(const LLSD& notificati
return;
}
createInventoryItem(str.str(), new_name, std::string(), permissions);
createInventoryItem(str.str(), new_name, std::string(), permissions, LLUUID::null);
}
const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type, bool allow_2k);
void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type, bool allow_2k, const LLUUID& dest);
void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::string &filename, S32 index, bool open_floater)
{
if (index == model_in.materials.size())
{
// bulk upload all the things
upload_bulk({ filename }, LLFilePicker::FFLOAD_MATERIAL, true);
upload_bulk({ filename }, LLFilePicker::FFLOAD_MATERIAL, true, LLUUID::null);
return;
}
@ -2848,10 +2853,10 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const ti
}
}
void LLMaterialEditor::importMaterial()
void LLMaterialEditor::importMaterial(const LLUUID dest_folder)
{
LLFilePickerReplyThread::startPicker(
[](const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)
[dest_folder](const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter load_filter, LLFilePicker::ESaveFilter save_filter)
{
if (LLAppViewer::instance()->quitRequested())
{
@ -2859,7 +2864,7 @@ void LLMaterialEditor::importMaterial()
}
if (filenames.size() > 0)
{
LLMaterialEditor::loadMaterialFromFile(filenames[0], -1);
LLMaterialEditor::loadMaterialFromFile(filenames[0], -1, dest_folder);
}
},
LLFilePicker::FFLOAD_MATERIAL,
@ -3542,6 +3547,7 @@ void LLMaterialEditor::saveTexture(LLImageJ2C* img, const std::string& name, con
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost,
mUploadFolder,
false,
cb,
failed_upload));

View File

@ -94,7 +94,7 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
void setFromGltfMetaData(const std::string& filename, const tinygltf::Model& model, S32 index);
// open a file dialog and select a gltf/glb file for import
static void importMaterial();
static void importMaterial(const LLUUID dest_folder = LLUUID::null);
// for live preview, apply current material to currently selected object
void applyToSelection();
@ -105,8 +105,11 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
void loadAsset() override;
// @index if -1 and file contains more than one material,
// will promt to select specific one
static void uploadMaterialFromModel(const std::string& filename, tinygltf::Model& model, S32 index);
static void loadMaterialFromFile(const std::string& filename, S32 index = -1);
static void uploadMaterialFromModel(const std::string& filename,
tinygltf::Model& model,
S32 index,
const LLUUID& dest_folder_id = LLUUID::null);
static void loadMaterialFromFile(const std::string& filename, S32 index = -1, const LLUUID& dest_folder = LLUUID::null);
void onSelectionChanged(); // live overrides selection changes
@ -134,8 +137,6 @@ class LLMaterialEditor : public LLPreview, public LLVOInventoryListener
void onClickSave();
void getGLTFModel(tinygltf::Model& model);
std::string getEncodedAsset();
bool decodeAsset(const std::vector<char>& buffer);
@ -239,7 +240,7 @@ private:
static void saveObjectsMaterialAs(const LLGLTFMaterial *render_material, const LLLocalGLTFMaterial *local_material, const LLPermissions& permissions, const LLUUID& object_id /* = LLUUID::null */, const LLUUID& item /* = LLUUID::null */);
static bool updateInventoryItem(const std::string &buffer, const LLUUID &item_id, const LLUUID &task_id);
static void createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& permissions);
static void createInventoryItem(const std::string &buffer, const std::string &name, const std::string &desc, const LLPermissions& permissions, const LLUUID& upload_folder);
void setFromGLTFMaterial(LLGLTFMaterial* mat);
bool setFromSelection();
@ -249,6 +250,7 @@ private:
friend class LLMaterialFilePicker;
LLUUID mAssetID;
LLUUID mUploadFolder;
LLTextureCtrl* mBaseColorTextureCtrl;
LLTextureCtrl* mMetallicTextureCtrl;

View File

@ -742,8 +742,12 @@ public:
};
void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
const char * const stage, const std::string & model_name)
void log_upload_error(
LLCore::HttpStatus status,
const LLSD& content,
const char * const stage,
const std::string & model_name,
const std::vector<std::string> & texture_filenames)
{
// Add notification popup.
LLSD args;
@ -801,6 +805,20 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
error_num++;
}
}
if (err.has("TextureIndex"))
{
S32 texture_index = err["TextureIndex"].asInteger();
if (texture_index < texture_filenames.size())
{
args["MESSAGE"] = message + "\n" + texture_filenames[texture_index];
}
else
{
llassert(false); // figure out why or how texture wasn't in the list
args["MESSAGE"] = message + llformat("\nTexture index: %d", texture_index);
}
}
}
else
{
@ -2158,7 +2176,7 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_
LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
const std::string & upload_url, bool do_upload,
const std::string & upload_url, LLUUID destination_folder_id, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer,
LLHandle<LLWholeModelUploadObserver> upload_observer)
: LLThread("mesh upload"),
@ -2166,6 +2184,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mDiscarded(false),
mDoUpload(do_upload),
mWholeModelUploadURL(upload_url),
mDestinationFolderId(destination_folder_id),
mFeeObserverHandle(fee_observer),
mUploadObserverHandle(upload_observer)
{
@ -2283,13 +2302,21 @@ LLSD llsd_from_file(std::string filename)
return result;
}
void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, std::vector<std::string>& texture_list_dest, bool include_textures)
{
LLSD result;
LLSD res;
if (mDestinationFolderId.isNull())
{
result["folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_OBJECT);
result["texture_folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE);
}
else
{
result["folder_id"] = mDestinationFolderId;
result["texture_folder_id"] = mDestinationFolderId;
}
result["asset_type"] = "mesh";
result["inventory_type"] = "object";
result["description"] = "(No Description)";
@ -2432,7 +2459,7 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
LLPointer<LLImageJ2C> upload_file =
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
if (!upload_file.isNull() && upload_file->getDataSize())
if (!upload_file.isNull() && upload_file->getDataSize() && !upload_file->isBufferInvalid())
{
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
}
@ -2446,6 +2473,8 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
texture_index[texture] = texture_num;
std::string str = texture_str.str();
res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
// store indexes for error handling;
texture_list_dest.push_back(material.mDiffuseMapFilename);
texture_num++;
}
@ -2710,7 +2739,8 @@ void LLMeshUploadThread::doWholeModelUpload()
LL_DEBUGS(LOG_MESH) << "Hull generation completed." << LL_ENDL;
mModelData = LLSD::emptyMap();
wholeModelToLLSD(mModelData, true);
mTextureFiles.clear();
wholeModelToLLSD(mModelData, mTextureFiles, true);
LLSD body = mModelData["asset_resources"];
dump_llsd_to_file(body, make_dump_name("whole_model_body_", dump_num));
@ -2763,7 +2793,8 @@ void LLMeshUploadThread::requestWholeModelFee()
generateHulls();
mModelData = LLSD::emptyMap();
wholeModelToLLSD(mModelData, false);
mTextureFiles.clear();
wholeModelToLLSD(mModelData, mTextureFiles, false);
dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
mHttpPolicyClass,
@ -2829,7 +2860,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
body["error"] = LLSD::emptyMap();
body["error"]["message"] = reason;
body["error"]["identifier"] = "NetworkError"; // from asset-upload/upload_util.py
log_upload_error(status, body, "upload", mModelData["name"].asString());
log_upload_error(status, body, "upload", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@ -2864,7 +2895,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
else
{
LL_WARNS(LOG_MESH) << "Upload failed. Not in expected 'complete' state." << LL_ENDL;
log_upload_error(status, body, "upload", mModelData["name"].asString());
log_upload_error(status, body, "upload", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@ -2889,7 +2920,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
body["error"] = LLSD::emptyMap();
body["error"]["message"] = reason;
body["error"]["identifier"] = "NetworkError"; // from asset-upload/upload_util.py
log_upload_error(status, body, "fee", mModelData["name"].asString());
log_upload_error(status, body, "fee", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@ -2922,7 +2953,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
else
{
LL_WARNS(LOG_MESH) << "Fee request failed. Not in expected 'upload' state." << LL_ENDL;
log_upload_error(status, body, "fee", mModelData["name"].asString());
log_upload_error(status, body, "fee", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@ -4410,12 +4441,12 @@ bool LLMeshRepoThread::hasHeader(const LLUUID& mesh_id)
void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
std::string upload_url, bool do_upload,
std::string upload_url, const LLUUID& destination_folder_id, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
{
LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures,
upload_skin, upload_joints, lock_scale_if_joint_position,
upload_url, do_upload, fee_observer, upload_observer);
upload_url, destination_folder_id, do_upload, fee_observer, upload_observer);
mUploadWaitList.push_back(thread);
}

View File

@ -510,10 +510,13 @@ public:
LLHost mHost;
std::string mWholeModelFeeCapability;
std::string mWholeModelUploadURL;
LLUUID mDestinationFolderId;
LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
const std::string & upload_url, bool do_upload = true,
const std::string & upload_url,
const LLUUID destination_folder_id = LLUUID::null,
bool do_upload = true,
LLHandle<LLWholeModelFeeObserver> fee_observer = (LLHandle<LLWholeModelFeeObserver>()),
LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
~LLMeshUploadThread();
@ -529,7 +532,7 @@ public:
void doWholeModelUpload();
void requestWholeModelFee();
void wholeModelToLLSD(LLSD& dest, bool include_textures);
void wholeModelToLLSD(LLSD& dest, std::vector<std::string>& texture_list_dest, bool include_textures);
void decomposeMeshMatrix(LLMatrix4& transformation,
LLVector3& result_pos,
@ -550,6 +553,7 @@ private:
bool mDoUpload; // if false only model data will be requested, otherwise the model will be uploaded
LLSD mModelData;
std::vector<std::string> mTextureFiles;
// llcorehttp library interface objects.
LLCore::HttpStatus mHttpStatus;
@ -672,7 +676,9 @@ public:
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
std::string upload_url, bool do_upload = true,
std::string upload_url,
const LLUUID& destination_folder_id = LLUUID::null,
bool do_upload = true,
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()),
LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));

View File

@ -2350,7 +2350,7 @@ void LLModelPreview::updateStatusMessages()
if (lod != lod_high)
{
if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high])
if (total_submeshes[lod] && total_submeshes[lod] > total_submeshes[lod_high])
{ //number of submeshes is different
message = "mesh_status_submesh_mismatch";
upload_status[lod] = 2;

View File

@ -88,9 +88,16 @@ LLOutfitGallery::LLOutfitGallery(const LLOutfitGallery::Params& p)
mItemsInRow(p.items_in_row),
mRowPanWidthFactor(p.row_panel_width_factor),
mGalleryWidthFactor(p.gallery_width_factor),
mTextureSelected(NULL)
mTextureSelected(NULL),
mSortMenu(nullptr)
{
updateGalleryWidth();
LLControlVariable* ctrl = gSavedSettings.getControl("InventoryFavoritesColorText");
if (ctrl)
{
mSavedSettingInvFavColor = ctrl->getSignal()->connect(boost::bind(&LLOutfitGallery::handleInvFavColorChange, this));
}
}
LLOutfitGallery::Params::Params()
@ -421,16 +428,25 @@ void LLOutfitGallery::updateRowsIfNeeded()
bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)
{
static LLCachedControl<bool> outfit_gallery_sort_by_name(gSavedSettings, "OutfitGallerySortByName");
if(outfit_gallery_sort_by_name ||
((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage())))
static LLCachedControl<S32> sort_by_name(gSavedSettings, "OutfitGallerySortOrder", 0);
switch (sort_by_name())
{
std::string name1 = item1->getItemName();
std::string name2 = item2->getItemName();
return (LLStringUtil::compareDict(name1, name2) < 0);
case 2:
if (item1->isFavorite() != item2->isFavorite())
{
return item1->isFavorite();
break;
case 1:
if (item1->isDefaultImage() != item2->isDefaultImage())
break;
default:
break;
}
std::string name1 = item1->getItemName();
std::string name2 = item2->getItemName();
return (LLStringUtil::compareDict(name1, name2) < 0);
}
else
{
return item2->isDefaultImage();
}
@ -476,6 +492,20 @@ void LLOutfitGallery::updateGalleryWidth()
mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap;
}
void LLOutfitGallery::handleInvFavColorChange()
{
for (outfit_map_t::iterator iter = mOutfitMap.begin();
iter != mOutfitMap.end();
++iter)
{
if (!iter->second) continue;
LLOutfitGalleryItem* item = (LLOutfitGalleryItem*)iter->second;
// refresh font color
item->setOutfitFavorite(item->isFavorite());
}
}
LLPanel* LLOutfitGallery::addLastRow()
{
mRowCount++;
@ -627,7 +657,7 @@ void LLOutfitGallery::removeFromLastRow(LLOutfitGalleryItem* item)
mItemPanels.pop_back();
}
LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name, LLUUID outfit_id)
LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name, LLUUID outfit_id, bool is_favorite)
{
LLOutfitGalleryItem::Params giparams;
LLOutfitGalleryItem* gitem = LLUICtrlFactory::create<LLOutfitGalleryItem>(giparams);
@ -636,6 +666,7 @@ LLOutfitGalleryItem* LLOutfitGallery::buildGalleryItem(std::string name, LLUUID
gitem->setFollowsLeft();
gitem->setFollowsTop();
gitem->setOutfitName(name);
gitem->setOutfitFavorite(is_favorite);
gitem->setUUID(outfit_id);
gitem->setGallery(this);
return gitem;
@ -793,8 +824,7 @@ void LLOutfitGallery::updateAddedCategory(LLUUID cat_id)
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
if (!cat) return;
std::string name = cat->getName();
LLOutfitGalleryItem* item = buildGalleryItem(name, cat_id);
LLOutfitGalleryItem* item = buildGalleryItem(cat->getName(), cat_id, cat->getIsFavorite());
mOutfitMap.insert(LLOutfitGallery::outfit_map_value_t(cat_id, item));
item->setRightMouseDownCallback(boost::bind(&LLOutfitListBase::outfitRightClickCallBack, this,
_1, _2, _3, cat_id));
@ -863,6 +893,7 @@ void LLOutfitGallery::updateChangedCategoryName(LLViewerInventoryCategory *cat,
if (item)
{
item->setOutfitName(name);
item->setOutfitFavorite(cat->getIsFavorite());
}
}
}
@ -943,6 +974,10 @@ LLOutfitListGearMenuBase* LLOutfitGallery::createGearMenu()
static LLDefaultChildRegistry::Register<LLOutfitGalleryItem> r("outfit_gallery_item");
bool LLOutfitGalleryItem::sColorSetInitialized = false;
LLUIColor LLOutfitGalleryItem::sDefaultTextColor;
LLUIColor LLOutfitGalleryItem::sDefaultFavoriteColor;
LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p)
: LLPanel(p),
mGallery(nullptr),
@ -954,6 +989,12 @@ LLOutfitGalleryItem::LLOutfitGalleryItem(const Params& p)
mUUID(LLUUID())
{
buildFromFile("panel_outfit_gallery_item.xml");
if (!sColorSetInitialized)
{
sDefaultTextColor = LLUIColorTable::instance().getColor("White", LLColor4::white);
sDefaultFavoriteColor = LLUIColorTable::instance().getColor("InventoryFavoriteColor", LLColor4::white);
sColorSetInitialized = true;
}
}
LLOutfitGalleryItem::~LLOutfitGalleryItem()
@ -1000,6 +1041,19 @@ void LLOutfitGalleryItem::draw()
gl_draw_scaled_image(interior.mLeft - 1, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
}
static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true);
if(mFavorite && draw_star())
{
const S32 HPAD = 3;
const S32 VPAD = 6; // includes padding for text and for the image
const S32 image_size = 14;
static LLPointer<LLUIImage> fav_img = LLRender2D::getInstance()->getUIImage("Inv_Favorite_Star_Full");
const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
gl_draw_scaled_image(
border.getWidth() - image_size - HPAD, image_size + VPAD + mOutfitNameText->getRect().getHeight(),
image_size, image_size, fav_img->getImage(), UI_VERTEX_COLOR % alpha);
}
}
void LLOutfitGalleryItem::setOutfitName(std::string name)
@ -1009,18 +1063,28 @@ void LLOutfitGalleryItem::setOutfitName(std::string name)
mOutfitName = name;
}
void LLOutfitGalleryItem::setOutfitFavorite(bool is_favorite)
{
mFavorite = is_favorite;
static LLCachedControl<bool> use_color(gSavedSettings, "InventoryFavoritesColorText");
mOutfitNameText->setReadOnlyColor((mFavorite && use_color()) ? sDefaultFavoriteColor.get() : sDefaultTextColor.get());
}
void LLOutfitGalleryItem::setOutfitWorn(bool value)
{
mWorn = value;
LLStringUtil::format_map_t worn_string_args;
std::string worn_string = getString("worn_string", worn_string_args);
LLUIColor text_color = LLUIColorTable::instance().getColor("White", LLColor4::white);
mOutfitWornText->setReadOnlyColor(text_color);
mOutfitNameText->setReadOnlyColor(text_color);
mOutfitWornText->setReadOnlyColor(sDefaultTextColor.get());
mOutfitNameText->setReadOnlyColor(sDefaultTextColor.get());
mOutfitWornText->setFont(value ? LLFontGL::getFontSansSerifBold() : LLFontGL::getFontSansSerifSmall());
mOutfitNameText->setFont(value ? LLFontGL::getFontSansSerifBold() : LLFontGL::getFontSansSerifSmall());
mOutfitWornText->setValue(value ? worn_string : "");
mOutfitNameText->setText(mOutfitName); // refresh LLTextViewModel to pick up font changes
static LLCachedControl<bool> use_color(gSavedSettings, "InventoryFavoritesColorText");
mOutfitNameText->setReadOnlyColor((mFavorite && use_color()) ? sDefaultFavoriteColor.get() : sDefaultTextColor.get());
}
void LLOutfitGalleryItem::setSelected(bool value)
@ -1172,6 +1236,7 @@ LLContextMenu* LLOutfitGalleryContextMenu::createMenu()
registrar.add("Outfit.Delete", boost::bind(LLOutfitGallery::onRemoveOutfit, selected_id));
registrar.add("Outfit.Create", boost::bind(&LLOutfitGalleryContextMenu::onCreate, this, _2));
registrar.add("Outfit.Thumbnail", boost::bind(&LLOutfitGalleryContextMenu::onThumbnail, this, selected_id));
registrar.add("Outfit.Favorite", boost::bind(&LLOutfitGalleryContextMenu::onFavorite, this, selected_id));
registrar.add("Outfit.Save", boost::bind(&LLOutfitGalleryContextMenu::onSave, this, selected_id));
enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitGalleryContextMenu::onEnable, this, _2));
enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitGalleryContextMenu::onVisible, this, _2));
@ -1218,17 +1283,6 @@ void LLOutfitGalleryGearMenu::onUpdateItemsVisibility()
LLOutfitListGearMenuBase::onUpdateItemsVisibility();
}
void LLOutfitGalleryGearMenu::onChangeSortOrder()
{
bool sort_by_name = !gSavedSettings.getBOOL("OutfitGallerySortByName");
gSavedSettings.setBOOL("OutfitGallerySortByName", sort_by_name);
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
if (gallery)
{
gallery->reArrangeRows();
}
}
bool LLOutfitGalleryGearMenu::hasDefaultImage()
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
@ -1345,6 +1399,15 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
}
}
LLToggleableMenu* LLOutfitGallery::getSortMenu()
{
if (!mSortMenu)
{
mSortMenu = new LLOutfitGallerySortMenu(this);
}
return mSortMenu->getMenu();
}
LLUUID LLOutfitGallery::getPhotoAssetId(const LLUUID& outfit_id)
{
outfit_map_t::iterator outfit_it = mOutfitMap.find(outfit_id);
@ -1360,3 +1423,84 @@ LLUUID LLOutfitGallery::getDefaultPhoto()
return LLUUID();
}
//////////////////// LLOutfitGallerySortMenu ////////////////////
LLOutfitGallerySortMenu::LLOutfitGallerySortMenu(LLOutfitListBase* parent_panel)
: mPanelHandle(parent_panel->getHandle())
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
registrar.add("Sort.OnSort", boost::bind(&LLOutfitGallerySortMenu::onSort, this, _2));
enable_registrar.add("Sort.OnEnable", boost::bind(&LLOutfitGallerySortMenu::onEnable, this, _2));
mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_outfit_gallery_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
LLToggleableMenu* LLOutfitGallerySortMenu::getMenu()
{
return mMenu;
}
void LLOutfitGallerySortMenu::updateItemsVisibility()
{
onUpdateItemsVisibility();
}
void LLOutfitGallerySortMenu::onUpdateItemsVisibility()
{
if (!mMenu) return;
}
bool LLOutfitGallerySortMenu::onEnable(LLSD::String param)
{
static LLCachedControl<S32> sort_order(gSavedSettings, "OutfitGallerySortOrder", 0);
if ("favorites_to_top" == param)
{
return sort_order == 2;
}
else if ("images_to_top" == param)
{
return sort_order == 1;
}
else if ("by_name" == param)
{
return sort_order == 0;
}
return false;
}
void LLOutfitGallerySortMenu::onSort(LLSD::String param)
{
S32 sort_order = gSavedSettings.getS32("OutfitGallerySortOrder");
S32 new_sort_order = 0;
if ("favorites_to_top" == param)
{
new_sort_order = 2;
}
else if ("images_to_top" == param)
{
new_sort_order = 1;
}
else if ("by_name" == param)
{
new_sort_order = 0;
}
if (sort_order == new_sort_order)
{
new_sort_order = sort_order ? 0 : 1;
}
gSavedSettings.setS32("OutfitGallerySortOrder", new_sort_order);
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mPanelHandle.get());
if (gallery)
{
gallery->reArrangeRows();
}
}

View File

@ -42,11 +42,13 @@ class LLOutfitGalleryItem;
class LLOutfitListGearMenuBase;
class LLOutfitGalleryGearMenu;
class LLOutfitGalleryContextMenu;
class LLOutfitGallerySortMenu;
class LLOutfitGallery : public LLOutfitListBase
{
public:
friend class LLOutfitGalleryGearMenu;
friend class LLOutfitGallerySortMenu;
friend class LLOutfitGalleryContextMenu;
friend class LLUpdateGalleryOnPhotoLinked;
@ -102,10 +104,12 @@ public:
/*virtual*/ bool getHasExpandableFolders() { return false; }
/*virtual*/ void onChangeSortOrder(const LLSD& userdata) {};
void updateMessageVisibility();
bool hasDefaultImage(const LLUUID& outfit_cat_id);
void refreshOutfit(const LLUUID& category_id);
virtual LLToggleableMenu* getSortMenu();
protected:
/*virtual*/ void onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id);
@ -133,8 +137,9 @@ private:
void reArrangeRows(S32 row_diff = 0);
void updateRowsIfNeeded();
void updateGalleryWidth();
void handleInvFavColorChange();
LLOutfitGalleryItem* buildGalleryItem(std::string name, LLUUID outfit_id);
LLOutfitGalleryItem* buildGalleryItem(std::string name, LLUUID outfit_id, bool is_favorite);
LLOutfitGalleryItem* getSelectedItem() const;
LLOutfitGalleryItem* getItem(const LLUUID& id) const;
@ -176,6 +181,7 @@ private:
int mGalleryWidthFactor;
LLListContextMenu* mOutfitGalleryMenu;
LLOutfitGallerySortMenu* mSortMenu;
typedef std::map<LLUUID, LLOutfitGalleryItem*> outfit_map_t;
typedef outfit_map_t::value_type outfit_map_value_t;
@ -187,6 +193,8 @@ private:
LLInventoryCategoriesObserver* mOutfitsObserver;
boost::signals2::connection mSavedSettingInvFavColor;
};
class LLOutfitGalleryContextMenu : public LLOutfitContextMenu
{
@ -213,8 +221,6 @@ public:
protected:
/*virtual*/ void onUpdateItemsVisibility();
private:
/*virtual*/ void onChangeSortOrder();
bool hasDefaultImage();
};
@ -243,6 +249,7 @@ public:
bool setImageAssetId(LLUUID asset_id);
LLUUID getImageAssetId();
void setOutfitName(std::string name);
void setOutfitFavorite(bool is_favorite);
void setOutfitWorn(bool value);
void setSelected(bool value);
void setUUID(const LLUUID &outfit_id) {mUUID = outfit_id;}
@ -250,6 +257,7 @@ public:
std::string getItemName() {return mOutfitName;}
bool isDefaultImage() {return mDefaultImage;}
bool isFavorite() { return mFavorite; }
bool isHidden() {return mHidden;}
void setHidden(bool hidden) {mHidden = hidden;}
@ -267,7 +275,29 @@ private:
bool mWorn;
bool mDefaultImage;
bool mHidden;
bool mFavorite;
std::string mOutfitName;
static bool sColorSetInitialized;
static LLUIColor sDefaultTextColor;
static LLUIColor sDefaultFavoriteColor;
};
class LLOutfitGallerySortMenu
{
public:
LLOutfitGallerySortMenu(LLOutfitListBase* parent_panel);
LLToggleableMenu* getMenu();
void updateItemsVisibility();
private:
void onUpdateItemsVisibility();
bool onEnable(LLSD::String param);
void onSort(LLSD::String param);
LLToggleableMenu* mMenu;
LLHandle<LLPanel> mPanelHandle;
};
#endif // LL_LLOUTFITGALLERYCTRL_H

View File

@ -35,6 +35,7 @@
#include "llaccordionctrltab.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llappviewer.h"
#include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
#include "llinspecttexture.h"
@ -45,6 +46,7 @@
#include "lloutfitobserver.h"
#include "lltoggleablemenu.h"
#include "lltransutil.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
#include "llvoavatar.h"
#include "llvoavatarself.h"
@ -53,14 +55,24 @@
static bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y);
static const LLOutfitTabNameComparator OUTFIT_TAB_NAME_COMPARATOR;
static const LLOutfitTabFavComparator OUTFIT_TAB_FAV_COMPARATOR;
/*virtual*/
bool LLOutfitTabNameComparator::compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const
{
std::string name1 = tab1->getTitle();
std::string name2 = tab2->getTitle();
return (LLStringUtil::compareDict(tab1->getTitle(), tab2->getTitle()) < 0);
}
return (LLStringUtil::compareDict(name1, name2) < 0);
bool LLOutfitTabFavComparator::compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const
{
LLOutfitAccordionCtrlTab* taba = (LLOutfitAccordionCtrlTab*)tab1;
LLOutfitAccordionCtrlTab* tabb = (LLOutfitAccordionCtrlTab*)tab2;
if (taba->getFavorite() != tabb->getFavorite())
{
return taba->getFavorite();
}
return (LLStringUtil::compareDict(tab1->getTitle(), tab2->getTitle()) < 0);
}
struct outfit_accordion_tab_params : public LLInitParam::Block<outfit_accordion_tab_params, LLOutfitAccordionCtrlTab::Params>
@ -80,6 +92,9 @@ const outfit_accordion_tab_params& get_accordion_tab_params()
{
initialized = true;
LLOutfitAccordionCtrlTab::sFavoriteIcon = LLUI::getUIImage("Inv_Favorite_Star_Full");
LLOutfitAccordionCtrlTab::sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255));
LLXMLNodePtr xmlNode;
if (LLUICtrlFactory::getLayeredXMLNode("outfit_accordion_tab.xml", xmlNode))
{
@ -103,11 +118,20 @@ LLOutfitsList::LLOutfitsList()
, mAccordion(NULL)
, mListCommands(NULL)
, mItemSelected(false)
, mSortMenu(nullptr)
{
LLControlVariable* ctrl = gSavedSettings.getControl("InventoryFavoritesColorText");
if (ctrl)
{
mSavedSettingInvFavColor = ctrl->getSignal()->connect(boost::bind(&LLOutfitsList::handleInvFavColorChange, this));
}
}
LLOutfitsList::~LLOutfitsList()
{
delete mSortMenu;
mSavedSettingInvFavColor.disconnect();
mGearMenuConnection.disconnect();
}
bool LLOutfitsList::postBuild()
@ -115,9 +139,25 @@ bool LLOutfitsList::postBuild()
mAccordion = getChild<LLAccordionCtrl>("outfits_accordion");
mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
initComparator();
return LLOutfitListBase::postBuild();
}
void LLOutfitsList::initComparator()
{
S32 mode = gSavedSettings.getS32("OutfitListSortOrder");
if (mode == 0)
{
mAccordion->setComparator(&OUTFIT_TAB_NAME_COMPARATOR);
}
else
{
mAccordion->setComparator(&OUTFIT_TAB_FAV_COMPARATOR);
}
sortOutfits();
}
//virtual
void LLOutfitsList::onOpen(const LLSD& info)
{
@ -154,6 +194,7 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
tab->setName(name);
tab->setTitle(name);
tab->setFavorite(cat->getIsFavorite());
// *TODO: LLUICtrlFactory::defaultBuilder does not use "display_children" from xml. Should be investigated.
tab->setDisplayChildren(false);
@ -183,8 +224,9 @@ void LLOutfitsList::updateAddedCategory(LLUUID cat_id)
// Setting callback to reset items selection inside outfit on accordion collapsing and expanding (EXT-7875)
tab->setDropDownStateChangedCallback(boost::bind(&LLOutfitsList::resetItemSelection, this, list, cat_id));
// force showing list items that don't match current filter(EXT-7158)
list->setForceShowingUnmatchedItems(true);
// Depending on settings, force showing list items that don't match current filter(EXT-7158)
static LLCachedControl<bool> list_filter(gSavedSettings, "OutfitListFilterFullList");
list->setForceShowingUnmatchedItems(list_filter(), false);
// Setting list commit callback to monitor currently selected wearable item.
list->setCommitCallback(boost::bind(&LLOutfitsList::onListSelectionChange, this, _1));
@ -249,13 +291,11 @@ void LLOutfitsList::onHighlightBaseOutfit(LLUUID base_id, LLUUID prev_id)
{
if (mOutfitsMap[prev_id])
{
mOutfitsMap[prev_id]->setTitleFontStyle("NORMAL");
mOutfitsMap[prev_id]->setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
((LLOutfitAccordionCtrlTab*)mOutfitsMap[prev_id])->setOutfitSelected(false);
}
if (mOutfitsMap[base_id])
{
mOutfitsMap[base_id]->setTitleFontStyle("BOLD");
mOutfitsMap[base_id]->setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));
((LLOutfitAccordionCtrlTab*)mOutfitsMap[base_id])->setOutfitSelected(true);
}
}
@ -313,6 +353,11 @@ void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
}
}
void LLOutfitListBase::onAction(const LLSD& userdata)
{
performAction(userdata.asString());
}
// virtual
bool LLOutfitListBase::isActionEnabled(const LLSD& userdata)
{
@ -425,11 +470,12 @@ void LLOutfitsList::updateChangedCategoryName(LLViewerInventoryCategory *cat, st
if (outfits_iter != mOutfitsMap.end())
{
// Update tab name with the new category name.
LLAccordionCtrlTab* tab = outfits_iter->second;
LLOutfitAccordionCtrlTab* tab = (LLOutfitAccordionCtrlTab*) outfits_iter->second;
if (tab)
{
tab->setName(name);
tab->setTitle(name);
tab->setFavorite(cat->getIsFavorite());
}
}
}
@ -521,7 +567,7 @@ void LLOutfitsList::onFilterSubStringChanged(const std::string& new_string, cons
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (list)
{
list->setFilterSubString(new_string, tab->getDisplayChildren());
list->setFilterSubString(new_string, true);
}
if (old_string.empty())
@ -738,6 +784,75 @@ void LLOutfitsList::onOutfitRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUI
}
}
void LLOutfitsList::handleInvFavColorChange()
{
for (outfits_map_t::iterator iter = mOutfitsMap.begin();
iter != mOutfitsMap.end();
++iter)
{
if (!iter->second) continue;
LLOutfitAccordionCtrlTab* tab = (LLOutfitAccordionCtrlTab*)iter->second;
// refresh font color
tab->setFavorite(tab->getFavorite());
}
}
void LLOutfitsList::onChangeSortOrder(const LLSD& userdata)
{
std::string sort_data = userdata.asString();
if (sort_data == "favorites_to_top")
{
// at the moment this is a toggle
S32 val = gSavedSettings.getS32("OutfitListSortOrder");
gSavedSettings.setS32("OutfitListSortOrder", (val ? 0 : 1));
initComparator();
}
else if (sort_data == "show_entire_outfit")
{
bool new_val = !gSavedSettings.getBOOL("OutfitListFilterFullList");
gSavedSettings.setBOOL("OutfitListFilterFullList", new_val);
if (!getFilterSubString().empty())
{
for (outfits_map_t::value_type& outfit : mOutfitsMap)
{
LLAccordionCtrlTab* tab = outfit.second;
const LLUUID& category_id = outfit.first;
if (!tab) continue;
LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView());
if (list)
{
list->setForceRefresh(true);
list->setForceShowingUnmatchedItems(new_val, tab->getDisplayChildren());
}
applyFilterToTab(category_id, tab, getFilterSubString());
}
mAccordion->arrange();
}
}
}
LLToggleableMenu* LLOutfitsList::getSortMenu()
{
if (!mSortMenu)
{
mSortMenu = new LLOutfitListSortMenu(this);
}
return mSortMenu->getMenu();
}
void LLOutfitsList::updateMenuItemsVisibility()
{
if (mSortMenu)
{
mSortMenu->updateItemsVisibility();
}
LLOutfitListBase::updateMenuItemsVisibility();
}
LLOutfitListGearMenuBase* LLOutfitsList::createGearMenu()
{
return new LLOutfitListGearMenu(this);
@ -755,10 +870,10 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
LLOutfitListBase::LLOutfitListBase()
: LLPanelAppearanceTab()
, mIsInitialized(false)
, mGearMenu(nullptr)
{
mCategoriesObserver = new LLInventoryCategoriesObserver();
mOutfitMenu = new LLOutfitContextMenu(this);
//mGearMenu = createGearMenu();
}
LLOutfitListBase::~LLOutfitListBase()
@ -821,6 +936,10 @@ void LLOutfitListBase::observerCallback(const LLUUID& category_id)
void LLOutfitListBase::refreshList(const LLUUID& category_id)
{
if (LLAppViewer::instance()->quitRequested())
{
return;
}
bool wasNull = mRefreshListState.CategoryUUID.isNull();
mRefreshListState.CategoryUUID.setNull();
@ -879,8 +998,18 @@ void LLOutfitListBase::onIdle(void* userdata)
void LLOutfitListBase::onIdleRefreshList()
{
if (mRefreshListState.CategoryUUID.isNull())
if (LLAppViewer::instance()->quitRequested())
{
mRefreshListState.CategoryUUID.setNull();
gIdleCallbacks.deleteFunction(onIdle, this);
return;
}
if (mRefreshListState.CategoryUUID.isNull())
{
LL_WARNS() << "Called onIdleRefreshList without id" << LL_ENDL;
gIdleCallbacks.deleteFunction(onIdle, this);
return;
}
const F64 MAX_TIME = 0.05f;
F64 curent_time = LLTimer::getTotalSeconds();
@ -1041,6 +1170,20 @@ void LLOutfitListBase::expandAllFolders()
onExpandAllFolders();
}
void LLOutfitListBase::updateMenuItemsVisibility()
{
mGearMenu->updateItemsVisibility();
}
LLToggleableMenu* LLOutfitListBase::getGearMenu()
{
if (!mGearMenu)
{
mGearMenu = createGearMenu();
}
return mGearMenu->getMenu();
};
void LLOutfitListBase::deselectOutfit(const LLUUID& category_id)
{
// Reset selection if the outfit is selected.
@ -1067,6 +1210,7 @@ LLContextMenu* LLOutfitContextMenu::createMenu()
registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id));
registrar.add("Outfit.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList));
registrar.add("Outfit.Thumbnail", boost::bind(&LLOutfitContextMenu::onThumbnail, this, selected_id));
registrar.add("Outfit.Favorite", boost::bind(&LLOutfitContextMenu::onFavorite, this, selected_id));
registrar.add("Outfit.Save", boost::bind(&LLOutfitContextMenu::onSave, this, selected_id));
enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2));
@ -1117,6 +1261,16 @@ bool LLOutfitContextMenu::onVisible(LLSD::String param)
{
return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id);
}
else if ("favorites_add" == param)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_cat_id);
return cat && !cat->getIsFavorite();
}
else if ("favorites_remove" == param)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_cat_id);
return cat && cat->getIsFavorite();
}
return true;
}
@ -1141,6 +1295,14 @@ void LLOutfitContextMenu::onThumbnail(const LLUUID &outfit_cat_id)
}
}
void LLOutfitContextMenu::onFavorite(const LLUUID& outfit_cat_id)
{
if (outfit_cat_id.notNull())
{
toggle_favorite(outfit_cat_id);
}
}
void LLOutfitContextMenu::onSave(const LLUUID &outfit_cat_id)
{
if (outfit_cat_id.notNull())
@ -1171,14 +1333,13 @@ LLOutfitListGearMenuBase::LLOutfitListGearMenuBase(LLOutfitListBase* olist)
registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenuBase::onRename, this));
registrar.add("Gear.Delete", boost::bind(&LLOutfitListBase::removeSelected, mOutfitList));
registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenuBase::onCreate, this, _2));
registrar.add("Gear.Collapse", boost::bind(&LLOutfitListBase::onCollapseAllFolders, mOutfitList));
registrar.add("Gear.Expand", boost::bind(&LLOutfitListBase::onExpandAllFolders, mOutfitList));
registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenuBase::onAdd, this));
registrar.add("Gear.Save", boost::bind(&LLOutfitListGearMenuBase::onSave, this));
registrar.add("Gear.Thumbnail", boost::bind(&LLOutfitListGearMenuBase::onThumbnail, this));
registrar.add("Gear.SortByName", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this));
registrar.add("Gear.Favorite", boost::bind(&LLOutfitListGearMenuBase::onFavorite, this));
registrar.add("Gear.SortByImage", boost::bind(&LLOutfitListGearMenuBase::onChangeSortOrder, this));
enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenuBase::onEnable, this, _2));
enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenuBase::onVisible, this, _2));
@ -1312,6 +1473,16 @@ bool LLOutfitListGearMenuBase::onVisible(LLSD::String param)
{
return false;
}
else if ("favorites_add" == param)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
return cat && !cat->getIsFavorite();
}
else if ("favorites_remove" == param)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(selected_outfit_id);
return cat && cat->getIsFavorite();
}
return true;
}
@ -1323,6 +1494,12 @@ void LLOutfitListGearMenuBase::onThumbnail()
LLFloaterReg::showInstance("change_item_thumbnail", data);
}
void LLOutfitListGearMenuBase::onFavorite()
{
const LLUUID& selected_outfit_id = getSelectedOutfitID();
toggle_favorite(selected_outfit_id);
}
void LLOutfitListGearMenuBase::onChangeSortOrder()
{
@ -1346,6 +1523,72 @@ void LLOutfitListGearMenu::onUpdateItemsVisibility()
LLOutfitListGearMenuBase::onUpdateItemsVisibility();
}
//////////////////// LLOutfitListSortMenu ////////////////////
LLOutfitListSortMenu::LLOutfitListSortMenu(LLOutfitListBase* parent_panel)
: mPanelHandle(parent_panel->getHandle())
{
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
registrar.add("Sort.Collapse", boost::bind(&LLOutfitListBase::onCollapseAllFolders, parent_panel));
registrar.add("Sort.Expand", boost::bind(&LLOutfitListBase::onExpandAllFolders, parent_panel));
registrar.add("Sort.OnSort", boost::bind(&LLOutfitListBase::onChangeSortOrder, parent_panel, _2));
enable_registrar.add("Sort.OnEnable", boost::bind(&LLOutfitListSortMenu::onEnable, this, _2));
mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(
"menu_outfit_list_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
llassert(mMenu);
}
LLToggleableMenu* LLOutfitListSortMenu::getMenu()
{
return mMenu;
}
void LLOutfitListSortMenu::updateItemsVisibility()
{
onUpdateItemsVisibility();
}
void LLOutfitListSortMenu::onUpdateItemsVisibility()
{
if (!mMenu) return;
mMenu->setItemVisible("expand", true);
mMenu->setItemVisible("collapse", true);
mMenu->setItemVisible("sort_favorites_to_top", true);
mMenu->setItemVisible("show_entire_outfit_in_search", true);
}
bool LLOutfitListSortMenu::onEnable(LLSD::String param)
{
if ("favorites_to_top" == param)
{
static LLCachedControl<S32> sort_order(gSavedSettings, "OutfitListSortOrder", 0);
return sort_order == 1;
}
else if ("show_entire_outfit" == param)
{
static LLCachedControl<bool> filter_mode(gSavedSettings, "OutfitListFilterFullList", 0);
return filter_mode;
}
return false;
}
//////////////////// LLOutfitAccordionCtrlTab ////////////////////
LLUIImage* LLOutfitAccordionCtrlTab::sFavoriteIcon;
LLUIColor LLOutfitAccordionCtrlTab::sFgColor;
void LLOutfitAccordionCtrlTab::draw()
{
LLAccordionCtrlTab::draw();
drawFavoriteIcon();
}
bool LLOutfitAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask)
{
if (y >= getLocalRect().getHeight() - getHeaderHeight())
@ -1366,4 +1609,61 @@ bool LLOutfitAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask)
return LLAccordionCtrlTab::handleToolTip(x, y, mask);
}
void LLOutfitAccordionCtrlTab::setFavorite(bool is_favorite)
{
mIsFavorite = is_favorite;
static LLUICachedControl<bool> highlight_color("InventoryFavoritesColorText", true);
if (!mIsSelected && mIsFavorite && highlight_color())
{
setTitleColor(LLUIColorTable::instance().getColor("InventoryFavoriteColor"));
}
else
{
setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
}
}
void LLOutfitAccordionCtrlTab::setOutfitSelected(bool val)
{
mIsSelected = val;
if (val)
{
setTitleFontStyle("BOLD");
setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));
}
else
{
setTitleFontStyle("NORMAL");
static LLUICachedControl<bool> highlight_color("InventoryFavoritesColorText", true);
if (mIsFavorite && highlight_color())
{
setTitleColor(LLUIColorTable::instance().getColor("InventoryFavoriteColor"));
}
else
{
setTitleColor(LLUIColorTable::instance().getColor("AccordionHeaderTextColor"));
}
}
}
void LLOutfitAccordionCtrlTab::drawFavoriteIcon()
{
if (!mIsFavorite)
{
return;
}
static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true);
if (!draw_star)
{
return;
}
const S32 PAD = 2;
const S32 image_size = 18;
gl_draw_scaled_image(
getRect().getWidth() - image_size - PAD, getRect().getHeight() - image_size - PAD,
image_size, image_size, sFavoriteIcon->getImage(), sFgColor);
}
// EOF

View File

@ -41,6 +41,7 @@
class LLAccordionCtrlTab;
class LLInventoryCategoriesObserver;
class LLOutfitListGearMenuBase;
class LLOutfitListSortMenuBase;
class LLWearableItemsList;
class LLListContextMenu;
@ -61,6 +62,17 @@ public:
/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const;
};
class LLOutfitTabFavComparator : public LLAccordionCtrl::LLTabComparator
{
LOG_CLASS(LLOutfitTabFavComparator);
public:
LLOutfitTabFavComparator() {};
virtual ~LLOutfitTabFavComparator() {};
/*virtual*/ bool compare(const LLAccordionCtrlTab* tab1, const LLAccordionCtrlTab* tab2) const;
};
class LLOutfitListBase : public LLPanelAppearanceTab
{
public:
@ -92,6 +104,7 @@ public:
boost::signals2::connection setSelectionChangeCallback(selection_change_callback_t cb);
void outfitRightClickCallBack(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id);
void onAction(const LLSD& userdata);
virtual bool isActionEnabled(const LLSD& userdata);
virtual void performAction(std::string action);
virtual bool hasItemSelected() = 0;
@ -109,6 +122,12 @@ public:
virtual bool getHasExpandableFolders() = 0;
virtual void onChangeSortOrder(const LLSD& userdata) = 0;
virtual void updateMenuItemsVisibility();
virtual LLToggleableMenu* getGearMenu();
virtual bool getTrashMenuVisible() { return true; };
protected:
void observerCallback(const LLUUID& category_id);
virtual LLOutfitListGearMenuBase* createGearMenu() = 0;
@ -139,6 +158,7 @@ protected:
selection_change_signal_t mSelectionChangeSignal;
LLListContextMenu* mOutfitMenu;
LLOutfitListGearMenuBase* mGearMenu;
boost::signals2::connection mGearMenuConnection;
};
//////////////////////////////////////////////////////////////////////////
@ -155,7 +175,6 @@ protected:
/* virtual */ LLContextMenu* createMenu();
bool onEnable(LLSD::String param);
bool onVisible(LLSD::String param);
static void editOutfit();
@ -163,6 +182,7 @@ protected:
static void renameOutfit(const LLUUID& outfit_cat_id);
void onThumbnail(const LLUUID &outfit_cat_id);
void onFavorite(const LLUUID& outfit_cat_id);
void onSave(const LLUUID &outfit_cat_id);
private:
@ -182,6 +202,7 @@ public:
protected:
virtual void onUpdateItemsVisibility();
virtual void onThumbnail();
virtual void onFavorite();
virtual void onChangeSortOrder();
const LLUUID& getSelectedOutfitID();
@ -202,6 +223,23 @@ private:
bool onVisible(LLSD::String param);
};
class LLOutfitListSortMenu
{
public:
LLOutfitListSortMenu(LLOutfitListBase* parent_panel);
LLToggleableMenu* getMenu();
void updateItemsVisibility();
private:
void onUpdateItemsVisibility();
bool onEnable(LLSD::String param);
LLToggleableMenu* mMenu;
LLHandle<LLPanel> mPanelHandle;
};
class LLOutfitListGearMenu : public LLOutfitListGearMenuBase
{
public:
@ -221,8 +259,16 @@ public:
Params() : cat_id("cat_id") {}
};
virtual void draw();
virtual bool handleToolTip(S32 x, S32 y, MASK mask);
void setFavorite(bool is_favorite);
bool getFavorite() const { return mIsFavorite; }
void setOutfitSelected(bool val);
static LLUIImage* sFavoriteIcon;
static LLUIColor sFgColor;
protected:
LLOutfitAccordionCtrlTab(const LLOutfitAccordionCtrlTab::Params &p)
: LLAccordionCtrlTab(p),
@ -230,7 +276,11 @@ public:
{}
friend class LLUICtrlFactory;
void drawFavoriteIcon();
LLUUID mFolderID;
bool mIsFavorite = false;
bool mIsSelected = false;
};
/**
* @class LLOutfitsList
@ -249,6 +299,7 @@ public:
virtual ~LLOutfitsList();
/*virtual*/ bool postBuild();
void initComparator();
/*virtual*/ void onOpen(const LLSD& info);
@ -287,6 +338,10 @@ public:
/*virtual*/ bool getHasExpandableFolders() { return true; }
/*virtual*/ void onChangeSortOrder(const LLSD& userdata);
virtual LLToggleableMenu* getSortMenu();
void updateMenuItemsVisibility();
protected:
LLOutfitListGearMenuBase* createGearMenu();
@ -357,6 +412,8 @@ private:
static void onOutfitRename(const LLSD& notification, const LLSD& response);
void handleInvFavColorChange();
//LLInventoryCategoriesObserver* mCategoriesObserver;
LLAccordionCtrl* mAccordion;
@ -374,13 +431,15 @@ private:
// Used to monitor COF changes for updating items worn state. See EXT-8636.
uuid_vec_t mCOFLinkedItems;
//LLOutfitListGearMenu* mGearMenu;
LLOutfitListSortMenu* mSortMenu;
//bool mIsInitialized;
/**
* True if there is a selection inside currently selected outfit
*/
bool mItemSelected;
boost::signals2::connection mSavedSettingInvFavColor;
};
#endif //LL_LLOUTFITSLIST_H

View File

@ -29,6 +29,8 @@
#include "llpanel.h"
class LLToggleableMenu;
class LLPanelAppearanceTab : public LLPanel
{
public:
@ -47,6 +49,11 @@ public:
const std::string& getFilterSubString() { return mFilterSubString; }
virtual void updateMenuItemsVisibility() = 0;
virtual LLToggleableMenu* getGearMenu() = 0;
virtual LLToggleableMenu* getSortMenu() = 0;
virtual bool getTrashMenuVisible() = 0;
protected:
/**

View File

@ -481,10 +481,6 @@ LLPanelFace::~LLPanelFace()
void LLPanelFace::onVisibilityChange(bool new_visibility)
{
if (new_visibility)
{
gAgent.showLatestFeatureNotification("gltf");
}
LLPanel::onVisibilityChange(new_visibility);
}

View File

@ -85,6 +85,7 @@ bool LLPanelGroupCreate::postBuild()
mInsignia = getChild<LLTextureCtrl>("insignia", true);
mInsignia->setAllowLocalTexture(false);
mInsignia->setBakeTextureEnabled(false);
mInsignia->setCanApplyImmediately(false);
return true;

View File

@ -197,6 +197,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
{
mInsignia->setCommitCallback(onCommitAny, this);
mInsignia->setAllowLocalTexture(false);
mInsignia->setBakeTextureEnabled(false);
}
mFounderName = getChild<LLTextBox>("founder_name");

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