Merge branch 'release/2025.05' of https://github.com/secondlife/viewer
# Conflicts: # autobuild.xml # indra/llui/llfolderviewitem.h # indra/llui/lltexteditor.cpp # indra/llui/lltexteditor.h # indra/newview/app_settings/settings.xml # indra/newview/llagent.cpp # indra/newview/llappviewer.cpp # indra/newview/llfloatermodelpreview.h # indra/newview/llinventorybridge.cpp # indra/newview/llinventorybridge.h # indra/newview/llinventoryfilter.cpp # indra/newview/llinventoryfilter.h # indra/newview/llmaterialeditor.cpp # indra/newview/lloutfitslist.cpp # indra/newview/lloutfitslist.h # indra/newview/llpanelmaininventory.cpp # indra/newview/llpaneloutfitedit.cpp # indra/newview/llpaneloutfitsinventory.cpp # indra/newview/llpaneloutfitsinventory.h # indra/newview/llpanelpermissions.cpp # indra/newview/llpanelpermissions.h # indra/newview/llpanelwearing.cpp # indra/newview/llpanelwearing.h # indra/newview/llselectmgr.h # indra/newview/llskinningutil.cpp # indra/newview/lltexturectrl.cpp # indra/newview/lltexturefetch.cpp # indra/newview/lltooldraganddrop.cpp # indra/newview/llviewerattachmenu.cpp # indra/newview/llviewerinventory.cpp # indra/newview/llviewerinventory.h # indra/newview/llviewerwindow.cpp # indra/newview/llvoavatar.cpp # indra/newview/llwearableitemslist.cpp # indra/newview/skins/default/textures/textures.xml # indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml # indra/newview/skins/default/xui/en/floater_object_weights.xml # indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml # indra/newview/skins/default/xui/en/menu_inventory.xml # indra/newview/skins/default/xui/en/menu_outfit_tab.xml # indra/newview/skins/default/xui/en/menu_wearing_tab.xml # indra/newview/skins/default/xui/en/notifications.xml # indra/newview/skins/default/xui/en/panel_main_inventory.xml # indra/newview/skins/default/xui/en/panel_outfit_gallery.xml # indra/newview/skins/default/xui/en/panel_outfits_list.xml # indra/newview/skins/default/xui/en/panel_outfits_wearing.xml # indra/newview/skins/default/xui/en/panel_places.xml # indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml # indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml # indra/newview/skins/default/xui/en/sidepanel_appearance.xml # indra/newview/skins/default/xui/en/strings.xml # indra/newview/skins/default/xui/ja/panel_settings_sky_sunmoon.xml # indra/newview/skins/default/xui/pl/panel_settings_sky_sunmoon.xmlmaster
commit
4c355879cc
|
|
@ -2651,23 +2651,17 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
</map>
|
||||
<key>threejs</key>
|
||||
<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>name</key>
|
||||
<string>threejs</string>
|
||||
<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>
|
||||
<key>common</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
|
|
@ -2679,33 +2673,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<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>linux64</string>
|
||||
</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>
|
||||
<string>common</string>
|
||||
</map>
|
||||
</map>
|
||||
<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>
|
||||
</map>
|
||||
<key>tinygltf</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -125,6 +125,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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
|
|
@ -122,7 +122,7 @@ namespace LL
|
|||
size_t threads=1,
|
||||
size_t capacity=1024*1024,
|
||||
bool auto_shutdown = true):
|
||||
ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown)
|
||||
ThreadPoolBase(name, threads, new queue_t(name, capacity, false), auto_shutdown)
|
||||
{}
|
||||
~ThreadPoolUsing() override {}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,12 +30,15 @@ using Lock = LLCoros::LockType;
|
|||
/*****************************************************************************
|
||||
* WorkQueueBase
|
||||
*****************************************************************************/
|
||||
LL::WorkQueueBase::WorkQueueBase(const std::string& name):
|
||||
super(makeName(name))
|
||||
LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown)
|
||||
: super(makeName(name))
|
||||
{
|
||||
if (auto_shutdown)
|
||||
{
|
||||
// TODO: register for "LLApp" events so we can implicitly close() on
|
||||
// viewer shutdown.
|
||||
}
|
||||
}
|
||||
|
||||
void LL::WorkQueueBase::runUntilClose()
|
||||
{
|
||||
|
|
@ -212,8 +215,8 @@ void LL::WorkQueueBase::checkCoroutine(const std::string& method)
|
|||
/*****************************************************************************
|
||||
* WorkQueue
|
||||
*****************************************************************************/
|
||||
LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
|
||||
super(name),
|
||||
LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity, bool auto_shutdown):
|
||||
super(name, auto_shutdown),
|
||||
mQueue(capacity)
|
||||
{
|
||||
}
|
||||
|
|
@ -261,8 +264,8 @@ bool LL::WorkQueue::tryPop_(Work& work)
|
|||
/*****************************************************************************
|
||||
* WorkSchedule
|
||||
*****************************************************************************/
|
||||
LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity):
|
||||
super(name),
|
||||
LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity, bool auto_shutdown):
|
||||
super(name, auto_shutdown),
|
||||
mQueue(capacity)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ namespace LL
|
|||
* You may omit the WorkQueueBase name, in which case a unique name is
|
||||
* synthesized; for practical purposes that makes it anonymous.
|
||||
*/
|
||||
WorkQueueBase(const std::string& name);
|
||||
WorkQueueBase(const std::string& name, bool auto_shutdown);
|
||||
|
||||
/**
|
||||
* Since the point of WorkQueue is to pass work to some other worker
|
||||
|
|
@ -212,7 +212,7 @@ namespace LL
|
|||
* You may omit the WorkQueue name, in which case a unique name is
|
||||
* synthesized; for practical purposes that makes it anonymous.
|
||||
*/
|
||||
WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
|
||||
WorkQueue(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
|
||||
|
||||
/**
|
||||
* Since the point of WorkQueue is to pass work to some other worker
|
||||
|
|
@ -282,7 +282,7 @@ namespace LL
|
|||
* You may omit the WorkSchedule name, in which case a unique name is
|
||||
* synthesized; for practical purposes that makes it anonymous.
|
||||
*/
|
||||
WorkSchedule(const std::string& name = std::string(), size_t capacity=1024);
|
||||
WorkSchedule(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
|
||||
|
||||
/**
|
||||
* Since the point of WorkSchedule is to pass work to some other worker
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
@ -813,6 +845,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))
|
||||
{
|
||||
|
|
@ -973,6 +1022,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()))
|
||||
|
|
@ -1015,6 +1069,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;
|
||||
|
|
@ -1060,6 +1115,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);
|
||||
|
|
@ -1255,6 +1321,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;
|
||||
}
|
||||
|
||||
|
|
@ -1266,11 +1337,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;
|
||||
}
|
||||
|
||||
|
|
@ -1318,6 +1395,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))
|
||||
{
|
||||
|
|
@ -1440,6 +1528,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
|
||||
{
|
||||
|
|
@ -1487,6 +1592,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;
|
||||
}
|
||||
|
|
@ -1519,6 +1628,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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 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)
|
||||
|
|
|
|||
|
|
@ -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 ©)
|
|||
// 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 sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
inline F32 LLVector3::lengthSquared(void) const
|
||||
inline F32 LLVector3::lengthSquared() 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@ 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(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
|
||||
|
||||
|
|
@ -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,53 +310,38 @@ 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
|
||||
{
|
||||
return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
|
||||
return sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
inline F32 LLVector4::lengthSquared(void) const
|
||||
|
|
@ -398,12 +351,12 @@ inline F32 LLVector4::lengthSquared(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
|
||||
{
|
||||
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)
|
||||
|
|
@ -527,13 +476,13 @@ inline LLVector4::operator glm::vec4() const
|
|||
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)
|
||||
{
|
||||
LLVector4 vec = a - b;
|
||||
return (vec.lengthSquared());
|
||||
return vec.lengthSquared();
|
||||
}
|
||||
|
||||
inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u)
|
||||
|
|
@ -547,15 +496,11 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u)
|
|||
|
||||
inline F32 LLVector4::normalize(void)
|
||||
{
|
||||
F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
|
||||
F32 oomag;
|
||||
F32 mag = sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
|
||||
|
||||
if (mag > FP_MAG_THRESHOLD)
|
||||
{
|
||||
oomag = 1.f/mag;
|
||||
mV[VX] *= oomag;
|
||||
mV[VY] *= oomag;
|
||||
mV[VZ] *= oomag;
|
||||
*this /= mag;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -564,34 +509,18 @@ inline F32 LLVector4::normalize(void)
|
|||
mV[2] = 0.f;
|
||||
mag = 0;
|
||||
}
|
||||
return (mag);
|
||||
return mag;
|
||||
}
|
||||
|
||||
// deprecated
|
||||
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]);
|
||||
|
|
|
|||
|
|
@ -69,7 +69,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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ public:
|
|||
S32 notify(const LLSD& info);
|
||||
bool notifyChildren(const LLSD& info);
|
||||
|
||||
void draw();
|
||||
virtual void draw();
|
||||
|
||||
void storeOpenCloseState();
|
||||
void restoreOpenCloseState();
|
||||
|
|
|
|||
|
|
@ -1366,9 +1366,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)
|
||||
|
|
@ -1436,6 +1444,7 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)
|
|||
|
||||
if (visibility_changed && notify_parent)
|
||||
{
|
||||
rearrangeItems();
|
||||
notifyParentItemsRectChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -494,7 +494,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.
|
||||
|
|
|
|||
|
|
@ -1787,6 +1787,11 @@ LLRect LLFolderView::getVisibleRect()
|
|||
return visible_rect;
|
||||
}
|
||||
|
||||
S32 LLFolderView::getVisibleContentWidth()
|
||||
{
|
||||
return (mScrollContainer ? mScrollContainer->getVisibleContentRect().getWidth() : 0);
|
||||
}
|
||||
|
||||
bool LLFolderView::getShowSelectionContext()
|
||||
{
|
||||
if (mShowSelectionContext)
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ public:
|
|||
void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);
|
||||
void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; }
|
||||
LLRect getVisibleRect();
|
||||
S32 getVisibleContentWidth();
|
||||
|
||||
bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward);
|
||||
void setShowSelectionContext(bool show) { mShowSelectionContext = show; }
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
@ -62,7 +63,11 @@ LLUIColor LLFolderViewItem::sProtectedColor;
|
|||
S32 LLFolderViewItem::sTopPad = 0;
|
||||
LLUIImagePtr LLFolderViewItem::sFolderArrowImg;
|
||||
LLUIImagePtr LLFolderViewItem::sSelectionImg;
|
||||
LLUIImagePtr LLFolderViewItem::sFavoriteImg;
|
||||
LLUIImagePtr LLFolderViewItem::sFavoriteContentImg;
|
||||
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;
|
||||
|
|
@ -104,6 +109,8 @@ void LLFolderViewItem::initClass()
|
|||
sTopPad = default_params.item_top_pad;
|
||||
sFolderArrowImg = default_params.folder_arrow_image;
|
||||
sSelectionImg = default_params.selection_image;
|
||||
sFavoriteImg = default_params.favorite_image;
|
||||
sFavoriteContentImg = default_params.favorite_content_image;
|
||||
sSuffixFont = getLabelFontForStyle(LLFontGL::NORMAL);
|
||||
|
||||
// <FS:Ansariel> Make inventory selection color independent from menu color
|
||||
|
|
@ -132,6 +139,8 @@ void LLFolderViewItem::cleanupClass()
|
|||
sFonts.clear();
|
||||
sFolderArrowImg = nullptr;
|
||||
sSelectionImg = nullptr;
|
||||
sFavoriteImg = nullptr;
|
||||
sFavoriteContentImg = nullptr;
|
||||
sSuffixFont = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -140,13 +149,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"),
|
||||
|
|
@ -169,6 +180,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 ),
|
||||
|
|
@ -189,7 +202,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),
|
||||
|
|
@ -206,6 +219,21 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
|
|||
mForInventory(p.for_inventory),
|
||||
mItemTopPad(p.item_top_pad)
|
||||
{
|
||||
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);
|
||||
|
|
@ -228,6 +256,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)
|
||||
|
|
@ -342,6 +371,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()
|
||||
|
|
@ -376,6 +406,8 @@ void LLFolderViewItem::refreshSuffix()
|
|||
mIconOpen = vmi->getIconOpen();
|
||||
mIconOverlay = vmi->getIconOverlay();
|
||||
|
||||
mIsFavorite = vmi->isFavorite() && !vmi->isItemInTrash();
|
||||
|
||||
if (mRoot->useLabelSuffix())
|
||||
{
|
||||
// Very Expensive!
|
||||
|
|
@ -589,10 +621,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)
|
||||
|
|
@ -837,6 +874,38 @@ void LLFolderViewItem::drawOpenFolderArrow()
|
|||
}
|
||||
}
|
||||
|
||||
void LLFolderViewItem::drawFavoriteIcon()
|
||||
{
|
||||
static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true);
|
||||
static LLUICachedControl<bool> draw_hollow_star("InventoryFavoritesUseHollowStar", true);
|
||||
|
||||
LLUIImage* favorite_image = nullptr;
|
||||
if (draw_star && mIsFavorite)
|
||||
{
|
||||
favorite_image = sFavoriteImg;
|
||||
}
|
||||
else if (draw_hollow_star && mHasFavorites && !isOpen())
|
||||
{
|
||||
favorite_image = sFavoriteContentImg;
|
||||
}
|
||||
|
||||
if (favorite_image)
|
||||
{
|
||||
constexpr S32 PAD = 3;
|
||||
constexpr S32 image_size = 14;
|
||||
|
||||
S32 width = mRoot->getVisibleContentWidth(); // star should stick to scroller's right side
|
||||
if (width <= 0)
|
||||
{
|
||||
width = getRect().getWidth();
|
||||
}
|
||||
|
||||
gl_draw_scaled_image(
|
||||
width - image_size - PAD, getRect().getHeight() - mItemHeight + PAD,
|
||||
image_size, image_size, favorite_image->getImage(), sFgColor);
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/ bool LLFolderViewItem::isHighlightAllowed()
|
||||
{
|
||||
return mIsSelected;
|
||||
|
|
@ -994,6 +1063,7 @@ void LLFolderViewItem::draw()
|
|||
{
|
||||
drawOpenFolderArrow();
|
||||
}
|
||||
drawFavoriteIcon();
|
||||
|
||||
drawHighlight(show_context, filled, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
|
||||
|
|
@ -1065,7 +1135,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())
|
||||
{
|
||||
|
|
@ -1203,7 +1286,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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1229,6 +1313,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
|
||||
|
|
@ -1872,6 +1961,140 @@ 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)
|
||||
{
|
||||
// already processed either on previous run or by a different callback
|
||||
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->getViewModelItem()->isItemInTrash())
|
||||
{
|
||||
// do not display favorite-stars in trash
|
||||
self->mFavoritesDirtyFlags = 0;
|
||||
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->mFavoritesDirtyFlags == FAVORITE_ADDED)
|
||||
{
|
||||
if (!self->mHasFavorites)
|
||||
{
|
||||
// propagate up, exclude root
|
||||
LLFolderViewFolder* parent = self;
|
||||
while (parent
|
||||
&& (!parent->hasFavorites() || parent->mFavoritesDirtyFlags)
|
||||
&& !parent->getViewModelItem()->isAgentInventoryRoot())
|
||||
{
|
||||
parent->setHasFavorites(true);
|
||||
if (parent->mFavoritesDirtyFlags)
|
||||
{
|
||||
// Parent will remove onIdleUpdateFavorites later, don't remove now,
|
||||
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
|
||||
// but removing 'parent' can invalidate following iterator
|
||||
parent->mFavoritesDirtyFlags = 0;
|
||||
}
|
||||
parent = parent->getParentFolder();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "FAVORITE_ADDED for a folder without favorites" << LL_ENDL;
|
||||
self->mFavoritesDirtyFlags = 0;
|
||||
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
|
||||
}
|
||||
}
|
||||
else if (self->mFavoritesDirtyFlags > FAVORITE_ADDED)
|
||||
{
|
||||
// full check
|
||||
LLFolderViewFolder* parent = self;
|
||||
while (parent && !parent->getViewModelItem()->isAgentInventoryRoot())
|
||||
{
|
||||
bool has_favorites = false;
|
||||
for (items_t::iterator iter = parent->mItems.begin();
|
||||
iter != parent->mItems.end();)
|
||||
{
|
||||
items_t::iterator iit = iter++;
|
||||
if ((*iit)->isFavorite())
|
||||
{
|
||||
has_favorites = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (folders_t::iterator iter = parent->mFolders.begin();
|
||||
iter != parent->mFolders.end() && !has_favorites;)
|
||||
{
|
||||
folders_t::iterator fit = iter++;
|
||||
if ((*fit)->isFavorite() || (*fit)->hasFavorites())
|
||||
{
|
||||
has_favorites = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_favorites)
|
||||
{
|
||||
if (parent->hasFavorites())
|
||||
{
|
||||
parent->setHasFavorites(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing changed
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// propagate up, exclude root
|
||||
while (parent
|
||||
&& (!parent->hasFavorites() || parent->mFavoritesDirtyFlags)
|
||||
&& !parent->getViewModelItem()->isAgentInventoryRoot())
|
||||
{
|
||||
parent->setHasFavorites(true);
|
||||
if (parent->mFavoritesDirtyFlags)
|
||||
{
|
||||
// Parent will remove onIdleUpdateFavorites later, don't remove now,
|
||||
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
|
||||
// but removing 'parent' can invalidate following iterator
|
||||
parent->mFavoritesDirtyFlags = 0;
|
||||
}
|
||||
parent = parent->getParentFolder();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (parent->mFavoritesDirtyFlags)
|
||||
{
|
||||
// Parent will remove onIdleUpdateFavorites later, don't remove now.
|
||||
// We are inside gIdleCallbacks. Removing 'self' callback is safe,
|
||||
// but removing 'parent' can invalidate following iterator
|
||||
parent->mFavoritesDirtyFlags = 0;
|
||||
}
|
||||
parent = parent->getParentFolder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLFolderViewFolder::isRemovable()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -97,6 +99,8 @@ protected:
|
|||
LLWString mLabel;
|
||||
S32 mLabelWidth;
|
||||
bool mLabelWidthDirty;
|
||||
bool mIsFavorite;
|
||||
bool mHasFavorites;
|
||||
S32 mLabelPaddingRight;
|
||||
LLFolderViewFolder* mParentFolder;
|
||||
LLPointer<LLFolderViewModelItem> mViewModelItem;
|
||||
|
|
@ -126,7 +130,7 @@ protected:
|
|||
mIsCurSelection,
|
||||
mDragAndDropTarget,
|
||||
mIsMouseOverTitle,
|
||||
mAllowWear,
|
||||
mMarketplaceItem,
|
||||
mAllowDrop,
|
||||
mSingleFolderMode,
|
||||
mDoubleClickOverride,
|
||||
|
|
@ -137,6 +141,7 @@ protected:
|
|||
|
||||
LLUIColor mFontColor;
|
||||
LLUIColor mFontHighlightColor;
|
||||
static bool sColorSetInitialized;
|
||||
|
||||
// <FS:Ansariel> Inventory specials
|
||||
bool mForInventory;
|
||||
|
|
@ -153,9 +158,11 @@ protected:
|
|||
static LLUIColor sFilterTextColor;
|
||||
static LLUIColor sSuffixColor;
|
||||
static LLUIColor sSearchStatusColor;
|
||||
static LLUIColor sFavoriteColor;
|
||||
// <FS:Ansariel> Special for protected items
|
||||
static LLUIColor sProtectedColor;
|
||||
|
||||
|
||||
// this is an internal method used for adding items to folders. A
|
||||
// no-op at this level, but reimplemented in derived classes.
|
||||
virtual void addItem(LLFolderViewItem*) { }
|
||||
|
|
@ -218,6 +225,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();
|
||||
|
||||
|
|
@ -308,6 +317,7 @@ public:
|
|||
// virtual void handleDropped();
|
||||
virtual void draw();
|
||||
void drawOpenFolderArrow();
|
||||
void drawFavoriteIcon();
|
||||
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,
|
||||
|
|
@ -326,6 +336,8 @@ private:
|
|||
static S32 sTopPad;
|
||||
static LLUIImagePtr sFolderArrowImg;
|
||||
static LLUIImagePtr sSelectionImg;
|
||||
static LLUIImagePtr sFavoriteImg;
|
||||
static LLUIImagePtr sFavoriteContentImg;
|
||||
static LLFontGL* sSuffixFont;
|
||||
|
||||
LLFontVertexBuffer mLabelFontBuffer;
|
||||
|
|
@ -415,6 +427,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();
|
||||
|
|
|
|||
|
|
@ -163,6 +163,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;
|
||||
|
|
@ -172,6 +173,7 @@ public:
|
|||
virtual void move( LLFolderViewModelItem* parent_listener ) = 0;
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -184,6 +186,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?
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "llfocusmgr.h"
|
||||
#include "llcoord.h"
|
||||
#include "llwindow.h"
|
||||
#include "llemojihelper.h"
|
||||
#include "llcriticaldamp.h"
|
||||
#include "lluictrlfactory.h"
|
||||
|
||||
|
|
@ -1432,6 +1433,7 @@ void LLMenuItemBranchDownGL::openMenu( void )
|
|||
}
|
||||
else
|
||||
{
|
||||
LLEmojiHelper::instance().hideHelper(nullptr, true);
|
||||
if (branch->getTornOff())
|
||||
{
|
||||
LLFloater * branch_parent = dynamic_cast<LLFloater *>(branch->getParent());
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -274,6 +274,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
|
|||
mEnableTooltipPaste(p.enable_tooltip_paste),
|
||||
mPassDelete(false),
|
||||
mKeepSelectionOnReturn(false),
|
||||
mSelectAllOnFocusReceived(false),
|
||||
mSelectedOnFocusReceived(false),
|
||||
mEnableTabRemove(p.enable_tab_remove) // <FS:Ansariel> FIRE-15591: Optional tab remove
|
||||
{
|
||||
mSourceID.generate();
|
||||
|
|
@ -448,6 +450,7 @@ void LLTextEditor::selectNext(const std::string& search_text_in, bool case_insen
|
|||
// [/SL:KB]
|
||||
|
||||
mIsSelecting = true;
|
||||
mSelectedOnFocusReceived = false;
|
||||
mSelectionEnd = mCursorPos;
|
||||
mSelectionStart = llmin((S32)getLength(), (S32)(mCursorPos + search_text.size()));
|
||||
}
|
||||
|
|
@ -739,6 +742,13 @@ bool LLTextEditor::canSelectAll() const
|
|||
return true;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLTextEditor::deselect()
|
||||
{
|
||||
LLTextBase::deselect();
|
||||
mSelectedOnFocusReceived = false;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLTextEditor::selectAll()
|
||||
{
|
||||
|
|
@ -757,6 +767,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)
|
||||
{
|
||||
static LLUICachedControl<bool> useBWEmojis( "FSUseBWEmojis", false); // <FS:Beq/> Add B&W emoji font support
|
||||
|
|
@ -835,8 +850,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;
|
||||
|
|
@ -2334,6 +2357,11 @@ void LLTextEditor::focusLostHelper()
|
|||
gEditMenuHandler = NULL;
|
||||
}
|
||||
|
||||
if (mSelectedOnFocusReceived)
|
||||
{
|
||||
deselect();
|
||||
}
|
||||
|
||||
if (mCommitOnFocusLost)
|
||||
{
|
||||
onCommit();
|
||||
|
|
|
|||
|
|
@ -143,8 +143,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();
|
||||
|
||||
|
|
@ -353,6 +355,8 @@ private:
|
|||
bool mEnableTooltipPaste;
|
||||
bool mPassDelete;
|
||||
bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter
|
||||
bool mSelectAllOnFocusReceived;
|
||||
bool mSelectedOnFocusReceived;
|
||||
bool mEnableTabRemove; // <FS:Ansariel> FIRE-15591: Optional tab remove
|
||||
|
||||
LLUUID mSourceID;
|
||||
|
|
|
|||
|
|
@ -350,10 +350,14 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
|
|||
LLWindowWin32Thread();
|
||||
|
||||
void run() override;
|
||||
void close() override;
|
||||
|
||||
// closes queue, wakes thread, waits until thread closes
|
||||
void wakeAndDestroy();
|
||||
// Detroys handles and window
|
||||
// Either post to or call from window thread
|
||||
void destroyWindow();
|
||||
|
||||
// Closes queue, wakes thread, waits until thread closes.
|
||||
// Call from main thread
|
||||
bool wakeAndDestroy();
|
||||
|
||||
void glReady()
|
||||
{
|
||||
|
|
@ -410,6 +414,7 @@ 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;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -863,6 +868,7 @@ LLWindowWin32::~LLWindowWin32()
|
|||
}
|
||||
|
||||
delete mDragDrop;
|
||||
mDragDrop = NULL;
|
||||
|
||||
delete [] mWindowTitle;
|
||||
mWindowTitle = NULL;
|
||||
|
|
@ -874,6 +880,7 @@ LLWindowWin32::~LLWindowWin32()
|
|||
mWindowClassName = NULL;
|
||||
|
||||
delete mWindowThread;
|
||||
mWindowThread = NULL;
|
||||
}
|
||||
|
||||
void LLWindowWin32::show()
|
||||
|
|
@ -992,7 +999,11 @@ void LLWindowWin32::close()
|
|||
mhDC = NULL;
|
||||
mWindowHandle = NULL;
|
||||
|
||||
mWindowThread->wakeAndDestroy();
|
||||
if (mWindowThread->wakeAndDestroy())
|
||||
{
|
||||
// thread will delete itselfs once done
|
||||
mWindowThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLWindowWin32::isValid()
|
||||
|
|
@ -1533,10 +1544,10 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
|
|||
|
||||
LL_INFOS("Window") << "pixel formats done." << LL_ENDL ;
|
||||
|
||||
S32 swap_method = 0;
|
||||
S32 swap_method = 0;
|
||||
S32 cur_format = 0;
|
||||
const S32 max_format = (S32)num_formats - 1;
|
||||
GLint swap_query = WGL_SWAP_METHOD_ARB;
|
||||
GLint swap_query = WGL_SWAP_METHOD_ARB;
|
||||
|
||||
// SL-14705 Fix name tags showing in front of objects with AMD GPUs.
|
||||
// On AMD hardware we need to iterate from the first pixel format to the end.
|
||||
|
|
@ -1759,6 +1770,7 @@ void LLWindowWin32::recreateWindow(RECT window_rect, DWORD dw_ex_style, DWORD dw
|
|||
// important to call DestroyWindow() from the window thread
|
||||
if (!destroy_window_handler(oldWindowHandle))
|
||||
{
|
||||
|
||||
LL_WARNS("Window") << "Failed to properly close window before recreating it!"
|
||||
<< LL_ENDL;
|
||||
}
|
||||
|
|
@ -3209,10 +3221,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
|
||||
|
|
@ -4742,25 +4758,11 @@ void LLWindowWin32::getWindowChrome( U32 &aChromeW, U32 &aChromeH )
|
|||
#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
|
||||
|
|
@ -4917,6 +4919,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
|
|||
{
|
||||
sWindowThreadId = std::this_thread::get_id();
|
||||
LogChange logger("Window");
|
||||
|
||||
//as good a place as any to up the MM timer resolution (see ms_sleep)
|
||||
//attempt to set timer resolution to 1ms
|
||||
TIMECAPS tc;
|
||||
|
|
@ -4954,6 +4957,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
|
|||
", ", msg.wParam, ")");
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
mMessageQueue.pushFront(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -4973,108 +4977,105 @@ void LLWindowWin32::LLWindowWin32Thread::run()
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
destroyWindow();
|
||||
|
||||
if (mDeleteOnExit)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
|
||||
void LLWindowWin32::LLWindowWin32Thread::destroyWindow()
|
||||
{
|
||||
if (mWindowHandleThrd != NULL && IsWindow(mWindowHandleThrd))
|
||||
{
|
||||
if (mhDCThrd)
|
||||
{
|
||||
if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
|
||||
{
|
||||
LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
|
||||
}
|
||||
mhDCThrd = NULL;
|
||||
}
|
||||
|
||||
// This causes WM_DESTROY to be sent *immediately*
|
||||
if (!destroy_window_handler(mWindowHandleThrd))
|
||||
{
|
||||
LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something killed the window while we were busy destroying gl or handle somehow got broken
|
||||
LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
|
||||
}
|
||||
mWindowHandleThrd = NULL;
|
||||
mhDCThrd = NULL;
|
||||
}
|
||||
|
||||
bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
|
||||
{
|
||||
if (mQueue->isClosed())
|
||||
{
|
||||
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.
|
||||
// Also hiding window now prevents user from suspending it
|
||||
// via some action (like dragging it around)
|
||||
ShowWindow(mWindowHandleThrd, SW_HIDE);
|
||||
// Hide the window immediately to prevent user interaction during shutdown
|
||||
if (mWindowHandleThrd)
|
||||
{
|
||||
ShowWindow(mWindowHandleThrd, SW_HIDE);
|
||||
}
|
||||
|
||||
// Schedule destruction
|
||||
mGLReady = false;
|
||||
|
||||
// Capture current handle before we lose it
|
||||
HWND old_handle = mWindowHandleThrd;
|
||||
post([this]()
|
||||
{
|
||||
if (IsWindow(mWindowHandleThrd))
|
||||
{
|
||||
if (mhDCThrd)
|
||||
{
|
||||
if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
|
||||
{
|
||||
LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
|
||||
}
|
||||
mhDCThrd = NULL;
|
||||
}
|
||||
|
||||
// This causes WM_DESTROY to be sent *immediately*
|
||||
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;
|
||||
});
|
||||
// Clear the user data to prevent callbacks from finding us
|
||||
if (old_handle)
|
||||
{
|
||||
SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL);
|
||||
}
|
||||
|
||||
// Signal thread to clean up when done
|
||||
mDeleteOnExit = true;
|
||||
|
||||
// Close the queue first
|
||||
LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
|
||||
mQueue->close();
|
||||
|
||||
// Post a nonsense user message to wake up the thread in
|
||||
// case it is waiting for a getMessage()
|
||||
// Wake up the thread if it's stuck in GetMessage()
|
||||
if (old_handle)
|
||||
{
|
||||
WPARAM wparam{ 0xB0B0 };
|
||||
LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle
|
||||
<< ", " << WM_DUMMY_
|
||||
<< ", " << wparam << ")" << std::dec << LL_ENDL;
|
||||
|
||||
// Use PostMessage to signal thread to wake up
|
||||
PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
|
||||
}
|
||||
|
||||
// There are cases where window will refuse to close,
|
||||
// can't wait forever on join, check state instead
|
||||
LLTimer timeout;
|
||||
timeout.setTimerExpirySec(2.0);
|
||||
while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd)
|
||||
// Cleanly detach threads instead of joining them to avoid blocking the main thread
|
||||
// This is acceptable since the thread will self-delete with mDeleteOnExit
|
||||
for (auto& pair : mThreads)
|
||||
{
|
||||
ms_sleep(100);
|
||||
try {
|
||||
// Only detach if the thread is joinable
|
||||
if (pair.second.joinable())
|
||||
{
|
||||
pair.second.detach();
|
||||
}
|
||||
}
|
||||
catch (const std::system_error& e) {
|
||||
LL_WARNS("Window") << "Exception detaching thread: " << e.what() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (getQueue().done() || mWindowHandleThrd == NULL)
|
||||
{
|
||||
// Window is closed, started closing or is cleaning up
|
||||
// now wait for our single thread to die.
|
||||
if (mWindowHandleThrd)
|
||||
{
|
||||
LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
|
||||
}
|
||||
for (auto& pair : mThreads)
|
||||
{
|
||||
pair.second.join();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something suspended window thread, can't afford to wait forever
|
||||
// so kill thread instead
|
||||
// Ex: This can happen if user starts dragging window arround (if it
|
||||
// was visible) or a modal notification pops up
|
||||
LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL;
|
||||
|
||||
for (auto& pair : mThreads)
|
||||
{
|
||||
// very unsafe
|
||||
TerminateThread(pair.second.native_handle(), 0);
|
||||
pair.second.detach();
|
||||
}
|
||||
}
|
||||
LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLWindowWin32::post(const std::function<void()>& func)
|
||||
|
|
|
|||
|
|
@ -458,6 +458,7 @@ set(viewer_SOURCE_FILES
|
|||
llhudeffectpointat.cpp
|
||||
llhudeffecttrail.cpp
|
||||
llhudeffectblob.cpp
|
||||
llhudeffectresetskeleton.cpp
|
||||
llhudicon.cpp
|
||||
llhudmanager.cpp
|
||||
llhudnametag.cpp
|
||||
|
|
@ -1278,6 +1279,7 @@ set(viewer_HEADER_FILES
|
|||
llhudeffectpointat.h
|
||||
llhudeffecttrail.h
|
||||
llhudeffectblob.h
|
||||
llhudeffectresetskeleton.h
|
||||
llhudicon.h
|
||||
llhudmanager.h
|
||||
llhudnametag.h
|
||||
|
|
|
|||
|
|
@ -3630,6 +3630,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>
|
||||
|
|
@ -18557,10 +18568,32 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<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>
|
||||
|
|
@ -23246,6 +23279,50 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<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>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>InventoryFavoritesUseHollowStar</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show star near folders that contain favorites</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>InventoryFavoritesColorText</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>render favorite items using InventoryFavoriteText as color</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>InventoryAddAttachmentBehavior</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Defines behavior when hitting return on an inventory item</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>StatsReportMaxDuration</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -602,7 +602,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>
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ void GLTFSceneManager::uploadSelection()
|
|||
LLFloaterPerms::getGroupPerms("Uploads"),
|
||||
LLFloaterPerms::getEveryonePerms("Uploads"),
|
||||
expected_upload_cost,
|
||||
LLUUID::null,
|
||||
false,
|
||||
finish,
|
||||
failure));
|
||||
|
|
@ -283,6 +284,7 @@ void GLTFSceneManager::uploadSelection()
|
|||
LLFloaterPerms::getGroupPerms("Uploads"),
|
||||
LLFloaterPerms::getEveryonePerms("Uploads"),
|
||||
expected_upload_cost,
|
||||
LLUUID::null,
|
||||
false,
|
||||
finish,
|
||||
failure));
|
||||
|
|
@ -559,6 +561,7 @@ void GLTFSceneManager::update()
|
|||
LLFloaterPerms::getGroupPerms("Uploads"),
|
||||
LLFloaterPerms::getEveryonePerms("Uploads"),
|
||||
expected_upload_cost,
|
||||
LLUUID::null,
|
||||
false,
|
||||
finish,
|
||||
failure));
|
||||
|
|
|
|||
|
|
@ -140,8 +140,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;
|
||||
|
|
@ -242,7 +242,6 @@ private:
|
|||
LLVector3d mPosGlobal;
|
||||
};
|
||||
|
||||
|
||||
class LLTeleportRequestViaLocationLookAt : public LLTeleportRequestViaLocation
|
||||
{
|
||||
public:
|
||||
|
|
@ -690,7 +689,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())
|
||||
{
|
||||
|
|
@ -716,13 +715,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)
|
||||
|
|
@ -962,7 +956,6 @@ void LLAgent::movePitch(F32 mag)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Does this parcel allow you to fly?
|
||||
bool LLAgent::canFly()
|
||||
{
|
||||
|
|
@ -1061,7 +1054,6 @@ void LLAgent::setFlying(bool fly, bool fail_sound)
|
|||
LLFloaterMove::setFlyingMode(fly);
|
||||
}
|
||||
|
||||
|
||||
// UI based mechanism of setting fly state
|
||||
//-----------------------------------------------------------------------------
|
||||
// toggleFlying()
|
||||
|
|
@ -1309,7 +1301,6 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
|
|||
mRegionChangedSignal();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getRegion()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1318,7 +1309,6 @@ LLViewerRegion *LLAgent::getRegion() const
|
|||
return mRegionp;
|
||||
}
|
||||
|
||||
|
||||
LLHost LLAgent::getRegionHost() const
|
||||
{
|
||||
if (mRegionp)
|
||||
|
|
@ -1349,7 +1339,6 @@ bool LLAgent::inPrelude()
|
|||
return mRegionp && mRegionp->isPrelude();
|
||||
}
|
||||
|
||||
|
||||
std::string LLAgent::getRegionCapability(const std::string &name)
|
||||
{
|
||||
if (!mRegionp)
|
||||
|
|
@ -1358,7 +1347,6 @@ std::string LLAgent::getRegionCapability(const std::string &name)
|
|||
return mRegionp->getCapability(name);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// canManageEstate()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1386,7 +1374,6 @@ void LLAgent::sendMessage()
|
|||
gMessageSystem->sendMessage(mRegionp->getHost());
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// sendReliableMessage()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1420,7 +1407,6 @@ LLVector3 LLAgent::getVelocity() const
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// setPositionAgent()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1494,7 +1480,6 @@ const LLVector3 &LLAgent::getPositionAgent()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return mFrameAgent.getOrigin();
|
||||
}
|
||||
|
||||
|
|
@ -1503,7 +1488,6 @@ boost::signals2::connection LLAgent::whenPositionChanged(position_signal_t::slot
|
|||
return mOnPositionChanged.connect(fn);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getRegionsVisited()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1520,7 +1504,6 @@ F64 LLAgent::getDistanceTraveled() const
|
|||
return mDistanceTraveled;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getPosAgentFromGlobal()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1531,7 +1514,6 @@ LLVector3 LLAgent::getPosAgentFromGlobal(const LLVector3d &pos_global) const
|
|||
return pos_agent;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getPosGlobalFromAgent()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1552,7 +1534,6 @@ void LLAgent::sitDown()
|
|||
setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// resetAxes()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1561,7 +1542,6 @@ void LLAgent::resetAxes()
|
|||
mFrameAgent.resetAxes();
|
||||
}
|
||||
|
||||
|
||||
// Copied from LLCamera::setOriginAndLookAt
|
||||
// Look_at must be unit vector
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1590,7 +1570,6 @@ void LLAgent::resetAxes(const LLVector3 &look_at)
|
|||
mFrameAgent.setAxes(look_at, left, up);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// rotate()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1599,7 +1578,6 @@ void LLAgent::rotate(F32 angle, const LLVector3 &axis)
|
|||
mFrameAgent.rotate(angle, axis);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// rotate()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1608,7 +1586,6 @@ void LLAgent::rotate(F32 angle, F32 x, F32 y, F32 z)
|
|||
mFrameAgent.rotate(angle, x, y, z);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// rotate()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1617,7 +1594,6 @@ void LLAgent::rotate(const LLMatrix3 &matrix)
|
|||
mFrameAgent.rotate(matrix);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// rotate()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1626,7 +1602,6 @@ void LLAgent::rotate(const LLQuaternion &quaternion)
|
|||
mFrameAgent.rotate(quaternion);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getReferenceUpVector()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1655,7 +1630,6 @@ LLVector3 LLAgent::getReferenceUpVector()
|
|||
return up_vector;
|
||||
}
|
||||
|
||||
|
||||
// Radians, positive is forward into ground
|
||||
//-----------------------------------------------------------------------------
|
||||
// pitch()
|
||||
|
|
@ -1699,7 +1673,6 @@ void LLAgent::pitch(F32 angle)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// roll()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1708,7 +1681,6 @@ void LLAgent::roll(F32 angle)
|
|||
mFrameAgent.roll(angle);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// yaw()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1720,7 +1692,6 @@ void LLAgent::yaw(F32 angle)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns a quat that represents the rotation of the agent in the absolute frame
|
||||
//-----------------------------------------------------------------------------
|
||||
// getQuat()
|
||||
|
|
@ -1756,7 +1727,6 @@ void LLAgent::setControlFlags(U32 mask)
|
|||
mControlFlags |= mask;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// clearControlFlags()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -2179,7 +2149,6 @@ void LLAgent::startAutoPilotGlobal(
|
|||
mAutoPilotNoProgressFrameCount = 0;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// setAutoPilotTargetGlobal
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -2233,7 +2202,6 @@ void LLAgent::startFollowPilot(const LLUUID &leader_id, bool allow_flying, F32 s
|
|||
allow_flying);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// stopAutoPilot()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -2275,7 +2243,6 @@ void LLAgent::stopAutoPilot(bool user_cancel)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns necessary agent pitch and yaw changes, radians.
|
||||
//-----------------------------------------------------------------------------
|
||||
// autoPilot()
|
||||
|
|
@ -2464,7 +2431,6 @@ void LLAgent::autoPilot(F32 *delta_yaw)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// propagate()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -2485,18 +2451,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
|
||||
|
|
@ -2677,7 +2644,6 @@ void LLAgent::clearRenderState(U8 clearstate)
|
|||
mRenderState &= ~clearstate;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// getRenderState()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -2719,6 +2685,7 @@ void LLAgent::endAnimationUpdateUI()
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (gAgentCamera.getCameraMode() == gAgentCamera.getLastCameraMode())
|
||||
{
|
||||
// We're already done endAnimationUpdateUI for this transition.
|
||||
|
|
@ -2835,7 +2802,6 @@ void LLAgent::endAnimationUpdateUI()
|
|||
}
|
||||
// </FS:PP>
|
||||
|
||||
|
||||
gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR);
|
||||
if( gMorphView )
|
||||
{
|
||||
|
|
@ -3557,7 +3523,6 @@ void LLAgent::sendMaturityPreferenceToServer(U8 pPreferredMaturity)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferredMaturity)
|
||||
{
|
||||
U8 maturity = SIM_ACCESS_MIN;
|
||||
|
|
@ -3633,7 +3598,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())
|
||||
|
|
@ -3988,7 +3952,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
|
||||
|
|
@ -5104,7 +5067,6 @@ void LLAgent::onCapabilitiesReceivedAfterTeleport()
|
|||
check_merchant_status();
|
||||
}
|
||||
|
||||
|
||||
//void LLAgent::teleportRequest(
|
||||
// const U64& region_handle,
|
||||
// const LLVector3& pos_local,
|
||||
|
|
@ -5244,7 +5206,6 @@ void LLAgent::doTeleportViaLure(const LLUUID& lure_id, bool godlike)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// James Cook, July 28, 2005
|
||||
void LLAgent::teleportCancel()
|
||||
{
|
||||
|
|
@ -5555,7 +5516,6 @@ LLAgent::ETeleportState LLAgent::getTeleportState() const
|
|||
// teleportRequest(region_handle, pos_local, getTeleportKeepsLookAt());
|
||||
//}
|
||||
|
||||
|
||||
void LLAgent::setTeleportState(ETeleportState state)
|
||||
{
|
||||
if (mTeleportRequest && (state != TELEPORT_NONE) && (mTeleportRequest->getStatus() == LLTeleportRequest::kFailed))
|
||||
|
|
@ -5751,7 +5711,6 @@ void LLAgent::stopFidget()
|
|||
gAgent.sendAnimationRequests(anims, ANIM_REQUEST_STOP);
|
||||
}
|
||||
|
||||
|
||||
void LLAgent::requestEnterGodMode()
|
||||
{
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
|
|
@ -5887,7 +5846,6 @@ void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& dire
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// <FS:Ansariel> Keep this for OpenSim
|
||||
//void LLAgent::updateAgentUserInfoCoro(std::string capurl, std::string directory_visibility)
|
||||
void LLAgent::updateAgentUserInfoCoro(std::string capurl, bool im_via_email, std::string directory_visibility)
|
||||
|
|
|
|||
|
|
@ -1592,13 +1592,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));
|
||||
|
|
@ -1606,7 +1605,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
|
||||
|
|
@ -1625,8 +1624,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;
|
||||
|
|
@ -2580,7 +2579,8 @@ void LLAgentCamera::changeCameraToFollow(bool animate)
|
|||
AOEngine::getInstance()->inMouselook(false);
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,11 +121,8 @@ private:
|
|||
// Preset
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
// [RLVa:KB] - @setcam family
|
||||
/** Determines default camera offset scale depending on the current camera preset */
|
||||
ECameraPreset getCameraPreset() const { return mCameraPreset; }
|
||||
// [/RLVa:KB]
|
||||
void switchCameraPreset(ECameraPreset preset);
|
||||
ECameraPreset getCameraPreset() const { return mCameraPreset; }
|
||||
/** Determines default camera offset depending on the current camera preset */
|
||||
LLVector3 getCameraOffsetInitial();
|
||||
// [RLVa:KB] - @setcam_eyeoffsetscale
|
||||
|
|
@ -177,8 +174,9 @@ public:
|
|||
F32 getCameraMinOffGround(); // Minimum height off ground for this mode, meters
|
||||
void setCameraCollidePlane(const LLVector4 &plane) { mCameraCollidePlane = plane; }
|
||||
bool calcCameraMinDistance(F32 &obj_min_distance);
|
||||
F32 getCurrentCameraBuildOffset() { return (F32)mCameraFocusOffset.length(); }
|
||||
F32 getCurrentCameraBuildOffset() const { return (F32)mCameraFocusOffset.length(); }
|
||||
void clearCameraLag() { mCameraLag.clearVec(); }
|
||||
const LLVector3& getCameraUpVector() const { return mCameraUpVector; }
|
||||
private:
|
||||
LLVector3 getAvatarRootPosition();
|
||||
|
||||
|
|
@ -188,7 +186,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;
|
||||
|
|
@ -320,7 +317,7 @@ public:
|
|||
F32 getAgentHUDTargetZoom();
|
||||
|
||||
void resetCameraZoomFraction();
|
||||
F32 getCurrentCameraZoomFraction() { return mCameraZoomFraction; }
|
||||
F32 getCurrentCameraZoomFraction() const { return mCameraZoomFraction; }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Pan
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -844,7 +844,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);
|
||||
|
|
|
|||
|
|
@ -2116,7 +2116,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
|
||||
|
||||
|
|
@ -2146,7 +2146,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2428,7 +2431,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
|
|||
}
|
||||
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);
|
||||
|
||||
|
|
@ -4272,7 +4275,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);
|
||||
|
|
@ -4380,7 +4383,7 @@ void LLAppearanceMgr::syncCofVersionAndRefreshCoro()
|
|||
/*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;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,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,
|
||||
|
|
|
|||
|
|
@ -504,6 +504,12 @@ static bool app_metrics_qa_mode = false;
|
|||
|
||||
void idle_afk_check()
|
||||
{
|
||||
// Don't check AFK status during startup states
|
||||
if (LLStartUp::getStartupState() < STATE_STARTED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// check idle timers
|
||||
F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32();
|
||||
// <FS:CR> Cache frequently hit location
|
||||
|
|
@ -514,11 +520,20 @@ void idle_afk_check()
|
|||
// [/RLVa:KB]
|
||||
// static LLCachedControl<S32> afk_timeout(gSavedSettings, "AFKTimeout", 300);
|
||||
// <FS:CR> Explicit conversions just cos.
|
||||
//if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK())
|
||||
if (static_cast<S32>(afk_timeout) && (current_idle > static_cast<F32>(afk_timeout)) && ! gAgent.getAFK())
|
||||
//if (afk_timeout() && (current_idle > afk_timeout()) && !gAgent.getAFK())
|
||||
if (static_cast<S32>(afk_timeout) && (current_idle > static_cast<F32>(afk_timeout)))
|
||||
{
|
||||
LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
|
||||
gAgent.setAFK();
|
||||
if (!gAgent.getAFK())
|
||||
{
|
||||
LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL;
|
||||
gAgent.setAFK();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Refresh timer so that random one click or hover won't clear the status.
|
||||
// But expanding the window still should lift afk status
|
||||
gAwayTimer.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2181,36 +2196,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();
|
||||
|
|
@ -2409,6 +2394,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();
|
||||
|
||||
|
|
|
|||
|
|
@ -537,11 +537,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) )
|
||||
|
|
|
|||
|
|
@ -101,6 +101,12 @@ LLVOAvatar *LLControlAvatar::getAttachedAvatar()
|
|||
|
||||
void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const
|
||||
{
|
||||
static LLCachedControl<F32> anim_max_legal_offset(gSavedSettings, "AnimatedObjectsMaxLegalOffset", MAX_LEGAL_OFFSET);
|
||||
F32 max_legal_offset = llmax(anim_max_legal_offset(), 0.f);
|
||||
|
||||
static LLCachedControl<F32> anim_max_legal_size(gSavedSettings, "AnimatedObjectsMaxLegalSize", MAX_LEGAL_SIZE);
|
||||
F32 max_legal_size = llmax(anim_max_legal_size(), 1.f);
|
||||
|
||||
new_pos_fixup = LLVector3();
|
||||
new_scale_fixup = 1.0f;
|
||||
LLVector3 vol_pos = mRootVolp->getRenderPosition();
|
||||
|
|
@ -125,14 +131,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;
|
||||
|
|
@ -140,11 +146,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -227,7 +233,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
|
||||
|
|
|
|||
|
|
@ -691,7 +691,7 @@ void LLConversationLog::onClearLogResponse(const LLSD& notification, const LLSD&
|
|||
{
|
||||
mConversations.clear();
|
||||
notifyObservers();
|
||||
cache();
|
||||
saveToFile(getFileName());
|
||||
deleteBackupLogs();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,6 +82,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; }
|
||||
|
|
|
|||
|
|
@ -420,17 +420,15 @@ bool LLFloaterAutoReplaceSettings::callbackNewListName(const LLSD& notification,
|
|||
{
|
||||
LL_DEBUGS("AutoReplace")<<"called"<<LL_ENDL;
|
||||
|
||||
// <FS:Ansariel> FIRE-31256: Add Cancel button for new auto-replace list dialog
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
if (option != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
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);
|
||||
|
|
@ -516,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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -128,8 +128,8 @@ std::string STATUS[] =
|
|||
//-----------------------------------------------------------------------------
|
||||
// LLFloaterBvhPreview()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename) :
|
||||
LLFloaterNameDesc(filename)
|
||||
LLFloaterBvhPreview::LLFloaterBvhPreview(const LLSD& args) :
|
||||
LLFloaterNameDesc(args)
|
||||
{
|
||||
mLastMouseX = 0;
|
||||
mLastMouseY = 0;
|
||||
|
|
@ -1447,7 +1447,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class LLFloaterBvhPreview : public LLFloaterNameDesc
|
|||
friend class LLPreviewAnimation;
|
||||
|
||||
public:
|
||||
LLFloaterBvhPreview(const std::string& filename);
|
||||
LLFloaterBvhPreview(const LLSD& args);
|
||||
virtual ~LLFloaterBvhPreview();
|
||||
|
||||
bool postBuild();
|
||||
|
|
|
|||
|
|
@ -133,7 +133,8 @@ protected:
|
|||
LLSettingsEditPanel() :
|
||||
LLPanel(),
|
||||
mIsDirty(false),
|
||||
mOnDirtyChanged()
|
||||
mOnDirtyChanged(),
|
||||
mCanEdit(false)
|
||||
{}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ constexpr F32 ALPHA_EMPTY_THRESHOLD_RATIO = 0.999f;
|
|||
//-----------------------------------------------------------------------------
|
||||
// LLFloaterImagePreview()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) :
|
||||
LLFloaterNameDesc(filename),
|
||||
LLFloaterImagePreview::LLFloaterImagePreview(const LLSD& args) :
|
||||
LLFloaterNameDesc(args),
|
||||
|
||||
mAvatarPreview(NULL),
|
||||
mSculptedPreview(NULL),
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ protected:
|
|||
class LLFloaterImagePreview : public LLFloaterNameDesc
|
||||
{
|
||||
public:
|
||||
LLFloaterImagePreview(const std::string& filename);
|
||||
LLFloaterImagePreview(const LLSD& args);
|
||||
virtual ~LLFloaterImagePreview();
|
||||
|
||||
bool postBuild() override;
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -425,14 +425,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)
|
||||
|
|
@ -592,7 +592,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);
|
||||
|
|
@ -1850,7 +1850,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());
|
||||
}
|
||||
|
||||
|
|
@ -1973,9 +1973,15 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
|
|||
|| index == LLModelPreview::GENERATE // <FS:Beq/> Improved LOD generation
|
||||
|| 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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
static void onSuffixStandardSelected(LLUICtrl* ctrl, void* userdata); // <FS:Beq> mesh loader suffix configuration
|
||||
static void onSelectUDPhysics(LLUICtrl* ctrl, void* userdata); // <FS:Beq/> custom setter for upload preview settings tab
|
||||
|
||||
|
|
@ -227,6 +225,7 @@ private:
|
|||
|
||||
void createSmoothComboBox(LLComboBox* combo_box, float min, float max);
|
||||
|
||||
LLUUID mDestinationFolderId;
|
||||
LLButton* mUploadBtn;
|
||||
LLButton* mCalculateBtn;
|
||||
LLViewerTextEditor* mUploadLogText;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,21 +58,24 @@ public:
|
|||
LLFloaterObjectWeights(const LLSD& key);
|
||||
~LLFloaterObjectWeights();
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
bool postBuild() override;
|
||||
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
void onOpen(const LLSD& key) override;
|
||||
|
||||
/*virtual*/ void onWeightsUpdate(const SelectionCost& selection_cost);
|
||||
/*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
|
||||
|
|
|
|||
|
|
@ -3213,7 +3213,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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -116,6 +116,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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -36,6 +36,7 @@
|
|||
#include "llhudeffecttrail.h"
|
||||
#include "llhudeffectlookat.h"
|
||||
#include "llhudeffectpointat.h"
|
||||
#include "llhudeffectresetskeleton.h"
|
||||
#include "llhudnametag.h"
|
||||
#include "llvoicevisualizer.h"
|
||||
|
||||
|
|
@ -263,6 +264,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,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();
|
||||
|
|
|
|||
|
|
@ -1906,6 +1906,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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ public:
|
|||
|
||||
protected:
|
||||
LLPointer<LLViewerFetchedTexture> m_Image;
|
||||
S32 mImageBoostLevel = LLGLTexture::BOOST_NONE;
|
||||
std::string mLoadingText;
|
||||
};
|
||||
|
||||
|
|
@ -135,12 +134,8 @@ LLTexturePreviewView::LLTexturePreviewView(const LLView::Params& p)
|
|||
|
||||
LLTexturePreviewView::~LLTexturePreviewView()
|
||||
{
|
||||
if (m_Image)
|
||||
{
|
||||
m_Image->setBoostLevel(mImageBoostLevel);
|
||||
m_Image = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LLTexturePreviewView::draw()
|
||||
{
|
||||
|
|
@ -160,18 +155,18 @@ void LLTexturePreviewView::draw()
|
|||
bool isLoading = (!m_Image->isFullyLoaded()) && (m_Image->getDiscardLevel() > 0);
|
||||
if (isLoading)
|
||||
LLFontGL::getFontSansSerif()->renderUTF8(mLoadingText, 0, rctClient.mLeft + 3, rctClient.mTop - 25, LLColor4::white, LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::DROP_SHADOW);
|
||||
m_Image->addTextureStats((isLoading) ? MAX_IMAGE_AREA : (F32)(rctClient.getWidth() * rctClient.getHeight()));
|
||||
|
||||
m_Image->setKnownDrawSize(MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTexturePreviewView::setImageFromAssetId(const LLUUID& idAsset)
|
||||
{
|
||||
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())
|
||||
|
|
|
|||
|
|
@ -874,6 +874,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)
|
||||
{
|
||||
|
|
@ -891,7 +893,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||
disabled_items.push_back(std::string("Copy"));
|
||||
}
|
||||
|
||||
if (isAgentInventory() && !single_folder_root && !isMarketplaceListingsFolder())
|
||||
bool is_agent_inventory = isAgentInventory();
|
||||
if (is_agent_inventory && !single_folder_root && !is_cof && !is_inbox)
|
||||
{
|
||||
items.push_back(std::string("New folder from selected"));
|
||||
items.push_back(std::string("Subfolder Separator"));
|
||||
|
|
@ -904,6 +907,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"));
|
||||
|
|
@ -916,6 +932,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
|
||||
|
|
@ -925,7 +942,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"));
|
||||
// <FS> Locked folder
|
||||
|
|
@ -968,6 +985,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())
|
||||
|
|
@ -993,8 +1011,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
|
|||
// <FS:Ansariel> Enable paste for inbox; doesn't actually makes much sense,
|
||||
// but since we are not prevented from pasting via shortcut,
|
||||
// we enable it in the context menu, too.
|
||||
//if (!isCOFFolder() && !isInboxFolder()
|
||||
if (!isCOFFolder()
|
||||
//if (!is_cof && !is_inbox)
|
||||
if (!is_cof
|
||||
// <FS:TT> Client LSL Bridge (also for #AO)
|
||||
&& !isLockedFolder())
|
||||
// </FS:TT>
|
||||
|
|
@ -1435,6 +1453,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;
|
||||
}
|
||||
|
||||
// [SL:KB] - Patch: Inventory-Misc | Checked: 2011-05-28 (Catznip-2.6.0a) | Added: Catznip-2.6.0a
|
||||
bool LLInvFVBridge::isLibraryInventory() const
|
||||
{
|
||||
|
|
@ -2520,7 +2545,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())
|
||||
|
|
@ -2693,6 +2732,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)
|
||||
|
|
@ -4693,6 +4742,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"));
|
||||
// <FS:Ansariel> Undo weird menu design
|
||||
disabled_items.push_back(std::string("New Script"));
|
||||
disabled_items.push_back(std::string("New Note"));
|
||||
|
|
@ -4727,6 +4777,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"));
|
||||
// <FS:Ansariel> Undo weird menu design
|
||||
disabled_items.push_back(std::string("New Script"));
|
||||
disabled_items.push_back(std::string("New Note"));
|
||||
|
|
@ -4808,6 +4859,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
|
|||
if (!isMarketplaceListingsFolder() && !model->isObjectDescendentOf(mUUID, outfits_id))
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
items.push_back(std::string("upload_options"));
|
||||
items.push_back(std::string("upload_def"));
|
||||
//items.push_back(std::string("create_new")); // <FS:Ansariel> Undo weird menu design
|
||||
items.push_back(std::string("New Script"));
|
||||
|
|
@ -4841,6 +4893,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();
|
||||
|
|
@ -7658,16 +7719,13 @@ void LLObjectBridge::performAction(LLInventoryModel* model, std::string action)
|
|||
item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
|
||||
if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
|
||||
{
|
||||
rez_attachment(item, NULL, true); // Replace if "Wear"ing.
|
||||
static LLCachedControl<bool> replace_item(gSavedSettings, "InventoryAddAttachmentBehavior", false);
|
||||
rez_attachment(item, NULL, ("attach" == action) ? replace_item() : true); // Replace if "Wear"ing.
|
||||
}
|
||||
else if(item && item->isFinished())
|
||||
{
|
||||
// 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));
|
||||
// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2013-02-04 (Catznip-3.4)
|
||||
// "Wear" from inventory replaces, so library items should too
|
||||
LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(rez_attachment_cb, _1, (LLViewerJointAttachment*)0, true));
|
||||
// [/SL;KB]
|
||||
copy_inventory_item(
|
||||
gAgent.getID(),
|
||||
item->getPermissions().getOwner(),
|
||||
|
|
@ -8906,7 +8964,8 @@ void LLObjectBridgeAction::attachOrDetach()
|
|||
else
|
||||
{
|
||||
// <FS:Ansariel> Double-click add/replace option
|
||||
//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.
|
||||
LLAppearanceMgr::instance().wearItemOnAvatar(mUUID, true, !gSavedSettings.getBOOL("FSDoubleClickAddInventoryObjects")); // Don't replace if adding.
|
||||
}
|
||||
}
|
||||
|
|
@ -9100,6 +9159,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);
|
||||
}
|
||||
|
|
@ -9134,6 +9194,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()
|
||||
{
|
||||
}
|
||||
|
|
@ -9145,8 +9250,8 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
|
|||
if (get_selection_item_uuids(selected_items, ids))
|
||||
{
|
||||
// <FS:Ansariel> Fix broken add wearable check
|
||||
//if (!LLAppearanceMgr::instance().canAddWearables(ids) && canWearSelected(ids))
|
||||
if (!canWearSelected(ids) || !LLAppearanceMgr::instance().canAddWearables(ids))
|
||||
//if (!LLAppearanceMgr::instance().canAddWearables(ids, false) && canWearSelected(ids))
|
||||
if (!canWearSelected(ids) || !LLAppearanceMgr::instance().canAddWearables(ids, false))
|
||||
{
|
||||
disabled_items.push_back(std::string("Wearable And Object Wear"));
|
||||
disabled_items.push_back(std::string("Wearable Add"));
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
@ -182,6 +183,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
|
||||
|
||||
|
|
@ -277,6 +279,7 @@ public:
|
|||
|
||||
LLViewerInventoryItem* getItem() const;
|
||||
virtual const LLUUID& getThumbnailUUID() const;
|
||||
virtual bool isFavorite() const;
|
||||
|
||||
protected:
|
||||
bool confirmRemoveItem(const LLSD& notification, const LLSD& response);
|
||||
|
|
@ -319,6 +322,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;}
|
||||
|
||||
|
|
@ -780,6 +784,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;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Worn Inventory Panel related classes
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -844,7 +887,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.
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
|
|||
mFilterUUID(p.uuid),
|
||||
mFilterLinks(p.links),
|
||||
mFilterThumbnails(p.thumbnails),
|
||||
mFilterFavorites(p.favorites),
|
||||
mCoalescedObjectsOnly(p.coalesced_objects_only), // <FS:Zi> FIRE-31369: Add inventory filter for coalesced objects
|
||||
mSearchVisibility(p.search_visibility)
|
||||
{
|
||||
|
|
@ -178,6 +179,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;
|
||||
|
|
@ -240,6 +242,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 |
|
||||
|
|
@ -292,6 +307,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)
|
||||
|
|
@ -671,6 +696,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)
|
||||
|
|
@ -905,6 +948,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;
|
||||
|
|
@ -1017,6 +1086,11 @@ void LLInventoryFilter::toggleSearchVisibilityLibrary()
|
|||
}
|
||||
}
|
||||
|
||||
void LLInventoryFilter::setFilterNoTrashFolder()
|
||||
{
|
||||
mFilterOps.mFilterTypes |= FILTERTYPE_NO_TRASH_ITEMS;
|
||||
}
|
||||
|
||||
void LLInventoryFilter::setFilterNoMarketplaceFolder()
|
||||
{
|
||||
mFilterOps.mFilterTypes |= FILTERTYPE_NO_MARKETPLACE_ITEMS;
|
||||
|
|
@ -1856,6 +1930,11 @@ U64 LLInventoryFilter::getFilterThumbnails() const
|
|||
return mFilterOps.mFilterThumbnails;
|
||||
}
|
||||
|
||||
U64 LLInventoryFilter::getFilterFavorites() const
|
||||
{
|
||||
return mFilterOps.mFilterFavorites;
|
||||
}
|
||||
|
||||
bool LLInventoryFilter::hasFilterString() const
|
||||
{
|
||||
return mFilterSubString.size() > 0;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,8 @@ public:
|
|||
FILTERTYPE_MARKETPLACE_LISTING_FOLDER = 0x1 << 9, // pass iff folder is a listing folder
|
||||
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_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
|
||||
|
|
@ -150,6 +158,7 @@ public:
|
|||
Optional<PermissionMask> permissions;
|
||||
Optional<EFilterCreatorType> creator_type;
|
||||
Optional<EFilterThumbnail> thumbnails;
|
||||
Optional<EFilterFavorite> favorites;
|
||||
Optional<bool> coalesced_objects_only; // <FS:Zi> FIRE-31369: Add inventory filter for coalesced objects
|
||||
|
||||
Params()
|
||||
|
|
@ -158,6 +167,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),
|
||||
|
|
@ -180,6 +190,7 @@ public:
|
|||
mFilterWearableTypes,
|
||||
mFilterSettingsTypes, // for _SETTINGS
|
||||
mFilterThumbnails,
|
||||
mFilterFavorites,
|
||||
mFilterLinks,
|
||||
mFilterCategoryTypes; // For _CATEGORY
|
||||
LLUUID mFilterUUID; // for UUID
|
||||
|
|
@ -225,6 +236,7 @@ public:
|
|||
U64 getFilterSettingsTypes() const;
|
||||
U64 getSearchVisibilityTypes() const;
|
||||
U64 getFilterThumbnails() const;
|
||||
U64 getFilterFavorites() const;
|
||||
|
||||
bool isFilterObjectTypesWith(LLInventoryType::EType t) const;
|
||||
void setFilterObjectTypes(U64 types);
|
||||
|
|
@ -239,8 +251,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; }
|
||||
|
|
@ -361,6 +375,7 @@ public:
|
|||
LLInventoryFilter& operator =(const LLInventoryFilter& other);
|
||||
|
||||
bool checkAgainstFilterThumbnails(const LLUUID& object_id) const;
|
||||
bool checkAgainstFilterFavorites(const LLUUID& object_id) const;
|
||||
|
||||
private:
|
||||
bool areDateLimitsSet();
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -2575,6 +2578,143 @@ void ungroup_folder_items(const LLUUID& folder_id)
|
|||
}); // <FS:Ansariel> FIRE-32736: Add confirmation before ungrouping folder
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
@ -2874,6 +3014,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)
|
||||
{
|
||||
|
|
@ -3790,6 +3944,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)
|
||||
|
|
@ -3912,6 +4080,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);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,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);
|
||||
|
|
@ -350,6 +355,18 @@ protected:
|
|||
LLUUID mGroupID;
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLFavoritesCollector
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
class LLFavoritesCollector : public LLInventoryCollectFunctor
|
||||
{
|
||||
public:
|
||||
LLFavoritesCollector() {}
|
||||
virtual ~LLFavoritesCollector() {}
|
||||
virtual bool operator()(LLInventoryCategory* cat,
|
||||
LLInventoryItem* item);
|
||||
};
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Class LLBuddyCollector
|
||||
//
|
||||
|
|
@ -624,6 +641,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2339,7 +2352,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;
|
||||
}
|
||||
|
||||
|
|
@ -2855,6 +2868,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();
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -484,22 +498,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)
|
||||
|
|
@ -778,6 +777,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"));
|
||||
}
|
||||
|
||||
|
|
@ -786,6 +786,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())
|
||||
{
|
||||
|
|
@ -831,6 +843,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"));
|
||||
|
|
@ -967,6 +990,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"));
|
||||
}
|
||||
|
|
@ -1017,6 +1041,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);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ void LLInventoryItemsList::doIdle()
|
|||
{
|
||||
if (mRefreshState == REFRESH_COMPLETE) return;
|
||||
|
||||
if (isInVisibleChain() || mForceRefresh )
|
||||
if (isInVisibleChain() || mForceRefresh || !getFilterSubString().empty())
|
||||
{
|
||||
refresh();
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,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;
|
||||
|
|
@ -3044,8 +3044,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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -786,6 +786,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();
|
||||
|
|
@ -803,6 +810,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);
|
||||
|
|
@ -816,6 +824,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;
|
||||
|
|
@ -841,11 +850,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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -858,25 +867,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -61,11 +61,13 @@
|
|||
// [/RLVa:KB]
|
||||
#include "fsfloaterpartialinventory.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");
|
||||
|
|
@ -690,6 +692,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
|
||||
|
|
@ -718,6 +733,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 = getFolderByID(model_item->getParentUUID());
|
||||
if (new_parent)
|
||||
{
|
||||
new_parent->updateHasFavorites(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
|
@ -731,9 +756,11 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
|
|||
{
|
||||
LLFolderViewModelItem* old_parent_vmi = old_parent->getViewModelItem();
|
||||
LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(old_parent_vmi);
|
||||
LLFolderViewFolder* new_parent = (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());
|
||||
// Item has been moved.
|
||||
if (old_parent != new_parent)
|
||||
LLFolderViewFolder* new_parent = getFolderByID(model_item->getParentUUID());
|
||||
|
||||
if (old_parent != new_parent // Item has been moved.
|
||||
&& (new_parent != NULL || !isInRootContent(item_id, view_item)) // item is not or shouldn't be in root content
|
||||
)
|
||||
{
|
||||
if (new_parent != NULL)
|
||||
{
|
||||
|
|
@ -768,6 +795,18 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
|
|||
{
|
||||
old_parent_vmi->dirtyDescendantsFilter();
|
||||
}
|
||||
|
||||
if (view_item->isFavorite())
|
||||
{
|
||||
if (old_parent)
|
||||
{
|
||||
old_parent->updateHasFavorites(false); // favorite was removed
|
||||
}
|
||||
if (new_parent)
|
||||
{
|
||||
new_parent->updateHasFavorites(true); // favorite was added
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -793,6 +832,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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -910,7 +953,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();
|
||||
|
|
@ -992,20 +1051,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;
|
||||
}
|
||||
|
|
@ -1036,6 +1084,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)
|
||||
{
|
||||
|
|
@ -1939,26 +2003,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)
|
||||
|
|
@ -2531,6 +2577,273 @@ 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;
|
||||
bool isInRootContent(const LLUUID& id, LLFolderViewItem* view_item) override;
|
||||
|
||||
protected:
|
||||
LLInventoryFavoritesItemsPanel(const Params&);
|
||||
friend class LLUICtrlFactory;
|
||||
|
||||
void findAndInitRootContent(const LLUUID& folder_id) override;
|
||||
void initRootContent() override;
|
||||
|
||||
// removeFavorite removes item from root, does not readd favorited children if present
|
||||
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);
|
||||
}
|
||||
|
||||
bool LLInventoryFavoritesItemsPanel::isInRootContent(const LLUUID& id, LLFolderViewItem* view_item)
|
||||
{
|
||||
if (!view_item->isFavorite())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<LLUUID>::iterator found = mRootContentIDs.find(id);
|
||||
return found != mRootContentIDs.end();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mInventory->unlockDirectDescendentArrays(id);
|
||||
}
|
||||
|
||||
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
|
||||
// Todo: Consider implementing and checking hasFavorites to save on search
|
||||
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)
|
||||
{
|
||||
const LLViewerInventoryCategory* cat = dynamic_cast<const LLViewerInventoryCategory*>(model_item);
|
||||
// Todo: Consider implementing and checking hasFavorites to save on search
|
||||
if (cat)
|
||||
{
|
||||
// re-add any favorited children
|
||||
mBuildRootQueue.emplace_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -269,7 +269,8 @@ 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);
|
||||
virtual bool isInRootContent(const LLUUID& id, LLFolderViewItem* view_item) { return false; }
|
||||
LLFolderViewItem* getItemByID(const LLUUID& id);
|
||||
LLFolderViewFolder* getFolderByID(const LLUUID& id);
|
||||
void setSelectionByID(const LLUUID& obj_id, bool take_keyboard_focus);
|
||||
|
|
@ -353,6 +354,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;
|
||||
|
|
@ -390,7 +393,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,
|
||||
|
|
@ -413,6 +416,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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1417,7 +1417,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();
|
||||
|
|
@ -1587,12 +1587,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);
|
||||
|
|
@ -1906,7 +1906,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())
|
||||
{
|
||||
|
|
@ -1929,12 +1933,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;
|
||||
|
||||
|
|
@ -2434,17 +2439,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;
|
||||
}
|
||||
|
||||
|
|
@ -2857,10 +2862,10 @@ void LLMaterialEditor::setFromGltfMetaData(const std::string& filename, const ti
|
|||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
// </FS:Zi>
|
||||
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())
|
||||
{
|
||||
|
|
@ -2870,7 +2875,7 @@ void LLMaterialEditor::importMaterial()
|
|||
{
|
||||
if (filenames.size() > 0)
|
||||
{
|
||||
LLMaterialEditor::loadMaterialFromFile(filenames[0], -1);
|
||||
LLMaterialEditor::loadMaterialFromFile(filenames[0], -1, dest_folder);
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
|
|
@ -3563,6 +3568,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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -772,8 +772,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;
|
||||
|
|
@ -831,6 +835,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
|
||||
{
|
||||
|
|
@ -2579,7 +2597,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"),
|
||||
|
|
@ -2587,6 +2605,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)
|
||||
{
|
||||
|
|
@ -2703,13 +2722,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)";
|
||||
|
|
@ -2852,7 +2879,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());
|
||||
}
|
||||
|
|
@ -2866,6 +2893,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++;
|
||||
}
|
||||
|
||||
|
|
@ -3130,7 +3159,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));
|
||||
|
|
@ -3183,7 +3213,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,
|
||||
|
|
@ -3249,7 +3280,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)
|
||||
{
|
||||
|
|
@ -3284,7 +3315,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)
|
||||
{
|
||||
|
|
@ -3309,7 +3340,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)
|
||||
{
|
||||
|
|
@ -3342,7 +3373,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)
|
||||
{
|
||||
|
|
@ -5176,12 +5207,12 @@ LLUUID LLMeshRepoThread::getCreatorFromHeader(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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -665,10 +665,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();
|
||||
|
|
@ -684,7 +687,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,
|
||||
|
|
@ -705,6 +708,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;
|
||||
|
|
@ -830,7 +834,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>()));
|
||||
|
||||
|
|
|
|||
|
|
@ -3228,7 +3228,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;
|
||||
|
|
@ -4431,7 +4431,6 @@ bool LLModelPreview::render()
|
|||
fmp->setViewOptionEnabled("show_skin_weight", show_skin_weight);
|
||||
}
|
||||
}
|
||||
//if (this) return TRUE;
|
||||
|
||||
if (upload_skin && !has_skin_weights)
|
||||
{ //can't upload skin weights if model has no skin weights
|
||||
|
|
|
|||
|
|
@ -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,19 +428,28 @@ 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();
|
||||
case 2:
|
||||
if (item1->isFavorite() != item2->isFavorite())
|
||||
{
|
||||
return item1->isFavorite();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (item1->isDefaultImage() != item2->isDefaultImage())
|
||||
{
|
||||
return item2->isDefaultImage();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (LLStringUtil::compareDict(name1, name2) < 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return item2->isDefaultImage();
|
||||
}
|
||||
std::string name1 = item1->getItemName();
|
||||
std::string name2 = item2->getItemName();
|
||||
return (LLStringUtil::compareDict(name1, name2) < 0);
|
||||
}
|
||||
|
||||
void LLOutfitGallery::reArrangeRows(S32 row_diff)
|
||||
|
|
@ -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 : sDefaultTextColor);
|
||||
}
|
||||
|
||||
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 : sDefaultTextColor);
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
@ -1210,24 +1275,11 @@ void LLOutfitGalleryGearMenu::onUpdateItemsVisibility()
|
|||
{
|
||||
if (!mMenu) return;
|
||||
bool have_selection = getSelectedOutfitID().notNull();
|
||||
mMenu->setItemVisible("expand", false);
|
||||
mMenu->setItemVisible("collapse", false);
|
||||
mMenu->setItemVisible("thumbnail", have_selection);
|
||||
mMenu->setItemVisible("sort_folders_by_name", true);
|
||||
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);
|
||||
|
|
@ -1344,6 +1396,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);
|
||||
|
|
@ -1359,3 +1420,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -61,14 +63,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>
|
||||
|
|
@ -88,6 +100,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))
|
||||
{
|
||||
|
|
@ -111,11 +126,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()
|
||||
|
|
@ -123,9 +147,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)
|
||||
{
|
||||
|
|
@ -163,6 +203,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);
|
||||
|
|
@ -196,8 +237,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));
|
||||
|
|
@ -315,13 +357,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -383,6 +423,11 @@ void LLOutfitsList::onSetSelectedOutfitByUUID(const LLUUID& outfit_uuid)
|
|||
}
|
||||
}
|
||||
|
||||
void LLOutfitListBase::onAction(const LLSD& userdata)
|
||||
{
|
||||
performAction(userdata.asString());
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool LLOutfitListBase::isActionEnabled(const LLSD& userdata)
|
||||
{
|
||||
|
|
@ -495,11 +540,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -591,7 +637,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())
|
||||
|
|
@ -808,6 +854,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);
|
||||
|
|
@ -825,11 +940,11 @@ bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y)
|
|||
LLOutfitListBase::LLOutfitListBase()
|
||||
: LLPanelAppearanceTab()
|
||||
, mIsInitialized(false)
|
||||
, mGearMenu(nullptr)
|
||||
, mAvatarComplexityLabel(NULL) // <FS:Ansariel> Show avatar complexity in appearance floater
|
||||
{
|
||||
mCategoriesObserver = new LLInventoryCategoriesObserver();
|
||||
mOutfitMenu = new LLOutfitContextMenu(this);
|
||||
//mGearMenu = createGearMenu();
|
||||
}
|
||||
|
||||
LLOutfitListBase::~LLOutfitListBase()
|
||||
|
|
@ -892,6 +1007,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();
|
||||
|
||||
|
|
@ -987,8 +1106,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();
|
||||
|
|
@ -1143,15 +1272,8 @@ void LLOutfitListBase::ChangeOutfitSelection(LLWearableItemsList* list, const LL
|
|||
|
||||
bool LLOutfitListBase::postBuild()
|
||||
{
|
||||
mGearMenu = createGearMenu();
|
||||
|
||||
// <FS:Ansariel> Show avatar complexity in appearance floater
|
||||
mAvatarComplexityLabel = getChild<LLTextBox>("avatar_complexity_label");
|
||||
|
||||
LLMenuButton* menu_gear_btn = getChild<LLMenuButton>("options_gear_btn");
|
||||
|
||||
menu_gear_btn->setMouseDownCallback(boost::bind(&LLOutfitListGearMenuBase::updateItemsVisibility, mGearMenu));
|
||||
menu_gear_btn->setMenu(mGearMenu->getMenu());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1165,6 +1287,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.
|
||||
|
|
@ -1202,6 +1338,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));
|
||||
|
|
@ -1252,6 +1389,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;
|
||||
}
|
||||
|
|
@ -1276,6 +1423,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())
|
||||
|
|
@ -1306,14 +1461,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));
|
||||
|
|
@ -1447,6 +1601,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;
|
||||
}
|
||||
|
|
@ -1458,6 +1622,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()
|
||||
{
|
||||
|
||||
|
|
@ -1473,13 +1643,79 @@ LLOutfitListGearMenu::~LLOutfitListGearMenu()
|
|||
void LLOutfitListGearMenu::onUpdateItemsVisibility()
|
||||
{
|
||||
if (!mMenu) return;
|
||||
mMenu->setItemVisible("expand", true);
|
||||
mMenu->setItemVisible("collapse", true);
|
||||
mMenu->setItemVisible("thumbnail", getSelectedOutfitID().notNull());
|
||||
mMenu->setItemVisible("favorite", getSelectedOutfitID().notNull());
|
||||
mMenu->setItemVisible("sepatator3", false);
|
||||
mMenu->setItemVisible("sort_folders_by_name", false);
|
||||
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)
|
||||
{
|
||||
// <FS:Ansariel> Make thumbnail tooltip work properly
|
||||
|
|
@ -1513,4 +1749,54 @@ bool LLOutfitAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
|
||||
return LLAccordionCtrlTab::handleToolTip(x, y, mask);
|
||||
}
|
||||
|
||||
void LLOutfitAccordionCtrlTab::setFavorite(bool is_favorite)
|
||||
{
|
||||
mIsFavorite = is_favorite;
|
||||
updateTitleColor();
|
||||
}
|
||||
|
||||
void LLOutfitAccordionCtrlTab::setOutfitSelected(bool val)
|
||||
{
|
||||
mIsSelected = val;
|
||||
setTitleFontStyle(mIsSelected ? "BOLD" : "NORMAL");
|
||||
updateTitleColor();
|
||||
}
|
||||
|
||||
void LLOutfitAccordionCtrlTab::updateTitleColor()
|
||||
{
|
||||
static LLUICachedControl<bool> highlight_color("InventoryFavoritesColorText", true);
|
||||
if (mIsFavorite && highlight_color())
|
||||
{
|
||||
setTitleColor(LLUIColorTable::instance().getColor("InventoryFavoriteColor"));
|
||||
}
|
||||
else if (mIsSelected)
|
||||
{
|
||||
setTitleColor(LLUIColorTable::instance().getColor("SelectedOutfitTextColor"));
|
||||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
class LLAccordionCtrlTab;
|
||||
class LLInventoryCategoriesObserver;
|
||||
class LLOutfitListGearMenuBase;
|
||||
class LLOutfitListSortMenuBase;
|
||||
class LLWearableItemsList;
|
||||
class LLListContextMenu;
|
||||
class LLTextBox;
|
||||
|
|
@ -62,6 +63,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:
|
||||
|
|
@ -94,6 +106,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;
|
||||
|
|
@ -111,6 +124,12 @@ public:
|
|||
|
||||
virtual bool getHasExpandableFolders() = 0;
|
||||
|
||||
virtual void onChangeSortOrder(const LLSD& userdata) = 0;
|
||||
|
||||
virtual void updateMenuItemsVisibility();
|
||||
virtual LLToggleableMenu* getGearMenu();
|
||||
virtual bool getTrashMenuVisible() { return true; };
|
||||
|
||||
// <FS:Ansariel> Show avatar complexity in appearance floater
|
||||
void updateAvatarComplexity(U32 complexity);
|
||||
|
||||
|
|
@ -144,6 +163,7 @@ protected:
|
|||
selection_change_signal_t mSelectionChangeSignal;
|
||||
LLListContextMenu* mOutfitMenu;
|
||||
LLOutfitListGearMenuBase* mGearMenu;
|
||||
boost::signals2::connection mGearMenuConnection;
|
||||
// <FS:Ansariel> Show avatar complexity in appearance floater
|
||||
LLTextBox* mAvatarComplexityLabel;
|
||||
};
|
||||
|
|
@ -162,7 +182,6 @@ protected:
|
|||
/* virtual */ LLContextMenu* createMenu();
|
||||
|
||||
bool onEnable(LLSD::String param);
|
||||
|
||||
bool onVisible(LLSD::String param);
|
||||
|
||||
static void editOutfit();
|
||||
|
|
@ -170,6 +189,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:
|
||||
|
|
@ -189,6 +209,7 @@ public:
|
|||
protected:
|
||||
virtual void onUpdateItemsVisibility();
|
||||
virtual void onThumbnail();
|
||||
virtual void onFavorite();
|
||||
virtual void onChangeSortOrder();
|
||||
|
||||
const LLUUID& getSelectedOutfitID();
|
||||
|
|
@ -209,6 +230,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:
|
||||
|
|
@ -228,8 +266,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),
|
||||
|
|
@ -237,7 +283,12 @@ public:
|
|||
{}
|
||||
friend class LLUICtrlFactory;
|
||||
|
||||
void updateTitleColor();
|
||||
void drawFavoriteIcon();
|
||||
|
||||
LLUUID mFolderID;
|
||||
bool mIsFavorite = false;
|
||||
bool mIsSelected = false;
|
||||
};
|
||||
/**
|
||||
* @class LLOutfitsList
|
||||
|
|
@ -256,6 +307,7 @@ public:
|
|||
virtual ~LLOutfitsList();
|
||||
|
||||
/*virtual*/ bool postBuild();
|
||||
void initComparator();
|
||||
|
||||
/*virtual*/ void onOpen(const LLSD& info);
|
||||
|
||||
|
|
@ -294,6 +346,10 @@ public:
|
|||
|
||||
/*virtual*/ bool getHasExpandableFolders() { return true; }
|
||||
|
||||
/*virtual*/ void onChangeSortOrder(const LLSD& userdata);
|
||||
virtual LLToggleableMenu* getSortMenu();
|
||||
void updateMenuItemsVisibility();
|
||||
|
||||
protected:
|
||||
LLOutfitListGearMenuBase* createGearMenu();
|
||||
|
||||
|
|
@ -365,6 +421,8 @@ private:
|
|||
|
||||
static void onOutfitRename(const LLSD& notification, const LLSD& response);
|
||||
|
||||
void handleInvFavColorChange();
|
||||
|
||||
// <FS:Ansariel> FIRE-22484: Double-click wear in outfits list
|
||||
void onDoubleClick(LLWearableItemsList* list);
|
||||
|
||||
|
|
@ -385,13 +443,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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -527,10 +527,6 @@ LLPanelFace::~LLPanelFace()
|
|||
|
||||
void LLPanelFace::onVisibilityChange(bool new_visibility)
|
||||
{
|
||||
if (new_visibility)
|
||||
{
|
||||
gAgent.showLatestFeatureNotification("gltf");
|
||||
}
|
||||
LLPanel::onVisibilityChange(new_visibility);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ bool LLPanelGroupCreate::postBuild()
|
|||
|
||||
mInsignia = getChild<LLTextureCtrl>("insignia", true);
|
||||
mInsignia->setAllowLocalTexture(false);
|
||||
mInsignia->setBakeTextureEnabled(false);
|
||||
mInsignia->setCanApplyImmediately(false);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group)
|
|||
{
|
||||
mInsignia->setCommitCallback(onCommitAny, this);
|
||||
mInsignia->setAllowLocalTexture(false);
|
||||
mInsignia->setBakeTextureEnabled(false);
|
||||
}
|
||||
mFounderName = getChild<LLTextBox>("founder_name");
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ const std::string FILTERS_FILENAME("filters.xml");
|
|||
const std::string ALL_ITEMS("All Items");
|
||||
const std::string RECENT_ITEMS("Recent Items");
|
||||
const std::string WORN_ITEMS("Worn Items");
|
||||
const std::string FAVORITES("Favorites");
|
||||
|
||||
static LLPanelInjector<LLPanelMainInventory> t_inventory("panel_main_inventory");
|
||||
|
||||
|
|
@ -313,6 +314,17 @@ bool LLPanelMainInventory::postBuild()
|
|||
}
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
|
||||
LLInventoryPanel* favorites_panel = getChild<LLInventoryPanel>(FAVORITES);
|
||||
if (favorites_panel)
|
||||
{
|
||||
favorites_panel->setSortOrder(gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER));
|
||||
LLInventoryFilter& favorites_filter = favorites_panel->getFilter();
|
||||
favorites_filter.setEmptyLookupMessage("InventoryNoMatchingFavorites");
|
||||
favorites_filter.markDefault();
|
||||
favorites_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, favorites_panel, _1, _2));
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Only if we actually have it!
|
||||
//mSearchTypeCombo = getChild<LLComboBox>("search_type");
|
||||
mSearchTypeCombo = findChild<LLComboBox>("search_type");
|
||||
|
|
@ -716,7 +728,8 @@ void LLPanelMainInventory::doCreate(const LLSD& userdata)
|
|||
}
|
||||
else
|
||||
{
|
||||
menu_create_inventory_item(getPanel(), NULL, userdata);
|
||||
selectAllItemsPanel();
|
||||
menu_create_inventory_item(mAllItemsPanel, NULL, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue